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