Expanded the verilog parsing to include simple handling of ifdef,

ifndef, endif conditional statements.  Pre-define the key "LVS"
for use with netgen.  Also corrected some problems stemming from
the way delimiters are handled and the flexible use of whitespace
in verilog.
This commit is contained in:
Tim Edwards 2018-04-25 15:00:49 -04:00
parent aee4b846e2
commit 1fe341833c
1 changed files with 107 additions and 9 deletions

View File

@ -62,6 +62,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
// Global storage for verilog parameters
struct hashdict verilogparams;
// Global storage for verilog definitions
struct hashdict verilogdefs;
// Global storage for wire buses
struct hashdict buses;
@ -339,8 +341,10 @@ void CleanupModule() {
}
if (has_submodules == FALSE) SetClass(CLASS_MODULE);
RecurseHashTable(&verilogparams, freebus);
HashKill(&buses);
if (buses.hashtab != NULL) {
RecurseHashTable(&buses, freebus);
HashKill(&buses);
}
}
/*------------------------------------------------------*/
@ -401,6 +405,19 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
if (match(nexttok, "//"))
SkipNewLine(VLOG_DELIMITERS);
/* Ignore primitive definitions */
else if (match(nexttok, "primitive")) {
while (1) {
SkipNewLine(VLOG_DELIMITERS);
SkipTok(VLOG_DELIMITERS);
if (EndParseFile()) break;
if (match(nexttok, "endprimitive")) {
in_module = 0;
break;
}
}
}
else if (match(nexttok, "module")) {
InitializeHashTable(&buses, OBJHASHSIZE);
SkipTokNoNewline(VLOG_DELIMITERS);
@ -500,8 +517,11 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
}
in_param = (char)1;
}
else if (match(nexttok, "(")) {
SkipTok(VLOG_DELIMITERS);
else if (nexttok[0] == '(') {
if (match(nexttok, "("))
SkipTok(VLOG_DELIMITERS);
else
nexttok++;
while (match(nexttok, "//")) {
SkipNewLine(VLOG_DELIMITERS);
SkipTok(VLOG_DELIMITERS);
@ -562,7 +582,12 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
wb.start = wb.end = -1;
}
else {
char *pptr;
if ((pptr = strrchr(nexttok, ')')) != NULL)
*pptr = '\0';
Port(nexttok);
if (pptr != NULL) break;
}
}
hasports = 1;
@ -570,6 +595,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
}
}
SkipTok(VLOG_DELIMITERS);
if (nexttok == NULL) break;
while (match(nexttok, "//")) { SkipNewLine(VLOG_DELIMITERS); SkipTok(VLOG_DELIMITERS); }
}
SetClass((blackbox) ? CLASS_MODULE : CLASS_SUBCKT);
@ -688,20 +714,43 @@ skip_endmodule:
FREE(iname);
SkipNewLine(VLOG_DELIMITERS);
}
else if (match(nexttok, "`define") || match(nexttok, "localparam")) {
else if (match(nexttok, "`define")) {
struct property *kl = NULL;
// Pick up key-value pair and store in current cell
/* Parse for definitions used in expressions. Save */
/* definitions in the "verilogdefs" hash table. */
SkipTokNoNewline(VLOG_DELIMITERS);
if ((nexttok == NULL) || (nexttok[0] == '\0')) break;
kl = NewProperty();
kl->key = strsave(nexttok);
kl->idx = 0;
kl->type = PROP_STRING;
kl->slop.dval = 0.0;
SkipTokNoNewline(VLOG_DELIMITERS);
if ((nexttok == NULL) || (nexttok[0] == '\0'))
// Let "`define X" be equivalent to "`define X 1"
kl->pdefault.string = strsave("1");
else
kl->pdefault.string = strsave(nexttok);
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)
{
struct property *kl = NULL;
if ((eqptr = strchr(nexttok, '=')) != NULL) {
*eqptr = '\0';
kl = NewProperty();
kl->key = strsave(nexttok);
@ -714,6 +763,41 @@ skip_endmodule:
}
}
/* 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);
SkipTok(VLOG_DELIMITERS);
if (EndParseFile()) break;
if (match(nexttok, "//"))
continue;
else if (match(nexttok, "`ifdef") || match(nexttok, "`ifndef")) {
nested++;
}
else if (match(nexttok, "`endif")) {
if (nested == 0)
break;
else
nested--;
}
}
}
}
else if (match(nexttok, "wire")) { /* wire = node */
struct bus wb, *nb;
char nodename[128];
@ -1229,6 +1313,7 @@ baddevice:
char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
{
struct property *kl = NULL;
struct cellstack *CellStack = NULL;
struct nlist *tp;
int filenum;
@ -1257,6 +1342,17 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
}
InitializeHashTable(&verilogparams, OBJHASHSIZE);
InitializeHashTable(&verilogdefs, OBJHASHSIZE);
/* Add the pre-defined key "LVS" to verilogdefs */
kl = NewProperty();
kl->key = strsave("LVS");
kl->idx = 0;
kl->type = PROP_STRING;
kl->slop.dval = 0.0;
kl->pdefault.string = strsave("1");
HashPtrInstall(kl->key, kl, &verilogdefs);
/* All verilog files should start with a comment line, */
/* but we won't depend upon it. Any comment line */
@ -1270,6 +1366,8 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
RecurseHashTable(&verilogparams, freeprop);
HashKill(&verilogparams);
RecurseHashTable(&verilogdefs, freeprop);
HashKill(&verilogdefs);
// Record the top level file.
if (LookupCellFile(fname, filenum) == NULL) CellDef(fname, filenum);