1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: simalscom.c
6  * Asynchronous Logic Simulator command handler
7  * From algorithms by: Brent Serbin and Peter J. Gallant
8  * Last maintained by: Steven M. Rubin
9  *
10  * Copyright (c) 2000 Static Free Software.
11  *
12  * Electric(tm) is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Electric(tm) is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Electric(tm); see the file COPYING.  If not, write to
24  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
25  * Boston, Mass 02111-1307, USA.
26  *
27  * Static Free Software
28  * 4119 Alpine Road
29  * Portola Valley, California 94028
30  * info@staticfreesoft.com
31  */
32 
33 #include "config.h"
34 #if SIMTOOL
35 
36 #include "global.h"
37 #include "sim.h"
38 #include "simals.h"
39 #include "usrdiacom.h"
40 
41 /* prototypes for local routines */
42 static void      simals_erase_submod(CONPTR);
43 static void      simals_print_in_entry(ROWPTR);
44 static void      simals_print_out_entry(ROWPTR);
45 static void      simals_print_xref_entry(CONPTR, INTBIG);
46 static CHAR     *simals_strengthstring(INTSML);
47 static void      simals_makeactelmodel(CHAR *name, FILE *io, LIBRARY *lib);
48 static void      simals_sdfannotate(CONPTR cellhead);
49 static NODEINST *simals_getcellinstance(CHAR *celltype, CHAR *instance);
50 static void      simals_sdfportdelay(CONPTR cellhead, NODEINST *ni, CHAR *path);
51 static INTBIG    simals_getportdelayvalue(CHAR *datastring, CHAR *transition, DELAY_TYPES delaytype);
52 static INTBIG    simals_getdval(CHAR *tstring, DELAY_TYPES delaytype);
53 static void      simals_order_save(void);
54 static void      simals_order_restore(CHAR *list);
55 static void      simals_update_netlist(void);
56 static CHAR     *simals_parent_level(CHAR *child);
57 static INTBIG    simals_get_tdindex(CHAR *name);
58 
59 /* local variables */
60 static DELAY_TYPES simals_sdfdelaytype;
61 static CHAR *simals_tnames[] = {x_("01"), x_("10"), x_("0Z"), x_("Z1"), x_("1Z"), x_("Z0"), x_("0X"), x_("X1"), x_("1X"), x_("X0"), x_("XZ"), x_("ZX")};
62 
63 /****************************** ACTEL MODELS ******************************/
64 
65 typedef enum {inputparam, outputparam, bidirparam, edgesenseinputparam,
66 	fourstatebiputparam} PARAMTYPE;
67 
68 typedef struct Iactelparam
69 {
70 	CHAR               *paramname;
71 	PARAMTYPE           paramtype;
72 	BOOLEAN             duplicate;
73 	struct Iactelparam *next;
74 } ACTELPARAM;
75 
76 #define MAXCHRS 300
77 
78 /*
79  * Name: simals_build_actel_command
80  *
81  * Description:
82  *	This procedure reads an Actel table file and creates a library with
83  * ALS-netlist cells.
84  */
simals_build_actel_command(INTBIG count,CHAR * par[])85 void simals_build_actel_command(INTBIG count, CHAR *par[])
86 {
87 	FILE *io;
88 	INTBIG len, i, filecount;
89 	CHAR *filename, line[MAXCHRS], **filelist;
90 	REGISTER CHAR *pt, *start;
91 	static INTBIG filetypeacteltab = -1;
92 	REGISTER void *infstr;
93 
94 	if (count == 0)
95 	{
96 		ttyputusage(x_("telltool simulation als build-actel-model TABLEFILE"));
97 		return;
98 	}
99 	len = estrlen(par[0]);
100 	for(i=len-1; i>0; i--) if (par[0][i] == DIRSEP) break;
101 	par[0][i] = 0;
102 	filecount = filesindirectory(par[0], &filelist);
103 	if (filecount == 0)
104 	{
105 		ttyputerr(M_("There are no files in directory '%s'"), par[0]);
106 		return;
107 	}
108 	for(i=0; i<filecount; i++)
109 	{
110 		infstr = initinfstr();
111 		addstringtoinfstr(infstr, par[0]);
112 		addtoinfstr(infstr, DIRSEP);
113 		addstringtoinfstr(infstr, filelist[i]);
114 		pt = returninfstr(infstr);
115 		if (filetypeacteltab < 0)
116 			filetypeacteltab = setupfiletype(x_("tab"), x_("*.tab"), MACFSTAG('TEXT'), FALSE, x_("actel"), M_("QuickPartTable"));
117 		io = xopen(pt, filetypeacteltab, x_(""), &filename);
118 		if (io == 0)
119 		{
120 			ttyputerr(M_("Cannot find Actel file %s"), pt);
121 			break;
122 		}
123 		for(;;)
124 		{
125 			if (xfgets(line, MAXCHRS, io) != 0) break;
126 			pt = line;
127 			while (*pt == ' ' || *pt == '\t') pt++;
128 			if (*pt == 0 || *pt == '#') continue;
129 
130 			if (namesamen(pt, x_("model "), 6) != 0) continue;
131 			pt += 6;
132 			while (*pt == ' ' || *pt == '\t') pt++;
133 			start = pt;
134 			while (*pt != 0 && *pt != ':') pt++;
135 			if (*pt != 0) *pt = 0;
136 			simals_makeactelmodel(start, io, el_curlib);
137 		}
138 		xclose(io);
139 	}
140 }
141 
simals_makeactelmodel(CHAR * name,FILE * io,LIBRARY * lib)142 void simals_makeactelmodel(CHAR *name, FILE *io, LIBRARY *lib)
143 {
144 	CHAR line[MAXCHRS];
145 	REGISTER CHAR *pt, *start, save, *cellname;
146 	REGISTER NODEPROTO *np;
147 	INTBIG statetablestate;
148 	BOOLEAN doinginput, edgesense, fourstate;
149 	ACTELPARAM *ap, *lastap, *inputlist, *outputlist, *paramlist, *paramtail, *nextap, *newap;
150 	void *sa;
151 	REGISTER void *infstr;
152 
153 	sa = newstringarray(sim_tool->cluster);
154 	if (sa == 0) return;
155 
156 	/* dump header information for the model */
157 	infstr = initinfstr();
158 	addstringtoinfstr(infstr, x_("# Actel model for "));
159 	addstringtoinfstr(infstr, name);
160 	addtostringarray(sa, returninfstr(infstr));
161 
162 	inputlist = outputlist = paramlist = 0;
163 	statetablestate = 0;
164 	for(;;)
165 	{
166 		if (xfgets(line, MAXCHRS, io) != 0) break;
167 
168 		/* find the first keyword */
169 		pt = line;
170 		while (*pt == ' ' || *pt == '\t') pt++;
171 		if (*pt == '#') continue;
172 		if (*pt == 0) continue;
173 
174 		/* stop if done with table */
175 		if (namesamen(pt, x_("end"), 3) == 0) break;
176 
177 		/* see if gathering state table information */
178 		if (statetablestate != 0)
179 		{
180 			if (statetablestate == 1)
181 			{
182 				/* get state table header */
183 				statetablestate = 2;
184 				doinginput = TRUE;
185 				paramtail = 0;
186 				for(;;)
187 				{
188 					while (*pt == ' ' || *pt == '\t') pt++;
189 					start = pt;
190 					while (*pt != 0 && *pt != ' ' && *pt != '\t' && *pt != ',' && *pt != ';' &&
191 						*pt != ':') pt++;
192 					save = *pt;   *pt = 0;
193 					if (doinginput)
194 					{
195 						/* search input list for this one */
196 						lastap = 0;
197 						for(ap = inputlist; ap != 0; ap = ap->next)
198 						{
199 							if (estrcmp(ap->paramname, start) == 0) break;
200 							lastap = ap;
201 						}
202 						if (ap == 0)
203 						{
204 							/* see if it is on the output list */
205 							for(ap = outputlist; ap != 0; ap = ap->next)
206 								if (estrcmp(ap->paramname, start) == 0) break;
207 							if (ap == 0)
208 							{
209 								ttyputerr(M_("In model %s, symbol %s not found in parameter lists"),
210 									name, start);
211 								return;
212 							}
213 							newap = (ACTELPARAM *)emalloc(sizeof (ACTELPARAM), sim_tool->cluster);
214 							if (newap == 0) return;
215 							(void)allocstring(&newap->paramname, ap->paramname, sim_tool->cluster);
216 							newap->paramtype = ap->paramtype;
217 							newap->duplicate = TRUE;
218 							ap = newap;
219 						} else
220 						{
221 							if (lastap == 0) inputlist = ap->next; else
222 								lastap->next = ap->next;
223 						}
224 					} else
225 					{
226 						/* search output list for this one */
227 						lastap = 0;
228 						for(ap = outputlist; ap != 0; ap = ap->next)
229 						{
230 							if (estrcmp(ap->paramname, start) == 0) break;
231 							lastap = ap;
232 						}
233 						if (ap == 0)
234 						{
235 							/* see if it is already on the input list */
236 							for(ap = paramlist; ap != 0; ap = ap->next)
237 								if (estrcmp(ap->paramname, start) == 0) break;
238 							if (ap == 0)
239 							{
240 								ttyputerr(M_("In model %s, symbol %s not found in parameter lists"),
241 									name, start);
242 								return;
243 							}
244 							newap = (ACTELPARAM *)emalloc(sizeof (ACTELPARAM), sim_tool->cluster);
245 							if (newap == 0) return;
246 							(void)allocstring(&newap->paramname, ap->paramname, sim_tool->cluster);
247 							newap->paramtype = ap->paramtype;
248 							newap->duplicate = TRUE;
249 							ap = newap;
250 						} else
251 						{
252 							if (lastap == 0) outputlist = ap->next; else
253 								lastap->next = ap->next;
254 						}
255 					}
256 					ap->next = 0;
257 					if (paramtail == 0) paramlist = paramtail = ap; else
258 					{
259 						paramtail->next = ap;
260 						paramtail = ap;
261 					}
262 					*pt = save;
263 					while (*pt == ' ' || *pt == '\t') pt++;
264 					if (*pt == ';') break;
265 					if (*pt == ':') { pt += 2;   doinginput = FALSE;   continue; }
266 					if (*pt == ',') { pt++;   continue; }
267 					ttyputerr(M_("In model %s, missing comma in Actel symbol list"), name);
268 					return;
269 				}
270 
271 				/* now dump the model header */
272 				infstr = initinfstr();
273 				addstringtoinfstr(infstr, x_("gate "));
274 				addstringtoinfstr(infstr, name);
275 				addstringtoinfstr(infstr, x_("("));
276 				for(ap = paramlist; ap != 0; ap = ap->next)
277 				{
278 					if (ap->duplicate) continue;
279 					if (ap != paramlist) addstringtoinfstr(infstr, x_(", "));
280 					addstringtoinfstr(infstr, ap->paramname);
281 				}
282 				addstringtoinfstr(infstr, x_(")"));
283 				addtostringarray(sa, returninfstr(infstr));
284 				addtostringarray(sa, x_("t: delta=1.0e-9"));
285 				continue;
286 			} else
287 			{
288 				/* get state table entry */
289 				ap = paramlist;
290 				infstr = initinfstr();
291 				addstringtoinfstr(infstr, x_("i: "));
292 				for(;;)
293 				{
294 					while (*pt == ' ' || *pt == '\t') pt++;
295 					addstringtoinfstr(infstr, ap->paramname);
296 					addstringtoinfstr(infstr, x_("="));
297 					switch (*pt)
298 					{
299 						case '0': addstringtoinfstr(infstr, x_("L"));   break;
300 						case '1': addstringtoinfstr(infstr, x_("H"));   break;
301 						case '?': addstringtoinfstr(infstr, x_("X"));   break;
302 						case '[': addstringtoinfstr(infstr, x_("E"));   break;
303 						case '(': addstringtoinfstr(infstr, x_("F"));   break;
304 						case 'Z': addstringtoinfstr(infstr, x_("Z"));   break;
305 						case 'X': addstringtoinfstr(infstr, x_("XX"));  break;
306 						case '!': addstringtoinfstr(infstr, x_("N"));   break;
307 					}
308 					addstringtoinfstr(infstr, x_(" "));
309 
310 					while (*pt != 0 && *pt != ',' && *pt != ';' && *pt != ':') pt++;
311 					if (*pt == ';') break;
312 					if (*pt == ':') { addstringtoinfstr(infstr, x_("o: "));   pt++; }
313 					pt++;
314 					ap = ap->next;
315 				}
316 				addtostringarray(sa, returninfstr(infstr));
317 				continue;
318 			}
319 		}
320 
321 		/* handle "edge_sense" prefix */
322 		edgesense = FALSE;
323 		if (namesamen(pt, x_("edge_sense"), 10) == 0)
324 		{
325 			edgesense = TRUE;
326 			pt += 10;
327 			while (*pt == ' ' || *pt == '\t') pt++;
328 		}
329 
330 		/* handle "four_state" prefix */
331 		fourstate = FALSE;
332 		if (namesamen(pt, x_("four_state"), 10) == 0)
333 		{
334 			fourstate = TRUE;
335 			pt += 10;
336 			while (*pt == ' ' || *pt == '\t') pt++;
337 		}
338 
339 		/* gather inputs */
340 		if (namesamen(pt, x_("input"), 5) == 0)
341 		{
342 			pt += 5;
343 			for(;;)
344 			{
345 				while (*pt == ' ' || *pt == '\t') pt++;
346 				start = pt;
347 				while (*pt != 0 && *pt != ' ' && *pt != '\t' && *pt != ',' && *pt != ';') pt++;
348 				save = *pt;   *pt = 0;
349 				ap = (ACTELPARAM *)emalloc(sizeof (ACTELPARAM), sim_tool->cluster);
350 				if (ap == 0) break;
351 				(void)allocstring(&ap->paramname, start, sim_tool->cluster);
352 				if (edgesense) ap->paramtype = edgesenseinputparam; else
353 					ap->paramtype = inputparam;
354 				ap->duplicate = FALSE;
355 				ap->next = inputlist;
356 				inputlist = ap;
357 				*pt = save;
358 				while (*pt == ' ' || *pt == '\t') pt++;
359 				if (*pt == ';') break;
360 				if (*pt == ',') { pt++;   continue; }
361 				ttyputerr(M_("In model %s, missing comma in Actel input list"), name);
362 				return;
363 			}
364 			continue;
365 		}
366 
367 		/* gather outputs */
368 		if (namesamen(pt, x_("output"), 6) == 0)
369 		{
370 			pt += 6;
371 			for(;;)
372 			{
373 				while (*pt == ' ' || *pt == '\t') pt++;
374 				start = pt;
375 				while (*pt != 0 && *pt != ' ' && *pt != '\t' && *pt != ',' && *pt != ';') pt++;
376 				save = *pt;   *pt = 0;
377 				ap = (ACTELPARAM *)emalloc(sizeof (ACTELPARAM), sim_tool->cluster);
378 				if (ap == 0) break;
379 				(void)allocstring(&ap->paramname, start, sim_tool->cluster);
380 				ap->paramtype = outputparam;
381 				ap->duplicate = FALSE;
382 				ap->next = outputlist;
383 				outputlist = ap;
384 				*pt = save;
385 				while (*pt == ' ' || *pt == '\t') pt++;
386 				if (*pt == ';') break;
387 				if (*pt == ',') { pt++;   continue; }
388 				ttyputerr(M_("In model %s, missing comma in Actel output list"), name);
389 				return;
390 			}
391 			continue;
392 		}
393 
394 		/* gather bidirectionals */
395 		if (namesamen(pt, x_("biput"), 5) == 0)
396 		{
397 			pt += 5;
398 			for(;;)
399 			{
400 				while (*pt == ' ' || *pt == '\t') pt++;
401 				start = pt;
402 				while (*pt != 0 && *pt != ' ' && *pt != '\t' && *pt != ',' && *pt != ';') pt++;
403 				save = *pt;   *pt = 0;
404 				ap = (ACTELPARAM *)emalloc(sizeof (ACTELPARAM), sim_tool->cluster);
405 				if (ap == 0) break;
406 				(void)allocstring(&ap->paramname, start, sim_tool->cluster);
407 				if (fourstate) ap->paramtype = fourstatebiputparam; else
408 					ap->paramtype = bidirparam;
409 				ap->duplicate = FALSE;
410 				ap->next = inputlist;
411 				inputlist = ap;
412 				*pt = save;
413 				while (*pt == ' ' || *pt == '\t') pt++;
414 				if (*pt == ';') break;
415 				if (*pt == ',') { pt++;   continue; }
416 				ttyputerr(M_("In model %s, missing comma in Actel biput list"), name);
417 				return;
418 			}
419 			continue;
420 		}
421 
422 		/* start state table */
423 		if (namesamen(pt, x_("state_table"), 11) == 0)
424 		{
425 			statetablestate = 1;
426 			continue;
427 		}
428 	}
429 	infstr = initinfstr();
430 	addstringtoinfstr(infstr, x_("load"));
431 	for(ap = paramlist; ap != 0; ap = nextap)
432 	{
433 		nextap = ap->next;
434 		if (ap->paramtype == inputparam || ap->paramtype == edgesenseinputparam)
435 		{
436 			addstringtoinfstr(infstr, x_(" "));
437 			addstringtoinfstr(infstr, ap->paramname);
438 			addstringtoinfstr(infstr, x_("=1.0"));
439 		}
440 		efree(ap->paramname);
441 		efree((CHAR *)ap);
442 	}
443 	addtostringarray(sa, returninfstr(infstr));
444 
445 	/* now put strings onto a cell */
446 	infstr = initinfstr();
447 	addstringtoinfstr(infstr, name);
448 	addstringtoinfstr(infstr, x_("{net-als}"));
449 	cellname = returninfstr(infstr);
450 	np = newnodeproto(cellname, lib);
451 	if (np == NONODEPROTO)
452 	{
453 		ttyputerr(M_("Cannot create cell %s"), cellname);
454 		return;
455 	}
456 	stringarraytotextcell(sa, np, TRUE);
457 	killstringarray(sa);
458 	ttyputmsg(M_("Created %s"), describenodeproto(np));
459 }
460 
461 /****************************** CLOCK ******************************/
462 
463 /*
464  * Name: simals_clock_command
465  *
466  * Description:
467  *	This procedure enters a complex clock vector into the user defined
468  * event list.  The user is polled for the node name and timing parameters
469  * before any entry is made into the linklist.
470  */
simals_clock_command(INTBIG count,CHAR * par[])471 void simals_clock_command(INTBIG count, CHAR *par[])
472 {
473 	double   time, totaltime;
474 	NODEPTR  nodehead;
475 	NODEPROTO *np;
476 	LINKPTR  vectptr1, vectptr2, sethead;
477 	ROWPTR   clokhead;
478 	float    linear;
479 	LINKPTR  vectroot;
480 	CHAR     **vectptr;
481 	INTSML    strength;
482 	INTBIG    num, l, i;
483 
484 	if (sim_window_isactive(&np) == 0)
485 	{
486 		ttyputerr(M_("No simulator active"));
487 		return;
488 	}
489 	if (count < 1)
490 	{
491 		ttyputusage(x_("telltool simulation als clock NODENAME (freq | period | custom)"));
492 		return;
493 	}
494 
495 	simals_convert_to_upper(par[0]);
496 	nodehead = simals_find_node(par[0]);
497 	if (! nodehead)
498 	{
499 		ttyputerr(M_("ERROR: Unable to find node %s"), par[0]);
500 		return;
501 	}
502 
503 	if (count < 2)
504 	{
505 		count = sim_alsclockdlog(&par[1]) + 1;
506 		if (count < 2) return;
507 	}
508 
509 	/* see if there are frequency/period parameters */
510 	l = estrlen(par[1]);
511 	if (namesamen(par[1], x_("frequency"), l) == 0 || namesamen(par[1], x_("period"), l) == 0)
512 	{
513 		if (count < 3)
514 		{
515 			ttyputusage(x_("telltool simulation als clock NODENAME frequency/period PERIOD"));
516 			return;
517 		}
518 		time = eatof(par[2]);
519 		if (time <= 0.0)
520 		{
521 			ttyputerr(M_("Clock timing parameter must be greater than 0"));
522 			return;
523 		}
524 
525 		if (namesamen(par[1], x_("frequency"), l) == 0) time = 1.0f / time;
526 
527 		vectptr2 = simals_alloc_link_mem();
528 		if (vectptr2 == 0) return;
529 		vectptr2->type = 'N';
530 		vectptr2->ptr = (CHAR *)nodehead;
531 		vectptr2->state = LOGIC_HIGH;
532 		vectptr2->strength = VDD_STRENGTH;
533 		vectptr2->priority = 1;
534 		vectptr2->time = 0.0;
535 		vectptr2->right = 0;
536 
537 		vectptr1 = simals_alloc_link_mem();
538 		if (vectptr1 == 0) return;
539 		vectptr1->type = 'N';
540 		vectptr1->ptr = (CHAR *)nodehead;
541 		vectptr1->state = LOGIC_LOW;
542 		vectptr1->strength = VDD_STRENGTH;
543 		vectptr1->priority = 1;
544 		vectptr1->time = time / 2.0f;
545 		vectptr1->right = vectptr2;
546 
547 		clokhead = (ROWPTR)simals_alloc_mem((INTBIG)sizeof(ROW));
548 		if (clokhead == 0) return;
549 		clokhead->inptr = (IOPTR)vectptr1;
550 		clokhead->outptr = 0;
551 		clokhead->delta = (float)time;
552 		clokhead->linear = 0.0;
553 		clokhead->exp = 0.0;
554 		clokhead->abs = 0.0;
555 		clokhead->random = 0.0;
556 		clokhead->next = 0;
557 		clokhead->delay = 0;
558 
559 		sethead = simals_alloc_link_mem();
560 		if (sethead == 0) return;
561 		sethead->type = 'C';
562 		sethead->ptr = (CHAR *)clokhead;
563 		sethead->state = 0;
564 		sethead->priority = 1;
565 		sethead->time = 0.0;
566 		sethead->right = 0;
567 		simals_insert_set_list(sethead);
568 
569 		(void)simals_initialize_simulator(FALSE);
570 		return;
571 	}
572 
573 	if (namesamen(par[1], x_("custom"), l) != 0)
574 	{
575 		ttyputbadusage(x_("telltool simulation als clock"));
576 		return;
577 	}
578 
579 	/* handle custom clock specification */
580 	if (count < 7)
581 	{
582 		ttyputusage(x_("telltool simulation als clock custom RAN STR CY (L D) *"));
583 		return;
584 	}
585 
586 	linear = (float)eatof(par[2]);
587 	strength = (INTSML)simals_atoi(par[3])*2;
588 	num = simals_atoi(par[4]);
589 
590 	totaltime = 0.0;
591 	vectroot = 0;
592 	vectptr = (CHAR**) &vectroot;
593 	for(i=5; i<count; i += 2)
594 	{
595 		vectptr2 = simals_alloc_link_mem();
596 		if (vectptr2 == 0) return;
597 		vectptr2->type = 'N';
598 		vectptr2->ptr = (CHAR *) nodehead;
599 		vectptr2->state = simals_trans_state_to_number(par[i]);
600 		vectptr2->strength = strength;
601 		vectptr2->priority = 1;
602 		vectptr2->time = eatof(par[i+1]);
603 		totaltime += vectptr2->time;
604 		vectptr2->right = 0;
605 		*vectptr = (CHAR*) vectptr2;
606 		vectptr = (CHAR**) &(vectptr2->right);
607 	}
608 	vectptr2->time = 0.0;
609 
610 	clokhead = (ROWPTR) simals_alloc_mem((INTBIG)sizeof(ROW));
611 	if (clokhead == 0) return;
612 	clokhead->inptr = (IOPTR) vectroot;
613 	clokhead->outptr = 0;
614 	clokhead->delta = (float)totaltime;
615 	clokhead->linear = linear;
616 	clokhead->exp = 0.0;
617 	clokhead->abs = 0.0;
618 	clokhead->random = 0.0;
619 	clokhead->next = 0;
620 	clokhead->delay = 0;
621 
622 	sethead = simals_alloc_link_mem();
623 	if (sethead == 0) return;
624 	sethead->type = 'C';
625 	sethead->ptr = (CHAR *) clokhead;
626 	sethead->state = num;
627 	sethead->priority = 1;
628 	sethead->time = 0.0;
629 	sethead->right = 0;
630 	simals_insert_set_list(sethead);
631 
632 	(void)simals_initialize_simulator(FALSE);
633 }
634 
635 /****************************** ERASE ******************************/
636 
simals_erase_model(void)637 void simals_erase_model(void)
638 {
639 	MODPTR modptr, nextmodptr;
640 	EXPTR exptr, nextexptr;
641 	CONPTR conptr, nextconptr;
642 	IOPTR ioptr, nextioptr;
643 	ROWPTR rowptr, nextrowptr;
644 	LOADPTR loadptr, nextloadptr;
645 	FUNCPTR funcptr;
646 	NODEPTR node, nextnode;
647 	STATPTR statptr, nextstatptr;
648 
649 	/* reset miscellaneous simulation variables */
650 	simals_linkfront = 0;
651 	simals_linkback = 0;
652 
653 	/* loop through all test vectors */
654 	simals_clearallvectors(TRUE);
655 
656 	/* loop throuth all cells in flattened network */
657 	if (simals_cellroot != 0)
658 	{
659 		simals_erase_submod(simals_cellroot);
660 		efree((CHAR *)simals_cellroot);
661 		simals_cellroot = 0;
662 	}
663 	simals_levelptr = 0;
664 
665 	/* loop through all nodes in flattened network */
666 	for(node = simals_noderoot; node != 0; node = nextnode)
667 	{
668 		nextnode = node->next;
669 
670 		/* erase all loads on the nodes */
671 		for(loadptr = node->pinptr; loadptr != 0; loadptr = nextloadptr)
672 		{
673 			nextloadptr = loadptr->next;
674 			efree((CHAR *)loadptr);
675 		}
676 
677 		/* erase all stats on the nodes */
678 		for(statptr = node->statptr; statptr != 0; statptr = nextstatptr)
679 		{
680 			nextstatptr = statptr->next;
681 			efree((CHAR *)statptr);
682 		}
683 		efree((CHAR *)node);
684 	}
685 	simals_noderoot = 0;
686 
687 	/* loop through all primitives in flattened network */
688 	for(modptr = simals_primroot; modptr != 0; modptr = nextmodptr)
689 	{
690 		nextmodptr = modptr->next;
691 		if (modptr->type == 'F')
692 		{
693 			/* loop through each formal port on the function */
694 			for(exptr = modptr->exptr; exptr != 0; exptr = nextexptr)
695 			{
696 				nextexptr = exptr->next;
697 				efree((CHAR *)exptr);
698 			}
699 
700 			/* loop through each parameter on the function */
701 			funcptr = (FUNCPTR)modptr->ptr;
702 			for(exptr = funcptr->inptr; exptr != 0; exptr = nextexptr)
703 			{
704 				nextexptr = exptr->next;
705 				efree((CHAR *)exptr);
706 			}
707 
708 			efree((CHAR *)funcptr);
709 		}
710 		if (modptr->type == 'G')
711 		{
712 			/* loop through each row in the gate */
713 			for(rowptr = (ROWPTR)modptr->ptr; rowptr != 0; rowptr = nextrowptr)
714 			{
715 				nextrowptr = rowptr->next;
716 
717 				/* loop through each input on the row */
718 				for(ioptr = rowptr->inptr; ioptr != 0; ioptr = nextioptr)
719 				{
720 					nextioptr = ioptr->next;
721 					efree((CHAR *)ioptr);
722 				}
723 
724 				/* loop through each output on the row */
725 				for(ioptr = rowptr->outptr; ioptr != 0; ioptr = nextioptr)
726 				{
727 					nextioptr = ioptr->next;
728 					efree((CHAR *)ioptr);
729 				}
730 				if (rowptr->delay != 0) efree((CHAR *)rowptr->delay);
731 				efree((CHAR *)rowptr);
732 			}
733 		}
734 		if (modptr->level != 0) efree((CHAR *)modptr->level);
735 		efree((CHAR *)modptr);
736 	}
737 	simals_primroot = 0;
738 
739 	/* loop through each model/gate/function in hierarchical description */
740 	for(modptr = simals_modroot; modptr != 0; modptr = nextmodptr)
741 	{
742 		nextmodptr = modptr->next;
743 		efree((CHAR *)modptr->name);
744 
745 		/* loop through each formal port on the model/gate/function */
746 		for(exptr = modptr->exptr; exptr != 0; exptr = nextexptr)
747 		{
748 			nextexptr = exptr->next;
749 			efree((CHAR *)exptr->node_name);
750 			efree((CHAR *)exptr);
751 		}
752 
753 		/* loop through each "SET" instruction in the model/gate/function */
754 		for(ioptr = modptr->setptr; ioptr != 0; ioptr = nextioptr)
755 		{
756 			nextioptr = ioptr->next;
757 			efree((CHAR *)ioptr->nodeptr);
758 			efree((CHAR *)ioptr);
759 		}
760 
761 		/* special cleanup for functions */
762 		if (modptr->type == 'F')
763 		{
764 			funcptr = (FUNCPTR)modptr->ptr;
765 
766 			/* loop through each load in the function */
767 			for(loadptr = modptr->loadptr; loadptr != 0; loadptr = nextloadptr)
768 			{
769 				nextloadptr = loadptr->next;
770 				efree((CHAR *)loadptr->ptr);
771 				efree((CHAR *)loadptr);
772 			}
773 
774 			/* loop through each input on the function */
775 			for(exptr = funcptr->inptr; exptr != 0; exptr = nextexptr)
776 			{
777 				nextexptr = exptr->next;
778 				efree((CHAR *)exptr->node_name);
779 				efree((CHAR *)exptr);
780 			}
781 			efree((CHAR *)funcptr);
782 		}
783 
784 		/* special cleanup for models */
785 		if (modptr->type == 'M')
786 		{
787 			/* loop through each instance in the model */
788 			for(conptr = (CONPTR)modptr->ptr; conptr != 0; conptr = nextconptr)
789 			{
790 				nextconptr = conptr->next;
791 				efree((CHAR *)conptr->inst_name);
792 				if (conptr->model_name != 0) efree(conptr->model_name);
793 
794 				/* loop through each actual port on the instance */
795 				for(exptr = conptr->exptr; exptr != 0; exptr = nextexptr)
796 				{
797 					nextexptr = exptr->next;
798 					efree((CHAR *)exptr->node_name);
799 					efree((CHAR *)exptr);
800 				}
801 				efree((CHAR *)conptr);
802 			}
803 		}
804 
805 		/* special cleanup for gates */
806 		if (modptr->type == 'G')
807 		{
808 			/* loop through each row in the gate */
809 			for(rowptr = (ROWPTR)modptr->ptr; rowptr != 0; rowptr = nextrowptr)
810 			{
811 				nextrowptr = rowptr->next;
812 
813 				/* loop through each input on the row */
814 				for(ioptr = rowptr->inptr; ioptr != 0; ioptr = nextioptr)
815 				{
816 					nextioptr = ioptr->next;
817 					efree((CHAR *)ioptr->nodeptr);
818 					efree((CHAR *)ioptr);
819 				}
820 
821 				/* loop through each output on the row */
822 				for(ioptr = rowptr->outptr; ioptr != 0; ioptr = nextioptr)
823 				{
824 					nextioptr = ioptr->next;
825 					efree((CHAR *)ioptr->nodeptr);
826 					efree((CHAR *)ioptr);
827 				}
828 				if (rowptr->delay != 0) efree((CHAR *)rowptr->delay);
829 				efree((CHAR *)rowptr);
830 			}
831 
832 			/* loop through each load in the gate */
833 			for(loadptr = modptr->loadptr; loadptr != 0; loadptr = nextloadptr)
834 			{
835 				nextloadptr = loadptr->next;
836 				efree((CHAR *)loadptr->ptr);
837 				efree((CHAR *)loadptr);
838 			}
839 		}
840 
841 		if (modptr->level != 0) efree((CHAR *)modptr->level);
842 		efree((CHAR *)modptr);
843 	}
844 	simals_modroot = 0;
845 }
846 
847 /*
848  * Routine to clear all test vectors (even the power and ground vectors if "pwrgnd"
849  * is true).
850  */
simals_clearallvectors(BOOLEAN pwrgnd)851 void simals_clearallvectors(BOOLEAN pwrgnd)
852 {
853 	LINKPTR thisset, vecthead, nextvec, nextset, lastset;
854 	ROWPTR clokhead;
855 
856 	lastset = 0;
857 	for(thisset = simals_setroot; thisset != 0; thisset = nextset)
858 	{
859 		nextset = thisset->right;
860 		if (pwrgnd || thisset->strength != VDD_STRENGTH)
861 		{
862 			if (thisset->type == 'C')
863 			{
864 				clokhead = (ROWPTR)thisset->ptr;
865 				for (vecthead = (LINKPTR)clokhead->inptr; vecthead; vecthead = nextvec)
866 				{
867 					nextvec = vecthead->right;
868 					simals_free_link_mem(vecthead);
869 				}
870 				efree((CHAR *)clokhead);
871 			}
872 			simals_free_link_mem(thisset);
873 
874 			if (lastset == 0) simals_setroot = nextset; else
875 				lastset->right = nextset;
876 		} else
877 		{
878 			lastset = thisset;
879 		}
880 	}
881 }
882 
simals_erase_submod(CONPTR conhead)883 void simals_erase_submod(CONPTR conhead)
884 {
885 	CONPTR conptr, nextconptr;
886 	EXPTR exptr, nextexptr;
887 	REGISTER INTBIG chn, i;
888 
889 	for(conptr = conhead->child; conptr != 0; conptr = nextconptr)
890 	{
891 		nextconptr = conptr->next;
892 		simals_erase_submod(conptr);
893 		for(exptr = conptr->exptr; exptr != 0; exptr = nextexptr)
894 		{
895 			nextexptr = exptr->next;
896 			efree((CHAR *)exptr);
897 		}
898 		efree((CHAR *)conptr);
899 	}
900 	if (conhead->display_page != 0)
901 	{
902 		chn = conhead->num_chn + 1;
903 		for (i = 1; i < chn; i++)
904 			efree((CHAR *)conhead->display_page[i].name);
905 		efree((CHAR *)conhead->display_page);
906 	}
907 }
908 
909 /****************************** GO ******************************/
910 
911 /*
912  * Name: simals_go_command
913  *
914  * Description:
915  *	This procedure parses the command line for the go command from the
916  * keyboard.  The maximum execution time must also be specified for the
917  * simulation run.
918  */
simals_go_command(INTBIG count,CHAR * par[])919 void simals_go_command(INTBIG count, CHAR *par[])
920 {
921 	double max;
922 	NODEPROTO *np;
923 
924 	if (sim_window_isactive(&np) == 0)
925 	{
926 		ttyputerr(M_("No simulator active"));
927 		return;
928 	}
929 	if (count < 1)
930 	{
931 		ttyputerr(M_("Must specify simulation time"));
932 		return;
933 	}
934 	max = eatof(par[0]);
935 	if (max <= 0.0)
936 	{
937 		ttyputerr(M_("Simulation time must be greater than 0 seconds"));
938 		return;
939 	}
940 	sim_window_settimerange(0, 0.0, max);
941 
942 	(void)simals_initialize_simulator(TRUE);
943 }
944 
945 /****************************** HELP ******************************/
946 
947 /*
948  * Name: simals_help_command
949  *
950  * Description:
951  *	This procedure process the help command and display help information.
952  */
simals_help_command(void)953 void simals_help_command(void)
954 {
955 	(void)us_helpdlog(x_("ALS"));
956 }
957 
958 /****************************** LEVEL ******************************/
959 
960 /*
961  * Name: simals_level_up_command
962  *
963  * Description:
964  *	This procedure changes the level of hierarchy up one level.
965  */
simals_level_up_command(void)966 void simals_level_up_command(void)
967 {
968 	CONPTR  cellptr;
969 	INTBIG   l, len, i;
970 	double maintime, exttime;
971 	NODEPROTO *np;
972 
973 	if (sim_window_isactive(&np) == 0)
974 	{
975 		ttyputerr(_("No simulator active"));
976 		return;
977 	}
978 
979 	if (simals_levelptr == 0)
980 	{
981 		ttyputerr(_("No simulation is running"));
982 		return;
983 	}
984 	cellptr = simals_levelptr->parent;
985 	if (! cellptr)
986 	{
987 		ttyputerr(_("ERROR: Currently at top level of hierarchy"));
988 		return;
989 	}
990 
991 	simals_levelptr = cellptr;
992 
993 	/* determine the level title */
994 	if (simals_title != 0)
995 	{
996 		len = strlen(simals_title);
997 		for(i=len-1; i>0; i--)
998 			if (simals_title[i] == '.') break;
999 		if (i > 0) simals_title[i] = 0; else
1000 		{
1001 			efree((CHAR *)simals_title);
1002 			simals_title = 0;
1003 		}
1004 	}
1005 
1006 	/* reinitialize simulator while preserving time information */
1007 	maintime = sim_window_getmaincursor();
1008 	exttime = sim_window_getextensioncursor();
1009 	if (simals_set_current_level()) return;
1010 	sim_window_setmaincursor(maintime);
1011 	sim_window_setextensioncursor(exttime);
1012 
1013 	l = simals_levelptr->num_chn;
1014 	sim_window_setnumframes(l);
1015 	sim_window_settopvisframe(0);
1016 	(void)simals_initialize_simulator(TRUE);
1017 }
1018 
1019 /*
1020  * Name: simals_level_set_command
1021  *
1022  * Description:
1023  *	This procedure changes the level of hierarchy to a specified new (lower) level.
1024  */
simals_level_set_command(CHAR * instname)1025 void simals_level_set_command(CHAR *instname)
1026 {
1027 	CONPTR  cellptr;
1028 	INTBIG   l;
1029 	double maintime, exttime;
1030 	CHAR    *pt;
1031 	NODEPROTO *np;
1032 	void *infstr;
1033 
1034 	if (sim_window_isactive(&np) == 0)
1035 	{
1036 		ttyputerr(_("No simulator active"));
1037 		return;
1038 	}
1039 
1040 	if (instname != 0)
1041 	{
1042 		for(pt = instname; *pt != 0; pt++) if (*pt == ' ') break;
1043 		*pt = 0;
1044 		simals_convert_to_upper(instname);
1045 		cellptr = simals_find_level(instname);
1046 		if (! cellptr)
1047 		{
1048 			ttyputerr(M_("ERROR: Unable to find level %s"), instname);
1049 			return;
1050 		}
1051 
1052 		simals_levelptr = cellptr;
1053 
1054 		/* determine the level title */
1055 		infstr = initinfstr();
1056 		if (simals_title != 0) formatinfstr(infstr, x_("%s."), simals_title);
1057 		addstringtoinfstr(infstr, simals_levelptr->inst_name);
1058 		if (simals_title != 0) efree((CHAR *)simals_title);
1059 		allocstring(&simals_title, returninfstr(infstr), sim_tool->cluster);
1060 	}
1061 
1062 	/* reinitialize simulator while preserving time information */
1063 	maintime = sim_window_getmaincursor();
1064 	exttime = sim_window_getextensioncursor();
1065 	if (simals_set_current_level()) return;
1066 	sim_window_setmaincursor(maintime);
1067 	sim_window_setextensioncursor(exttime);
1068 
1069 	l = simals_levelptr->num_chn;
1070 	sim_window_setnumframes(l);
1071 	sim_window_settopvisframe(0);
1072 	(void)simals_initialize_simulator(TRUE);
1073 }
1074 
1075 /****************************** PRINT ******************************/
1076 
1077 /*
1078  * routine to print out the display screen status and information
1079  */
simals_print_command(INTBIG count,CHAR * par[])1080 void simals_print_command(INTBIG count, CHAR *par[])
1081 {
1082 	INTBIG l;
1083 	CHAR *pt, *s1;
1084 	LINKPTR  linkhead;
1085 	NODEPTR  nodehead;
1086 	STATPTR  stathead;
1087 	MODPTR   primhead;
1088 	ROWPTR   rowhead;
1089 	EXPTR    exhead;
1090 	FUNCPTR  funchead;
1091 	CONPTR   cellhead;
1092 	REGISTER void *infstr;
1093 
1094 	if (count < 1)
1095 	{
1096 		ttyputusage(x_("telltool simulation als print OPTION"));
1097 		return;
1098 	}
1099 	l = estrlen(pt = par[0]);
1100 
1101 	if (namesamen(pt, x_("size"), l) == 0 && l >= 2)
1102 	{
1103 		ttyputmsg(M_("Number of Primitive Elements in Database = %ld"), simals_pseq);
1104 		ttyputmsg(M_("Number of Nodes in Database = %ld"), simals_nseq);
1105 		return;
1106 	}
1107 
1108 	if (namesamen(pt, x_("vector"), l) == 0 && l >= 1)
1109 	{
1110 		linkhead = simals_setroot;
1111 		ttyputmsg(M_("** VECTOR LINKLIST **"));
1112 		while (linkhead)
1113 		{
1114 			switch (linkhead->type)
1115 			{
1116 				case 'N':
1117 					nodehead = (NODEPTR)linkhead->ptr;
1118 					s1 = simals_trans_number_to_state(linkhead->state);
1119 					ttyputmsg(M_("***** vector: $N%ld, state = %s, strength = %s, time = %g, priority = %d"),
1120 						nodehead->num, s1, simals_strengthstring(linkhead->strength),
1121 							linkhead->time, linkhead->priority);
1122 					break;
1123 				case 'F':
1124 					stathead = (STATPTR)linkhead->ptr;
1125 					nodehead = stathead->nodeptr;
1126 					s1 = simals_trans_number_to_state(linkhead->state);
1127 					ttyputmsg(M_("***** function: $N%ld, state = %s, strength = %s, time = %g, priority = %d"),
1128 						nodehead->num, s1, simals_strengthstring(linkhead->strength),
1129 							linkhead->time, linkhead->priority);
1130 					break;
1131 				case 'R':
1132 					ttyputmsg(M_("***** rowptr = %ld, time = %g, priority = %d"),
1133 						linkhead->ptr, linkhead->time, linkhead->priority);
1134 					break;
1135 				case 'C':
1136 					ttyputmsg(M_("***** clokptr = %ld, time = %g, priority = %d"),
1137 						linkhead->ptr, linkhead->time, linkhead->priority);
1138 			}
1139 			linkhead = linkhead->right;
1140 		}
1141 		return;
1142 	}
1143 
1144 	if (namesamen(pt, x_("netlist"), l) == 0 && l >= 1)
1145 	{
1146 		ttyputmsg(M_("** NETWORK DESCRIPTION **"));
1147 		for (primhead = simals_primroot; primhead; primhead = primhead->next)
1148 		{
1149 			if (stopping(STOPREASONDISPLAY)) return;
1150 			switch (primhead->type)
1151 			{
1152 				case 'F':
1153 					infstr = initinfstr();
1154 					formatinfstr(infstr, M_("FUNCTION %ld: %s (instance %s) ["), primhead->num, primhead->name,
1155 						(primhead->level == NULL) ? M_("null") : primhead->level);
1156 					for (exhead = primhead->exptr; exhead; exhead=exhead->next)
1157 					{
1158 						if (exhead != primhead->exptr) addstringtoinfstr(infstr, x_(", "));
1159 						formatinfstr(infstr, x_("N%ld"), exhead->nodeptr->num);
1160 					}
1161 					addstringtoinfstr(infstr, x_("]"));
1162 					ttyputmsg(x_("%s"), returninfstr(infstr));
1163 					infstr = initinfstr();
1164 					addstringtoinfstr(infstr, M_("  Event Driving Inputs:"));
1165 					funchead = (FUNCPTR)primhead->ptr;
1166 					for (exhead = funchead->inptr; exhead; exhead=exhead->next)
1167 						formatinfstr(infstr, x_(" N%ld"), exhead->nodeptr->num);
1168 					ttyputmsg(x_("%s"), returninfstr(infstr));
1169 					infstr = initinfstr();
1170 					addstringtoinfstr(infstr, M_("  Output Ports:"));
1171 					for (exhead = primhead->exptr; exhead; exhead=exhead->next)
1172 					{
1173 						if (exhead->node_name)
1174 							formatinfstr(infstr, x_(" N%ld"), ((STATPTR)exhead->node_name)->nodeptr->num);
1175 					}
1176 					ttyputmsg(x_("%s"), returninfstr(infstr));
1177 					ttyputmsg(M_("  Timing: D=%g, L=%g, E=%g, R=%g, A=%g"), funchead->delta,
1178 						funchead->linear, funchead->exp, funchead->random, funchead->abs);
1179 					ttyputmsg(M_("  Firing Priority = %d"), primhead->priority);
1180 					break;
1181 				case 'G':
1182 					ttyputmsg(M_("GATE %ld: %s (instance %s)"), primhead->num, primhead->name,
1183 						(primhead->level == NULL) ? M_("null") : primhead->level);
1184 					for (rowhead = (ROWPTR)primhead->ptr; rowhead; rowhead=rowhead->next)
1185 					{
1186 						ttyputmsg(M_("  Timing: D=%g, L=%g, E=%g, R=%g, A=%g"), rowhead->delta,
1187 							rowhead->linear, rowhead->exp, rowhead->random, rowhead->abs);
1188 						ttyputmsg(M_("  Delay type: %s"), (rowhead->delay == NULL) ? M_("null") : rowhead->delay);
1189 						simals_print_in_entry(rowhead);
1190 						simals_print_out_entry(rowhead);
1191 					}
1192 					ttyputmsg(M_("  Firing Priority = %d"), primhead->priority);
1193 					break;
1194 				default:
1195 					ttyputerr(M_("Illegal primitive type '%c', database is bad"), primhead->type);
1196 					break;
1197 			}
1198 		}
1199 		return;
1200 	}
1201 
1202 	if (namesamen(pt, x_("xref"), l) == 0 && l >= 1)
1203 	{
1204 		ttyputmsg(M_("** CROSS REFERENCE TABLE **"));
1205 		simals_print_xref_entry(simals_levelptr, 0);
1206 		return;
1207 	}
1208 
1209 	if (namesamen(pt, x_("state"), l) == 0 && l >= 2)
1210 	{
1211 		if (count < 2)
1212 		{
1213 			ttyputusage(x_("telltool simulation als print state NODENAME"));
1214 			return;
1215 		}
1216 		simals_convert_to_upper(par[1]);
1217 		nodehead = simals_find_node(par[1]);
1218 		if (nodehead == 0)
1219 		{
1220 			ttyputerr(M_("ERROR: Unable to find node %s"), par[1]);
1221 			return;
1222 		}
1223 
1224 		s1 = simals_trans_number_to_state(nodehead->new_state);
1225 		ttyputmsg(M_("Node %s: State = %s, Strength = %s"), par[1], s1,
1226 			simals_strengthstring(nodehead->new_strength));
1227 		stathead = nodehead->statptr;
1228 		while (stathead)
1229 		{
1230 			s1 = simals_trans_number_to_state(stathead->new_state);
1231 			ttyputmsg(M_("Primitive %ld:    State = %s, Strength = %s"), stathead->primptr->num,
1232 				s1, simals_strengthstring(stathead->new_strength));
1233 			stathead = stathead->next;
1234 		}
1235 		return;
1236 	}
1237 
1238 	if (namesamen(pt, x_("instances"), l) == 0 && l >= 1)
1239 	{
1240 		ttyputmsg(M_("Instances at level: %s"), simals_compute_path_name(simals_levelptr));
1241 		for (cellhead = simals_levelptr->child; cellhead; cellhead = cellhead->next)
1242 		{
1243 			if (stopping(STOPREASONDISPLAY)) break;
1244 			ttyputmsg(M_("Name: %s, Model: %s"), cellhead->inst_name, cellhead->model_name);
1245 		}
1246 		return;
1247 	}
1248 	ttyputbadusage(x_("telltool simulation als print"));
1249 }
1250 
simals_strengthstring(INTSML strength)1251 CHAR *simals_strengthstring(INTSML strength)
1252 {
1253 	if (strength == OFF_STRENGTH) return(_("off"));
1254 	if (strength <= NODE_STRENGTH) return(_("node"));
1255 	if (strength <= GATE_STRENGTH) return(_("gate"));
1256 	return(_("power"));
1257 }
1258 
1259 /*
1260  * Name: simals_print_in_entry
1261  *
1262  * Description:
1263  *	This procedure examines an input entry and prints out the condition
1264  * that it represents.  It is possible for an input entry operand to represent
1265  * a logic value, integer value, or another node address.
1266  *
1267  * Calling Arguments:
1268  *	rowhead = pointer to the row being printed
1269  */
simals_print_in_entry(ROWPTR rowhead)1270 void simals_print_in_entry(ROWPTR rowhead)
1271 {
1272 	INTBIG	  num;
1273 	CHAR	  flag, s1[15], *s2;
1274 	UCHAR     operatr;
1275 	IOPTR	  iohead;
1276 	NODEPTR	  nodehead;
1277 	REGISTER void *infstr;
1278 
1279 	flag = 0;
1280 	infstr = initinfstr();
1281 	addstringtoinfstr(infstr, M_("  Input: "));
1282 
1283 	for (iohead = rowhead->inptr; iohead; iohead = iohead->next)
1284 	{
1285 		if (flag) addstringtoinfstr(infstr, x_("& "));
1286 		flag = 1;
1287 
1288 		nodehead = (NODEPTR)iohead->nodeptr;
1289 		(void)esnprintf(s1, 15, x_("N%ld"), nodehead->num);
1290 		addstringtoinfstr(infstr, s1);
1291 
1292 		if (iohead->operatr > 127)
1293 		{
1294 			operatr = iohead->operatr - 128;
1295 			nodehead = (NODEPTR) iohead->operand;
1296 			(void)esnprintf(s1, 15, x_("%cN%ld"), operatr, nodehead->num);
1297 			addstringtoinfstr(infstr, s1);
1298 			continue;
1299 		}
1300 
1301 		addtoinfstr(infstr, iohead->operatr);
1302 
1303 		num = (INTBIG)iohead->operand;
1304 		s2 = simals_trans_number_to_state(num);
1305 		addstringtoinfstr(infstr, s2);
1306 		addstringtoinfstr(infstr, x_(" "));
1307 	}
1308 	ttyputmsg(x_("%s"), returninfstr(infstr));
1309 }
1310 
1311 /*
1312  * Name: simals_print_out_entry
1313  *
1314  * Description:
1315  *	This procedure examines an output entry and prints out the condition
1316  * that it represents.  It is possible for an output entry operand to represent
1317  * a logic value, integer value, or another node address.
1318  *
1319  * Calling Arguments:
1320  *	rowhead = pointer to the row being printed
1321  */
simals_print_out_entry(ROWPTR rowhead)1322 void simals_print_out_entry(ROWPTR rowhead)
1323 {
1324 	INTBIG	  num;
1325 	CHAR      flag, *s2, s1[50];
1326 	UCHAR     operatr;
1327 	IOPTR	  iohead;
1328 	STATPTR	stathead;
1329 	NODEPTR	nodehead;
1330 	REGISTER void *infstr;
1331 
1332 	flag = 0;
1333 	infstr = initinfstr();
1334 	addstringtoinfstr(infstr, M_("  Output: "));
1335 
1336 	for (iohead = rowhead->outptr; iohead; iohead = iohead->next)
1337 	{
1338 		if (flag) addstringtoinfstr(infstr, x_("& "));
1339 		flag = 1;
1340 
1341 		stathead = (STATPTR)iohead->nodeptr;
1342 		nodehead = stathead->nodeptr;
1343 		(void)esnprintf(s1, 50, x_("N%ld"), nodehead->num);
1344 		addstringtoinfstr(infstr, s1);
1345 
1346 		if (iohead->operatr > 127)
1347 		{
1348 			operatr = iohead->operatr - 128;
1349 			nodehead = (NODEPTR) iohead->operand;
1350 			(void)esnprintf(s1, 50, x_("%cN%ld@%d "), operatr, nodehead->num, (iohead->strength+1)/2);
1351 			addstringtoinfstr(infstr, s1);
1352 			continue;
1353 		}
1354 
1355 		addtoinfstr(infstr, iohead->operatr);
1356 
1357 		num = (INTBIG)iohead->operand;
1358 		s2 = simals_trans_number_to_state(num);
1359 		addstringtoinfstr(infstr, s2);
1360 		(void)esnprintf(s1, 50, x_("@%d "), (iohead->strength+1)/2);
1361 		addstringtoinfstr(infstr, s1);
1362 	}
1363 	ttyputmsg(x_("%s"), returninfstr(infstr));
1364 }
1365 
1366 /*
1367  * Name: simals_print_xref_entry
1368  *
1369  * Description:
1370  *	This procedure prints entries from the cross reference table that was
1371  * generated to transform the hierarchical network description into a totally flat
1372  * network description.  The calling arguments define the root of the reference
1373  * table column and the level of indentation for the column.
1374  *
1375  * Calling Arguments:
1376  *	cellhead = pointer to cross reference table
1377  *	tab	= integer value indicating level of output indentation
1378  */
simals_print_xref_entry(CONPTR cellhead,INTBIG tab)1379 void simals_print_xref_entry(CONPTR cellhead, INTBIG tab)
1380 {
1381 	INTBIG  i, k, delay;
1382 	CHAR    tabsp[200], ts[256];
1383 	EXPTR   exhead;
1384 	CONPTR  subcell;
1385 	REGISTER void *infstr;
1386 
1387 	if (stopping(STOPREASONDISPLAY)) return;
1388 	for (i = 0; i < tab; ++i) tabsp[i] = ' ';
1389 	tabsp[tab] = 0;
1390 	ttyputmsg(M_("%sLevel: %s, Model: %s"), tabsp, simals_compute_path_name(cellhead),
1391 		cellhead->model_name);
1392 
1393 	for (exhead = cellhead->exptr; exhead; exhead = exhead->next)
1394 	{
1395 		if (stopping(STOPREASONDISPLAY)) return;
1396 		k = 0;
1397 		infstr = 0;
1398 		for (i=0; i<12; i++)
1399 		{
1400 			delay = exhead->td[i];
1401 			if (delay != 0)
1402 			{
1403 				if (k == 0) infstr = initinfstr();
1404 				(void)esnprintf(ts, 256, x_("%s=%ld "), simals_tnames[i], delay);
1405 				addstringtoinfstr(infstr, ts);
1406 				k++;
1407 			}
1408 		}
1409 		if (k == 0) ttyputmsg(x_("%s%14s --> N%ld"), tabsp, exhead->node_name, exhead->nodeptr->num); else
1410 			ttyputmsg(x_("%s%14s --> N%ld (%s)"), tabsp, exhead->node_name, exhead->nodeptr->num, returninfstr(infstr));
1411 	}
1412 
1413 	if (simals_instbuf[simals_instptr[1]] == 'X') return;
1414 
1415 	for (subcell = cellhead->child; subcell; subcell = subcell->next)
1416 		simals_print_xref_entry(subcell, tab + 10);
1417 }
1418 
1419 /****************************** SEED ******************************/
1420 
1421 /*
1422  * Name: simals_seed_command
1423  *
1424  * Description:
1425  *	This procedure sets a flag which tells the simulator if it is necessary
1426  * to reseed the Random Number Generator each time a simulation is run.
1427  */
simals_seed_command(INTBIG count,CHAR * par[])1428 void simals_seed_command(INTBIG count, CHAR *par[])
1429 {
1430 	if (count < 1)
1431 	{
1432 		ttyputusage(x_("telltool simulation als seed (reset | no-reset)"));
1433 		return;
1434 	}
1435 	if (namesamen(par[0], x_("reset"), estrlen(par[0])) == 0)
1436 		simals_seed_flag = FALSE; else simals_seed_flag = TRUE;
1437 }
1438 
1439 /****************************** SET ******************************/
1440 
1441 /*
1442  * Name: simals_set_command
1443  *
1444  * Description:
1445  *	This procedure sets the specified node to the state that is indicated
1446  * in the command line.
1447 */
simals_set_command(INTBIG count,CHAR * par[])1448 void simals_set_command(INTBIG count, CHAR *par[])
1449 {
1450 	INTBIG	state;
1451 	INTSML	strength;
1452 	double   time;
1453 	NODEPTR  nodehead;
1454 	LINKPTR  sethead;
1455 	NODEPROTO *np;
1456 
1457 	if (sim_window_isactive(&np) == 0)
1458 	{
1459 		ttyputerr(_("No simulator active"));
1460 		return;
1461 	}
1462 	if (count < 4)
1463 	{
1464 		ttyputusage(x_("telltool simulation als set NODE LEVEL STRENGTH TIME"));
1465 		return;
1466 	}
1467 	simals_convert_to_upper(par[0]);
1468 	nodehead = simals_find_node(par[0]);
1469 	if (! nodehead)
1470 	{
1471 		ttyputerr(_("ERROR: Unable to find node %s"), par[0]);
1472 		return;
1473 	}
1474 
1475 	state = simals_trans_state_to_number(par[1]);
1476 	strength = (INTSML)simals_atoi(par[2])*2;
1477 	time = eatof(par[3]);
1478 
1479 	sethead = simals_alloc_link_mem();
1480 	if (sethead == 0) return;
1481 	sethead->type = 'N';
1482 	sethead->ptr = (CHAR *)nodehead;
1483 	sethead->state = state;
1484 	sethead->strength = strength;
1485 	sethead->priority = 2;
1486 	sethead->time = time;
1487 	sethead->right = 0;
1488 	simals_insert_set_list(sethead);
1489 
1490 	ttyputmsg(M_("Node '%s' scheduled, state = %s, strength = %s, time = %g"), par[0], par[1],
1491 		simals_strengthstring(strength), time);
1492 	(void)simals_initialize_simulator(FALSE);
1493 }
1494 
1495 /****************************** TRACE ******************************/
1496 
1497 /*
1498  * Name: simals_trace_command
1499  *
1500  * Description:
1501  *	This procedure turns on/off the trace buffer.  If it is turned off, no
1502  * timing diagram information will be stored in memory for plotting.
1503  */
simals_trace_command(INTBIG count,CHAR * par[])1504 void simals_trace_command(INTBIG count, CHAR *par[])
1505 {
1506 	INTBIG l;
1507 	CHAR *pt;
1508 
1509 	if (count < 1)
1510 	{
1511 		ttyputusage(x_("telltool simulation als trace OPTION"));
1512 		return;
1513 	}
1514 	l = estrlen(pt = par[0]);
1515 	if (namesamen(pt, x_("on"), l) == 0 && l >= 2)
1516 	{
1517 		(void)setvalkey((INTBIG)sim_tool, VTOOL, simals_no_update_key, 0, VINTEGER);
1518 		return;
1519 	}
1520 	if (namesamen(pt, x_("off"), l) == 0 && l >= 2)
1521 	{
1522 		(void)setvalkey((INTBIG)sim_tool, VTOOL, simals_no_update_key, 1, VINTEGER);
1523 		return;
1524 	}
1525 	ttyputbadusage(x_("telltool simulation als trace"));
1526 }
1527 
1528 /****************************** VECTOR ******************************/
1529 
simals_vector_command(INTBIG count,CHAR * par[])1530 void simals_vector_command(INTBIG count, CHAR *par[])
1531 {
1532 	INTBIG	 l, flag;
1533 	INTSML   strength;
1534 	CHAR     s1[256], *s2, *pt, **vectptr1, **backptr;
1535 	CHAR    *filename, *truename;
1536 	FILE    *vin, *vout;
1537 	LINKPTR  sethead, vecthead, vectptr2, nextvec;
1538 	ROWPTR   clokhead;
1539 	NODEPTR  nodehead;
1540 	double   time;
1541 	NODEPROTO *np;
1542 	REGISTER void *infstr;
1543 
1544 	if (sim_window_isactive(&np) == 0)
1545 	{
1546 		ttyputerr(_("No simulator active"));
1547 		return;
1548 	}
1549 	if (count < 1)
1550 	{
1551 		ttyputusage(x_("telltool simulation als vector OPTION"));
1552 		return;
1553 	}
1554 	l = estrlen(pt = par[0]);
1555 
1556 	if (namesamen(pt, x_("load"), l) == 0)
1557 	{
1558 		if (count < 2)
1559 		{
1560 			par[1] = fileselect(_("ALS vector file"), sim_filetypealsvec, x_(""));
1561 			if (par[1] == 0) return;
1562 		}
1563 		vin = xopen(par[1], sim_filetypealsvec, x_(""), &filename);
1564 		if (! vin)
1565 		{
1566 			ttyputerr(_("ERROR: Can't open %s"), par[1]);
1567 			return;
1568 		}
1569 
1570 		/* clear all vectors */
1571 		while (simals_setroot)
1572 		{
1573 			sethead = simals_setroot;
1574 			simals_setroot = simals_setroot->right;
1575 			if (sethead->type == 'C')
1576 			{
1577 				clokhead = (ROWPTR) sethead->ptr;
1578 				for (vectptr2 = (LINKPTR) clokhead->inptr; vectptr2; vectptr2 = nextvec)
1579 				{
1580 					nextvec = vectptr2->right;
1581 					simals_free_link_mem(vectptr2);
1582 				}
1583 				efree((CHAR *)clokhead);
1584 			}
1585 			simals_free_link_mem(sethead);
1586 		}
1587 
1588 		flag = 1;
1589 		for(;;)
1590 		{
1591 			if (flag)
1592 			{
1593 				if (xfgets(s1, 255, vin))
1594 				{
1595 					xclose(vin);
1596 					(void)simals_initialize_simulator(FALSE);
1597 					break;
1598 				}
1599 				simals_convert_to_upper(s1);
1600 				if (simals_fragment_command(s1)) break;
1601 			}
1602 
1603 			if (! estrcmp(simals_instbuf, x_("CLOCK")))
1604 			{
1605 				simals_convert_to_upper(&(simals_instbuf[simals_instptr[1]]));
1606 				nodehead = simals_find_node(&(simals_instbuf[simals_instptr[1]]));
1607 				if (! nodehead)
1608 				{
1609 					ttyputerr(_("ERROR: Unable to find node %s"),
1610 						&(simals_instbuf[simals_instptr[1]]));
1611 					flag = 1;
1612 					continue;
1613 				}
1614 				strength = eatoi(&(simals_instbuf[simals_instptr[9]]))*2;
1615 
1616 				sethead = simals_alloc_link_mem();
1617 				if (sethead == 0) return;
1618 				sethead->type = 'C';
1619 				sethead->ptr = (CHAR*)(clokhead = (ROWPTR) simals_alloc_mem((INTBIG)sizeof(ROW)));
1620 				if (sethead->ptr == 0) return;
1621 				sethead->state = eatoi(&(simals_instbuf[simals_instptr[13]]));
1622 				sethead->priority = 1;
1623 				sethead->time = eatof(&(simals_instbuf[simals_instptr[11]]));
1624 				sethead->right = 0;
1625 				simals_insert_set_list(sethead);
1626 
1627 				clokhead->delta = (float)eatof(&(simals_instbuf[simals_instptr[3]]));
1628 				clokhead->linear = (float)eatof(&(simals_instbuf[simals_instptr[5]]));
1629 				clokhead->exp = (float)eatof(&(simals_instbuf[simals_instptr[7]]));
1630 				clokhead->abs = 0.0;
1631 				clokhead->random = 0.0;
1632 				clokhead->next = 0;
1633 				clokhead->delay = 0;
1634 
1635 				vectptr1 = (CHAR**) &(clokhead->inptr);
1636 				for(;;)
1637 				{
1638 					if (xfgets(s1, 255, vin))
1639 					{
1640 						xclose(vin);
1641 						(void)simals_initialize_simulator(FALSE);
1642 						return;
1643 					}
1644 					simals_convert_to_upper(s1);
1645 					if (simals_fragment_command(s1)) return;
1646 					if (!estrcmp(simals_instbuf, x_("CLOCK")) || !estrcmp(simals_instbuf, x_("SET")))
1647 					{
1648 						flag = 0;
1649 						break;
1650 					}
1651 					vectptr2 = simals_alloc_link_mem();
1652 					if (vectptr2 == 0) return;
1653 					vectptr2->type = 'N';
1654 					vectptr2->ptr = (CHAR *)nodehead;
1655 					vectptr2->state = simals_trans_state_to_number(simals_instbuf);
1656 					vectptr2->strength = strength;
1657 					vectptr2->priority = 1;
1658 					vectptr2->time = eatof(&(simals_instbuf[simals_instptr[1]]));
1659 					vectptr2->right = 0;
1660 					*vectptr1 = (CHAR*) vectptr2;
1661 					vectptr1 = (CHAR**) &(vectptr2->right);
1662 				}
1663 			}
1664 
1665 			if (! estrcmp(simals_instbuf, x_("SET")))
1666 			{
1667 				simals_convert_to_upper(&(simals_instbuf[simals_instptr[1]]));
1668 				nodehead = simals_find_node(&(simals_instbuf[simals_instptr[1]]));
1669 				if (! nodehead)
1670 				{
1671 					ttyputerr(_("ERROR: Unable to find node %s"),
1672 						&(simals_instbuf[simals_instptr[1]]));
1673 					flag = 1;
1674 					continue;
1675 				}
1676 
1677 				sethead = simals_alloc_link_mem();
1678 				if (sethead == 0) return;
1679 				sethead->type = 'N';
1680 				sethead->ptr = (CHAR *) nodehead;
1681 				sethead->state = simals_trans_state_to_number(&(simals_instbuf[simals_instptr[2]]));
1682 				sethead->strength = eatoi(&(simals_instbuf[simals_instptr[3]]))*2;
1683 				sethead->priority = 2;
1684 				sethead->time = eatof(&(simals_instbuf[simals_instptr[5]]));
1685 				sethead->right = 0;
1686 				simals_insert_set_list(sethead);
1687 				flag = 1;
1688 			}
1689 		}
1690 		return;
1691 	}
1692 
1693 	if (namesamen(pt, x_("new"), l) == 0)
1694 	{
1695 		/* clear all vectors */
1696 		simals_clearallvectors(FALSE);
1697 		(void)simals_initialize_simulator(FALSE);
1698 		return;
1699 	}
1700 
1701 	if (namesamen(pt, x_("save"), l) == 0)
1702 	{
1703 		if (count < 2)
1704 		{
1705 			infstr = initinfstr();
1706 			formatinfstr(infstr, x_("%s.vec"), el_curlib->libname);
1707 			par[1] = fileselect(_("ALS vector file"), sim_filetypealsvec|FILETYPEWRITE,
1708 				returninfstr(infstr));
1709 			if (par[1] == 0) return;
1710 		}
1711 		vout = xcreate(par[1], sim_filetypealsvec, 0, &truename);
1712 		if (vout == 0)
1713 		{
1714 			if (truename != 0) ttyputerr(_("ERROR: Can't create %s"), truename);
1715 			return;
1716 		}
1717 
1718 		for (sethead = simals_setroot; sethead; sethead = sethead->right)
1719 		{
1720 			switch (sethead->type)
1721 			{
1722 				case 'C':
1723 					clokhead = (ROWPTR)sethead->ptr;
1724 					vecthead = (LINKPTR)clokhead->inptr;
1725 					simals_compute_node_name((NODEPTR)vecthead->ptr, s1);
1726 					xprintf(vout, x_("CLOCK %s D=%g L=%g E=%g "), s1, clokhead->delta,
1727 						clokhead->linear, clokhead->exp);
1728 					xprintf(vout, x_("STRENGTH=%d TIME=%g CYCLES=%ld\n"), vecthead->strength/2,
1729 						sethead->time, sethead->state);
1730 					for (; vecthead; vecthead = vecthead->right)
1731 					{
1732 						s2 = simals_trans_number_to_state(vecthead->state);
1733 						xprintf(vout, x_("  %s %g\n"), s2, vecthead->time);
1734 					}
1735 					break;
1736 				case 'N':
1737 					simals_compute_node_name((NODEPTR)sethead->ptr, s1);
1738 					s2 = simals_trans_number_to_state(sethead->state);
1739 					xprintf(vout, x_("SET %s=%s@%d TIME=%g\n"), s1, s2, sethead->strength/2,
1740 						sethead->time);
1741 			}
1742 		}
1743 		xclose(vout);
1744 		return;
1745 	}
1746 
1747 	if (namesamen(pt, x_("delete"), l) == 0)
1748 	{
1749 		if (count < 3)
1750 		{
1751 			ttyputusage(x_("telltool simulation als vector delete NODE OPTIONS"));
1752 			return;
1753 		}
1754 		simals_convert_to_upper(par[1]);
1755 		nodehead = simals_find_node(par[1]);
1756 		if (! nodehead)
1757 		{
1758 			ttyputerr(_("ERROR: Unable to find node %s"), par[1]);
1759 			return;
1760 		}
1761 
1762 		backptr = (CHAR**) &simals_setroot;
1763 		sethead = simals_setroot;
1764 
1765 		if (par[2][0] == 'a')
1766 		{
1767 			while (sethead)
1768 			{
1769 				if (sethead->type == 'C')
1770 				{
1771 					clokhead = (ROWPTR)sethead->ptr;
1772 					vecthead = (LINKPTR)clokhead->inptr;
1773 					if ((NODEPTR)vecthead->ptr == nodehead)
1774 					{
1775 						*backptr = (CHAR *)sethead->right;
1776 						simals_free_link_mem(sethead);
1777 						sethead = (LINKPTR)*backptr;
1778 						efree((CHAR *)clokhead);
1779 						for (; vecthead; vecthead = nextvec)
1780 						{
1781 							nextvec = vecthead->right;
1782 							simals_free_link_mem(vecthead);
1783 						}
1784 						continue;
1785 					}
1786 				} else
1787 				{
1788 					if ((NODEPTR)sethead->ptr == nodehead)
1789 					{
1790 						*backptr = (CHAR *)sethead->right;
1791 						simals_free_link_mem(sethead);
1792 						sethead = (LINKPTR)*backptr;
1793 						continue;
1794 					}
1795 				}
1796 
1797 				backptr = (CHAR**) &(sethead->right);
1798 				sethead = sethead->right;
1799 			}
1800 			(void)simals_initialize_simulator(FALSE);
1801 			return;
1802 		}
1803 
1804 		if (count < 4)
1805 		{
1806 			ttyputusage(x_("telltool simulation als vector delete time TIME"));
1807 			return;
1808 		}
1809 		time = eatof(par[2]);
1810 		while (sethead)
1811 		{
1812 			if (sethead->time == time)
1813 			{
1814 				if (sethead->type == 'C')
1815 				{
1816 					clokhead = (ROWPTR)sethead->ptr;
1817 					vecthead = (LINKPTR)clokhead->inptr;
1818 					if ((NODEPTR)vecthead->ptr == nodehead)
1819 					{
1820 						*backptr = (CHAR*)sethead->right;
1821 						simals_free_link_mem(sethead);
1822 						sethead = (LINKPTR)*backptr;
1823 						efree((CHAR *)clokhead);
1824 						for (; vecthead; vecthead = nextvec)
1825 						{
1826 							nextvec = vecthead->right;
1827 							simals_free_link_mem(vecthead);
1828 						}
1829 						(void)simals_initialize_simulator(FALSE);
1830 						return;
1831 					}
1832 				} else
1833 				{
1834 					if ((NODEPTR)sethead->ptr == nodehead)
1835 					{
1836 						*backptr = (CHAR *)sethead->right;
1837 						simals_free_link_mem(sethead);
1838 						sethead = (LINKPTR)*backptr;
1839 						(void)simals_initialize_simulator(FALSE);
1840 						return;
1841 					}
1842 				}
1843 			}
1844 
1845 			backptr = (CHAR**) &(sethead->right);
1846 			sethead = sethead->right;
1847 		}
1848 		return;
1849 	}
1850 
1851 	ttyputbadusage(x_("telltool simulation als vector"));
1852 }
1853 
1854 /****************************** ANNOTATE ******************************/
1855 
1856 /*
1857  * Name: simals_annotate_command
1858  *
1859  * Description:
1860  *   Annotate node information onto corresponding schematic.
1861  */
simals_annotate_command(INTBIG count,CHAR * par[])1862 void simals_annotate_command(INTBIG count, CHAR *par[])
1863 {
1864 	if (count < 1)
1865 	{
1866 		ttyputusage(x_("telltool simulation als annotate [minimum | typical | maximum]"));
1867 		return;
1868 	}
1869 
1870 	if (simals_levelptr == 0)
1871 	{
1872 		ttyputerr(M_("Must start simulator before annotating delay information"));
1873 		return;
1874 	}
1875 
1876 	if (namesamen(par[0], x_("min"), 3) == 0) simals_sdfdelaytype = DELAY_MIN;
1877 		else if (namesamen(par[0], x_("typ"), 3) == 0) simals_sdfdelaytype = DELAY_TYP;
1878 			else if (namesamen(par[0], x_("max"), 3) == 0) simals_sdfdelaytype = DELAY_MAX;
1879 				else
1880 	{
1881 		ttyputbadusage(x_("telltool simulation als annotate"));
1882 		return;
1883 	}
1884 
1885 	simals_sdfannotate(simals_levelptr);
1886 	simals_update_netlist();
1887 	ttyputmsg(M_("Completed annotation of SDF %s delay values"), par[0]);
1888 }
1889 
1890 /*
1891  * Routine to annotate SDF port delay info onto ALS netlist.
1892  */
simals_sdfannotate(CONPTR cellhead)1893 void simals_sdfannotate(CONPTR cellhead)
1894 {
1895 	CHAR    *s1;
1896 	CONPTR  subcell;
1897 	NODEINST *ni;
1898 
1899 	if (stopping(STOPREASONDISPLAY)) return;
1900 	s1 = simals_compute_path_name(cellhead);
1901 
1902 	ni = simals_getcellinstance(cellhead->model_name, s1);
1903 	if (ni != NONODEINST)
1904 	{
1905 		simals_sdfportdelay(cellhead, ni, s1);
1906 	}
1907 
1908 	if (simals_instbuf[simals_instptr[1]] == 'X') return;
1909 
1910 	for (subcell = cellhead->child; subcell; subcell = subcell->next)
1911 		simals_sdfannotate(subcell);
1912 }
1913 
1914 /*
1915  * Routine to get a NODEINST for specified cell instance.
1916  */
simals_getcellinstance(CHAR * celltype,CHAR * instance)1917 NODEINST *simals_getcellinstance(CHAR *celltype, CHAR *instance)
1918 {
1919 	NODEINST *ni;
1920 	NODEPROTO *np;
1921 	VARIABLE *var;
1922 	CHAR *pt, **instlist, *str, tmp[256];
1923 	INTBIG i, j, count = 1;
1924 	Q_UNUSED( celltype );
1925 
1926 	np = getcurcell();
1927 	ni = NONODEINST;
1928 
1929 	/* count number of hierarchy levels */
1930 	(void)esnprintf(tmp, 256, x_("%s"), instance);
1931 	for (pt = tmp; *pt != 0; pt++) if (*pt == '.') count++;
1932 
1933 	/* separate out each hiearchy level - skip first level which is the top */
1934 	instlist = (CHAR **)emalloc(count * (sizeof(CHAR *)), el_tempcluster);
1935 	pt = instance;
1936 	for (i=0, j=0; i<count; i++)
1937 	{
1938 		str = getkeyword(&pt, x_("."));
1939 		if (i >= 2) if (allocstring(&instlist[j++], str, el_tempcluster))
1940 			return(NONODEINST);
1941 		(void)tonextchar(&pt);
1942 	}
1943 	count -= 2;
1944 
1945 	if (count == 0) return(NONODEINST);
1946 
1947 	/* find the NODEINST corresponding to bottom level of hierarchy */
1948 	for(i=0; i<count; i++)
1949 	{
1950 		for (ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1951 		{
1952 			var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key);
1953 			if (var == NOVARIABLE) continue;
1954 			if (namesame((CHAR *)var->addr, instlist[i]) != 0) continue;
1955 			np = ni->proto;
1956 			break;
1957 		}
1958 		if (ni == NONODEINST) break;
1959 		if (np->primindex != 0) break;
1960 	}
1961 
1962 	return(ni);
1963 }
1964 
1965 /*
1966  * Routine to extract SDF port delay information and annotate it to ALS netlist.
1967  */
simals_sdfportdelay(CONPTR cellhead,NODEINST * ni,CHAR * path)1968 void simals_sdfportdelay(CONPTR cellhead, NODEINST *ni, CHAR *path)
1969 {
1970 	VARIABLE *var;
1971 	PORTARCINST *pi;
1972 	INTBIG len, i, j, delay;
1973 	EXPTR exhead;
1974 
1975 	for (exhead = cellhead->exptr; exhead; exhead = exhead->next)
1976 	{
1977 		for (pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1978 		{
1979 			if (namesame(pi->proto->protoname, exhead->node_name) == 0)
1980 			{
1981 				var = getval((INTBIG)pi, VPORTARCINST, VSTRING|VISARRAY, x_("SDF_absolute_port_delay"));
1982 				if (var != NOVARIABLE)
1983 				{
1984 					len = getlength(var);
1985 					for (i=0; i<len; i++)
1986 					{
1987 						if (namesamen(path, ((CHAR **)var->addr)[i], estrlen(path)) == 0)
1988 						{
1989 							for (j=0; j<12; j++)
1990 							{
1991 								delay = simals_getportdelayvalue(((CHAR **)var->addr)[i],
1992 									simals_tnames[j], simals_sdfdelaytype);
1993 								if (delay != -1) exhead->td[j] = delay; else
1994 									exhead->td[j] = 0;
1995 							}
1996 						}
1997 					}
1998 				}
1999 			}
2000 		}
2001 	}
2002 }
2003 
2004 /*
2005  * Routine to extract delay value from delay data string.
2006  */
simals_getportdelayvalue(CHAR * datastring,CHAR * transition,DELAY_TYPES delaytype)2007 INTBIG simals_getportdelayvalue(CHAR *datastring, CHAR *transition, DELAY_TYPES delaytype)
2008 {
2009 	CHAR *pt, *ts, **instlist, *str, tmp[256];
2010 	INTBIG i, count = 1;
2011 
2012 	/* count number of parts in data string */
2013 	(void)esnprintf(tmp, 256, x_("%s"), datastring);
2014 	for (pt = tmp; *pt != 0; pt++) if (*pt == ' ') count++;
2015 
2016 	/* split data string into separate pieces */
2017 	instlist = (CHAR **)emalloc(count * (sizeof(CHAR *)), el_tempcluster);
2018 	pt = datastring;
2019 	for (i=0; i<count; i++)
2020 	{
2021 		str = getkeyword(&pt, x_(" "));
2022 		if (allocstring(&instlist[i], str, el_tempcluster)) return(-1);
2023 	}
2024 
2025 	/* get piece that corresponds to specified transition */
2026 	for (i=0; i<count; i++)
2027 	{
2028 		if (namesamen(instlist[i], transition, estrlen(transition)) == 0)
2029 		{
2030 			if (allocstring(&ts, instlist[i], el_tempcluster)) return(-1);
2031 			return(simals_getdval(ts, delaytype));
2032 		}
2033 	}
2034 
2035 	return(-1);
2036 }
2037 
2038 /*
2039  * Routine to get a delay value string from a transition string.
2040  *     if tstring is '01(111:222:333)' and delaytype is DELAY_TYP return 222
2041  */
simals_getdval(CHAR * tstring,DELAY_TYPES delaytype)2042 INTBIG simals_getdval(CHAR *tstring, DELAY_TYPES delaytype)
2043 {
2044 	CHAR *pt, *str, *bs, ts[256], *t1, *t2, *t3;
2045 	INTBIG i, start = 0, stop = 0;
2046 
2047 	bs = str = (CHAR *)emalloc((estrlen(tstring)+1) * SIZEOFCHAR, el_tempcluster);
2048 	for (pt = tstring; *pt != 0; pt++)
2049 	{
2050 		if (*pt == ')') stop++;
2051 		if (start && !stop) *str++ = *pt;
2052 		if (*pt == '(') start++;
2053 	}
2054 	*str = 0;
2055 
2056 	(void)esnprintf(ts, 256, x_("%s"), bs);
2057 
2058 	/* delay string is not a triple, only one delay value implies typical */
2059 	if (estrstr(ts, x_(":")) == NULL)
2060 	{
2061 		if (delaytype == DELAY_TYP) return(eatoi(ts));
2062 		return(-1);
2063 	}
2064 
2065 	pt = ts;
2066 	for (i=0; i<3; i++)
2067 	{
2068 		str = getkeyword(&pt, x_(":"));
2069 		if (i == 0) if (allocstring(&t1, str, el_tempcluster)) return(-1);
2070 		if (i == 1) if (allocstring(&t2, str, el_tempcluster)) return(-1);
2071 		if (i == 2) if (allocstring(&t3, str, el_tempcluster)) return(-1);
2072 		(void)tonextchar(&pt);
2073 	}
2074 
2075 	switch (delaytype)
2076 	{
2077 		case DELAY_MIN:
2078 			return(eatoi(t1));
2079 		case DELAY_TYP:
2080 			return(eatoi(t2));
2081 		case DELAY_MAX:
2082 			return(eatoi(t3));
2083 		default:
2084 			return(-1);
2085 	}
2086 }
2087 
2088 /****************************** ORDER ******************************/
2089 
2090 /*
2091  * Name: simals_order_command
2092  *
2093  * Description:
2094  *   Save/restore signal trace order for waveform display.
2095  */
simals_order_command(INTBIG count,CHAR * par[])2096 void simals_order_command(INTBIG count, CHAR *par[])
2097 {
2098 	if (count < 1)
2099 	{
2100 		ttyputusage(x_("telltool simulation als order [save | restore]"));
2101 		return;
2102 	}
2103 
2104 	if (namesamen(par[0], x_("sav"), 3) == 0) simals_order_save();
2105 		else if (namesamen(par[0], x_("res"), 3) == 0)
2106 	{
2107 		if (count != 2)
2108 		{
2109 			ttyputusage(x_("telltool simulation als order restore OPTION"));
2110 			return;
2111 		}
2112 		simals_order_restore(par[1]);
2113 	} else
2114 	{
2115 		ttyputbadusage(x_("telltool simulation als order"));
2116 		return;
2117 	}
2118 }
2119 
simals_order_save(void)2120 void simals_order_save(void)
2121 {
2122 	INTBIG tr;
2123 	BOOLEAN first = FALSE;
2124 	CHAR str[256], *ts;
2125 	NODEPROTO *curcell;
2126 	REGISTER void *infstr = 0;
2127 
2128 	sim_window_inittraceloop();
2129 	while ((tr = sim_window_nexttraceloop()) != 0)
2130 	{
2131 		if (!first) infstr = initinfstr();
2132 		(void)esnprintf(str, 256, x_("%s:"), sim_window_gettracename(tr));
2133 		addstringtoinfstr(infstr, str);
2134 		first = TRUE;
2135 	}
2136 
2137 	if (first)
2138 	{
2139 		ts = returninfstr(infstr);
2140 		ts[(estrlen(ts)-1)] = 0;  /* chop off trailing ":" */
2141 
2142 		/* save on current cell */
2143 		curcell = getcurcell();
2144 		if (curcell != NULL) (void)setval((INTBIG)curcell, VNODEPROTO,
2145 			x_("SIM_als_trace_order"), (INTBIG)ts, VSTRING);
2146 	}
2147 }
2148 
simals_order_restore(CHAR * list)2149 void simals_order_restore(CHAR *list)
2150 {
2151 	INTBIG tc = 0, i, found, lines, thispos, pos, fromlib = 0;
2152 	INTBIG tr, trl;
2153 	NODEPTR node;
2154 	VARIABLE *var;
2155 	NODEPROTO *curcell;
2156 	CHAR *pt, *str, **tl, tmp[256];
2157 
2158 	if (namesame(list, x_("fromlib")) == 0)
2159 	{
2160 		curcell = getcurcell();
2161 		if (curcell != NONODEPROTO)
2162 		{
2163 			var = getval((INTBIG)curcell, VNODEPROTO, VSTRING, x_("SIM_als_trace_order"));
2164 			if (var != NOVARIABLE)
2165 			{
2166 				(void)esnprintf(tmp, 256, x_("%s"), (CHAR *)var->addr);
2167 				fromlib++;
2168 			}
2169 			else return;
2170 		}
2171 		else return;
2172 	}
2173 	else (void)esnprintf(tmp, 256, x_("%s"), list);
2174 
2175 	/* count number of traces and fill trace list array */
2176 	for (pt = tmp; *pt != 0; pt++) if (*pt == ':') tc++;
2177 	if (tc == 0) return;
2178 	tc++;
2179 	tl = (CHAR **)emalloc(tc * (sizeof(CHAR *)), el_tempcluster);
2180 	pt = tmp;
2181 	for (i=0; i<tc; i++)
2182 	{
2183 		str = getkeyword(&pt, x_(":"));
2184 		(void)allocstring(&tl[i], str, el_tempcluster);
2185 		(void)tonextchar(&pt);
2186 	}
2187 
2188 	/* delete traces not in restored list */
2189 	sim_window_cleartracehighlight();
2190 	sim_window_inittraceloop();
2191 	while ((tr = sim_window_nexttraceloop()) != 0)
2192 	{
2193 		found = 0;
2194 		for (i=0; i<tc; i++)
2195 		{
2196 			if (namesame(sim_window_gettracename(tr), tl[i]) == 0) found++;
2197 		}
2198 		if (!found)
2199 		{
2200 			thispos = sim_window_gettraceframe(tr);
2201 			sim_window_inittraceloop2();
2202 			for(;;)
2203 			{
2204 				trl = sim_window_nexttraceloop2();
2205 				if (trl == 0) break;
2206 				pos = sim_window_gettraceframe(trl);
2207 				if (pos > thispos) sim_window_settraceframe(trl, pos-1);
2208 			}
2209 			lines = sim_window_getnumframes();
2210 			if (lines > 1) sim_window_setnumframes(lines-1);
2211 
2212 			/* remove from the simulator's list */
2213 			for(i=0; i<simals_levelptr->num_chn; i++)
2214 			{
2215 				node = simals_levelptr->display_page[i+1].nodeptr;
2216 				if (node == 0) continue;
2217 				if (simals_levelptr->display_page[i+1].displayptr == tr)
2218 				{
2219 					simals_levelptr->display_page[i+1].displayptr = 0;
2220 					break;
2221 				}
2222 			}
2223 
2224 			/* kill trace, redraw */
2225 			sim_window_killtrace(tr);
2226 			sim_window_setnumframes(sim_window_getnumframes()-1);
2227 		}
2228 	}
2229 
2230 	/* order the traces */
2231 	sim_window_setnumframes(tc);
2232 	sim_window_inittraceloop();
2233 	while ((tr = sim_window_nexttraceloop()) != 0)
2234 	{
2235 		for (i=0; i<tc; i++)
2236 		   if (namesame(tl[i], sim_window_gettracename(tr)) == 0) break;
2237 		if (fromlib) sim_window_settraceframe(tr, tc-i-1); else  /* order from library save is bottom to top */
2238 			sim_window_settraceframe(tr, i);
2239 	}
2240 
2241 	sim_window_redraw();
2242 }
2243 
2244 /*
2245  * Update the flattened netlist with the annotated delay values.
2246  */
simals_update_netlist(void)2247 void simals_update_netlist(void)
2248 {
2249 	MODPTR primhead;
2250 	CONPTR cellhead;
2251 	ROWPTR rowhead;
2252 	EXPTR exhead;
2253 	INTBIG delay, max_delay;
2254 
2255 	for (primhead = simals_primroot; primhead; primhead = primhead->next)
2256 	{
2257 		switch(primhead->type)
2258 		{
2259 			case 'F':
2260 				break;
2261 
2262 			case 'G':
2263 				/* cycle through all entries in table */
2264 				for (rowhead = (ROWPTR)primhead->ptr; rowhead; rowhead=rowhead->next)
2265 				{
2266 					/* check for valid delay transition name for current entry */
2267 					if (estrcmp(rowhead->delay, x_("XX")))
2268 					{
2269 						/* TESTING - get the max delay value of all input ports matching transition */
2270 						cellhead = simals_find_level(simals_parent_level(primhead->level));
2271 						max_delay = 0;
2272 						for (exhead = cellhead->exptr; exhead; exhead = exhead->next)
2273 						{
2274 							delay = exhead->td[simals_get_tdindex(rowhead->delay)];
2275 							if (max_delay < delay) max_delay = delay;
2276 						}
2277 						if (max_delay != 0)
2278 						{
2279 							rowhead->abs = (float)max_delay * 1.0e-12f;
2280 						}
2281 						ttyputmsg(M_("*** DEBUG *** gate: %s, level: %s, delay: %g(%s)"),
2282 							primhead->name, primhead->level, (float)max_delay * 1.0e-12, rowhead->delay);
2283 						ttyputmsg(M_("  Timing: D=%g, L=%g, E=%g, R=%g, A=%g"),
2284 							rowhead->delta, rowhead->linear, rowhead->exp, rowhead->random, rowhead->abs);
2285 						simals_print_in_entry(rowhead);
2286 						simals_print_out_entry(rowhead);
2287 					}
2288 				}
2289 				break;
2290 
2291 			default:
2292 				ttyputerr(M_("Illegal primitive type '%c', database is bad"), primhead->type);
2293 				break;
2294 		}
2295 	}
2296 }
2297 
2298 /*
2299  * Return index for transition delays given text name.
2300  */
simals_get_tdindex(CHAR * name)2301 INTBIG simals_get_tdindex(CHAR *name)
2302 {
2303 	INTBIG i;
2304 
2305 	for (i=0; i<12; i++)
2306 	{
2307 		if (!estrcmp(simals_tnames[i], name)) return(i);
2308 	}
2309 	return(0);  /* return '01' index */
2310 }
2311 
2312 /*
2313  * Return the parent level of the given child.
2314  *     if .TOP.NODE3.G1 is child, .TOP.NODE3 is parent
2315  */
simals_parent_level(CHAR * child)2316 CHAR *simals_parent_level(CHAR *child)
2317 {
2318 	CHAR tmp[256], *pt, *str, **instlist;
2319 	INTBIG i, count = 1;
2320 	REGISTER void *infstr;
2321 
2322 	(void)esnprintf(tmp, 256, x_("%s"), child);
2323 	for (pt = tmp; *pt != 0; pt++) if (*pt == '.') count++;
2324 
2325 	/* separate out each hiearchy level */
2326 	instlist = (CHAR **)emalloc(count * (sizeof(CHAR *)), el_tempcluster);
2327 	pt = child;
2328 	for (i=0; i<count; i++)
2329 	{
2330 		str = getkeyword(&pt, x_("."));
2331 		(void)allocstring(&instlist[i], str, el_tempcluster);
2332 		(void)tonextchar(&pt);
2333 	}
2334 
2335 	/* create the parent level name */
2336 	infstr = initinfstr();
2337 	for (i=0; i<count-1; i++)
2338 	{
2339 		addstringtoinfstr(infstr, instlist[i]);
2340 		if (i != (count - 2)) addstringtoinfstr(infstr, x_("."));
2341 	}
2342 
2343 	return(returninfstr(infstr));
2344 }
2345 
2346 #endif  /* SIMTOOL - at top */
2347