1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: simalsgraph.c
6 * Asynchronous Logic Simulator graphics interface
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 "usr.h"
40 #include "network.h"
41 #include "edialogs.h"
42
43 static INTBIG sim_window_iter;
44 static BOOLEAN sim_als_wantweak = FALSE, sim_als_wantstrong = FALSE, sim_als_wantfull = FALSE;
45
46 /* prototypes for local routines */
47 static BOOLEAN simals_topofsignals(CHAR**);
48 static CHAR *simals_nextsignals(void);
49 static INTBIG simals_count_channels(CONPTR);
50 static void simals_helpwindow(BOOLEAN waveform);
51 static int simals_sortbusnames(const void *e1, const void *e2);
52
simals_topofsignals(CHAR ** c)53 BOOLEAN simals_topofsignals(CHAR **c)
54 {
55 Q_UNUSED( c );
56 sim_window_iter = 0;
57 return(TRUE);
58 }
59
simals_nextsignals(void)60 CHAR *simals_nextsignals(void)
61 {
62 CHAR *nextname;
63
64 for(; ; sim_window_iter++)
65 {
66 if (sim_window_iter >= simals_levelptr->num_chn) return(0);
67 if (simals_levelptr->display_page[sim_window_iter+1].nodeptr == 0) continue;
68 if (simals_levelptr->display_page[sim_window_iter+1].displayptr == 0) break;
69 }
70 nextname = simals_levelptr->display_page[sim_window_iter+1].name;
71 sim_window_iter++;
72 return(nextname);
73 }
74
75 static COMCOMP sim_window_pickalstrace = {NOKEYWORD, simals_topofsignals,
76 simals_nextsignals, NOPARAMS, 0, x_(" \t"), N_("pick a signal to display"), x_("")};
77
78 /*
79 * Routine to start ALS simulation of cell "np".
80 */
simals_startsimulation(NODEPROTO * np)81 BOOLEAN simals_startsimulation(NODEPROTO *np)
82 {
83 extern TOOL *vhdl_tool;
84 REGISTER INTBIG error;
85
86 /* initialize memory */
87 simals_init();
88
89 /* demand an ALS netlist */
90 error = asktool(vhdl_tool, x_("want-netlist-input"), (INTBIG)np, sim_filetypeals);
91 if (error != 0) return(TRUE);
92
93 /* read netlist */
94 simals_erase_model();
95 if (simals_read_net_desc(np)) return(TRUE);
96 if (simals_flatten_network()) return(TRUE);
97
98 if (simals_title != 0)
99 {
100 efree((CHAR *)simals_title);
101 simals_title = 0;
102 }
103
104 /* initialize display */
105 simals_init_display();
106 return(FALSE);
107 }
108
109 /*
110 * The character handler for the waveform window of ALS simulation
111 */
simals_charhandlerwave(WINDOWPART * w,INTSML chr,INTBIG special)112 BOOLEAN simals_charhandlerwave(WINDOWPART *w, INTSML chr, INTBIG special)
113 {
114 REGISTER INTBIG i, j, traces, pos, thispos, strength, *tracelist,
115 tr, trl, nexttr, prevtr, highsig, *highsigs, numbits, bitoffset;
116 INTBIG state, *theBits;
117 CHAR *par[30], *name;
118 NODEPTR node, nodehead;
119 NODEPROTO *np;
120 double endtime;
121 LINKPTR sethead;
122
123 ttynewcommand();
124
125 /* special characters are not handled here */
126 if (special != 0)
127 return(us_charhandler(w, chr, special));
128
129 /* can always preserve snapshot */
130 if (chr == 'p')
131 {
132 sim_window_savegraph();
133 sim_als_wantweak = sim_als_wantstrong = sim_als_wantfull = FALSE;
134 return(FALSE);
135 }
136
137 /* can always do help */
138 if (chr == '?')
139 {
140 simals_helpwindow(TRUE);
141 sim_als_wantweak = sim_als_wantstrong = sim_als_wantfull = FALSE;
142 return(FALSE);
143 }
144
145 /* if not simulating, don't handle any simulation commands */
146 if (sim_window_isactive(&np) == 0)
147 return(us_charhandler(w, chr, special));
148
149 numbits = 0;
150 switch (chr)
151 {
152 /* update display */
153 case 'u':
154 endtime = simals_initialize_simulator(TRUE);
155 if ((sim_window_state&ADVANCETIME) != 0) sim_window_setmaincursor(endtime);
156 return(FALSE);
157
158 /* convert busses */
159 case 'b':
160 (void)sim_window_buscommand();
161 return(FALSE);
162
163 /* add trace */
164 case 'a':
165 i = ttygetparam(_("Signal to add"), &sim_window_pickalstrace, 3, par);
166 if (i == 0) return(FALSE);
167
168 /* find the signal */
169 for(i=0; i<simals_levelptr->num_chn; i++)
170 {
171 node = simals_levelptr->display_page[i+1].nodeptr;
172 if (node == 0) continue;
173 if (simals_levelptr->display_page[i+1].displayptr != 0) continue;
174 name = simals_levelptr->display_page[i+1].name;
175 if (namesame(name, par[0]) == 0) break;
176 }
177 if (i >= simals_levelptr->num_chn) return(FALSE);
178
179 /* ready to add: remove highlighting */
180 sim_window_cleartracehighlight();
181
182 /* count the number of traces */
183 sim_window_inittraceloop();
184 for(traces=0; ; traces++) if (sim_window_nexttraceloop() == 0) break;
185
186 /* if there are no traces, put new trace on line zero */
187 if (traces == 0) j = 0; else
188 {
189 /* other traces exist, make a new line in the plot */
190 j = sim_window_getnumframes();
191 sim_window_setnumframes(j+1);
192 }
193
194 /* create a new trace in the last slot */
195 tr = sim_window_newtrace(j, simals_levelptr->display_page[i+1].name,
196 (INTBIG)simals_levelptr->display_page[i+1].nodeptr);
197 simals_levelptr->display_page[i+1].displayptr = tr;
198 simals_fill_display_arrays();
199 sim_window_redraw();
200 sim_window_addhighlighttrace(tr);
201 sim_als_wantweak = sim_als_wantstrong = sim_als_wantfull = FALSE;
202 return(FALSE);
203
204 /* handle weak and strong prefixes */
205 case 'w':
206 if (sim_als_wantweak || sim_als_wantstrong) ttybeep(SOUNDBEEP, FALSE);
207 sim_als_wantweak = TRUE;
208 return(FALSE);
209 case 's':
210 if (sim_als_wantweak || sim_als_wantstrong) ttybeep(SOUNDBEEP, FALSE);
211 sim_als_wantstrong = TRUE;
212 return(FALSE);
213 case 'f':
214 if (sim_als_wantfull) ttybeep(SOUNDBEEP, FALSE);
215 sim_als_wantfull = TRUE;
216 return(FALSE);
217
218 /* different flavors of low values */
219 case '0':
220 case 'l':
221 state = LOGIC_LOW; strength = GATE_STRENGTH;
222 if (sim_als_wantweak) strength = NODE_STRENGTH; else
223 if (sim_als_wantstrong) strength = VDD_STRENGTH;
224 break;
225
226 /* different flavors of high values */
227 case '1':
228 case 'h':
229 state = LOGIC_HIGH; strength = GATE_STRENGTH;
230 if (sim_als_wantweak) strength = NODE_STRENGTH; else
231 if (sim_als_wantstrong) strength = VDD_STRENGTH;
232 break;
233
234 /* different flavors of undefined values */
235 case 'x':
236 state = LOGIC_X; strength = GATE_STRENGTH;
237 if (sim_als_wantweak) strength = NODE_STRENGTH; else
238 if (sim_als_wantstrong) strength = VDD_STRENGTH;
239 break;
240
241 /* different flavors of wide numeric values */
242 case 'v':
243 numbits = sim_window_getwidevalue(&theBits);
244 if (numbits < 0) return(FALSE);
245 strength = GATE_STRENGTH;
246 if (sim_als_wantweak) strength = NODE_STRENGTH; else
247 if (sim_als_wantstrong) strength = VDD_STRENGTH;
248 break;
249
250 /* signal tracing */
251 case 't':
252 if (sim_als_wantfull)
253 {
254 simals_trace_all_nodes = TRUE;
255 (void)simals_initialize_simulator(TRUE);
256 simals_trace_all_nodes = FALSE;
257 } else
258 {
259 highsigs = sim_window_gethighlighttraces();
260 if (highsigs[0] == 0)
261 {
262 ttyputerr(_("Select signal names first"));
263 return(FALSE);
264 }
265 for(i=0; highsigs[i] != 0; i++)
266 ((NODEPTR)sim_window_gettracedata(highsigs[i]))->tracenode = TRUE;
267 (void)simals_initialize_simulator(TRUE);
268 for(i=0; highsigs[i] != 0; i++)
269 ((NODEPTR)sim_window_gettracedata(highsigs[i]))->tracenode = FALSE;
270 }
271 return(FALSE);
272
273 /* signal clock setting, info, erasing, removing (all handled later) */
274 case 'c':
275 case 'i':
276 case 'e':
277 case 'r':
278 case DELETEKEY:
279 strength = OFF_STRENGTH;
280 break;
281
282 default:
283 sim_als_wantweak = sim_als_wantstrong = sim_als_wantfull = FALSE;
284 return(us_charhandler(w, chr, special));
285 }
286 sim_als_wantweak = sim_als_wantstrong = sim_als_wantfull = FALSE;
287
288 /* the following commands demand a current trace...get it */
289 highsigs = sim_window_gethighlighttraces();
290 if (highsigs[0] == 0)
291 {
292 ttyputerr(_("Select a signal name first"));
293 return(FALSE);
294 }
295 if (chr == 'r' || chr == DELETEKEY) /* remove trace */
296 {
297 sim_window_cleartracehighlight();
298
299 /* delete them */
300 nexttr = prevtr = 0;
301 for(j=0; highsigs[j] != 0; j++)
302 {
303 highsig = highsigs[j];
304 thispos = sim_window_gettraceframe(highsig);
305 sim_window_inittraceloop();
306 nexttr = prevtr = 0;
307 for(;;)
308 {
309 trl = sim_window_nexttraceloop();
310 if (trl == 0) break;
311 pos = sim_window_gettraceframe(trl);
312 if (pos > thispos)
313 {
314 pos--;
315 if (pos == thispos) nexttr = trl;
316 sim_window_settraceframe(trl, pos);
317 } else if (pos == thispos-1) prevtr = trl;
318 }
319
320 /* remove from the simulator's list */
321 for(i=0; i<simals_levelptr->num_chn; i++)
322 {
323 node = simals_levelptr->display_page[i+1].nodeptr;
324 if (node == 0) continue;
325 if (simals_levelptr->display_page[i+1].displayptr == highsig)
326 {
327 simals_levelptr->display_page[i+1].displayptr = 0;
328 break;
329 }
330 }
331
332 /* kill trace */
333 sim_window_killtrace(highsig);
334 }
335 if (nexttr != 0) sim_window_addhighlighttrace(nexttr); else
336 if (prevtr != 0) sim_window_addhighlighttrace(prevtr);
337 sim_window_redraw();
338 return(FALSE);
339 }
340
341 if (highsigs[1] != 0)
342 {
343 ttyputerr(_("Select just one signal name first"));
344 return(FALSE);
345 }
346 highsig = highsigs[0];
347
348 if (chr == 'c') /* set clock waveform */
349 {
350 tracelist = sim_window_getbustraces(highsig);
351 if (tracelist != 0 && tracelist[0] != 0)
352 {
353 ttyputerr(_("Cannot set clock waveform on a bus signal"));
354 return(FALSE);
355 }
356 par[0] = sim_window_gettracename(highsig);
357 simals_clock_command(1, par);
358 return(FALSE);
359 }
360 if (chr == 'i') /* print signal info */
361 {
362 par[0] = x_("state");
363 par[1] = sim_window_gettracename(highsig);
364 simals_print_command(2, par);
365 return(FALSE);
366 }
367 if (chr == 'e') /* clear signal vectors */
368 {
369 tracelist = sim_window_getbustraces(highsig);
370 if (tracelist != 0 && tracelist[0] != 0)
371 {
372 for(i=0; tracelist[i] != 0; i++)
373 {
374 par[0] = x_("delete");
375 par[1] = sim_window_gettracename(tracelist[i]);
376 par[2] = x_("all");
377 simals_vector_command(3, par);
378 }
379 } else
380 {
381 par[0] = x_("delete");
382 par[1] = sim_window_gettracename(highsig);
383 par[2] = x_("all");
384 simals_vector_command(3, par);
385 }
386 return(FALSE);
387 }
388
389 /* handle setting of values on signals */
390 if (chr == 'v')
391 {
392 tracelist = sim_window_getbustraces(highsig);
393 if (tracelist == 0 || tracelist[0] == 0)
394 {
395 ttyputerr(_("Select a bus signal before setting numeric values on it"));
396 return(FALSE);
397 }
398 for(i=0; tracelist[i] != 0; i++) ;
399 bitoffset = numbits - i;
400 for(i=0; tracelist[i] != 0; i++)
401 {
402 nodehead = simals_find_node(sim_window_gettracename(tracelist[i]));
403 if (! nodehead) return(FALSE);
404 sethead = simals_alloc_link_mem();
405 if (sethead == 0) return(FALSE);
406 sethead->type = 'N';
407 sethead->ptr = (CHAR *)nodehead;
408 if (i+bitoffset < 0 || theBits[i+bitoffset] == 0) sethead->state = LOGIC_LOW; else
409 sethead->state = LOGIC_HIGH;
410 sethead->strength = (INTSML)strength;
411 sethead->priority = 2;
412 sethead->time = sim_window_getmaincursor();
413 sethead->right = 0;
414 simals_insert_set_list(sethead);
415 }
416 } else
417 {
418 nodehead = simals_find_node(sim_window_gettracename(highsig));
419 if (! nodehead) return(FALSE);
420 sethead = simals_alloc_link_mem();
421 if (sethead == 0) return(FALSE);
422 sethead->type = 'N';
423 sethead->ptr = (CHAR *)nodehead;
424 sethead->state = state;
425 sethead->strength = (INTSML)strength;
426 sethead->priority = 2;
427 sethead->time = sim_window_getmaincursor();
428 sethead->right = 0;
429 simals_insert_set_list(sethead);
430 }
431
432 endtime = simals_initialize_simulator(FALSE);
433 if ((sim_window_state&ADVANCETIME) != 0) sim_window_setmaincursor(endtime);
434 return(FALSE);
435 }
436
437 /*
438 * The character handler for the schematic/layout window of ALS simulation
439 */
simals_charhandlerschem(WINDOWPART * w,INTSML chr,INTBIG special)440 BOOLEAN simals_charhandlerschem(WINDOWPART *w, INTSML chr, INTBIG special)
441 {
442 INTBIG state, i, highsigcount, *highsiglist;
443 REGISTER INTSML strength;
444 REGISTER NETWORK *net, **netlist;
445 CHAR *par[30], *pt;
446 double endtime;
447 NODEPTR nodehead;
448 LINKPTR sethead;
449
450 ttynewcommand();
451
452 /* special characters are not handled here */
453 if (special != 0)
454 return(us_charhandler(w, chr, special));
455
456 switch (chr)
457 {
458 case '?':
459 simals_helpwindow(FALSE);
460 sim_als_wantweak = sim_als_wantstrong = FALSE;
461 return(FALSE);
462 case 'u':
463 endtime = simals_initialize_simulator(TRUE);
464 if ((sim_window_state&ADVANCETIME) != 0) sim_window_setmaincursor(endtime);
465 return(FALSE);
466 case 'w':
467 if (sim_als_wantweak || sim_als_wantstrong) ttybeep(SOUNDBEEP, FALSE);
468 sim_als_wantweak = TRUE;
469 return(FALSE);
470 case 's':
471 if (sim_als_wantweak || sim_als_wantstrong) ttybeep(SOUNDBEEP, FALSE);
472 sim_als_wantstrong = TRUE;
473 return(FALSE);
474 case '0':
475 case 'l':
476 state = LOGIC_LOW; strength = GATE_STRENGTH;
477 if (sim_als_wantweak) strength = NODE_STRENGTH; else
478 if (sim_als_wantstrong) strength = VDD_STRENGTH;
479 break;
480 case '1':
481 case 'h':
482 state = LOGIC_HIGH; strength = GATE_STRENGTH;
483 if (sim_als_wantweak) strength = NODE_STRENGTH; else
484 if (sim_als_wantstrong) strength = VDD_STRENGTH;
485 break;
486 case 'x':
487 state = LOGIC_X; strength = GATE_STRENGTH;
488 if (sim_als_wantweak) strength = NODE_STRENGTH; else
489 if (sim_als_wantstrong) strength = VDD_STRENGTH;
490 break;
491 case 'c':
492 case 'i':
493 case 't':
494 case 'e':
495 strength = OFF_STRENGTH;
496 break;
497 default:
498 sim_als_wantweak = sim_als_wantstrong = FALSE;
499 return(us_charhandler(w, chr, special));
500 }
501 sim_als_wantweak = sim_als_wantstrong = FALSE;
502
503 /* find the net in the waveform window */
504 netlist = net_gethighlightednets(FALSE);
505 net = netlist[0];
506 if (net == NONETWORK) return(FALSE);
507 if (net->namecount > 0) pt = networkname(net, 0); else
508 pt = describenetwork(net);
509 highsiglist = sim_window_findtrace(pt, &highsigcount);
510 if (highsigcount == 0)
511 {
512 ttyputerr(_("Cannot find network %s in simulation"), pt);
513 return(FALSE);
514 }
515 sim_window_cleartracehighlight();
516 for(i=0; i<highsigcount; i++)
517 sim_window_addhighlighttrace(highsiglist[i]);
518
519 if (chr == 'c')
520 {
521 par[0] = sim_window_gettracename(highsiglist[0]);
522 simals_clock_command(1, par);
523 return(FALSE);
524 }
525 if (chr == 'i')
526 {
527 par[0] = x_("state");
528 par[1] = sim_window_gettracename(highsiglist[0]);
529 simals_print_command(2, par);
530 return(FALSE);
531 }
532 if (chr == 't')
533 {
534 nodehead = (NODEPTR)sim_window_gettracedata(highsiglist[0]);
535 nodehead->tracenode = TRUE;
536 (void)simals_initialize_simulator(TRUE);
537 nodehead->tracenode = FALSE;
538 return(FALSE);
539 }
540 if (chr == 'e')
541 {
542 par[0] = x_("delete");
543 par[1] = sim_window_gettracename(highsiglist[0]);
544 par[2] = x_("all");
545 simals_vector_command(3, par);
546 simals_fill_display_arrays();
547 sim_window_redraw();
548 return(FALSE);
549 }
550
551 nodehead = simals_find_node(sim_window_gettracename(highsiglist[0]));
552 if (nodehead == 0) return(FALSE);
553
554 sethead = simals_alloc_link_mem();
555 if (sethead == 0) return(FALSE);
556 sethead->type = 'N';
557 sethead->ptr = (CHAR *)nodehead;
558 sethead->state = state;
559 sethead->strength = strength;
560 sethead->priority = 2;
561 sethead->time = sim_window_getmaincursor();
562 sethead->right = 0;
563 simals_insert_set_list(sethead);
564 endtime = simals_initialize_simulator(FALSE);
565
566 if ((sim_window_state&ADVANCETIME) != 0) sim_window_setmaincursor(endtime);
567 return(FALSE);
568 }
569
simals_helpwindow(BOOLEAN waveform)570 void simals_helpwindow(BOOLEAN waveform)
571 {
572 REGISTER INTBIG active;
573 NODEPROTO *np;
574
575 active = sim_window_isactive(&np);
576 if (active == 0)
577 {
578 ttyputmsg(_("There is no current simulation"));
579 return;
580 }
581
582 if (waveform)
583 ttyputmsg(_("These keys may be typed in the ALS Waveform window:")); else
584 ttyputmsg(_("These keys may be typed in the ALS Schematic window:"));
585 ttyputinstruction(x_(";,0"), 4, _("Set signal low (normal strength)"));
586 ttyputinstruction(x_("wl"), 4, _("Set signal low (weak strength)"));
587 ttyputinstruction(x_("sl"), 4, _("Set signal low (strong strength)"));
588 ttyputinstruction(x_("h,1"), 4, _("Set signal high (normal strength)"));
589 ttyputinstruction(x_("wh"), 4, _("Set signal high (weak strength)"));
590 ttyputinstruction(x_("sh"), 4, _("Set signal high (strong strength)"));
591 ttyputinstruction(x_(" x"), 4, _("Set signal undefined (normal strength)"));
592 ttyputinstruction(x_("wx"), 4, _("Set signal undefined (weak strength)"));
593 ttyputinstruction(x_("sx"), 4, _("Set signal undefined (strong strength)"));
594 if (waveform)
595 {
596 ttyputinstruction(x_(" v"), 4, _("Set bus to wide value (normal strength)"));
597 ttyputinstruction(x_("wv"), 4, _("Set bus to wide value (weak strength)"));
598 ttyputinstruction(x_("sv"), 4, _("Set bus to wide value (strong strength)"));
599 }
600 ttyputinstruction(x_(" c"), 4, _("Set signal to be a clock"));
601 ttyputinstruction(x_(" e"), 4, _("Delete all vectors on signal"));
602 ttyputinstruction(x_(" i"), 4, _("Print information about signal"));
603 ttyputinstruction(x_(" t"), 4, _("Trace events on signal(s)"));
604 ttyputinstruction(x_(" u"), 4, _("Update display (resimulate)"));
605
606 if (waveform)
607 {
608 ttyputinstruction(x_(" a"), 4, _("Add signal to simulation window"));
609 ttyputinstruction(x_(" r"), 4, _("Remove signal from the window"));
610 ttyputinstruction(x_(" b"), 4, _("Combine selected signals into a bus"));
611 ttyputinstruction(x_("ft"), 4, _("Full Trace of all events"));
612 ttyputinstruction(x_(" p"), 4, _("Preserve snapshot of simulation window in database"));
613 }
614 }
615
616 /*
617 * Name: simals_count_channels
618 *
619 * Description:
620 * This function returns the number of exported channels in a given level.
621 *
622 * Calling Argument:
623 * level_pointer : pointer to a level
624 */
simals_count_channels(CONPTR level_pointer)625 INTBIG simals_count_channels(CONPTR level_pointer)
626 {
627 INTBIG count=0;
628 EXPTR exhead;
629
630 for (exhead = level_pointer->exptr; exhead; exhead = exhead->next) count++;
631 return(count);
632 }
633
634 /*
635 * Name: simals_set_current_level
636 *
637 * Description:
638 * This procedure is used to initialize the display channels to the current
639 * level of the database hierarchy. Returns true on error.
640 */
simals_set_current_level(void)641 BOOLEAN simals_set_current_level(void)
642 {
643 INTBIG i, j, k, buscount, oldsigcount, chn, bussignals[MAXSIMWINDOWBUSWIDTH],
644 len, olen;
645 CHAR **oldsignames;
646 REGISTER VARIABLE *var;
647 NODEPTR nodehead;
648 NODE *node, *subnode;
649 EXPTR exhead;
650 CHAR *name, *subname, *pt, *opt, *start, save;
651 void *sa;
652 NODEPROTO *np;
653 REGISTER void *infstr;
654
655 for (nodehead = simals_noderoot; nodehead; nodehead = nodehead->next)
656 nodehead->plot_node = 0;
657
658 if (simals_levelptr->display_page)
659 {
660 exhead = simals_levelptr->exptr;
661 for (i = 1; i <= simals_levelptr->num_chn; i++)
662 {
663 if (exhead)
664 {
665 exhead->nodeptr->plot_node = 1;
666 exhead = exhead->next;
667 }
668 }
669 } else
670 {
671 simals_levelptr->num_chn = simals_count_channels(simals_levelptr);
672 chn = simals_levelptr->num_chn + 1;
673 simals_levelptr->display_page = (CHNPTR)simals_alloc_mem((INTBIG)(chn * sizeof(CHANNEL)));
674 if (simals_levelptr->display_page == 0) return(TRUE);
675
676 exhead = simals_levelptr->exptr;
677 for (i = 1; i < chn; i++)
678 {
679 if (exhead)
680 {
681 name = exhead->node_name;
682 simals_levelptr->display_page[i].nodeptr = exhead->nodeptr;
683 exhead->nodeptr->plot_node = 1;
684 exhead = exhead->next;
685 } else
686 {
687 name = x_("");
688 simals_levelptr->display_page[i].nodeptr = 0;
689 }
690 (void)allocstring(&simals_levelptr->display_page[i].name, name, sim_tool->cluster);
691
692 /* convert names to proper bracketed form */
693 name = simals_levelptr->display_page[i].name;
694 len = estrlen(name) - 1;
695 if (name[len] == '_')
696 {
697 olen = len;
698 while (len > 0 && isdigit(name[len-1])) len--;
699 if (len != olen && name[len-1] == '_')
700 {
701 /* found the form "name_INDEX_" */
702 name[len-1] = '[';
703 name[olen] = ']';
704 }
705 }
706 }
707 }
708
709 /* prepare the simulation window */
710 oldsigcount = 0;
711 i = sim_window_isactive(&np);
712 if ((i&SIMWINDOWWAVEFORM) == 0)
713 {
714 if (i != 0 && np != simals_mainproto)
715 {
716 /* stop simulation of cell "np" */
717 sim_window_stopsimulation();
718 }
719
720 /* no simulation running: start it up */
721 if (simals_levelptr->num_chn <= 0) return(TRUE);
722
723 var = getvalkey((INTBIG)simals_mainproto, VNODEPROTO, VSTRING|VISARRAY,
724 sim_window_signalorder_key);
725 if (var != NOVARIABLE)
726 {
727 oldsigcount = getlength(var);
728 if (oldsigcount > 0)
729 {
730 sa = newstringarray(sim_tool->cluster);
731 for(i=0; i<oldsigcount; i++)
732 addtostringarray(sa, ((CHAR **)var->addr)[i]);
733 oldsignames = getstringarray(sa, &oldsigcount);
734 }
735 }
736 if (sim_window_create(simals_levelptr->num_chn, simals_mainproto,
737 ((sim_window_state&SHOWWAVEFORM) != 0 ? simals_charhandlerwave : 0),
738 simals_charhandlerschem, ALS))
739 {
740 if (oldsigcount > 0) killstringarray(sa);
741 return(TRUE);
742 }
743 sim_window_state = (sim_window_state & ~SIMENGINECUR) | SIMENGINECURALS;
744 }
745
746 /* set the window title */
747 if (simals_title == 0) sim_window_titleinfo(_("Top Level")); else
748 {
749 sim_window_titleinfo(simals_title);
750 }
751
752 /* load the traces */
753 sim_window_killalltraces(TRUE);
754 for(i=0; i<simals_levelptr->num_chn; i++)
755 simals_levelptr->display_page[i+1].displayptr = 0;
756
757 /* add in saved signals */
758 for(j=0; j<oldsigcount; j++)
759 {
760 /* see if the name is a bus */
761 for(pt = oldsignames[j]; *pt != 0; pt++) if (*pt == '\t') break;
762 if (*pt == '\t')
763 {
764 /* a bus */
765 pt++;
766 for(buscount = 0; ; )
767 {
768 for(start = pt; *pt != 0; pt++) if (*pt == '\t') break;
769 save = *pt;
770 *pt = 0;
771 opt = start;
772 if (*opt == '-') opt++;
773 for( ; *opt != 0; opt++)
774 if (!isdigit(*opt) || *opt == ':') break;
775 if (*opt == ':') start = opt+1;
776 for(i=0; i<simals_levelptr->num_chn; i++)
777 {
778 node = simals_levelptr->display_page[i+1].nodeptr;
779 if (node == 0) continue;
780 name = simals_levelptr->display_page[i+1].name;
781 if (namesame(name, start) != 0) continue;
782 bussignals[buscount] = sim_window_newtrace(-1, name, (INTBIG)node);
783 simals_levelptr->display_page[i+1].displayptr = bussignals[buscount];
784 buscount++;
785 break;
786 }
787 *pt++ = save;
788 if (save == 0) break;
789 }
790
791 /* create the bus */
792 infstr = initinfstr();
793 for(pt = oldsignames[j]; *pt != 0; pt++)
794 {
795 if (*pt == '\t') break;
796 addtoinfstr(infstr, *pt);
797 }
798 (void)sim_window_makebus(buscount, bussignals, returninfstr(infstr));
799 } else
800 {
801 /* a single signal */
802 pt = oldsignames[j];
803 if (*pt == '-') pt++;
804 for( ; *pt != 0; pt++)
805 if (!isdigit(*pt) || *pt == ':') break;
806 if (*pt == ':') pt++; else pt = oldsignames[j];
807 for(i=0; i<simals_levelptr->num_chn; i++)
808 {
809 node = simals_levelptr->display_page[i+1].nodeptr;
810 if (node == 0) continue;
811 name = simals_levelptr->display_page[i+1].name;
812 if (namesame(name, pt) != 0) continue;
813 simals_levelptr->display_page[i+1].displayptr = sim_window_newtrace(-1, name,
814 (INTBIG)node);
815 break;
816 }
817 }
818 }
819
820 /* add in other signals not in the saved list */
821 for(i=0; i<simals_levelptr->num_chn; i++)
822 {
823 if (simals_levelptr->display_page[i+1].displayptr != 0) continue;
824 node = simals_levelptr->display_page[i+1].nodeptr;
825 if (node == 0) continue;
826 name = simals_levelptr->display_page[i+1].name;
827 for(k=0; name[k] != 0; k++) if (name[k] == '[') break;
828 if (name[k] == '[')
829 {
830 /* found an arrayed signal: gather it into a bus */
831 buscount = 0;
832 for(j=0; j<simals_levelptr->num_chn; j++)
833 {
834 if (simals_levelptr->display_page[j+1].displayptr != 0) continue;
835 if (simals_levelptr->display_page[j+1].nodeptr == 0) continue;
836 subname = simals_levelptr->display_page[j+1].name;
837 if (namesamen(subname, name, k) != 0) continue;
838 if (buscount >= MAXSIMWINDOWBUSWIDTH) break;
839 bussignals[buscount++] = j;
840 }
841 esort(bussignals, buscount, SIZEOFINTBIG, simals_sortbusnames);
842 for(j=0; j<buscount; j++)
843 {
844 k = bussignals[j];
845 subnode = simals_levelptr->display_page[k+1].nodeptr;
846 subname = simals_levelptr->display_page[k+1].name;
847 bussignals[j] = sim_window_newtrace(-1, subname, (INTBIG)subnode);
848 simals_levelptr->display_page[k+1].displayptr = bussignals[j];
849 }
850
851 /* create the bus */
852 if (buscount > 1)
853 {
854 (void)sim_window_makebus(buscount, bussignals, 0);
855 }
856 } else
857 {
858 simals_levelptr->display_page[i+1].displayptr = sim_window_newtrace(-1, name,
859 (INTBIG)node);
860 }
861 }
862 sim_window_cleartracehighlight();
863 sim_window_settimerange(0, 0.0, 0.0000005f);
864 sim_window_setmaincursor(0.0000002f);
865 sim_window_setextensioncursor(0.0000003f);
866 if (oldsigcount > 0) killstringarray(sa);
867 return(FALSE);
868 }
869
870 /*
871 * Helper routine for "esort" that makes bus signals be numerically ordered
872 */
simals_sortbusnames(const void * e1,const void * e2)873 int simals_sortbusnames(const void *e1, const void *e2)
874 {
875 REGISTER CHAR *n1, *n2;
876 REGISTER INTBIG i1, i2;
877
878 i1 = *((INTBIG *)e1);
879 i2 = *((INTBIG *)e2);
880 n1 = simals_levelptr->display_page[i1+1].name;
881 n2 = simals_levelptr->display_page[i2+1].name;
882 if ((net_options&NETDEFBUSBASEDESC) != 0)
883 return(namesamenumeric(n2, n1));
884 return(namesamenumeric(n1, n2));
885 }
886
simals_fill_display_arrays(void)887 void simals_fill_display_arrays(void)
888 {
889 INTBIG *numsteps, i, j, pos, num_chan;
890 INTSML **statearrays;
891 INTBIG *nodelist, displayobj;
892 TRAKPTR trakhead;
893 double min, max, **timearrays;
894
895 /* determine size needed for waveform arrays */
896 num_chan = simals_levelptr->num_chn;
897 numsteps = (INTBIG *)emalloc(num_chan * SIZEOFINTBIG, el_tempcluster);
898 if (numsteps == 0) return;
899 nodelist = (INTBIG *)emalloc(num_chan * SIZEOFINTBIG, el_tempcluster);
900 if (nodelist == 0) return;
901 timearrays = (double **)emalloc(num_chan * (sizeof (double *)), el_tempcluster);
902 if (timearrays == 0) return;
903 statearrays = (INTSML **)emalloc(num_chan * (sizeof (INTSML *)), el_tempcluster);
904 if (statearrays == 0) return;
905 for(i=0; i<num_chan; i++)
906 {
907 numsteps[i] = 1;
908 displayobj = simals_levelptr->display_page[i+1].displayptr;
909 if (displayobj == 0) nodelist[i] = 0; else
910 nodelist[i] = sim_window_gettracedata(displayobj);
911 }
912
913 sim_window_gettimeextents(&min, &max);
914 if (simals_trakfull == 0) i = 0; else i = simals_trakptr;
915 for( ; i < simals_trakptr && i < simals_trace_size; i++)
916 {
917 trakhead = &(simals_trakroot[i]);
918 if (trakhead->time > max) break;
919 for (j=0; j<num_chan; j++)
920 {
921 if (nodelist[j] == 0) continue;
922 if (nodelist[j] != (INTBIG)trakhead->ptr) continue;
923 numsteps[j]++;
924 }
925 }
926
927 /* allocate space for the waveform arrays */
928 for (j=0; j<num_chan; j++)
929 {
930 if (nodelist[j] == 0) continue;
931 timearrays[j] = (double *)emalloc(numsteps[j] * (sizeof (double)), sim_tool->cluster);
932 statearrays[j] = (INTSML *)emalloc(numsteps[j] * SIZEOFINTSML, sim_tool->cluster);
933 if (timearrays[j] == 0 || statearrays[j] == 0) return;
934 }
935
936 /* fill the arrays */
937 for (i=0; i<num_chan; i++)
938 {
939 if (nodelist[i] == 0) continue;
940 numsteps[i] = 1;
941 timearrays[i][0] = min;
942 statearrays[i][0] = (LOGIC_LOW << 8) | OFF_STRENGTH;
943 }
944 if (simals_trakfull == 0) i = 0; else i = simals_trakptr;
945 for( ; i < simals_trakptr && i < simals_trace_size; i++)
946 {
947 trakhead = &(simals_trakroot[i]);
948 if (trakhead->time > max) break;
949 for (j=0; j<num_chan; j++)
950 {
951 if (nodelist[j] == 0) continue;
952 if (nodelist[j] != (INTBIG)trakhead->ptr) continue;
953 pos = numsteps[j]++;
954 timearrays[j][pos] = trakhead->time;
955 statearrays[j][pos] = (INTSML)((trakhead->state << 8) | trakhead->strength);
956 }
957 }
958
959 /* give the data to the simulation window system */
960 for (j=0; j<num_chan; j++)
961 {
962 if (nodelist[j] == 0) continue;
963 displayobj = simals_levelptr->display_page[j+1].displayptr;
964 sim_window_loaddigtrace(displayobj, numsteps[j], timearrays[j], statearrays[j]);
965 efree((CHAR *)timearrays[j]);
966 efree((CHAR *)statearrays[j]);
967 }
968 efree((CHAR *)nodelist);
969 efree((CHAR *)numsteps);
970 efree((CHAR *)timearrays);
971 efree((CHAR *)statearrays);
972 }
973
974 /*
975 * Routine that feeds the current signals into the explorer window.
976 */
simals_reportsignals(WINDOWPART * simwin,void * (* addbranch)(CHAR *,void *),void * (* findbranch)(CHAR *,void *),void * (* addleaf)(CHAR *,void *),CHAR * (* nodename)(void *))977 void simals_reportsignals(WINDOWPART *simwin, void *(*addbranch)(CHAR*, void*),
978 void *(*findbranch)(CHAR*, void*), void *(*addleaf)(CHAR*, void*), CHAR *(*nodename)(void*))
979 {
980 (*addleaf)("NO SIGNALS YET", 0);
981 }
982
983 #endif /* SIMTOOL - at top */
984