diff --git a/base/netfile.c b/base/netfile.c index 74ff942..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). @@ -253,7 +265,6 @@ void TrimQuoted(char *line) } } } - } /*----------------------------------------------------------------------*/ @@ -267,112 +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); - } + // This is more reliable than feof() ... + testc = getc(infile); + if (testc == -1) return -1; + ungetc(testc, infile); - /* Check for substitutions (verilog only). Make sure linetok is */ - /* large enough to hold the entire line after substitutions. */ + 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); + } - if (definitions != NULL) { - char *s, *w, e; - struct property *kl; - int len, dlen, vlen, addin = 0; - unsigned char found = FALSE; + /* Check for substitutions (verilog only). Make sure linetok is */ + /* large enough to hold the entire line after substitutions. */ - 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); - } - } - } + if (definitions != NULL) { + char *s, *w, e; + struct property *kl; + int len, dlen, vlen, addin = 0; + unsigned char found = FALSE; - /* Make definition substitutions (verilog only) */ + 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); + } + } + } - if (definitions != NULL) { - char *s, *t, *w, e; - struct property *kl; - int len, dlen, vlen, addin = 0; + /* Make definition substitutions (verilog only) */ - 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); + if (definitions != NULL) { + char *s, *t, *w, e; + struct property *kl; - TrimQuoted(linetok); - linenum++; + 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); - nexttok = strdtok(linetok, WHITESPACE_DELIMITER, delimiter); - return 0; + 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); + } + } + + /* 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; } /*----------------------------------------------------------------------*/ diff --git a/base/netfile.h b/base/netfile.h index ccec49b..3fe7ffe 100644 --- a/base/netfile.h +++ b/base/netfile.h @@ -33,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/verilog.c b/base/verilog.c index 520f944..c4e5003 100644 --- a/base/verilog.c +++ b/base/verilog.c @@ -560,7 +560,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 */ @@ -1010,46 +1010,6 @@ skip_endmodule: } } - /* Process conditions. Note that conditionals may be nested. */ - - else if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef") || - match(nexttok, "`elsif") || match(nexttok, "`else")) { - 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); - while (((invert == 0) && (kl == NULL)) - || ((invert == 1) && (kl != NULL))) { - /* Skip to matching `endif, `elsif, or `else */ - while (1) { - SkipNewLine(VLOG_DELIMITERS); - SkipTokComments(VLOG_DELIMITERS); - if (EndParseFile()) break; - if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef")) { - nested++; - } - else if (match(nexttok, "`endif") || match(nexttok, "`elsif") || - match(nexttok, "`else")) { - if (nested == 0) - break; - else - nested--; - } - } - if (match(nexttok, "`elsif")) { - SkipTokComments(VLOG_DELIMITERS); - invert = 0; - kl = (struct property *)HashLookup(nexttok, &verilogdefs); - } - else break; - } - } - else if (match(nexttok, "wire") || match(nexttok, "assign")) { /* wire = node */ struct bus wb, wb2, *nb; char nodename[128], noderoot[100]; @@ -1179,14 +1139,26 @@ skip_endmodule: } } else { + j = -1; rhs = LookupObject(nexttok, CurrentCell); } if ((lhs == NULL) || (rhs == NULL)) { - /* Not parsable, probably behavioral verilog? */ - Printf("Module '%s' is not structural verilog, " - "making black-box.\n", model); - SetClass(CLASS_MODULE); - goto skip_endmodule; + 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 */ @@ -1219,9 +1191,10 @@ skip_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")) {