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