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 */