From 8e0371e09b6e28d8be4d5b5fedaf0fc508104ef4 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sun, 5 May 2019 10:52:07 -0400 Subject: [PATCH] Corrected handling of verilog backslash-escaped names in the verilog netlist parser. --- base/netfile.c | 19 ++++++++++++++++++- base/verilog.c | 51 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/base/netfile.c b/base/netfile.c index dd29d3c..432ff26 100644 --- a/base/netfile.c +++ b/base/netfile.c @@ -471,6 +471,23 @@ 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". */ + + if (*s == '\\') { + while (*s != '\0') { + if (*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 +496,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/verilog.c b/base/verilog.c index 78d70b1..136cac7 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; @@ -291,6 +292,8 @@ int GetBusTok(struct bus *wb) return 1; } } + /* Move token forward to bus name */ + SkipTokComments(VLOG_DELIMITERS); } else { struct bus *hbus; @@ -312,7 +315,7 @@ int GetBusTok(struct bus *wb) int GetBus(char *astr, struct bus *wb) { - char *colonptr, *brackstart, *brackend; + char *colonptr, *brackstart, *brackend, *sstr; int result, start, end; if (wb == NULL) return 0; @@ -320,15 +323,21 @@ int GetBus(char *astr, struct bus *wb) wb->start = -1; wb->end = -1; } - brackstart = strchr(astr, '['); + sstr = astr; + + // Skip to the end of verilog names bounded by '\' and ' ' + if (*sstr == '\\') + while (*sstr && *sstr != ' ') sstr++; + + brackstart = strchr(sstr, '['); if (brackstart != NULL) { - brackend = strchr(astr, ']'); + brackend = strchr(sstr, ']'); if (brackend == NULL) { Printf("Badly formed array notation \"%s\"\n", astr); return 1; } *brackend = '\0'; - colonptr = strchr(astr, ':'); + colonptr = strchr(sstr, ':'); if (colonptr) *colonptr = '\0'; result = sscanf(brackstart + 1, "%d", &start); if (colonptr) *colonptr = ':'; @@ -1229,12 +1238,12 @@ skip_endmodule: arraystart = wb.start; arrayend = wb.end; } - SkipTokComments(VLOG_DELIMITERS); } if (match(nexttok, "(")) { char savetok = (char)0; struct portelement *new_port; + char *in_line_net = NULL; // Read the pin list while (nexttok != NULL) { @@ -1261,7 +1270,7 @@ 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 @@ -1270,7 +1279,29 @@ skip_endmodule: new_port->net = strsave(localnet); } else { - new_port->net = strsave(nexttok); + if (!strcmp(nexttok, "{")) { + char *in_line_net = (char *)MALLOC(1); + *in_line_net = '\0'; + /* In-line array---Read to "}" */ + while (nexttok) { + char *new_in_line_net = (char *)MALLOC( + strlen(in_line_net) + + strlen(nexttok) + 1); + 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, "[")) { @@ -1279,8 +1310,8 @@ skip_endmodule: if (!match(nexttok, ")")) { char *expnet; expnet = (char *)MALLOC(strlen(new_port->net) - + strlen(nexttok) + 2); - sprintf(expnet, "%s[%s", new_port->net, nexttok); + + strlen(nexttok) + 3); + sprintf(expnet, "%s [%s", new_port->net, nexttok); FREE(new_port->net); new_port->net = expnet; }