From 3dc70148d1edff5a7d326f97d401fa1293ae45a2 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sun, 8 Sep 2019 19:59:27 -0400 Subject: [PATCH] Added support in the verilog parser for definitions anywhere in the code using the backtick expression. Also expanded the parsing of "ifdef", "ifndef", and "endif" to include "elsif" and "else". All forms of "if" statements should now be handled, since verilog does not define boolean expressions in ifdef operators like most languages do. --- base/netfile.c | 79 +++++++++++++++++++++++- base/netfile.h | 1 + base/verilog.c | 163 ++++++++++++++++++------------------------------- 3 files changed, 137 insertions(+), 106 deletions(-) diff --git a/base/netfile.c b/base/netfile.c index b0fd12e..74ff942 100644 --- a/base/netfile.c +++ b/base/netfile.c @@ -191,6 +191,8 @@ struct filestack { static struct filestack *OpenFiles = NULL; +struct hashdict *definitions = (struct hashdict *)NULL; + #define WHITESPACE_DELIMITER " \t\n\r" /*----------------------------------------------------------------------*/ @@ -292,9 +294,82 @@ int GetNextLineNoNewline(char *delimiter) FREE(linetok); linetok = (char *)MALLOC(linesize); } - linenum++; - strcpy(linetok, line); + + /* 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; + int len, dlen, vlen, addin = 0; + + 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); return 0; diff --git a/base/netfile.h b/base/netfile.h index fbcf413..ccec49b 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 */ diff --git a/base/verilog.c b/base/verilog.c index b7a9ae3..520f944 100644 --- a/base/verilog.c +++ b/base/verilog.c @@ -121,19 +121,22 @@ 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) { + // 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) { @@ -142,53 +145,15 @@ 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; - } - } - else { - 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); - 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" + Printf("Parameter %s has value %g that cannot be parsed" " as an integer.\n", nexttok, kl->pdefault.dval); - return 1; - } + return 1; } - else { - Printf("Parameter %s has unknown type; don't know how" + } + else { + Printf("Parameter %s has unknown type; don't know how" " to parse.\n", nexttok); - return 1; - } + return 1; } } } @@ -204,18 +169,22 @@ 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) { + // 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; } } @@ -232,47 +201,8 @@ int GetBusTok(struct bus *wb) } else { Printf("Parameter %s has unknown type; don't know how" - " 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); - 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; - } + return 1; } } } @@ -1026,6 +956,22 @@ skip_endmodule: } HashPtrInstall(kl->key, kl, &verilogdefs); } + 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, "localparam")) { // Pick up key = value pairs and store in current cell while (nexttok != NULL) @@ -1064,10 +1010,10 @@ skip_endmodule: } } - /* Note: This is just the most basic processing of conditionals, */ - /* although it does handle nested conditionals. */ + /* Process conditions. Note that conditionals may be nested. */ - else if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef")) { + 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; @@ -1077,9 +1023,9 @@ skip_endmodule: /* To be done: Handle boolean arithmetic on conditionals */ kl = (struct property *)HashLookup(nexttok, &verilogdefs); - if (((invert == 0) && (kl == NULL)) + while (((invert == 0) && (kl == NULL)) || ((invert == 1) && (kl != NULL))) { - /* Skip to matching `endif */ + /* Skip to matching `endif, `elsif, or `else */ while (1) { SkipNewLine(VLOG_DELIMITERS); SkipTokComments(VLOG_DELIMITERS); @@ -1087,13 +1033,20 @@ skip_endmodule: if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef")) { nested++; } - else if (match(nexttok, "`endif")) { + 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; } } @@ -1909,6 +1862,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 */ @@ -1931,6 +1885,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);