1 /* "NETGEN", a netlist-specification tool for VLSI
2 Copyright (C) 1989, 1990 Massimo A. Sivilotti
3 Author's address: mass@csvax.cs.caltech.edu;
4 Caltech 256-80, Pasadena CA 91125.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation (any version).
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file copying. If not, write to
17 the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19 /* verilog.c -- Input for Verilog format (structural verilog only) */
20
21 /* The verilog input is limited to "structural verilog", that is, */
22 /* verilog code that only defines inputs, outputs, local nodes (via the */
23 /* "wire" statement), and instanced modules. All modules are read down */
24 /* to the point where either a module (1) does not conform to the */
25 /* requirements above, or (2) has no module definition, in which case */
26 /* it is treated as a "black box" subcircuit and therefore becomes a */
27 /* low-level device. Because in verilog syntax all instances of a */
28 /* module repeat both the module pin names and the local connections, */
29 /* placeholders can be built without the need to redefine pins later, */
30 /* as must be done for formats like SPICE that don't declare pin names */
31 /* in an instance call. */
32
33 /* Note that use of 1'b0 or 1'b1 and similar variants is prohibited; */
34 /* the structural netlist should either declare VSS and/or VDD as */
35 /* inputs, or use tie-high and tie-low standard cells. */
36
37 /* Most verilog syntax has been captured below. Still to do: Handle */
38 /* vectors that are created on the fly using {...} notation, including */
39 /* the {n{...}} concatenation method. */
40
41 #include "config.h"
42
43 #include <stdio.h>
44 #include <stdlib.h> /* for calloc(), free(), getenv() */
45 #ifndef IBMPC
46 #include <sys/types.h> /* for getpwnam() tilde expansion */
47 #include <pwd.h>
48 #endif
49
50 #ifdef TCL_NETGEN
51 #include <tcl.h>
52 #endif
53
54 #include "netgen.h"
55 #include "objlist.h"
56 #include "netfile.h"
57 #include "print.h"
58 #include "hash.h"
59
60 // See netfile.c for explanation of delimiters. 'X'
61 // separates single-character delimiters from two-character delimiters.
62 #define VLOG_DELIMITERS "X///**/#((**)X,;:(){}[]="
63 #define VLOG_PIN_NAME_DELIMITERS "X///**/(**)X()"
64 #define VLOG_PIN_CHECK_DELIMITERS "X///**/(**)X,;(){}"
65
66 // Used by portelement structure "flags" record.
67 #define PORT_NOT_FOUND 0
68 #define PORT_FOUND 1
69
70 // Global storage for verilog parameters
71 struct hashdict verilogparams;
72 // Global storage for verilog definitions
73 struct hashdict verilogdefs;
74
75 // Global storage for wire buses
76 struct hashdict buses;
77
78 struct bus {
79 int start;
80 int end;
81 };
82
83 // Free a bus structure in the hash table during cleanup
84
freebus(struct hashlist * p)85 int freebus (struct hashlist *p)
86 {
87 struct bus *wb;
88
89 wb = (struct bus *)(p->ptr);
90 FREE(wb);
91 return 1;
92 }
93
94 // Create a new bus structure
95
NewBus()96 struct bus *NewBus()
97 {
98 struct bus *wb;
99
100 wb = (struct bus *)CALLOC(1, sizeof(struct bus));
101 if (wb == NULL) Fprintf(stderr, "NewBus: Core allocation error\n");
102 return (wb);
103 }
104
105 //-------------------------------------------------------------------------
106 // Find a character c in a string, assuming that string may contain
107 // verilog names, where anything, including char c, may appear in the
108 // string if it is a backslash-escaped name. Only the position of
109 // character c outside of a verilog name is reported.
110 //-------------------------------------------------------------------------
111
strvchr(char * string,char c)112 char *strvchr(char *string, char c)
113 {
114 char *s;
115
116 for (s = string; *s != '\0'; s++) {
117 if (*s == '\\') {
118 while (*s != '\0' && *s != ' ') s++;
119 if (*s == '\0') {
120 Fprintf(stderr, "Error: Verilog backslash-escaped name"
121 " does not end with a space.\n");
122 break;
123 }
124 }
125 if (*s == c) return s;
126 }
127 return NULL;
128 }
129
130 //-------------------------------------------------------------------------
131 // Get bus indexes from the notation name[a:b]. If there is only "name"
132 // then look up the name in the bus hash list and return the index bounds.
133 // Return 0 on success, 1 on syntax error, and -1 if signal is not a bus.
134 //
135 // Note that this routine relies on the delimiter characters including
136 // "[", ":", and "]" when calling NextTok.
137 //-------------------------------------------------------------------------
138
GetBusTok(struct bus * wb)139 int GetBusTok(struct bus *wb)
140 {
141 int result, start, end;
142 struct property *kl = NULL;
143
144 if (wb == NULL) return 0;
145 else {
146 wb->start = -1;
147 wb->end = -1;
148 }
149
150 if (match(nexttok, "[")) {
151 SkipTokComments(VLOG_DELIMITERS);
152
153 result = sscanf(nexttok, "%d", &start);
154 if (result != 1) {
155 char *aptr = NULL;
156 char addin;
157
158 // Check for "+/-(n)" at end of a parameter name
159 aptr = strrchr(nexttok, '+');
160 if (aptr == NULL) aptr = strrchr(nexttok, '-');
161 if (aptr != NULL) {
162 addin = *aptr;
163 *aptr = '\0';
164 }
165
166 // Is name in the parameter list?
167 kl = (struct property *)HashLookup(nexttok, &verilogparams);
168 if (kl == NULL) {
169 Printf("Array value %s is not a number or a parameter.\n",
170 nexttok);
171 return 1;
172 }
173 else {
174 if (kl->type == PROP_STRING) {
175 result = sscanf(kl->pdefault.string, "%d", &start);
176 if (result != 1) {
177 Printf("Parameter %s has value %s that cannot be parsed"
178 " as an integer.\n", nexttok, kl->pdefault.string);
179 return 1;
180 }
181 }
182 else if (kl->type == PROP_INTEGER) {
183 start = kl->pdefault.ival;
184 }
185 else if (kl->type == PROP_DOUBLE) {
186 start = (int)kl->pdefault.dval;
187 if ((double)start != kl->pdefault.dval) {
188 Printf("Parameter %s has value %g that cannot be parsed"
189 " as an integer.\n", nexttok, kl->pdefault.dval);
190 return 1;
191 }
192 }
193 else {
194 Printf("Parameter %s has unknown type; don't know how"
195 " to parse.\n", nexttok);
196 return 1;
197 }
198 }
199 if (aptr != NULL) {
200 int addval;
201 *aptr = addin;
202 if (sscanf(aptr + 1, "%d", &addval) != 1) {
203 Printf("Unable to parse parameter increment '%s'\n", aptr);
204 return 1;
205 }
206 start += (addin == '+') ? addval : -addval;
207 }
208 }
209 SkipTokComments(VLOG_DELIMITERS);
210 if (match(nexttok, "]")) {
211 result = 1;
212 end = start; // Single bit
213 }
214 else if (!match(nexttok, ":")) {
215 Printf("Badly formed array notation: Expected colon, found %s\n", nexttok);
216 return 1;
217 }
218 else {
219 SkipTokComments(VLOG_DELIMITERS);
220
221 result = sscanf(nexttok, "%d", &end);
222 if (result != 1) {
223 char *aptr = NULL;
224 char addin;
225
226 // Check for "+/-(n)" at end of a parameter name
227 aptr = strrchr(nexttok, '+');
228 if (aptr == NULL) aptr = strrchr(nexttok, '-');
229 if (aptr != NULL) {
230 addin = *aptr;
231 *aptr = '\0';
232 }
233
234 // Is name in the parameter list?
235 kl = (struct property *)HashLookup(nexttok, &verilogparams);
236 if (kl == NULL) {
237 Printf("Array value %s is not a number or a parameter.\n",
238 nexttok);
239 return 1;
240 }
241 else {
242 if (kl->type == PROP_STRING) {
243 result = sscanf(kl->pdefault.string, "%d", &end);
244 if (result != 1) {
245 Printf("Parameter %s has value %s that cannot be parsed"
246 " as an integer.\n", nexttok,
247 kl->pdefault.string);
248 return 1;
249 }
250 }
251 else if (kl->type == PROP_INTEGER) {
252 end = kl->pdefault.ival;
253 }
254 else if (kl->type == PROP_DOUBLE) {
255 end = (int)kl->pdefault.dval;
256 if ((double)end != kl->pdefault.dval) {
257 Printf("Cannot parse second digit from parameter "
258 "%s value %g\n", nexttok, kl->pdefault.dval);
259 return 1;
260 }
261 }
262 else {
263 Printf("Parameter %s has unknown type; don't know how"
264 " to parse.\n", nexttok);
265 return 1;
266 }
267 }
268 if (aptr != NULL) {
269 int addval;
270 *aptr = addin;
271 if (sscanf(aptr + 1, "%d", &addval) != 1) {
272 Printf("Unable to parse parameter increment '%s'\n", aptr);
273 return 1;
274 }
275 end += (addin == '+') ? addval : -addval;
276 }
277 }
278 }
279 wb->start = start;
280 wb->end = end;
281
282 while (!match(nexttok, "]")) {
283 SkipTokComments(VLOG_DELIMITERS);
284 if (nexttok == NULL) {
285 Printf("End of file reached while reading array bounds.\n");
286 return 1;
287 }
288 else if (match(nexttok, ";")) {
289 // Better than reading to end-of-file, give up on end-of-statement
290 Printf("End of statement reached while reading array bounds.\n");
291 return 1;
292 }
293 }
294 }
295 else {
296 struct bus *hbus;
297 hbus = (struct bus *)HashLookup(nexttok, &buses);
298 if (hbus != NULL) {
299 wb->start = hbus->start;
300 wb->end = hbus->end;
301 }
302 else
303 return -1;
304 }
305 return 0;
306 }
307
308 //--------------------------------------------------------------------
309 // GetBus() is similar to GetBusTok() (see above), but it parses from
310 // a string instead of the input tokenizer.
311 //--------------------------------------------------------------------
312
GetBus(char * astr,struct bus * wb)313 int GetBus(char *astr, struct bus *wb)
314 {
315 char *colonptr, *brackstart, *brackend, *sigend, sdelim, *aastr;
316 int result, start, end;
317
318 if (wb == NULL) return 0;
319 else {
320 wb->start = -1;
321 wb->end = -1;
322 }
323
324 /* Check for wire bundles. If there are bundles, process each */
325 /* section separately and concatenate the sizes. */
326 /* To be done: Handle nested bundles, including N-times concatenation */
327
328 if (*astr == '{') {
329 struct bus wbb;
330
331 astr++;
332 wb->end = 0;
333 while((*astr != '\0') && (*astr != '}')) {
334 sigend = strvchr(astr, ',');
335 if (sigend == NULL) sigend = strvchr(astr, '}');
336 if (sigend == NULL) {
337 Printf("Badly formed wire bundle \"%s\"\n", astr - 1);
338 return 1;
339 }
340 sdelim = *sigend;
341 *sigend = '\0';
342 if (GetBus(astr, &wbb) == 0) {
343 if (wbb.start > wbb.end)
344 wb->start += (wbb.start - wbb.end + 1);
345 else
346 wb->start += (wbb.end - wbb.start + 1);
347 }
348 else {
349 wb->start++;
350 }
351 *sigend = sdelim;
352 astr = sigend + 1;
353 }
354 return 0;
355 }
356
357 // Delimiters may appear in backslash-escaped names. . . ignore these.
358 aastr = astr;
359 if (*aastr == '\\') {
360 aastr++;
361 while (*aastr != ' ' && *aastr != '\\' && *aastr != '\0') aastr++;
362 }
363
364 brackstart = strvchr(aastr, '[');
365 if (brackstart != NULL) {
366 brackend = strvchr(aastr, ']');
367 if (brackend == NULL) {
368 Printf("Badly formed array notation \"%s\"\n", astr);
369 return 1;
370 }
371 *brackend = '\0';
372 colonptr = strvchr(aastr, ':');
373 if (colonptr) *colonptr = '\0';
374 result = sscanf(brackstart + 1, "%d", &start);
375 if (colonptr) *colonptr = ':';
376 if (result != 1) {
377 Printf("Badly formed array notation \"%s\"\n", astr);
378 *brackend = ']';
379 return 1;
380 }
381 if (colonptr)
382 result = sscanf(colonptr + 1, "%d", &end);
383 else {
384 result = 1;
385 end = start; // Single bit
386 }
387 *brackend = ']';
388 if (result != 1) {
389 Printf("Badly formed array notation \"%s\"\n", astr);
390 return 1;
391 }
392 wb->start = start;
393 wb->end = end;
394 }
395 else {
396 struct bus *hbus;
397 hbus = (struct bus *)HashLookup(astr, &buses);
398 if (hbus != NULL) {
399 wb->start = hbus->start;
400 wb->end = hbus->end;
401 }
402 else
403 return -1;
404 }
405 return 0;
406 }
407
408 // Output a Verilog Module. Note that since Verilog does not describe
409 // low-level devices like transistors, capacitors, etc., then this
410 // format is limited to black-box subcircuits. Cells containing any
411 // such low-level devices are ignored.
412
VerilogModule(struct nlist * tp)413 void VerilogModule(struct nlist *tp)
414 {
415 struct objlist *ob, *mob;
416 int node, maxnode;
417 char *model;
418 struct tokstack *stackptr;
419
420 /* 1st pass: traverse list of objects for low-level device checks */
421
422 for (ob = tp->cell; ob != NULL; ob = ob->next) {
423 if (ob->type == FIRSTPIN) {
424 struct nlist *tp2;
425
426 tp2 = LookupCellFile(ob->model.class, tp->file);
427
428 /* Check the class. Low-level devices cause the */
429 /* routine to return without generating output. */
430
431 switch (tp2->class) {
432 case CLASS_NMOS4: case CLASS_PMOS4: case CLASS_FET4:
433 case CLASS_NMOS: case CLASS_PMOS: case CLASS_FET3:
434 case CLASS_FET: case CLASS_ECAP:
435 case CLASS_NPN: case CLASS_PNP: case CLASS_BJT:
436 case CLASS_RES: case CLASS_RES3:
437 case CLASS_DIODE: case CLASS_INDUCTOR:
438 case CLASS_CAP: case CLASS_CAP3:
439 case CLASS_XLINE:
440 return;
441 case CLASS_SUBCKT: case CLASS_MODULE:
442 break;
443 default:
444 Printf ("Bad device class \"%s\" found.\n", tp2->class);
445 break; /* ignore it. . . */
446 }
447 }
448 }
449
450 /* Check to see that all children have been dumped first */
451
452 for (ob = tp->cell; ob != NULL; ob = ob->next) {
453 if (ob->type == FIRSTPIN) {
454 struct nlist *tp2;
455
456 tp2 = LookupCellFile(ob->model.class, tp->file);
457 if ((tp2 != NULL) && !(tp2->dumped) && (tp2->class == CLASS_SUBCKT))
458 VerilogModule(tp2);
459 }
460 }
461
462 /* Print module pin list */
463
464 FlushString("module %s (\n",tp->name);
465 for (ob = tp->cell; ob != NULL; ob = ob->next)
466 if (IsPortInPortlist(ob, tp)) FlushString("input %s,\n", ob->name);
467 FlushString(");\n");
468
469 /* Print names of all nodes as 'wire' statements */
470
471 maxnode = 0;
472 for (ob = tp->cell; ob != NULL; ob = ob->next)
473 if (ob->node > maxnode) maxnode = ob->node;
474
475 /* was: for (node = 0; node <= maxnode; node++) */
476 for (node = 1; node <= maxnode; node++)
477 FlushString(" wire %s;\n", NodeName(tp, node));
478
479 /* 2nd pass: traverse list of objects for output */
480
481 for (ob = tp->cell; ob != NULL; ob = ob->next) {
482 if (ob->type == FIRSTPIN) {
483 int drain_node, gate_node, source_node;
484 struct nlist *tp2;
485
486 tp2 = LookupCellFile(ob->model.class, tp->file);
487 model = tp2->name;
488
489 /* Check the class. Low-level devices cause the routine to */
490 /* return value 1 (don't output). */
491
492 switch (tp2->class) {
493 case CLASS_SUBCKT: case CLASS_MODULE:
494 break;
495 default:
496 Printf ("Bad device class found.\n");
497 continue; /* ignore it. . . */
498 }
499
500 FlushString("%s %s (\n", model, ob->instance.name);
501
502 /* Print out nodes. */
503
504 mob = tp2->cell;
505 while (ob) {
506 if (ob->type >= FIRSTPIN)
507 FlushString(".%s(%s),\n", mob->name, ob->name);
508 ob = ob->next;
509 mob = mob->next;
510 if (ob->next && ob->next->type <= FIRSTPIN) break;
511 }
512 FlushString(");\n", model, ob->instance.name);
513 }
514 }
515
516 FlushString("endmodule\n");
517 tp->dumped = 1;
518 }
519
520 /* Write a Verilog module (top-level routine) */
521
VerilogTop(char * name,int fnum,char * filename)522 void VerilogTop(char *name, int fnum, char *filename)
523 {
524 struct nlist *tp;
525 char FileName[500];
526
527 tp = LookupCellFile(name, fnum);
528
529 if (tp == NULL) {
530 Printf ("No cell '%s' found.\n", name);
531 return;
532 }
533
534 if (filename == NULL || strlen(filename) == 0)
535 SetExtension(FileName, name, VERILOG_EXTENSION);
536 else
537 SetExtension(FileName, filename, VERILOG_EXTENSION);
538
539 if (!OpenFile(FileName, 80)) {
540 perror("write verilog: Unable to open output file.");
541 return;
542 }
543 ClearDumpedList();
544 /* Start with general information in comment lines at the top */
545 FlushString("/*\n");
546 FlushString(" * Verilog structural netlist for cell %s\n", name);
547 FlushString(" * Written by Netgen %s.%s\n\n", NETGEN_VERSION, NETGEN_REVISION);
548 FlushString(" */\n");
549 VerilogModule(tp);
550 CloseFile(FileName);
551 }
552
553 /* If any pins are marked unconnected, see if there are */
554 /* other pins of the same name that have connections. */
555
CleanupModule()556 void CleanupModule() {
557 int maxnode = 0;
558 int has_submodules = FALSE;
559 struct objlist *sobj, *nobj, *lobj, *pobj;
560 struct objlist *myLastPort, *object_it, *myNextObject;
561
562 if (CurrentCell == NULL) return;
563
564 myLastPort = NULL;
565
566 /* Reorder objects so that all ports come first, before nodes, because
567 * parts of the code depend on it.
568 */
569
570 for (object_it = CurrentCell->cell; object_it && object_it->type <= 0;
571 object_it = myNextObject ) {
572
573 myNextObject = object_it->next;
574 if (!myNextObject) // end of list
575 continue;
576
577 if (myLastPort == NULL) {
578 if (object_it->type == PORT) {
579 myLastPort = object_it; // port at begining of list
580 myNextObject = object_it; // otherwise skips one
581 }
582 else if (myNextObject->type == PORT) {
583 object_it->next = myNextObject->next;
584 myNextObject->next = CurrentCell->cell;
585 CurrentCell->cell = myNextObject;
586 myLastPort = myNextObject;
587 }
588 }
589 else if (myNextObject->type == PORT) {
590 object_it->next = myNextObject->next;
591 myNextObject->next = myLastPort->next;
592 myLastPort->next = myNextObject;
593 myLastPort = myNextObject;
594 }
595 }
596
597 for (sobj = CurrentCell->cell; sobj; sobj = sobj->next)
598 if (sobj->node > maxnode)
599 maxnode = sobj->node + 1;
600
601 lobj = NULL;
602 for (sobj = CurrentCell->cell; sobj != NULL;) {
603 nobj = sobj->next;
604 if (sobj->type == FIRSTPIN)
605 has_submodules = TRUE;
606 if (sobj->node < 0) {
607 if (IsPort(sobj) && sobj->model.port == PROXY)
608 sobj->node = maxnode++;
609 else if (IsPort(sobj)) {
610 for (pobj = CurrentCell->cell; pobj && (pobj->type == PORT);
611 pobj = pobj->next) {
612 if (pobj == sobj) continue;
613 if (match(pobj->name, sobj->name) && pobj->node >= 0) {
614 sobj->node = pobj->node;
615 break;
616 }
617 }
618 lobj = sobj;
619 }
620 else
621 lobj = sobj;
622 }
623 else
624 lobj = sobj;
625 sobj = nobj;
626 }
627 if (has_submodules == FALSE) SetClass(CLASS_MODULE);
628
629 if (buses.hashtab != NULL) {
630 RecurseHashTable(&buses, freebus);
631 HashKill(&buses);
632 }
633 }
634
635 /*------------------------------------------------------*/
636 /* Structure for stacking nested module definitions */
637 /*------------------------------------------------------*/
638
639 /* Forward declarations */
640 extern void IncludeVerilog(char *, int, struct cellstack **, int);
641
642 /* External declarations (from spice.c) */
643 extern void PushStack(char *cellname, struct cellstack **top);
644 extern void PopStack(struct cellstack **top);
645
646 /*------------------------------------------------------*/
647 /* Read a verilog structural netlist */
648 /*------------------------------------------------------*/
649
ReadVerilogFile(char * fname,int filenum,struct cellstack ** CellStackPtr,int blackbox)650 void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
651 int blackbox)
652 {
653 int cdnum = 1, rdnum = 1, i, ival;
654 int warnings = 0, hasports, inlined_decls = 0, localcount = 1;
655 double dval;
656 char devtype, in_module, in_param;
657 char *eqptr, *matchptr;
658 struct keyvalue *kvlist = NULL;
659 char inst[256], model[256], instname[256], portname[256], pkey[256];
660 struct nlist *tp;
661 struct objlist *parent, *sobj, *nobj, *lobj, *pobj;
662
663 inst[255] = '\0';
664 model[255] = '\0';
665 instname[255] = '\0';
666 in_module = (char)0;
667 in_param = (char)0;
668
669 while (!EndParseFile()) {
670
671 SkipTokComments(VLOG_DELIMITERS); /* get the next token */
672 if ((EndParseFile()) && (nexttok == NULL)) break;
673 else if (nexttok == NULL)
674 break;
675
676 /* Ignore end-of-statement markers */
677 else if (match(nexttok, ";"))
678 continue;
679
680 /* Ignore primitive definitions */
681 else if (match(nexttok, "primitive")) {
682 while (1) {
683 SkipNewLine(VLOG_DELIMITERS);
684 SkipTokComments(VLOG_DELIMITERS);
685 if (EndParseFile()) break;
686 if (match(nexttok, "endprimitive")) {
687 in_module = 0;
688 break;
689 }
690 }
691 }
692
693 /* Handle parameters by treating as a localparam or definition. */
694 /* Currently anything other than a constant value is not handled */
695 /* and so will flag a warning. */
696
697 else if (match(nexttok, "parameter") || match(nexttok, "localparam")) {
698 char *paramkey = NULL;
699 char *paramval = NULL;
700
701 // Pick up key = value pairs and store in current cell. Look only
702 // at the keyword before "=". Then set the definition as everything
703 // remaining in the line, excluding comments, until the end-of-statement
704
705 while (nexttok != NULL)
706 {
707 struct property *kl = NULL;
708
709 /* Parse for parameters used in expressions. Save */
710 /* parameters in the "verilogparams" hash table. */
711
712 SkipTok(VLOG_DELIMITERS);
713 if ((nexttok == NULL) || (nexttok[0] == '\0')) break;
714 if (match(nexttok, "=")) {
715 /* Pick up remainder of statement */
716 while (nexttok != NULL) {
717 SkipTokNoNewline("X///**/X;,");
718 if (nexttok == NULL) break;
719 if (match(nexttok, ";") || match(nexttok, ",")) break;
720 if (paramval == NULL) paramval = strsave(nexttok);
721 else {
722 char *paramlast;
723 /* Append nexttok to paramval */
724 paramlast = paramval;
725 paramval = (char *)MALLOC(strlen(paramlast) + strlen(nexttok)
726 + 2);
727 sprintf(paramval, "%s %s", paramlast, nexttok);
728 FREE(paramlast);
729 }
730 }
731
732 kl = NewProperty();
733 kl->key = strsave(paramkey);
734 kl->idx = 0;
735 kl->merge = MERGE_NONE;
736
737 if (ConvertStringToInteger(paramval, &ival) == 1) {
738 kl->type = PROP_INTEGER;
739 kl->slop.ival = 0;
740 kl->pdefault.ival = ival;
741 }
742 else if (ConvertStringToFloat(paramval, &dval) == 1) {
743 kl->type = PROP_DOUBLE;
744 kl->slop.dval = 0.01;
745 kl->pdefault.dval = dval;
746 }
747 else {
748 kl->type = PROP_STRING;
749 kl->slop.dval = 0.0;
750 kl->pdefault.string = strsave(paramval);
751 }
752
753 HashPtrInstall(paramkey, kl, &verilogparams);
754 FREE(paramval);
755 paramval = NULL;
756
757 if ((nexttok == NULL) || match(nexttok, ";")) break;
758 }
759 else {
760 if (paramkey != NULL) FREE(paramkey);
761 paramkey = strsave(nexttok);
762 }
763 }
764 if (paramval != NULL) FREE(paramval);
765 if (paramkey != NULL) FREE(paramkey);
766 }
767
768 else if (match(nexttok, "module")) {
769 InitializeHashTable(&buses, OBJHASHSIZE);
770 SkipTokNoNewline(VLOG_DELIMITERS);
771 if (nexttok == NULL) {
772 Fprintf(stderr, "Badly formed \"module\" line\n");
773 goto skip_endmodule;
774 }
775
776 if (in_module == (char)1) {
777 Fprintf(stderr, "Missing \"endmodule\" statement on subcircuit.\n");
778 InputParseError(stderr);
779 }
780 in_module = (char)1;
781
782 /* Save pointer to current cell */
783 if (CurrentCell != NULL)
784 parent = CurrentCell->cell;
785 else
786 parent = NULL;
787
788 /* Check for existence of the cell. We may need to rename it. */
789
790 snprintf(model, 99, "%s", nexttok);
791 tp = LookupCellFile(nexttok, filenum);
792
793 /* Check for name conflict with duplicate cell names */
794 /* This may mean that the cell was used before it was */
795 /* defined, but CDL files sometimes just redefine the */
796 /* same cell over and over. So check if it's empty. */
797
798 if ((tp != NULL) && (tp->class != CLASS_MODULE)) {
799 int n;
800 char *ds;
801
802 // NOTE: Use this to ignore the new definition---should be
803 // an option to netgen.
804 /* goto skip_endmodule; */
805
806 ds = strrchr(model, '[');
807 if ((ds != NULL) && (*(ds + 1) == '['))
808 sscanf(ds + 2, "%d", &n);
809 else {
810 ds = model + strlen(model);
811 sprintf(ds, "[[0]]");
812 n = -1;
813 }
814
815 Printf("Duplicate cell %s in file\n", nexttok);
816 tp->flags |= CELL_DUPLICATE;
817 while (tp != NULL) {
818 n++;
819 /* Append "[[n]]" to the preexisting model name to force uniqueness */
820 sprintf(ds, "[[%d]]", n);
821 tp = LookupCellFile(model, filenum);
822 }
823 Printf("Renaming original cell to %s\n", model);
824 InstanceRename(nexttok, model, filenum);
825 CellRehash(nexttok, model, filenum);
826 CellDef(nexttok, filenum);
827 tp = LookupCellFile(nexttok, filenum);
828 }
829 else if (tp != NULL) { /* Make a new definition for an empty cell */
830 FreePorts(nexttok);
831 CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
832 CellDef(model, filenum);
833 tp = LookupCellFile(model, filenum);
834 }
835 else if (tp == NULL) { /* Completely new cell, no name conflict */
836 CellDef(model, filenum);
837 tp = LookupCellFile(model, filenum);
838 }
839
840 hasports = (char)0;
841 inlined_decls = (char)0;
842
843 if (tp != NULL) {
844 struct bus wb, *nb;
845
846 PushStack(tp->name, CellStackPtr);
847
848 /* Need to support both types of I/O lists: Those */
849 /* that declare names only in the module list and */
850 /* follow with input/output and vector size */
851 /* declarations as individual statements in the module */
852 /* definition, and those which declare everything */
853 /* inside the pin list. */
854
855 SkipTokComments(VLOG_DELIMITERS);
856
857 // Check for parameters within #( ... )
858
859 if (match(nexttok, "#(")) {
860 SkipTokComments(VLOG_DELIMITERS);
861 in_param = (char)1;
862 }
863 else if (match(nexttok, "(")) {
864 SkipTokComments(VLOG_DELIMITERS);
865 }
866
867 wb.start = wb.end = -1;
868 while ((nexttok != NULL) && !match(nexttok, ";")) {
869 if (in_param) {
870 if (match(nexttok, ")")) {
871 in_param = (char)0;
872 SkipTokComments(VLOG_DELIMITERS);
873 if (!match(nexttok, "(")) {
874 Fprintf(stderr, "Badly formed module block parameter list.\n");
875 goto skip_endmodule;
876 }
877 }
878 else if (match(nexttok, "=")) {
879
880 // The parameter value is the next token.
881 SkipTokComments(VLOG_DELIMITERS); /* get the next token */
882 eqptr = nexttok;
883
884 // Try first as a double, otherwise it's a string
885 // Double value's slop defaults to 1%.
886 if (ConvertStringToFloat(eqptr, &dval) == 1)
887 PropertyDouble(tp->name, filenum, pkey, 0.01, dval);
888 else
889 PropertyString(tp->name, filenum, pkey, 0, eqptr);
890 }
891 else {
892 /* Assume this is a keyword and save it */
893 strcpy(pkey, nexttok);
894 }
895 }
896 else if (!match(nexttok, ",")) {
897 if (match(nexttok, ")")) break;
898 // Ignore input, output, and inout keywords, and handle buses.
899
900 if (inlined_decls == (char)0) {
901 if (match(nexttok, "input") || match(nexttok, "output") ||
902 match(nexttok, "inout"))
903 inlined_decls = (char)1;
904 }
905 else {
906 if (!match(nexttok, "input") && !match(nexttok, "output") &&
907 !match(nexttok, "inout") && !match(nexttok, "real") &&
908 !match(nexttok, "wire") && !match(nexttok, "logic") &&
909 !match(nexttok, "integer")) {
910 if (match(nexttok, "[")) {
911 if (GetBusTok(&wb) != 0) {
912 // Didn't parse as a bus, so wing it
913 wb.start = wb.end = -1;
914 Port(nexttok);
915 }
916 }
917 else {
918 if (wb.start != -1) {
919 if (wb.start > wb.end) {
920 for (i = wb.start; i >= wb.end; i--) {
921 sprintf(portname, "%s[%d]", nexttok, i);
922 Port(portname);
923 }
924 }
925 else {
926 for (i = wb.start; i <= wb.end; i++) {
927 sprintf(portname, "%s[%d]", nexttok, i);
928 Port(portname);
929 }
930 }
931 /* Also register this port as a bus */
932 nb = NewBus();
933 nb->start = wb.start;
934 nb->end = wb.end;
935 HashPtrInstall(nexttok, nb, &buses);
936
937 wb.start = wb.end = -1;
938 }
939 else {
940 Port(nexttok);
941 }
942 }
943 hasports = 1;
944 }
945 }
946 }
947 SkipTokComments(VLOG_DELIMITERS);
948 if (nexttok == NULL) break;
949 }
950 SetClass((blackbox) ? CLASS_MODULE : CLASS_SUBCKT);
951
952 if (inlined_decls == 1) {
953 if (hasports == 0)
954 // If the cell defines no ports, then create a proxy
955 Port((char *)NULL);
956
957 /* In the blackbox case, don't read the cell contents */
958 if (blackbox) goto skip_endmodule;
959 }
960 }
961 else {
962
963 skip_endmodule:
964 /* There was an error, so skip to the end of the */
965 /* subcircuit definition */
966
967 while (1) {
968 SkipNewLine(VLOG_DELIMITERS);
969 SkipTokComments(VLOG_DELIMITERS);
970 if (EndParseFile()) break;
971 if (match(nexttok, "endmodule")) {
972 in_module = 0;
973 break;
974 }
975 }
976 }
977 }
978 else if (match(nexttok, "input") || match(nexttok, "output")
979 || match(nexttok, "inout")) {
980 struct bus wb, *nb;
981
982 // Parsing of ports as statements not in the module pin list.
983 wb.start = wb.end = -1;
984 while (1) {
985 SkipTokComments(VLOG_DELIMITERS);
986 if (EndParseFile()) break;
987
988 if (match(nexttok, ";")) {
989 // End of statement
990 break;
991 }
992 else if (match(nexttok, "[")) {
993 if (GetBusTok(&wb) != 0) {
994 // Didn't parse as a bus, so wing it
995 wb.start = wb.end = -1;
996 Port(nexttok);
997 }
998 }
999 else if (!match(nexttok, ",")) {
1000 if (wb.start != -1) {
1001 if (wb.start > wb.end) {
1002 for (i = wb.start; i >= wb.end; i--) {
1003 sprintf(portname, "%s[%d]", nexttok, i);
1004 Port(portname);
1005 }
1006 }
1007 else {
1008 for (i = wb.start; i <= wb.end; i++) {
1009 sprintf(portname, "%s[%d]", nexttok, i);
1010 Port(portname);
1011 }
1012 }
1013 /* Also register this port as a bus */
1014 nb = NewBus();
1015 nb->start = wb.start;
1016 nb->end = wb.end;
1017 HashPtrInstall(nexttok, nb, &buses);
1018 wb.start = wb.end = -1;
1019 }
1020 else {
1021 Port(nexttok);
1022 }
1023 }
1024 hasports = 1;
1025 }
1026 }
1027 else if (match(nexttok, "endmodule")) {
1028
1029 CleanupModule();
1030 EndCell();
1031
1032 if (in_module == (char)0) {
1033 Fprintf(stderr, "\"endmodule\" occurred outside of a module!\n");
1034 InputParseError(stderr);
1035 }
1036 in_module = (char)0;
1037
1038 if (*CellStackPtr) PopStack(CellStackPtr);
1039 if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
1040 SkipNewLine(VLOG_DELIMITERS);
1041 }
1042
1043 else if (match(nexttok, "`include")) {
1044 char *iname, *iptr, *quotptr, *pathend, *userpath = NULL;
1045
1046 SkipTokNoNewline(VLOG_DELIMITERS);
1047 if (nexttok == NULL) continue; /* Ignore if no filename */
1048
1049 // Any file included in another Verilog file needs to be
1050 // interpreted relative to the path of the parent Verilog file,
1051 // unless it's an absolute pathname.
1052
1053 pathend = strrchr(fname, '/');
1054 iptr = nexttok;
1055 while (*iptr == '\'' || *iptr == '\"') iptr++;
1056 if ((pathend != NULL) && (*iptr != '/') && (*iptr != '~')) {
1057 *pathend = '\0';
1058 iname = (char *)MALLOC(strlen(fname) + strlen(iptr) + 2);
1059 sprintf(iname, "%s/%s", fname, iptr);
1060 *pathend = '/';
1061 }
1062 #ifndef IBMPC
1063 else if ((*iptr == '~') && (*(iptr + 1) == '/')) {
1064 /* For ~/<path>, substitute tilde from $HOME */
1065 userpath = getenv("HOME");
1066 iname = (char *)MALLOC(strlen(userpath) + strlen(iptr));
1067 sprintf(iname, "%s%s", userpath, iptr + 1);
1068 }
1069 else if (*iptr == '~') {
1070 /* For ~<user>/<path>, substitute tilde from getpwnam() */
1071 struct passwd *passwd;
1072 char *pathstart;
1073 pathstart = strchr(iptr, '/');
1074 if (pathstart) *pathstart = '\0';
1075 passwd = getpwnam(iptr + 1);
1076 if (passwd != NULL) {
1077 userpath = passwd->pw_dir;
1078 if (pathstart) {
1079 *pathstart = '/';
1080 iname = (char *)MALLOC(strlen(userpath) + strlen(pathstart) + 1);
1081 sprintf(iname, "%s%s", userpath, pathstart);
1082 }
1083 else {
1084 /* Almost certainly an error, but make the substitution anyway */
1085 iname = STRDUP(userpath);
1086 }
1087 }
1088 else {
1089 /* Probably an error, but copy the filename verbatim */
1090 iname = STRDUP(iptr);
1091 }
1092 }
1093 #endif
1094 else
1095 iname = STRDUP(iptr);
1096
1097 // Eliminate any single or double quotes around the filename
1098 iptr = iname;
1099 quotptr = iptr;
1100 while (*quotptr != '\'' && *quotptr != '\"' &&
1101 *quotptr != '\0' && *quotptr != '\n') quotptr++;
1102 if (*quotptr == '\'' || *quotptr == '\"') *quotptr = '\0';
1103
1104 IncludeVerilog(iptr, filenum, CellStackPtr, blackbox);
1105 FREE(iname);
1106 SkipNewLine(VLOG_DELIMITERS);
1107 }
1108 else if (match(nexttok, "`define")) {
1109 struct property *kl = NULL;
1110
1111 // Pick up key-value pair and store in current cell
1112
1113 /* Parse for definitions used in expressions. Save */
1114 /* definitions in the "verilogdefs" hash table. */
1115
1116 SkipTokNoNewline(VLOG_DELIMITERS);
1117 if ((nexttok == NULL) || (nexttok[0] == '\0')) break;
1118
1119 kl = NewProperty();
1120 kl->key = strsave(nexttok);
1121 kl->idx = 0;
1122 kl->merge = MERGE_NONE;
1123
1124 SkipTokNoNewline(VLOG_DELIMITERS);
1125 if ((nexttok == NULL) || (nexttok[0] == '\0')) {
1126 // Let "`define X" be equivalent to "`define X 1". Use integer value.
1127 kl->type = PROP_INTEGER;
1128 kl->pdefault.ival = 1;
1129 kl->slop.ival = 0;
1130 }
1131 else if (nexttok[0] == '(') {
1132 /* For now, the netgen verilog parser doesn't handle `define f(X) ... */
1133 SkipNewLine(VLOG_DELIMITERS);
1134 FREE(kl->key);
1135 FREE(kl);
1136 kl = NULL;
1137 }
1138 else if (ConvertStringToInteger(nexttok, &ival) == 1) {
1139 /* Parameter parses as an integer */
1140 kl->type = PROP_INTEGER;
1141 kl->pdefault.ival = ival;
1142 kl->slop.ival = 0; // Exact match default
1143 }
1144 else if (ConvertStringToFloat(nexttok, &dval) == 1) {
1145 /* Parameter parses as a floating-point number */
1146 kl->type = PROP_DOUBLE;
1147 kl->pdefault.dval = dval;
1148 kl->slop.dval = 0.01; // One percent default
1149 }
1150 else {
1151 char *toks;
1152
1153 /* Treat the parameter as a string; BUT pull everything to */
1154 /* EOL, not just the current token. */
1155 toks = GetLineAtTok();
1156
1157 kl->type = PROP_STRING;
1158 kl->pdefault.string = strsave(toks);
1159 kl->slop.dval = 0.0;
1160
1161 SkipNewLine(VLOG_DELIMITERS);
1162 }
1163 if (kl) HashPtrInstall(kl->key, kl, &verilogdefs);
1164 }
1165 else if (match(nexttok, "`undef")) {
1166 struct property *kl = NULL;
1167
1168 SkipTokNoNewline(VLOG_DELIMITERS);
1169 if ((nexttok == NULL) || (nexttok[0] == '\0')) break;
1170
1171 kl = HashLookup(nexttok, &verilogdefs);
1172 if (kl != NULL) {
1173 HashDelete(nexttok, &verilogdefs);
1174 if (kl->type == PROP_STRING)
1175 if (kl->pdefault.string != NULL)
1176 FREE(kl->pdefault.string);
1177 FREE(kl->key);
1178 }
1179 /* Presumably it is not an error to undefine an undefined keyword */
1180 }
1181 else if (match(nexttok, "real") || match(nexttok, "integer")) {
1182 Printf("Ignoring '%s' in module '%s'\n", nexttok, model);
1183 /* Do not skip to end of module, as these can be in the middle of */
1184 /* I/O assignments, which need to be parsed. */
1185 while (!match(nexttok, ";")) SkipTok("X///**/X,;");
1186 continue;
1187 }
1188 else if (match(nexttok, "wire") || match(nexttok, "assign")) { /* wire = node */
1189 struct bus wb, wb2, *nb;
1190 char nodename[128], noderoot[100];
1191 int is_wire = match(nexttok, "wire");
1192 int j;
1193 struct objlist *lhs, *rhs;
1194
1195 /* Get left-hand side expression. If this is a wire statement, */
1196 /* then define the wire. If is_wire is false, then the wire */
1197 /* should already be defined. */
1198
1199 if (is_wire) {
1200 SkipTokNoNewline(VLOG_DELIMITERS);
1201 if (match(nexttok, "real"))
1202 SkipTokNoNewline(VLOG_DELIMITERS);
1203 else if (match(nexttok, "logic"))
1204 SkipTokNoNewline(VLOG_DELIMITERS);
1205
1206 if (GetBusTok(&wb) == 0) {
1207 /* Handle bus notation */
1208 SkipTokNoNewline(VLOG_DELIMITERS);
1209 strcpy(noderoot, nexttok);
1210 if (wb.start > wb.end) {
1211 for (i = wb.end; i <= wb.start; i++) {
1212 sprintf(nodename, "%s[%d]", nexttok, i);
1213 if (LookupObject(nodename, CurrentCell) == NULL)
1214 Node(nodename);
1215 if (i == wb.start) lhs = LookupObject(nodename, CurrentCell);
1216 }
1217 }
1218 else {
1219 for (i = wb.start; i <= wb.end; i++) {
1220 sprintf(nodename, "%s[%d]", nexttok, i);
1221 if (LookupObject(nodename, CurrentCell) == NULL)
1222 Node(nodename);
1223 if (i == wb.start) lhs = LookupObject(nodename, CurrentCell);
1224 }
1225 }
1226 nb = NewBus();
1227 nb->start = wb.start;
1228 nb->end = wb.end;
1229 HashPtrInstall(nexttok, nb, &buses);
1230 }
1231 else {
1232 if (LookupObject(nexttok, CurrentCell) == NULL) {
1233 Node(nexttok);
1234 lhs = LookupObject(nexttok, CurrentCell);
1235 }
1236 }
1237 while (1) {
1238 SkipTokNoNewline(VLOG_DELIMITERS);
1239 if (match(nexttok, ",")) {
1240 SkipTokComments(VLOG_DELIMITERS);
1241 if (LookupObject(nexttok, CurrentCell) == NULL) {
1242 Node(nexttok);
1243 lhs = LookupObject(nexttok, CurrentCell);
1244 }
1245 }
1246 else break;
1247 }
1248 }
1249 else { /* "assign" */
1250 SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
1251 if (GetBus(nexttok, &wb) == 0) {
1252 char *aptr = strvchr(nexttok, '[');
1253 if (aptr != NULL) {
1254 *aptr = '\0';
1255 /* Find object of first net in bus */
1256 strcpy(noderoot, nexttok);
1257 sprintf(nodename, "%s[%d]", nexttok, wb.start);
1258 lhs = LookupObject(nodename, CurrentCell);
1259 *aptr = '[';
1260 }
1261 else {
1262 strcpy(noderoot, nexttok);
1263 /* Set LHS to the start of the vector */
1264 sprintf(nodename, "%s[%d]", nexttok, wb.start);
1265 lhs = LookupObject(nodename, CurrentCell);
1266 }
1267 }
1268 else {
1269 lhs = LookupObject(nexttok, CurrentCell);
1270 strcpy(noderoot, nexttok);
1271 }
1272 SkipTokComments(VLOG_DELIMITERS);
1273 if (lhs && ((!nexttok) || (!match(nexttok, "=")))) {
1274 fprintf(stderr, "Empty assignment for net %s\n", lhs->name);
1275 }
1276 }
1277
1278 /* Check for assignment statement, and handle any allowed uses. */
1279 /* Any uses other than those mentioned below will cause the entire */
1280 /* module to be treated as a black box. */
1281
1282 // Allowed uses of "assign" for netlists:
1283 // "assign a = b" joins two nets.
1284 // "assign a = {b, c, ...}" creates a bus from components.
1285 // "assign" using any boolean arithmetic is not structural verilog.
1286
1287 if (nexttok && match(nexttok, "=")) {
1288 char assignname[128], assignroot[100];
1289
1290 i = wb.start;
1291 while (1) {
1292 SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
1293 if (!nexttok) break;
1294
1295 if (match(nexttok, "{")) {
1296 /* RHS is a bundle */
1297 continue;
1298 }
1299 else if (match(nexttok, "}")) {
1300 /* End of bundle */
1301 continue;
1302 }
1303 else if (match(nexttok, ",")) {
1304 /* Additional signals in bundle */
1305 continue;
1306 }
1307 else if (match(nexttok, ";")) {
1308 /* End of assignment */
1309 break;
1310 }
1311 else {
1312 if (GetBus(nexttok, &wb2) == 0) {
1313 char *aptr = strvchr(nexttok, '[');
1314 j = wb2.start;
1315 if (aptr != NULL) {
1316 *aptr = '\0';
1317 strcpy(assignroot, nexttok);
1318 sprintf(assignname, "%s[%d]", nexttok, j);
1319 rhs = LookupObject(assignname, CurrentCell);
1320 *aptr = '[';
1321 }
1322 }
1323 else {
1324 j = -1;
1325 rhs = LookupObject(nexttok, CurrentCell);
1326 }
1327 if ((lhs == NULL) || (rhs == NULL)) {
1328 if (rhs != NULL) {
1329 Printf("Improper assignment; left-hand side cannot "
1330 "be parsed.\n");
1331 if (j != -1)
1332 Printf("Right-hand side is \"%s\".\n", assignroot);
1333 else
1334 Printf("Right-hand side is \"%s\".\n", rhs->name);
1335 Printf("Improper expression is \"%s\".\n", nexttok);
1336 break;
1337 }
1338 if (lhs != NULL) {
1339 Printf("Improper assignment; right-hand side cannot "
1340 "be parsed.\n");
1341 if (i != -1)
1342 Printf("Left-hand side is \"%s\".\n", noderoot);
1343 else
1344 Printf("Left-hand side is \"%s\".\n", lhs->name);
1345 Printf("Improper expression is \"%s\".\n", nexttok);
1346 /* Not parsable, probably behavioral verilog? */
1347 Printf("Module '%s' is not structural verilog, "
1348 "making black-box.\n", model);
1349 SetClass(CLASS_MODULE);
1350 goto skip_endmodule;
1351 }
1352 }
1353 while (1) {
1354 /* Assign bits in turn from bundle in RHS to bits of LHS */
1355 /* until bits in signal are exhausted or LHS is full. */
1356
1357 if (i != -1)
1358 sprintf(nodename, "%s[%d]", noderoot, i);
1359 else
1360 sprintf(nodename, lhs->name);
1361 if (j != -1)
1362 sprintf(assignname, "%s[%d]", assignroot, j);
1363 else
1364 sprintf(assignname, rhs->name);
1365
1366 join(nodename, assignname);
1367
1368 if (i == wb.end) break;
1369 i += (wb.end > wb.start) ? 1 : -1;
1370
1371 if (j == wb2.end) break;
1372 j += (wb2.end > wb2.start) ? 1 : -1;
1373 }
1374 }
1375 }
1376 }
1377 while (nexttok && !match(nexttok, ";"))
1378 SkipTokComments(VLOG_DELIMITERS);
1379 }
1380 else if (match(nexttok, "endmodule")) {
1381 // No action---new module is started with next 'module' statement,
1382 // if any.
1383 SkipNewLine(VLOG_DELIMITERS);
1384 in_module = (char)0; /* Should have been done already */
1385 }
1386 else if (nexttok[0] == '`') {
1387 // Ignore any other directive starting with a backtick (e.g., `timescale)
1388 SkipNewLine(VLOG_DELIMITERS);
1389 }
1390 else if (match(nexttok, "reg") || match(nexttok, "always") ||
1391 match(nexttok, "specify") || match(nexttok, "initial")) {
1392 Printf("Behavioral keyword '%s' found in source.\n", nexttok);
1393 Printf("Module '%s' is not structural verilog, making black-box.\n", model);
1394 // To be done: Remove any contents (but may not be necessary)
1395 // Recast as module
1396 SetClass(CLASS_MODULE);
1397 goto skip_endmodule;
1398 }
1399 else { /* module instances */
1400 char instancename[100], modulename[100];
1401 int itype, arraystart, arrayend, arraymax, arraymin;
1402 char ignore;
1403
1404 instancename[99] = '\0';
1405 modulename[99] = '\0';
1406
1407 struct portelement {
1408 char *name; // Name of port in subcell
1409 char *net; // Name of net connecting to port in the parent
1410 int width; // Width of port, if port is a bus
1411 char flags; // Used for marking if port was added into netlist
1412 struct portelement *next;
1413 };
1414
1415 struct portelement *head, *tail, *scan, *last, *scannext;
1416 struct objlist *obptr;
1417
1418 strncpy(modulename, nexttok, 99);
1419
1420 /* If module name is a verilog primitive, then treat the module as a */
1421 /* black box (this is not a complete list. Preferable to use hash */
1422 /* function instead of lots of strcmp() calls). */
1423
1424 if (!strcmp(modulename, "buf") || !strcmp(modulename, "notif1") ||
1425 !strcmp(modulename, "not") || !strcmp(modulename, "and") ||
1426 !strcmp(modulename, "or") || !strcmp(modulename, "bufif0") ||
1427 !strcmp(modulename, "bufif1") || !strcmp(modulename, "notif0")) {
1428
1429 Printf("Module contains verilog primitive '%s'.\n", nexttok);
1430 Printf("Module '%s' is not structural verilog, making black-box.\n", model);
1431 SetClass(CLASS_MODULE);
1432 goto skip_endmodule;
1433 }
1434
1435 if (!(*CellStackPtr)) {
1436 CellDef(fname, filenum);
1437 PushStack(fname, CellStackPtr);
1438 }
1439
1440 SkipTokComments(VLOG_DELIMITERS);
1441
1442 nextinst:
1443 ignore = FALSE;
1444 head = NULL;
1445 tail = NULL;
1446
1447 // Next token must be '#(' (parameters) or an instance name
1448
1449 if (match(nexttok, "#(")) {
1450
1451 // Read the parameter list
1452 SkipTokComments(VLOG_DELIMITERS);
1453
1454 while (nexttok != NULL) {
1455 char *paramname;
1456
1457 if (match(nexttok, ")")) {
1458 SkipTokComments(VLOG_DELIMITERS);
1459 break;
1460 }
1461 else if (match(nexttok, ",")) {
1462 SkipTokComments(VLOG_DELIMITERS);
1463 continue;
1464 }
1465
1466 // We need to look for parameters of the type ".name(value)"
1467
1468 else if (nexttok[0] == '.') {
1469 paramname = strsave(nexttok + 1);
1470 SkipTokComments(VLOG_DELIMITERS);
1471 if (!match(nexttok, "(")) {
1472 Printf("Error: Expecting parameter value, got %s.\n", nexttok);
1473 }
1474 SkipTokComments(VLOG_DELIMITERS);
1475 if (match(nexttok, ")")) {
1476 Printf("Error: Parameter with no value found.\n");
1477 }
1478 else {
1479 AddProperty(&kvlist, paramname, nexttok);
1480 SkipTokComments(VLOG_DELIMITERS);
1481 if (!match(nexttok, ")")) {
1482 Printf("Error: Expecting end of parameter value, "
1483 "got %s.\n", nexttok);
1484 }
1485 }
1486 FREE(paramname);
1487 }
1488 SkipTokComments(VLOG_DELIMITERS);
1489 }
1490 if (!nexttok) {
1491 Printf("Error: Still reading module, but got end-of-file.\n");
1492 goto skip_endmodule;
1493 }
1494 }
1495
1496 strncpy(instancename, nexttok, 99);
1497 /* Printf("Diagnostic: new instance is %s\n", instancename); */
1498 SkipTokComments(VLOG_DELIMITERS);
1499
1500 arraystart = arrayend = -1;
1501 if (match(nexttok, "[")) {
1502 // Handle instance array notation.
1503 struct bus wb;
1504 if (GetBusTok(&wb) == 0) {
1505 arraystart = wb.start;
1506 arrayend = wb.end;
1507 }
1508 SkipTokComments(VLOG_DELIMITERS);
1509 }
1510
1511 if (match(nexttok, "(")) {
1512 char savetok = (char)0;
1513 struct portelement *new_port;
1514
1515 // Read the pin list
1516 while (nexttok != NULL) {
1517 SkipTokComments(VLOG_DELIMITERS);
1518 if (match(nexttok, ")")) break;
1519 else if (match(nexttok, ",")) continue;
1520
1521 // We need to look for pins of the type ".name(value)"
1522
1523 if (nexttok[0] != '.') {
1524 Printf("Warning: Ignoring subcircuit with no pin names "
1525 "at \"%s\"\n", nexttok);
1526 InputParseError(stderr);
1527 while (nexttok != NULL) {
1528 SkipTokComments(VLOG_DELIMITERS);
1529 if (match(nexttok, ";")) break;
1530 }
1531 ignore = TRUE;
1532 break;
1533 }
1534 else {
1535 new_port = (struct portelement *)CALLOC(1, sizeof(struct portelement));
1536 new_port->name = strsave(nexttok + 1);
1537 new_port->width = -1;
1538 new_port->flags = PORT_NOT_FOUND;
1539 SkipTokComments(VLOG_DELIMITERS);
1540 if (!match(nexttok, "(")) {
1541 Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok);
1542 SkipNewLine(VLOG_DELIMITERS);
1543 }
1544 SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
1545 if (match(nexttok, ")")) {
1546 char localnet[100];
1547 // Empty parens, so create a new local node
1548 savetok = (char)1;
1549 if (arraystart != -1) {
1550 /* No-connect on an instance array must also be an array */
1551 sprintf(localnet, "_noconnect_%d_[%d:%d]", localcount++,
1552 arraystart, arrayend);
1553 }
1554 else
1555 sprintf(localnet, "_noconnect_%d_", localcount++);
1556 new_port->net = strsave(localnet);
1557 }
1558 else {
1559 if (!strcmp(nexttok, "{")) {
1560 char *wire_bundle = (char *)MALLOC(1);
1561 char *new_wire_bundle = NULL;
1562 *wire_bundle = '\0';
1563 /* Wire bundle---read to "}" */
1564 while (nexttok) {
1565 new_wire_bundle = (char *)MALLOC(strlen(wire_bundle) +
1566 strlen(nexttok) + 1);
1567 /* Roundabout way to do realloc() becase there is no REALLOC() */
1568 strcpy(new_wire_bundle, wire_bundle);
1569 strcat(new_wire_bundle, nexttok);
1570 FREE(wire_bundle);
1571 wire_bundle = new_wire_bundle;
1572 if (!strcmp(nexttok, "}")) break;
1573 SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
1574 }
1575 if (!nexttok) {
1576 Printf("Unterminated net in pin %s\n", wire_bundle);
1577 }
1578 new_port->net = wire_bundle;
1579 }
1580 else if (nexttok[0] == '~' || nexttok[0] == '!' || nexttok[0] == '-') {
1581 /* All of these imply that the signal is logically manipulated */
1582 /* in turn implying behavioral code. */
1583 Printf("Module '%s' is not structural verilog, "
1584 "making black-box.\n", model);
1585 SetClass(CLASS_MODULE);
1586 goto skip_endmodule;
1587 }
1588 else
1589 new_port->net = strsave(nexttok);
1590
1591 /* Read array information along with name; will be parsed later */
1592 SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
1593 if (match(nexttok, "[")) {
1594 /* Check for space between name and array identifier */
1595 SkipTokComments(VLOG_PIN_NAME_DELIMITERS);
1596 if (!match(nexttok, ")")) {
1597 char *expnet;
1598 expnet = (char *)MALLOC(strlen(new_port->net)
1599 + strlen(nexttok) + 2);
1600 sprintf(expnet, "%s[%s", new_port->net, nexttok);
1601 FREE(new_port->net);
1602 new_port->net = expnet;
1603 }
1604 SkipTokComments(VLOG_DELIMITERS);
1605 }
1606
1607 if (!match(nexttok, ")")) {
1608 Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok);
1609 SkipNewLine(VLOG_DELIMITERS);
1610 }
1611 }
1612
1613 if (head == NULL) head = new_port;
1614 else tail->next = new_port;
1615 new_port->next = NULL;
1616 tail = new_port;
1617 }
1618 }
1619 }
1620 else {
1621 Printf("Expected to find instance pin block but got \"%s\"\n", nexttok);
1622 }
1623 if (ignore == TRUE) continue; /* moving along. . . */
1624
1625 /* Verilog allows multiple instances of a single cell type to be chained */
1626 /* together with commas. */
1627
1628 SkipTokComments(VLOG_DELIMITERS);
1629 if (match(nexttok, ",")) {
1630 goto nextinst;
1631 }
1632
1633 /* Otherwise, instance must end with a semicolon */
1634
1635 else if (!match(nexttok, ";")) {
1636 Printf("Expected to find end of instance but got \"%s\"\n", nexttok);
1637 InputParseError(stderr);
1638 }
1639
1640 /* Check for ignored class */
1641
1642 if ((itype = IsIgnored(modulename, filenum)) == IGNORE_CLASS) {
1643 Printf("Class '%s' instanced in input but is being ignored.\n", model);
1644 return;
1645 }
1646
1647 /* Check for shorted pins */
1648
1649 if ((itype == IGNORE_SHORTED) && (head != NULL)) {
1650 unsigned char shorted = (unsigned char)1;
1651 struct portelement *p;
1652 for (p = head->next; p; p = p->next) {
1653 if (strcasecmp(head->name, p->name))
1654 shorted = (unsigned char)0;
1655 break;
1656 }
1657 if (shorted == (unsigned char)1) {
1658 Printf("Instance of '%s' is shorted, ignoring.\n", modulename);
1659 while (head) {
1660 p = head->next;
1661 FREE(head);
1662 head = p;
1663 }
1664 return;
1665 }
1666 }
1667
1668 if (head == NULL) {
1669 Fprintf(stderr, "Warning: Cell %s has no pins\n", modulename);
1670 }
1671
1672 /* Check that the module exists. If not, generate an empty */
1673 /* module entry matching the call. */
1674
1675 tp = LookupCellFile(modulename, filenum);
1676 if (tp == NULL) {
1677 struct bus wb, pb;
1678 char defport[128];
1679
1680 Fprintf(stdout, "Creating placeholder cell definition for "
1681 "module %s.\n", modulename);
1682 CellDef(modulename, filenum);
1683 CurrentCell->flags |= CELL_PLACEHOLDER;
1684 for (scan = head; scan != NULL; scan = scan->next) {
1685 // Check if net name is a wire bus or portion of a bus
1686 if (GetBus(scan->net, &wb) == 0) {
1687 int range;
1688
1689 // This takes care of three situations:
1690 // (1) The signal bus length matches the number of instances:
1691 // apply one signal per instance.
1692 // (2) The signal bus length is a multiple of the number of instances:
1693 // apply a signal sub-bus to each instance.
1694 // (3) The number of instances is a multiple of the signal bus length:
1695 // apply the same signal to each instance.
1696
1697 if ((arrayend - arraystart) == (wb.end - wb.start)) {
1698 // Net is a bus, but net is split over arrayed instances
1699 Port(scan->name);
1700 }
1701 else if (wb.start > wb.end) {
1702 if ((arraystart - arrayend) > (wb.start - wb.end))
1703 range = (((arraystart - arrayend) + 1) /
1704 ((wb.start - wb.end) + 1)) - 1;
1705 else
1706 range = (((wb.start - wb.end) + 1) /
1707 ((arraystart - arrayend) + 1)) - 1;
1708
1709 for (i = range; i >= 0; i--) {
1710 sprintf(defport, "%s[%d]", scan->name, i);
1711 Port(defport);
1712 }
1713 }
1714 else {
1715 if ((arrayend - arraystart) > (wb.end - wb.start))
1716 range = (((arrayend - arraystart) + 1) /
1717 ((wb.end - wb.start) + 1)) - 1;
1718 else
1719 range = (((wb.end - wb.start) + 1) /
1720 ((arrayend - arraystart) + 1)) - 1;
1721
1722 for (i = 0; i <= range; i++) {
1723 sprintf(defport, "%s[%d]", scan->name, i);
1724 Port(defport);
1725 }
1726 }
1727 }
1728 else {
1729 Port(scan->name);
1730 }
1731 }
1732 if (head == NULL) {
1733 Port((char *)NULL); // Must have something for pin 1
1734 }
1735 SetClass(CLASS_MODULE);
1736 tp = CurrentCell;
1737 EndCell();
1738 ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
1739 }
1740
1741 /* Work through scan list and expand ports/nets that are arrays */
1742
1743 last = (struct portelement *)NULL;
1744 scan = head;
1745 while (scan != NULL) {
1746 int portstart, portend, portnum;
1747
1748 scannext = scan->next;
1749 portstart = -1;
1750
1751 for (obptr = tp->cell; obptr && obptr->type == PORT; obptr = obptr->next) {
1752 char *delimiter;
1753 if ((delimiter = strrchr(obptr->name, '[')) != NULL) {
1754 *delimiter = '\0';
1755 if ((*matchfunc)(obptr->name, scan->name)) {
1756 if (sscanf(delimiter + 1, "%d", &portnum) == 1) {
1757 if (portstart == -1)
1758 portstart = portnum;
1759 else
1760 portend = portnum;
1761 }
1762 }
1763 *delimiter = '[';
1764 }
1765 }
1766 if (portstart != -1) {
1767 struct bus wb;
1768 struct portelement *new_port;
1769 char vname[256];
1770 int j, result;
1771 struct objlist *bobj;
1772 char *bptr;
1773 int minnet, maxnet, testidx, width;
1774
1775 width = portstart - portend;
1776 if (width < 0) width = -width;
1777 width++;
1778 scan->width = width;
1779
1780 result = GetBus(scan->net, &wb);
1781 if (result == -1) {
1782 /* CHECK: THIS CODE SHOULD BE DELETED, IT IS NOT THE ISSUE */
1783 /* Not bus notation, but check if signal was defined as a bus */
1784 wb.start = wb.end = -1;
1785 minnet = maxnet = -1;
1786
1787 /* Pins should be in index order start->end. Other nodes */
1788 /* should be in order start->end by node number. */
1789
1790 for (bobj = CurrentCell->cell; bobj; bobj = bobj->next) {
1791 if (bobj->type == PORT) {
1792 if ((bptr = strvchr(bobj->name, '[')) != NULL) {
1793 *bptr = '\0';
1794 if (!strcmp(bobj->name, scan->net)) {
1795 *bptr = '[';
1796 if (wb.start == -1)
1797 sscanf(bptr + 1, "%d", &wb.start);
1798 else
1799 sscanf(bptr + 1, "%d", &wb.end);
1800 }
1801 }
1802 }
1803 else if (bobj->type == NODE) {
1804 if ((bptr = strvchr(bobj->name, '[')) != NULL) {
1805 *bptr = '\0';
1806 if (!strcmp(bobj->name, scan->net)) {
1807 if (sscanf(bptr + 1, "%d", &testidx) == 1) {
1808 if (minnet == -1) {
1809 minnet = maxnet = bobj->node;
1810 wb.start = wb.end = testidx;
1811 }
1812 else if (bobj->node < minnet) {
1813 minnet = bobj->node;
1814 wb.start = testidx;
1815 }
1816 else if (bobj->node > maxnet) {
1817 maxnet = bobj->node;
1818 wb.end = testidx;
1819 }
1820 }
1821 }
1822 *bptr = '[';
1823 }
1824 }
1825 }
1826 if (wb.start != -1) result = 0;
1827 }
1828
1829 if (result == 0) {
1830 int match = 0;
1831 int wblen, arraylen;
1832
1833 arraylen = arraystart - arrayend;
1834 wblen = wb.start - wb.end;
1835
1836 if (arraylen < 0) arraylen = -arraylen;
1837 if (wblen < 0) wblen = -wblen;
1838
1839 arraylen++;
1840 wblen++;
1841
1842 if ((scan->width * arraylen) == wblen) match = 1;
1843 else if (wblen == scan->width) match = 1;
1844 else if (wblen == arraylen) match = 1;
1845 else {
1846 Fprintf(stderr, "Warning: Net %s bus width (%d) does not match "
1847 "port %s bus width (%d) or array width (%d).\n",
1848 scan->net, wblen, scan->name, scan->width, arraylen);
1849 }
1850
1851 // Net is bit-sliced across array of instances.
1852
1853 if (wb.start > wb.end) {
1854 char *bptr = NULL, *cptr = NULL, cchar, *netname;
1855 unsigned char is_bundle = 0;
1856 struct bus wbb;
1857
1858 i = wb.start;
1859 j = portstart;
1860
1861 netname = scan->net;
1862 if (*netname == '{') {
1863 is_bundle = 1;
1864 netname++;
1865 cptr = strvchr(netname, ',');
1866 if (cptr == NULL) cptr = strvchr(netname, '}');
1867 if (cptr == NULL) cptr = netname + strlen(netname) - 1;
1868 cchar = *cptr;
1869 *cptr = '\0';
1870 }
1871
1872 // Remove indexed part of scan->net
1873 if (GetBus(netname, &wbb) == 0) {
1874 i = wbb.start;
1875 if ((bptr = strvchr(netname, '[')) != NULL)
1876 *bptr = '\0';
1877 }
1878 else
1879 i = -1;
1880
1881 while (1) {
1882 new_port = (struct portelement *)CALLOC(1,
1883 sizeof(struct portelement));
1884 sprintf(vname, "%s[%d]", scan->name, j);
1885 new_port->name = strsave(vname);
1886 if (i == -1)
1887 sprintf(vname, "%s", netname);
1888 else
1889 sprintf(vname, "%s[%d]", netname, i);
1890 new_port->net = strsave(vname);
1891 new_port->width = scan->width;
1892
1893 if (last == NULL)
1894 head = new_port;
1895 else
1896 last->next = new_port;
1897
1898 new_port->next = scannext;
1899 last = new_port;
1900
1901 if (j == portend) break;
1902
1903 if (portstart > portend) j--;
1904 else j++;
1905 if (i != -1) {
1906 if (wbb.start > wbb.end) i--;
1907 else i++;
1908 }
1909
1910 if (is_bundle &&
1911 ((i == -1) ||
1912 ((wbb.start > wbb.end) && (i < wbb.end)) ||
1913 ((wbb.start <= wbb.end) && (i > wbb.end)))) {
1914 if (bptr) *bptr = '[';
1915
1916 netname = cptr + 1;
1917 if (cptr) *cptr = cchar; /* Restore previous bundle delimiter */
1918 cptr = strvchr(netname, ',');
1919 if (cptr == NULL) cptr = strvchr(netname, '}');
1920 if (cptr == NULL) cptr = netname + strlen(netname) - 1;
1921 cchar = *cptr;
1922 *cptr = '\0';
1923
1924 if (GetBus(netname, &wbb) == 0) {
1925 i = wbb.start;
1926 if ((bptr = strvchr(netname, '[')) != NULL)
1927 *bptr = '\0';
1928 }
1929 else i = -1;
1930 }
1931 }
1932 FREE(scan);
1933 scan = last;
1934 if (cptr) *cptr = cchar; /* Restore bundle delimiter */
1935 }
1936 }
1937 else if (portstart != portend) {
1938 Fprintf(stderr, "Error: Single net %s is connected to bus port %s\n",
1939 scan->net, scan->name);
1940 }
1941 }
1942 last = scan;
1943 scan = scannext;
1944 }
1945
1946 arraymax = (arraystart > arrayend) ? arraystart : arrayend;
1947 arraymin = (arraystart > arrayend) ? arrayend : arraystart;
1948
1949 for (i = arraymin; i <= arraymax; i++) {
1950 char *brackptr;
1951 int j;
1952 char locinst[128];
1953
1954 if (i != -1)
1955 sprintf(locinst, "%s[%d]", instancename, i);
1956 else
1957 strcpy(locinst, instancename);
1958 Instance(modulename, locinst);
1959 LinkProperties(modulename, kvlist);
1960
1961 obptr = LookupInstance(locinst, CurrentCell);
1962 if (obptr != NULL) {
1963 do {
1964 struct bus wb, wb2;
1965 char *obpinname;
1966 int obpinidx;
1967
1968 // NOTE: Verilog allows any order of pins, since both the
1969 // instance and cell pin names are given. So for each pin
1970 // in obptr (which defines the pin order) , we have to find
1971 // the corresponding pin in the scan list.
1972
1973 obpinname = strrchr(obptr->name, '/');
1974 if (!obpinname) break;
1975 obpinname++;
1976
1977 scan = head;
1978 obpinidx = -1;
1979 while (scan != NULL) {
1980 if (match(obpinname, scan->name)) {
1981 scan->flags |= PORT_FOUND;
1982 break;
1983 }
1984 scan = scan->next;
1985 }
1986 if (scan == NULL) {
1987 char localnet[100];
1988
1989 /* Assume an implicit unconnected pin */
1990 sprintf(localnet, "_noconnect_%d_", localcount++);
1991 Node(localnet);
1992 join(localnet, obptr->name);
1993 Fprintf(stderr,
1994 "Note: Implicit pin %s in instance %s of %s in cell %s\n",
1995 obpinname, locinst, modulename, CurrentCell->name);
1996 }
1997 else if (GetBus(scan->net, &wb) == 0) {
1998 char *bptr2;
1999 char *scanroot;
2000 scanroot = strsave(scan->net);
2001 brackptr = strvchr(scanroot, '[');
2002 if (brackptr) *brackptr = '\0';
2003
2004 if (arraystart == -1) {
2005 // Port may be an array
2006 int range;
2007 char pinname[128];
2008
2009 // Check if port is an array
2010 if (obpinidx == -1) {
2011 if (wb.start != wb.end) {
2012 Printf("Error: Bus connected to single port\n");
2013 }
2014 // Use only the first bit of the bus
2015 sprintf(pinname, "%s[%d]", scanroot, wb.start);
2016 if (LookupObject(pinname, CurrentCell) == NULL)
2017 Node(pinname);
2018 join(pinname, obptr->name);
2019 if (brackptr) *brackptr = '[';
2020 }
2021 else {
2022 // NOTE: Making unsupportable assumption that
2023 // pin and port indexes match---need to fix this!
2024 sprintf(pinname, "%s[%d]", scanroot, obpinidx);
2025 if (LookupObject(pinname, CurrentCell) == NULL)
2026 Node(pinname);
2027 join(pinname, obptr->name);
2028 }
2029 }
2030 else {
2031 // Instance must be an array
2032 char netname[128];
2033 int slice, portlen, siglen;
2034
2035 /* Get the array size of the port for bit slicing */
2036 portlen = (scan->width < 0) ? 1 : scan->width;
2037
2038 /* Get the full array size of the connecting bus */
2039 GetBus(scanroot, &wb2);
2040 siglen = wb2.start - wb2.end;
2041 if (siglen < 0) siglen = -siglen;
2042 siglen++;
2043
2044 // If signal array is smaller than the portlength *
2045 // length of instance array, then the signal wraps.
2046
2047 if (wb2.start >= wb2.end && arraystart >= arrayend) {
2048 slice = wb.start - (arraystart - i) * portlen;
2049 while (slice < wb2.end) slice += siglen;
2050 }
2051 else if (wb2.start < wb2.end && arraystart > arrayend) {
2052 slice = wb.start + (arraystart - i) * portlen;
2053 while (slice > wb2.end) slice -= siglen;
2054 }
2055 else if (wb2.start > wb2.end && arraystart < arrayend) {
2056 slice = wb.start - (arraystart + i) * portlen;
2057 while (slice < wb2.end) slice += siglen;
2058 }
2059 else { // (wb2.start < wb2.end && arraystart < arrayend)
2060 slice = wb.start + (arraystart + i) * portlen;
2061 while (slice > wb2.end) slice -= siglen;
2062 }
2063
2064 sprintf(netname, "%s[%d]", scanroot, slice);
2065 if (LookupObject(netname, CurrentCell) == NULL) Node(netname);
2066 join(netname, obptr->name);
2067 }
2068 FREE(scanroot);
2069 }
2070 else {
2071 if (LookupObject(scan->net, CurrentCell) == NULL) Node(scan->net);
2072 join(scan->net, obptr->name);
2073 }
2074
2075 /* Before exiting the loop, check if all ports in the */
2076 /* scan list were handled. */
2077
2078 if ((obptr->next == NULL) || (obptr->next->type <= FIRSTPIN)) {
2079 for (scan = head; scan; scan = scan->next) {
2080 if (!(scan->flags & PORT_FOUND)) {
2081 if (tp->flags & CELL_PLACEHOLDER) {
2082 char tempname[128];
2083 int maxnode;
2084
2085 /* This pin was probably implicit in the first call */
2086 /* and so it needs to be added to the definition. */
2087
2088 ReopenCellDef(modulename, filenum);
2089 Port(scan->name);
2090 ReopenCellDef((*CellStackPtr)->cellname, filenum);
2091
2092 /* obptr->next now gets the new port. Update the */
2093 /* port number, and copy class and instance name. */
2094 nobj = GetObject();
2095 sprintf(tempname, "%s%s%s", obptr->instance.name,
2096 SEPARATOR, scan->name);
2097 nobj->name = strsave(tempname);
2098 nobj->model.class = strsave(obptr->model.class);
2099 nobj->instance.name = strsave(obptr->instance.name);
2100 nobj->type = obptr->type + 1;
2101 nobj->next = obptr->next;
2102 nobj->node = -1;
2103 obptr->next = nobj;
2104 HashPtrInstall(nobj->name, nobj, &(CurrentCell->objdict));
2105
2106 if (LookupObject(scan->net, CurrentCell) == NULL)
2107 Node(scan->net);
2108 join(scan->net, nobj->name);
2109 scan->flags |= PORT_FOUND;
2110
2111 /* Now any previous instance of the same cell must */
2112 /* insert the same additional pin as a no-connect. */
2113 /* NOTE: This should be running a callback on all */
2114 /* cells in the file, not just CurrentCell. */
2115
2116 for (sobj = CurrentCell->cell; sobj && (sobj != obptr);
2117 sobj = sobj->next) {
2118 if (sobj->type == FIRSTPIN) {
2119 if (match(sobj->model.class, obptr->model.class)) {
2120 while (sobj->next->type > FIRSTPIN)
2121 sobj = sobj->next;
2122 /* Stop when reaching the current instance */
2123 if (sobj->type == obptr->type + 1) break;
2124 nobj = GetObject();
2125 sprintf(tempname, "%s%s%s", sobj->instance.name,
2126 SEPARATOR, scan->name);
2127 nobj->name = strsave(tempname);
2128 nobj->model.class = strsave(sobj->model.class);
2129 nobj->instance.name = strsave(sobj->instance.name);
2130 nobj->type = obptr->type + 1;
2131 nobj->node = -1;
2132 nobj->next = sobj->next;
2133 sobj->next = nobj;
2134 HashPtrInstall(nobj->name, nobj,
2135 &(CurrentCell->objdict));
2136
2137 sprintf(tempname, "_noconnect_%d_", localcount++);
2138 Node(tempname);
2139 join(tempname, nobj->name);
2140 Fprintf(stderr, "Note: Implicit pin %s in instance "
2141 "%s of %s in cell %s\n",
2142 scan->name, sobj->instance.name,
2143 modulename, CurrentCell->name);
2144 }
2145 }
2146 }
2147 }
2148 else {
2149 Fprintf(stderr, "Error: Instance %s has pin %s which is "
2150 "not in the %s cell definition.\n",
2151 locinst, scan->name, modulename);
2152 }
2153 }
2154 }
2155 }
2156
2157 obptr = obptr->next;
2158 } while (obptr != NULL && obptr->type > FIRSTPIN);
2159 }
2160 if (i == -1) break; /* No array */
2161 }
2162 DeleteProperties(&kvlist);
2163
2164 /* free up the allocated list */
2165 scan = head;
2166 while (scan != NULL) {
2167 scannext = scan->next;
2168 FREE(scan->name);
2169 FREE(scan->net);
2170 FREE(scan);
2171 scan = scannext;
2172 }
2173 }
2174 continue;
2175
2176 baddevice:
2177 Fprintf(stderr, "Badly formed line in input.\n");
2178 }
2179
2180 /* Watch for bad ending syntax */
2181
2182 if (in_module == (char)1) {
2183 Fprintf(stderr, "Missing \"endmodule\" statement in module.\n");
2184 InputParseError(stderr);
2185 }
2186
2187 if (*(CellStackPtr)) {
2188 CleanupModule();
2189 EndCell();
2190 if (*CellStackPtr) PopStack(CellStackPtr);
2191 if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
2192 }
2193
2194 if (warnings)
2195 Fprintf(stderr, "File %s read with %d warning%s.\n", fname,
2196 warnings, (warnings == 1) ? "" : "s");
2197 }
2198
2199 /*----------------------------------------------*/
2200 /* Top-level verilog module file read routine */
2201 /*----------------------------------------------*/
2202
ReadVerilogTop(char * fname,int * fnum,int blackbox)2203 char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
2204 {
2205 struct property *kl = NULL;
2206 struct cellstack *CellStack = NULL;
2207 struct nlist *tp;
2208 int filenum;
2209
2210 // Make sure CurrentCell is clear
2211 CurrentCell = NULL;
2212
2213 if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
2214
2215 if (strchr(fname, '.') == NULL) {
2216 char name[1024];
2217 SetExtension(name, fname, VERILOG_EXTENSION);
2218 if ((filenum = OpenParseFile(name, *fnum)) < 0) {
2219 Fprintf(stderr, "Error in Verilog file read: No file %s\n", name);
2220 *fnum = filenum;
2221 return NULL;
2222 }
2223 }
2224 else {
2225 Fprintf(stderr, "Error in Verilog file read: No file %s\n", fname);
2226 *fnum = filenum;
2227 return NULL;
2228 }
2229 }
2230
2231 /* All Verilog file reading is case sensitive. However: if */
2232 /* a SPICE file was read before it, then it will be forced to */
2233 /* be case insensitive, with a stern warning. */
2234
2235 if (matchfunc == matchnocase) {
2236 Printf("Warning: A case-insensitive file has been read and so the "
2237 "verilog file must be treated case-insensitive to match.\n");
2238 }
2239 else {
2240 matchfunc = match;
2241 matchintfunc = matchfile;
2242 hashfunc = hashcase;
2243 }
2244
2245 InitializeHashTable(&verilogparams, OBJHASHSIZE);
2246 InitializeHashTable(&verilogdefs, OBJHASHSIZE);
2247 definitions = &verilogdefs;
2248
2249 /* Add the pre-defined key "LVS" to verilogdefs */
2250
2251 kl = NewProperty();
2252 kl->merge = MERGE_NONE;
2253 kl->key = strsave("LVS");
2254 kl->idx = 0;
2255 kl->type = PROP_INTEGER;
2256 kl->slop.ival = 0;
2257 kl->pdefault.ival = 1;
2258 HashPtrInstall(kl->key, kl, &verilogdefs);
2259
2260 ReadVerilogFile(fname, filenum, &CellStack, blackbox);
2261 CloseParseFile();
2262
2263 // Cleanup
2264 while (CellStack != NULL) PopStack(&CellStack);
2265
2266 RecurseHashTable(&verilogparams, freeprop);
2267 HashKill(&verilogparams);
2268 RecurseHashTable(&verilogdefs, freeprop);
2269 HashKill(&verilogdefs);
2270 definitions = (struct hashdict *)NULL;
2271
2272 // Record the top level file.
2273 if (LookupCellFile(fname, filenum) == NULL) CellDef(fname, filenum);
2274
2275 tp = LookupCellFile(fname, filenum);
2276 if (tp) tp->flags |= CELL_TOP;
2277
2278 *fnum = filenum;
2279 return fname;
2280 }
2281
2282 /*--------------------------------------*/
2283 /* Wrappers for ReadVerilogTop() */
2284 /*--------------------------------------*/
2285
ReadVerilog(char * fname,int * fnum)2286 char *ReadVerilog(char *fname, int *fnum)
2287 {
2288 return ReadVerilogTop(fname, fnum, 0);
2289 }
2290
2291 /*--------------------------------------*/
2292 /* Verilog file include routine */
2293 /*--------------------------------------*/
2294
IncludeVerilog(char * fname,int parent,struct cellstack ** CellStackPtr,int blackbox)2295 void IncludeVerilog(char *fname, int parent, struct cellstack **CellStackPtr,
2296 int blackbox)
2297 {
2298 int filenum = -1;
2299 char name[256];
2300
2301 /* If fname does not begin with "/", then assume that it is */
2302 /* in the same relative path as its parent. */
2303
2304 if (fname[0] != '/') {
2305 char *ppath;
2306 if (*CellStackPtr && ((*CellStackPtr)->cellname != NULL)) {
2307 strcpy(name, (*CellStackPtr)->cellname);
2308 ppath = strrchr(name, '/');
2309 if (ppath != NULL)
2310 strcpy(ppath + 1, fname);
2311 else
2312 strcpy(name, fname);
2313 filenum = OpenParseFile(name, parent);
2314 }
2315 }
2316
2317 /* If we failed the path relative to the parent, then try the */
2318 /* filename alone (relative to the path where netgen was */
2319 /* executed). */
2320
2321 if (filenum < 0) {
2322 if ((filenum = OpenParseFile(fname, parent)) < 0) {
2323
2324 /* If that fails, see if a standard Verilog extension */
2325 /* helps, if the file didn't have an extension. But */
2326 /* really, we're getting desperate at this point. */
2327
2328 if (strchr(fname, '.') == NULL) {
2329 SetExtension(name, fname, VERILOG_EXTENSION);
2330 filenum = OpenParseFile(name, parent);
2331 if (filenum < 0) {
2332 fprintf(stderr,"Error in Verilog file include: No file %s\n", name);
2333 return;
2334 }
2335 }
2336 else {
2337 fprintf(stderr,"Error in Verilog file include: No file %s\n", fname);
2338 return;
2339 }
2340 }
2341 }
2342 ReadVerilogFile(fname, parent, CellStackPtr, blackbox);
2343 CloseParseFile();
2344 }
2345
2346