From 16da74a2f9d64c4160d0c3600eca0eae95d52186 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 18 Nov 2022 21:44:06 -0500 Subject: [PATCH] Implemented a method in EFBuildNode() to capture nodes which are redundant (same name, different net). Previously, the method was to keep the first such node and ignore all others except to add their resistance and capacitance to the original node. This prevented routines like "def write" from enumerating all nets unless they had unique names. The new method keeps the additional records including the node location where they can be found by EFNodeVisit(), but flags them with EF_UNIQUE_NODE so that routines like ext2spice or ext2sim can choose to ignore them. This implies that this method could be used to reimplement "extract unique" within "ext2spice" or "ext2sim" without altering label text. This has not yet been implemented. --- ext2sim/ext2sim.c | 1 + ext2spice/ext2hier.c | 2 ++ ext2spice/ext2spice.c | 2 ++ extcheck/extcheck.c | 1 + extflat/EFbuild.c | 25 +++++++++++++++++++++++-- extflat/extflat.h | 9 +++++++++ lef/defWrite.c | 6 ++++++ 7 files changed, 44 insertions(+), 2 deletions(-) diff --git a/ext2sim/ext2sim.c b/ext2sim/ext2sim.c index 8f00ea58..fcf703a5 100644 --- a/ext2sim/ext2sim.c +++ b/ext2sim/ext2sim.c @@ -1596,6 +1596,7 @@ int simnodeVisit(node, res, cap) char *fmt; EFAttr *ap; + if (node->efnode_flags & EF_UNIQUE_NODE) return 0; if (esDevNodesOnly && node->efnode_client == (ClientData) NULL) return 0; diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 8112aa70..22ab9a35 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1252,6 +1252,7 @@ spcsubHierVisit(hc, node, res, cap, resstrptr) HierName *hierName; char *nsn; + if (node->efnode_flags & EF_UNIQUE_NODE) return 0; if (node->efnode_flags & EF_GLOB_SUBS_NODE) { hierName = (HierName *) node->efnode_name->efnn_hier; @@ -1292,6 +1293,7 @@ spcnodeHierVisit(hc, node, res, cap) char *fmt, *nsn; EFAttr *ap; + if (node->efnode_flags & EF_UNIQUE_NODE) return 0; if (node->efnode_client) { if (esDistrJunct) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 6ca1b9c6..7a6a97f6 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -3344,6 +3344,7 @@ spcsubVisit(node, res, cap, resstr) HierName *hierName; char *nsn; + if (node->efnode_flags & EF_UNIQUE_NODE) return 0; if (node->efnode_flags & EF_GLOB_SUBS_NODE) { hierName = (HierName *) node->efnode_name->efnn_hier; @@ -3383,6 +3384,7 @@ spcnodeVisit(node, res, cap) char *fmt, *nsn; EFAttr *ap; + if (node->efnode_flags & EF_UNIQUE_NODE) return 0; if (node->efnode_client) { isConnected = (esDistrJunct) ? diff --git a/extcheck/extcheck.c b/extcheck/extcheck.c index ed0f66ee..e592e39b 100644 --- a/extcheck/extcheck.c +++ b/extcheck/extcheck.c @@ -135,6 +135,7 @@ nodeVisit(node, res, cap) cap = (cap + 500) / 1000; res = (res + 500) / 1000; + if (node->efnode_flags & EF_UNIQUE_NODE) return 0; ecNumNodes++; if (EFHNIsGlob(node->efnode_name->efnn_hier)) ecNumGlobalNodes++; diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index 9b509fa2..3a0a53c1 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -155,6 +155,8 @@ efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName, HashEntry *he; unsigned size; int n; + char *uqname = nodeName; + int uqidx; he = HashFind(&def->def_nodes, nodeName); if (newname = (EFNodeName *) HashGetValue(he)) @@ -185,7 +187,20 @@ efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName, if (isSubsnode == TRUE) newnode->efnode_flags |= EF_GLOB_SUBS_NODE; - return; + /* If tracking unique nodes (for "def write", for example), + * collect unique node positions in the client data so that + * all of them can be visited. + */ + uqname = mallocMagic(strlen(nodeName) + 8); + uqidx = 0; + while (1) + { + sprintf(uqname, "%s_uq%d", nodeName, uqidx); + he = HashFind(&def->def_nodes, uqname); + if ((newname = (EFNodeName *)HashGetValue(he)) == NULL) + break; + uqidx++; + } } } @@ -193,7 +208,7 @@ efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName, { /* Allocate a new node with 'nodeName' as its single name */ newname = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName))); - newname->efnn_hier = EFStrToHN((HierName *) NULL, nodeName); + newname->efnn_hier = EFStrToHN((HierName *) NULL, uqname); newname->efnn_port = -1; /* No port assignment */ newname->efnn_refc = 0; /* Only reference is self */ newname->efnn_next = NULL; @@ -239,6 +254,12 @@ efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName, /* If isSubsnode was TRUE, then turn off backwards compatibility mode */ if (isSubsnode == TRUE) EFCompat = FALSE; + + if (uqname != nodeName) + { + newnode->efnode_flags |= EF_UNIQUE_NODE; + freeMagic(uqname); + } } /* diff --git a/extflat/extflat.h b/extflat/extflat.h index 65f7aa3f..585ae40d 100644 --- a/extflat/extflat.h +++ b/extflat/extflat.h @@ -212,6 +212,15 @@ typedef struct efnhdr * line of the .ext file as the global default substrate node. */ #define EF_GLOB_SUBS_NODE 0x80 + /* + * EF_UNIQUE_NODE marks a node that has the same name as another + * node, indicating that the nodes are electrically connected only + * by name. The processing routine can determine whether to + * process these individually. The capacitance and resistance + * values are merged with the first node of the same name. The + * location is maintained so that the net fragment can be found. + */ +#define EF_UNIQUE_NODE 0x100 extern int efNumResistClasses; /* Number of resistance classes in efResists */ diff --git a/lef/defWrite.c b/lef/defWrite.c index 7f091cfd..4a2b9334 100644 --- a/lef/defWrite.c +++ b/lef/defWrite.c @@ -295,6 +295,9 @@ defnodeCount(node, res, cap, total) char ndn[256]; char *cp, clast; + /* Ignore ports---use the unique node entries instead */ + if (node->efnode_flags & EF_TOP_PORT) return 0; + /* Ignore the substrate node if it is not connected to any routing */ if (node->efnode_type == TT_SPACE) return 0; @@ -669,6 +672,9 @@ defnodeVisit(node, res, cap, defdata) EFNodeName *thisnn; int defNetGeometryFunc(); /* Forward declaration */ + /* Ignore ports---use the unique node entries instead */ + if (node->efnode_flags & EF_TOP_PORT) return 0; + /* For regular nets, only count those nodes having port */ /* connections. For special nets, only count those nodes */ /* that were marked with the EF_SPECIAL flag while counting */