diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2019-10-19 11:16:40 +0200 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2019-10-19 11:16:40 +0200 |
commit | 9533572cd883ec7e30ff6c5e4283c6e3bb9b75f0 (patch) | |
tree | c46a4f67f8e3e1e81637ee949627b172a15dda64 | |
parent | 2e6501ce6a1d655c636bc7ed01ee50ba7d0d26ac (diff) | |
parent | 519925f7484ec32feec6ded0504edc457ccc29ed (diff) |
Update upstream source from tag 'upstream/1.5.133'
Update to upstream version '1.5.133'
with Debian dir 92b0bbf919a079e9162ea08fd6af7c7d2357c964
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | base/netcmp.c | 198 | ||||
-rw-r--r-- | base/netfile.c | 265 | ||||
-rw-r--r-- | base/netfile.h | 2 | ||||
-rw-r--r-- | base/objlist.c | 4 | ||||
-rw-r--r-- | base/verilog.c | 764 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rwxr-xr-x | scripts/configure | 2 | ||||
-rw-r--r-- | scripts/configure.in | 2 | ||||
-rwxr-xr-x | scripts/makedbh | 187 | ||||
-rw-r--r-- | tcltk/tclnetgen.c | 4 | ||||
-rwxr-xr-x | tcltk/tkcon.tcl | 20 |
14 files changed, 850 insertions, 608 deletions
@@ -1,12 +1,14 @@ netgen netgenexec defs.mak +scripts/defs.mak config.cache config.log +scripts/config.log config.status +scripts/config.status *.o *.so *~ *.log UPDATE_ME -VERSION @@ -85,6 +85,8 @@ and IRSIM version 9.7: make make install +Note: For FreeBSD, use 'gmake' instead. + IN CASE OF FAILURE ------------------- Please contact me (tim@opencircuitdesign.com) to report compile-time and @@ -1 +1 @@ -1.5.118 +1.5.133 diff --git a/base/netcmp.c b/base/netcmp.c index 38272fb..21d048c 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -3704,27 +3704,6 @@ int series_optimize(struct objlist *ob1, struct nlist *tp1, int idx1, return PropertyOptimize(obn, tp1, run1, TRUE, comb); } -/*--------------------------------------------------------------*/ -/* Combine properties of ob1 starting at property idx1 up to */ -/* property (idx1 + run1) to match the properties of ob2 at */ -/* idx2 to (idx2 + run2). run1 is always larger than run2. */ -/*--------------------------------------------------------------*/ - -int series_combine(struct objlist *ob1, struct nlist *tp1, int idx1, int run1, - struct objlist *ob2, struct nlist *tp2, int idx2, int run2) -{ - struct objlist *obn, *obp; - int i, j; - int changed = 0; - - obn = ob1; - for (i = 0; i < idx1; i++) obn = obn->next; - obp = ob2; - for (i = 0; i < idx2; i++) obp = obp->next; - - return changed; -} - typedef struct _propsort { double value; int idx; @@ -3782,7 +3761,7 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) vl = &(obp->instance.props[p]); if (vl->type == PROP_ENDLIST) break; if (vl->key == NULL) continue; - if (!strcmp(vl->key, "S")) { + if ((*matchfunc)(vl->key, "S")) { sval = vl->value.ival; sl = vl; } @@ -3843,27 +3822,6 @@ int parallel_optimize(struct objlist *ob1, struct nlist *tp1, int idx1, } /*--------------------------------------------------------------*/ -/* Combine properties of ob1 starting at property idx1 up to */ -/* property (idx1 + run1) to match the properties of ob2 at */ -/* idx2 to (idx2 + run2). run1 is always larger than run2. */ -/*--------------------------------------------------------------*/ - -int parallel_combine(struct objlist *ob1, struct nlist *tp1, int idx1, int run1, - struct objlist *ob2, struct nlist *tp2, int idx2, int run2) -{ - struct objlist *obn, *obp; - int i, j; - int changed = 0; - - obn = ob1; - for (i = 0; i < idx1; i++) obn = obn->next; - obp = ob2; - for (i = 0; i < idx2; i++) obp = obp->next; - - return changed; -} - -/*--------------------------------------------------------------*/ /* Sort properties of ob1 starting at property idx1 up to */ /* property (idx1 + run). Use parallel critical property for */ /* sorting. Multiply critical property by M before sort. */ @@ -3906,7 +3864,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) vl = &(obp->instance.props[p]); if (vl->type == PROP_ENDLIST) break; if (vl->key == NULL) continue; - if (!strcmp(vl->key, "M")) { + if ((*matchfunc)(vl->key, "M")) { mval = vl->value.ival; ml = vl; } @@ -3952,7 +3910,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) vl = &(obp->instance.props[p]); if (vl->type == PROP_ENDLIST) break; if (vl->key == NULL) continue; - if (!strcmp(vl->key, "M")) { + if ((*matchfunc)(vl->key, "M")) { mval = vl->value.ival; ml = vl; } @@ -3960,7 +3918,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) if (kl == NULL) continue; /* Ignored property */ if (subs_crit == NULL) subs_crit = vl->key; - if ((subs_crit != NULL) && !strcmp(vl->key, subs_crit)) { + if ((subs_crit != NULL) && (*matchfunc)(vl->key, subs_crit)) { if ((vl->type == PROP_STRING || vl->type == PROP_EXPRESSION) && (kl->type != vl->type)) PromoteProperty(kl, vl); @@ -4198,20 +4156,6 @@ void PropertySortAndCombine(struct objlist *pre1, struct nlist *tp1, ob2 = pre2->next; } - /* Do not run parallel_combine until all other changes have been resolved */ - if (changed == 0) { - if (max2 > max1) - changed += parallel_combine(ob2, tp2, idx2, max2, ob1, tp1, idx1, max1); - else if (max1 > max2) - changed += parallel_combine(ob1, tp1, idx1, max1, ob2, tp2, idx2, max2); - - if (changed > 0) { - FREE(netwk1); - FREE(netwk2); - continue; - } - } - /* Case 2: Series devices with more elements in one circuit */ /* Find the largest group of series devices in circuit1 */ @@ -4297,14 +4241,6 @@ void PropertySortAndCombine(struct objlist *pre1, struct nlist *tp1, ob2 = pre2->next; } - /* Do not run series_combine until all other changes have been resolved */ - if (changed == 0) { - if (max2 > max1) - changed += series_combine(ob2, tp2, idx2, max2, ob1, tp1, idx1, max1); - else if (max1 > max2) - changed += series_combine(ob1, tp1, idx1, max1, ob2, tp2, idx2, max2); - } - FREE(netwk1); FREE(netwk2); @@ -4338,9 +4274,10 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, { struct objlist *ob2, *obt; struct property *kl, *m_rec, **plist; + unsigned char **clist; struct valuelist ***vlist, *vl, *vl2, *newvlist; proplinkptr plink, ptop; - int pcount, p, i, j, k, pmatch, ival, crit, ctype; + int pcount, p, i, j, k, pmatch, ival, ctype; double dval; static struct valuelist nullvl, dfltvl; char multiple[2], other[2]; @@ -4362,8 +4299,6 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, m_rec = NULL; ptop = NULL; pcount = 1; - crit = -1; - ctype = -1; kl = (struct property *)HashFirst(&(tp->propdict)); while (kl != NULL) { // Make a linked list so we don't have to iterate through the hash again @@ -4378,31 +4313,22 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, else kl->idx = pcount++; - // Set critical property index, if there is one. - - if (series == FALSE) { - if (kl->merge & MERGE_P_CRIT) crit = kl->idx; - if (kl->merge & (MERGE_P_ADD | MERGE_P_PAR)) - ctype = kl->merge & (MERGE_P_ADD | MERGE_P_PAR); - } - else if (series == TRUE) { - if (kl->merge & MERGE_S_CRIT) crit = kl->idx; - if (kl->merge & (MERGE_S_ADD | MERGE_S_PAR)) - ctype = kl->merge & (MERGE_S_ADD | MERGE_S_PAR); - } - kl = (struct property *)HashNext(&(tp->propdict)); } // Recast the linked list as an array plist = (struct property **)CALLOC(pcount, sizeof(struct property *)); vlist = (struct valuelist ***)CALLOC(pcount, sizeof(struct valuelist **)); - if (m_rec == NULL) + clist = (unsigned char **)CALLOC(pcount, sizeof(unsigned char *)); + if (m_rec == NULL) { vlist[0] = (struct valuelist **)CALLOC(run, sizeof(struct valuelist *)); + clist[0] = (unsigned char *)CALLOC(run, sizeof(unsigned char)); + } while (ptop != NULL) { plist[ptop->prop->idx] = ptop->prop; vlist[ptop->prop->idx] = (struct valuelist **)CALLOC(run, sizeof(struct valuelist *)); + clist[ptop->prop->idx] = (unsigned char *)CALLOC(run, sizeof(unsigned char)); plink = ptop; FREE(ptop); ptop = plink->next; @@ -4436,6 +4362,16 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, } else if (kl != NULL) { vlist[kl->idx][i] = vl; + if (series == FALSE) { + if (kl->merge & (MERGE_P_ADD | MERGE_P_PAR)) + clist[kl->idx][i] = kl->merge & + (MERGE_P_ADD | MERGE_P_PAR | MERGE_P_CRIT); + } + else if (series == TRUE) { + if (kl->merge & (MERGE_S_ADD | MERGE_S_PAR)) + clist[kl->idx][i] = kl->merge & + (MERGE_S_ADD | MERGE_S_PAR | MERGE_S_CRIT); + } } } if (++i == run) break; @@ -4497,11 +4433,20 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, } } - // Critical properties can be multiplied up by M (S) and do not - // need to match. May want a more nuanced comparison, though. - if (p == crit) { - pmatch++; - continue; + // Additive properties do not need to be matched, since + // they can be combined. Critical paroperties must be + // matched. Properties with no merge behavior must match. + + ctype = clist[p][i]; + if (!(ctype & MERGE_S_CRIT)) { + if ((series == TRUE) && (ctype & (MERGE_S_ADD | MERGE_S_PAR))) { + pmatch++; + continue; + } + if ((series == FALSE) && (ctype & (MERGE_P_ADD | MERGE_P_PAR))) { + pmatch++; + continue; + } } switch(vl->type) { @@ -4590,42 +4535,53 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, } } - // If comb == TRUE, reduce M (or S) to 1 by merging the critical - // property (if any) + // If comb == TRUE, reduce M (or S) to 1 by merging additive properties + // (if any) - if ((comb == TRUE) && (crit != -1)) { + if (comb == TRUE) { int mult; for (i = 0; i < run; i++) { if (vlist[0][i] == NULL) continue; mult = vlist[0][i]->value.ival; if (mult > 1) { changed = 0; - vl = vlist[crit][i]; - if ((ctype == MERGE_S_ADD) || (ctype == MERGE_P_ADD)) { - if (vl->type == PROP_INTEGER) - vl->value.ival *= mult; - else if (vl->type == PROP_DOUBLE) - vl->value.dval *= (double)mult; - vlist[0][i]->value.ival = 1; - changed += mult; - } - else if ((ctype == MERGE_S_PAR) || (ctype == MERGE_P_PAR)) { - /* Technically one should check if divide-by-mult */ - /* reduces the value to < 1 and promote to double */ - /* if so, but that's a very unlikely case. */ - if (vl->type == PROP_INTEGER) - vl->value.ival /= mult; - else if (vl->type == PROP_DOUBLE) - vl->value.dval /= (double)mult; - vlist[0][i]->value.ival = 1; - changed += mult; - } - if (changed > 0) { - if (series) - Printf("Combined %d series devices.\n", changed); - else - Printf("Combined %d parallel devices.\n", changed); + /* For all properties that are not M, S, or crit, */ + /* combine as specified by the merge type of the property. */ + + for (p = 1; p < pcount; p++) { + vl = vlist[p][i]; + ctype = clist[p][i]; + + /* critical properties never combine */ + if ((series == TRUE) && (ctype & MERGE_S_CRIT)) continue; + if ((series == FALSE) && (ctype & MERGE_P_CRIT)) continue; + + if (ctype & (MERGE_S_ADD | MERGE_P_ADD)) { + if (vl->type == PROP_INTEGER) + vl->value.ival *= mult; + else if (vl->type == PROP_DOUBLE) + vl->value.dval *= (double)mult; + vlist[0][i]->value.ival = 1; + changed += mult; + } + else if (ctype & (MERGE_S_PAR | MERGE_P_PAR)) { + /* Technically one should check if divide-by-mult */ + /* reduces the value to < 1 and promote to double */ + /* if so, but that's a very unlikely case. */ + if (vl->type == PROP_INTEGER) + vl->value.ival /= mult; + else if (vl->type == PROP_DOUBLE) + vl->value.dval /= (double)mult; + vlist[0][i]->value.ival = 1; + changed += mult; + } + if (changed > 0) { + if (series) + Printf("Combined %d series devices.\n", changed); + else + Printf("Combined %d parallel devices.\n", changed); + } } } } @@ -4652,9 +4608,11 @@ cleanup: kl = (struct property *)plist[p]; if (kl) kl->idx = 0; FREE(vlist[p]); + FREE(clist[p]); } FREE(plist); FREE(vlist); + FREE(clist); return changed; } @@ -4913,9 +4871,9 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1, kl2 = &klm; else if (vl2 == &svl) kl2 = &kls; - else if (vl1 == &mvl) + else if ((*matchfunc)(vl2->key, mvl.key)) kl2 = &klm; - else if (vl1 == &svl) + else if ((*matchfunc)(vl2->key, svl.key)) kl2 = &kls; else continue; diff --git a/base/netfile.c b/base/netfile.c index dd29d3c..5dd140e 100644 --- a/base/netfile.c +++ b/base/netfile.c @@ -47,6 +47,18 @@ static FILE *outfile; static int Graph = 0; int File; +/*------------------------------------------------------*/ +/* Structure for stacking nested `if[n]def in verilog */ +/*------------------------------------------------------*/ + +struct ifstack { + int invert; + struct property *kl; + struct ifstack *next; +}; + +struct ifstack *condstack = NULL; + extern char *SetExtension(char *buffer, char *path, char *extension) /* add 'extension' to 'path' (overwriting previous extension, if any), write it into buffer (if buffer is null, malloc a buffer). @@ -191,6 +203,8 @@ struct filestack { static struct filestack *OpenFiles = NULL; +struct hashdict *definitions = (struct hashdict *)NULL; + #define WHITESPACE_DELIMITER " \t\n\r" /*----------------------------------------------------------------------*/ @@ -251,7 +265,6 @@ void TrimQuoted(char *line) } } } - } /*----------------------------------------------------------------------*/ @@ -265,39 +278,202 @@ void TrimQuoted(char *line) int GetNextLineNoNewline(char *delimiter) { - char *newbuf; - int testc; + char *newbuf; + int testc; + int nested = 0; - if (feof(infile)) return -1; + if (feof(infile)) return -1; - // This is more reliable than feof() ... - testc = getc(infile); - if (testc == -1) return -1; - ungetc(testc, infile); + while (1) { /* May loop indefinitely in an `if[n]def conditional */ - if (linesize == 0) { - /* Allocate memory for line */ - linesize = 500; - line = (char *)MALLOC(linesize); - linetok = (char *)MALLOC(linesize); - } - fgets(line, linesize, infile); - while (strlen(line) == linesize - 1) { - newbuf = (char *)MALLOC(linesize + 500); - strcpy(newbuf, line); - FREE(line); - line = newbuf; - fgets(line + linesize - 1, 501, infile); - linesize += 500; - FREE(linetok); - linetok = (char *)MALLOC(linesize); - } - linenum++; - strcpy(linetok, line); - TrimQuoted(linetok); + // This is more reliable than feof() ... + testc = getc(infile); + if (testc == -1) return -1; + ungetc(testc, infile); + + if (linesize == 0) { + /* Allocate memory for line */ + linesize = 500; + line = (char *)MALLOC(linesize); + linetok = (char *)MALLOC(linesize); + } + fgets(line, linesize, infile); + while (strlen(line) == linesize - 1) { + newbuf = (char *)MALLOC(linesize + 500); + strcpy(newbuf, line); + FREE(line); + line = newbuf; + fgets(line + linesize - 1, 501, infile); + linesize += 500; + FREE(linetok); + linetok = (char *)MALLOC(linesize); + } + + /* Check for substitutions (verilog only). Make sure linetok is */ + /* large enough to hold the entire line after substitutions. */ + + if (definitions != NULL) { + char *s, *w, e; + struct property *kl; + int len, dlen, vlen, addin = 0; + unsigned char found = FALSE; + + for (s = line; *s != '\0'; s++) { + if (*s == '`') { + w = s + 1; + while (isalnum(*w)) w++; + e = *w; + *w = '\0'; + kl = (struct property *)HashLookup(s + 1, definitions); + if (kl != NULL) { + dlen = strlen(s); + if (kl->type == PROP_STRING) { + vlen = strlen(kl->pdefault.string); + } + else vlen = 12; /* Leave room for numeric conversion */ + addin += vlen - dlen + 1; + found = TRUE; + } + *w = e; + } + } + if (found) { + len = strlen(line); + if (len + addin > linesize) { + while (len + addin > linesize) linesize += 500; + FREE(linetok); + linetok = (char *)MALLOC(linesize); + } + } + } + + /* Make definition substitutions (verilog only) */ + + if (definitions != NULL) { + char *s, *t, *w, e; + struct property *kl; + + t = linetok; + for (s = line; *s != '\0'; s++) { + if (*s == '`') { + w = s + 1; + while (isalnum(*w)) w++; + e = *w; + *w = '\0'; + kl = (struct property *)HashLookup(s + 1, definitions); + if (kl != NULL) { + if (kl->type == PROP_STRING) + strcpy(t, kl->pdefault.string); + else if (kl->type == PROP_INTEGER) + sprintf(t, "%d", kl->pdefault.ival); + else if (kl->type == PROP_DOUBLE) + sprintf(t, "%g", kl->pdefault.dval); + t += strlen(t); + s = w - 1; + } + else *t++ = *s; + *w = e; + } + else *t++ = *s; + } + *t = '\0'; + } + else + strcpy(linetok, line); + + TrimQuoted(linetok); + linenum++; + + nexttok = strdtok(linetok, WHITESPACE_DELIMITER, delimiter); + if (nexttok == NULL) return 0; + + /* Handle `ifdef, `ifndef, `elsif, `else, and `endif (verilog */ + /* only, where indicated by a non-NULL "definitions") */ + + if (definitions == NULL) return 0; + + /* If currently skipping through a section, handle conditionals differently */ + + if (condstack) { + if (((condstack->invert == 0) && (condstack->kl == NULL)) + || ((condstack->invert == 1) && (condstack->kl != NULL))) { + if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef")) { + nested++; + continue; + } + else if (nested > 0) { + if (match(nexttok, "`endif")) nested--; + continue; + } + else if (nexttok[0] != '`') continue; + } + } + + /* Handle conditionals (that is not being skipped over) */ + + if (match(nexttok, "`endif")) { + if (condstack == NULL) { + fprintf(stderr, "Error: `endif without corresponding `if[n]def\n"); + } + else { + struct ifstack *iftop = condstack; + condstack = condstack->next; + FREE(iftop); + } + } - nexttok = strdtok(linetok, WHITESPACE_DELIMITER, delimiter); - return 0; + /* Note that `if[n]def may be nested. */ + + else if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef") || + match(nexttok, "`elsif") || match(nexttok, "`else")) { + + /* Every `ifdef or `ifndef increases condstack by 1 */ + if (nexttok[1] == 'i') { + struct ifstack *newif = (struct ifstack *)MALLOC(sizeof(struct ifstack)); + newif->next = condstack; + condstack = newif; + } + if (condstack == NULL) { + fprintf(stderr, "Error: %s without `if[n]def\n", nexttok); + break; + } + else { + if (match(nexttok, "`else")) { + /* Invert the sense of the if[n]def scope */ + condstack->invert = (condstack->invert == 1) ? 0 : 1; + } + else if (match(nexttok, "`elsif")) { + nexttok = strdtok(NULL, WHITESPACE_DELIMITER, delimiter); + if (nexttok == NULL) { + fprintf(stderr, "Error: `elsif with no conditional.\n"); + return 0; + } + /* Keep the same scope but redefine the parameter */ + condstack->invert = 0; + condstack->kl = (struct property *)HashLookup(nexttok, definitions); + } + else { + condstack->invert = (nexttok[3] == 'n') ? 1 : 0; + nexttok = strdtok(NULL, WHITESPACE_DELIMITER, delimiter); + if (nexttok == NULL) { + fprintf(stderr, "Error: %s with no conditional.\n", nexttok); + return 0; + } + condstack->kl = (struct property *)HashLookup(nexttok, definitions); + } + } + } + else if (condstack) { + if (((condstack->invert == 0) && (condstack->kl == NULL)) + || ((condstack->invert == 1) && (condstack->kl != NULL))) + continue; + else + break; + } + else + break; + } + return 0; } /*----------------------------------------------------------------------*/ @@ -471,6 +647,33 @@ char *strdtok(char *pstring, char *delim1, char *delim2) /* "stoken" is now set. Now find the end of the current token */ + s = stoken; + + /* Special verilog rule: If a name begins with '\', then all characters */ + /* are a valid part of the name until a space character is reached. The */ + /* space character becomes part of the verilog name. The remainder of the */ + /* name is parsed according to the rules of "delim2". */ + + /* Special verilog rule exception: To handle the problems caused by */ + /* translating verilog backslash-escaped names into other netlist formats */ + /* like SPICE where the convention is strictly prohibited, I have used the */ + /* convention in qflow scripts to replace the trailing space with another */ + /* backslash, so the name is effectively delimited by a pair of back- */ + /* slashes. Therefore check for a space or another backslash, whichever */ + /* comes first. That will satisfy both methods. Technically this routine */ + /* should know whether it is parsing SPICE or verilog and handle the syntax */ + /* accordingly (needs to be done). */ + + if (*s == '\\') { + while (*s != '\0') { + if ((*s == ' ') || (*s == '\\')) { + s++; + break; + } + s++; + } + } + /* Check string from position stoken. If a character in "delim2" is found, */ /* save the character in "lastdelim", null the byte at that position, and */ /* return the token. If a character in "delim1" is found, do the same but */ @@ -479,7 +682,7 @@ char *strdtok(char *pstring, char *delim1, char *delim2) /* as for "delim2" above. If not, then set "lastdelim" to a null byte and */ /* return the token. */ - for (s = stoken; *s; s++) { + for (; *s; s++) { twofer = (delim2 && (*delim2 == 'X')) ? TRUE : FALSE; for (s2 = ((twofer == TRUE) ? delim2 + 1 : delim2); s2 && *s2; s2++) { if (*s2 == 'X') { diff --git a/base/netfile.h b/base/netfile.h index fbcf413..3fe7ffe 100644 --- a/base/netfile.h +++ b/base/netfile.h @@ -24,6 +24,7 @@ extern void FlushString (char *format, ...); extern char *SetExtension(char *buffer, char *path, char *extension); extern int File; +extern struct hashdict *definitions; /* input routines */ @@ -32,6 +33,7 @@ extern char *nexttok; extern char *strdtok(char *pstring, char *delim1, char *delim2); extern void SkipTok(char *delimiter); extern void SkipTokNoNewline(char *delimiter); +extern void SkipTokComments(char *delimiter); extern void SkipNewLine(char *delimiter); extern void SpiceTokNoNewline(void); /* handles SPICE "+" continuation line */ extern void SpiceSkipNewLine(void); /* handles SPICE "+" continuation line */ diff --git a/base/objlist.c b/base/objlist.c index 14df071..e864a17 100644 --- a/base/objlist.c +++ b/base/objlist.c @@ -598,7 +598,11 @@ static int PrintCellHashTableElement(struct hashlist *p) if (Debug == 1) Printf("Cell: %s (instanced %d times); Primitive\n", ptr->name, ptr->number); else if (Debug == 3) { /* list */ +#ifdef TCL_NETGEN Tcl_AppendElement(netgeninterp, ptr->name); +#else + Printf("%s ", ptr->name); +#endif } } else if ((Debug == 2) || (Debug == 3)) { /* list only */ diff --git a/base/verilog.c b/base/verilog.c index 78d70b1..c9aa988 100644 --- a/base/verilog.c +++ b/base/verilog.c @@ -59,8 +59,9 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ // See netfile.c for explanation of delimiters. 'X' // separates single-character delimiters from two-character delimiters. -#define VLOG_DELIMITERS "X///**/#((**)X,::(){}[]=" +#define VLOG_DELIMITERS "X///**/#((**)X,;:(){}[]=" #define VLOG_PIN_NAME_DELIMITERS "X///**/(**)X()" +#define VLOG_PIN_CHECK_DELIMITERS "X///**/(**)X,;(){}" // Global storage for verilog parameters struct hashdict verilogparams; @@ -120,19 +121,33 @@ int GetBusTok(struct bus *wb) if (match(nexttok, "[")) { SkipTokComments(VLOG_DELIMITERS); - // Check for parameter names and substitute values if found. - if (nexttok[0] == '`') { - kl = (struct property *)HashLookup(nexttok + 1, &verilogdefs); + result = sscanf(nexttok, "%d", &start); + if (result != 1) { + char *aptr = NULL; + char addin; + + // Check for "+/-(n)" at end of a parameter name + aptr = strrchr(nexttok, '+'); + if (aptr == NULL) aptr = strrchr(nexttok, '-'); + if (aptr != NULL) { + addin = *aptr; + *aptr = '\0'; + } + + // Is name in the parameter list? + kl = (struct property *)HashLookup(nexttok, &verilogparams); if (kl == NULL) { - Printf("Unknown definition %s found in array notation.\n", nexttok); + Printf("Array value %s is not a number or a parameter.\n", + nexttok); + return 1; } else { if (kl->type == PROP_STRING) { result = sscanf(kl->pdefault.string, "%d", &start); if (result != 1) { - Printf("Cannot parse first digit from parameter %s value %s\n", - nexttok, kl->pdefault.string); - return 1; + Printf("Parameter %s has value %s that cannot be parsed" + " as an integer.\n", nexttok, kl->pdefault.string); + return 1; } } else if (kl->type == PROP_INTEGER) { @@ -141,54 +156,25 @@ int GetBusTok(struct bus *wb) else if (kl->type == PROP_DOUBLE) { start = (int)kl->pdefault.dval; if ((double)start != kl->pdefault.dval) { - Printf("Cannot parse first digit from parameter %s value %g\n", - nexttok, kl->pdefault.dval); - return 1; + Printf("Parameter %s has value %g that cannot be parsed" + " as an integer.\n", nexttok, kl->pdefault.dval); + return 1; } } else { - Printf("Parameter %s has unknown type; don't know how to parse.\n", - nexttok); + Printf("Parameter %s has unknown type; don't know how" + " to parse.\n", nexttok); return 1; } } - } - else { - result = sscanf(nexttok, "%d", &start); - if (result != 1) { - // Is name in the parameter list? - kl = (struct property *)HashLookup(nexttok, &verilogparams); - if (kl == NULL) { - Printf("Array value %s is not a number or a parameter.\n", - nexttok); + if (aptr != NULL) { + int addval; + *aptr = addin; + if (sscanf(aptr + 1, "%d", &addval) != 1) { + Printf("Unable to parse parameter increment '%s'\n", aptr); return 1; } - else { - if (kl->type == PROP_STRING) { - result = sscanf(kl->pdefault.string, "%d", &start); - if (result != 1) { - Printf("Parameter %s has value %s that cannot be parsed" - " as an integer.\n", nexttok, kl->pdefault.string); - return 1; - } - } - else if (kl->type == PROP_INTEGER) { - start = kl->pdefault.ival; - } - else if (kl->type == PROP_DOUBLE) { - start = (int)kl->pdefault.dval; - if ((double)start != kl->pdefault.dval) { - Printf("Parameter %s has value %g that cannot be parsed" - " as an integer.\n", nexttok, kl->pdefault.dval); - return 1; - } - } - else { - Printf("Parameter %s has unknown type; don't know how" - " to parse.\n", nexttok); - return 1; - } - } + start += (addin == '+') ? addval : -addval; } } SkipTokComments(VLOG_DELIMITERS); @@ -203,18 +189,33 @@ int GetBusTok(struct bus *wb) else { SkipTokComments(VLOG_DELIMITERS); - // Check for parameter names and substitute values if found. - if (nexttok[0] == '`') { - kl = (struct property *)HashLookup(nexttok + 1, &verilogdefs); + result = sscanf(nexttok, "%d", &end); + if (result != 1) { + char *aptr = NULL; + char addin; + + // Check for "+/-(n)" at end of a parameter name + aptr = strrchr(nexttok, '+'); + if (aptr == NULL) aptr = strrchr(nexttok, '-'); + if (aptr != NULL) { + addin = *aptr; + *aptr = '\0'; + } + + // Is name in the parameter list? + kl = (struct property *)HashLookup(nexttok, &verilogparams); if (kl == NULL) { - Printf("Unknown definition %s found in array notation.\n", nexttok); + Printf("Array value %s is not a number or a parameter.\n", + nexttok); + return 1; } else { if (kl->type == PROP_STRING) { result = sscanf(kl->pdefault.string, "%d", &end); - if (result != 1) { - Printf("Cannot parse second digit from parameter " - "%s value %s\n", nexttok, kl->pdefault.string); + if (result != 1) { + Printf("Parameter %s has value %s that cannot be parsed" + " as an integer.\n", nexttok, + kl->pdefault.string); return 1; } } @@ -231,48 +232,18 @@ int GetBusTok(struct bus *wb) } else { Printf("Parameter %s has unknown type; don't know how" - " to parse.\n", nexttok); + " to parse.\n", nexttok); return 1; } } - } - else { - result = sscanf(nexttok, "%d", &end); - if (result != 1) { - // Is name in the parameter list? - kl = (struct property *)HashLookup(nexttok, &verilogparams); - if (kl == NULL) { - Printf("Array value %s is not a number or a parameter.\n", - nexttok); + if (aptr != NULL) { + int addval; + *aptr = addin; + if (sscanf(aptr + 1, "%d", &addval) != 1) { + Printf("Unable to parse parameter increment '%s'\n", aptr); return 1; } - else { - if (kl->type == PROP_STRING) { - result = sscanf(kl->pdefault.string, "%d", &end); - if (result != 1) { - Printf("Parameter %s has value %s that cannot be parsed" - " as an integer.\n", nexttok, - kl->pdefault.string); - return 1; - } - } - else if (kl->type == PROP_INTEGER) { - end = kl->pdefault.ival; - } - else if (kl->type == PROP_DOUBLE) { - end = (int)kl->pdefault.dval; - if ((double)end != kl->pdefault.dval) { - Printf("Cannot parse second digit from parameter " - "%s value %g\n", nexttok, kl->pdefault.dval); - return 1; - } - } - else { - Printf("Parameter %s has unknown type; don't know how" - " to parse.\n", nexttok); - return 1; - } - } + end += (addin == '+') ? addval : -addval; } } } @@ -312,7 +283,7 @@ int GetBusTok(struct bus *wb) int GetBus(char *astr, struct bus *wb) { - char *colonptr, *brackstart, *brackend; + char *colonptr, *brackstart, *brackend, *sigend, sdelim; int result, start, end; if (wb == NULL) return 0; @@ -320,6 +291,40 @@ int GetBus(char *astr, struct bus *wb) wb->start = -1; wb->end = -1; } + + /* Check for wire bundles. If there are bundles, process each */ + /* section separately and concatenate the sizes. */ + /* To be done: Handle nested bundles, including N-times concatenation */ + + if (*astr == '{') { + struct bus wbb; + + astr++; + wb->end = 0; + while((*astr != '\0') && (*astr != '}')) { + sigend = strchr(astr, ','); + if (sigend == NULL) sigend = strchr(astr, '}'); + if (sigend == NULL) { + Printf("Badly formed wire bundle \"%s\"\n", astr - 1); + return 1; + } + sdelim = *sigend; + *sigend = '\0'; + if (GetBus(astr, &wbb) == 0) { + if (wbb.start > wbb.end) + wb->start += (wbb.start - wbb.end + 1); + else + wb->start += (wbb.end - wbb.start + 1); + } + else { + wb->start++; + } + *sigend = sdelim; + astr = sigend + 1; + } + return 0; + } + brackstart = strchr(astr, '['); if (brackstart != NULL) { brackend = strchr(astr, ']'); @@ -595,7 +600,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr, instname[255] = '\0'; in_module = (char)0; in_param = (char)0; - + while (!EndParseFile()) { SkipTokComments(VLOG_DELIMITERS); /* get the next token */ @@ -620,6 +625,81 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr, } } + /* Handle parameters by treating as a localparam or definition. */ + /* Currently anything other than a constant value is not handled */ + /* and so will flag a warning. */ + + else if (match(nexttok, "parameter") || match(nexttok, "localparam")) { + char *paramkey = NULL; + char *paramval = NULL; + + // Pick up key = value pairs and store in current cell. Look only + // at the keyword before "=". Then set the defition as everything + // remaining in the line, excluding comments, until the end-of-statement + + while (nexttok != NULL) + { + struct property *kl = NULL; + + /* Parse for parameters used in expressions. Save */ + /* parameters in the "verilogparams" hash table. */ + + SkipTok(VLOG_DELIMITERS); + if ((nexttok == NULL) || (nexttok[0] == '\0')) break; + if (match(nexttok, "=")) { + /* Pick up remainder of statement */ + while (nexttok != NULL) { + SkipTokNoNewline("X///**/X;,"); + if (nexttok == NULL) break; + if (match(nexttok, ";") || match(nexttok, ",")) break; + if (paramval == NULL) paramval = strsave(nexttok); + else { + char *paramlast; + /* Append nexttok to paramval */ + paramlast = paramval; + paramval = (char *)MALLOC(strlen(paramlast) + strlen(nexttok) + + 2); + sprintf(paramval, "%s %s", paramlast, nexttok); + FREE(paramlast); + } + } + + kl = NewProperty(); + kl->key = strsave(paramkey); + kl->idx = 0; + kl->merge = MERGE_NONE; + + if (ConvertStringToInteger(paramval, &ival) == 1) { + kl->type = PROP_INTEGER; + kl->slop.ival = 0; + kl->pdefault.ival = ival; + } + else if (ConvertStringToFloat(paramval, &dval) == 1) { + kl->type = PROP_DOUBLE; + kl->slop.dval = 0.01; + kl->pdefault.dval = dval; + } + else { + kl->type = PROP_STRING; + kl->slop.dval = 0.0; + kl->pdefault.string = strsave(paramval); + } + + HashPtrInstall(paramkey, kl, &verilogparams); + FREE(paramval); + paramval = NULL; + + if ((nexttok == NULL) || match(nexttok, ";")) break; + } + else { + if (paramkey != NULL) FREE(paramkey); + paramkey = strsave(nexttok); + } + } + if (paramval != NULL) FREE(paramval); + if (paramkey != NULL) FREE(paramkey); + } + else if (match(nexttok, "module")) { InitializeHashTable(&buses, OBJHASHSIZE); SkipTokNoNewline(VLOG_DELIMITERS); @@ -696,7 +776,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr, inlined_decls = (char)0; if (tp != NULL) { - struct bus wb; + struct bus wb, *nb; PushStack(tp->name, CellStackPtr); @@ -760,7 +840,8 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr, else { if (!match(nexttok, "input") && !match(nexttok, "output") && !match(nexttok, "inout") && !match(nexttok, "real") && - !match(nexttok, "logic") && !match(nexttok, "integer")) { + !match(nexttok, "wire") && !match(nexttok, "logic") && + !match(nexttok, "integer")) { if (match(nexttok, "[")) { if (GetBusTok(&wb) != 0) { // Didn't parse as a bus, so wing it @@ -782,6 +863,12 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr, Port(portname); } } + /* Also register this port as a bus */ + nb = NewBus(); + nb->start = wb.start; + nb->end = wb.end; + HashPtrInstall(nexttok, nb, &buses); + wb.start = wb.end = -1; } else { @@ -991,151 +1078,219 @@ skip_endmodule: } HashPtrInstall(kl->key, kl, &verilogdefs); } - else if (match(nexttok, "localparam")) { - // Pick up key = value pairs and store in current cell - while (nexttok != NULL) - { - struct property *kl = NULL; - - /* Parse for parameters used in expressions. Save */ - /* parameters in the "verilogparams" hash table. */ - - SkipTokNoNewline(VLOG_DELIMITERS); - if ((nexttok == NULL) || (nexttok[0] == '\0')) break; - if ((eqptr = strchr(nexttok, '=')) != NULL) { - *eqptr = '\0'; - kl = NewProperty(); - kl->key = strsave(nexttok); - kl->idx = 0; - kl->merge = MERGE_NONE; - - if (ConvertStringToInteger(eqptr + 1, &ival) == 1) { - kl->type = PROP_INTEGER; - kl->slop.ival = 0; - kl->pdefault.ival = ival; + else if (match(nexttok, "`undef")) { + struct property *kl = NULL; + + SkipTokNoNewline(VLOG_DELIMITERS); + if ((nexttok == NULL) || (nexttok[0] == '\0')) break; + + kl = HashLookup(nexttok, &verilogdefs); + if (kl != NULL) { + HashDelete(nexttok, &verilogdefs); + if (kl->type == PROP_STRING) + if (kl->pdefault.string != NULL) + FREE(kl->pdefault.string); + FREE(kl->key); + } + /* Presumably it is not an error to undefine an undefined keyword */ + } + else if (match(nexttok, "real") || match(nexttok, "integer")) { + Printf("Ignoring '%s' in module '%s'\n", nexttok, model); + /* Do not skip to end of module, as these can be in the middle of */ + /* I/O assignments, which need to be parsed. */ + while (!match(nexttok, ";")) SkipTok("X///**/X,;"); + continue; + } + else if (match(nexttok, "wire") || match(nexttok, "assign")) { /* wire = node */ + struct bus wb, wb2, *nb; + char nodename[128], noderoot[100]; + int is_wire = match(nexttok, "wire"); + int j; + struct objlist *lhs, *rhs; + + /* Get left-hand side expression. If this is a wire statement, */ + /* then define the wire. If is_wire is false, then the wire */ + /* should already be defined. */ + + if (is_wire) { + SkipTokNoNewline(VLOG_DELIMITERS); + if (match(nexttok, "real")) + SkipTokNoNewline(VLOG_DELIMITERS); + else if (match(nexttok, "logic")) + SkipTokNoNewline(VLOG_DELIMITERS); + + if (GetBusTok(&wb) == 0) { + /* Handle bus notation */ + SkipTokNoNewline(VLOG_DELIMITERS); + strcpy(noderoot, nexttok); + if (wb.start > wb.end) { + for (i = wb.end; i <= wb.start; i++) { + sprintf(nodename, "%s[%d]", nexttok, i); + if (LookupObject(nodename, CurrentCell) == NULL) + Node(nodename); + if (i == wb.start) lhs = LookupObject(nodename, CurrentCell); + } + } + else { + for (i = wb.start; i <= wb.end; i++) { + sprintf(nodename, "%s[%d]", nexttok, i); + if (LookupObject(nodename, CurrentCell) == NULL) + Node(nodename); + if (i == wb.start) lhs = LookupObject(nodename, CurrentCell); + } + } + nb = NewBus(); + nb->start = wb.start; + nb->end = wb.end; + HashPtrInstall(nexttok, nb, &buses); } - else if (ConvertStringToFloat(eqptr + 1, &dval) == 1) { - kl->type = PROP_DOUBLE; - kl->slop.dval = 0.01; - kl->pdefault.dval = dval; + else { + if (LookupObject(nexttok, CurrentCell) == NULL) { + Node(nexttok); + lhs = LookupObject(nexttok, CurrentCell); + } + } + while (1) { + SkipTokNoNewline(VLOG_DELIMITERS); + if (match(nexttok, ",")) { + SkipTokComments(VLOG_DELIMITERS); + if (LookupObject(nexttok, CurrentCell) == NULL) { + Node(nexttok); + lhs = LookupObject(nexttok, CurrentCell); + } + } + else break; + } + } + else { /* "assign" */ + SkipTokComments(VLOG_PIN_CHECK_DELIMITERS); + if (GetBus(nexttok, &wb) == 0) { + char *aptr = strchr(nexttok, '['); + if (aptr != NULL) { + *aptr = '\0'; + /* Find object of first net in bus */ + strcpy(noderoot, nexttok); + sprintf(nodename, "%s[%d]", nexttok, wb.start); + lhs = LookupObject(nodename, CurrentCell); + *aptr = '['; + } } else { - kl->type = PROP_STRING; - kl->slop.dval = 0.0; - kl->pdefault.string = strsave(eqptr + 1); + lhs = LookupObject(nexttok, CurrentCell); + } + SkipTokComments(VLOG_DELIMITERS); + if (lhs && ((!nexttok) || (!match(nexttok, "=")))) { + fprintf(stderr, "Empty assignment for net %s\n", lhs->name); } - HashPtrInstall(nexttok, kl, &verilogparams); - } - } - } - - /* Note: This is just the most basic processing of conditionals, */ - /* although it does handle nested conditionals. */ - - else if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef")) { - struct property *kl; - int nested = 0; - int invert = (nexttok[3] == 'n') ? 1 : 0; - - SkipTokNoNewline(VLOG_DELIMITERS); - - /* To be done: Handle boolean arithmetic on conditionals */ - - kl = (struct property *)HashLookup(nexttok, &verilogdefs); - if (((invert == 0) && (kl == NULL)) - || ((invert == 1) && (kl != NULL))) { - /* Skip to matching `endif */ - while (1) { - SkipNewLine(VLOG_DELIMITERS); - SkipTokComments(VLOG_DELIMITERS); - if (EndParseFile()) break; - if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef")) { - nested++; - } - else if (match(nexttok, "`endif")) { - if (nested == 0) - break; - else - nested--; - } - } } - } - else if (match(nexttok, "wire") || match(nexttok, "assign")) { /* wire = node */ - struct bus wb, *nb; - char nodename[128]; - int is_assignment = FALSE; - struct objlist *lhs, *rhs; + /* Check for assignment statement, and handle any allowed uses. */ + /* Any uses other than those mentioned below will cause the entire */ + /* module to be treated as a black box. */ - // Several allowed uses of "assign": - // "assign a = b" joins two nets. - // "assign a = {b, c, ...}" creates a bus from components. - // "assign" using any boolean arithmetic is not structural verilog. + // Allowed uses of "assign" for netlists: + // "assign a = b" joins two nets. + // "assign a = {b, c, ...}" creates a bus from components. + // "assign" using any boolean arithmetic is not structural verilog. - SkipTokNoNewline(VLOG_DELIMITERS); - if (match(nexttok, "real")) SkipTokNoNewline(VLOG_DELIMITERS); - while (nexttok != NULL) { - if (match(nexttok, "=")) { - is_assignment = TRUE; - } - else if (GetBusTok(&wb) == 0) { - /* Handle bus notation */ - SkipTokNoNewline(VLOG_DELIMITERS); - if (wb.start > wb.end) { - for (i = wb.end; i <= wb.start; i++) { - sprintf(nodename, "%s[%d]", nexttok, i); - if (LookupObject(nodename, CurrentCell) == NULL) - Node(nodename); + if (nexttok && match(nexttok, "=")) { + char assignname[128], assignroot[100]; + + i = wb.start; + while (1) { + SkipTokComments(VLOG_PIN_CHECK_DELIMITERS); + if (!nexttok) break; + + if (match(nexttok, "{")) { + /* RHS is a bundle */ + continue; } - } - else { - for (i = wb.start; i <= wb.end; i++) { - sprintf(nodename, "%s[%d]", nexttok, i); - if (LookupObject(nodename, CurrentCell) == NULL) - Node(nodename); + else if (match(nexttok, "}")) { + /* End of bundle */ + continue; } - } - nb = NewBus(); - nb->start = wb.start; - nb->end = wb.end; - HashPtrInstall(nexttok, nb, &buses); - } - else { - if (is_assignment) { - /* Handle assignment statements */ - /* To be done: Handle where both are bus names, and */ - /* where lhs is a bus name and rhs is a list of nets */ - if ((rhs = LookupObject(nexttok, CurrentCell)) != NULL) { - join(lhs->name, rhs->name); - } - else { - Printf("Module '%s' is not structural verilog, " - "making black-box.\n", model); - SetClass(CLASS_MODULE); - goto skip_endmodule; - } - is_assignment = FALSE; - } - else if (LookupObject(nexttok, CurrentCell) == NULL) - Node(nexttok); - lhs = LookupObject(nexttok, CurrentCell); - } - do { - SkipTokNoNewline(VLOG_DELIMITERS); - } while (nexttok && match(nexttok, ";")); - } + else if (match(nexttok, ",")) { + /* Additional signals in bundle */ + continue; + } + else if (match(nexttok, ";")) { + /* End of assignment */ + break; + } + else { + if (GetBus(nexttok, &wb2) == 0) { + char *aptr = strchr(nexttok, '['); + j = wb2.start; + if (aptr != NULL) { + *aptr = '\0'; + strcpy(assignroot, nexttok); + sprintf(assignname, "%s[%d]", nexttok, j); + rhs = LookupObject(assignname, CurrentCell); + *aptr = '['; + } + } + else { + j = -1; + rhs = LookupObject(nexttok, CurrentCell); + } + if ((lhs == NULL) || (rhs == NULL)) { + if (rhs != NULL) { + Printf("Improper assignment; left-hand side cannot " + "be parsed.\n"); + Printf("Right-hand side is \"%s\".\n", rhs->name); + break; + } + if (lhs != NULL) { + Printf("Improper assignment; right-hand side cannot " + "be parsed.\n"); + Printf("Left-hand side is \"%s\".\n", lhs->name); + /* Not parsable, probably behavioral verilog? */ + Printf("Module '%s' is not structural verilog, " + "making black-box.\n", model); + SetClass(CLASS_MODULE); + goto skip_endmodule; + } + } + while (1) { + /* Assign bits in turn from bundle in RHS to bits of LHS */ + /* until bits in signal are exhausted or LHS is full. */ + + if (i != -1) + sprintf(nodename, "%s[%d]", noderoot, i); + else + sprintf(nodename, lhs->name); + if (j != -1) + sprintf(assignname, "%s[%d]", assignroot, j); + else + sprintf(assignname, rhs->name); + + join(nodename, assignname); + + if (i == wb.end) break; + i += (wb.end > wb.start) ? 1 : -1; + + if (j == wb2.end) break; + j += (wb2.end > wb2.start) ? 1 : -1; + } + } + } + } + while (nexttok && !match(nexttok, ";")) + SkipTokComments(VLOG_DELIMITERS); } else if (match(nexttok, "endmodule")) { // No action---new module is started with next 'module' statement, // if any. SkipNewLine(VLOG_DELIMITERS); + in_module = (char)0; /* Should have been done already */ } else if (nexttok[0] == '`') { - // Ignore any other directive starting with a backtick + // Ignore any other directive starting with a backtick (e.g., `timescale) SkipNewLine(VLOG_DELIMITERS); } - else if (match(nexttok, "reg") || match(nexttok, "always")) { + else if (match(nexttok, "reg") || match(nexttok, "always") || + match(nexttok, "specify") || match(nexttok, "initial")) { + Printf("Behavioral keyword '%s' found in source.\n", nexttok); Printf("Module '%s' is not structural verilog, making black-box.\n", model); // To be done: Remove any contents (but may not be necessary) // Recast as module @@ -1145,6 +1300,7 @@ skip_endmodule: else { /* module instances */ char instancename[100], modulename[100]; int itype, arraystart, arrayend, arraymax, arraymin; + char ignore; instancename[99] = '\0'; modulename[99] = '\0'; @@ -1164,9 +1320,12 @@ skip_endmodule: PushStack(fname, CellStackPtr); } + SkipTokComments(VLOG_DELIMITERS); + +nextinst: + ignore = FALSE; head = NULL; tail = NULL; - SkipTokComments(VLOG_DELIMITERS); // Next token must be '#(' (parameters) or an instance name @@ -1239,19 +1398,21 @@ skip_endmodule: // Read the pin list while (nexttok != NULL) { SkipTokComments(VLOG_DELIMITERS); - // NOTE: Deal with `ifdef et al. properly. Ignoring for now. - while (nexttok[0] == '`') { - SkipNewLine(VLOG_DELIMITERS); - SkipTokComments(VLOG_DELIMITERS); - } if (match(nexttok, ")")) break; else if (match(nexttok, ",")) continue; // We need to look for pins of the type ".name(value)" if (nexttok[0] != '.') { - Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok); - SkipNewLine(VLOG_DELIMITERS); + Printf("Warning: Ignoring subcircuit with no pin names " + "at \"%s\"\n", nexttok); + InputParseError(stderr); + while (nexttok != NULL) { + SkipTokComments(VLOG_DELIMITERS); + if (match(nexttok, ";")) break; + } + ignore = TRUE; + break; } else { new_port = (struct portelement *)CALLOC(1, sizeof(struct portelement)); @@ -1261,31 +1422,61 @@ skip_endmodule: Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok); SkipNewLine(VLOG_DELIMITERS); } - SkipTokComments(VLOG_PIN_NAME_DELIMITERS); + SkipTokComments(VLOG_PIN_CHECK_DELIMITERS); if (match(nexttok, ")")) { char localnet[100]; // Empty parens, so create a new local node savetok = (char)1; - sprintf(localnet, "_noconnect_%d_", localcount++); + if (arraystart != -1) { + /* No-connect on an instance array must also be an array */ + sprintf(localnet, "_noconnect_%d_[%d:%d]", localcount++, + arraystart, arrayend); + } + else + sprintf(localnet, "_noconnect_%d_", localcount++); new_port->net = strsave(localnet); } else { - new_port->net = strsave(nexttok); + if (!strcmp(nexttok, "{")) { + char *in_line_net = (char *)MALLOC(1); + char *new_in_line_net = NULL; + *in_line_net = '\0'; + /* In-line array---read to "}" */ + while (nexttok) { + new_in_line_net = (char *)MALLOC(strlen(in_line_net) + + strlen(nexttok) + 1); + /* Roundabout way to do realloc() becase there is no REALLOC() */ + strcpy(new_in_line_net, in_line_net); + strcat(new_in_line_net, nexttok); + FREE(in_line_net); + in_line_net = new_in_line_net; + if (!strcmp(nexttok, "}")) break; + SkipTokComments(VLOG_PIN_CHECK_DELIMITERS); + } + if (!nexttok) { + Printf("Unterminated net in pin %s\n", in_line_net); + } + new_port->net = in_line_net; + } + else + new_port->net = strsave(nexttok); + /* Read array information along with name; will be parsed later */ - SkipTokComments(VLOG_DELIMITERS); - if (match(nexttok, "[")) { + SkipTokComments(VLOG_PIN_CHECK_DELIMITERS); + if (match(nexttok, "[")) { /* Check for space between name and array identifier */ - SkipTokComments(VLOG_PIN_NAME_DELIMITERS); - if (!match(nexttok, ")")) { - char *expnet; - expnet = (char *)MALLOC(strlen(new_port->net) - + strlen(nexttok) + 2); - sprintf(expnet, "%s[%s", new_port->net, nexttok); - FREE(new_port->net); - new_port->net = expnet; + SkipTokComments(VLOG_PIN_NAME_DELIMITERS); + if (!match(nexttok, ")")) { + char *expnet; + expnet = (char *)MALLOC(strlen(new_port->net) + + strlen(nexttok) + 2); + sprintf(expnet, "%s[%s", new_port->net, nexttok); + FREE(new_port->net); + new_port->net = expnet; } SkipTokComments(VLOG_DELIMITERS); - } + } + if (!match(nexttok, ")")) { Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok); SkipNewLine(VLOG_DELIMITERS); @@ -1302,10 +1493,21 @@ skip_endmodule: else { Printf("Expected to find instance pin block but got \"%s\"\n", nexttok); } - /* Instance should end with a semicolon */ + if (ignore == TRUE) continue; /* moving along. . . */ + + /* Verilog allows multiple instances of a single cell type to be chained */ + /* together with commas. */ + SkipTokComments(VLOG_DELIMITERS); - if (!match(nexttok, ";")) { + if (match(nexttok, ",")) { + goto nextinst; + } + + /* Otherwise, instance must end with a semicolon */ + + else if (!match(nexttok, ";")) { Printf("Expected to find end of instance but got \"%s\"\n", nexttok); + InputParseError(stderr); } /* Check for ignored class */ @@ -1482,14 +1684,44 @@ skip_endmodule: // Otherwise, net is bit-sliced across array of instances. } else if (wb.start > wb.end) { + char *bptr, *cptr, cchar, *netname; + unsigned char is_bundle = 0; + struct bus wbb; + i = wb.start; j = portstart; + + netname = scan->net; + if (*netname == '{') { + is_bundle = 1; + netname++; + cptr = strchr(netname, ','); + if (cptr == NULL) cptr = strchr(netname, '}'); + if (cptr == NULL) cptr = netname + strlen(netname) - 1; + cchar = *cptr; + *cptr = '\0'; + } + + // Remove indexed part of scan->net + if (GetBus(netname, &wbb) == 0) { + i = wbb.start; + if ((bptr = strchr(netname, '[')) != NULL) + *bptr = '\0'; + } + else + i = -1; + + if (is_bundle) *cptr = cchar; /* Restore bundle delimiter */ + while (1) { new_port = (struct portelement *)CALLOC(1, sizeof(struct portelement)); sprintf(vname, "%s[%d]", scan->name, j); new_port->name = strsave(vname); - sprintf(vname, "%s[%d]", scan->net, i); + if (i == -1) + sprintf(vname, "%s", netname); + else + sprintf(vname, "%s[%d]", netname, i); new_port->net = strsave(vname); if (last == NULL) @@ -1504,8 +1736,31 @@ skip_endmodule: if (portstart > portend) j--; else j++; - if (wb.start > wb.end) i--; + if (wbb.start > wbb.end) i--; else i++; + + if (is_bundle && + ((i == -1) || + ((wbb.start > wbb.end) && (i < wbb.end)) || + ((wbb.start < wbb.end) && (i > wbb.end)))) { + if (bptr) *bptr = '['; + + netname = cptr + 1; + cptr = strchr(netname, ','); + if (cptr == NULL) cptr = strchr(netname, '}'); + if (cptr == NULL) cptr = netname + strlen(netname) - 1; + cchar = *cptr; + *cptr = '\0'; + + if (GetBus(netname, &wbb) == 0) { + i = wbb.start; + if ((bptr = strchr(netname, '[')) != NULL) + *bptr = '\0'; + } + else i = -1; + + *cptr = cchar; /* Restore delimiter */ + } } FREE(scan); scan = last; @@ -1600,7 +1855,7 @@ skip_endmodule: // Instance must be an array char netname[128]; int slice; - if (wb.start > wb.end && arraystart > arrayend) + if (wb.start >= wb.end && arraystart >= arrayend) slice = wb.start - (arraystart - i); else if (wb.start < wb.end && arraystart > arrayend) slice = wb.start + (arraystart - i); @@ -1608,6 +1863,7 @@ skip_endmodule: slice = wb.start - (arraystart + i); else // (wb.start < wb.end && arraystart < arrayend) slice = wb.start + (arraystart + i); + sprintf(netname, "%s[%d]", scanroot, slice); if (LookupObject(netname, CurrentCell) == NULL) Node(netname); join(netname, obptr->name); @@ -1696,6 +1952,7 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox) InitializeHashTable(&verilogparams, OBJHASHSIZE); InitializeHashTable(&verilogdefs, OBJHASHSIZE); + definitions = &verilogdefs; /* Add the pre-defined key "LVS" to verilogdefs */ @@ -1718,6 +1975,7 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox) HashKill(&verilogparams); RecurseHashTable(&verilogdefs, freeprop); HashKill(&verilogdefs); + definitions = (struct hashdict *)NULL; // Record the top level file. if (LookupCellFile(fname, filenum) == NULL) CellDef(fname, filenum); @@ -1778,10 +2036,10 @@ void IncludeVerilog(char *fname, int parent, struct cellstack **CellStackPtr, if (strchr(fname, '.') == NULL) { SetExtension(name, fname, VERILOG_EXTENSION); filenum = OpenParseFile(name, parent); - } - if (filenum < 0) { - Fprintf(stderr,"Error in Verilog file include: No file %s\n",name); - return; + } + if (filenum < 0) { + fprintf(stderr,"Error in Verilog file include: No file %s\n", fname); + return; } } } @@ -4,4 +4,4 @@ # all of its config scripts in a different directory than the configure # script itself. -( CFLAGS="-g" ; export CFLAGS ; cd scripts ; ./configure $* ) +( CFLAGS="-g" ; export CFLAGS ; cd scripts ; ./configure "$@" ) diff --git a/scripts/configure b/scripts/configure index c6d171b..001921b 100755 --- a/scripts/configure +++ b/scripts/configure @@ -6413,7 +6413,7 @@ fi # Not available on all versions: check for include file. SHLIB_CFLAGS="-fpic" LDDL_FLAGS="-shared ${LIB_SPECS}" - CFLAGS="${CFLAGS} -l/usr/X11R6/include" + CFLAGS="${CFLAGS} -L/usr/X11R6/include" ;; *-netbsd*|*-openbsd*) diff --git a/scripts/configure.in b/scripts/configure.in index 2f951c2..601a6df 100644 --- a/scripts/configure.in +++ b/scripts/configure.in @@ -1120,7 +1120,7 @@ if test $usingTcl ; then # Not available on all versions: check for include file. SHLIB_CFLAGS="-fpic" LDDL_FLAGS="-shared ${LIB_SPECS}" - CFLAGS="${CFLAGS} -l/usr/X11R6/include" + CFLAGS="${CFLAGS} -L/usr/X11R6/include" ;; *-netbsd*|*-openbsd*) diff --git a/scripts/makedbh b/scripts/makedbh deleted file mode 100755 index 3338a35..0000000 --- a/scripts/makedbh +++ /dev/null @@ -1,187 +0,0 @@ -#!/bin/csh -f -# -# makes the "database.h" (1st argument, $1) file from "database.h.in" -# (2nd argument, $2), setting various mask operation definitions -# according to the number of words implied by the value of TT_MAXTYPES - -# The following mess grabs the value of TT_MAXTYPES from database.h.in -# -set maxtypes=`sed -n -e '/^#define[[:space:]]*TT_MAXTYPES/s/#define[[:space:]]*TT_MAXTYPES[[:space:]]*//p' < $1 | sed -e 's/\/\*[[:print:]]*\*\/[[:space:]]*//g' ` -# -# Alternative method works with outdated versions of sed/ed. -# -if ($maxtypes == "") then - set maxtypes=`sed -n -e '/^#define[ ]*TT_MAXTYPES/s/#define[ ]*TT_MAXTYPES[ ]*//p' < $1 | sed -e 's/\/\*.*\*\/[ ]*//g' ` -endif -# -# If we can't generate database.h correctly, nothing is going to compile. -# -if ($maxtypes == "") then - echo "Bad sed script in scripts/makedbh: Cannot generate database/database.h!" - exit -endif - -# Find derived values from bits per word -# Note that bits-per-word should be determined from the compiler, but -# 32 bits per word has always been hardwired into magic. -# -set bpw = 32 - -# @ wordmask=$bpw - 1 -# set wordshift=`echo "c=l($bpw); d=l(2); scale=0; c/d" | bc -l` -# @ maskwords=$maxtypes + $bpw - 1 -# @ maskwords/=$bpw - -@ maskwords=$maxtypes + $bpw - 1 -@ maskwords/=$bpw - - -# Generate the main part of the database.h file from database.h.in -cat $1 > $2 - -# Generate a list of integers from 0 to the value of "maskwords" - 1 -set count="" -@ maskwords-- -while (${maskwords} >= 0) - set count=`echo ${count} ${maskwords}` - @ maskwords-- -end - -# Definitions - -echo "#define TTMaskZero(m) ( \" >> $2 -foreach i (${count}) - echo -n " (m)->tt_words[$i] = 0" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "#define TTMaskIsZero(m) ( \" >> $2 -foreach i (${count}) - echo -n " (m)->tt_words[$i] == 0" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo " && \" >> $2 - endif -end - -echo "#define TTMaskEqual(m, n) ( \" >> $2 -foreach i (${count}) - echo -n " (m)->tt_words[$i] == (n)->tt_words[$i]" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo " && \" >> $2 - endif -end - -echo "#define TTMaskIntersect(m, n) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] & (n)->tt_words[$i])" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo " || \" >> $2 - endif -end - -echo "#define TTMaskCom(m) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] = ~(m)->tt_words[$i])" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "#define TTMaskCom2(m, n) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] = ~(n)->tt_words[$i])" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "#define TTMaskSetMask(m, n) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] |= (n)->tt_words[$i])" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "#define TTMaskSetMask3(m, n, o) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] |= (n)->tt_words[$i] | (o)->tt_words[$i])" \ - >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "#define TTMaskAndMask(m, n) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] &= (n)->tt_words[$i])" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "#define TTMaskAndMask3(m, n, o) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] = (n)->tt_words[$i] & (o)->tt_words[$i])" \ - >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "#define TTMaskClearMask(m, n) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] &= ~(n)->tt_words[$i])" >> $2 - if ($i == 0) then - echo ")" >> $2 - echo "" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "#define TTMaskClearMask3(m, n, o) ( \" >> $2 -foreach i (${count}) - echo -n " ((m)->tt_words[$i] = (n)->tt_words[$i] & ~(o)->tt_words[$i])" \ - >> $2 - if ($i == 0) then - echo ")" >> $2 - else - echo ", \" >> $2 - endif -end - -echo "" >> $2 -echo "#endif /* _DATABASE_H */" >> $2 diff --git a/tcltk/tclnetgen.c b/tcltk/tclnetgen.c index 14cdd2c..faeba22 100644 --- a/tcltk/tclnetgen.c +++ b/tcltk/tclnetgen.c @@ -3811,8 +3811,8 @@ _netcmp_permute(ClientData clientData, if (PermuteForget(tp->name, fnum, NULL, NULL)) Fprintf(stdout, "No permutations on circuit %s\n", tp->name); else - Fprintf(stderr, "Unable to reset model %s pin permutation %s, %s.\n", - tp->name, pin1, pin2); + Fprintf(stderr, "Unable to reset model %s pin permutations.\n", + tp->name); } return TCL_OK; } diff --git a/tcltk/tkcon.tcl b/tcltk/tkcon.tcl index 609220a..ea49ae6 100755 --- a/tcltk/tkcon.tcl +++ b/tcltk/tkcon.tcl @@ -741,9 +741,9 @@ proc ::tkcon::EvalCmd {w cmd} { set tag [UniqueTag $w] $w insert output $res [list stderr $tag] \n stderr $w tag bind $tag <Enter> \ - [list $w tag configure $tag -under 1] + [list $w tag configure $tag -underline 1] $w tag bind $tag <Leave> \ - [list $w tag configure $tag -under 0] + [list $w tag configure $tag -underline 0] $w tag bind $tag <ButtonRelease-1> \ "if {!\[info exists tkPriv(mouseMoved)\] || !\$tkPriv(mouseMoved)} \ {[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}" @@ -2472,8 +2472,8 @@ proc ::tkcon::ErrorHighlight w { set tag [UniqueTag $w] $w tag add $tag $start+${c0}c $start+1c+${c1}c $w tag configure $tag -foreground $COLOR(stdout) - $w tag bind $tag <Enter> [list $w tag configure $tag -under 1] - $w tag bind $tag <Leave> [list $w tag configure $tag -under 0] + $w tag bind $tag <Enter> [list $w tag configure $tag -underline 1] + $w tag bind $tag <Leave> [list $w tag configure $tag -underline 0] $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \ {[list edit -attach $app -type proc -find $what -- $cmd]}" } @@ -2501,8 +2501,8 @@ proc ::tkcon::ErrorHighlight w { set tag [UniqueTag $w] $w tag add $tag $ix+1c $start $w tag configure $tag -foreground $COLOR(proc) - $w tag bind $tag <Enter> [list $w tag configure $tag -under 1] - $w tag bind $tag <Leave> [list $w tag configure $tag -under 0] + $w tag bind $tag <Enter> [list $w tag configure $tag -underline 1] + $w tag bind $tag <Leave> [list $w tag configure $tag -underline 0] $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \ {[list edit -attach $app -type proc -- $cmd]}" } @@ -2954,14 +2954,14 @@ proc edit {args} { ## set text $w.text set m [menu [::tkcon::MenuButton $menu Edit edit]] - $m add command -label "Cut" -under 2 \ + $m add command -label "Cut" -underline 2 \ -command [list tk_textCut $text] - $m add command -label "Copy" -under 0 \ + $m add command -label "Copy" -underline 0 \ -command [list tk_textCopy $text] - $m add command -label "Paste" -under 0 \ + $m add command -label "Paste" -underline 0 \ -command [list tk_textPaste $text] $m add separator - $m add command -label "Find" -under 0 \ + $m add command -label "Find" -underline 0 \ -command [list ::tkcon::FindBox $text] ## Send To Menu |