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.
This commit is contained in:
Tim Edwards 2022-02-25 20:59:59 -05:00
parent bae5d9cd06
commit b1b986cbe4
1 changed files with 83 additions and 1 deletions

View File

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