diff --git a/resis/ResRex.c b/resis/ResRex.c index cd738a24..b0804f45 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -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) diff --git a/resis/ResSimple.c b/resis/ResSimple.c index c225ad10..13fbfd4c 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -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) {