From 06386bee1bf3899d9758946743b2752400f6bbea Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 25 Oct 2022 20:14:44 -0400 Subject: [PATCH] Corrected an issue with "flatten": If a cell has disconnected ports, then flattening instances of that cell can cause a port of the parent cell connected to the disconnected port of the child cell to itself become disconnected. If the parent port is not changed to show the disconnected state, then pin mismatch can occur if the netlist being matched didn't have the same flattened subcell. This condition is now detected and handled correctly. --- VERSION | 2 +- base/flatten.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 476edb5..f876ffa 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.235 +1.5.236 diff --git a/base/flatten.c b/base/flatten.c index ad6516e..1fb83ba 100644 --- a/base/flatten.c +++ b/base/flatten.c @@ -243,6 +243,13 @@ void flattenCell(char *name, int file) ThisCell->dumped = 1; /* indicate cell has been flattened */ } +/* Structure used to keep track of nodes needing checking */ + +struct linkednode { + int node; + struct linkednode *next; +}; + /*--------------------------------------------------------------*/ /* flattenInstancesOf -- */ /* */ @@ -265,6 +272,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance) struct nlist *ThisCell; struct nlist *ChildCell; struct objlist *tmp, *ob2, *ob3; + struct linkednode *checknodes = NULL, *newlnode, *chknode; int notdone, rnodenum; char tmpstr[1024]; int nextnode, oldmax, numflat = 0; @@ -416,6 +424,16 @@ int flattenInstancesOf(char *name, int fnum, char *instance) } UpdateNodeNumbers(ChildStart, tmp->node, ob2->node); } + else if (tmp->node == -1) { + /* Opposite case: If child port is an unconnected node, then */ + /* removing the instance may make the parent node become */ + /* unconnected. For now, just record the node number. At the */ + /* end we'll check if these nodes are actually disconnected. */ + newlnode = (struct linkednode *)MALLOC(sizeof(struct linkednode)); + newlnode->node = ob2->node; + newlnode->next = checknodes; + checknodes = newlnode; + } /* in pathological cases, the lengths of the port lists may * change. This is an error, but that is no reason to allow @@ -598,6 +616,29 @@ int flattenInstancesOf(char *name, int fnum, char *instance) NextObj = ParentParams; } /* repeat until no more instances found */ } + + /* Check nodes that may have become disconnected after child flattening */ + while (checknodes != NULL) { + struct objlist *portnode = NULL; + + chknode = checknodes; + checknodes = checknodes->next; + + for (ob3 = ThisCell->cell; ob3; ob3 = ob3->next) { + if ((ob3->type != PORT) && (portnode == NULL)) + break; + else if ((ob3->type == PORT) && (ob3->node == chknode->node)) + portnode = ob3; + else if ((ob3->type >= FIRSTPIN) && (ob3->node == chknode->node)) + break; + } + if ((ob3 == NULL) && (portnode != NULL)) { + /* Port became disconnected when child was flattened */ + portnode->node = -1; + } + FREE(chknode); + } + CacheNodeNames(ThisCell); ThisCell->dumped = 1; /* indicate cell has been flattened */ return numflat;