From b1b986cbe4de543e8b572ee81acf7d47cb3a9345 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 25 Feb 2022 20:59:59 -0500 Subject: [PATCH] Added a procedure to esMakePorts() in ext2hier.c which tracks the EF_SUBS_PORT flags up the hierarchy. This is a rather lot of code needed to make substrate connections to circuits where the substrate connects to devices but not make such connections where the substrate doesn't. There may be simpler ways to accomplish the same thing, depending on whether the order of "merge" statements in a .ext file is reliable; this code does not depend on it. --- ext2spice/ext2hier.c | 84 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index e02a2b11..5bfae6f9 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1585,6 +1585,14 @@ devDistJunctHierVisit(hc, dev, scale) return 0; } +/* Structure used to store flags and an EFNode pointer */ + +typedef struct _flagDefRecord { + int fdr_flags; /* Flags to propagate (if any) */ + EFNode *fdr_node; /* Node of parent cell (if any) */ + struct _flagDefRecord *fdr_next; /* Keep in a linked list */ +} flagDefRecord; + /* * ---------------------------------------------------------------------------- * @@ -1608,8 +1616,10 @@ esMakePorts(hc, cdata) Connection *conn; Def *def = hc->hc_use->use_def, *portdef, *updef; Use *use; - HashEntry *he; + HashTable flagHashTable; + HashEntry *he, *he1, *he2; EFNodeName *nn; + flagDefRecord *flagrec, *flagrec2, *flagtop; char *name, *portname, *tptr, *aptr, *locname; int j; @@ -1617,6 +1627,20 @@ esMakePorts(hc, cdata) /* Done when the bottom of the hierarchy is reached */ if (HashGetNumEntries(&def->def_uses) == 0) return 0; + /* The entire purpose of this hash table is to avoid unnecessary */ + /* use of the substrate as a port. Technically, every layout has */ + /* a substrate. For LVS, however, only the connections to devices */ + /* are relevant. This is tracked with the EF_SUBS_PORT flag. But */ + /* the flag needs to be propagated up through the hierarchy, and */ + /* that hierarchy can best be determined here. Since the */ + /* connections made by "merge" statements may weave through */ + /* multiple cells, the child-to-parent propagation of the */ + /* EF_SUBS_PORT flag must be made by surveying all of the */ + /* connections. */ + + flagtop = NULL; + HashInit(&flagHashTable, 32, HT_STRINGKEYS); + for (conn = (Connection *)def->def_conns; conn; conn = conn->conn_next) { for (j = 0; j < 2; j++) @@ -1626,6 +1650,33 @@ esMakePorts(hc, cdata) if ((tptr = strchr(name, '/')) == NULL) continue; + /* Create entries for both node names in the flag hash table, */ + /* and make them both point to the same record. */ + + he1 = HashFind(&flagHashTable, name); + flagrec = (flagDefRecord *)HashGetValue(he1); + he2 = HashFind(&flagHashTable, locname); + flagrec2 = (flagDefRecord *)HashGetValue(he2); + + if ((flagrec == NULL) && (flagrec2 == NULL)) + { + flagrec = (flagDefRecord *)mallocMagic(sizeof(flagDefRecord)); + flagrec->fdr_node = NULL; + flagrec->fdr_flags = 0; + flagrec->fdr_next = flagtop; + flagtop = flagrec; + + HashSetValue(he1, flagrec); + HashSetValue(he2, flagrec); + } + else if (flagrec == NULL) + { + flagrec = flagrec2; + HashSetValue(he1, flagrec); + } + else if (flagrec2 == NULL) + HashSetValue(he2, flagrec); + portname = name; updef = def; @@ -1704,6 +1755,14 @@ esMakePorts(hc, cdata) // TxPrintf("Port connection in %s from net %s to net %s (%s)\n", // def->def_name, locname, name, portname); } + + /* Propagate the EF_SUBS_PORT flag */ + if (nn->efnn_node && (nn->efnn_node->efnode_flags & EF_SUBS_PORT)) + { + flagrec->fdr_flags = EF_SUBS_PORT; + if (flagrec->fdr_node != NULL) + flagrec->fdr_node->efnode_flags |= EF_SUBS_PORT; + } } if ((tptr = strchr(portname, '/')) == NULL) @@ -1712,6 +1771,21 @@ esMakePorts(hc, cdata) updef = portdef; } + + /* If locname is a port of the parent, set this in the flag */ + /* record, and if the flag is non-zero, apply it immediately. */ + + if (strchr(locname, '/') == NULL) + { + he = HashFind(&def->def_nodes, locname); + if (he != NULL) + { + nn = (EFNodeName *) HashGetValue(he); + flagrec->fdr_node = nn->efnn_node; + flagrec->fdr_node->efnode_flags |= flagrec->fdr_flags; + } + } + } } @@ -1805,6 +1879,14 @@ esMakePorts(hc, cdata) // name, portname); } } + + /* Free table data */ + while (flagtop != NULL) + { + freeMagic((char *)flagtop); + flagtop = flagtop->fdr_next; + } + HashKill(&flagHashTable); return 0; }