From f29452e55091b04d6d1ef762e9eb0340b19d59c6 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Thu, 21 May 2026 14:19:24 -0400 Subject: [PATCH 1/2] An example found by Leo Moser showed that netgen makes an incorrect pin assignment when a verilog input file declares a signal "bundle" with only one signal in it. The solution is to detect bundles which have only one component in them, and remove the bundle delimiters ("{...}") so that the pin connection is treated as a simple signal or vector. --- VERSION | 2 +- base/verilog.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 8d116e3..f3b8376 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.319 +1.5.320 diff --git a/base/verilog.c b/base/verilog.c index 7468af8..b40f02e 100644 --- a/base/verilog.c +++ b/base/verilog.c @@ -2295,7 +2295,18 @@ nextinst: FREE(wire_bundle); wire_bundle = new_wire_bundle; if (!strcmp(nexttok, "}")) + { + /* If a "bundle" has only one component, then it is + * not really a bundle and should be treated as a + * single wire. + */ + if (strchr(wire_bundle, ',') == NULL) { + int blen = strlen(wire_bundle + 1) - 1; + memmove(wire_bundle, wire_bundle + 1, blen); + *(wire_bundle + blen) = '\0'; + } break; + } SkipTokComments(VLOG_PIN_CHECK_DELIMITERS); } if (!nexttok) { From 9630670071293152601b2af7313a92d299d5af2f Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Thu, 21 May 2026 15:35:57 -0400 Subject: [PATCH 2/2] The example cited in the last commit is not completely solved by the code changes in the last commit. There is still an issue in which pins should match between name X on one side and X[Y] on the other side, if there is no X[Z] where Z != Y, specifically if one or both cells is a black box, since the equivalence cannot be determined by net matching. The pin matching has gotten out of hand and really should be completely redone. . . --- base/netcmp.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/base/netcmp.c b/base/netcmp.c index 72f088c..5985a03 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -7896,7 +7896,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) if (*(cover + i) == (char)0) { j = 0; for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) { - char *name1, *name2; + char *name1, *name2, *aptr1 = NULL, *aptr2 = NULL; if (!IsPort(ob2)) break; @@ -7914,8 +7914,59 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) if (!strncmp(name1, "proxy", 5) && (ob2->node == -1)) name1 +=5; if (!strncmp(name2, "proxy", 5) && (ob1->node == -1)) name2 +=5; + /* Recognize an array as matching a non-array of the same */ + /* name if the array is size 1. There must be a better way */ + /* to do this; this method makes excessive calls to */ + /* matchfunc(). */ + + if ((tc1->flags & CELL_PLACEHOLDER) || (tc2->flags && CELL_PLACEHOLDER)) { + aptr1 = strchr(name1, '['); + aptr2 = strchr(name2, '['); + + if ((aptr1 != NULL) && (aptr2 == NULL)) { + *aptr1 = '\0'; + if ((*matchfunc)(name1, name2)) { + /* Check that name1 does not have another array + * component in ob1 + */ + struct objlist *ob3; + for (ob3 = tc1->cell; ob3; ob3 = ob3->next) { + if (!IsPort(ob3)) break; + if (ob3 == ob1) continue; + if (!strncmp(ob3->name, name1, strlen(name1)) && + *(ob3->name + strlen(name1)) == '[') { + *aptr1 = '['; + break; + } + } + } + } + + if ((aptr1 == NULL) && (aptr2 != NULL)) { + *aptr2 = '\0'; + if ((*matchfunc)(name1, name2)) { + /* Check that name2 does not have another array + * component in ob1 + */ + struct objlist *ob3; + for (ob3 = tc2->cell; ob3; ob3 = ob3->next) { + if (!IsPort(ob3)) break; + if (ob3 == ob2) continue; + if (!strncmp(ob3->name, name2, strlen(name2)) && + *(ob3->name + strlen(name2)) == '[') { + *aptr2 = '['; + break; + } + } + } + } + } + if ((*matchfunc)(name1, name2)) { + if (aptr1) *aptr1 = '['; + if (aptr2) *aptr2 = '['; + /* If both sides have unconnected nodes, then pins with */ /* matching names are an automatic match. Otherwise, if */ /* matching black-box entries, then pins are always */ @@ -8069,6 +8120,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) } } if (bangptr2) *bangptr2 = '!'; + if (aptr1) *aptr1 = '['; + if (aptr2) *aptr2 = '['; j++; } }