Corrected an error in the original resistor network simplifying

routine that marks resistors in loops to prevent infinite
recursion, but later incorrectly eliminates those resistors.
Also:  Changed the "tolerance" command to affect only the R-C
time constant tolerance.  Added a "threshold" command option
that limits output of small resistors.  This can help reduce
large networks that are otherwise not reducible by the three
methods of reduction (serial, parallel, and delta-wye), but
does affect output values (slightly).  This will probably need
to be revisited at some point.
This commit is contained in:
Tim Edwards 2023-09-28 17:15:27 -04:00
parent 656b5dbabe
commit 088bb828ac
2 changed files with 89 additions and 59 deletions

View File

@ -96,9 +96,9 @@ struct saveList {
/* Structure stores information required to be sent to ExtResisForDef() */
typedef struct
{
float tolerance;
float tdiTolerance;
float frequency;
float rthresh;
struct saveList *savePlanes;
CellDef *mainDef;
} ResisData;
@ -118,14 +118,14 @@ ExtResisForDef(celldef, resisdata)
CellDef *celldef;
ResisData *resisdata;
{
RDev *oldRDev;
HashSearch hs;
HashEntry *entry;
devPtr *tptr, *oldtptr;
RDev *oldRDev;
HashSearch hs;
HashEntry *entry;
devPtr *tptr, *oldtptr;
ResSimNode *node;
int result, idx;
char *devname;
Plane *savePlane;
int result, idx;
char *devname;
Plane *savePlane;
ResRDevList = NULL;
ResOriginalNodes = NULL;
@ -135,7 +135,7 @@ ExtResisForDef(celldef, resisdata)
HashFind(&ResProcessedTable, celldef->cd_name);
/* Prepare the substrate for resistance extraction */
savePlane = extResPrepSubstrate(celldef);
savePlane = extResPrepSubstrate(celldef);
if (savePlane != NULL)
{
struct saveList *newsl;
@ -150,18 +150,18 @@ ExtResisForDef(celldef, resisdata)
idx = 0;
while (ExtGetDevInfo(idx++, &devname, NULL, NULL, NULL, NULL, NULL))
{
if (idx == TT_MAXTYPES)
{
TxError("Error: Ran out of space for device types!\n");
break;
}
efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
if (idx == TT_MAXTYPES)
{
TxError("Error: Ran out of space for device types!\n");
break;
}
efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
}
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
/* read in .sim file */
result = (ResReadSim(celldef->cd_name,
ResSimDevice, ResSimCapacitor, ResSimResistor,
ResSimDevice, ResSimCapacitor, ResSimResistor,
ResSimAttribute, ResSimMerge, ResSimSubckt) == 0);
/* Clean up the EFDevTypes table */
@ -212,7 +212,7 @@ ExtResisForDef(celldef, resisdata)
HashKill(&ResNodeTable);
while (ResRDevList != NULL)
{
oldRDev = ResRDevList;
oldRDev = ResRDevList;
ResRDevList = ResRDevList->nextDev;
if (oldRDev->layout != NULL)
{
@ -223,7 +223,6 @@ ExtResisForDef(celldef, resisdata)
}
}
/*
*-------------------------------------------------------------------------
*
@ -241,12 +240,13 @@ ExtResisForDef(celldef, resisdata)
void
CmdExtResis(win, cmd)
MagWindow *win;
TxCommand *cmd;
MagWindow *win;
TxCommand *cmd;
{
int i, j, k, option, value, saveFlags;
static int init = 1;
static float tolerance, tdiTolerance, fhFrequency;
int i, j, k, option, value, saveFlags;
static int init = 1;
static float rthresh, tdiTolerance, fhFrequency;
CellDef *mainDef;
CellUse *selectedUse;
ResisData resisdata;
@ -264,8 +264,9 @@ CmdExtResis(win, cmd)
static char *cmdExtresisCmd[] =
{
"tolerance [value] set ratio between resistor and device tol.",
"all extract all the nets",
"threshold [value] set minimum resistor extraction threshold",
"tolerance [value] set ratio between resistor and device tol.",
"simplify [on/off] turn on/off simplification of resistor nets",
"extout [on/off] turn on/off writing of .res.ext file",
"lumped [on/off] turn on/off writing of updated lumped resistances",
@ -286,8 +287,9 @@ CmdExtResis(win, cmd)
};
typedef enum {
RES_BAD=-2, RES_AMBIG, RES_TOL,
RES_ALL, RES_SIMP, RES_EXTOUT, RES_LUMPED, RES_SILENT,
RES_BAD=-2, RES_AMBIG, RES_ALL,
RES_THRESH, RES_TOL,
RES_SIMP, RES_EXTOUT, RES_LUMPED, RES_SILENT,
RES_SKIP, RES_IGNORE, RES_INCLUDE, RES_BOX, RES_CELL,
RES_BLACKBOX, RES_FASTHENRY, RES_GEOMETRY, RES_HELP,
#ifdef LAPLACE
@ -303,7 +305,7 @@ typedef enum {
TTMaskZero(&(ResCopyMask[i]));
TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]);
}
tolerance = 1;
rthresh = 0;
tdiTolerance = 1;
fhFrequency = 10e6; /* 10 MHz default */
HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS);
@ -350,13 +352,12 @@ typedef enum {
ResOptionsFlags |= ResOpt_ExplicitRtol;
if (cmd->tx_argc > 2)
{
tolerance = MagAtof(cmd->tx_argv[2]);
if (tolerance <= 0)
tdiTolerance = MagAtof(cmd->tx_argv[2]);
if (tdiTolerance <= 0)
{
TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]);
return;
}
tdiTolerance = tolerance;
}
else
{
@ -368,6 +369,26 @@ typedef enum {
}
return;
case RES_THRESH:
if (cmd->tx_argc > 2)
{
rthresh = MagAtof(cmd->tx_argv[2]);
if (rthresh < 0)
{
TxError("Usage: %s threshold [value]\n", cmd->tx_argv[0]);
return;
}
}
else
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)rthresh));
#else
TxPrintf("Resistance threshold is %g.\n", rthresh);
#endif
}
return;
case RES_ALL:
ResOptionsFlags |= ResOpt_ExtractAll;
break;
@ -648,7 +669,7 @@ typedef enum {
ResOptionsFlags &= ~ResOpt_Power;
#endif
resisdata.tolerance = tolerance;
resisdata.rthresh = rthresh;
resisdata.tdiTolerance = tdiTolerance;
resisdata.frequency = fhFrequency;
resisdata.mainDef = mainDef;
@ -964,13 +985,13 @@ ResCheckSimNodes(celldef, resisdata)
{
ResSimNode *node;
devPtr *ptr;
float ftolerance, rctolerance, minRes, cumRes;
float ftolerance, minRes, cumRes;
int failed1=0;
int failed3=0;
int total =0;
char *outfile = celldef->cd_name;
float tol = resisdata->tolerance;
float rctol = resisdata->tdiTolerance;
float rthresh = resisdata->rthresh;
int nidx = 1, eidx = 1; /* node & segment counters for geom. */
if (ResOptionsFlags & ResOpt_DoExtFile)
@ -1166,16 +1187,10 @@ ResCheckSimNodes(celldef, resisdata)
continue;
}
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
if ((rctol == 0.0) || (tol == 0.0))
{
ftolerance = 0.0;
rctolerance = 0.0;
}
if (minRes > resisdata->rthresh)
ftolerance = minRes;
else
{
ftolerance = minRes / tol;
rctolerance = minRes / rctol;
}
ftolerance = resisdata->rthresh;
/*
* Is the device resistance greater than the lumped node
@ -1201,11 +1216,10 @@ ResCheckSimNodes(celldef, resisdata)
ResWriteLumpFile(node);
}
if (gparams.rg_maxres >= ftolerance ||
gparams.rg_maxres >= rctolerance ||
(ResOptionsFlags & ResOpt_ExtractAll))
{
resNodeNum = 0;
failed3 += ResWriteExtFile(celldef, node, tol, rctol,
failed3 += ResWriteExtFile(celldef, node, rctol,
&nidx, &eidx);
}
}
@ -1780,10 +1794,10 @@ ResAlignNodes(nodelist, reslist)
*/
int
ResWriteExtFile(celldef, node, tol, rctol, nidx, eidx)
ResWriteExtFile(celldef, node, rctol, nidx, eidx)
CellDef *celldef;
ResSimNode *node;
float tol, rctol;
float rctol;
int *nidx, *eidx;
{
float RCdev;
@ -1793,7 +1807,7 @@ ResWriteExtFile(celldef, node, tol, rctol, nidx, eidx)
RCdev = gparams.rg_bigdevres * gparams.rg_nodecap;
if (tol == 0.0 || (node->status & FORCE) ||
if ((node->status & FORCE) ||
(ResOptionsFlags & ResOpt_ExtractAll) ||
(ResOptionsFlags & ResOpt_Simplify) == 0 ||
(rctol + 1) * RCdev < rctol * gparams.rg_Tdi)

View File

@ -41,7 +41,6 @@ void ResSetPathRes();
void resPathNode();
void resPathRes();
Heap ResistorHeap;
int resRemoveLoops = FALSE;
/* Forward declarations */
@ -810,10 +809,12 @@ ResPruneTree(node, minTdi, nodelist1, nodelist2, resistorlist)
{
currentRes = current->re_thisEl;
current = current->re_nextEl;
/* if branch points outward, call routine on subtrees */
if (currentRes->rr_connection1 == node)
ResPruneTree(currentRes->rr_connection2, minTdi, nodelist1,
nodelist2, resistorlist);
/* Ignore previously found loops */
if (!(currentRes->rr_status & RES_TDI_IGNORE))
/* If branch points outward, call routine on subtrees */
if (currentRes->rr_connection1 == node)
ResPruneTree(currentRes->rr_connection2, minTdi, nodelist1,
nodelist2, resistorlist);
}
/* We eliminate this branch if:
@ -863,7 +864,6 @@ ResDoSimplify(tolerance, rctol, goodies)
float totalcap;
resResistor *res;
resRemoveLoops = FALSE;
ResSetPathRes();
for (node = ResNodeList; node != NULL; node = node->rn_more)
bigres = MAX(bigres, node->rn_noderes);
@ -893,12 +893,16 @@ ResDoSimplify(tolerance, rctol, goodies)
res = res->rr_nextResistor;
oldres->rr_status &= ~RES_HEAP;
/*------ NOTE: resistors marked with RES_TDI_IGNORE are
* part of loops but should NOT be removed.
if (oldres->rr_status & RES_TDI_IGNORE)
{
ResDeleteResPointer(oldres->rr_node[0], oldres);
ResDeleteResPointer(oldres->rr_node[1], oldres);
ResEliminateResistor(oldres, &ResResList);
}
------*/
}
if (ResOptionsFlags & ResOpt_Tdi)
@ -1045,7 +1049,12 @@ ResSetPathRes()
/*
*-------------------------------------------------------------------------
* resPathNode ---
*
* Given node "node", add every resistor connected to the node, and
* for which the node on the other side has not been processed, to
* the heap. Node is marked with FINISHED to prevent going 'round
* and 'round loops.
*-------------------------------------------------------------------------
*/
@ -1073,6 +1082,18 @@ resPathNode(node)
/*
*-------------------------------------------------------------------------
*
* resPathRes ---
*
* Given resistor "res" pulled from the heap (in heap order, which
* is the highest valued resistor currently in the heap):
*
* If both ends of the resistor have been processed, then we have
* a loop, and should return.
*
* Otherwise, call resPathNode() on the node of whichever end of
* the resistor has not yet been processed, thus continuing through
* the path from the origin.
*
*-------------------------------------------------------------------------
*/
@ -1093,12 +1114,7 @@ resPathRes(res)
if (flag0 && flag1)
{
res->rr_status |= RES_TDI_IGNORE;
if (resRemoveLoops)
{
ResDeleteResPointer(node0, res);
ResDeleteResPointer(node1, res);
ResEliminateResistor(res, &ResResList);
}
/* Loop found---return without calling resPathNode() */
}
else if (flag0)
{