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.
This commit is contained in:
parent
a8576d26a9
commit
3dc70148d1
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
163
base/verilog.c
163
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue