1 /****************************************************************************
2 Copyright (C) 1987-2015 by Jeffery P. Hansen
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 Last edit by hansen on Sat Sep 26 18:35:12 2009
19 ****************************************************************************/
20
21 #include <stdlib.h>
22 #include <assert.h>
23
24 #include "tkgate.h"
25
26 #define MAXDEPTH 128
27
28 extern GScope *Scope;
29
30 int security_exec_level;
31
32 static char *unitStrings[] = {"s","ms","us","ns","ps","fs"};
33
34 /*****************************************************************************
35 *
36 * Convert a character to a value.
37 *
38 * Paramaters:
39 * c Character to convert
40 *
41 * Returns: Value corresponding to c or -1 if it was an unknown
42 *
43 *****************************************************************************/
charToSym(char c)44 static int charToSym(char c)
45 {
46 if (isdigit(c))
47 return c - '0';
48 else if (c >= 'A' && c <= 'F')
49 return c - 'A' + 10;
50 else if (c >= 'a' && c <= 'f')
51 return c - 'a' + 10;
52 else
53 return -1;
54 }
55
56
parse_verilog_bits(unsigned * Svalue,unsigned * Svalid,const char * A)57 static void parse_verilog_bits(unsigned *Svalue,unsigned *Svalid,const char *A)
58 {
59 int d = strlen(A);
60 int i;
61
62 *Svalue = 0;
63 *Svalid = ~0;
64
65 for (i = 0;i < d;i++) {
66 int digitVal = charToSym(A[d-i-1]);
67
68 if (digitVal < 0)
69 *Svalid &= ~(1 << i);
70
71 *Svalue |= digitVal << i;
72 }
73
74 if (d < TKGATE_WORDSIZE && charToSym(A[0]) < 0) {
75 *Svalid &= ((1 << d)-1);
76 }
77 }
78
parse_verilog_hex(unsigned * Svalue,unsigned * Svalid,const char * A)79 void parse_verilog_hex(unsigned *Svalue,unsigned *Svalid,const char *A)
80 {
81 int len = strlen(A); /* Length of string */
82 int i;
83
84 *Svalue = 0;
85 *Svalid = 0;
86
87 for (i = 0;i < len;i++) {
88 int digitValue, digitValid;
89
90 if (A[i] == '(') {
91 digitValue = 0;
92 digitValid = 0;
93 for (i++;A[i] != ')';i++) {
94 int d = charToSym(A[i]);
95 int v = (d < 0) ? 0 : 1;
96 if (d < 0) d = 0;
97 digitValue = (digitValue << 1) | d;
98 digitValid = (digitValid << 1) | v;
99 }
100 } else {
101 digitValue = charToSym(A[i]);
102 digitValid = (digitValue < 0) ? 0 :0xf;
103 if (digitValue < 0) digitValue = 0;
104 }
105
106 /*
107 * If the initial digit is not unknown, make all bits above the
108 * specified bits valid.
109 */
110 if (i == 0 && digitValid == 0xf)
111 *Svalid = ~0;
112
113 *Svalid = (*Svalid << 4) | digitValid;
114 *Svalue = (*Svalue << 4) | digitValue;
115 }
116
117 /* printf("parse_verilog_hex: [%s] valid=%x value=%x\n",A,*Svalid,*Svalue);*/
118 }
119
parse_verilog_oct(unsigned * Svalue,unsigned * Svalid,const char * A)120 static void parse_verilog_oct(unsigned *Svalue,unsigned *Svalid,const char *A)
121 {
122 int len = strlen(A); /* Length of string */
123 int i;
124
125 *Svalue = 0;
126 *Svalid = 0;
127
128 for (i = 0;i < len;i++) {
129 int digitValue, digitValid;
130
131 if (A[i] == '(') {
132 digitValue = 0;
133 digitValid = 0;
134 for (i++;A[i] != ')';i++) {
135 int d = charToSym(A[i]);
136 int v = (d < 0) ? 0 : 1;
137 if (d < 0) d = 0;
138 digitValue = (digitValue << 1) | d;
139 digitValid = (digitValid << 1) | v;
140 }
141 } else {
142 digitValue = charToSym(A[i]);
143 digitValid = (digitValue < 0) ? 0 :0x7;
144 if (digitValue < 0) digitValue = 0;
145 }
146
147 /*
148 * If the initial digit is not unknown, make all bits above the
149 * specified bits valid.
150 */
151 if (i == 0 && digitValid == 0x7)
152 *Svalid = ~0;
153
154 *Svalid = (*Svalid << 3) | digitValid;
155 *Svalue = (*Svalue << 3) | digitValue;
156 }
157
158 /* printf("parse_verilog_hex: [%s] valid=%x value=%x\n",A,*Svalid,*Svalue);*/
159 }
160
161 /*****************************************************************************
162 *
163 * Parse a verilog-style constant
164 *
165 * Parameters:
166 * value String representation of constant to be parsed
167 * *ivalue Returned integer representation of value (up to 32-bits)
168 * *ivalid Returned mask of valid bits
169 * *nbits Returned number of bits
170 *
171 * Returns: Non-zero if consant was invalid, 0 if valid.
172 *
173 * Parse a verilog-style constant as received from the simulator.
174 * Only 'b' and 'h' types are used, with 'b' types being used only
175 * for single-bit values.
176 *
177 *****************************************************************************/
parse_verilog_constant(char * value,unsigned * ivalue,unsigned * ivalid,int * nbits)178 int parse_verilog_constant(char *value,unsigned *ivalue,unsigned *ivalid,int *nbits)
179 {
180 const char *p;
181 char c;
182
183 if (*value == 'x') {
184 *ivalue = 0;
185 *ivalid = 0;
186 return 0;
187 }
188
189 *nbits = 0;
190 if (sscanf(value,"%d'%c",nbits,&c) == 2) {
191 p = strchr(value,'\'')+2;
192 } else if (sscanf(value,"'%c",&c) == 1) {
193 nbits = 0;
194 p = strchr(value,'\'')+2;
195 } else {
196 nbits = 0;
197 p = value;
198 c = 'i';
199 }
200
201 switch (c) {
202 case 'b' :
203 parse_verilog_bits(ivalue,ivalid,p);
204 break;
205 case 'h' :
206 parse_verilog_hex(ivalue,ivalid,p);
207 break;
208 case 'o' :
209 parse_verilog_oct(ivalue,ivalid,p);
210 break;
211 case 'd' :
212 case 'i' :
213 *ivalid = ~0;
214 if (sscanf(p,"%u",ivalue) != 1)
215 return -1;
216 break;
217 default:
218 return -1;
219 break;
220 }
221 return 0;
222 }
223
sendSimCmd(char * fmt,...)224 void sendSimCmd(char *fmt,...)
225 {
226 char buf[STRMAX];
227 va_list ap;
228
229 va_start(ap,fmt);
230 vsprintf(buf,fmt,ap);
231 va_end(ap);
232
233 DoTclL("Simulator::cmdSend",buf,NULL);
234 }
235
new_GSimSwitch(char * wname,char * gname,GCElement * g)236 GSimSwitch *new_GSimSwitch(char *wname,char *gname,GCElement *g)
237 {
238 GSimSwitch *ss = (GSimSwitch*)ob_malloc(sizeof(GSimSwitch),"GSimSwitch");
239
240 ss->name = ob_strdup(wname);
241 ss->gname = ob_strdup(gname);
242 ss->gate = g;
243 ss->state = (unsigned*)ob_malloc(sizeof(unsigned),"unsigned");
244 *ss->state = g->u.sw.dipval;
245
246 return ss;
247 }
248
new_GSimLed(char * wname,char * gname,GCElement * g)249 GSimLed *new_GSimLed(char *wname,char *gname,GCElement *g)
250 {
251 GSimLed *ss = (GSimLed*)ob_malloc(sizeof(GSimLed),"GSimLed");
252
253 ss->name = ob_strdup(wname);
254 ss->gname = ob_strdup(gname);
255 ss->gate = g;
256
257 return ss;
258 }
259
new_GSimModule(GModuleDef * M,GCElement * g,GSimModule * P)260 GSimModule *new_GSimModule(GModuleDef *M,GCElement *g,GSimModule *P)
261 {
262 GSimModule *sM = (GSimModule*) ob_malloc(sizeof(GSimModule),"GSimModule");
263
264 sM->mod = M;
265 sM->inst = g;
266 sM->parent = P;
267
268 sM->probes = new_SHash();
269 sM->switches = new_SHash();
270 sM->leds = new_SHash();
271 sM->children = new_SHash();
272
273 return sM;
274 }
275
sim_findNet(const char * name)276 GNet *sim_findNet(const char *name)
277 {
278 char buf[STRMAX],*T;
279 char *ptr[MAXDEPTH];
280 GModuleDef *M = TkGate.circuit->root_mod;
281 GNet *n = 0;
282 int N,i;
283
284 strcpy(buf,name);
285 for (T = strtok(buf,"."), N = 0;T;T = strtok(0,"."), N++)
286 ptr[N] = T;
287
288 for (i = 0;i < N;i++) {
289 if (i != (N-1)) {
290 GCElement *g = GModuleDef_findGate(M,ptr[i]);
291
292 if (g && GCElement_isModule(g))
293 M = env_findModule(g->u.block.moduleName);
294 else
295 return 0;
296 } else
297 n = GModuleDef_findNet(M,ptr[i]);
298 }
299
300 return n;
301 }
302
303 /** @TODO Needs optimisation badly */
sim_findGate(const char * name)304 GCElement *sim_findGate(const char *name)
305 {
306 char buf[STRMAX],*T;
307 char *ptr[MAXDEPTH];
308 GModuleDef *M;
309 unsigned N,i;
310 GCElement *g;
311
312 strcpy(buf,name);
313 for (T = strtok(buf,"."), N = 0; T != NULL; T = strtok(NULL,"."), ++N)
314 ptr[N] = T;
315
316 assert(N>0);
317 if (N==0)
318 return 0;
319
320 if (strncmp(ptr[0], TkGate.circuit->root_mod->m_name, STRMAX)==0)
321 i=1; /* If path starting from root, ommit root element */
322 else
323 i=0;
324
325 M = TkGate.circuit->root_mod;
326
327 for (g = NULL;i < N;i++) {
328 g = GModuleDef_findGate(M,ptr[i]);
329 if (g && GCElement_isModule(g))
330 M = env_findModule(g->u.block.moduleName);
331 }
332 return g;
333 }
334
sim_findContainingMod(const char * path)335 GModuleDef *sim_findContainingMod(const char *path)
336 {
337 char buf[STRMAX],*p;
338 GModuleDef *M;
339
340 strcpy(buf,path);
341 if ((p = strrchr(buf,'.'))) {
342 GCElement *mg;
343 *p = 0;
344 mg = sim_findGate(buf);
345 if (mg)
346 M = env_findModule(mg->u.block.moduleName);
347 else
348 M = 0;
349 } else
350 M = TkGate.circuit->root_mod;
351
352 return M;
353 }
354
getSimTempFile(char * buf)355 void getSimTempFile(char *buf)
356 {
357 int fd;
358
359 strcpy(buf,"/tmp/tkgate.XXXXXX");
360 fd = mkstemp(buf);
361 close(fd);
362 }
363
364 /*****************************************************************************
365 *
366 * Initialize a SimInterface (Simulation Interface) object
367 *
368 * Parameters:
369 * si Object to initialize.
370 *
371 *****************************************************************************/
SimInterface_init(SimInterface * si)372 void SimInterface_init(SimInterface *si)
373 {
374 si->active = 0;
375 *si->simFileName = 0;
376 si->sim_root = 0;
377 si->area = 0;
378 si->staticPower = 0;
379 }
380
GSimModule_getTreePath(GSimModule * M,char * s)381 char *GSimModule_getTreePath(GSimModule *M,char *s)
382 {
383 if (!M->parent) {
384 return s + sprintf(s,"<%s>",M->mod->m_name);
385 }
386
387 s = GSimModule_getTreePath(M->parent,s);
388 return s + sprintf(s,"/%s<%s>",M->inst->ename,M->mod->m_name);
389 }
390
GSimModule_getPathPrefix(GSimModule * M,char * s)391 char *GSimModule_getPathPrefix(GSimModule *M,char *s)
392 {
393 if (!M->parent) {
394 return s + sprintf(s,"%s.",M->mod->m_name);
395 }
396
397 s = GSimModule_getPathPrefix(M->parent,s);
398 return s + sprintf(s,"%s.",M->inst->ename);
399 }
400
GSimModule_getNetPathName(GSimModule * M,GNet * n,char * buf)401 void GSimModule_getNetPathName(GSimModule *M,GNet *n,char *buf)
402 {
403 char *s;
404
405 s = GSimModule_getPathPrefix(M,buf);
406 strcpy(s,n->n_signame);
407 }
408
409
410 /*
411 The the full path of a gate g in the current module.
412 */
GSimModule_getFullPath(GSimModule * M,GCElement * g,char * buf)413 void GSimModule_getFullPath(GSimModule *M,GCElement *g,char *buf)
414 {
415 char *s;
416
417 s = GSimModule_getPathPrefix(M,buf);
418 if (g)
419 strcpy(s,g->ename);
420 }
421
new_GSimProbe(const char * name,GNet * net,int x,int y,GSimModule * sM)422 GSimProbe *new_GSimProbe(const char *name,GNet *net,int x,int y,GSimModule *sM)
423 {
424 GSimProbe *P = (GSimProbe *) ob_malloc(sizeof(GSimProbe),"GSimProbe");
425
426 P->name = ob_strdup(name);
427 P->net = net;
428 P->x = x;
429 P->y = y;
430 P->ss = sM;
431
432 return P;
433 }
434
delete_GSimProbe(GSimProbe * P)435 void delete_GSimProbe(GSimProbe *P)
436 {
437 ob_free(P->name);
438 ob_free(P);
439 }
440
GSimProbe_draw(GSimProbe * P)441 void GSimProbe_draw(GSimProbe *P)
442 {
443 static Icon *probe_icon = 0;
444
445 if (!probe_icon) {
446 int w,h,x,y;
447 Pixmap pm = Pixmap_registerFromFileWithParms("probe","probe.b",&w,&h,&x,&y);
448 probe_icon = new_Icon(pm,0,0,w,h,x,y);
449 }
450 Icon_draw(TkGate.D,TkGate.W,TkGate.toolGC,ctow_x(P->x),ctow_y(P->y),probe_icon);
451 dce_DrawString(TkGate.toolGC,P->x+20,P->y-20,BetweenTopAndBottom|AtLeft,P->name);
452 }
453
SimProbe_localName(GSimProbe * P)454 const char *SimProbe_localName(GSimProbe *P)
455 {
456 const char *x = strrchr(P->name,'.');
457 if (x)
458 return x+1;
459 else
460 return P->name;
461 }
462
463 /*****************************************************************************
464 *
465 * Lookup up a gate from its full path.
466 *
467 * Parameters:
468 * si Simulation interface to search
469 * name Full path name of gate
470 * *r_M Return for module gate was found in.
471 * *r_g Return for gate that was found
472 * *r_ss Return for GSimSwitch if gate was a switch/dip.
473 *
474 * Returns: Zero on success, negative on failure.
475 *
476 * Lookup the gate named 'name' where 'name' is a full path gate name. Returns the
477 * simulation module the gate is in, the GCElement structure and the correspoinding
478 * GSimSwitch for the specified gate. Only non-NULL return arguments will be assigned.
479 * The function returns non-zero if the specified gate is not found.
480 *
481 *****************************************************************************/
SimInterface_lookupGate(SimInterface * si,const char * name,GSimModule ** r_M,GCElement ** r_g,GSimSwitch ** r_ss)482 int SimInterface_lookupGate(SimInterface *si,const char *name,GSimModule **r_M,
483 GCElement **r_g,GSimSwitch **r_ss)
484 {
485 char buf[STRMAX],*T;
486 char *ptr[MAXDEPTH];
487 GSimModule *M;
488 GCElement *g;
489 GSimSwitch *ss;
490 int i,N;
491
492 M = si->sim_root;
493
494 strcpy(buf,name);
495 for (T = strtok(buf,"."), N = 0;T;T = strtok(0,"."), N++)
496 ptr[N] = T;
497
498 /*
499 * Find parent GSimModule of specified gate.
500 */
501 for (i = 1;i < N-1;i++) {
502 M = (GSimModule*)SHash_find(M->children,ptr[i]);
503 if (!M) return -1;
504 }
505
506 /*
507 * Find the actual gate.
508 */
509 g = GModuleDef_findGate(M->mod,ptr[N-1]);
510 if (!g) {
511 return -1;
512 }
513
514 /*
515 * Find the GSimSwitch if available.
516 */
517 ss = (GSimSwitch*) SHash_find(M->switches,g->ename);
518
519 if (r_M) *r_M = M;
520 if (r_g) *r_g = g;
521 if (r_ss) *r_ss = ss;
522
523 return 0;
524 }
525
526 /******************************************************************************
527 * Lookup the net named 'name' where 'name' is a full path net name. Returns the
528 * simulation module the net is in, and the wire.
529 *****************************************************************************/
SimInterface_lookupWire(SimInterface * si,const char * name,GSimModule ** r_M,GWire ** r_w,GNet ** r_n)530 int SimInterface_lookupWire(SimInterface *si,const char *name,GSimModule **r_M,GWire **r_w,GNet **r_n)
531 {
532 char buf[STRMAX],*T;
533 char *ptr[MAXDEPTH];
534 GSimModule *M;
535 GNet *n;
536 int i,N;
537
538 M = si->sim_root;
539
540 strcpy(buf,name);
541 for (T = strtok(buf,"."), N = 0;T;T = strtok(0,"."), N++)
542 ptr[N] = T;
543
544 /*
545 * Find parent GSimModule of specified wire.
546 */
547 for (i = 1;i < N-1;i++) {
548 M = (GSimModule*)SHash_find(M->children,ptr[i]);
549 if (!M) return -1;
550 }
551
552 if (GModuleDef_getType(M->mod) == MT_NETLIST) {
553 /*
554 * Find the actual net.
555 */
556 n = GModuleDef_findNet(M->mod,ptr[N-1]);
557 if (!n) return -1;
558
559 *r_M = M;
560 *r_w = n->n_driver;
561 if (r_n) *r_n = n;
562 } else {
563 /*
564 * This is an HDL module. Do not set a wire.
565 */
566 n = GModuleDef_findNet(M->mod,ptr[N-1]);
567 if (!n) return -1;
568 *r_M = M;
569 *r_w = 0;
570 if (r_n) *r_n = n;
571 }
572
573 return 0;
574 }
575
SimInterface_changeCurrentModule(GSimModule * new_sm,GSimModule * old_sm)576 void SimInterface_changeCurrentModule(GSimModule *new_sm,GSimModule *old_sm)
577 {
578 char buf[STRMAX];
579 HashElem *E;
580
581 if (old_sm) {
582 for (E = Hash_first(old_sm->leds);E;E = Hash_next(old_sm->leds,E)) {
583 GSimLed *sl = (GSimLed*) HashElem_obj(E);
584
585 GSimModule_getNetPathName(old_sm,sl->gate->wires[0]->net, buf);
586 sendSimCmd("$unprobe %s $led:%s",buf,sl->gate->ename);
587 }
588 for (E = Hash_first(new_sm->switches);E;E = Hash_next(new_sm->switches,E)) {
589 GSimSwitch *ss = (GSimSwitch*) HashElem_obj(E);
590
591 GSimModule_getNetPathName(new_sm,ss->gate->wires[0]->net, buf);
592 sendSimCmd("$unprobe %s $switch:%s",buf,ss->gate->ename);
593 }
594 }
595
596 if (new_sm) {
597 for (E = Hash_first(new_sm->switches);E;E = Hash_next(new_sm->switches,E)) {
598 GSimSwitch *ss = (GSimSwitch*) HashElem_obj(E);
599 ss->gate->u.sw.dipval = *ss->state;
600
601 GSimModule_getNetPathName(new_sm,ss->gate->wires[0]->net, buf);
602 sendSimCmd("$probe %s $switch:%s",buf,ss->gate->ename);
603 }
604 for (E = Hash_first(new_sm->leds);E;E = Hash_next(new_sm->leds,E)) {
605 GSimLed *sl = (GSimLed*) HashElem_obj(E);
606
607 GSimModule_getNetPathName(new_sm,sl->gate->wires[0]->net, buf);
608 sendSimCmd("$probe %s $led:%s",buf,sl->gate->ename);
609 }
610
611 GSimModule_getTreePath(new_sm, buf);
612 DoTcl("BlockTree::setActive %s", buf);
613 }
614
615
616 }
617
SimInterface_updateNetlistProbes(GSimModule * SM)618 void SimInterface_updateNetlistProbes(GSimModule *SM)
619 {
620 HashElem *E;
621
622 for (E = Hash_first(SM->probes);E;E = Hash_next(SM->probes,E)) {
623 GSimProbe *P = (GSimProbe*) HashElem_obj(E);
624 DoTcl("NetList::configureitem %s -probe 1",SimProbe_localName(P));
625 }
626 }
627
SimInterface_buildSimMods_aux(GModuleDef * M,GCElement * pg,GSimModule * P)628 static GSimModule *SimInterface_buildSimMods_aux(GModuleDef *M,GCElement *pg,GSimModule *P)
629 {
630 GSimModule *sM = new_GSimModule(M,pg,P);
631 HashElem *E;
632
633 for (E = Hash_first(M->m_gates);E;E = Hash_next(M->m_gates,E)) {
634 GCElement *g = (GCElement*) HashElem_obj(E);
635 GSimModule *csM;
636 GModuleDef *cM;
637 char netPath[STRMAX],componentPath[STRMAX];
638
639 GSimModule_getFullPath(sM,g,componentPath);
640
641 (*g->typeinfo->SimInitFunc)(TkGate.circuit->es,g,componentPath);
642
643 switch (g->typeinfo->code) {
644 case GC_SYMBLOCK :
645 case GC_BLOCK :
646 cM = env_findModule(g->u.block.moduleName);
647 if (cM) {
648 csM = SimInterface_buildSimMods_aux(cM,g,sM);
649 SHash_insert(sM->children,g->ename,csM);
650 }
651 break;
652 case GC_SWITCH :
653 case GC_DIP :
654 GSimModule_getNetPathName(sM,g->wires[0]->net,netPath);
655 SHash_insert(sM->switches,g->ename,new_GSimSwitch(netPath,componentPath,g));
656 break;
657 case GC_LED :
658 GSimModule_getNetPathName(sM,g->wires[0]->net,netPath);
659 SHash_insert(sM->leds,g->ename,new_GSimSwitch(netPath,componentPath,g));
660 break;
661 }
662 }
663
664 return sM;
665 }
666
SimInterface_buildSimMods(SimInterface * si)667 static void SimInterface_buildSimMods(SimInterface *si)
668 {
669 si->sim_root = SimInterface_buildSimMods_aux(TkGate.circuit->root_mod,0,0);
670 }
671
SimInterface_drawProbes(SimInterface * si)672 void SimInterface_drawProbes(SimInterface *si)
673 {
674 GSimModule *sM = TkGate.circuit->es->smod;
675 HashElem *E;
676
677 if (!sM) return;
678
679 for (E = Hash_first(sM->probes);E;E = Hash_next(sM->probes,E)) {
680 GSimProbe *P = (GSimProbe*) HashElem_obj(E);
681 GSimProbe_draw(P);
682 }
683 }
684
SimInterface_probeExists(SimInterface * si,GSimModule * sM,const char * name)685 int SimInterface_probeExists(SimInterface *si,GSimModule *sM,const char *name)
686 {
687 return SHash_find(sM->probes,name) != 0;
688 }
689
690 /*****************************************************************************
691 *
692 * Add a probe in response to request from simulator
693 *
694 *****************************************************************************/
SimInterface_addProbe(SimInterface * si,const char * name,int nbits)695 void SimInterface_addProbe(SimInterface *si,const char *name,int nbits)
696 {
697 GSimProbe *P;
698 GSimModule *sM;
699 GWire *w;
700 int visible;
701 int x,y;
702
703 if (GScope_findTrace(Scope, name)) return;
704 if (SimInterface_lookupWire(si,name,&sM,&w,0) != 0) return;
705 visible = (sM == TkGate.circuit->es->smod);
706
707 GScope_addTrace(Scope,name,name,nbits,TkGate.sortTraces);
708
709 if (GModuleDef_getType(sM->mod) == MT_NETLIST) {
710 GWire_pickProbePosition(w,&x,&y);
711 P = new_GSimProbe(name,w->net,x,y,sM);
712 SHash_insert(sM->probes,name,P);
713
714 if (visible) {
715 GSimProbe_draw(P);
716 DoTcl("NetList::configureitem %s -probe 1",SimProbe_localName(P));
717 }
718 } else {
719 P = new_GSimProbe(name,w->net,x,y,sM);
720 SHash_insert(sM->probes,name,P);
721
722 if (visible) {
723 DoTcl("NetList::configureitem %s -probe 1",SimProbe_localName(P));
724 }
725 }
726 }
727
728 /*****************************************************************************
729 *
730 * Remove a probe in response to request from simulator
731 *
732 *****************************************************************************/
SimInterface_delProbe(SimInterface * si,const char * name)733 void SimInterface_delProbe(SimInterface *si,const char *name)
734 {
735 GSimProbe *P;
736 GSimModule *sM;
737 GWire *w;
738 int visible;
739
740 if (!GScope_findTrace(Scope, name)) return;
741 if (SimInterface_lookupWire(si,name,&sM,&w,0) != 0) return;
742 visible = (sM == TkGate.circuit->es->smod);
743
744 P = SHash_find(sM->probes,name);
745 if (!P) return;
746
747 if (GModuleDef_getType(sM->mod) == MT_NETLIST) {
748
749 if (visible) {
750 GSimProbe_draw(P);
751 DoTcl("NetList::configureitem %s -probe 0",SimProbe_localName(P));
752 }
753 } else {
754 if (visible) {
755 DoTcl("NetList::configureitem %s -probe 0",SimProbe_localName(P));
756 }
757 }
758
759 SHash_remove(sM->probes,name);
760 delete_GSimProbe(P);
761
762 GScope_deleteTrace(Scope,name);
763 }
764
765 /*****************************************************************************
766 *
767 * Add or delete a probe in a circuit in response to interface request
768 *
769 *****************************************************************************/
SimInterface_addDelProbe(SimInterface * si,GSimModule * sM,const char * name,GWire * w,GWireNode * n,int x,int y)770 void SimInterface_addDelProbe(SimInterface *si,GSimModule *sM,const char *name,GWire *w,GWireNode *n,int x,int y)
771 {
772 GSimProbe *P;
773 int visible = (sM == TkGate.circuit->es->smod);
774
775 if (GModuleDef_getType(sM->mod) != MT_NETLIST) {
776 logError(ERL_ERROR,"SimInterface_addDelProbe called on HDL module.");
777 return;
778 }
779
780 if ((P = SHash_find(sM->probes,name))) { /* If probe exists, delete it */
781 if (visible)
782 GSimProbe_draw(P);
783 SHash_remove(sM->probes,name);
784 GScope_deleteTrace(Scope,name);
785 sendSimCmd("$unprobe %s",name);
786 DoTcl("NetList::configureitem %s -probe 0",SimProbe_localName(P));
787 delete_GSimProbe(P);
788 } else { /* else add it */
789 GScope_addTrace(Scope,name,name,w->net->n_nbits,TkGate.sortTraces);
790 GWire_pickProbePosition(w,&x,&y);
791 P = new_GSimProbe(name,w->net,x,y,sM);
792 SHash_insert(sM->probes,name,P);
793 if (visible)
794 GSimProbe_draw(P);
795 sendSimCmd("$probe %s",name);
796 DoTcl("NetList::configureitem %s -probe 1",SimProbe_localName(P));
797 }
798 }
799
SimInterface_addDelHDLProbe(SimInterface * si,GSimModule * sM,const char * name,GNet * net)800 void SimInterface_addDelHDLProbe(SimInterface *si,GSimModule *sM,const char *name,GNet *net)
801 {
802 GSimProbe *P;
803
804 if (GModuleDef_getType(sM->mod) != MT_TEXTHDL) {
805 logError(ERL_ERROR,"SimInterface_addDelHDLProbe called on non-HDL module.");
806 return;
807 }
808
809 if ((P = SHash_find(sM->probes,name))) { /* If probe exists, delete it */
810 SHash_remove(sM->probes,name);
811 GScope_deleteTrace(Scope,name);
812 sendSimCmd("$unprobe %s",name);
813 DoTcl("NetList::configureitem %s -probe 0",SimProbe_localName(P));
814 delete_GSimProbe(P);
815 } else {
816 P = new_GSimProbe(name,0,0,0,sM);
817 GScope_addTrace(Scope,name,name,GNet_getNBits(net),TkGate.sortTraces);
818 SHash_insert(sM->probes,name,P);
819 sendSimCmd("$probe %s",name);
820 DoTcl("NetList::configureitem %s -probe 1",SimProbe_localName(P));
821 }
822 }
823
SimInterface_setLed(SimInterface * si,char * gname,char * value)824 void SimInterface_setLed(SimInterface *si,char *gname,char *value)
825 {
826 GCElement *g;
827 unsigned ivalue,ivalid;
828 int n;
829
830 g = sim_findGate(gname);
831 if (!g)
832 g = GModuleDef_findGate(TkGate.circuit->es->smod->mod, gname);
833 if (!g) return;
834
835 parse_verilog_constant(value,&ivalue,&ivalid,&n);
836
837 #if 0
838 if (g->u.led.ltype == 1) {
839 printf("[%s] -> valid:%02x value:%02x\n",value,ivalid,ivalue);
840 }
841 #endif
842
843 if (g->u.led.value != ivalue || g->u.led.valid != ivalid) {
844 gate_draw(g,GD_NOWIRE);
845 g->u.led.value = ivalue;
846 g->u.led.valid = ivalid;
847 gate_draw(g,GD_NOWIRE);
848 }
849 }
850
851 /*****************************************************************************
852 *
853 * Set the state of a switch. This method is used in response to the
854 * "tell $switch" notice from simulator. It is used to ensure switch changes
855 * from a simulation script cause switches to be updated properly.
856 *
857 *****************************************************************************/
SimInterface_setSwitch(SimInterface * si,char * gname,char * value)858 void SimInterface_setSwitch(SimInterface *si,char *gname,char *value)
859 {
860 EditState *es = TkGate.circuit->es;
861 GCElement *g;
862 unsigned ivalue,ivalid;
863 int n;
864
865 g = sim_findGate(gname);
866 if (!g)
867 g = GModuleDef_findGate(TkGate.circuit->es->smod->mod, gname);
868 if (!g) return;
869
870 parse_verilog_constant(value,&ivalue,&ivalid,&n);
871
872 if (g->u.sw.dipval != ivalue) {
873 GSimSwitch *ss = SHash_find(es->smod->switches,g->ename);
874
875 gate_draw(g,0);
876 *ss->state = g->u.sw.dipval = ivalue;
877 gate_draw(g,0);
878 }
879 }
880
881
882 /*****************************************************************************
883 *
884 * Hit an object while in simulation mode.
885 *
886 * Parameters:
887 * si Simulator interface
888 * x,y Coordinates of hit
889 * isDoubleClick Non-zero if this is a double click.
890 *
891 *****************************************************************************/
SimInterface_hit(SimInterface * si,int x,int y,int isDoubleClick)892 void SimInterface_hit(SimInterface *si,int x,int y,int isDoubleClick)
893 {
894 GCElement *g = 0;
895 GWireNode *n = 0;
896 EditState *es = TkGate.circuit->es;
897
898 EditState_unselectAll(es);
899
900 if ((g = gate_hit(TkGate.circuit->es->env,x,y))) {
901 if (g->typeinfo->code == GC_JOINT) {
902 int i;
903
904 for (i = 0;i < 4;i++)
905 if (g->wires[i]) {
906 n = g->wires[i]->nodes;
907 break;
908 }
909 } else {
910 if ((*g->typeinfo->SimHitFunc)(es,g))
911 return;
912 else
913 n = wire_iohit(x,y,TkGate.circuit->es->env->m_wires);
914 }
915 } else
916 n = wire_iohit(x,y,TkGate.circuit->es->env->m_wires);
917
918 if (n) {
919 char buf[STRMAX];
920 GWire *w = wirenode_driver(n);
921
922 GSimModule_getNetPathName(es->smod, w->net,buf);
923
924 net_select(w->net,1);
925 TkGate.circuit->wnsel = n;
926 TkGate.circuit->wsel = wirenode_driver(n);
927
928 if (isDoubleClick) {
929 DoTcl("Simulator::hideValue");
930 SimInterface_addDelProbe(si,TkGate.circuit->es->smod,buf,w,n,x,y);
931 } else {
932 DoTcl("Simulator::showValue %s",buf);
933 }
934 }
935 }
936
SimInterface_hitRelease(SimInterface * si)937 void SimInterface_hitRelease(SimInterface *si)
938 {
939 DoTcl("Simulator::hideValue");
940 }
941
SimInterface_send(SimInterface * si,const char * command,...)942 void SimInterface_send(SimInterface *si,const char *command,...)
943 {
944 }
945
GSimModule_initSwitches(GSimModule * M)946 static void GSimModule_initSwitches(GSimModule *M)
947 {
948 HashElem *E;
949
950 for (E = Hash_first(M->switches);E;E = Hash_next(M->switches,E)) {
951 GSimSwitch *ss = (GSimSwitch*) HashElem_obj(E);
952 int nbits = ss->gate->wires[0]->net->n_nbits;
953 DoTcl("tkg_simNetSet %s %d'h%x",ss->name,nbits,*ss->state);
954 }
955
956 for (E = Hash_first(M->children);E;E = Hash_next(M->children,E)) {
957 GSimModule *cM = (GSimModule*) HashElem_obj(E);
958 GSimModule_initSwitches(cM);
959 }
960 }
961
GSimModule_initClocks(GSimModule * M,char * name)962 static void GSimModule_initClocks(GSimModule *M,char *name)
963 {
964 HashElem *E;
965 char *nend = name + strlen(name);
966
967
968 for (E = Hash_first(M->mod->m_gates);E;E = Hash_next(M->mod->m_gates,E)) {
969 GCElement *g = (GCElement*) HashElem_obj(E);
970
971 if (GCElement_getType(g) == GC_CLOCK) {
972 sprintf(nend,".%s",g->ename);
973 sendSimCmd("$regclock %s.Z",name);
974 }
975 }
976
977
978
979 for (E = Hash_first(M->children);E;E = Hash_next(M->children,E)) {
980 GSimModule *cM = (GSimModule*) HashElem_obj(E);
981 sprintf(nend,".%s",cM->inst->ename);
982 GSimModule_initClocks(cM,name);
983 }
984 }
985
GSimModule_initMemories(GSimModule * M,char * name)986 static void GSimModule_initMemories(GSimModule *M,char *name)
987 {
988 HashElem *E;
989 char *nend = name + strlen(name);
990
991 for (E = Hash_first(M->mod->m_gates);E;E = Hash_next(M->mod->m_gates,E)) {
992 GCElement *g = (GCElement*) HashElem_obj(E);
993
994 if (GCElement_getType(g) == GC_ROM || GCElement_getType(g) == GC_RAM) {
995 sprintf(nend,".%s",g->ename);
996
997 if (g->u.mem.memfile && *g->u.mem.memfile != 0)
998 sendSimCmd("$memload %s %s",g->u.mem.memfile,name);
999 }
1000 }
1001 for (E = Hash_first(M->children);E;E = Hash_next(M->children,E)) {
1002 GSimModule *cM = (GSimModule*) HashElem_obj(E);
1003 sprintf(nend,".%s",cM->inst->ename);
1004 GSimModule_initMemories(cM,name);
1005 }
1006 }
1007
1008
SimInterface_initClocks(SimInterface * si)1009 static void SimInterface_initClocks(SimInterface *si)
1010 {
1011 char name[STRMAX];
1012
1013 sprintf(name,"%s",si->sim_root->mod->m_name);
1014 GSimModule_initClocks(si->sim_root,name);
1015 }
1016
SimInterface_initMemories(SimInterface * si)1017 static void SimInterface_initMemories(SimInterface *si)
1018 {
1019 char name[STRMAX];
1020
1021 sprintf(name,"%s",si->sim_root->mod->m_name);
1022 GSimModule_initMemories(si->sim_root,name);
1023 }
1024
1025 /*****************************************************************************
1026 *
1027 * Add the probes that where saved from the previous invocation.
1028 *
1029 *****************************************************************************/
SimInterface_addSavedProbes(SimInterface * si)1030 static void SimInterface_addSavedProbes(SimInterface *si)
1031 {
1032 List *pNames = TkGate.circuit->c_probes;
1033 ListElem *le;
1034 int x;
1035
1036 /*
1037 * Temporarily disable trace sorting.
1038 */
1039 x = TkGate.sortTraces;
1040 TkGate.sortTraces = 0;
1041
1042 for (le = List_first(pNames);le;le = List_next(pNames,le)) {
1043 const char *name = ListElem_obj(le);
1044 GSimModule *sM;
1045 GWire *w;
1046 GNet *net;
1047
1048 if (SimInterface_lookupWire(si,name,&sM,&w,&net) != 0) {
1049 continue;
1050 }
1051
1052 sendSimCmd("$probe %s",name);
1053 SimInterface_addProbe(si,name,GNet_getNBits(net));
1054 }
1055
1056 TkGate.sortTraces = x;
1057 }
1058
1059 /*****************************************************************************
1060 *
1061 * Do post-scan simulator initialization
1062 *
1063 * Parameters:
1064 * si Simulator interface.
1065 *
1066 * Called after simulator has loaded circuit and reported that it is ready
1067 * to start simulation.
1068 *
1069 *****************************************************************************/
SimInterface_startUp(SimInterface * si)1070 static void SimInterface_startUp(SimInterface *si)
1071 {
1072 int i;
1073 const char *global_script;
1074
1075 DoTcl("Simulator::setupSecurity");
1076
1077 if (si->no_scope) {
1078 DoTcl("tkg_altStartup");
1079 return;
1080 }
1081
1082 DoTcl("Scope::post");
1083 GSimModule_initSwitches(si->sim_root);
1084 SimInterface_initClocks(si);
1085 SimInterface_initMemories(si);
1086 //unlink(si->simFileName);
1087 *si->simFileName = 0;
1088
1089 SimInterface_changeCurrentModule(TkGate.circuit->es->smod,0);
1090
1091 global_script = Tcl_GetVar(TkGate.tcl,"tkg_simInitScript",TCL_GLOBAL_ONLY);
1092 if (global_script && *global_script) {
1093 DoTclL("ScriptMgr::load",global_script,NULL);
1094 }
1095
1096 for (i = 0;i < TkGate.circuit->numInitScripts;i++) {
1097 DoTclL("ScriptMgr::load",TkGate.circuit->initScripts[i],NULL);
1098 }
1099
1100 BrkPtTable_sendAll(TkGate.circuit->c_breakpoints);
1101
1102 if (TkGate.saveTraces)
1103 SimInterface_addSavedProbes(si);
1104
1105 if (TkGate.circuit->simAutoStart) {
1106 DoTcl("tkg_simRun");
1107 // sendSimCmd("$go");
1108 }
1109 }
1110
1111 /*****************************************************************************
1112 *
1113 * Execute a tcl command under the current security policy.
1114 *
1115 *****************************************************************************/
SimInterface_doSanitizedTcl(char * cmd)1116 int SimInterface_doSanitizedTcl(char *cmd)
1117 {
1118 if (security_exec_level == 2) {
1119 DoTcl("%s",cmd);
1120 return 0;
1121 } else if (security_exec_level == 1) {
1122 char cmdName[STRMAX];
1123
1124 /* commands can not include a '[' character */
1125 if (strchr(cmd,'['))
1126 return -1;
1127
1128 if (sscanf(cmd,"%s",cmdName) != 1) return -1;
1129
1130
1131 DoTcl("VPD::isallowed %s",cmdName);
1132 if (Tcl_GetStringResult(TkGate.tcl)[0] != '1') return -1;
1133
1134 DoTcl(cmd);
1135 return 0;
1136 }
1137
1138 return 0;
1139 }
1140
1141 /*****************************************************************************
1142 *
1143 * Decode and report an error message from the simulator
1144 *
1145 * Parameters:
1146 * si Simulator interface object
1147 * level Level of error (0=warning, 1=error)
1148 * msg Encoded error message.
1149 *
1150 *****************************************************************************/
SimInterface_reportError(SimInterface * si,int level,const char * msg)1151 int SimInterface_reportError(SimInterface *si,int level,const char *msg)
1152 {
1153 char etype[STRMAX],text[STRMAX];
1154 char buf[STRMAX];
1155
1156 if (sscanf(msg,"%*s %s %[^\n]",etype,text) != 2)
1157 return -1;
1158
1159 if (strcmp(etype,"file") == 0) {
1160 Error_report(msg);
1161 } else if (strcmp(etype,"run") == 0) {
1162 char timeStr[STRMAX],msg[STRMAX];
1163 if (sscanf(text,"%s : %[^\n]",timeStr,msg) == 2) {
1164 char *p = buf;
1165 Error_decode(msg);
1166 p += sprintf(p,msgLookup("err.sim.run"), timeStr);
1167 sprintf(p," %s",msg);
1168 message(MC_MSGLOG|MC_URGENT,"%s",buf);
1169 } else {
1170 message(MC_MSGLOG|MC_URGENT,"[BADLY FORMATTED MESSAGE] %s",text);
1171 }
1172 } else if (strcmp(etype,"command") == 0) {
1173 Error_decode(text);
1174 sprintf(buf,"%s: %s",msgLookup("err.sim.cmd"),text);
1175 message(MC_MSGLOG|MC_URGENT,"%s",buf);
1176 } else {
1177 Error_decode(text);
1178 sprintf(buf,"Unknown Error Type: %s",text);
1179 message(MC_MSGLOG|MC_URGENT,"%s",buf);
1180 }
1181
1182 return 0;
1183 }
1184
1185 /*****************************************************************************
1186 *
1187 *
1188 *
1189 *****************************************************************************/
SimInterface_setSimMods(SimInterface * si)1190 void SimInterface_setSimMods(SimInterface *si)
1191 {
1192 List L;
1193 EditState *es;
1194 ListElem *E;
1195
1196 List_init(&L);
1197
1198 for (es = TkGate.circuit->es;es;es = es->parent)
1199 List_addToHead(&L,es);
1200
1201 E = List_first(&L);
1202 es = (EditState*) ListElem_obj(E);
1203 es->smod = si->sim_root;
1204 for (E = List_next(&L,E);E;E = List_next(&L,E)) {
1205 es = (EditState*) ListElem_obj(E);
1206 assert(es->inst);
1207 /* printf("smod = %s\n",es->inst->ename);*/
1208 es->smod = (GSimModule*)SHash_find(es->parent->smod->children,es->inst->ename);
1209 }
1210
1211 List_uninit(&L);
1212 }
1213
1214 /*****************************************************************************
1215 *
1216 * Show simulator startup message.
1217 *
1218 *****************************************************************************/
SimInterface_showStartMsg()1219 void SimInterface_showStartMsg()
1220 {
1221 time_t now;
1222 char *nowstr,*p;
1223
1224 time(&now);
1225 nowstr = ctime(&now);
1226 if (nowstr) {
1227 p = strrchr(nowstr,'\n');
1228 if (p) *p = 0;
1229 DoTcl("InfoPanel::log \"Starting simulator at %s.\" -noshow 1 -color blue",nowstr);
1230 } else
1231 DoTcl("InfoPanel::log \"Starting simulator at unknown time.\" -noshow 1 -color blue");
1232 }
1233
1234 /*****************************************************************************
1235 *
1236 * Start the simulator
1237 *
1238 * Parameters:
1239 * si Simulation interface to use.
1240 *
1241 *****************************************************************************/
SimInterface_begin(SimInterface * si)1242 void SimInterface_begin(SimInterface *si)
1243 {
1244 EditState *es;
1245 Circuit *c = TkGate.circuit;
1246
1247 SimInterface_showStartMsg();
1248 editstate_makeRootAtTop(&c->es);
1249 es = c->es;
1250
1251 getSimTempFile(si->simFileName); /* Get a temp file for circuit */
1252
1253 if (VerilogWriteModules(si->simFileName,VSO_ALLMODS|VSO_NOHDLCHECK) != 0) { /* Save circuit to send to simulator */
1254 /* Could not save temporary file '%s' for simulator (disc full?) */
1255 message(1,msgLookup("err.sim.badtmp"),si->simFileName);
1256 return;
1257 }
1258
1259 SimInterface_buildSimMods(si); /* Build the simulator hierarchy */
1260
1261 /*
1262 Check to see if the top module on the module stack is really the root
1263 circuit. If not, switch to the root circuit.
1264 */
1265 for (es = c->es;es->parent;es = es->parent);
1266 if (c->root_mod != es->env) {
1267 while (c->es)
1268 editstate_pop(&c->es);
1269 editstate_push(&c->es,c->root_mod,0);
1270 editstate_setCurrent(c->es);
1271
1272 /* Simulation mode requires root module at top of edit stack. */
1273 message(0,msgLookup("msg.sim.chgtoroot"));
1274 }
1275
1276 /*
1277 Pop modules that don't have a concrete gate associated with them.
1278 */
1279 if (c->es->parent && !c->es->inst) {
1280 while (c->es->parent && !c->es->inst)
1281 editstate_pop(&c->es);
1282 editstate_setCurrent(c->es);
1283 message(0,msgLookup("msg.sim.nogatemod")); /* Simulation mode requires concrete module stack. */
1284 }
1285
1286 SimInterface_setSimMods(si);
1287
1288 /* Start simulator with specified file */
1289 switch (c->c_tvMode) {
1290 case TV_NONE :
1291 DoTcl("tkg_startSim %s none",
1292 si->simFileName,
1293 c->c_startup,SimInterface_unitsToStr(c->c_startupUnits)
1294 );
1295 break;
1296 case TV_AFTER :
1297 DoTcl("tkg_startSim %s %g%s",
1298 si->simFileName,
1299 c->c_startup,SimInterface_unitsToStr(c->c_startupUnits)
1300 );
1301 break;
1302 case TV_ALL :
1303 default:
1304 DoTcl("tkg_startSim %s 0ns", si->simFileName);
1305 break;
1306 }
1307
1308 si->active = 1;
1309
1310 FlagRedraw();
1311 }
1312
1313 /*
1314 Missing cleanup code for simulator module stuff
1315 */
SimInterface_end(SimInterface * si)1316 void SimInterface_end(SimInterface *si)
1317 {
1318 GScope_saveProbes(Scope);
1319
1320 si->active = 0;
1321 // if (*si->simFileName)
1322 //unlink(si->simFileName);
1323 DoTcl("tkg_endSim");
1324 DoTcl("Scope::unpost");
1325 #if 0
1326 SimInterface_flushBreaks(si);
1327 #endif
1328 }
1329
SimInterface_findPathToModule_aux(GCElement ** path,int depth,GModuleDef * p,GModuleDef * targetModule)1330 static int SimInterface_findPathToModule_aux(GCElement **path,
1331 int depth,
1332 GModuleDef *p,
1333 GModuleDef *targetModule)
1334 {
1335 HashElem *e;
1336
1337 /*
1338 * Found a path to the target module
1339 */
1340 if (p == targetModule)
1341 return depth;
1342
1343 for (e = Hash_first(p->m_gates);e;e = Hash_next(p->m_gates,e)) {
1344 GCElement *g = (GCElement*) HashElem_obj(e);
1345
1346 if (GCElement_isModule(g) && g->u.block.moduleName && *g->u.block.moduleName) {
1347 GModuleDef *child = env_findModule(g->u.block.moduleName);
1348 if (child) {
1349 int r = SimInterface_findPathToModule_aux(path,depth+1,child,targetModule);
1350 if (r > 0) {
1351 path[depth] = g;
1352 return r; /* Found a path */
1353 }
1354 }
1355 }
1356 }
1357
1358 /*
1359 * Did not find a path.
1360 */
1361 return -1;
1362 }
1363
SimInterface_findPathToModule(char * path,GModuleDef * m)1364 int SimInterface_findPathToModule(char *path,GModuleDef *m)
1365 {
1366 GCElement *mpath[MODULE_PATH_MAX];
1367 char *p;
1368 int n,i;
1369
1370 n = SimInterface_findPathToModule_aux(mpath, 0, TkGate.circuit->root_mod, m);
1371
1372 if (n <= 0)
1373 return -1;
1374
1375 sprintf(path,"/<%s>",GModuleDef_getName(TkGate.circuit->root_mod));
1376 p = path+strlen(path);
1377
1378 for (i = 0;i < n;i++) {
1379 GModuleDef *pathMod = env_findModule(mpath[i]->u.block.moduleName);
1380 sprintf(p,"/%s<%s>",mpath[i]->ename,GModuleDef_getName(pathMod));
1381 p += strlen(p);
1382 }
1383
1384 return 0;
1385 }
1386
SimInterface_navigateToModule(EditState ** es,const char * path)1387 void SimInterface_navigateToModule(EditState **es,const char *path)
1388 {
1389 char pathbuf[STRMAX],*t;
1390 char name[STRMAX];
1391 GModuleDef *M = TkGate.circuit->root_mod;
1392
1393 if (strncmp(path,"/<",2) != 0) {
1394 #if 1
1395 message(1,msgLookup("err.nojump"));
1396 #else
1397 M = env_findModule(path);
1398 if(!M) {
1399 message(1,msgLookup("err.nojump"));
1400 return;
1401 }
1402
1403 if (SimInterface_findPathToModule(pathbuf, M) < 0) {
1404 message(1,msgLookup("err.nojump"));
1405 return;
1406 }
1407
1408 if (*pathbuf != '/') {
1409 message(1,msgLookup("err.nojump"));
1410 return;
1411 }
1412
1413 //
1414 // Try again with full path
1415 //
1416 SimInterface_navigateToModule(es,pathbuf);
1417 #endif
1418 return;
1419 }
1420
1421 /*
1422 * Pop up to root module
1423 */
1424 while (*es && (*es)->env != M)
1425 editstate_pop(es);
1426
1427 strcpy(pathbuf,path);
1428 t = strtok(pathbuf,"/");
1429 for (t = strtok(0,"/");t;t = strtok(0,"/")) {
1430 if (sscanf(t,"%[^<]",name) == 1) {
1431 GCElement *g = GModuleDef_findGate(M,name);
1432
1433 if (GCElement_isModule(g) && g->u.block.moduleName && *g->u.block.moduleName) {
1434 M = env_findModule(g->u.block.moduleName);
1435 if (M)
1436 editstate_push(es,M,g);
1437 }
1438 }
1439 }
1440 editstate_setCurrent(*es);
1441
1442 // DoTcl("BlockTree::setActive %s",path);
1443
1444 FlagRedraw();
1445 }
1446
SimInterface_unitsToStr(int u)1447 const char* SimInterface_unitsToStr(int u)
1448 {
1449 if (u >= 0 && u < NUM_UNITS)
1450 return unitStrings[u];
1451 else
1452 return "bs";
1453 }
1454
SimInterface_strToUnits(const char * s)1455 int SimInterface_strToUnits(const char *s)
1456 {
1457 int u;
1458
1459 for (u = 0;u < NUM_UNITS;u++)
1460 if (strcmp(s,unitStrings[u]) == 0)
1461 return u;
1462
1463 return -1;
1464 }
1465
1466 /*****************************************************************************
1467 *
1468 * Convert a time in epochs to a time with units after it using the timescale
1469 * setting returned from the simulator.
1470 *
1471 *****************************************************************************/
SimInterface_formatTime(SimInterface * si,char * buf,simtime_t t)1472 char *SimInterface_formatTime(SimInterface *si, char *buf,simtime_t t)
1473 {
1474 double n = (double)t*si->si_tsmult/(double)si->si_precision;
1475 int units = si->si_units;
1476
1477
1478 while (n > 1000 && units > 0) {
1479 n /= 1000;
1480 units--;
1481 }
1482
1483 sprintf(buf,"%g%s",n,SimInterface_unitsToStr(units));
1484
1485 return buf;
1486 }
1487
1488 /*****************************************************************************
1489 *
1490 * Commands received from the simulator are processed here.
1491 *
1492 * Parameters:
1493 * si Simulator interface object
1494 * C Command to be processed
1495 *
1496 * Commands:
1497 * comment Ignore any text on this line
1498 * echo Echo text on this line to the log
1499 * ok Indicates circuit was read and is ready to be simulated
1500 * error_exit Indicates there was an error in the circuit while reading
1501 * showprobe Request from simulator to place a probe
1502 * hideprobe Request from simulator to hide a probe
1503 * valueof Indicates the value of a signal changed
1504 * tell Tell a listener that state has changed on a monitored net.
1505 * netdelay -currently not used-
1506 * cpath -currently not used-
1507 * cdone -currently not used-
1508 * stats Indicates statistics about a circuit.
1509 * badscript Indicates an error occured in a simulation script.
1510 * endscript Indicates a script has completed
1511 * break Indicates that simulation has stopped at a breakpoint.
1512 * stop Indicates that simulation has stopped.
1513 * post Requests that a VPD be posted
1514 * exec Requests that a tcl command be executed
1515 * error Reports an error
1516 * warning Reports a warning
1517 *
1518 *****************************************************************************/
SimInterface_command(SimInterface * si,const char * C)1519 int SimInterface_command(SimInterface *si,const char *C)
1520 {
1521 char buf[STRMAX],buf2[STRMAX],buf3[STRMAX],buf4[STRMAX];
1522 int a1,a2;
1523 simtime_t t = 0;
1524 unsigned u1,u2,u3,u4;
1525
1526 if (strncmp(C,"stop",4) == 0) {
1527 *buf = 0;
1528 }
1529
1530 while (*C == ' ')C++;
1531
1532 if (strncmp(C,"comment",7) == 0) { /* Ignore comments from simulator */
1533 return 0;
1534 } else if (sscanf(C,"echo %[^\n]",buf) == 1) {
1535 DoTcl("InfoPanel::log \"%s\"",quoteChars(buf2,buf,TCL_SPECIALCHARS));
1536 return 0;
1537 } else if (strncmp(C,"echo",4) == 0) {
1538 DoTcl("InfoPanel::log \"\"");
1539 return 0;
1540 } else if (sscanf(C," zoom %d",&a1) == 1) { /* Set zoom factor */
1541 DoTcl(".scope.main.frame.canvas setzoom %d",-a1);
1542 } else if (sscanf(C,"ok %d %s / %d %s",&a1,buf,&a2,buf2) == 4) { /* Simulator loaded file and is ready to go */
1543 si->si_tsmult = a1;
1544 si->si_units = SimInterface_strToUnits(buf);
1545 si->si_precision = Timescale_parse(a1,buf)/Timescale_parse(a2,buf2);
1546 if (si->si_precision == 0) si->si_precision = 1;
1547 Error_close();
1548 SimInterface_startUp(si);
1549 } else if (strncmp(C,"error_exit",10) == 0) { /* The simulator exited on an error */
1550 DoTcl("ErrBox::hadFatalErrors");
1551 Error_close();
1552 tkgate_setMajorMode(MM_EDIT);
1553 } else if (sscanf(C," showprobe %s %d", buf, &a1) == 2) { /* Probe set from script */
1554 SimInterface_addProbe(si,buf,a1);
1555 } else if (sscanf(C," hideprobe %s", buf) == 1) { /* Probe hidden from script */
1556 SimInterface_delProbe(si,buf);
1557 } else if (sscanf(C," valueof %s %s @ %llu", /* The value of a net has changed */
1558 buf,buf2,&t) == 3) {
1559 if (GScope_findTrace(Scope,buf)) {
1560 Scope_stepTo(t);
1561 Scope_setValue(buf,buf2);
1562 }
1563 } else if (sscanf(C," tell $queue %s %s @ %llu",buf,buf2,&t) == 3) { /* The value of a net has been requested */
1564 DoTclL("VPD::qdata",buf,buf2,NULL);
1565 } else if (sscanf(C," tell $show %s %s",buf,buf2) == 2) { /* The value of a net has been requested */
1566 sprintf(buf3,"%s=%s",buf,buf2);
1567 Tcl_SetVar(TkGate.tcl,"tkg_simDisplayedVal",
1568 buf3,TCL_GLOBAL_ONLY);
1569 } else if (sscanf(C," tell $led:%s %s %s @ %llu",buf3,buf,buf2,&t) == 4) { /* Set value of an led */
1570 strcat(buf,".");
1571 strcat(buf,buf3);
1572 SimInterface_setLed(si,buf,buf2);
1573 } else if (sscanf(C," tell $switch:%s %*s %s @ %llu",buf,buf2,&t) == 3) { /* Set value of an switch */
1574 SimInterface_setSwitch(si,buf,buf2);
1575 } else if (sscanf(C," netdelay %s %d %d",buf,&a1,&a2) == 3) { /* Net delay values */
1576 cpath_registerNetDelay(buf,a1,a2);
1577 } else if (sscanf(C," cpath %d %[^\n]",&a1,buf) == 2) { /* Critical path */
1578 DoTcl("tkg_cpathAdd %d {%s}",a1,buf);
1579 } else if (strncmp(C,"cdone",5) == 0) { /* End of critical path data */
1580 DoTcl("tkg_cpathEnd");
1581 } else if (sscanf(C," stats area=%d static_power=%d", /* Circuit statistics */
1582 &si->area,&si->staticPower) == 2) {
1583 message(0,"Estimated area=%d.",si->area,si->staticPower);
1584 } else if (sscanf(C," badscript %s",buf) == 1) { /* Report breakpoint/script syntax error */
1585 if (sscanf(buf,"break:%d",&a1) == 1)
1586 BrkPtTable_error(TkGate.circuit->c_breakpoints,a1);
1587 else if (sscanf(buf,"script:%d",&a1) == 1) {
1588 DoTcl("ScriptMgr::setState %d -1",a1);
1589 DoTcl("ScriptMgr::viewScriptFile script:%d",a1);
1590 }
1591 } else if (sscanf(C," endscript %s",buf) == 1) { /* Report script termination */
1592 if (sscanf(buf,"script:%d",&a1) == 1)
1593 DoTcl("ScriptMgr::setState %d 1",a1);
1594 } else if (sscanf(C," break %d %s",&a1,buf) == 2) { /* Simulator hit a breakpoint */
1595 BrkPtTable_activate(TkGate.circuit->c_breakpoints,a1,buf);
1596 } else if (sscanf(C," time @ %llu",&t) == 1) { /* Update current time */
1597 } else if (sscanf(C," go @ %llu",&t) == 1) { /* Simulator is in run mode */
1598 DoTcl("tkg_runLogo");
1599 DoTcl("Simulator::startTimeUpdates");
1600 DoTcl("set ::simulatorState go");
1601 } else if (sscanf(C," stop @ %llu",&t) == 1) { /* Simulator is in pause mode */
1602 if (si->no_scope) return 0;
1603
1604 if (Scope->s_time != t)
1605 DoTcl("tkg_stepLogo");
1606 DoTcl("Simulator::stopTimeUpdates");
1607 DoTcl("tkg_pauseLogo");
1608 Scope_stepTo(t);
1609 DoTcl("set ::simulatorState stop");
1610 } else if (sscanf(C," readystop @ %llu",&t) == 1) { /* Simulator is in paused and waiting for a net change */
1611 if (si->no_scope) return 0;
1612
1613 if (Scope->s_time != t)
1614 DoTcl("tkg_stepLogo");
1615 DoTcl("Simulator::stopTimeUpdates");
1616 DoTcl("tkg_pauseLogo");
1617 Scope_stepTo(t);
1618 DoTcl("set ::simulatorState readystop");
1619 } else if (sscanf(C," post %[^\n]",buf) == 1) { /* Post a VPD */
1620 int numArgs;
1621 const char **args;
1622
1623 if (Tcl_SplitList(TkGate.tcl, buf, &numArgs, &args) == TCL_OK) {
1624 DoTclV("VPD::post",numArgs,args);
1625 Tcl_Free((char*)args);
1626 }
1627 } else if (sscanf(C," netinfo %s %*s [%u:%u] [%u:%u]",buf,&u1,&u2,&u3,&u4) == 5) { /* */
1628 DoTcl("MemView::configMemory %s %d %d %d",buf,u1-u2+1,u3,u4);
1629 } else if (sscanf(C," memory %s %u : %[^\n]",buf,&u1,buf2) == 3) { /* */
1630 DoTcl("MemView::setData %s %u %s",buf,u1,buf2);
1631 } else if (sscanf(C," memory-addr %s %u %s %s @ %llu",buf,&u1,buf2,buf3,&t) == 5) { /* */
1632 DoTcl("MemView::setAccessAddr %s %u %s %s %llu",buf,u1,buf2,buf3,t);
1633 } else if (sscanf(C," exec %[^\n]",buf) == 1) { /* Create a tty window */
1634 if (SimInterface_doSanitizedTcl(buf) < 0) {
1635 message(MC_MSGLOG|MC_URGENT,msgLookup("err.protexec"),buf);
1636 }
1637 } else if (sscanf(C," warning %s",buf) == 1) { /* An error in a simulator input file. */
1638 SimInterface_reportError(si,0,C);
1639 } else if (sscanf(C," error %s",buf) == 1) { /* An error in a simulator input file. */
1640 SimInterface_reportError(si,1,C);
1641 } else if (sscanf(C," scripterror %s %s %s : %[^\n]",buf,buf2,buf3,buf4) == 4) { /* An error in a script file. */
1642 Error_decode(buf4);
1643 DoTclL("ScriptMgr::reportError",buf,buf2,buf3,buf4,NULL);
1644 } else if (sscanf(C," embeddedscript begin %s %u",buf,&u1) == 2) { /* Beginning of an embedded script. */
1645 Error_scriptBegin(buf,u1);
1646 } else if (sscanf(C," embeddedscript end %s %u",buf,&u1) == 2) { /* End of an embedded script. */
1647 Error_scriptEnd(buf,u1);
1648 }
1649
1650 if (t > 0) {
1651 DoTcl("set ::currentSimTime [gat_formatTime %llu]",t);
1652 }
1653
1654 return 0;
1655 }
1656
1657
1658