From 1d286f9973a9951c12ed2ae487dbcce3c4999685 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 1 Jan 2025 13:27:39 -0500 Subject: [PATCH] Corrected an issue with generating proxy pins that had previously forced flattening to be done whenever any pin mismatch occurred, which undermined the whole proxy pin method. With the proxy pins fixed, reinstated the method of avoiding flattening when pin issues can be trivially corrected. Also: Added output to the pin matching for one mismatch case that was being missed. --- VERSION | 2 +- base/flatten.c | 40 +++++++++++++++++++++++++++++++ base/netcmp.c | 57 ++++++++++++++++++++++++++++++++++++++------- tcltk/netgen.tcl.in | 5 ++++ 4 files changed, 95 insertions(+), 9 deletions(-) diff --git a/VERSION b/VERSION index 338640b..9dcb9bd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.289 +1.5.290 diff --git a/base/flatten.c b/base/flatten.c index 0a8c7af..90017dd 100644 --- a/base/flatten.c +++ b/base/flatten.c @@ -1306,6 +1306,14 @@ int UniquePins(char *name, int filenum) return 1; } +/* Structure used below for keeping track of node numbers + * belonging to removed nodes. + */ +struct LinkedNum { + int node; + struct LinkedNum *next; +}; + /*------------------------------------------------------*/ /* Callback function for CleanupPins */ /* Note that if the first pin of the instance is a */ @@ -1318,6 +1326,7 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata) struct nlist *ptr; struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob; struct nlist *tc = (struct nlist *)clientdata; + struct LinkedNum *newnodenum, *removedNodes = (struct LinkedNum *)NULL; int pinnum; char *saveinst = NULL; @@ -1373,6 +1382,15 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata) saveinst = ob->instance.name; } if (ob->model.class != NULL) FREE(ob->model.class); + + // Record the net number of the pin being removed, to + // check at the end if the net belonged to a pin that + // got orphaned. + newnodenum = (struct LinkedNum *)MALLOC(sizeof(struct LinkedNum)); + newnodenum->node = ob->node; + newnodenum->next = removedNodes; + removedNodes = newnodenum; + FREE(ob); } else { @@ -1416,6 +1434,28 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata) } } + while (removedNodes != NULL) { + int nodenum = removedNodes->node; + struct objlist *ob2; + + /* Only concerned with nodes that are in the pin list of ptr->cell */ + for (ob = ptr->cell; ob != NULL; ob = ob->next) { + if (ob->type != PORT) break; + if (ob->node == nodenum) break; + } + if (ob && (ob->type == PORT)) { + /* Check if this node number exists only in the port record */ + for (nob = ob->next; nob != NULL; nob = nob->next) + if (nob->node == nodenum) break; + if (nob == NULL) { + ob->node = -1; /* This pin is now disconnected */ + } + } + newnodenum = removedNodes; + removedNodes = removedNodes->next; + FREE(newnodenum); + } + if (saveinst != NULL) FREE(saveinst); return NULL; /* Keep the search going */ } diff --git a/base/netcmp.c b/base/netcmp.c index 0fa925a..c209fe1 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -6585,7 +6585,10 @@ int ResolveAutomorphsByPin(int match_nets) int portnum; /* Diagnostic */ - Fprintf(stdout, "Resolving symmetries by pin name.\n"); + if (match_nets) + Fprintf(stdout, "Resolving symmetries by net name.\n"); + else + Fprintf(stdout, "Resolving symmetries by pin name.\n"); for (NC = NodeClasses; NC != NULL; NC = NC->next) { struct Node *N1, *N2; @@ -7589,6 +7592,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) { if (ob2->type != PORT) break; else haspins = 1; + /* The model.port record for pins will be used to match the pin order + * of the cells in each netlist. Make sure the value is reset on + * entering this subroutine. + */ ob2->model.port = -1; } numnodes = 0; @@ -7742,7 +7749,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) if (strcmp(obn->name, "(no pins)")) { output_string_fill(ostr); output_string_left(ostr, "%s", obn->name); - output_string_right(ostr, "(no pin, node is %s", + output_string_right(ostr, "(no pin, node is %s)", obp->name); output_string_print(ostr); } @@ -8034,11 +8041,36 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) if (ob2->type != PORT) break; if (ob2->model.port == -1) { + /* Find this node in NodeClasses and find the corresponding + * net in the other circuit, if there is one (NOTE: Needs + * refactoring; should not be going through NodeClasses + * inside a loop.) + */ + obn = NULL; + for (NC = NodeClasses; NC != NULL; NC = NC->next) { + for (N2 = NC->nodes; N2 != NULL; N2 = N2->next) { + if (N2->graph != Circuit1->file) { + obp = N2->object; + if (IsPort(obp) && (obp->node == ob2->node)) { + for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) { + if (N1->graph == Circuit1->file) { + obn = N1->object; + } + } + } + } + } + } + if (Debug == 0) { // See above for reverse case if (strcmp(ob2->name, "(no pins)")) { output_string_fill(ostr); - output_string_left(ostr, "%s", "(no matching pin)"); + if (obn == NULL) + output_string_left(ostr, "%s", "(no matching pin)"); + else + output_string_left(ostr, "(no pin, node is %s)", + obn->name); output_string_right(ostr, "%s", ob2->name); output_string_print(ostr); } @@ -8155,12 +8187,15 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) if (obn == NULL) ob1->node = -1; /* Make disconnected */ } + /* NOTE: Previously kept the port if model.port is -1; however, + * all ports are -1 here so not sure why that was in there. . . + */ if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0 - || (ob1->node < 0 && tc1->class == CLASS_MODULE) - || (ob1->node < 0 && ob1->model.port == -1)) { + || (ob1->node < 0 && tc1->class == CLASS_MODULE)) { /* Add a proxy pin to tc2 */ obn = (struct objlist *)CALLOC(1, sizeof(struct objlist)); + obn->node = -1; if (ob1 == NULL) { obn->name = (char *)MALLOC(15); sprintf(obn->name, "proxy%d", rand() & 0x3ffffff); @@ -8172,7 +8207,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) obn->type = UNKNOWN; obn->model.port = (i - j); obn->instance.name = NULL; - obn->node = -1; if (ob2 == tc2->cell) { obn->next = ob2; @@ -8188,9 +8222,16 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist) HashPtrInstall(obn->name, obn, &(tc2->objdict)); } - else if (ob1 != NULL && ob1->type == PORT) { + else if (ob1 != NULL && ob1->type == PORT && ob1->node < 0) { /* Disconnected node was not meaningful, has no pin match in */ - /* the compared circuit, and so should be discarded. */ + /* the compared circuit, and so should be discarded. This */ + /* case is not output above, so do it here. */ + + output_string_fill(ostr); + output_string_left(ostr, "%s", ob1->name); + output_string_right(ostr, "%s", "(no matching pin)"); + output_string_print(ostr); + ob1->node = -2; needclean1 = 1; diff --git a/tcltk/netgen.tcl.in b/tcltk/netgen.tcl.in index 164850c..2d5c13c 100644 --- a/tcltk/netgen.tcl.in +++ b/tcltk/netgen.tcl.in @@ -655,6 +655,11 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} { } } elseif {[netgen::print queue] == {} && $result == 0} { set pinMismatch 1 + } else { + # This assumes that proxy pins are added correctly. Previously, + # that was not trusted, and so an initial pin mismatch would + # always force subcells to be flattened. + set doFlatten 0 } } if {$doFlatten} {