Merge branch 'master' into netgen-1.5
This commit is contained in:
commit
205cf2aa58
181
base/verilog.c
181
base/verilog.c
|
|
@ -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,30 +1064,33 @@ 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");
|
||||||
|
int j;
|
||||||
struct objlist *lhs, *rhs;
|
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.
|
|
||||||
|
|
||||||
|
if (is_wire) {
|
||||||
SkipTokNoNewline(VLOG_DELIMITERS);
|
SkipTokNoNewline(VLOG_DELIMITERS);
|
||||||
if (match(nexttok, "real")) SkipTokNoNewline(VLOG_DELIMITERS);
|
if (match(nexttok, "real"))
|
||||||
while (nexttok != NULL) {
|
SkipTokNoNewline(VLOG_DELIMITERS);
|
||||||
if (match(nexttok, "=")) {
|
else if (match(nexttok, "logic"))
|
||||||
is_assignment = TRUE;
|
SkipTokNoNewline(VLOG_DELIMITERS);
|
||||||
}
|
|
||||||
else if (GetBusTok(&wb) == 0) {
|
if (GetBusTok(&wb) == 0) {
|
||||||
/* Handle bus notation */
|
/* Handle bus notation */
|
||||||
SkipTokNoNewline(VLOG_DELIMITERS);
|
SkipTokNoNewline(VLOG_DELIMITERS);
|
||||||
|
strcpy(noderoot, nexttok);
|
||||||
if (wb.start > wb.end) {
|
if (wb.start > wb.end) {
|
||||||
for (i = wb.end; i <= wb.start; i++) {
|
for (i = wb.end; i <= wb.start; 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -1094,6 +1098,7 @@ skip_endmodule:
|
||||||
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();
|
||||||
|
|
@ -1102,29 +1107,127 @@ skip_endmodule:
|
||||||
HashPtrInstall(nexttok, nb, &buses);
|
HashPtrInstall(nexttok, nb, &buses);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (is_assignment) {
|
if (LookupObject(nexttok, CurrentCell) == NULL) {
|
||||||
/* Handle assignment statements */
|
Node(nexttok);
|
||||||
/* To be done: Handle where both are bus names, and */
|
lhs = LookupObject(nexttok, CurrentCell);
|
||||||
/* where lhs is a bus name and rhs is a list of nets */
|
}
|
||||||
if ((rhs = LookupObject(nexttok, CurrentCell)) != NULL) {
|
}
|
||||||
join(lhs->name, rhs->name);
|
while (1) {
|
||||||
|
SkipTokNoNewline(VLOG_DELIMITERS);
|
||||||
|
if (match(nexttok, ",")) {
|
||||||
|
SkipTokNoNewline(VLOG_DELIMITERS);
|
||||||
|
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 {
|
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, "
|
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 */
|
||||||
|
/* until bits in signal are exhausted or LHS is full. */
|
||||||
|
|
||||||
|
if (i != -1)
|
||||||
|
sprintf(nodename, "%s[%d]", noderoot, i);
|
||||||
|
else
|
||||||
|
sprintf(nodename, lhs->name);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
else if (LookupObject(nexttok, CurrentCell) == NULL)
|
|
||||||
Node(nexttok);
|
|
||||||
lhs = LookupObject(nexttok, CurrentCell);
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
SkipTokNoNewline(VLOG_DELIMITERS);
|
SkipTokNoNewline(VLOG_DELIMITERS);
|
||||||
} while (nexttok && match(nexttok, ";"));
|
} 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,9 +1373,32 @@ skip_endmodule:
|
||||||
new_port->net = strsave(localnet);
|
new_port->net = strsave(localnet);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
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);
|
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);
|
||||||
|
|
@ -1286,6 +1412,7 @@ skip_endmodule:
|
||||||
}
|
}
|
||||||
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);
|
||||||
|
|
@ -1785,7 +1912,7 @@ void IncludeVerilog(char *fname, int parent, struct cellstack **CellStackPtr,
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue