Final work on the first stage of the extresist overhaul. The
"extresist" command continues to work as before. However, the method now reads from .ext files instead of .sim files, so generating ".sim" and ".nodes" files is no longer necessary. In addition, the core code of "extresist" was put directly into ExtCell.c so that full R-C extraction can be run using "extract do resistance" followed by "extract all", without needing to run "extresist" at all other than to set parameters (e.g., "extresist tolerance 10").
This commit is contained in:
parent
76f97c90e5
commit
57c33c48c7
|
|
@ -35,9 +35,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
|||
#include "dbwind/dbwind.h" /* for DBWclientID */
|
||||
#include "commands/commands.h" /* for module auto-load */
|
||||
#include "textio/txcommands.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "utils/runstats.h"
|
||||
#include "utils/malloc.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -41,14 +41,11 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
|||
#include "commands/commands.h" /* for module auto-load */
|
||||
#include "textio/txcommands.h"
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "extflat/EFint.h"
|
||||
#include "utils/runstats.h"
|
||||
#include "ext2spice/ext2spice.h"
|
||||
|
||||
/* C99 compat */
|
||||
#include "extflat/extflat.h"
|
||||
|
||||
/* These global values are defined in ext2spice.c */
|
||||
extern HashTable subcktNameTable;
|
||||
extern DQueue subcktNameQueue;
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
|||
#include "dbwind/dbwind.h" /* for DBWclientID */
|
||||
#include "commands/commands.h" /* for module auto-load */
|
||||
#include "textio/txcommands.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "utils/runstats.h"
|
||||
|
||||
#include "ext2spice/ext2spice.h"
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
|||
#include "tiles/tile.h"
|
||||
#include "database/database.h" /* for TileType definition */
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/extparse.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h" /* for device class list */
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extractInt.h" /* for extGetDevType() */
|
||||
|
||||
/* C99 compat */
|
||||
|
|
|
|||
|
|
@ -36,9 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
#include "textio/textio.h"
|
||||
|
||||
extern char *efReadFileName;
|
||||
extern int efReadLineNum;
|
||||
#include "extflat/extparse.h"
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
extern int Tcl_printf();
|
||||
|
|
|
|||
|
|
@ -46,6 +46,14 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
/* C99 compat */
|
||||
#include "textio/textio.h"
|
||||
|
||||
#ifndef MAGIC_WRAPPER
|
||||
/* This must match the definition for extDevTable in extract/ExtBasic.c */
|
||||
const char * const extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
|
||||
"devcap", "devcaprev", "vsource", "diode", "pdiode",
|
||||
"ndiode", "subckt", "rsubckt", "msubckt", "csubckt",
|
||||
"dsubckt", "veriloga", NULL};
|
||||
#endif
|
||||
|
||||
/* Data shared with EFerror.c */
|
||||
char *efReadFileName; /* Name of file currently being read */
|
||||
int efReadLineNum; /* Current line number in above file */
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include "extflat/EFtypes.h" /* EFCapValue, HierName, EFPerimArea, EFNode */
|
||||
#include "extflat/EFint.h" /* Def, HierContext, Connection, Distance, CallArg */
|
||||
|
||||
|
||||
extern float EFScale; /* Scale factor to multiply all coords by */
|
||||
extern char *EFTech; /* Technology of extracted circuit */
|
||||
extern char *EFStyle; /* Extraction style of extracted circuit */
|
||||
|
|
|
|||
|
|
@ -16,19 +16,8 @@
|
|||
* *********************************************************************
|
||||
*/
|
||||
|
||||
/* These must be in the order of "known devices" in extract/extract.h. */
|
||||
/* This table is also used in extract/ExtBasic.c */
|
||||
|
||||
/* Note: "fet" refers to the original fet type; "mosfet" refers to the */
|
||||
/* new type. The main difference is that "fet" records area/perimeter */
|
||||
/* while "mosfet" records length/width. */
|
||||
|
||||
#ifndef MAGIC_WRAPPER
|
||||
const char * const extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
|
||||
"devcap", "devcaprev", "vsource", "diode", "pdiode",
|
||||
"ndiode", "subckt", "rsubckt", "msubckt", "csubckt",
|
||||
"dsubckt", "veriloga", NULL};
|
||||
#endif
|
||||
#ifndef _MAGIC__EXTFLAT__EXTPARSE_H
|
||||
#define _MAGIC__EXTFLAT__EXTPARSE_H
|
||||
|
||||
/*
|
||||
* The following table describes the kinds of lines
|
||||
|
|
@ -80,5 +69,7 @@ keyTable[] =
|
|||
/* atoCap - convert a string to a EFCapValue */
|
||||
#define atoCap(s) ((EFCapValue)atof(s))
|
||||
|
||||
extern int efReadLineNum; /* Current line number in the .ext file */
|
||||
extern int efReadLineNum; /* Current line number in the .ext file */
|
||||
extern char *efReadFileName; /* Name of current .ext file being read */
|
||||
|
||||
#endif /* _MAGIC__EXTFLAT__EXTPARSE_H */
|
||||
|
|
|
|||
|
|
@ -46,7 +46,20 @@ static char sccsid[] = "@(#)ExtBasic.c 4.13 MAGIC (Berkeley) 12/5/85";
|
|||
#include "utils/styles.h"
|
||||
#include "utils/stack.h"
|
||||
#include "utils/utils.h"
|
||||
#include "resis/resis.h"
|
||||
|
||||
/* These must be in the order of "known devices" in extract.h. */
|
||||
|
||||
/* Note: "fet" refers to the original fet type; "mosfet" refers to the */
|
||||
/* new type. The main difference is that "fet" records area/perimeter */
|
||||
/* while "mosfet" records length/width. */
|
||||
/* Also: Note that this table is repeated in extflat/EFread.c when */
|
||||
/* ext2spice/ext2sim are compiled as separate programs (i.e., non-Tcl) */
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
const char * const extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
|
||||
"devcap", "devcaprev", "vsource", "diode", "pdiode", "ndiode",
|
||||
"subckt", "rsubckt", "msubckt", "csubckt", "dsubckt", "veriloga", NULL};
|
||||
#endif
|
||||
|
||||
/* --------------------- Data local to this file ---------------------- */
|
||||
|
||||
|
|
@ -546,24 +559,6 @@ extBasic(def, outFile)
|
|||
extOutputDevices(def, transList, outFile);
|
||||
}
|
||||
|
||||
/* Integrated extresist --- Run "extresist" on the cell def just
|
||||
* extracted and produce an annotation file "<file>.res.ext".
|
||||
*/
|
||||
|
||||
if (ExtOptions & EXT_DOEXTRESIST)
|
||||
{
|
||||
ResisData resisdata;
|
||||
|
||||
/* These need to be passed to extresist somehow. Most are unused. */
|
||||
resisdata.rthresh = 0;
|
||||
resisdata.tdiTolerance = 1;
|
||||
resisdata.frequency = 10e6;
|
||||
resisdata.mainDef = def;
|
||||
resisdata.savePlanes = (struct saveList *)NULL; /* unused */
|
||||
|
||||
ExtResisForDef(def, &resisdata);
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
if (coupleInitialized)
|
||||
extCapHashKill(&extCoupleHash);
|
||||
|
|
@ -5000,9 +4995,12 @@ extFindNodes(def, clipArea, subonly)
|
|||
/* If the default substrate type is set, it is used *only* for */
|
||||
/* isolated substrate regions and does not mark the default */
|
||||
/* substrate, so remove it from the list of substrate types. */
|
||||
/* Note that this is not the case when doing full R-C */
|
||||
/* extraction. */
|
||||
|
||||
if (ExtCurStyle->exts_globSubstrateDefaultType != -1)
|
||||
TTMaskClearType(&subsTypesNonSpace,
|
||||
if (!(ExtOptions & EXT_DOEXTRESIST))
|
||||
if (ExtCurStyle->exts_globSubstrateDefaultType != -1)
|
||||
TTMaskClearType(&subsTypesNonSpace,
|
||||
ExtCurStyle->exts_globSubstrateDefaultType);
|
||||
|
||||
pNum = ExtCurStyle->exts_globSubstratePlane;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "debug/debug.h"
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extractInt.h"
|
||||
#include "resis/resis.h"
|
||||
#include "utils/signals.h"
|
||||
#include "utils/stack.h"
|
||||
#include "utils/utils.h"
|
||||
|
|
@ -115,6 +116,25 @@ ExtCell(def, outName, doLength)
|
|||
savePlane = extCellFile(def, f, doLength);
|
||||
if (f != NULL) fclose(f);
|
||||
|
||||
/* Integrated extresist --- Run "extresist" on the cell def just
|
||||
* extracted and produce an annotation file "<file>.res.ext".
|
||||
*/
|
||||
|
||||
if (ExtOptions & EXT_DOEXTRESIST)
|
||||
{
|
||||
ResisData *resisdata = ResInit();
|
||||
|
||||
UndoDisable();
|
||||
|
||||
ResOptionsFlags |= ResOpt_Signal;
|
||||
resisdata->mainDef = def;
|
||||
resisdata->savePlanes = (struct saveList *)NULL; /* unused */
|
||||
|
||||
ExtResisForDef(def, resisdata);
|
||||
|
||||
UndoEnable();
|
||||
}
|
||||
|
||||
if (extNumErrors > 0 || extNumWarnings > 0)
|
||||
{
|
||||
TxPrintf("%s:", def->cd_name);
|
||||
|
|
@ -493,7 +513,10 @@ extCellFile(def, f, doLength)
|
|||
extUniqueCell(def, EXT_UNIQ_TEMP);
|
||||
|
||||
/* Prep any isolated substrate areas */
|
||||
saveSub = extPrepSubstrate(def);
|
||||
if (ExtOptions & EXT_DOEXTRESIST)
|
||||
saveSub = extResPrepSubstrate(def);
|
||||
else
|
||||
saveSub = extPrepSubstrate(def);
|
||||
|
||||
/* Remove any label markers that were made by a previous extraction */
|
||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||
|
|
|
|||
|
|
@ -273,9 +273,9 @@ ResMakePortBreakpoints(def)
|
|||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ResMakeLabelBreakpoints(def, goodies)
|
||||
CellDef *def;
|
||||
ResGlobalParams *goodies;
|
||||
ResMakeLabelBreakpoints(def, resisdata)
|
||||
CellDef *def;
|
||||
ResisData *resisdata;
|
||||
{
|
||||
Plane *plane;
|
||||
Rect *rect;
|
||||
|
|
@ -294,12 +294,12 @@ ResMakeLabelBreakpoints(def, goodies)
|
|||
entry = HashFind(&ResNodeTable, slab->lab_text);
|
||||
node = ResInitializeNode(entry);
|
||||
|
||||
/* If the drivepoint position changes and the drivepoint is */
|
||||
/* in the "goodies" record, then make sure the tile type in */
|
||||
/* "goodies" gets changed to match. */
|
||||
/* If the drivepoint position changes and the drivepoint is */
|
||||
/* in the "resisdata" record, then make sure the tile type */
|
||||
/* in "resisdata" gets changed to match. */
|
||||
|
||||
if (goodies->rg_devloc == &node->drivepoint)
|
||||
goodies->rg_ttype = slab->lab_type;
|
||||
if (resisdata->rg_devloc == &node->drivepoint)
|
||||
resisdata->rg_ttype = slab->lab_type;
|
||||
|
||||
node->drivepoint = slab->lab_rect.r_ll;
|
||||
node->rs_bbox = slab->lab_rect;
|
||||
|
|
@ -490,9 +490,9 @@ ResFindNewContactTiles(contacts)
|
|||
*/
|
||||
|
||||
int
|
||||
ResProcessTiles(goodies, origin)
|
||||
Point *origin;
|
||||
ResGlobalParams *goodies;
|
||||
ResProcessTiles(resisdata, origin)
|
||||
Point *origin;
|
||||
ResisData *resisdata;
|
||||
|
||||
{
|
||||
Tile *startTile;
|
||||
|
|
@ -506,7 +506,7 @@ ResProcessTiles(goodies, origin)
|
|||
|
||||
if (ResOptionsFlags & ResOpt_Signal)
|
||||
{
|
||||
startTile = FindStartTile(goodies, origin);
|
||||
startTile = FindStartTile(resisdata, origin);
|
||||
if (startTile == NULL)
|
||||
return 1;
|
||||
resCurrentNode = NULL;
|
||||
|
|
@ -990,9 +990,9 @@ ResShaveContacts(tile, dinfo, def)
|
|||
*/
|
||||
|
||||
bool
|
||||
ResExtractNet(node, goodies, cellname)
|
||||
ResExtractNet(node, resisdata, cellname)
|
||||
ResExtNode *node;
|
||||
ResGlobalParams *goodies;
|
||||
ResisData *resisdata;
|
||||
char *cellname;
|
||||
{
|
||||
SearchContext scx;
|
||||
|
|
@ -1018,8 +1018,8 @@ ResExtractNet(node, goodies, cellname)
|
|||
|
||||
/* Pass back network pointers */
|
||||
|
||||
goodies->rg_maxres = 0;
|
||||
goodies->rg_tilecount = 0;
|
||||
resisdata->rg_maxres = 0;
|
||||
resisdata->rg_tilecount = 0;
|
||||
|
||||
/* Set up internal stuff if this is the first time through */
|
||||
|
||||
|
|
@ -1102,10 +1102,10 @@ ResExtractNet(node, goodies, cellname)
|
|||
resMakeDevFunc, (ClientData)thisDev);
|
||||
if (result == 0)
|
||||
{
|
||||
TxError("No device of type %s found at location %d,%d\n",
|
||||
TxError("No device of type %s found at location %s, %s\n",
|
||||
DBTypeLongNameTbl[thisDev->type],
|
||||
tptr->thisDev->location.p_x,
|
||||
tptr->thisDev->location.p_y);
|
||||
DBWPrintValue(tptr->thisDev->location.p_x, (MagWindow*)NULL, TRUE),
|
||||
DBWPrintValue(tptr->thisDev->location.p_y, (MagWindow*)NULL, FALSE));
|
||||
freeMagic(thisDev);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1185,12 +1185,12 @@ ResExtractNet(node, goodies, cellname)
|
|||
/* Finish preprocessing. */
|
||||
|
||||
ResMakePortBreakpoints(ResUse->cu_def);
|
||||
ResMakeLabelBreakpoints(ResUse->cu_def, goodies);
|
||||
ResMakeLabelBreakpoints(ResUse->cu_def, resisdata);
|
||||
ResFindNewContactTiles(ResContactList);
|
||||
ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def);
|
||||
|
||||
/* do extraction */
|
||||
if (ResProcessTiles(goodies, &startpoint) != 0) return TRUE;
|
||||
if (ResProcessTiles(resisdata, &startpoint) != 0) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1323,10 +1323,9 @@ ResGetTileFunc(tile, dinfo, tpptr)
|
|||
*/
|
||||
|
||||
Tile *
|
||||
FindStartTile(goodies, SourcePoint)
|
||||
FindStartTile(resisdata, SourcePoint)
|
||||
ResisData *resisdata;
|
||||
Point *SourcePoint;
|
||||
ResGlobalParams *goodies;
|
||||
|
||||
{
|
||||
Point workingPoint;
|
||||
Tile *tile, *tp;
|
||||
|
|
@ -1339,39 +1338,39 @@ FindStartTile(goodies, SourcePoint)
|
|||
/* If the drive point is on a contact, check for the contact residues */
|
||||
/* first, then the contact type itself. */
|
||||
|
||||
if (DBIsContact(goodies->rg_ttype))
|
||||
if (DBIsContact(resisdata->rg_ttype))
|
||||
{
|
||||
TileTypeBitMask *rmask = DBResidueMask(goodies->rg_ttype);
|
||||
TileType savtype = goodies->rg_ttype;
|
||||
TileTypeBitMask *rmask = DBResidueMask(resisdata->rg_ttype);
|
||||
TileType savtype = resisdata->rg_ttype;
|
||||
TileType rtype;
|
||||
|
||||
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
|
||||
if (TTMaskHasType(rmask, rtype))
|
||||
{
|
||||
goodies->rg_ttype = rtype;
|
||||
if ((tile = FindStartTile(goodies, SourcePoint)) != NULL)
|
||||
resisdata->rg_ttype = rtype;
|
||||
if ((tile = FindStartTile(resisdata, SourcePoint)) != NULL)
|
||||
{
|
||||
goodies->rg_ttype = savtype;
|
||||
resisdata->rg_ttype = savtype;
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
goodies->rg_ttype = savtype;
|
||||
resisdata->rg_ttype = savtype;
|
||||
}
|
||||
|
||||
workingPoint.p_x = goodies->rg_devloc->p_x;
|
||||
workingPoint.p_y = goodies->rg_devloc->p_y;
|
||||
workingPoint.p_x = resisdata->rg_devloc->p_x;
|
||||
workingPoint.p_y = resisdata->rg_devloc->p_y;
|
||||
|
||||
pnum = DBPlane(goodies->rg_ttype);
|
||||
pnum = DBPlane(resisdata->rg_ttype);
|
||||
|
||||
/* for drivepoints, we don't have to find a device */
|
||||
if (goodies->rg_status & DRIVEONLY)
|
||||
if (resisdata->rg_status & DRIVEONLY)
|
||||
{
|
||||
tile = PlaneGetHint(ResUse->cu_def->cd_planes[pnum]);
|
||||
GOTOPOINT(tile, &workingPoint);
|
||||
SourcePoint->p_x = workingPoint.p_x;
|
||||
SourcePoint->p_y = workingPoint.p_y;
|
||||
|
||||
if (TiGetTypeExact(tile) == goodies->rg_ttype)
|
||||
if (TiGetTypeExact(tile) == resisdata->rg_ttype)
|
||||
return tile;
|
||||
else
|
||||
{
|
||||
|
|
@ -1383,18 +1382,19 @@ FindStartTile(goodies, SourcePoint)
|
|||
if (workingPoint.p_x == LEFT(tile))
|
||||
{
|
||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
|
||||
if (TiGetRightType(tp) == goodies->rg_ttype)
|
||||
if (TiGetRightType(tp) == resisdata->rg_ttype)
|
||||
return(tp);
|
||||
}
|
||||
else if (workingPoint.p_y == BOTTOM(tile))
|
||||
{
|
||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
||||
if (TiGetTopType(tp) == goodies->rg_ttype)
|
||||
if (TiGetTopType(tp) == resisdata->rg_ttype)
|
||||
return(tp);
|
||||
}
|
||||
}
|
||||
TxError("Couldn't find wire at %d %d\n",
|
||||
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y);
|
||||
TxError("Couldn't find wire at %s %s\n",
|
||||
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
|
||||
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1409,15 +1409,17 @@ FindStartTile(goodies, SourcePoint)
|
|||
t1 = TiGetRightType(tile);
|
||||
else
|
||||
{
|
||||
TxError("Couldn't find device at %d %d\n",
|
||||
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y);
|
||||
TxError("Couldn't find device at %s %s\n",
|
||||
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
|
||||
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)) == 0)
|
||||
{
|
||||
TxError("Couldn't find device at %d %d\n",
|
||||
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y);
|
||||
TxError("Couldn't find device at %s %s\n",
|
||||
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
|
||||
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
|
||||
return(NULL);
|
||||
}
|
||||
else
|
||||
|
|
@ -1708,8 +1710,9 @@ FindStartTile(goodies, SourcePoint)
|
|||
/* Didn't find a terminal (S/D or substrate) type tile anywhere. Flag an error. */
|
||||
|
||||
if (devptr == NULL)
|
||||
TxError("Couldn't find a terminal of the device at %d %d\n",
|
||||
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y);
|
||||
TxError("Couldn't find a terminal of the device at %s %s\n",
|
||||
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow*)NULL, TRUE),
|
||||
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow*)NULL, FALSE));
|
||||
return((Tile *) NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "database/database.h"
|
||||
#include "utils/malloc.h"
|
||||
#include "textio/textio.h"
|
||||
#include "extflat/extparse.h"
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extractInt.h"
|
||||
#include "windows/windows.h"
|
||||
|
|
@ -175,13 +176,13 @@ ResPrintExtDev(outextfile, devices)
|
|||
fprintf(outextfile, " \"%s\" %d %s",
|
||||
devices->gate->name,
|
||||
devices->layout->rd_length * 2,
|
||||
devices->rs_gattr);
|
||||
(*devices->rs_gattr == '\0') ? "0" : devices->rs_gattr);
|
||||
|
||||
if (devices->source != NULL)
|
||||
fprintf(outextfile, " \"%s\" %d %s",
|
||||
devices->source->name,
|
||||
devices->layout->rd_width,
|
||||
devices->rs_sattr);
|
||||
(*devices->rs_sattr == '\0') ? "0" : devices->rs_sattr);
|
||||
|
||||
/* Don't write drain values for 2-terminal devices */
|
||||
if (devptr->exts_deviceSDCount > 1)
|
||||
|
|
@ -189,7 +190,7 @@ ResPrintExtDev(outextfile, devices)
|
|||
fprintf(outextfile, " \"%s\" %d %s",
|
||||
devices->drain->name,
|
||||
devices->layout->rd_width,
|
||||
devices->rs_dattr);
|
||||
(*devices->rs_dattr == '\0') ? "0" : devices->rs_dattr);
|
||||
|
||||
fprintf(outextfile, "\n");
|
||||
}
|
||||
|
|
@ -290,6 +291,13 @@ ResPrintExtNode(outextfile, nodelist, node)
|
|||
|
||||
if (NeedFix)
|
||||
{
|
||||
if (nodelist == NULL)
|
||||
{
|
||||
TxError("Error: Orphaned node \"%s\" not output.\n",
|
||||
node->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
|
@ -316,16 +324,16 @@ ResPrintExtNode(outextfile, nodelist, node)
|
|||
*/
|
||||
|
||||
void
|
||||
ResPrintStats(goodies, name)
|
||||
ResGlobalParams *goodies;
|
||||
char *name;
|
||||
ResPrintStats(resisdata, name)
|
||||
ResisData *resisdata;
|
||||
char *name;
|
||||
{
|
||||
static int totalnets = 0, totalnodes = 0, totalresistors = 0;
|
||||
int nodes, resistors;
|
||||
resNode *node;
|
||||
resResistor *res;
|
||||
|
||||
if (goodies == NULL)
|
||||
if (resisdata == NULL)
|
||||
{
|
||||
TxError("nets:%d nodes:%d resistors:%d\n",
|
||||
totalnets, totalnodes, totalresistors);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
266
resis/ResRex.c
266
resis/ResRex.c
|
|
@ -57,12 +57,10 @@ HashTable ResProcessedTable;
|
|||
|
||||
HashTable ResNodeTable; /* Hash table of ext file nodes */
|
||||
RDev *ResRDevList; /* Linked list of Ext devices */
|
||||
ResGlobalParams gparams; /* Junk passed between */
|
||||
/* ResCheckExtNodes and */
|
||||
/* ResExtractNet. */
|
||||
extern ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
|
||||
int resNodeNum;
|
||||
|
||||
extern ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
|
||||
|
||||
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile;
|
||||
char *ResCurrentNode;
|
||||
|
||||
|
|
@ -98,27 +96,10 @@ ExtResisForDef(celldef, resisdata)
|
|||
ResExtNode *node;
|
||||
int result, idx;
|
||||
char *devname;
|
||||
Plane *savePlane;
|
||||
|
||||
ResRDevList = NULL;
|
||||
ResOriginalNodes = NULL;
|
||||
|
||||
/* Check if this cell has been processed */
|
||||
if (HashLookOnly(&ResProcessedTable, celldef->cd_name)) return;
|
||||
HashFind(&ResProcessedTable, celldef->cd_name);
|
||||
|
||||
/* Prepare the substrate for resistance extraction */
|
||||
savePlane = extResPrepSubstrate(celldef);
|
||||
if (savePlane != NULL)
|
||||
{
|
||||
struct saveList *newsl;
|
||||
newsl = (struct saveList *)mallocMagic(sizeof(struct saveList));
|
||||
newsl->sl_plane = savePlane;
|
||||
newsl->sl_def = celldef;
|
||||
newsl->sl_next = resisdata->savePlanes;
|
||||
resisdata->savePlanes = newsl;
|
||||
}
|
||||
|
||||
/* Get device information from the current extraction style */
|
||||
idx = 0;
|
||||
while (ExtGetDevInfo(idx++, &devname, NULL, NULL, NULL, NULL, NULL))
|
||||
|
|
@ -139,17 +120,11 @@ ExtResisForDef(celldef, resisdata)
|
|||
for (idx = 0; idx < EFDevNumTypes; idx++) freeMagic(EFDevTypes[idx]);
|
||||
EFDevNumTypes = 0;
|
||||
|
||||
if (result)
|
||||
/* read in .nodes file */
|
||||
result = (ResReadNode(celldef->cd_name) == 0);
|
||||
|
||||
if (result)
|
||||
{
|
||||
/* Check for subcircuit ports */
|
||||
if (ResOptionsFlags & ResOpt_Blackbox)
|
||||
ResCheckBlackbox(celldef);
|
||||
else
|
||||
ResCheckPorts(celldef);
|
||||
|
||||
/* Extract networks for nets that require it. */
|
||||
if (!(ResOptionsFlags & ResOpt_FastHenry) ||
|
||||
|
|
@ -157,7 +132,7 @@ ExtResisForDef(celldef, resisdata)
|
|||
ResCheckExtNodes(celldef, resisdata);
|
||||
|
||||
if (ResOptionsFlags & ResOpt_Stat)
|
||||
ResPrintStats((ResGlobalParams *)NULL, "");
|
||||
ResPrintStats((ResisData *)NULL, "");
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
|
|
@ -197,13 +172,74 @@ ExtResisForDef(celldef, resisdata)
|
|||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* CmdExtResis-- reads in ext file and layout, and produces patches to the
|
||||
* .ext files that include resistors.
|
||||
* ResInit --
|
||||
*
|
||||
* Initialize data and hash tables for running "extresist".
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to an allocated ResisData structure. This
|
||||
* structure is static and may be modified by repeated execution
|
||||
* of "extresist" commands.
|
||||
*
|
||||
* Side effects:
|
||||
* Allocates memory for the ResisData structure.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
ResisData *
|
||||
ResInit()
|
||||
{
|
||||
static ResisData *resisdata;
|
||||
static int init = 1; /* Ensure initialization is done only once */
|
||||
int i;
|
||||
|
||||
if (init)
|
||||
{
|
||||
resisdata = (ResisData *)mallocMagic(sizeof(ResisData));
|
||||
|
||||
for (i = 0; i < NT; i++)
|
||||
{
|
||||
TTMaskZero(&(ResCopyMask[i]));
|
||||
TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]);
|
||||
}
|
||||
resisdata->rthresh = 0;
|
||||
resisdata->tdiTolerance = 1;
|
||||
resisdata->frequency = 10e6; /* 10 MHz default */
|
||||
|
||||
HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||
HashInit(&ResIncludeTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||
init = 0;
|
||||
}
|
||||
|
||||
/* Reset global parameters */
|
||||
resisdata->rg_ttype = TT_SPACE;
|
||||
resisdata->rg_Tdi = 0.0;
|
||||
resisdata->rg_nodecap = 0.0;
|
||||
resisdata->rg_maxres = 0.0;
|
||||
resisdata->rg_bigdevres = 0;
|
||||
resisdata->rg_tilecount = 0;
|
||||
resisdata->rg_status = 0;
|
||||
resisdata->rg_devloc = NULL;
|
||||
resisdata->rg_name = NULL;
|
||||
|
||||
return resisdata;
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* CmdExtResis--
|
||||
*
|
||||
* Reads in a .ext file and layout, and produces patches to the
|
||||
* .ext files that include resistors and subnets.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects: Produces .res.ext file for all nets that require resistors.
|
||||
* Side Effects:
|
||||
* Produces a .res.ext file with all nets that require subdivision
|
||||
* into resistive segments.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -214,12 +250,11 @@ CmdExtResis(win, cmd)
|
|||
TxCommand *cmd;
|
||||
{
|
||||
int i, j, k, option, value, saveFlags;
|
||||
static int init = 1;
|
||||
static float rthresh, tdiTolerance, fhFrequency;
|
||||
|
||||
CellDef *mainDef;
|
||||
CellUse *selectedUse;
|
||||
ResisData resisdata;
|
||||
ResisData *resisdata;
|
||||
Plane *savePlane;
|
||||
char *endptr; /* for use with strtod() */
|
||||
struct saveList *sl;
|
||||
|
||||
|
|
@ -262,31 +297,7 @@ typedef enum {
|
|||
RES_RUN
|
||||
} ResOptions;
|
||||
|
||||
if (init)
|
||||
{
|
||||
for (i = 0; i < NT; i++)
|
||||
{
|
||||
TTMaskZero(&(ResCopyMask[i]));
|
||||
TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]);
|
||||
}
|
||||
rthresh = 0;
|
||||
tdiTolerance = 1;
|
||||
fhFrequency = 10e6; /* 10 MHz default */
|
||||
HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||
HashInit(&ResIncludeTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||
init = 0;
|
||||
}
|
||||
|
||||
/* Initialize ResGlobalParams */
|
||||
gparams.rg_ttype = TT_SPACE;
|
||||
gparams.rg_Tdi = 0.0;
|
||||
gparams.rg_nodecap = 0.0;
|
||||
gparams.rg_maxres = 0.0;
|
||||
gparams.rg_bigdevres = 0;
|
||||
gparams.rg_tilecount = 0;
|
||||
gparams.rg_status = 0;
|
||||
gparams.rg_devloc = NULL;
|
||||
gparams.rg_name = NULL;
|
||||
resisdata = ResInit();
|
||||
|
||||
option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd)
|
||||
: RES_RUN;
|
||||
|
|
@ -316,8 +327,8 @@ typedef enum {
|
|||
ResOptionsFlags |= ResOpt_ExplicitRtol;
|
||||
if (cmd->tx_argc > 2)
|
||||
{
|
||||
tdiTolerance = MagAtof(cmd->tx_argv[2]);
|
||||
if (tdiTolerance <= 0)
|
||||
resisdata->tdiTolerance = MagAtof(cmd->tx_argv[2]);
|
||||
if (resisdata->tdiTolerance <= 0)
|
||||
{
|
||||
TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]);
|
||||
return;
|
||||
|
|
@ -326,9 +337,10 @@ typedef enum {
|
|||
else
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)tdiTolerance));
|
||||
Tcl_SetObjResult(magicinterp,
|
||||
Tcl_NewDoubleObj((double)resisdata->tdiTolerance));
|
||||
#else
|
||||
TxPrintf("Tolerance ratio is %g.\n", tdiTolerance);
|
||||
TxPrintf("Tolerance ratio is %g.\n", resisdata->tdiTolerance);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
|
@ -336,8 +348,8 @@ typedef enum {
|
|||
case RES_THRESH:
|
||||
if (cmd->tx_argc > 2)
|
||||
{
|
||||
rthresh = MagAtof(cmd->tx_argv[2]);
|
||||
if (rthresh < 0)
|
||||
resisdata->rthresh = MagAtof(cmd->tx_argv[2]);
|
||||
if (resisdata->rthresh < 0)
|
||||
{
|
||||
TxError("Usage: %s threshold [value]\n", cmd->tx_argv[0]);
|
||||
return;
|
||||
|
|
@ -346,9 +358,10 @@ typedef enum {
|
|||
else
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)rthresh));
|
||||
Tcl_SetObjResult(magicinterp,
|
||||
Tcl_NewDoubleObj((double)resisdata->rthresh));
|
||||
#else
|
||||
TxPrintf("Resistance threshold is %g.\n", rthresh);
|
||||
TxPrintf("Resistance threshold is %g.\n", resisdata->rthresh);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
|
@ -371,10 +384,10 @@ typedef enum {
|
|||
if (endptr == cmd->tx_argv[2])
|
||||
{
|
||||
TxError("Cannot parse frequency value. Assuming default\n");
|
||||
TxError("Frequency = %2.1f Hz\n", fhFrequency);
|
||||
TxError("Frequency = %2.1f Hz\n", resisdata->frequency);
|
||||
}
|
||||
else
|
||||
fhFrequency = (float)tmpf;
|
||||
resisdata->frequency = (float)tmpf;
|
||||
}
|
||||
saveFlags = ResOptionsFlags;
|
||||
ResOptionsFlags |= ResOpt_FastHenry | ResOpt_ExtractAll;
|
||||
|
|
@ -556,14 +569,14 @@ typedef enum {
|
|||
if (cmd->tx_argc != 3) return;
|
||||
tt = DBTechNoisyNameType(cmd->tx_argv[2]);
|
||||
if (tt <= 0 || ToolGetBox(&def, &rect)== FALSE) return;
|
||||
gparams.rg_devloc = &rect.r_ll;
|
||||
gparams.rg_ttype = tt;
|
||||
gparams.rg_status = DRIVEONLY;
|
||||
resisdata->rg_devloc = &rect.r_ll;
|
||||
resisdata->rg_ttype = tt;
|
||||
resisdata->rg_status = DRIVEONLY;
|
||||
oldoptions = ResOptionsFlags;
|
||||
ResOptionsFlags = ResOpt_DoSubstrate | ResOpt_Signal | ResOpt_Box;
|
||||
lnode.location = rect.r_ll;
|
||||
lnode.type = tt;
|
||||
if (ResExtractNet(&lnode, &gparams, NULL) != 0) return;
|
||||
if (ResExtractNet(&lnode, resisdata, NULL) != 0) return;
|
||||
ResPrintResistorList(stdout, ResResList);
|
||||
ResPrintDeviceList(stdout, ResRDevList);
|
||||
ResOptionsFlags = oldoptions;
|
||||
|
|
@ -607,23 +620,33 @@ typedef enum {
|
|||
}
|
||||
ResOptionsFlags |= ResOpt_Signal;
|
||||
|
||||
resisdata.rthresh = rthresh;
|
||||
resisdata.tdiTolerance = tdiTolerance;
|
||||
resisdata.frequency = fhFrequency;
|
||||
resisdata.mainDef = mainDef;
|
||||
resisdata.savePlanes = (struct saveList *)NULL;
|
||||
resisdata->mainDef = mainDef;
|
||||
resisdata->savePlanes = (struct saveList *)NULL;
|
||||
|
||||
/* Do subcircuits (if any) first */
|
||||
HashInit(&ResProcessedTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||
if (!(ResOptionsFlags & ResOpt_Blackbox))
|
||||
DBCellEnum(mainDef, resSubcircuitFunc, (ClientData) &resisdata);
|
||||
DBCellEnum(mainDef, resSubcircuitFunc, (ClientData)resisdata);
|
||||
|
||||
ExtResisForDef(mainDef, &resisdata);
|
||||
HashFind(&ResProcessedTable, mainDef->cd_name);
|
||||
|
||||
/* Prepare the substrate for resistance extraction */
|
||||
savePlane = extResPrepSubstrate(mainDef);
|
||||
if (savePlane != NULL)
|
||||
{
|
||||
struct saveList *newsl;
|
||||
newsl = (struct saveList *)mallocMagic(sizeof(struct saveList));
|
||||
newsl->sl_plane = savePlane;
|
||||
newsl->sl_def = mainDef;
|
||||
newsl->sl_next = resisdata->savePlanes;
|
||||
resisdata->savePlanes = newsl;
|
||||
}
|
||||
ExtResisForDef(mainDef, resisdata);
|
||||
HashKill(&ResProcessedTable);
|
||||
|
||||
/* Revert substrate planes */
|
||||
free_magic1_t mm1 = freeMagic1_init();
|
||||
for (sl = resisdata.savePlanes; sl; sl = sl->sl_next)
|
||||
for (sl = resisdata->savePlanes; sl; sl = sl->sl_next)
|
||||
{
|
||||
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
|
||||
freeMagic1(&mm1, sl);
|
||||
|
|
@ -664,10 +687,26 @@ resSubcircuitFunc(cellUse, rdata)
|
|||
CellUse *cellUse;
|
||||
ResisData *rdata;
|
||||
{
|
||||
CellDef *cellDef = cellUse->cu_def;
|
||||
CellDef *cellDef = cellUse->cu_def;
|
||||
Plane *savePlane;
|
||||
|
||||
if (DBIsSubcircuit(cellDef))
|
||||
{
|
||||
/* Check if this cell has been processed */
|
||||
if (HashLookOnly(&ResProcessedTable, cellDef->cd_name)) return 0;
|
||||
HashFind(&ResProcessedTable, cellDef->cd_name);
|
||||
|
||||
/* Prepare the substrate for resistance extraction */
|
||||
savePlane = extResPrepSubstrate(cellDef);
|
||||
if (savePlane != NULL)
|
||||
{
|
||||
struct saveList *newsl;
|
||||
newsl = (struct saveList *)mallocMagic(sizeof(struct saveList));
|
||||
newsl->sl_plane = savePlane;
|
||||
newsl->sl_def = cellDef;
|
||||
newsl->sl_next = rdata->savePlanes;
|
||||
rdata->savePlanes = newsl;
|
||||
}
|
||||
ExtResisForDef(cellDef, rdata);
|
||||
DBCellEnum(cellDef, resSubcircuitFunc, (ClientData)rdata);
|
||||
}
|
||||
|
|
@ -925,7 +964,6 @@ ResProcessNode(
|
|||
HashEntry *he;
|
||||
devPtr *ptr;
|
||||
float ftolerance, minRes, cumRes;
|
||||
float rctol = resisdata->tdiTolerance;
|
||||
float rthresh = resisdata->rthresh;
|
||||
int nidx = 1, eidx = 1; /* node & segment counters for geom. */
|
||||
|
||||
|
|
@ -956,14 +994,14 @@ ResProcessNode(
|
|||
/* Find largest SD device connected to node. */
|
||||
|
||||
minRes = FLT_MAX;
|
||||
gparams.rg_devloc = (Point *) NULL;
|
||||
gparams.rg_status = FALSE;
|
||||
gparams.rg_nodecap = node->capacitance;
|
||||
resisdata->rg_devloc = (Point *) NULL;
|
||||
resisdata->rg_status = FALSE;
|
||||
resisdata->rg_nodecap = node->capacitance;
|
||||
|
||||
/* The following is only used if there is a drivepoint */
|
||||
/* to identify which tile the drivepoint is on. */
|
||||
|
||||
gparams.rg_ttype = node->rs_ttype;
|
||||
resisdata->rg_ttype = node->rs_ttype;
|
||||
|
||||
for (ptr = node->firstDev; ptr != NULL; ptr = ptr->nextDev)
|
||||
{
|
||||
|
|
@ -999,8 +1037,8 @@ ResProcessNode(
|
|||
if (minRes > cumRes)
|
||||
{
|
||||
minRes = cumRes;
|
||||
gparams.rg_devloc = &t1->location;
|
||||
gparams.rg_ttype = t1->rs_ttype;
|
||||
resisdata->rg_devloc = &t1->location;
|
||||
resisdata->rg_ttype = t1->rs_ttype;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1020,25 +1058,25 @@ ResProcessNode(
|
|||
}
|
||||
if (node->status & DRIVELOC)
|
||||
{
|
||||
gparams.rg_devloc = &node->drivepoint;
|
||||
gparams.rg_status |= DRIVEONLY;
|
||||
resisdata->rg_devloc = &node->drivepoint;
|
||||
resisdata->rg_status |= DRIVEONLY;
|
||||
}
|
||||
if (node->status & PORTNODE)
|
||||
{
|
||||
/* The node is a port, not a device, so make */
|
||||
/* sure rg_ttype is set accordingly. */
|
||||
gparams.rg_ttype = node->rs_ttype;
|
||||
resisdata->rg_ttype = node->rs_ttype;
|
||||
}
|
||||
}
|
||||
if ((gparams.rg_devloc == NULL) && (node->status & FORCE))
|
||||
if ((resisdata->rg_devloc == NULL) && (node->status & FORCE))
|
||||
{
|
||||
TxError("Node %s has force label but no drive point or "
|
||||
"driving device\n", node->name);
|
||||
}
|
||||
if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL))
|
||||
if ((minRes == FLT_MAX) || (resisdata->rg_devloc == NULL))
|
||||
return 1;
|
||||
|
||||
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
|
||||
resisdata->rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
|
||||
if (minRes > resisdata->rthresh)
|
||||
ftolerance = minRes;
|
||||
else
|
||||
|
|
@ -1055,7 +1093,7 @@ ResProcessNode(
|
|||
ResFixPoint fp;
|
||||
|
||||
(*num_extracted)++;
|
||||
if (ResExtractNet(node, &gparams, outfile) != 0)
|
||||
if (ResExtractNet(node, resisdata, outfile) != 0)
|
||||
{
|
||||
/* On error, don't output this net, but keep going */
|
||||
if (node->type == TT_SPACE)
|
||||
|
|
@ -1066,15 +1104,16 @@ ResProcessNode(
|
|||
}
|
||||
else
|
||||
{
|
||||
ResDoSimplify(ftolerance, rctol, &gparams);
|
||||
ResDoSimplify(ftolerance, resisdata);
|
||||
if (ResOptionsFlags & ResOpt_DoLumpFile)
|
||||
ResWriteLumpFile(node);
|
||||
ResWriteLumpFile(node, resisdata);
|
||||
|
||||
if (gparams.rg_maxres >= ftolerance ||
|
||||
if (resisdata->rg_maxres >= ftolerance ||
|
||||
(ResOptionsFlags & ResOpt_ExtractAll))
|
||||
{
|
||||
resNodeNum = 0;
|
||||
(*num_output) += ResWriteExtFile(celldef, node, rctol, &nidx, &eidx);
|
||||
(*num_output) += ResWriteExtFile(celldef, node, resisdata,
|
||||
&nidx, &eidx);
|
||||
}
|
||||
}
|
||||
#ifdef PARANOID
|
||||
|
|
@ -1658,24 +1697,25 @@ ResSortByGate(DevpointerList)
|
|||
*/
|
||||
|
||||
void
|
||||
ResWriteLumpFile(node)
|
||||
ResWriteLumpFile(node, resisdata)
|
||||
ResExtNode *node;
|
||||
ResisData *resisdata;
|
||||
{
|
||||
int lumpedres;
|
||||
|
||||
if (ResOptionsFlags & ResOpt_Tdi)
|
||||
{
|
||||
if (gparams.rg_nodecap != 0)
|
||||
if (resisdata->rg_nodecap != 0)
|
||||
{
|
||||
lumpedres = (int)((gparams.rg_Tdi / gparams.rg_nodecap
|
||||
- (float)(gparams.rg_bigdevres)) / OHMSTOMILLIOHMS);
|
||||
lumpedres = (int)((resisdata->rg_Tdi / resisdata->rg_nodecap
|
||||
- (float)(resisdata->rg_bigdevres)) / OHMSTOMILLIOHMS);
|
||||
}
|
||||
else
|
||||
lumpedres = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lumpedres = gparams.rg_maxres;
|
||||
lumpedres = resisdata->rg_maxres;
|
||||
}
|
||||
fprintf(ResLumpFile, "R %s %d\n", node->name, lumpedres);
|
||||
}
|
||||
|
|
@ -1752,35 +1792,37 @@ ResAlignNodes(nodelist, reslist)
|
|||
*/
|
||||
|
||||
int
|
||||
ResWriteExtFile(celldef, node, rctol, nidx, eidx)
|
||||
ResWriteExtFile(celldef, node, resisdata, nidx, eidx)
|
||||
CellDef *celldef;
|
||||
ResExtNode *node;
|
||||
float rctol;
|
||||
ResisData *resisdata;
|
||||
int *nidx, *eidx;
|
||||
{
|
||||
float RCdev;
|
||||
char *cp, newname[MAXNAME];
|
||||
devPtr *ptr;
|
||||
resDevice *layoutDev, *ResGetDevice();
|
||||
float rctol;
|
||||
|
||||
RCdev = gparams.rg_bigdevres * gparams.rg_nodecap;
|
||||
rctol = resisdata->tdiTolerance;
|
||||
RCdev = resisdata->rg_bigdevres * resisdata->rg_nodecap;
|
||||
|
||||
if ((node->status & FORCE) ||
|
||||
(ResOptionsFlags & ResOpt_ExtractAll) ||
|
||||
(ResOptionsFlags & ResOpt_Simplify) == 0 ||
|
||||
(rctol + 1) * RCdev < rctol * gparams.rg_Tdi)
|
||||
(rctol + 1) * RCdev < rctol * resisdata->rg_Tdi)
|
||||
{
|
||||
ASSERT(gparams.rg_Tdi != -1, "ResWriteExtFile");
|
||||
ASSERT(resisdata->rg_Tdi != -1, "ResWriteExtFile");
|
||||
(void)sprintf(newname,"%s", node->name);
|
||||
cp = newname + strlen(newname)-1;
|
||||
if (*cp == '!' || *cp == '#') *cp = '\0';
|
||||
if ((rctol + 1) * RCdev < rctol * gparams.rg_Tdi ||
|
||||
if ((rctol + 1) * RCdev < rctol * resisdata->rg_Tdi ||
|
||||
(ResOptionsFlags & ResOpt_Tdi) == 0)
|
||||
{
|
||||
if ((ResOptionsFlags & (ResOpt_RunSilent | ResOpt_Tdi)) == ResOpt_Tdi)
|
||||
{
|
||||
TxPrintf("Adding %s; Tnew = %.2fns, Told = %.2fns\n",
|
||||
node->name, gparams.rg_Tdi / Z_TO_P, RCdev / Z_TO_P);
|
||||
node->name, resisdata->rg_Tdi / Z_TO_P, RCdev / Z_TO_P);
|
||||
}
|
||||
}
|
||||
for (ptr = node->firstDev; ptr != NULL; ptr=ptr->nextDev)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "utils/stack.h"
|
||||
#include "utils/tech.h"
|
||||
#include "textio/txcommands.h"
|
||||
#include "resis/resis.h"
|
||||
#include "resis/resis.h"
|
||||
|
||||
#define MILLIOHMSPEROHM 1000
|
||||
|
||||
|
|
@ -842,24 +842,26 @@ ResPruneTree(node, minTdi, nodelist1, nodelist2, resistorlist)
|
|||
*/
|
||||
|
||||
int
|
||||
ResDoSimplify(tolerance, rctol, goodies)
|
||||
float tolerance;
|
||||
float rctol;
|
||||
ResGlobalParams *goodies;
|
||||
ResDoSimplify(tolerance,resisdata)
|
||||
float tolerance;
|
||||
ResisData *resisdata;
|
||||
|
||||
{
|
||||
resNode *node, *slownode;
|
||||
float bigres = 0;
|
||||
float millitolerance;
|
||||
float totalcap;
|
||||
float rctol;
|
||||
resResistor *res;
|
||||
|
||||
ResSetPathRes();
|
||||
rctol = resisdata->tdiTolerance;
|
||||
ResSetPathRes(resisdata);
|
||||
|
||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||
bigres = MAX(bigres, node->rn_noderes);
|
||||
|
||||
bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */
|
||||
goodies->rg_maxres = bigres;
|
||||
resisdata->rg_maxres = bigres;
|
||||
|
||||
#ifdef PARANOID
|
||||
ResSanityChecks("ExtractSingleNet", ResResList, ResNodeList, ResDevList);
|
||||
|
|
@ -870,7 +872,7 @@ ResDoSimplify(tolerance, rctol, goodies)
|
|||
/* we're calculating lumped values so that the capacitance */
|
||||
/* values get calculated correctly. */
|
||||
|
||||
(void) ResDistributeCapacitance(ResNodeList, goodies->rg_nodecap);
|
||||
(void) ResDistributeCapacitance(ResNodeList, resisdata->rg_nodecap);
|
||||
|
||||
if (((tolerance > bigres) || ((ResOptionsFlags & ResOpt_Simplify) == 0)) &&
|
||||
((ResOptionsFlags & ResOpt_DoLumpFile) == 0))
|
||||
|
|
@ -895,43 +897,48 @@ ResDoSimplify(tolerance, rctol, goodies)
|
|||
------*/
|
||||
}
|
||||
|
||||
if (ResOptionsFlags & ResOpt_Tdi)
|
||||
if (ResOriginNode == NULL)
|
||||
{
|
||||
if (goodies->rg_nodecap != -1 &&
|
||||
TxError("Error: Network simplification: Failed to to get origin node.\n");
|
||||
resisdata->rg_Tdi = 0;
|
||||
}
|
||||
else if (ResOptionsFlags & ResOpt_Tdi)
|
||||
{
|
||||
if ((resisdata->rg_nodecap != -1) &&
|
||||
(totalcap = ResCalculateChildCapacitance(ResOriginNode)) != -1)
|
||||
{
|
||||
RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client;
|
||||
RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client;
|
||||
|
||||
goodies->rg_nodecap = totalcap;
|
||||
resisdata->rg_nodecap = totalcap;
|
||||
ResCalculateTDi(ResOriginNode, (resResistor *)NULL,
|
||||
goodies->rg_bigdevres);
|
||||
resisdata->rg_bigdevres);
|
||||
if (rc != (RCDelayStuff *)NULL)
|
||||
goodies->rg_Tdi = rc->rc_Tdi;
|
||||
resisdata->rg_Tdi = rc->rc_Tdi;
|
||||
else
|
||||
goodies->rg_Tdi = 0;
|
||||
resisdata->rg_Tdi = 0;
|
||||
|
||||
slownode = ResNodeList;
|
||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||
{
|
||||
rc = (RCDelayStuff *)node->rn_client;
|
||||
if ((rc != NULL) && (goodies->rg_Tdi < rc->rc_Tdi))
|
||||
if ((rc != NULL) && (resisdata->rg_Tdi < rc->rc_Tdi))
|
||||
{
|
||||
slownode = node;
|
||||
goodies->rg_Tdi = rc->rc_Tdi;
|
||||
resisdata->rg_Tdi = rc->rc_Tdi;
|
||||
}
|
||||
}
|
||||
slownode->rn_status |= RN_MAXTDI;
|
||||
}
|
||||
else
|
||||
goodies->rg_Tdi = -1;
|
||||
resisdata->rg_Tdi = -1;
|
||||
}
|
||||
else
|
||||
goodies->rg_Tdi = 0;
|
||||
resisdata->rg_Tdi = 0;
|
||||
|
||||
if ((rctol+1) * goodies->rg_bigdevres * goodies->rg_nodecap >
|
||||
rctol * goodies->rg_Tdi &&
|
||||
if ((rctol+1) * resisdata->rg_bigdevres * resisdata->rg_nodecap >
|
||||
rctol * resisdata->rg_Tdi &&
|
||||
(ResOptionsFlags & ResOpt_Tdi) &&
|
||||
goodies->rg_Tdi != -1)
|
||||
resisdata->rg_Tdi != -1)
|
||||
return 0;
|
||||
|
||||
/* Simplify network; resistors are still in milliohms, so use
|
||||
|
|
@ -960,11 +967,11 @@ ResDoSimplify(tolerance, rctol, goodies)
|
|||
/* have time constants less than the tolerance. */
|
||||
|
||||
if ((ResOptionsFlags & ResOpt_Tdi) &&
|
||||
goodies->rg_Tdi != -1 &&
|
||||
resisdata->rg_Tdi != -1 &&
|
||||
rctol != 0)
|
||||
{
|
||||
ResPruneTree(ResOriginNode, (rctol + 1) *
|
||||
goodies->rg_bigdevres * goodies->rg_nodecap / rctol,
|
||||
resisdata->rg_bigdevres * resisdata->rg_nodecap / rctol,
|
||||
&ResNodeList, &ResNodeQueue, &ResResList);
|
||||
}
|
||||
ResOriginNode->rn_status &= ~MARKED;
|
||||
|
|
@ -999,7 +1006,7 @@ ResDoSimplify(tolerance, rctol, goodies)
|
|||
*/
|
||||
|
||||
void
|
||||
ResSetPathRes()
|
||||
ResSetPathRes(ResisData *resisdata)
|
||||
{
|
||||
HeapEntry he;
|
||||
resNode *node;
|
||||
|
|
@ -1026,7 +1033,15 @@ ResSetPathRes()
|
|||
}
|
||||
if (ResOriginNode == NULL)
|
||||
{
|
||||
resDevice *res = ResGetDevice(gparams.rg_devloc, gparams.rg_ttype);
|
||||
resDevice *res = ResGetDevice(resisdata->rg_devloc, resisdata->rg_ttype);
|
||||
if (res == (resDevice *)NULL)
|
||||
{
|
||||
TxError("Error: No device type %s found at location %s %s\n",
|
||||
DBTypeLongNameTbl[resisdata->rg_ttype],
|
||||
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
|
||||
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
|
||||
return;
|
||||
}
|
||||
ResOriginNode = res->rd_fet_source;
|
||||
ResOriginNode->rn_why = RES_NODE_ORIGIN;
|
||||
ResOriginNode->rn_noderes = 0;
|
||||
|
|
|
|||
|
|
@ -244,25 +244,6 @@ typedef struct resdevtile
|
|||
int overlap;
|
||||
} ResDevTile;
|
||||
|
||||
/*
|
||||
Goodies contains random stuff passed between the node extractor
|
||||
and ResCheckExtNodes. The location of a start tile and the resistive
|
||||
tolerance are passed down, while the derived network is passed back.
|
||||
*/
|
||||
|
||||
typedef struct goodstuff
|
||||
{
|
||||
TileType rg_ttype;
|
||||
float rg_maxres;
|
||||
float rg_nodecap;
|
||||
float rg_Tdi;
|
||||
int rg_bigdevres;
|
||||
int rg_tilecount;
|
||||
int rg_status;
|
||||
Point *rg_devloc;
|
||||
char *rg_name;
|
||||
} ResGlobalParams;
|
||||
|
||||
/* Linked list structure to use to store the substrate plane from each */
|
||||
/* extracted CellDef so that they can be returned to the original after */
|
||||
/* extraction. */
|
||||
|
|
@ -275,13 +256,31 @@ struct saveList {
|
|||
|
||||
/* Structure stores information required to be sent to ExtResisForDef() */
|
||||
|
||||
typedef struct
|
||||
typedef struct resoptions
|
||||
{
|
||||
/* Global options for extresist */
|
||||
|
||||
float tdiTolerance;
|
||||
float frequency;
|
||||
float rthresh;
|
||||
struct saveList *savePlanes;
|
||||
CellDef *mainDef;
|
||||
|
||||
/*
|
||||
* Various information passed between the node extractor and
|
||||
* ResCheckExtNodes. The location of a start tile and the resistive
|
||||
* tolerance are passed down, while the derived network is passed back.
|
||||
*/
|
||||
|
||||
TileType rg_ttype;
|
||||
float rg_maxres;
|
||||
float rg_nodecap;
|
||||
float rg_Tdi;
|
||||
int rg_bigdevres;
|
||||
int rg_tilecount;
|
||||
int rg_status;
|
||||
Point *rg_devloc;
|
||||
char *rg_name;
|
||||
} ResisData;
|
||||
|
||||
/* Structure used in RC delay calculations for Tdi filter. */
|
||||
|
|
@ -546,10 +545,10 @@ extern TileTypeBitMask ResSDTypesBitMask;
|
|||
extern TileTypeBitMask ResSubTypesBitMask;
|
||||
extern HashTable ResDevTable;
|
||||
extern TileTypeBitMask ResNoMergeMask[NT];
|
||||
extern ResGlobalParams gparams;
|
||||
extern int ResPortIndex;
|
||||
|
||||
/* Routines used by ResReadExt() */
|
||||
extern ResisData *ResInit();
|
||||
extern int ResReadDevice();
|
||||
extern int ResReadCapacitor();
|
||||
extern int ResReadResistor();
|
||||
|
|
@ -576,6 +575,12 @@ extern void ResSortBreaks();
|
|||
extern Plane *extResPrepSubstrate();
|
||||
|
||||
/* C99 compat */
|
||||
extern void ExtResisForDef(CellDef *celldef, ResisData *resisdata);
|
||||
extern char *ResExtGetAttribute(char *sptr);
|
||||
extern int ResReadFET(int argc, char *argv[]);
|
||||
extern int ResReadPort(int argc, char *argv[]);
|
||||
extern char *ResExtGetAttribute(char *sptr);
|
||||
|
||||
extern void ResAddToQueue();
|
||||
extern bool ResCalcTileResistance();
|
||||
extern void ResCleanNode();
|
||||
|
|
@ -597,7 +602,7 @@ extern void ResPrintReference();
|
|||
extern void ResPrintResistorList();
|
||||
extern void ResPrintStats();
|
||||
extern void ResProcessJunction();
|
||||
extern int ResReadNode();
|
||||
extern ResExtNode *ResReadNode(int argc, char *argv[]);
|
||||
extern int ResReadExt();
|
||||
extern void ResRemoveFromQueue();
|
||||
extern int ResExtNewNode();
|
||||
|
|
|
|||
Loading…
Reference in New Issue