Found an additional scaling-up problem in ext2spice (previously handled
a scaling issue in extract) which was caused by the addition of hierarchical netlist generation. Finding hierarchical connections requires finding instances by name, so it is vastly better to create a hash table of instances instead of a linked list.
This commit is contained in:
parent
c669d83dc6
commit
9f5936c7cb
|
|
@ -1552,7 +1552,8 @@ esMakePorts(hc, cdata)
|
|||
char *name, *portname, *tptr, *aptr, *locname;
|
||||
int j;
|
||||
|
||||
if (def->def_uses == NULL) return 0; /* Bottom of hierarchy */
|
||||
/* Done when the bottom of the hierarchy is reached */
|
||||
if (HashGetNumEntries(&def->def_uses) == 0) return 0;
|
||||
|
||||
for (conn = (Connection *)def->def_conns; conn; conn = conn->conn_next)
|
||||
{
|
||||
|
|
@ -1579,13 +1580,11 @@ esMakePorts(hc, cdata)
|
|||
|
||||
// Find the cell for the instance
|
||||
portdef = NULL;
|
||||
for (use = updef->def_uses; use; use = use->use_next)
|
||||
he = HashFind(&updef->def_uses, portname);
|
||||
if (he != NULL)
|
||||
{
|
||||
if (!strcmp(use->use_id, portname))
|
||||
{
|
||||
portdef = use->use_def;
|
||||
break;
|
||||
}
|
||||
use = (Use *)HashGetValue(he);
|
||||
portdef = use->use_def;
|
||||
}
|
||||
if ((aptr == NULL) || (aptr > tptr))
|
||||
*tptr = '/';
|
||||
|
|
@ -1660,13 +1659,11 @@ esMakePorts(hc, cdata)
|
|||
|
||||
// Find the cell for the instance
|
||||
portdef = NULL;
|
||||
for (use = updef->def_uses; use; use = use->use_next)
|
||||
he = HashFind(&updef->def_uses, portname);
|
||||
if (he != NULL)
|
||||
{
|
||||
if (!strcmp(use->use_id, portname))
|
||||
{
|
||||
portdef = use->use_def;
|
||||
break;
|
||||
}
|
||||
use = (Use *)HashGetValue(he);
|
||||
portdef = use->use_def;
|
||||
}
|
||||
if ((aptr == NULL) || (aptr > tptr))
|
||||
*tptr = '/';
|
||||
|
|
@ -1747,7 +1744,7 @@ esHierVisit(hc, cdata)
|
|||
|
||||
if (def != topdef)
|
||||
{
|
||||
if (def->def_devs == NULL && def->def_uses == NULL)
|
||||
if ((def->def_devs == NULL) && (HashGetNumEntries(&def->def_uses) == 0))
|
||||
{
|
||||
if (locDoSubckt == AUTO)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1098,6 +1098,7 @@ efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf)
|
|||
Use *newuse;
|
||||
Def *newdef;
|
||||
char *cp;
|
||||
HashEntry *he;
|
||||
|
||||
newdef = efDefLook(subDefName);
|
||||
if (newdef == NULL)
|
||||
|
|
@ -1111,8 +1112,6 @@ efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf)
|
|||
newuse->use_trans.t_d = td;
|
||||
newuse->use_trans.t_e = te;
|
||||
newuse->use_trans.t_f = tf;
|
||||
newuse->use_next = def->def_uses;
|
||||
def->def_uses = newuse;
|
||||
|
||||
/* Set the use identifier and array information */
|
||||
if ((cp = strchr(subUseId, '[')) == NULL)
|
||||
|
|
@ -1121,15 +1120,21 @@ efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf)
|
|||
newuse->use_xlo = newuse->use_xhi = 0;
|
||||
newuse->use_ylo = newuse->use_yhi = 0;
|
||||
newuse->use_xsep = newuse->use_ysep = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*cp = '\0';
|
||||
newuse->use_id = StrDup((char **) NULL, subUseId);
|
||||
*cp = '[';
|
||||
(void) sscanf(cp, "[%d:%d:%d][%d:%d:%d]",
|
||||
else
|
||||
{
|
||||
*cp = '\0';
|
||||
newuse->use_id = StrDup((char **) NULL, subUseId);
|
||||
*cp = '[';
|
||||
(void) sscanf(cp, "[%d:%d:%d][%d:%d:%d]",
|
||||
&newuse->use_xlo, &newuse->use_xhi, &newuse->use_xsep,
|
||||
&newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep);
|
||||
}
|
||||
|
||||
he = HashFind(&def->def_uses, newuse->use_id);
|
||||
if (HashGetValue(he))
|
||||
TxError("Warning: use %s appears more than once in def!\n", newuse->use_id);
|
||||
HashSetValue(he, (ClientData)newuse);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1646,6 +1651,38 @@ efNodeMerge(node1, node2)
|
|||
freeMagic((char *) node2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* efFreeUseTable --
|
||||
*
|
||||
* Free the cell IDs allocated for each entry in the use hash table, and
|
||||
* the memory allocated by the cell use, leaving the hash entry null.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
efFreeUseTable(table)
|
||||
HashTable *table;
|
||||
{
|
||||
HashSearch hs;
|
||||
HashEntry *he;
|
||||
Use *use;
|
||||
HierName *hn;
|
||||
EFNodeName *nn;
|
||||
|
||||
HashStartSearch(&hs);
|
||||
while (he = HashNext(table, &hs))
|
||||
if (use = (Use *) HashGetValue(he))
|
||||
{
|
||||
if (use->use_id != NULL) freeMagic((char *)use->use_id);
|
||||
freeMagic(use);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
|||
|
|
@ -113,13 +113,10 @@ EFDone()
|
|||
freeMagic(def->def_name);
|
||||
efFreeNodeTable(&def->def_nodes);
|
||||
efFreeNodeList(&def->def_firstn);
|
||||
efFreeUseTable(&def->def_uses);
|
||||
HashKill(&def->def_nodes);
|
||||
HashKill(&def->def_dists);
|
||||
for (use = def->def_uses; use; use = use->use_next)
|
||||
{
|
||||
freeMagic(use->use_id);
|
||||
freeMagic((char *) use);
|
||||
}
|
||||
HashKill(&def->def_uses);
|
||||
for (conn = def->def_conns; conn; conn = conn->conn_next)
|
||||
efFreeConn(conn);
|
||||
for (conn = def->def_caps; conn; conn = conn->conn_next)
|
||||
|
|
@ -248,13 +245,15 @@ efDefNew(name)
|
|||
newdef->def_caps = (Connection *) NULL;
|
||||
newdef->def_resistors = (Connection *) NULL;
|
||||
newdef->def_devs = (Dev *) NULL;
|
||||
newdef->def_uses = (Use *) NULL;
|
||||
newdef->def_kills = (Kill *) NULL;
|
||||
|
||||
/* Initialize circular list of nodes */
|
||||
newdef->def_firstn.efnode_next = (EFNodeHdr *) &newdef->def_firstn;
|
||||
newdef->def_firstn.efnode_prev = (EFNodeHdr *) &newdef->def_firstn;
|
||||
|
||||
/* Initialize hash table of uses */
|
||||
HashInit(&newdef->def_uses, INITNODESIZE, HT_STRINGKEYS);
|
||||
|
||||
/* Initialize hash table of node names */
|
||||
HashInit(&newdef->def_nodes, INITNODESIZE, HT_STRINGKEYS);
|
||||
|
||||
|
|
|
|||
|
|
@ -193,16 +193,13 @@ EFFlatBuildOneLevel(def, flags)
|
|||
efFlatContext.hc_x = efFlatContext.hc_y = 0;
|
||||
efFlatRootUse.use_def = efFlatRootDef;
|
||||
|
||||
usecount = 0;
|
||||
|
||||
/* Record all nodes of the next level in the hierarchy */
|
||||
efHierSrUses(&efFlatContext, efAddNodes, (ClientData)TRUE);
|
||||
|
||||
/* Expand all subcells that contain connectivity information but */
|
||||
/* no active devices (including those in subcells). */
|
||||
|
||||
for (use = efFlatRootUse.use_def->def_uses; use; use = use->use_next)
|
||||
usecount++;
|
||||
usecount = HashGetNumEntries(&efFlatRootUse.use_def->def_uses);
|
||||
|
||||
/* Recursively flatten uses that have no active devices */
|
||||
if (usecount > 0)
|
||||
|
|
@ -366,11 +363,10 @@ efFlatNodesDeviceless(hc, cdata)
|
|||
ClientData cdata;
|
||||
{
|
||||
int *usecount = (int *)cdata;
|
||||
int newcount = 0;
|
||||
int newcount;
|
||||
Use *use;
|
||||
|
||||
for (use = hc->hc_use->use_def->def_uses; use; use = use->use_next)
|
||||
newcount++;
|
||||
newcount = HashGetNumEntries(&hc->hc_use->use_def->def_uses);
|
||||
|
||||
/* Recursively flatten uses that have no active devices */
|
||||
if (newcount > 0)
|
||||
|
|
@ -910,11 +906,10 @@ efFlatCapsDeviceless(hc)
|
|||
HierContext *hc;
|
||||
{
|
||||
Connection *conn;
|
||||
int newcount = 0;
|
||||
int newcount;
|
||||
Use *use;
|
||||
|
||||
for (use = hc->hc_use->use_def->def_uses; use; use = use->use_next)
|
||||
newcount++;
|
||||
newcount = HashGetNumEntries(&hc->hc_use->use_def->def_uses);
|
||||
|
||||
/* Recursively flatten uses that have no active devices */
|
||||
if (newcount > 0)
|
||||
|
|
|
|||
|
|
@ -77,9 +77,13 @@ efHierSrUses(hc, func, cdata)
|
|||
HierContext newhc;
|
||||
Transform t;
|
||||
Use *u;
|
||||
HashSearch hs;
|
||||
HashEntry *he;
|
||||
|
||||
for (u = hc->hc_use->use_def->def_uses; u; u = u->use_next)
|
||||
HashStartSearch(&hs);
|
||||
while (he = HashNext(&hc->hc_use->use_def->def_uses, &hs))
|
||||
{
|
||||
u = (Use *)HashGetValue(he);
|
||||
newhc.hc_use = u;
|
||||
if (!IsArray(u))
|
||||
{
|
||||
|
|
@ -237,6 +241,8 @@ EFHierSrDefs(hc, func, cdata)
|
|||
HierContext newhc;
|
||||
Use *u;
|
||||
int retval;
|
||||
HashSearch hs;
|
||||
HashEntry *he;
|
||||
|
||||
if (func == NULL)
|
||||
{
|
||||
|
|
@ -251,8 +257,10 @@ EFHierSrDefs(hc, func, cdata)
|
|||
hc->hc_use->use_def->def_flags |= DEF_PROCESSED;
|
||||
}
|
||||
|
||||
for (u = hc->hc_use->use_def->def_uses; u; u = u->use_next)
|
||||
HashStartSearch(&hs);
|
||||
while (he = HashNext(&hc->hc_use->use_def->def_uses, &hs))
|
||||
{
|
||||
u = (Use *)HashGetValue(he);
|
||||
newhc.hc_use = u;
|
||||
newhc.hc_hierName = NULL;
|
||||
GeoTransTrans(&u->use_trans, &hc->hc_trans, &newhc.hc_trans);
|
||||
|
|
|
|||
|
|
@ -155,11 +155,11 @@ typedef struct def
|
|||
int def_flags; /* Flags -- see below */
|
||||
HashTable def_nodes; /* Map names into EFNodeNames */
|
||||
HashTable def_dists; /* Map pairs of names into Distances */
|
||||
HashTable def_uses; /* Hash children of this def by name */
|
||||
EFNode def_firstn; /* Head of circular list of nodes */
|
||||
|
||||
/* The following are all NULL-terminated lists */
|
||||
|
||||
struct use *def_uses; /* Children of this def */
|
||||
Connection *def_conns; /* Hierarchical connections/adjustments */
|
||||
Connection *def_caps; /* Two-terminal capacitors */
|
||||
Connection *def_resistors; /* Two-terminal resistors */
|
||||
|
|
@ -199,8 +199,6 @@ typedef struct use
|
|||
{
|
||||
char *use_id; /* Use identifier (appears in hier paths) */
|
||||
Def *use_def; /* Sub def being used */
|
||||
// EFNodeName *use_ports; /* Port connections, for hierarchical output */
|
||||
struct use *use_next; /* Next use in list (NULL-terminated) */
|
||||
Transform use_trans; /* Transform up to parent coords (for fets) */
|
||||
ArrayInfo use_array; /* Arraying information */
|
||||
} Use;
|
||||
|
|
|
|||
|
|
@ -184,6 +184,8 @@ efReadDef(def, dosubckt, resist, noscale, toplevel)
|
|||
bool rc = TRUE;
|
||||
bool DoResist = resist;
|
||||
bool DoSubCircuit = dosubckt;
|
||||
HashSearch hs;
|
||||
HashEntry *he;
|
||||
|
||||
/* Mark def as available */
|
||||
def->def_flags |= DEF_AVAILABLE;
|
||||
|
|
@ -611,11 +613,16 @@ resistChanged:
|
|||
DoSubCircuit = FALSE;
|
||||
|
||||
/* Read in each def that has not yet been read in */
|
||||
for (use = def->def_uses; use; use = use->use_next)
|
||||
|
||||
HashStartSearch(&hs);
|
||||
while (he = HashNext(&def->def_uses, &hs))
|
||||
{
|
||||
use = (Use *)HashGetValue(he);
|
||||
if ((use->use_def->def_flags & DEF_AVAILABLE) == 0)
|
||||
if (efReadDef(use->use_def, DoSubCircuit, resist, noscale, FALSE)
|
||||
!= TRUE)
|
||||
rc = FALSE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue