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