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.
This commit is contained in:
Tim Edwards 2022-11-18 21:44:06 -05:00
parent fe89170f5a
commit 16da74a2f9
7 changed files with 44 additions and 2 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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) ?

View File

@ -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++;

View File

@ -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);
}
}
/*

View File

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

View File

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