Added a fallback method for "extresist" whenever a device terminal
connection to a net that has been decomposed into a resistor array cannot be found. This indicates some fundamental error in the way extresist works. However, it should not be producing an invalid and unsimulatable netlist. Instead, it makes an arbitrary connection from the device terminal to the resistor array and adds an entry in the output netlist (.res.ext file). This results in a poor representation of the resistor network to that terminal, but an otherwise simulatable netlist. A warning is issued to note that an arbitrary connection has been made. This is most typically a "garbage in, garbage out" situation in which insufficient information exists in a layout to inform magic on which direction current is traveling through a net. However, it should be possible to rewrite the extresist code so that magic makes somewhat informed decisions about current paths and produces a halfway decent representation of the actual net, instead of just giving up on the detailed extraction.
This commit is contained in:
parent
4445663cb1
commit
72368a3d13
|
|
@ -212,39 +212,54 @@ ResPrintExtDev(outextfile, devices)
|
|||
*/
|
||||
|
||||
void
|
||||
ResPrintExtNode(outextfile, nodelist, nodename)
|
||||
ResPrintExtNode(outextfile, nodelist, node)
|
||||
FILE *outextfile;
|
||||
resNode *nodelist;
|
||||
char *nodename;
|
||||
ResSimNode *node;
|
||||
{
|
||||
char *nodename = node->name;
|
||||
int nodenum = 0;
|
||||
char newname[MAXNAME+32], tmpname[MAXNAME], *cp;
|
||||
HashEntry *entry;
|
||||
ResSimNode *node, *ResInitializeNode();
|
||||
ResSimNode *newnode, *ResInitializeNode();
|
||||
bool DoKillNode = TRUE;
|
||||
resNode *snode = nodelist;
|
||||
bool NeedFix = FALSE;
|
||||
resNode *snode;
|
||||
|
||||
/* If any of the subnode names match the original node name, then */
|
||||
/* we don't want to rip out that node with a "killnode" statement. */
|
||||
|
||||
for (; nodelist != NULL; nodelist = nodelist->rn_more)
|
||||
for (snode = nodelist; snode != NULL; snode = snode->rn_more)
|
||||
{
|
||||
if (nodelist->rn_name != NULL)
|
||||
if (!strcmp(nodelist->rn_name, nodename))
|
||||
if (snode->rn_name != NULL)
|
||||
if (!strcmp(snode->rn_name, nodename))
|
||||
{
|
||||
DoKillNode = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If any device terminal failed to extract for any reason, then */
|
||||
/* this node cannot be killed. If it is already marked for killing */
|
||||
/* then there are no connections from the node to any of its sub- */
|
||||
/* nodes, so create one an flag a warning. Note that this */
|
||||
/* condition indicates a fundamental underlying error in device */
|
||||
/* extraction, but this prevents magic from generating an invalid */
|
||||
/* netlist. */
|
||||
|
||||
if (node->status & DONTKILL)
|
||||
if (DoKillNode == TRUE)
|
||||
{
|
||||
DoKillNode = FALSE;
|
||||
NeedFix = TRUE;
|
||||
}
|
||||
|
||||
if ((ResOptionsFlags & ResOpt_DoExtFile) && DoKillNode)
|
||||
{
|
||||
fprintf(outextfile, "killnode \"%s\"\n", nodename);
|
||||
}
|
||||
fprintf(outextfile, "killnode \"%s\"\n", nodename);
|
||||
|
||||
/* Create "rnode" entries for each subnode */
|
||||
|
||||
for (; snode != NULL; snode = snode->rn_more)
|
||||
for (snode = nodelist; snode != NULL; snode = snode->rn_more)
|
||||
{
|
||||
if (snode->rn_name == NULL)
|
||||
{
|
||||
|
|
@ -255,9 +270,9 @@ ResPrintExtNode(outextfile, nodelist, nodename)
|
|||
|
||||
(void)sprintf(newname, "%s%s%d", tmpname, ".n", nodenum++);
|
||||
entry = HashFind(&ResNodeTable, newname);
|
||||
node = ResInitializeNode(entry);
|
||||
snode->rn_name = node->name;
|
||||
node->oldname = nodename;
|
||||
newnode = ResInitializeNode(entry);
|
||||
snode->rn_name = newnode->name;
|
||||
newnode->oldname = nodename;
|
||||
}
|
||||
|
||||
if (ResOptionsFlags & ResOpt_DoExtFile)
|
||||
|
|
@ -272,6 +287,18 @@ ResPrintExtNode(outextfile, nodelist, nodename)
|
|||
0);
|
||||
}
|
||||
}
|
||||
|
||||
if (NeedFix)
|
||||
{
|
||||
/* Patch up the output netlist for an orphaned node by
|
||||
* creating a zero-valued resistance between it and the
|
||||
* first subnode (arbitrary connection). Flag a warning.
|
||||
*/
|
||||
fprintf(outextfile, "resist \"%s\" \"%s\" 0.0\n",
|
||||
node->name, nodelist->rn_name);
|
||||
TxError("Warning: Orphaned node \"%s\" arbitrarily attached to \"%s\"\n",
|
||||
node->name, nodelist->rn_name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1363,9 +1363,12 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
|||
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Missing gate connection of device at (%d %d) on net %s\n",
|
||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||
nodename);
|
||||
simNode->status |= DONTKILL;
|
||||
}
|
||||
}
|
||||
if (simDev->subs == simNode)
|
||||
{
|
||||
|
|
@ -1381,9 +1384,12 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
|||
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Missing substrate connection of device at (%d %d) on net %s\n",
|
||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||
nodename);
|
||||
simNode->status |= DONTKILL;
|
||||
}
|
||||
}
|
||||
|
||||
if (simDev->source == simNode)
|
||||
|
|
@ -1425,9 +1431,12 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
|||
/* one to each */
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||
nodename);
|
||||
simNode->status |= DONTKILL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1468,9 +1477,12 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
|||
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||
nodename);
|
||||
simNode->status |= DONTKILL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (simDev->drain == simNode)
|
||||
|
|
@ -1525,9 +1537,12 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
|||
drain->rn_name = simDev->drain->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||
nodename);
|
||||
simNode->status |= DONTKILL;
|
||||
}
|
||||
}
|
||||
else
|
||||
resNodeNum--;
|
||||
|
|
@ -1845,7 +1860,7 @@ ResWriteExtFile(celldef, node, rctol, nidx, eidx)
|
|||
}
|
||||
if (ResOptionsFlags & ResOpt_DoExtFile)
|
||||
{
|
||||
ResPrintExtNode(ResExtFile, ResNodeList, node->name);
|
||||
ResPrintExtNode(ResExtFile, ResNodeList, node);
|
||||
ResPrintExtRes(ResExtFile, ResResList, newname);
|
||||
}
|
||||
if (ResOptionsFlags & ResOpt_FastHenry)
|
||||
|
|
|
|||
|
|
@ -494,6 +494,7 @@ typedef struct capval
|
|||
#define DRIVELOC 0x0000100
|
||||
#define PORTNODE 0x0000200
|
||||
#define REDUNDANT 0x0000400
|
||||
#define DONTKILL 0x0000800
|
||||
|
||||
/* Capacitance table constants */
|
||||
#define RES_CAP_GND 0
|
||||
|
|
|
|||
Loading…
Reference in New Issue