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 #include <stdlib.h>
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <string.h>
22 #include <assert.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <pwd.h>
26 #include "tkgate.h"
27 #include "yybasic.h"
28 #include "vgrammar.h"
29 #include "ycmalloc.h"
30 
31 /*
32  * New built-in gate naming convension.
33  *
34  * _GGAND3B4D5 g1 (.Z(w1), .I0({{4}{w2}}), .I1(w3), .I2(w4));
35  *
36  * Here _GG is the prefix for built-in gates. "AND" is the base name
37  * of the gate, "3" indicates the number of inputs (or outputs depending
38  * on type) and B4 indicates the base bit width.  A leading "N" in front
39  * of the base name means the output is inverted.  For gates with multiple
40  * outputs, no qualifier means no inversion, and a qualifier such as "PN"
41  * means the first output is non-inverted and the second is inverted.
42  *
43  */
44 
45 int yyparse();
46 void BeginVR();
47 
48 #ifndef yyrestart
49 void yyrestart(FILE*);
50 #endif
51 
52 #define HDLTEXTBLOCKSIZE 512
53 
54 #define WENDSBLOCKSIZE	64
55 
56 GModuleDef *topModule = 0;
57 
58 int VerilogErrorCount = 0;
59 
60 
61 Encoder *parserEncoder = 0;
62 
63 static char *VerilogReadPrefix = 0;
64 static int translateDemux = 0;
65 
66 /*
67  * Table of previous versions.  As of version 1.6, the table includes only
68  * versions for which the flags change.  If the flag after the version name is
69  * non-zero, then the save file is incompatable with the current version.
70  */
71 VersionDef VERSIONS[]={
72   {TKGATE_FULL_VERSION,0},
73   {"2.0-b5",	VF_NOBACK},
74   {"1.9",	VF_NOBACK},
75   {"1.6h",	VF_NOBACK},
76   {"1.5c",	VF_NOBACK},
77   {"0.5",	VF_OLD}
78 };
79 int numVersions = sizeof(VERSIONS)/sizeof(VERSIONS[0]);
80 
81 /*
82  * Version where extender bar features was added.
83  */
84 static char *extBarVersion = "1.6i";
85 
86 /*
87  * Version where demux behavior was changed.
88  */
89 static char *newDemuxVersion = "2.0-b6";
90 
91 /*
92  * Version where net name display on nets was added.
93  */
94 static char *showSwitchNetsVersion = "2.0-b7";
95 
96 /*****************************************************************************
97  *
98  *   Data structure used to keep intermediate parser state.
99  *
100  *****************************************************************************/
101 static struct {
102   Version	gate_ver;	/* Version number of tkgate */
103   Version	ver;		/* Version number of current file */
104 
105   GModuleDef	*mod;		/* Current module being processed */
106   GNet		*net;		/* Current net being processed */
107   GCElement	*gate;		/* Current gate being processed */
108   int		vnum;		/* Variant number of gate */
109   GWire		*wire;
110   GWireNode	*node;
111 
112   List		*modHPorts;	/* Module ports that are in the #() list */
113   List		*modPorts;	/* Standard module ports */
114 
115 
116   char		invSpec[STRMAX]; /* Output inverter specification */
117 
118   int		del_mod;	/* Module is marked for deletion (e.g., top-level of library). */
119   List		*del_list;	/* List of modules scheduled for deletion */
120 
121   List		*mparm_list;	/* List of module parameters */
122 
123   int		numAllocedWends;/* Number of wends elements allocated */
124   GWire		**wends;	/* Array of wire ends */
125   int		numWEnds;	/* Number of wire ends */
126 
127   SHash		*netWEnds;
128 
129   int		numAllocedgPin;	/* Number of gPin/gNet/gComp elements allocated */
130   const char	**gPin;		/* Array of pin names */
131   GNet		**gNet;		/* Array of net objects */
132   int		*gComp;		/* Array of complement flags */
133   int		numPins;	/* Number of pins */
134   int		pidx;		/* Current pin index */
135   unsigned	revPads;	/* Bit array of pads that should be reversed */
136 
137   const char	*libraryName;	/* Name of current library being loaded (0 if not loading library) */
138   const char	*fileName;	/* Name of current file */
139 
140   struct {			/* Current symbol icon */
141     GModSymbol	*ms;
142     int		which;		/* What type of icon is this 0=normal, 1=select */
143     int		N;		/* Number of bytes allocated */
144     int		x,y;
145     char	*data;		/* Data buffer */
146     char	*p;		/* Current position in buffer */
147   } icon;
148 
149   int		numRequires;	/* Number of required libraries */
150   char		**requires;	/* Array of required libraries */
151 
152   int		isInterface;	/* We are parsing an interface statement */
153 
154   int		didTimescale;	/* Default timescale has been set */
155 } cur = {{{0}}};
156 
157 NHash *modSymbolTable = 0;
158 
cur_initModule()159 static void cur_initModule()
160 {
161   cur.net = 0;
162   cur.gate = 0;
163   cur.wire = 0;
164   cur.node = 0;
165   cur.del_mod = 0;
166   cur.numWEnds = 0;
167   cur.numPins = 0;
168   cur.wends = 0;
169   cur.gPin = 0;
170   cur.gNet = 0;
171   cur.gComp = 0;
172   cur.vnum = 0;
173   cur.netWEnds = new_SHash();
174 }
175 
cur_endModule()176 static void cur_endModule()
177 {
178   if (cur.netWEnds) delete_SHash(cur.netWEnds);
179 }
180 
cur_initCircuit()181 static void cur_initCircuit()
182 {
183   memset(&cur,0,sizeof(cur));
184 }
185 
186 /*
187  * Ensure that element n of wends has been allocated.
188  */
cur_wends_extend(int n)189 static void cur_wends_extend(int n)
190 {
191   if (!cur.wends) {
192     cur.wends = (GWire**)yc_calloc(WENDSBLOCKSIZE,sizeof(GWire*),ALGN_WORD);
193     cur.numAllocedWends = WENDSBLOCKSIZE;
194   }
195   if (n >= cur.numAllocedWends) {
196     while (n >= cur.numAllocedWends)
197       cur.numAllocedWends += WENDSBLOCKSIZE;
198     cur.wends = (GWire**)yc_realloc(cur.wends,
199 				    (cur.numAllocedWends - WENDSBLOCKSIZE)*sizeof(GWire*),
200 				    cur.numAllocedWends*sizeof(GWire*),ALGN_WORD);
201   }
202 }
203 
cur_gpin_extend(int n)204 static void cur_gpin_extend(int n)
205 {
206   if (!cur.gPin) {
207     cur.gPin = (const char**)yc_calloc(WENDSBLOCKSIZE,sizeof(char*),ALGN_WORD);
208     cur.gNet = (GNet**)yc_calloc(WENDSBLOCKSIZE,sizeof(GNet*),ALGN_WORD);
209     cur.gComp = (int*)yc_calloc(WENDSBLOCKSIZE,sizeof(int),ALGN_WORD);
210     cur.numAllocedgPin = WENDSBLOCKSIZE;
211   }
212   if (n >= cur.numAllocedgPin) {
213     while (n >= cur.numAllocedgPin)
214       cur.numAllocedgPin += WENDSBLOCKSIZE;
215     cur.gPin = (const char**)yc_realloc(cur.wends,
216 					(cur.numAllocedgPin-WENDSBLOCKSIZE)*sizeof(char*),
217 					cur.numAllocedgPin*sizeof(char*),ALGN_WORD);
218     cur.gNet = (GNet**)yc_realloc(cur.gNet,
219 				  (cur.numAllocedgPin-WENDSBLOCKSIZE)*sizeof(GNet*),
220 				  cur.numAllocedgPin*sizeof(GNet*),ALGN_WORD);
221     cur.gComp = (int*)yc_realloc(cur.gComp,
222 				 (cur.numAllocedgPin-WENDSBLOCKSIZE)*sizeof(int),
223 				 cur.numAllocedgPin*sizeof(int),ALGN_WORD);
224   }
225 }
226 
spread(unsigned M,unsigned x)227 static unsigned spread(unsigned M,unsigned x)
228 {
229   unsigned R = 0;
230   int i,j;
231 
232   j = 0;
233   for (i = 0;i < 32;i++)
234     if ((M & (1 << i)) && (x & (1 << j++)))
235       R |= (1 << i);
236 
237   return R;
238 }
239 
cur_endFile()240 static void cur_endFile()
241 {
242   cur.libraryName = 0;
243   cur.fileName = 0;
244 
245   if (cur.del_list) {
246     ListElem *le;
247 
248     for (le = List_first(cur.del_list);le;le = List_next(cur.del_list, le)) {
249       GModuleDef *M = (GModuleDef*) ListElem_obj(le);
250       delete_GModuleDef(M);
251     }
252 
253     delete_List(cur.del_list);
254   }
255   cur.del_list = 0;
256 }
257 
cur_scheduleModDelete(GModuleDef * M)258 static void cur_scheduleModDelete(GModuleDef *M)
259 {
260   if (!cur.del_list)
261     cur.del_list = new_List();
262   List_addToTail(cur.del_list, M);
263 }
264 
265 
VerilogLoadRequired(EditState ** es)266 int VerilogLoadRequired(EditState **es)
267 {
268   int n = cur.numRequires;
269   char **requires = cur.requires;
270   int i;
271 
272   cur.numRequires = 0;
273   cur.requires = 0;
274 
275   if (TkGate.tcl) {
276     for (i = 0;i < n;i++) {
277       if (VerilogOpenLibrary(requires[i]) < 0) {
278 	message(1,msgLookup("err.badlibopen"),requires[i]);	/* Unable to open library file '%s'. */
279       }
280       free(requires[i]);
281     }
282     free(requires);
283   }
284 
285   return 0;
286 }
287 
288 
289 /*****************************************************************************
290  *
291  * Load a new circuit from the named file.
292  *
293  * Parameters:
294  *      **es		The current editor state.
295  *      name		Name of circuit file to load.
296  *
297  *
298  *
299  *****************************************************************************/
VerilogOpen(EditState ** es,const char * name,int append)300 int VerilogOpen(EditState **es,const char *name,int append)
301 {
302   FILE *f;
303   char buf1[STRMAX];
304   extern int click_count;
305 
306   if (!(f = fopen(name,"r")))
307     return -1;
308 
309   click_count = 0;
310 
311   strcpy(buf1,name);
312   cur_initCircuit();
313   cur.fileName = buf1;
314   cur.libraryName = 0;
315   translateDemux = 0;
316 
317   VerilogReadPrefix = 0;
318   if (!append) {
319     Circuit_unloadAllLibraries(TkGate.circuit);
320     editstate_flushModules(es);
321     Circuit_clear();
322     Circuit_initOptions(TkGate.circuit);
323     topModule = 0;
324   } else
325     topModule = TkGate.circuit->root_mod;
326   modSymbolTable = new_NHash_noob();
327 
328   ycSetDefaultModuleType(HDLMODULE);
329 
330   ycFileName = name;
331   ycLineNumber = 1;
332   parserEncoder = Circuit_getLoadFileEncoder(TkGate.circuit);
333 #if LOCALE_DEBUG
334   printf("parserEncoding <%s> to <%s>\n",TkGate.locale->l_encVerilog, CE_UTF8);
335 #endif
336   yc_setup();
337   BeginVR();
338   yyrestart(f);
339   yc_pushpool();
340   yyparse();
341   yc_poppool();
342   fclose(f);
343 
344   delete_NHash(modSymbolTable);
345 
346   if (!topModule)
347     topModule = env_findAdd("main",1);
348 
349   editstate_push(es,topModule,0);
350   editstate_setCurrent(*es);
351   TkGate.circuit->root_mod = (*es)->env;
352   modint_deleteInterface(TkGate.circuit->root_mod);
353   DoTcl("BlockTree::openRoot");
354 
355   SetModified(MF_MODULE);
356 #if 0
357   env_updateMTCircuit();
358 #endif
359 
360   Circuit_setCurrentFileVersion(cur.ver.str);
361 
362   if (!TkGate.circuit->title) {
363     char *p = strrchr(cur.fileName,'/');
364     Circuit_setTitle(p ? (p+1) : cur.fileName);
365   }
366 
367   cur_endFile();
368 
369   VerilogLoadRequired(es);
370 
371   DoTcl("LibraryMgr::loadBaseLibraries");
372 
373   return 0;
374 }
375 
376 /*****************************************************************************
377  *
378  * Load the named library
379  *
380  *****************************************************************************/
VerilogOpenLibrary(const char * name)381 int VerilogOpenLibrary(const char *name)
382 {
383   FILE *f;
384   char fileName[STRMAX];
385   char libraryName[STRMAX];
386   char *p;
387 
388   /*
389    * Remove directory path and extension from library name.
390    */
391   strcpy(fileName,name);
392   strcpy(libraryName,name);
393   p = strrchr(libraryName,'/');
394   if (p) memmove(libraryName,p+1,strlen(p));
395   p = strrchr(libraryName,'.');
396   if (p) *p = 0;
397 
398   /*
399    * Library is already loaded.
400    */
401   if (SHash_find(TkGate.libraries,libraryName))
402     return TCL_OK;
403 
404   /*
405    * Register library as loaded.
406    */
407   SHash_insert(TkGate.libraries,libraryName,(void*)1);
408 
409   /*
410    * Look up filename for library.
411    */
412   if (*name != '/') {
413     DoTclL("findLibraryFile",name,NULL);
414     name = Tcl_GetStringResult(TkGate.tcl);
415     if (!*name) {
416       SHash_remove(TkGate.libraries,libraryName);
417       return -1;
418     }
419   }
420 
421   if (!(f = fopen(name,"r"))) {
422     SHash_remove(TkGate.libraries,libraryName);
423     return -1;
424   }
425 
426   VerilogReadPrefix = 0;
427 
428   ob_touch(TkGate.circuit);
429 
430   /*
431    * Set file name and library names.
432    */
433   cur_initCircuit();
434   cur.fileName = fileName;
435   cur.libraryName = libraryName;
436   translateDemux = 0;
437 
438   topModule = 0;
439   modSymbolTable = new_NHash_noob();
440 
441   ycSetDefaultModuleType(HDLMODULE);
442 
443   ycFileName = name;
444   ycLineNumber = 1;
445   parserEncoder = getEncoder(CE_UTF8,TkGate.locale->l_encVerilog);
446 #if LOCALE_DEBUG
447   printf("parserEncoding <%s> to <%s>\n",TkGate.locale->l_encVerilog,CE_UTF8);
448 #endif
449   yc_setup();
450   BeginVR();
451   yyrestart(f);
452   yc_pushpool();
453   yyparse();
454   yc_poppool();
455   fclose(f);
456 
457   delete_NHash(modSymbolTable);
458 
459   SetModified(MF_MODULE);
460 
461   cur_endFile();
462 
463   return 0;
464 }
465 
yyerror(const char * err,...)466 void yyerror(const char *err,...)
467 {
468   char buf[STRMAX];
469   extern int quietMode;
470 
471   va_list ap;
472 
473   VerilogErrorCount++;
474 
475   va_start(ap, err);
476 
477   if (TkGate.tcl) {
478     sprintf(buf,"tkg_verilogErr %s \"Line %d, ",ycFileName,ycLineNumber);
479     vsprintf(buf+strlen(buf),err,ap);
480     va_end(ap);
481     strcat(buf,"\"");
482     Tcl_Eval(TkGate.tcl,buf);
483   } else {
484     if (!quietMode) {
485       sprintf(buf,"%s,%d: ",ycFileName,ycLineNumber);
486       vsprintf(buf+strlen(buf),err,ap);
487       printf("%s\n",buf);
488     }
489   }
490 }
491 
492 /*****************************************************************************
493  *   Functions called by parser to construct modules
494  *****************************************************************************/
ParseVersion(const char * version,Version * V)495 int ParseVersion(const char *version,Version *V)
496 {
497   char p,x;
498   int n;
499 
500   if (*version == 'V') version++;	/* Ignore leading V if present */
501 
502   strncpy(V->str,version,sizeof(V->str));
503   V->str[sizeof(V->str)-1] = 0;
504   V->alpha = V->beta = 0;
505   V->revision = 0;
506 
507   if (sscanf(version,"%d.%d-uog",&V->major,&V->minor) == 2) {
508     return 0;
509   } else if (sscanf(version,"%d.%d.%d-a%d",&V->major,&V->minor,&V->revision,&V->alpha) == 4) {
510     return 0;
511   } else if (sscanf(version,"%d.%d.%d-b%d",&V->major,&V->minor,&V->revision,&V->beta) == 4) {
512     return 0;
513   } else if (sscanf(version,"%d.%d.%d",&V->major,&V->minor,&V->revision) == 3) {
514     return 0;
515   } else if (sscanf(version,"%d.%d-a%d",&V->major,&V->minor,&V->alpha) == 3 && V->major >= 2) {
516     return 0;
517   } else if (sscanf(version,"%d.%d-b%d",&V->major,&V->minor,&V->beta) == 3 && V->major >= 2) {
518     return 0;
519   } else if (sscanf(version,"%d.%d-rc%d",&V->major,&V->minor,&V->rc) == 3 && V->major >= 2) {
520     return 0;
521   }
522 
523   /*
524    * Handle pre-2.0 version numbers that may use letters for releases
525    */
526   n = sscanf(version,"%d.%d%c%c",&V->major,&V->minor,&p,&x);
527   switch (n) {
528   case 3 :
529     V->revision = p - 'a';
530     break;
531   case 2 :
532     V->revision = 0;
533     break;
534   default :
535     return -1;
536   }
537 
538   return 0;
539 }
540 
541 /*
542   Compare versions
543  */
VersionCmp(Version * V1,Version * V2)544 int VersionCmp(Version *V1,Version *V2)
545 {
546   if (V1->major < V2->major) return -1;
547   if (V1->major > V2->major) return 1;
548 
549   if (V1->minor < V2->minor) return -1;
550   if (V1->minor > V2->minor) return 1;
551 
552   if (V1->revision < V2->revision) return -1;
553   if (V1->revision > V2->revision) return 1;
554 
555   if (V1->beta == 0 && V1->alpha == 0) {
556     if (V2->beta || V2->alpha) return 1;
557   }
558 
559   if (V2->beta == 0 && V2->alpha == 0) {
560     if (V1->beta || V1->alpha) return -1;
561   }
562 
563   if (V1->beta < V2->beta) return -1;
564   if (V1->beta > V2->beta) return 1;
565 
566   if (V1->alpha < V2->alpha) return -1;
567   if (V1->alpha > V2->alpha) return 1;
568 
569   return 0;
570 }
571 
572 /*****************************************************************************
573  *
574  * Check the version number to see if there are any special transformations we
575  * need to make on the circuit to bring it into compliance with the current
576  * version of tkgate.
577  *
578  *****************************************************************************/
VerSetSpecialLoadFeatures(Version * V)579 void VerSetSpecialLoadFeatures(Version *V)
580 {
581   Version x_V;
582 
583   /*
584    * Check version number to set default value for extension bar use.
585    */
586   ParseVersion(extBarVersion,&x_V);
587   if (VersionCmp(V,&x_V) >= 0)
588     TkGate.circuit->useExtBars = 1;
589   else
590     TkGate.circuit->useExtBars = 0;
591 
592   /*
593    * Set default value of show switches based on file version.  Enable
594    * feature only for files created after the feature was added.
595    */
596   ParseVersion(showSwitchNetsVersion,&x_V);
597   if (VersionCmp(V,&x_V) >= 0)
598     TkGate.circuit->showSwitchNets = 1;
599   else
600     TkGate.circuit->showSwitchNets = 0;
601 
602   /*
603    * If we are older than "newDemuxVersion", then translate and DEMUX
604    * components into OLDDEMUX components.
605    */
606   ParseVersion(newDemuxVersion,&x_V);
607   if (VersionCmp(V,&x_V) < 0)
608     translateDemux = 1;
609 }
610 
611 /*****************************************************************************
612  *
613  * Check the version of the save file to see if we need to do any special
614  * load features or issue warnings about old format save files.
615  *
616  *****************************************************************************/
VerCheckVersion(const char * version)617 void VerCheckVersion(const char *version)
618 {
619   int i;
620   unsigned flags = VF_UNKNOWN;
621   Version V;
622 
623   ParseVersion(VERSIONS[0].vd_name, &V);
624   cur.gate_ver = V;
625 
626   if (ParseVersion(version, &V) < 0) {
627     message(1,msgLookup("err.badversion"));
628     return;
629   }
630 
631   cur.ver = V;
632 
633   for (i = 0;i < numVersions;i++) {
634     Version x_V;
635 
636     ParseVersion(VERSIONS[i].vd_name, &x_V);
637 
638     if (VersionCmp(&x_V,&V) < 0)
639       break;
640 
641     flags = VERSIONS[i].vd_flags;
642   }
643 
644   /*
645    * Set the default module type to netlist if a version tag is present.  For >2.0 save files
646    * we expect all modules to be tagged anyway, but pre 2.0 save files were untagged and
647    * support only netlist modules.  If no version tag is present, this is a non-tkgate
648    * save file and we want to use the default of all modules being HDL.  This allows
649    * us to read a regular verilog file into tkgate.
650    */
651   ycSetDefaultModuleType(NETMODULE);
652 
653   /* Loaded file with outdated version... */
654   if ((flags & VF_OLD))
655     message(1,msgLookup("err.oldversion"),cur.fileName,version,VERSIONS[0].vd_name);
656 
657   /* Loaded file with no backwards compatability */
658   if ((flags & VF_NOBACK))
659     message(1,msgLookup("err.noback"),cur.fileName,version,VERSIONS[0].vd_name);
660 
661   /* Loaded file with future? version number */
662   if ((flags & VF_UNKNOWN))
663     message(1,msgLookup("err.futureversion"),cur.fileName,version,VERSIONS[0].vd_name);
664 
665   VerSetSpecialLoadFeatures(&V);
666 }
667 
668 /*****************************************************************************
669  *
670  * Apply a circuit property from the save file.
671  *
672  *
673  * Note, some properties are 'file' properties, some are 'circuit'
674  * properties and some are both.   If the file being loaded is a library,
675  * or append file, then circuit properties are ignored and only file properties
676  * are applied for the scope of the load operation.
677  *
678  *****************************************************************************/
VerCircuitProp(const char * name,const void * value,int ptype)679 void VerCircuitProp(const char *name,const void *value,int ptype)
680 {
681   int bad_type = 0;
682   int do_circ_props = (cur.libraryName == 0);
683   Circuit *c = TkGate.circuit;
684 
685 
686   if (strcmp(name,"title") == 0) {
687     if (ptype == TYPE_STR) {
688       if (do_circ_props) Circuit_setTitle(value);
689     } else
690       bad_type = 1;
691   } else if (strcmp(name,"locale") == 0) {
692     Locale *locale = SHash_find(TkGate.localeTable, value);
693     if (!locale) {
694       yyerror(msgLookup("err.yy.badpropvalue"),value,name);
695       locale = SHash_find(TkGate.localeTable, "en");
696     }
697     if (do_circ_props) Circuit_setLocale(c, locale);
698 #if LOCALE_DEBUG
699     printf("file locale is <%s>\n",locale->l_code);
700 #endif
701   } else if (strcmp(name,"encoding") == 0) {
702     if (do_circ_props) Circuit_setFileEncoding(c, value);
703     parserEncoder = Circuit_getLoadFileEncoder(c);
704 #if LOCALE_DEBUG
705     printf("parserEncoding <%s> to <%s>\n",value,CE_UTF8);
706 #endif
707   } else if (strcmp(name,"prefix") == 0) {
708     if (ptype == TYPE_STR)
709       VerilogReadPrefix = yc_strdup(value);
710     else
711       bad_type = 1;
712   } else if (strcmp(name,"discardChanges") == 0) {
713     if (ptype == TYPE_INT) {
714       if (do_circ_props) c->discardChanges = *(int*)value;
715     } else
716       bad_type = 1;
717   } else if (strcmp(name,"timingViolationMode") == 0) {
718     if (do_circ_props) c->c_tvMode = *(int*)value;
719   } else if (strcmp(name,"initTime") == 0) {
720     char units[STRMAX];
721     int ucode;
722 
723     if (sscanf(value,"%lf %s",&c->c_startup,units) != 2
724 	|| c->c_startup < 0
725 	|| (ucode = Timescale_unitsToCode(units)) < 0) {
726       yyerror(msgLookup("err.yy.badpropvalue"),value,name);
727       return;
728     }
729     c->c_startupUnits = Timescale_unitsToCode(units);
730 
731     //fprintf(f,"//: property initTime = \"%g %s\"\n",c->c_startup,
732     //  Timescale_codeToUnits(c->c_startupUnits));
733   } else if (strcmp(name,"technology") == 0) {
734     if (ptype == TYPE_STR) {
735       if (do_circ_props) {
736 	if (TkGate.defaultTech)
737 	  Tcl_Free(TkGate.defaultTech);
738 	TkGate.defaultTech = Tcl_Alloc(strlen(value)+1);
739 	strcpy(TkGate.defaultTech,(char*)value);
740 	DoTcl("catch { ToolBar::resetTechList }");
741       }
742     } else
743       bad_type = 1;
744 
745   } else if (strcmp(name,"useExtBars") == 0) {
746     if (ptype == TYPE_INT) {
747       if (do_circ_props) c->useExtBars = *(int*)value;
748     } else
749       bad_type = 1;
750   } else if (strcmp(name,"showSwitchNets") == 0) {
751     if (ptype == TYPE_INT) {
752       if (do_circ_props) c->showSwitchNets = *(int*)value;
753     } else
754       bad_type = 1;
755   } else if (strcmp(name,"simClockMode") == 0) {
756     if (ptype == TYPE_INT) {
757       if (do_circ_props) c->simClockMode = *(int*)value;
758     } else
759       bad_type = 1;
760   } else if (strcmp(name,"simClockName") == 0) {
761     if (ptype == TYPE_STR) {
762       if (do_circ_props) c->simClockName = ob_strdup(value);
763     } else
764       bad_type = 1;
765   } else if (strcmp(name,"simAutoStart") == 0) {
766     if (ptype == TYPE_INT) {
767       if (do_circ_props) c->simAutoStart = *(int*)value;
768     } else
769       bad_type = 1;
770   } else {
771     yyerror(msgLookup("err.yy.badprop"),name);
772   }
773 
774   if (bad_type)
775     yyerror(msgLookup("err.yy.baddata"),name);
776 }
777 
778 /*
779  * Called to set a symbol for a module instance
780  */
VerSetBlockSymbol(unsigned id)781 void VerSetBlockSymbol(unsigned id)
782 {
783   if (modSymbolTable) {
784     GModSymbol *ms = (GModSymbol*) NHash_find(modSymbolTable,id);
785     cur.gate = SymBlock_convert(cur.gate,ms,cur.mod,0);
786   }
787 }
788 
789 
790 /*
791  * Called when parsing a /symbolBegin (with non-zero id), or a /symbolEnd (with 0 id).
792  */
VerSymbol(unsigned id)793 void VerSymbol(unsigned id)
794 {
795   if (id) {
796     cur.icon.ms = new_GModSymbol();
797     if (modSymbolTable) {
798       NHash_insert(modSymbolTable,id,cur.icon.ms);
799     }
800   } else {
801     cur.icon.ms = 0;
802   }
803 }
804 
805 /*
806  * This function is called at the beginning and end of an icon definition block.
807  * At the end of the block it is called with all zeros.
808  */
VerSetIcon(const char * name,int N,int x,int y)809 void VerSetIcon(const char *name,int N,int x,int y)
810 {
811   GModSymbol *ms = cur.icon.ms;
812 
813   if (!ms) {
814     yyerror(msgLookup("err.yy.nosym"));
815     return;
816   }
817 
818   if (name) {
819     if (N < 0) N = 0;
820     N++;			/* space for end-of-string */
821 
822     cur.icon.N = N;
823     cur.icon.data = cur.icon.p = (char*) ob_malloc(N,"char*");
824     *cur.icon.p = 0;
825     cur.icon.x = x;
826     cur.icon.y = y;
827 
828     if (strcmp(name,"normal") == 0) {
829       cur.icon.which = 0;
830     } else if (strcmp(name,"select") == 0) {
831       cur.icon.which = 1;
832     } else {
833       yyerror(msgLookup("err.yy.badicon"),name);
834       return;
835     }
836   } else {
837     if (cur.icon.which == 0)
838       GModSymbol_setNormalIcon(ms,cur.icon.data,cur.icon.x,cur.icon.y);
839     else
840       GModSymbol_setSelectIcon(ms,cur.icon.data,cur.icon.x,cur.icon.y);
841 
842   }
843 }
844 
VerSymPort(const char * ptype,const char * name,int nbits,int x,int y,int orient)845 void VerSymPort(const char *ptype,const char *name,int nbits,int x,int y,int orient)
846 {
847   GModSymbol *ms = cur.icon.ms;
848   int t = IN;
849 
850   if (!ms) {
851     yyerror(msgLookup("err.yy.nosym"));
852     return;
853   }
854 
855   if (strcmp(ptype,"input") == 0)
856     t = IN;
857   else if (strcmp(ptype,"output") == 0)
858     t = OUT;
859   else if (strcmp(ptype,"inout") == 0)
860     t = TRI;
861 
862   GModSymbol_addPort(ms,new_GSymPort(name,x,y,t,orient,nbits));
863 }
864 
VerIconData(const char * data)865 void VerIconData(const char *data)
866 {
867   int L = strlen(data);
868 
869   if ( (cur.icon.p - cur.icon.data) + L+1 >= cur.icon.N) {
870     yyerror(msgLookup("err.yy.toomuchdata"));
871     return;
872   }
873 
874   cur.icon.p += sprintf(cur.icon.p,"%s\n",data);
875 }
876 
877 /*
878  * Set a module property
879  */
VerModuleProp(const char * name,const void * value,int ptype)880 void VerModuleProp(const char *name,const void *value,int ptype)
881 {
882   int bad_type = 0;
883 
884   if (strcmp(name,"prot_data") == 0) {
885     if (ptype == TYPE_INT) {
886       if (cur.mod)
887 	cur.mod->m_protData = *(int*)value;
888     } else
889       bad_type = 1;
890   } else if (strcmp(name,"prot_intf") == 0) {
891     if (ptype == TYPE_INT) {
892       if (cur.mod)
893 	cur.mod->m_protIntf = *(int*)value;
894     } else
895       bad_type = 1;
896   } else if (strcmp(name,"symbol") == 0) {
897     if (cur.mod) {
898       unsigned id = *(unsigned*)value;
899       GModSymbol *ms;
900 
901       /*
902        * Convert the reference to a symbol block.
903        */
904       if (cur.mod && modSymbolTable && cur.mod->m_interface) {
905 	GCElement *g = cur.mod->m_interface;
906 	ms = (GModSymbol*) NHash_find(modSymbolTable,id);
907 	if (ms)
908 	  g = SymBlock_convert(g,ms,TkGate.circuit->mid_mod,1);
909 	else
910 	  yyerror(msgLookup("err.yy.nosyminst"),id,g->ename,cur.mod->m_name);
911 	cur.gate = g;
912       }
913     }
914   } else if (strcmp(name,"pptype") == 0) {
915     if (ptype == TYPE_INT) {
916       if (cur.mod)
917 	cur.mod->m_pptype = *(int*)value;
918     } else
919       bad_type = 1;
920   } else {
921     yyerror(msgLookup("err.yy.badmodprop"),name);
922   }
923 
924   if (bad_type)
925     yyerror(msgLookup("err.yy.badmoddata"),name);
926 }
927 
928 
VerAddScript(const char * name)929 void VerAddScript(const char *name)
930 {
931   if (TkGate.tcl) {
932     DoTcl("gat_setCircProp -script \"%s\"",name);
933   }
934 }
935 
VerAddVLib(const char * name)936 void VerAddVLib(const char *name)
937 {
938   if (cur.numRequires == 0) {
939     cur.requires = (char**) malloc(8*sizeof(char*));
940   } else if ((cur.numRequires % 8) == 0) {
941     cur.requires = (char**) realloc(cur.requires,(cur.numRequires+8)*sizeof(char*));
942   }
943   cur.requires[cur.numRequires++] = strdup(name);
944 }
945 
946 /*****************************************************************************
947  *
948  * Create a new module from a verilog description
949  *
950  * Parameters:
951  *     mtype		Type of module (MT_NETLIST or MT_TEXTHDL)
952  *     name		Name of the module
953  *     isMain		Non-zero if this is the top-level module
954  *
955  * Creates a new module and sets cur.mod equal to the generated module.  In
956  * most cases, the new module is also registered with the circuit, but if we
957  * are currently reading a library and the module already exists as a non-library
958  * module, then we do not want to overwrite that module.  In this case we
959  * create a module, set a delete flag and do not register the module.
960  *
961  *****************************************************************************/
VerNewModule(int mtype,const char * name,int isMain)962 void VerNewModule(int mtype, const char *name,int isMain)
963 {
964   GModuleDef *M;
965 
966   cur_initModule();
967 
968   if (cur.libraryName) {
969     /*
970      * Prepare to read in a library module.  We create a module definition even
971      * if we don't intend to retain it in the final circuit so we don't cause problems
972      * for the parser.  We set the flag cur.del_mod if we want to delete the module
973      * after loading.  We retain a library module if: the block does not exist in the
974      * current circuit, if the existing block is also a library block, or the existing
975      * module is an empty block other than the root module.
976      */
977     M = env_findModule(name);
978     if (!M  || M->m_isLib ||  (!GModuleDef_isTop(M) && Hash_numElems(M->m_gates) == 0 && !M->m_text)) {
979       M = env_removeModule(name,1);
980       if (M) delete_GModuleDef(M);
981       M = new_GModuleDef(name);
982     } else {
983       M = new_GModuleDef(name);
984       cur.del_mod = 1;
985     }
986     if (isMain)
987       cur.del_mod = 1;
988 
989     GModuleDef_setLibrary(M,cur.libraryName);
990   } else {
991     M = env_removeModule(name,1);
992     if (!M) M = new_GModuleDef(name);
993     if (isMain) {
994       TkGate.circuit->root_mod = M;
995     }
996   }
997 
998   GModuleDef_setFileName(M,cur.fileName);
999 
1000   /*
1001    * mtype is passed using yacc tokens.  We need to translate it to the internal
1002    * symbol codes we are using.
1003    */
1004   M->m_type = (mtype == NETMODULE) ? MT_NETLIST : MT_TEXTHDL;
1005 
1006   env_clear(M);
1007   cur.mod = M;
1008   if (isMain && !topModule) {
1009     topModule = M;
1010     TkGate.circuit->root_mod = M;
1011   }
1012 
1013   if (!cur.del_mod) {
1014     env_insertModule(cur.mod);
1015     if (!GModuleDef_isTop(cur.mod))
1016       modint_setInterface(cur.mod,0);
1017   }
1018 }
1019 
1020 /*****************************************************************************
1021  *
1022  * Collects hash parameter list data of the form:
1023  *
1024  * #(.a(4), b = 8)
1025  *
1026  * These parameter lists are used in module declarations.  This function is
1027  * only called when reading a native (non-tkgate) verilog file.  Parameter
1028  * values and expressions are stored so that they can be regenerated as part
1029  * of an HDL module definition.
1030  *
1031  *****************************************************************************/
VerModHashParm(const char * name,Expr * e)1032 void VerModHashParm(const char *name,Expr *e)
1033 {
1034   char buf[STRMAX],*p;
1035 
1036   if (!nativeVerilog) return;
1037 
1038   if (!cur.modHPorts) cur.modHPorts = new_List();
1039 
1040   p = buf + sprintf(buf,"%s = ",name);
1041   Expr_sprint(p,STRMAX-strlen(buf),e);
1042 
1043   List_addToTail(cur.modHPorts, (char*)strdup(buf));
1044 }
1045 
VerModParm(const char * name)1046 void VerModParm(const char *name)
1047 {
1048   if (!nativeVerilog) return;
1049 
1050   if (name) {
1051     /*
1052      * If called with non-null 'name' we are adding ports to the module.
1053      */
1054     if (!cur.modPorts) cur.modPorts = new_List();
1055     List_addToTail(cur.modPorts, (char*)name);
1056   } else {
1057     /*
1058      * If called with null 'name' we generate the module declaration line.
1059      */
1060     char buf[STRMAX],*p;
1061 
1062     p = buf;
1063     p += sprintf(p,"module %s",cur.mod->m_name);
1064 
1065     if (cur.modHPorts && List_numElems(cur.modHPorts) > 0) {
1066       ListElem *le;
1067       int doComma = 0;
1068 
1069       p += sprintf(p," #(");
1070       for (le = List_first(cur.modHPorts);le;le = List_next(cur.modHPorts, le)) {
1071 	const char *name = (const char*) ListElem_obj(le);
1072 	if (doComma) p += sprintf(p,", ");
1073 	doComma = 1;
1074 	p += sprintf(p,"%s",name);
1075       }
1076       p += sprintf(p,") ");
1077     }
1078 
1079 
1080     if (cur.modPorts && List_numElems(cur.modPorts) > 0) {
1081       ListElem *le;
1082       int doComma = 0;
1083 
1084       p += sprintf(p,"(");
1085       for (le = List_first(cur.modPorts);le;le = List_next(cur.modPorts, le)) {
1086 	const char *name = (const char*) ListElem_obj(le);
1087 	if (doComma) p += sprintf(p,", ");
1088 	doComma = 1;
1089 	p += sprintf(p,"%s",name);
1090       }
1091       p += sprintf(p,")");
1092     }
1093 
1094     p += sprintf(p,";");
1095     VerAddHdlLine(buf);
1096   }
1097 }
1098 
1099 /*****************************************************************************
1100  *
1101  * Called to finish up reading a netlist module
1102  *
1103  *****************************************************************************/
VerEndNetlistModule()1104 void VerEndNetlistModule()
1105 {
1106   HashElem *E;
1107   GWireList *wl;
1108   PHash *bad_wires;
1109   PHash *bad_nets;
1110 
1111 	bad_wires = new_PHash_noob();
1112 	bad_nets = new_PHash_noob();
1113 
1114   /*
1115      Fix up wire nets.  There may be redunant processing here,
1116      but I'm too lazy to worry about it right now.
1117    */
1118   for (E = Hash_first(cur.mod->m_nets);E;E = Hash_next(cur.mod->m_nets,E)) {
1119     GNet *n = (GNet*) HashElem_obj(E);
1120     if (n->n_driver) {
1121       wire_finalizeNet(n->n_driver);
1122     } else {
1123       /* Net %s has no driver in module %s. (only for net list) */
1124       if (cur.mod->m_type != MT_TEXTHDL)
1125 	message(1,msgLookup("err.nodrive"),n->n_signame,cur.mod->m_name);
1126     }
1127   }
1128 
1129   for (E = Hash_first(cur.netWEnds);E;E = Hash_next(cur.netWEnds,E)) {
1130     GWire **wends = (GWire**) HashElem_obj(E);
1131     ob_free(wends);
1132   }
1133   SHash_flush(cur.netWEnds);
1134 
1135   for (wl = cur.mod->m_wires;wl;wl = wl->wl_next) {
1136     GWire *w1 = wl->wl_wire;
1137     GWire *w2 = wire_driver(w1);
1138 
1139     if (w1 == w2) continue;
1140 
1141     if (!w1->gate && !w2->gate) {
1142       PHash_insert(bad_wires,w2,w2);
1143       PHash_insert(bad_wires,w1,w1);
1144       PHash_insert(bad_nets,w1->net,w1->net);
1145     }
1146   }
1147 
1148   if (Hash_numElems(bad_wires) > 0) {
1149     for (E = Hash_first(bad_wires);E;E = Hash_next(bad_wires,E)) {
1150       GWire *W = (GWire*) HashElem_obj(E);
1151 
1152       message(1,msgLookup("err.noconn"),W->net->n_signame,W->nidx); /* Wire %s{%d} has no connections - deleted. */
1153       cur.mod->m_wires = wire_unlink(cur.mod->m_wires,W);
1154     }
1155     for (E = Hash_first(bad_nets);E;E = Hash_next(bad_nets,E)) {
1156       GNet *n = (GNet*) HashElem_obj(E);
1157 
1158       delete_GNet(n);
1159     }
1160   }
1161 
1162   /*
1163    * If file version does not match current version, apply the version
1164    * delta function to all gates in the module.
1165    */
1166   if (VersionCmp(&cur.gate_ver,&cur.ver) != 0) {
1167     for (E = Hash_first(cur.mod->m_gates);E;E = Hash_next(cur.mod->m_gates,E)) {
1168       GCElement *g = (GCElement*) HashElem_obj(E);
1169       GGateInfo *gi = g->typeinfo;
1170       if (gi->VersionDelta)
1171 	(*gi->VersionDelta)(g,&cur.ver);
1172     }
1173   }
1174 
1175   if (cur.del_mod) {
1176     cur_scheduleModDelete(cur.mod);
1177     cur.mod = 0;
1178   }
1179 
1180 
1181   delete_PHash(bad_wires);
1182   delete_PHash(bad_nets);
1183 
1184   cur.mod = 0;
1185 }
1186 
1187 /*****************************************************************************
1188  *
1189  * Called to finish up reading an HDL  module
1190  *
1191  *****************************************************************************/
VerEndHDLModule()1192 void VerEndHDLModule()
1193 {
1194   if (cur.modPorts) {
1195     delete_List(cur.modPorts);
1196     cur.modPorts = 0;
1197   }
1198   if (cur.modHPorts) {
1199     delete_List(cur.modHPorts);
1200     cur.modHPorts = 0;
1201   }
1202 
1203   if (nativeVerilog) {
1204     VerAddHdlLine("endmodule");
1205   }
1206 
1207   if (TkGate.tcl) {
1208     if (nativeVerilog && !GModuleDef_isTop(cur.mod))
1209       igen_generate_initial(cur.mod);
1210   }
1211 
1212   cur.mod = 0;
1213 }
1214 
1215 /*****************************************************************************
1216  *
1217  * Called to finish up reading a module and call the appropriate finish function.
1218  *
1219  *****************************************************************************/
VerEndModule()1220 void VerEndModule()
1221 {
1222   VerCallMParmFlush();
1223 
1224   if (cur.mod->m_type == MT_TEXTHDL)
1225     VerEndHDLModule();
1226   else
1227     VerEndNetlistModule();
1228 
1229   cur_endModule();
1230 }
1231 
1232 /*****************************************************************************
1233  *
1234  * Make the current module the root module.
1235  *
1236  *****************************************************************************/
VerSetRootMod()1237 void VerSetRootMod()
1238 {
1239   if (!cur.libraryName) {
1240     topModule = cur.mod;
1241     TkGate.circuit->root_mod = cur.mod;
1242   } else {
1243     if (!cur.del_mod)
1244       env_removeModule(cur.mod->m_name,1);
1245     cur.del_mod = 1;
1246   }
1247 }
1248 
1249 /*****************************************************************************
1250  *
1251  * Finish up a net declaration.
1252  *
1253  *****************************************************************************/
VerFinishNet()1254 void VerFinishNet()
1255 {
1256   GWire **wends;
1257   int i;
1258 
1259   if (!cur.net) return;
1260 
1261 #if 0
1262   printf("FinishNet: %s\n",cur.net->n_signame);
1263 #endif
1264 
1265   wends = (GWire**) ob_calloc(cur.numWEnds,sizeof(GWire*),"GWire*[]");
1266   for (i = 0;i < cur.numWEnds;i++)
1267     wends[i] = cur.wends[i];
1268   cur.net->n_wnum = cur.numWEnds;
1269 
1270   SHash_insert(cur.netWEnds,cur.net->n_signame,wends);
1271 
1272   if (!VerilogReadPrefix) {
1273     /*
1274      * Tag something if we are reading an old-style file.
1275      */
1276     if (GNet_getShowName(cur.net)) {
1277       GNet_showName(cur.net);
1278     }
1279   }
1280 
1281   cur.net = 0;
1282 }
1283 
1284 /*****************************************************************************
1285  *
1286  * Called at end of net declarations in a netlist module.
1287  *
1288  *****************************************************************************/
VerEndDecls()1289 void VerEndDecls()
1290 {
1291   VerFinishNet();
1292 }
1293 
1294 /*****************************************************************************
1295  *
1296  * Begin a new net declarations.
1297  *
1298  * Parameters:
1299  *     name		Name of the new net.
1300  *     nbits		Number of bits on the net.
1301  *     vtype		Verilog type code (by token code)
1302  *
1303  *****************************************************************************/
VerNewNet(const char * name,int nbits,int vtype)1304 void VerNewNet(const char *name,int nbits,int vtype)
1305 {
1306   VerFinishNet();
1307 
1308   cur.net = (GNet*) new_GNet(name,cur.mod);
1309 
1310   /*
1311    * Need to map the token code to a verilog type code
1312    */
1313   switch (vtype) {
1314   case TRI :
1315     cur.net->n_vtype = NV_TRI;
1316     break;
1317   case WIRE :
1318     cur.net->n_vtype = NV_WIRE;
1319     break;
1320   case WAND :
1321     cur.net->n_vtype = NV_WAND;
1322     break;
1323   case TRIAND :
1324     cur.net->n_vtype = NV_TRIAND;
1325     break;
1326   case WOR :
1327     cur.net->n_vtype = NV_WOR;
1328     break;
1329   case TRIOR :
1330     cur.net->n_vtype = NV_TRIOR;
1331     break;
1332   case TRI0 :
1333     cur.net->n_vtype = NV_TRI0;
1334     break;
1335   case TRI1 :
1336     cur.net->n_vtype = NV_TRI1;
1337     break;
1338   case TRIREG :
1339     cur.net->n_vtype = NV_TRIREG;
1340     break;
1341   default :
1342     cur.net->n_vtype = NV_WIRE;
1343   }
1344 
1345   net_setSize(cur.net,nbits);
1346   cur.numWEnds = 0;
1347 }
1348 
1349 /*****************************************************************************
1350  *
1351  * Add a line of HDL text to the current module
1352  *
1353  * Parameters:
1354  *     text		Line of text to add.
1355  *
1356  *****************************************************************************/
VerAddHdlLine(const char * text)1357 void VerAddHdlLine(const char *text)
1358 {
1359   int mlen,alen,msize,amsize;
1360   char buf[STRMAX];
1361 
1362   recodeText(parserEncoder,buf,STRMAX,text);
1363   text = buf;
1364 
1365   cur.mod->m_type = MT_TEXTHDL;
1366 
1367   if (!cur.mod->m_text) {
1368     GModuleDef_allocText(cur.mod,HDLTEXTBLOCKSIZE);
1369     *cur.mod->m_text = 0;
1370   }
1371 
1372   mlen = strlen(cur.mod->m_text);
1373   alen = strlen(text);
1374   msize = ((mlen+1+HDLTEXTBLOCKSIZE-1) / HDLTEXTBLOCKSIZE)*HDLTEXTBLOCKSIZE;		/* Current buffer size */
1375   amsize = ((mlen+alen+2+HDLTEXTBLOCKSIZE-1) / HDLTEXTBLOCKSIZE)*HDLTEXTBLOCKSIZE;	/* Required buffer size */
1376 
1377   if ( msize != amsize) {
1378     GModuleDef_allocText(cur.mod,amsize);
1379   }
1380 
1381   sprintf(cur.mod->m_text+mlen,"%s\n",text);
1382 }
1383 
1384 /*****************************************************************************
1385  *
1386  * Create a primitive gate from its base name
1387  *
1388  * Parameters:
1389  *
1390  *
1391  *
1392  *****************************************************************************/
VerGate(const char * func,const char * name)1393 void VerGate(const char *func,const char *name)
1394 {
1395   GGateInfo *gi = 0;
1396   int vnum = 0;
1397   GCElement *g;
1398 
1399   /*
1400    * Try new-style primitive gate names
1401    */
1402   gi = GGateInfo_lookup(func);
1403 
1404   /*
1405    * If not found, try old-style primitive gate names
1406    */
1407   if (!gi) {
1408     gi = GGateInfo_vlookup(func);
1409     vnum = gi ? GGateInfo_variantNum(gi,func) : 0;
1410   }
1411 
1412   if (gi) {
1413     g = (*gi->MakeFunction)(0,cur.mod,gi->code,0,0,0,name,1,0,0);
1414     cur.gate = g;
1415     cur.vnum = vnum;
1416     cur.numPins = 0;
1417     cur.pidx = 0;
1418     cur.revPads = 0;
1419   } else {
1420     yyerror(msgLookup("err.yy.badprim"),func);
1421     cur.gate = 0;
1422   }
1423 }
1424 
1425 /*****************************************************************************
1426  *
1427  * Rename the current instance.
1428  *
1429  * Parameters:
1430  *     name		New name for current instance.
1431  *
1432  *****************************************************************************/
VerRenameCurrent(const char * name)1433 void VerRenameCurrent(const char *name)
1434 {
1435   if (cur.gate) {
1436     gate_setName(cur.gate, name, cur.mod);
1437   }
1438 }
1439 
1440 /*****************************************************************************
1441  *
1442  * Create a new gate from a cell name.
1443  *
1444  * Parameters:
1445  *   func		Name of function (a block name or a _GG primitive name)
1446  *   name		Name of the instance
1447  *
1448  *****************************************************************************/
VerCell(const char * func,const char * name)1449 void VerCell(const char *func,const char *name)
1450 {
1451   GGateInfo *gi = 0;
1452   int vnum = -1;
1453   GCElement *g;
1454 
1455   if (VerilogReadPrefix) {
1456     /*
1457      * Use new-style primitive gate names
1458      */
1459     GCellSpec gcs;
1460 
1461 
1462     if (GGateInfo_decodeTypeName(func,&gcs)) {
1463       if (translateDemux && strcmp(gcs.gc_info->name,"DEMUX") == 0) {
1464 	char funcx[STRMAX],*p;
1465 
1466 	strcpy(funcx,func);
1467 	p = strstr(funcx,"DEMUX");
1468 	memmove(p+2,p,strlen(p)+1);
1469 	memmove(p,"DECODER",7);
1470 	GGateInfo_decodeTypeName(funcx,&gcs);
1471       }
1472 
1473       gi = gcs.gc_info;
1474       strcpy(cur.invSpec,gcs.gc_invSpec);
1475       vnum = -1;
1476     } else
1477       strcpy(cur.invSpec,"");
1478 
1479   } else {
1480     /*
1481      * Use old-style primitive gate names
1482      */
1483 
1484     /*
1485      * Always translate "demux" for old save files.
1486      */
1487     if (strcmp(func,"demux") == 0) {
1488       func = "olddemux";
1489     }
1490 
1491     gi = GGateInfo_vlookup(func);
1492     vnum = gi ? GGateInfo_variantNum(gi,func) : 0;
1493   }
1494 
1495   if (gi) {
1496     g = (*gi->MakeFunction)(0,cur.mod,gi->code,0,0,0,name,1,0,0);
1497   } else {
1498     gi = GGateInfo_lookup("MODULE");
1499     g = (*gi->MakeFunction)(0,cur.mod,gi->code,0,0,0,name,1,0,0);
1500     g->u.block.moduleName = ob_strdup(func);
1501 
1502     if (cur.mparm_list) {
1503       ListElem *le;
1504 
1505       for (le = List_first(cur.mparm_list);le;le = List_next(cur.mparm_list, le)) {
1506 	char **pair = (char**) ListElem_obj(le);
1507 	Block_setParmPort(g,pair[0],pair[1]);
1508       }
1509     }
1510   }
1511   cur.gate = g;
1512   cur.vnum = vnum;
1513   cur.numPins = 0;
1514   cur.pidx = 0;
1515   cur.revPads = 0;
1516 }
1517 
1518 /*****************************************************************************
1519  *
1520  * Complete construction of a gate read from verilog file.
1521  *
1522  *****************************************************************************/
VerEndGate()1523 void VerEndGate()
1524 {
1525   if (!cur.gate) return;
1526   if (cur.vnum == 0) {
1527     cur.gate = 0;
1528     return;
1529   }
1530 
1531   if (cur.vnum != -1) {
1532     int N = GCElement_numPads(cur.gate);
1533     int M = spread(cur.gate->typeinfo->vmask,cur.vnum);
1534     int i;
1535 
1536     for (i = 0;i < N;i++) {
1537       GWire *w;
1538       if (!(M & (1<<i))) continue;
1539 
1540       for (w = cur.gate->wires[i];w;w = w->next)
1541 	w->invert = 1;
1542     }
1543   } else {
1544     char *ip = cur.invSpec;
1545     GGateInfo *gi = cur.gate->typeinfo;
1546     int N = GCElement_numPads(cur.gate);
1547     int i;
1548 
1549     for (i = 0;i < N;i++) {
1550       GWire *w;
1551 
1552       if (gi->Pad[i].iotype == IN) continue;
1553 
1554       for (w = cur.gate->wires[i];w;w = w->next) {
1555 	if (*ip == 'N') {
1556 	  w->invert = 1;
1557 	}
1558 	if (*ip && ip[1]) ip++;
1559       }
1560     }
1561   }
1562 
1563   cur.gate = 0;
1564 }
1565 
VerAttach(const char * pin,const char * net,int isComp)1566 void VerAttach(const char *pin,const char *net,int isComp)
1567 {
1568   int p = cur.numPins++;
1569 
1570   cur_gpin_extend(p);
1571   cur.gPin[p] = pin;
1572   cur.gNet[p] = (GNet*) SHash_find(cur.mod->m_nets,net);
1573   cur.gComp[p] = isComp;
1574   if (!cur.gNet[p])
1575     yyerror(msgLookup("err.yy.nonet"),net);
1576 }
1577 
VerRevPad(int pad)1578 void VerRevPad(int pad)
1579 {
1580   cur.revPads |= 1 << pad;
1581 }
1582 
VerTranDup()1583 void VerTranDup()
1584 {
1585   int s = cur.numPins-1;
1586   int d = cur.numPins++;
1587 
1588   cur_gpin_extend(d);
1589   cur.gPin[d] = "D";
1590   cur.gNet[d] = cur.gNet[s];
1591   cur.gComp[d] = 0;
1592 }
1593 
VerTranRange(int msb,int lsb)1594 void VerTranRange(int msb,int lsb)
1595 {
1596   cur.gate->u.tap.msb = msb;
1597   cur.gate->u.tap.lsb = lsb;
1598 }
1599 
VerJointNet(const char * nname)1600 void VerJointNet(const char *nname)
1601 {
1602   static GGateInfo *pi = 0;
1603   GNet *n;
1604   int i;
1605 
1606   if (!pi) pi = GGateInfo_lookup("JOINT");
1607   n = (GNet*) SHash_find(cur.mod->m_nets,nname);
1608   for (i = 0;i < pi->NumPads;i++) {
1609     cur_gpin_extend(i);
1610     cur.gPin[i] = pi->Pad[i].name;
1611     cur.gNet[i] = n;
1612     cur.gComp[i] = 0;
1613   }
1614   cur.numPins = pi->NumPads;
1615 }
1616 
VerMakeNode(int x,int y,int showSize,int isLabeled,int offset)1617 void VerMakeNode(int x,int y,int showSize,int isLabeled,int offset)
1618 {
1619   GWireNode *n = new_GWireNode();
1620 
1621 #if 0
1622   printf("%p: makeNode(%d, %d, size:%d, islabeled:%d, offset:%d)\n",n,x,y,showSize,isLabeled,offset);
1623 #endif
1624 
1625   n->x = x;
1626   n->y = y;
1627   n->showSize = showSize;
1628   n->isLabeled = isLabeled;
1629   if (offset >= 0) {
1630     n->offset = offset;
1631     n->labelSide = 0;
1632   } else {
1633     n->offset = -offset;
1634     n->labelSide = 1;
1635   }
1636 
1637   if (!cur.node) {
1638     cur.wire->nodes = n;
1639     n->end = cur.wire;
1640   } else {
1641     cur.node->out = n;
1642     n->in = cur.node;
1643   }
1644   cur.node = n;
1645 }
1646 
VerMakeWire(int p)1647 void VerMakeWire(int p)
1648 {
1649   GWire *w;
1650 
1651   while (cur.numWEnds <= p) {
1652     cur_wends_extend(cur.numWEnds);
1653     cur.wends[cur.numWEnds++] = 0;
1654   }
1655 
1656   w = wire_newend(cur.mod,cur.net,0);
1657   cur.wends[p] = w;
1658   w->nidx = p;
1659 
1660   if (p == 0)
1661     w->net->n_driver = w;
1662 
1663   if (cur.wire) {
1664     if (cur.node) {
1665       w->nodes = cur.node;
1666       w->nodes->end = w;
1667       w->driver = cur.wire;
1668     }
1669     cur.wire = 0;
1670   } else {
1671     cur.wire = w;
1672     w->driver = w;
1673   }
1674   cur.node = 0;
1675 }
1676 
VerSetPos(int x,int y)1677 void VerSetPos(int x,int y)
1678 {
1679   if (cur.gate) {
1680     cur.gate->xpos = x;
1681     cur.gate->ypos = y;
1682   }
1683 }
1684 
VerSetSize(int w,int h)1685 void VerSetSize(int w,int h)
1686 {
1687   if (cur.gate && cur.gate->typeinfo->code == GC_BLOCK) {
1688     cur.gate->u.block.gwidth = w;
1689     cur.gate->u.block.gheight = h;
1690   }
1691 }
1692 
VerSetRot(int r)1693 void VerSetRot(int r)
1694 {
1695   if (cur.gate)
1696     cur.gate->orient = r;
1697 }
1698 
VerSetShowName(int sn)1699 void VerSetShowName(int sn)
1700 {
1701   if (cur.gate)
1702     cur.gate->show_name = sn;
1703   else if (cur.net) {
1704     cur.net->n_show_name = sn;
1705     net_update(cur.net);
1706   }
1707 }
1708 
VerSetWireDecorationPos(int wire,int segment,int offset)1709 void VerSetWireDecorationPos(int wire,int segment,int offset)
1710 {
1711 }
1712 
VerSetInterfaceProperty(const char * prop,int n)1713 void VerSetInterfaceProperty(const char *prop,int n)
1714 {
1715   if (!cur.mod) return;
1716 
1717   if (strcmp(prop,"/pd") == 0)
1718     cur.mod->m_protData = n;
1719   else if (strcmp(prop,"/pi") == 0)
1720     cur.mod->m_protIntf = n;
1721   else if (strcmp(prop,"/pe") == 0)
1722     cur.mod->m_protEdit = n;
1723   else if (strcmp(prop,"/pp") == 0)
1724     cur.mod->m_pptype = n;
1725 }
1726 
VerSetProperty(const char * prop,int n)1727 void VerSetProperty(const char *prop,int n)
1728 {
1729   if (cur.isInterface) {
1730     VerSetInterfaceProperty(prop, n);
1731     return;
1732   }
1733 
1734 
1735   if (strcmp(prop,"/anc") == 0)
1736     cur.gate->anchored = (n != 0);
1737 
1738   if (strcmp(prop,"/cpc") == 0)
1739     cur.gate->cpath_cut = (n != 0);
1740 
1741   if (cur.gate->typeinfo->SetProp)
1742     (*cur.gate->typeinfo->SetProp)(cur.gate,prop,&n);
1743 }
1744 
VerSetStrProperty(const char * prop,const char * value)1745 void VerSetStrProperty(const char *prop,const char *value)
1746 {
1747   if (strcmp(prop,"/tech") == 0) {
1748     cur.gate->cust_delay = 0;
1749     if (cur.gate->tech) ob_free(cur.gate->tech);
1750     cur.gate->tech = ob_strdup(value);
1751   }
1752   if (strcmp(prop,"/delay") == 0) {
1753     char buf[STRMAX],*p;
1754     int i;
1755 
1756     cur.gate->cust_delay = 1;
1757     strcpy(buf,value);
1758     for (i = 0, p = strtok(buf," ");p;i++, p = strtok(0," ")) {
1759       int d;
1760       sscanf(p,"%d",&d);
1761       cur.gate->delays[i] = d;
1762     }
1763   }
1764 
1765   if (cur.gate->typeinfo->SetProp)
1766     (*cur.gate->typeinfo->SetProp)(cur.gate,prop,value);
1767 }
1768 
VerAddScriptLine(const char * line)1769 void VerAddScriptLine(const char *line)
1770 {
1771   if (!cur.gate) return;
1772 
1773   if (cur.gate->typeinfo->SetProp)
1774     (*cur.gate->typeinfo->SetProp)(cur.gate,"/line",line);
1775 }
1776 
InsertPadWire(GWire * w,GWire * r)1777 static GWire *InsertPadWire(GWire *w,GWire *r)
1778 {
1779   if (!r) {
1780     r = w;
1781   } else if (w == r) {
1782     yyerror(msgLookup("err.yy.bogussave"));
1783   } else if (w->PadNum < r->PadNum) {
1784     w->next = r;
1785     r = w;
1786   } else {
1787     r->next = InsertPadWire(w,r->next);
1788   }
1789   return r;
1790 }
1791 
1792 /*****************************************************************************
1793  *
1794  * Fasten a wire to a gate.
1795  *
1796  * Parameters:
1797  *    g			Gate on which wire is to be fastened
1798  *    pspec		The port specifier on the gate
1799  *    n			The net which is to be attached
1800  *    p			The wire position number
1801  *    bdir              The direction of the wire if applicable
1802  *
1803  *****************************************************************************/
FastenToGate(GCElement * g,const char * pspec,GNet * n,int p,int bdir)1804 static GWire *FastenToGate(GCElement *g,const char *pspec,GNet *n,int p,int bdir)
1805 {
1806   GGateInfo *gi = cur.gate->typeinfo;
1807   GWire **wends = (GWire**) SHash_find(cur.netWEnds,n->n_signame);
1808   int N = GCElement_numPads(g);
1809   int padNum;				/* Pad number (which pad) */
1810   int padPos;				/* Pad position (number within pad) */
1811   GWire *w;				/* Wire to attach */
1812   extern GGateInfo gate_symblock_info;
1813   GPadLoc *loc;
1814 
1815   /*
1816    * Compensate for a bug with nmos/pmos in old save files.  Older save files
1817    * had the S and Z ports reversed.  The old simlator also had an independent
1818    * bug which caused the ports to be reveresed back to the correct position
1819    * so this problem went unnoticed.
1820    */
1821   if (!VerilogReadPrefix) {
1822     if (strcmp(gi->name,"NMOS") == 0 || strcmp(gi->name,"PMOS") == 0) {
1823       if (*pspec == 'Z')
1824 	pspec = "S";
1825       else if (*pspec == 'S')
1826 	pspec = "Z";
1827     }
1828   }
1829 
1830   w = wends[p];
1831 
1832   switch (bdir) {
1833   case '=' : w->WireDir = TRI; break;
1834   case '>' : w->WireDir = IN; break;
1835   case '<' : w->WireDir = OUT; break;
1836   }
1837 
1838   if (g->typeinfo == &gate_symblock_info) {		/* Symbol block instances */
1839     GModSymbol *ms = g->u.block.symbol;
1840     int i;
1841     padNum = 0;
1842     for (i = 0;i < N;i++) {
1843       GSymPort *p = GModSymbol_getPort(ms,i);
1844       if (strcmp(pspec,p->msp_name) == 0)
1845 	padNum = i;
1846     }
1847     padPos = 0;
1848   } else if (pspec)  {					/* Instances with a pspec */
1849     char pn[STRMAX];
1850 
1851     switch (sscanf(pspec,"%[^0123456789]%d",pn,&padPos)) {
1852     case 2:
1853       break;
1854     case 1:
1855       strcpy(pn,pspec);
1856       padPos = 0;
1857       break;
1858     default :
1859       yyerror(msgLookup("err.yy.pinformat"),pspec);
1860       return 0;
1861     }
1862     for (padNum = 0;padNum < gi->NumPads;padNum++)
1863       if (strcmp(gi->Pad[padNum].name,pn) == 0)
1864 	break;
1865 
1866     if (padNum == N) {
1867       yyerror(msgLookup("err.yy.pinname"),pn,gi->name);
1868       return 0;
1869     }
1870   } else {						/* Instances with no pspec */
1871     padNum = padPos = 0;
1872   }
1873 
1874   loc = GCElement_getPadLoc(g,padNum,cur.gate->orient);
1875   w->PadNum = padPos;
1876   w->next = 0;
1877   if (cur.revPads & (1 << padNum)) {
1878     w->next = cur.gate->wires[padNum];
1879     cur.gate->wires[padNum] = w;
1880   } else
1881     cur.gate->wires[padNum] = InsertPadWire(w,cur.gate->wires[padNum]);
1882   w->gate = cur.gate;
1883   if (loc) w->orient = loc->dir;
1884 
1885 #if 0
1886   printf("FastenToGate(%s/%s,%s,%s,%d,%d)  padNum=%d  padPos=%d ldir=%d\n",
1887 	 g->ename, gi->name ,pspec, n->n_signame, p, bdir,padNum,padPos,loc->dir);
1888 #endif
1889 
1890   if (gi->code == GC_BLOCK)
1891     block_setWireEnd(cur.gate,w,padNum);
1892 
1893   return w;
1894 }
1895 
1896 /*****************************************************************************
1897  *
1898  * Place wire on a gate.
1899  *
1900  * Parameters:
1901  *     p	Place wire end p on gate
1902  *
1903  * This function is called for each element in the /w:[ ] group for a gate to
1904  * attach the specific wire ends to a gate.
1905  *
1906  *****************************************************************************/
VerPlaceWire(int p)1907 void VerPlaceWire(int p)
1908 {
1909   int x;			/* Position in argument list */
1910   GNet *n;			/* Net for position x */
1911   const char *pin;		/* Pin name for position x */
1912   GWire *w;
1913 
1914   x = cur.pidx++;
1915   if (p < 0) return;
1916   if (!cur.gate) return;
1917 
1918   n = cur.gNet[x];
1919   if (n) {
1920     pin = cur.gPin[x];
1921     w = FastenToGate(cur.gate,pin,n,p,0);
1922     if (cur.gComp[x]) {
1923       w->invert = 1;
1924     }
1925   } else {
1926     yyerror(msgLookup("err.yy.nonetpos"),x,cur.gate->ename);
1927   }
1928 }
1929 
VerBlockPort(const char * pname,int pdir,int widx)1930 void VerBlockPort(const char *pname,int pdir,int widx)
1931 {
1932   int x;			/* Position in argument list */
1933   GNet *n;			/* Net for position x */
1934   const char *pin;		/* Pin name for position x */
1935   GWire *w;
1936 
1937   x = cur.pidx++;
1938   if (!cur.gate) return;
1939 
1940   n = cur.gNet[x];
1941   pin = pname;
1942   w = FastenToGate(cur.gate,pin,n,widx,pdir);
1943   w->name = ob_strdup(cur.gPin[x]);
1944 }
1945 
VerBeginBD()1946 void VerBeginBD()
1947 {
1948   GCElement *g;
1949 
1950   if (!cur.del_mod) {
1951     //    modint_setInterface(cur.mod,0);
1952     g = modint_find(cur.mod->m_name);
1953     cur.gate = g;
1954   } else
1955     cur.gate = 0;
1956 
1957   cur.isInterface = 1;
1958 }
1959 
VerEndBD()1960 void VerEndBD()
1961 {
1962   cur.gate = 0;
1963   cur.isInterface = 0;
1964 }
1965 
1966 /*
1967  * Add a port to a module interface definition.
1968  */
VerBDPort(const char * pname,int pdir,const char * name,int nbits,int onum,int oden)1969 void VerBDPort(const char *pname,int pdir,const char *name,int nbits,int onum,int oden)
1970 {
1971   int x,y;
1972   GWire *e1,*e2;
1973   GCElement *g = cur.gate;
1974   int p;
1975 
1976   if (!g) return; /* We are ignoring this interface */
1977 
1978   x = y = 0;
1979 
1980   p = GGateInfo_getPadNum(g->typeinfo,pname);
1981   if (p < 0) {
1982     printf("failed to find pad '%s'\n",pname);
1983     return;
1984   }
1985 
1986   wire_new(TkGate.circuit->mid_mod,&e1,&e2);
1987 
1988   switch (p) {
1989   case BLOCK_TIN :
1990   case BLOCK_TOUT :
1991   case BLOCK_TTRI :
1992     x = g->xpos + (g->u.block.gwidth*onum)/oden;
1993     y = g->ypos;
1994     break;
1995   case BLOCK_LIN :
1996   case BLOCK_LOUT :
1997   case BLOCK_LTRI :
1998     x = g->xpos;
1999     y = g->ypos + (g->u.block.gheight*onum)/oden;
2000     break;
2001   case BLOCK_RIN :
2002   case BLOCK_ROUT :
2003   case BLOCK_RTRI :
2004     x = g->xpos + g->u.block.gwidth;
2005     y = g->ypos + (g->u.block.gheight*onum)/oden;
2006     break;
2007   case BLOCK_BIN :
2008   case BLOCK_BOUT :
2009   case BLOCK_BTRI :
2010     x = g->xpos + (g->u.block.gwidth*onum)/oden;
2011     y = g->ypos + g->u.block.gheight;
2012     break;
2013   }
2014   e1->offset.num = onum;
2015   e1->offset.den = oden;
2016   block_attach(TkGate.circuit->mid_mod,g,e1,e2,x,y,name,pdir);
2017 
2018   net_setSize(e1->net,nbits);
2019 }
2020 
2021 /*
2022  * Check for trailing ".v"
2023  */
isVerilogFile(const char * name)2024 int isVerilogFile(const char *name)
2025 {
2026   int l;
2027 
2028   if (!name) return 0;
2029   l = strlen(name);
2030   if (l < 2) return 0;
2031 
2032   if (strcmp(name+l-2,".v") == 0)
2033     return 1;
2034   else
2035     return 0;
2036 }
2037 
VerBeginDelayDef(const char * tech,const char * prim)2038 void VerBeginDelayDef(const char *tech, const char *prim)
2039 {
2040   GDelayDef_begin(tech,prim);
2041 }
2042 
VerEndDelayDef()2043 void VerEndDelayDef()
2044 {
2045   GDelayDef_end();
2046 }
2047 
VerCallMParmFlush()2048 void VerCallMParmFlush()
2049 {
2050   if (cur.mparm_list)
2051     List_flush(cur.mparm_list);
2052 
2053   cur.mparm_list = 0;
2054 }
2055 
VerCallMParmAdd(const char * name,const char * value)2056 void VerCallMParmAdd(const char *name,const char *value)
2057 {
2058   char **pair;
2059 
2060   if (!cur.mparm_list)
2061     cur.mparm_list = new_List();
2062 
2063   pair = (char**) yc_malloc(2*sizeof(char*),ALGN_WORD);
2064   pair[0] = name ? yc_strdup(name) : 0;
2065   pair[1] = yc_strdup(value);
2066 
2067   List_addToTail(cur.mparm_list, pair);
2068 }
2069 
ycDirective(char * dtext)2070 void ycDirective(char *dtext)
2071 {
2072   int n1,n2;
2073   char u1[STRMAX],u2[STRMAX],*p;
2074 
2075   if (strlen(dtext) > STRMAX) return;
2076 
2077   p = strrchr(dtext,'\n');
2078   if (p) *p = 0;
2079 
2080   if (sscanf(dtext, "`timescale %d %[^/ \t] / %d %s", &n1, u1, &n2, u2) == 4) {
2081     unsigned long long x1 = Timescale_parse(n1,u1);
2082     unsigned long long x2 = Timescale_parse(n2,u2);
2083 
2084     if (x1 == 0 || x2 == 0) {
2085       yyerror(msgLookup("err.yy.baddirective"),dtext);
2086       return;
2087     }
2088 
2089     if (!cur.didTimescale) {
2090       TkGate.circuit->c_timescale.ts_units = x1;
2091       TkGate.circuit->c_timescale.ts_precision = x2;
2092       cur.didTimescale = 1;
2093     }
2094   }
2095 }
2096