Merge branch 'master' into netgen-1.5

This commit is contained in:
Tim Edwards 2019-08-11 03:00:07 -04:00
commit 205cf2aa58
1 changed files with 201 additions and 74 deletions

View File

@ -61,6 +61,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
// separates single-character delimiters from two-character delimiters. // 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_NAME_DELIMITERS "X///**/(**)X()"
#define VLOG_PIN_CHECK_DELIMITERS "X///**/(**)X,;(){}"
// Global storage for verilog parameters // Global storage for verilog parameters
struct hashdict verilogparams; struct hashdict verilogparams;
@ -1063,68 +1064,170 @@ skip_endmodule:
} }
else if (match(nexttok, "wire") || match(nexttok, "assign")) { /* wire = node */ else if (match(nexttok, "wire") || match(nexttok, "assign")) { /* wire = node */
struct bus wb, *nb; struct bus wb, wb2, *nb;
char nodename[128]; char nodename[128], noderoot[100];
int is_assignment = FALSE; int is_wire = match(nexttok, "wire");
struct objlist *lhs, *rhs; int j;
struct objlist *lhs, *rhs;
// Several allowed uses of "assign": /* Get left-hand side expression. If this is a wire statement, */
// "assign a = b" joins two nets. /* then define the wire. If is_wire is false, then the wire */
// "assign a = {b, c, ...}" creates a bus from components. /* should already be defined. */
// "assign" using any boolean arithmetic is not structural verilog.
SkipTokNoNewline(VLOG_DELIMITERS); if (is_wire) {
if (match(nexttok, "real")) SkipTokNoNewline(VLOG_DELIMITERS); SkipTokNoNewline(VLOG_DELIMITERS);
while (nexttok != NULL) { if (match(nexttok, "real"))
if (match(nexttok, "=")) { SkipTokNoNewline(VLOG_DELIMITERS);
is_assignment = TRUE; else if (match(nexttok, "logic"))
} SkipTokNoNewline(VLOG_DELIMITERS);
else if (GetBusTok(&wb) == 0) {
/* Handle bus notation */ if (GetBusTok(&wb) == 0) {
SkipTokNoNewline(VLOG_DELIMITERS); /* Handle bus notation */
if (wb.start > wb.end) { SkipTokNoNewline(VLOG_DELIMITERS);
for (i = wb.end; i <= wb.start; i++) { strcpy(noderoot, nexttok);
sprintf(nodename, "%s[%d]", nexttok, i); if (wb.start > wb.end) {
if (LookupObject(nodename, CurrentCell) == NULL) for (i = wb.end; i <= wb.start; i++) {
Node(nodename); sprintf(nodename, "%s[%d]", nexttok, i);
if (LookupObject(nodename, CurrentCell) == NULL)
Node(nodename);
if (i == wb.start) lhs = LookupObject(nodename, CurrentCell);
}
} }
} else {
else { for (i = wb.start; i <= wb.end; i++) {
for (i = wb.start; i <= wb.end; i++) { sprintf(nodename, "%s[%d]", nexttok, i);
sprintf(nodename, "%s[%d]", nexttok, i); if (LookupObject(nodename, CurrentCell) == NULL)
if (LookupObject(nodename, CurrentCell) == NULL) Node(nodename);
Node(nodename); if (i == wb.start) lhs = LookupObject(nodename, CurrentCell);
}
} }
} nb = NewBus();
nb = NewBus(); nb->start = wb.start;
nb->start = wb.start; nb->end = wb.end;
nb->end = wb.end; HashPtrInstall(nexttok, nb, &buses);
HashPtrInstall(nexttok, nb, &buses); }
} else {
else { if (LookupObject(nexttok, CurrentCell) == NULL) {
if (is_assignment) { Node(nexttok);
/* Handle assignment statements */ lhs = LookupObject(nexttok, CurrentCell);
/* To be done: Handle where both are bus names, and */ }
/* where lhs is a bus name and rhs is a list of nets */ }
if ((rhs = LookupObject(nexttok, CurrentCell)) != NULL) { while (1) {
join(lhs->name, rhs->name); SkipTokNoNewline(VLOG_DELIMITERS);
} if (match(nexttok, ",")) {
else { SkipTokNoNewline(VLOG_DELIMITERS);
Printf("Module '%s' is not structural verilog, " if (LookupObject(nexttok, CurrentCell) == NULL) {
Node(nexttok);
lhs = LookupObject(nexttok, CurrentCell);
}
}
else break;
}
}
else { /* "assign" */
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (GetBus(nexttok, &wb) == 0) {
char *aptr = strchr(nexttok, '[');
if (aptr != NULL) {
*aptr = '\0';
/* Find object of first net in bus */
strcpy(noderoot, nexttok);
sprintf(nodename, "%s[%d]", nexttok, wb.start);
lhs = LookupObject(nodename, CurrentCell);
*aptr = '[';
}
}
else {
lhs = LookupObject(nexttok, CurrentCell);
}
SkipTokNoNewline(VLOG_DELIMITERS);
if (lhs && ((!nexttok) || (!match(nexttok, "=")))) {
fprintf(stderr, "Empty assignment for net %s\n", lhs->name);
}
}
/* Check for assignment statement, and handle any allowed uses. */
/* Any uses other than those mentioned below will cause the entire */
/* module to be treated as a black box. */
// Allowed uses of "assign" for netlists:
// "assign a = b" joins two nets.
// "assign a = {b, c, ...}" creates a bus from components.
// "assign" using any boolean arithmetic is not structural verilog.
if (nexttok && match(nexttok, "=")) {
char assignname[128], assignroot[100];
i = wb.start;
while (1) {
SkipTokNoNewline(VLOG_PIN_CHECK_DELIMITERS);
if (!nexttok) break;
if (match(nexttok, "{")) {
/* RHS is a bundle */
continue;
}
else if (match(nexttok, "}")) {
/* End of bundle */
continue;
}
else if (match(nexttok, ",")) {
/* Additional signals in bundle */
continue;
}
else if (match(nexttok, ";")) {
/* End of assignment */
break;
}
else {
if (GetBus(nexttok, &wb2) == 0) {
char *aptr = strchr(nexttok, '[');
j = wb2.start;
if (aptr != NULL) {
*aptr = '\0';
strcpy(assignroot, nexttok);
sprintf(assignname, "%s[%d]", nexttok, j);
rhs = LookupObject(assignname, CurrentCell);
*aptr = '[';
}
}
else {
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); "making black-box.\n", model);
SetClass(CLASS_MODULE); SetClass(CLASS_MODULE);
goto skip_endmodule; goto skip_endmodule;
} }
is_assignment = FALSE; while (1) {
} /* Assign bits in turn from bundle in RHS to bits of LHS */
else if (LookupObject(nexttok, CurrentCell) == NULL) /* until bits in signal are exhausted or LHS is full. */
Node(nexttok);
lhs = LookupObject(nexttok, CurrentCell); if (i != -1)
} sprintf(nodename, "%s[%d]", noderoot, i);
do { else
SkipTokNoNewline(VLOG_DELIMITERS); sprintf(nodename, lhs->name);
} while (nexttok && match(nexttok, ";")); if (j != -1)
} sprintf(assignname, "%s[%d]", assignroot, j);
else
sprintf(assignname, rhs->name);
join(nodename, assignname);
if (j == wb2.end) break;
if (i == wb.end) break;
j += (wb2.end > wb2.start) ? 1 : -1;
}
}
i += (wb.end > wb.start) ? 1 : -1;
}
}
do {
SkipTokNoNewline(VLOG_DELIMITERS);
} while (nexttok && match(nexttok, ";"));
} }
else if (match(nexttok, "endmodule")) { else if (match(nexttok, "endmodule")) {
// No action---new module is started with next 'module' statement, // No action---new module is started with next 'module' statement,
@ -1261,7 +1364,7 @@ skip_endmodule:
Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok); Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok);
SkipNewLine(VLOG_DELIMITERS); SkipNewLine(VLOG_DELIMITERS);
} }
SkipTokComments(VLOG_PIN_NAME_DELIMITERS); SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (match(nexttok, ")")) { if (match(nexttok, ")")) {
char localnet[100]; char localnet[100];
// Empty parens, so create a new local node // Empty parens, so create a new local node
@ -1270,22 +1373,46 @@ skip_endmodule:
new_port->net = strsave(localnet); new_port->net = strsave(localnet);
} }
else { else {
new_port->net = strsave(nexttok); if (!strcmp(nexttok, "{")) {
char *in_line_net = (char *)MALLOC(1);
char *new_in_line_net = NULL;
*in_line_net = '\0';
/* In-line array---read to "}" */
while (nexttok) {
new_in_line_net = (char *)MALLOC(strlen(in_line_net) +
strlen(nexttok) + 1);
/* Roundabout way to do realloc() becase there is no REALLOC() */
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 */ /* Read array information along with name; will be parsed later */
SkipTokComments(VLOG_DELIMITERS); SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (match(nexttok, "[")) { if (match(nexttok, "[")) {
/* Check for space between name and array identifier */ /* Check for space between name and array identifier */
SkipTokComments(VLOG_PIN_NAME_DELIMITERS); SkipTokComments(VLOG_PIN_NAME_DELIMITERS);
if (!match(nexttok, ")")) { if (!match(nexttok, ")")) {
char *expnet; char *expnet;
expnet = (char *)MALLOC(strlen(new_port->net) expnet = (char *)MALLOC(strlen(new_port->net)
+ strlen(nexttok) + 2); + strlen(nexttok) + 2);
sprintf(expnet, "%s[%s", new_port->net, nexttok); sprintf(expnet, "%s[%s", new_port->net, nexttok);
FREE(new_port->net); FREE(new_port->net);
new_port->net = expnet; new_port->net = expnet;
} }
SkipTokComments(VLOG_DELIMITERS); SkipTokComments(VLOG_DELIMITERS);
} }
if (!match(nexttok, ")")) { if (!match(nexttok, ")")) {
Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok); Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok);
SkipNewLine(VLOG_DELIMITERS); SkipNewLine(VLOG_DELIMITERS);
@ -1783,10 +1910,10 @@ void IncludeVerilog(char *fname, int parent, struct cellstack **CellStackPtr,
if (strchr(fname, '.') == NULL) { if (strchr(fname, '.') == NULL) {
SetExtension(name, fname, VERILOG_EXTENSION); SetExtension(name, fname, VERILOG_EXTENSION);
filenum = OpenParseFile(name, parent); filenum = OpenParseFile(name, parent);
} }
if (filenum < 0) { if (filenum < 0) {
Fprintf(stderr,"Error in Verilog file include: No file %s\n",name); fprintf(stderr,"Error in Verilog file include: No file %s\n", fname);
return; return;
} }
} }
} }