diff --git a/ext2sim/ext2sim.c b/ext2sim/ext2sim.c index bc98475d..d5b96c5a 100644 --- a/ext2sim/ext2sim.c +++ b/ext2sim/ext2sim.c @@ -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" diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 2f6ed027..4a4c54a1 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -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; diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 1e08a484..f494e8d0 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -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" diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index a9ca61c7..fed2f975 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -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 */ diff --git a/extflat/EFerr.c b/extflat/EFerr.c index c69d3bf5..b5eb511d 100644 --- a/extflat/EFerr.c +++ b/extflat/EFerr.c @@ -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(); diff --git a/extflat/EFread.c b/extflat/EFread.c index 1a7c70fc..e4c2253e 100644 --- a/extflat/EFread.c +++ b/extflat/EFread.c @@ -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 */ diff --git a/extflat/extflat.h b/extflat/extflat.h index 0dc740fc..b85b858c 100644 --- a/extflat/extflat.h +++ b/extflat/extflat.h @@ -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 */ diff --git a/extflat/extparse.h b/extflat/extparse.h index 55944622..a688bde7 100644 --- a/extflat/extparse.h +++ b/extflat/extparse.h @@ -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 */ diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index bda0a076..3aeb18d4 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -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 ".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; diff --git a/extract/ExtCell.c b/extract/ExtCell.c index 26fa5cb9..0cdc396c 100644 --- a/extract/ExtCell.c +++ b/extract/ExtCell.c @@ -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 ".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) diff --git a/resis/ResMain.c b/resis/ResMain.c index dcfc14f7..dc9979e4 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -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); } diff --git a/resis/ResPrint.c b/resis/ResPrint.c index 4f03d9e3..08acf785 100644 --- a/resis/ResPrint.c +++ b/resis/ResPrint.c @@ -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); diff --git a/resis/ResReadExt.c b/resis/ResReadExt.c index b792cffb..5bd5df68 100644 --- a/resis/ResReadExt.c +++ b/resis/ResReadExt.c @@ -19,6 +19,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include #include "utils/magic.h" +#include "utils/main.h" #include "utils/geometry.h" #include "utils/geofast.h" #include "tiles/tile.h" @@ -29,6 +30,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "extract/extract.h" #include "extract/extractInt.h" #include "extflat/extflat.h" +#include "extflat/extparse.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "utils/utils.h" @@ -36,50 +38,54 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "textio/txcommands.h" #include "resis/resis.h" -/* constants defining where various fields can be found in .ext files. */ -/* (FIXME---Needs to be changed to positions in .ext files) */ +/* constants defining where various fields can be found in .ext files. */ +/* The value corresponds to the argument number on the list after */ +/* parsing by efReadLine(). */ -#define RDEV_LENGTH 4 -#define RDEV_WIDTH 5 -#define RDEV_DEVX 6 -#define RDEV_DEVY 7 -#define RDEV_ATTR 8 -#define RDEV_NUM_ATTR 3 -#define RESNODENAME 1 -#define NODERESISTANCE 2 -#define COUPLETERMINAL1 1 -#define COUPLETERMINAL2 2 -#define COUPLEVALUE 3 -#define REALNAME 1 -#define ALIASNAME 2 -#define NODES_NODENAME 0 -#define NODES_NODEX 1 -#define NODES_NODEY 2 -#define NODES_NODETYPE 3 -#define NODE_BBOX_LL_X 5 -#define NODE_BBOX_LL_Y 6 -#define NODE_BBOX_UR_X 7 -#define NODE_BBOX_UR_Y 8 -#define NODELAMBDA 2 -#define NODEUNITS 1 -#define ATTRIBUTENODENAME 1 -#define ATTRIBUTEVALUE 2 +#define FET_NAME 1 +#define FET_X 2 +#define FET_Y 3 +#define FET_AREA 4 +#define FET_PERIM 5 +#define FET_SUBS 6 +#define FET_GATE 7 +#define FET_GATE_ATTR 9 +#define FET_SOURCE 10 +#define FET_SOURCE_ATTR 12 +#define FET_DRAIN 13 +#define FET_DRAIN_ATTR 15 + +#define DEV_NAME 2 +#define DEV_X 3 +#define DEV_Y 4 + +#define NODES_NODENAME 1 +#define NODES_NODEX 4 +#define NODES_NODEY 5 +#define NODES_NODETYPE 6 + +#define COUPLETERMINAL1 1 +#define COUPLETERMINAL2 2 +#define COUPLEVALUE 3 -#define RES_EXT_ATTR 0 #define RES_EXT_ATTR_NAME 1 #define RES_EXT_ATTR_X 2 #define RES_EXT_ATTR_Y 3 -#define RES_EXT_ATTR_TILE 6 +#define RES_EXT_ATTR_TYPE 6 #define RES_EXT_ATTR_TEXT 7 -#define MAXTOKEN 1024 -#define MAXLINE 40 +#define PORT_NAME 1 +#define PORT_LLX 3 +#define PORT_LLY 4 +#define PORT_URX 5 +#define PORT_URY 6 +#define PORT_TYPE 7 + #define MAXDIGIT 20 ResExtNode *ResInitializeNode(); ResExtNode *ResOriginalNodes; /*Linked List of Nodes */ -static float resscale = 1.0; /* Scale factor */ char RDEV_NOATTR[1] = {'0'}; ResFixPoint *ResFixList; @@ -96,27 +102,49 @@ ResFixPoint *ResFixList; */ int -ResReadExt(char *extfile); +ResReadExt(char *extfile) { char *line = NULL, *argv[128]; - int result, fettype, readdrivepoints; - int size = 0; + int result, locresult; + int argc, n, size = 0; FILE *fp; + CellDef *dbdef; + ResExtNode *curnode; + + /* Search for the .ext fie in the same way that efReadDef() does. */ fp = PaOpen(extfile, "r", ".ext", EFSearchPath, EFLibPath, (char **)NULL); + if ((fp == NULL) && (dbdef = DBCellLookDef(extfile)) != NULL) + { + char *filepath, *sptr; + + filepath = StrDup((char **)NULL, dbdef->cd_file); + sptr = strrchr(filepath, '/'); + if (sptr) + { + *sptr = '\0'; + fp = PaOpen(extfile, "r", ".ext", filepath, EFLibPath, (char **)NULL); + } + freeMagic(filepath); + } + + /* Try with the standard search path */ + if ((fp == NULL) && (EFSearchPath == NULL)) + fp = PaOpen(extfile, "r", ".ext", Path, EFLibPath, (char **)NULL); + if (fp == NULL) { TxError("Cannot open file %s%s\n", extfile, ".ext"); return 1; } - readdrivepoints = FALSE; /* Read in the file. Makes use of various functions * from extflat, mostly in EFread.c. */ - EFSaveLocs = False; + EFSaveLocs = FALSE; efReadLineNum = 0; + result = 0; while ((argc = efReadLine(&line, &size, fp, argv)) >= 0) { @@ -137,35 +165,33 @@ ResReadExt(char *extfile); */ switch (keyTable[n].k_key) { - case SCALE: - resscale = (float)atof(argv[1]); - if (resscale == 0.0) resscale = 1.0; - break; case DEVICE: - ResReadSubckt(argc, argv); + locresult = ResReadDevice(argc, argv); break; case FET: - ResReadDevice(argc, argv); + locresult = ResReadFET(argc, argv); break; case MERGE: - ResReadDrivePoint(argc, argv); + /* To be completed */ + /* ResReadDrivePoint(argc, argv); */ break; case NODE: case SUBSTRATE: - ResReadNode(argc, argv); + curnode = ResReadNode(argc, argv); break; case PORT: - ResReadPort(argc, argv); + locresult = ResReadPort(argc, argv); break; case ATTR: - result = ResExtAttribute(curnodename, - argv[1], &readdrivepoints); + locresult = ResReadAttribute(curnode, argc, argv); + break; + case CAP: + locresult = ResReadCapacitor(argc, argv); break; default: break; - - /* to do: Handle CAP, RESISTOR, maybe others? */ } + if (locresult == 1) result = 1; } fclose(fp); return(result); @@ -175,10 +201,45 @@ ResReadExt(char *extfile); /* *------------------------------------------------------------------------- * - * ResReadNode-- Reads in a node file, puts location of nodes into node - * structures. + * ResReadNode-- Reads in a node statement, puts location and type of + * node into a node structure. * - * Results: 0 if the node was read correctly, 1 otherwise. + * Results: Pointer to the node record if the node was read correctly, + * NULL otherwise. + * + * Side Effects: see above + * + *------------------------------------------------------------------------- + */ + +ResExtNode * +ResReadNode(int argc, char *argv[]) +{ + HashEntry *entry; + ResExtNode *node; + + entry = HashFind(&ResNodeTable, argv[NODES_NODENAME]); + node = ResInitializeNode(entry); + + node->location.p_x = atoi(argv[NODES_NODEX]); + node->location.p_y = atoi(argv[NODES_NODEY]); + node->type = DBTechNameType(argv[NODES_NODETYPE]); + + if (node->type == -1) + { + TxError("Bad tile type name in .ext file for node %s\n", node->name); + return NULL; + } + return node; +} + +/* + *------------------------------------------------------------------------- + * + * ResReadPort-- Reads in a port statement from the .ext file and sets + * node records accordingly to mark the node as a drivepoint. + * + * Results: 0 if successful and 1 otherwise. * * Side Effects: see above * @@ -186,366 +247,255 @@ ResReadExt(char *extfile); */ int -ResReadNode(int argc, char *argv[]) +ResReadPort(int argc, + char *argv[]) { HashEntry *entry; ResExtNode *node; - char *cp; - float lambda; - entry = HashFind(&ResNodeTable, line[NODES_NODENAME]); + entry = HashFind(&ResNodeTable, argv[PORT_NAME]); node = ResInitializeNode(entry); - node->location.p_x = atoi(line[NODES_NODEX]); - node->location.p_y = atoi(line[NODES_NODEY]); - if ((cp = strchr(line[NODES_NODETYPE], ';'))) *cp = '\0'; - node->type = DBTechNameType(line[NODES_NODETYPE]); + node->drivepoint.p_x = atoi(argv[PORT_LLX]); + node->drivepoint.p_y = atoi(argv[PORT_LLY]); + node->status |= FORCE; + /* To do: Check for multiple ports on a net; each port needs its + * own drivepoint. + */ + node->status |= DRIVELOC | PORTNODE; + node->rs_bbox.r_ll = node->drivepoint; + node->rs_bbox.r_ur.p_x = atoi(argv[PORT_URX]); + node->rs_bbox.r_ur.p_y = atoi(argv[PORT_URY]); + node->rs_ttype = DBTechNoisyNameType(argv[PORT_TYPE]); + node->type = node->rs_ttype; if (node->type == -1) { - TxError("Bad tile type name in .ext file for node %s\n", - node->name); + TxError("Bad tile type name in .ext file for node %s\n", node->name); return 1; } return 0; } +/* + *------------------------------------------------------------------------- + * + * ResNodeAddDevice -- + * + * Given a device and a node which connects to one of its terminals, + * add the device to the node's device list. Device type is one + * of the indexes defined by GATE, SOURCE, or DRAIN (to do: generalize + * this). + * + * Results: + * None. + * + * Side effects: + * Allocates memory for a devPtr, adds to the node's firstDev linked + * list. + * + *------------------------------------------------------------------------- + */ + +void +ResNodeAddDevice(ResExtNode *node, + RDev *device, + int termtype) +{ + devPtr *tptr; + + tptr = (devPtr *)mallocMagic((unsigned)(sizeof(devPtr))); + tptr->thisDev = device; + tptr->nextDev = node->firstDev; + node->firstDev = tptr; + tptr->terminal = termtype; +} + +/* + *------------------------------------------------------------------------- + * + * ResReadDevice-- + * + * Process a "device" line from a ext file. + * + * Results: returns 0 if line was added correctly. + * + * Side Effects: Allocates devicesl + * + *------------------------------------------------------------------------- + */ + +int +ResReadDevice(int argc, + char *argv[]) +{ + RDev *device; + int rvalue, i, j, k; + ExtDevice *devptr; + TileType ttype; + HashEntry *entry; + ResExtNode *node; + + device = (RDev *)mallocMagic((unsigned)(sizeof(RDev))); + + device->resistance = 0; /* Linear resistance from FET line, unused */ + + device->status = FALSE; + device->nextDev = ResRDevList; + + /* Find the device definition record corresponding to the device name */ + devptr = (ExtDevice *)NULL; + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + { + for (devptr = ExtCurStyle->exts_device[ttype]; devptr; + devptr = devptr->exts_next) + if (!strcmp(devptr->exts_deviceName, argv[DEV_NAME])) break; + if (devptr != NULL) break; + } + + device->location.p_x = atoi(argv[DEV_X]); + device->location.p_y = atoi(argv[DEV_Y]); + + device->rs_gattr = RDEV_NOATTR; + device->rs_sattr = RDEV_NOATTR; + device->rs_dattr = RDEV_NOATTR; + device->rs_devptr = devptr; + + device->source = (ResExtNode *)NULL; + device->drain = (ResExtNode *)NULL; + device->subs = (ResExtNode *)NULL; + + /* Pass over parameters and find the next argument */ + for (i = DEV_Y; i < argc; i++) + if (!StrIsInt(argv[i]) && !(strchr(argv[i], '='))) + break; + + if (i == argc) + { + TxError("Bad device %s: Too few arguments in .ext file\n", + argv[DEV_NAME]); + return 1; + } + + /* Find and record the device terminal nodes */ + /* Note that this only records up to two terminals matching FET + * source and drain; it needs to be expanded to include an + * arbitrary number of terminals. + */ + + if (strcmp(argv[i], "None")) + { + entry = HashFind(&ResNodeTable, argv[i]); + device->subs = (ResExtNode *)HashGetValue(entry); + ResNodeAddDevice(device->subs, device, SUBS); + } + i++; + entry = HashFind(&ResNodeTable, argv[i]); + device->gate = (ResExtNode *)HashGetValue(entry); + device->rs_gattr = StrDup((char **)NULL, argv[i + 2]); + ResNodeAddDevice(device->gate, device, GATE); + i += 3; + + if (i < argc - 2) + { + entry = HashFind(&ResNodeTable, argv[i]); + device->source = (ResExtNode *)HashGetValue(entry); + device->rs_sattr = StrDup((char **)NULL, argv[i + 2]); + ResNodeAddDevice(device->source, device, SOURCE); + i += 3; + } + + if (i < argc - 2) + { + entry = HashFind(&ResNodeTable, argv[i]); + device->drain = (ResExtNode *)HashGetValue(entry); + device->rs_dattr = StrDup((char **)NULL, argv[i + 2]); + ResNodeAddDevice(device->drain, device, DRAIN); + i += 3; + } + if (i < argc - 2) + { + TxError("Warning: Device %s has more than 4 ports (not handled).\n", + argv[DEV_NAME]); + } + + device->rs_ttype = extGetDevType(devptr->exts_deviceName); + + ResRDevList = device; + device->layout = NULL; + return 0; +} /* *------------------------------------------------------------------------- * - * ResReadSubckt-- Processes a subcircuit line from a ext file. - * This uses the "user subcircuit" extension defined in - * IRSIM, although it is mostly intended as a way to work - * around the device type limitations of the .ext format - * when using extresist. + * ResReadFET-- Processes a "fet" line from a ext file. * * Results: returns 0 if line was added correctly. * - * Side Effects: Allocates devices and adds nodes to the node hash table. + * Side Effects: Allocates devices. * *------------------------------------------------------------------------- */ int -ResReadSubckt(line) - char line[][MAXTOKEN]; +ResReadFET(int argc, + char *argv[]) { RDev *device; int rvalue, i, j, k; - static int nowarning = TRUE; - float lambda; - TileType ttype = TT_SPACE; - char *lptr = NULL, *wptr = NULL; ExtDevice *devptr; - - device = (RDev *) mallocMagic((unsigned) (sizeof(RDev))); - - device->status = FALSE; - device->nextDev = ResRDevList; - - lambda = (float)ExtCurStyle->exts_unitsPerLambda / resscale; - device->location.p_x = 0; - device->location.p_y = 0; - - device->rs_gattr=RDEV_NOATTR; - device->rs_sattr=RDEV_NOATTR; - device->rs_dattr=RDEV_NOATTR; - - ResRDevList = device; - device->layout = NULL; - device->source = device->drain = device->gate = device->subs = NULL; - - /* The last argument is the name of the device */ - for (i = 1; line[i][0] != '\0'; i++); - i--; - - /* To do: Replace this search with a pre-prepared hash */ - /* table to key off of the device name. */ - for (j = 0; j < EFDevNumTypes; j++) - if (!strcmp(EFDevTypes[j], line[i])) - break; - - /* Read attributes, especially to pick up values for L, W, X, and Y; - * and source and drain area and perimeter, that are critical for use - * by extresist. - */ - for (k = 1; line[k][0] != '\0'; k++) - { - char *eqptr; - eqptr = strchr(line[k], '='); - if (eqptr != NULL) - { - if (k < i) i = k; - eqptr++; - switch (line[k][0]) { - case 'l': - lptr = eqptr; - break; - case 'w': - wptr = eqptr; - break; - case 'x': - device->location.p_x = (int)((float)atof(eqptr) / lambda); - break; - case 'y': - device->location.p_y = (int)((float)atof(eqptr) / lambda); - break; - case 's': - device->rs_sattr = StrDup((char **)NULL, eqptr); - break; - case 'd': - device->rs_dattr = StrDup((char **)NULL, eqptr); - break; - } - } - } - - if (j == EFDevNumTypes) - { - TxError("Failure to find device type %s\n", line[i]); - return 1; - } - ttype = extGetDevType(EFDevTypes[j]); - ASSERT(ttype >= 0, "ttype<0"); - - /* Find the device record that corresponds to the device name */ - for (devptr = ExtCurStyle->exts_device[ttype]; devptr; devptr = devptr->exts_next) - if (!strcmp(devptr->exts_deviceName, EFDevTypes[j])) - break; - - device->rs_devptr = devptr; - device->rs_ttype = ttype; - - if (lptr != NULL && wptr != NULL) - { - HashEntry *he; - float rpersquare; - - he = HashLookOnly(&devptr->exts_deviceResist, "linear"); - if (he != NULL) - rpersquare = (ResValue)(spointertype)HashGetValue(he); - else - rpersquare = (ResValue)0.0; - /* Subcircuit types may not have a length or width value, in which */ - /* case it is zero. Don't induce a divide-by-zero error. */ - if (MagAtof(wptr) == 0) - device->resistance = 0; - else - device->resistance = MagAtof(lptr) * rpersquare/MagAtof(wptr); - } - else - device->resistance = 0; - - rvalue = 0; - for (k = 1; k < i; k++) - { - if (k > SUBS) - { - TxError("Device %s has more than 4 ports (not handled).\n", line[i]); - break; /* No method to handle more ports than this */ - } - rvalue += ResExtNewNode(line[k], k, device); - } - - return rvalue; -} - -/* - *------------------------------------------------------------------------- - * - * ResReadDevice-- Processes a device line from a ext file. - * - * Results: returns 0 if line was added correctly. - * - * Side Effects: Allocates devices and adds nodes to the node hash table. - * - *------------------------------------------------------------------------- - */ - -int -ResReadDevice(line, rpersquare, devptr) - char line[][MAXTOKEN]; - float rpersquare; - ExtDevice *devptr; - -{ - RDev *device; - int rvalue, i, j, k; - char *newattr, tmpattr[MAXTOKEN]; - static int nowarning = TRUE; - float lambda; - ExtDevice *devtest; - - if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0')) - { - TxError("error in input file:\n"); - return 1; - } + TileType ttype; + HashEntry *entry; + ResExtNode *node; device = (RDev *)mallocMagic((unsigned)(sizeof(RDev))); - if (nowarning && rpersquare == 0) - { - TxError("Warning: FET resistance not included or " - "set to zero in technology file-\n"); - TxError("All driven nodes will be extracted\n"); - nowarning = FALSE; - } - if (MagAtof(line[RDEV_WIDTH]) != 0) - device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare / - MagAtof(line[RDEV_WIDTH]); - else - device->resistance = 0; + + device->resistance = 0; /* Linear resistance from FET line, unused */ device->status = FALSE; device->nextDev = ResRDevList; - /* Check that devptr matches the device name and number of terminals */ - /* Note that this routine is only called for the original "fet" */ - /* types with fixed names, so the names must match and there must */ - /* always be three terminals (two source/drain terminals). */ + /* Find the device definition record corresponding to the device name */ + devptr = (ExtDevice *)NULL; + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + { + for (devptr = ExtCurStyle->exts_device[ttype]; devptr; + devptr = devptr->exts_next) + if (!strcmp(devptr->exts_deviceName, argv[FET_NAME])) break; + if (devptr != NULL) break; + } - if (devptr->exts_deviceSDCount != 2) - for (devtest = devptr->exts_next; devtest; devtest = devtest->exts_next) - if (devtest->exts_deviceSDCount == 2) - { - devptr = devtest; - break; - } - - lambda = (float)ExtCurStyle->exts_unitsPerLambda / resscale; - device->location.p_x = (int)((float)atof(line[RDEV_DEVX]) / lambda); - device->location.p_y = (int)((float)atof(line[RDEV_DEVY]) / lambda); + device->location.p_x = atoi(argv[FET_X]); + device->location.p_y = atoi(argv[FET_Y]); device->rs_gattr=RDEV_NOATTR; device->rs_sattr=RDEV_NOATTR; device->rs_dattr=RDEV_NOATTR; device->rs_devptr = devptr; - device->gate = device->source = device->drain = device->subs = NULL; + /* Find and record the FET terminal nodes */ + + entry = HashFind(&ResNodeTable, argv[FET_GATE]); + device->gate = (ResExtNode *)HashGetValue(entry); + + entry = HashFind(&ResNodeTable, argv[FET_SOURCE]); + device->source = (ResExtNode *)HashGetValue(entry); + + entry = HashFind(&ResNodeTable, argv[FET_DRAIN]); + device->drain = (ResExtNode *)HashGetValue(entry); + + entry = HashFind(&ResNodeTable, argv[FET_SUBS]); + device->subs = (ResExtNode *)HashGetValue(entry); device->rs_ttype = extGetDevType(devptr->exts_deviceName); - /* ext attributes look like g=a1,a2 */ - /* ext attributes are "a1","a2" */ - /* Do conversion from one to the other here */ - /* NOTE: As of version 8.3.366, .ext attributes will end in two */ - /* integer values, not quoted, for device area and perimeter. Do */ - /* not quote them. */ + /* Copy attributes verbatim */ + device->rs_gattr = StrDup((char **)NULL, argv[FET_GATE_ATTR]); + device->rs_sattr = StrDup((char **)NULL, argv[FET_SOURCE_ATTR]); + device->rs_dattr = StrDup((char **)NULL, argv[FET_DRAIN_ATTR]); - for (i = RDEV_ATTR; i < RDEV_ATTR + RDEV_NUM_ATTR; i++) - { - char *cptr, *sptr; - int d1, d2; - - if (line[i][0] == '\0') break; - - sptr = &line[i][2]; /* Start after "s=" or "d=" */ - tmpattr[0] = '\0'; - while ((cptr = strchr(sptr, ',')) != NULL) - { - if (sscanf(sptr, "%d,%d", &d1, &d2) == 2) - { - strcat(tmpattr, sptr); - sptr = NULL; - break; - } - else - { - *cptr = '\0'; - strcat(tmpattr, "\""); - strcat(tmpattr, sptr); - strcat(tmpattr, "\","); - sptr = cptr + 1; - *cptr = ','; - } - } - if (sptr && (strlen(sptr) != 0)) - { - strcat(tmpattr, "\""); - strcat(tmpattr, sptr); - strcat(tmpattr, "\""); - } - - newattr = (char *)mallocMagic(strlen(tmpattr) + 1); - strcpy(newattr, tmpattr); - switch (line[i][0]) - { - case 'g': - device->rs_gattr = newattr; - break; - case 's': - device->rs_sattr = newattr; - break; - case 'd': - device->rs_dattr = newattr; - break; - default: - TxError("Bad fet attribute\n"); - break; - } - } ResRDevList = device; device->layout = NULL; - rvalue = ResExtNewNode(line[GATE], GATE, device) + - ResExtNewNode(line[SOURCE], SOURCE, device) + - ResExtNewNode(line[DRAIN], DRAIN, device); - - return rvalue; -} - -/* - *------------------------------------------------------------------------- - * - * ResExtNewNode-- Adds a new node to the Node Hash Table. - * - * Results: returns zero if node is added correctly, one otherwise. - * - * Side Effects: Allocates a new ResExtNode - * - *------------------------------------------------------------------------- - */ - -int -ResExtNewNode(line, type, device) - char line[]; - int type; - RDev *device; - -{ - HashEntry *entry; - ResExtNode *node; - devPtr *tptr; - - if (line[0] == '\0') - { - TxError("Missing device connection\n"); - return 1; - } - entry = HashFind(&ResNodeTable, line); - node = ResInitializeNode(entry); - tptr = (devPtr *)mallocMagic((unsigned)(sizeof(devPtr))); - tptr->thisDev = device; - tptr->nextDev = node->firstDev; - node->firstDev = tptr; - tptr->terminal = type; - switch(type) - { - case GATE: - device->gate = node; - break; - case SOURCE: - device->source = node; - break; - case DRAIN: - device->drain = node; - break; - case SUBS: - device->subs = node; - break; - default: - TxError("Bad Terminal Specifier\n"); - break; - } return 0; } @@ -565,102 +515,36 @@ ResExtNewNode(line, type, device) */ int -ResReadCapacitor(line) - char line[][MAXTOKEN]; - +ResReadCapacitor(int argc, + char *argv[]) { HashEntry *entry1, *entry2; ResExtNode *node1, *node2; - if (line[COUPLETERMINAL1][0] == 0 || line[COUPLETERMINAL2][0] == 0) - { - TxError("Bad Capacitor\n"); - return(1); - } - entry1 = HashFind(&ResNodeTable, line[COUPLETERMINAL1]); + entry1 = HashFind(&ResNodeTable, argv[COUPLETERMINAL1]); node1 = ResInitializeNode(entry1); + if (ResOptionsFlags & ResOpt_Signal) { - node1->capacitance += MagAtof(line[COUPLEVALUE]); - if (strcmp(line[COUPLETERMINAL2], "GND") == 0 || - strcmp(line[COUPLETERMINAL2], "Vdd") == 0) - { - return 0; - } - entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]); + node1->capacitance += MagAtof(argv[COUPLEVALUE]); + entry2 = HashFind(&ResNodeTable, argv[COUPLETERMINAL2]); node2 = ResInitializeNode(entry2); - node2->capacitance += MagAtof(line[COUPLEVALUE]); + node2->capacitance += MagAtof(argv[COUPLEVALUE]); return 0; } - if (strcmp(line[COUPLETERMINAL2], "GND") == 0) - { - node1->capacitance += MagAtof(line[COUPLEVALUE]); - return 0; - } - if (strcmp(line[COUPLETERMINAL2], "Vdd") == 0) - { - node1->cap_vdd += MagAtof(line[COUPLEVALUE]); - return 0; - } - entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]); + + entry2 = HashFind(&ResNodeTable, argv[COUPLETERMINAL2]); node2 = ResInitializeNode(entry2); - if (strcmp(line[COUPLETERMINAL1], "GND") == 0) - { - node2->capacitance += MagAtof(line[COUPLEVALUE]); - return 0; - } - if (strcmp(line[COUPLETERMINAL1], "Vdd") == 0) - { - node2->cap_vdd += MagAtof(line[COUPLEVALUE]); - return 0; - } - node1->cap_couple += MagAtof(line[COUPLEVALUE]); - node2->cap_couple += MagAtof(line[COUPLEVALUE]); + + node1->cap_couple += MagAtof(argv[COUPLEVALUE]); + node2->cap_couple += MagAtof(argv[COUPLEVALUE]); return 0; } - /* *------------------------------------------------------------------------- * - * ResReadResistor-- Adds the capacitance from a R line to the appropriate - * node. - * - * Results - * Return 0 to keep search going, 1 to abort - * - * Side Effects: modifies resistance field of ResExtNode - * - *------------------------------------------------------------------------- - */ - -int -ResReadResistor(line) - char line[][MAXTOKEN]; -{ - HashEntry *entry; - ResExtNode *node; - - if (line[RESNODENAME][0] == 0) - { - TxError("Bad Resistor\n"); - return 1; - } - entry = HashFind(&ResNodeTable, line[RESNODENAME]); - node = ResInitializeNode(entry); - if (node->resistance != 0) - { - TxError("Duplicate Resistance Entries\n"); - return 1; - } - node->resistance = MagAtof(line[NODERESISTANCE]); - return(0); -} - -/* - *------------------------------------------------------------------------- - * - * ResExtAttribute--checks to see if a node attribute is a resistance + * ResReadAttribute--checks to see if a node attribute is a resistance * attribute. If it is, add it to the correct node's status flag. * Only works with 5.0 1/line attributes * @@ -673,25 +557,18 @@ ResReadResistor(line) */ int -ResReadAttribute(aname, avalue, readdrivepoints) - char *aname; - char *avalue; - bool *readdrivepoints; - +ResReadAttribute(ResExtNode *node, + int argc, + char *argv[]) { - HashEntry *entry; - ResExtNode *node; + char *aname, *avalue; char digit[MAXDIGIT]; int i; static int notwarned = TRUE; - if (aname[0] == 0) - { - TxError("Bad Resistor\n"); - return 1; - } - entry = HashFind(&ResNodeTable, aname); - node = ResInitializeNode(entry); + aname = argv[RES_EXT_ATTR_NAME]; + avalue = argv[RES_EXT_ATTR_TEXT]; + if (strncmp(avalue, "res:skip", 8) == 0) { if (node->status & FORCE) @@ -723,133 +600,14 @@ ResReadAttribute(aname, avalue, readdrivepoints) else if (strncmp(avalue, "res:drive", 9) == 0 && (ResOptionsFlags & ResOpt_Signal)) { - if (*readdrivepoints == FALSE) - { - ResExtProcessDrivePoints(rootname); - *readddrivepoints = TRUE; - } - /* is the attribute in root.ext? */ - if (node->drivepoint.p_x != INFINITY) - node->status |= DRIVELOC; - else - { - if (notwarned) - TxError("Drivepoint for %s not defined in %s.ext; is it " - "defined in a child cell?\n", node->name, rootname); - notwarned = FALSE; - } + node->drivepoint.p_x = atoi(argv[RES_EXT_ATTR_X]); + node->drivepoint.p_y = atoi(argv[RES_EXT_ATTR_Y]); + node->rs_ttype = DBTechNoisyNameType(argv[RES_EXT_ATTR_TYPE]); + node->status |= DRIVELOC; } return 0; } -/* - *------------------------------------------------------------------------- - * - * ResExtProcessDrivePoints -- if the ext file contains a res:drive attribute, - * and we are doing a signal extraction, - * we need to search through the .ext file looking for attr labels that - * contain this text. For efficiency, the .ext file is only parsed when - * the first res:drive is encountered. res:drive labels only work if - * they are in the root cell. - * - * FIXME---The .ext file is being read and this routine should only - * read in additional lines as necessary. - * - * Results: - * None. - * - * Side Effects: - * - *------------------------------------------------------------------------- - */ - -void -ResExtProcessDrivePoints(FILE *fp) -{ - char line[MAXLINE][MAXTOKEN]; - FILE *fp; - HashEntry *entry; - ResExtNode *node; - - while (gettokens(line, fp) != 0) - { - if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 || - strncmp(line[RES_EXT_ATTR_TEXT], "\"res:drive\"", 11) != 0) - continue; - - entry = HashFind(&ResNodeTable, line[RES_EXT_ATTR_NAME]); - node = ResInitializeNode(entry); - node->drivepoint.p_x = atoi(line[RES_EXT_ATTR_X]); - node->drivepoint.p_y = atoi(line[RES_EXT_ATTR_Y]); - node->rs_ttype = DBTechNoisyNameType(line[RES_EXT_ATTR_TILE]); - } - fclose(fp); -} - -/* - *------------------------------------------------------------------------- - * - * ResExtProcessFixPoints -- if the ext file contains a "res:fix:name" label - * and we are checking for power supply noise, then we have to - * parse the .ext file looking for the fix label locations. This - * is only done after the first res:fix label is encountered. - * - * (FIXME---This is now all in the .ext file so the information does - * not need to be read twice.) - * - * Results: - * None. - * - * Side Effects: - * For each new name, allocate memory - * - *------------------------------------------------------------------------- - */ - -void -ResExtProcessFixPoints(filename) - char *filename; -{ - char line[MAXLINE][MAXTOKEN], *label, *c; - FILE *fp; - ResFixPoint *thisfix; - - fp = PaOpen(filename, "r", ".ext", (ExtLocalPath == NULL) ? "." : ExtLocalPath, - (char *)NULL, (char **)NULL); - if (fp == NULL) - { - TxError("Cannot open file %s%s\n", filename, ".ext"); - return; - } - while (gettokens(line, fp) != 0) - { - if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 || - strncmp(line[RES_EXT_ATTR_TEXT], "\"res:fix", 8) != 0) - continue; - label = line[RES_EXT_ATTR_TEXT]; - label += 8; - if (*label == ':') label++; - if ((c=strrchr(label, '"')) != NULL) *c = '\0'; - else if (*label != '\0') - { - TxError("Bad res:fix attribute label %s\n", - line[RES_EXT_ATTR_TEXT]); - *label ='\0'; - } - thisfix = (ResFixPoint *)mallocMagic((unsigned)(sizeof(ResFixPoint) - + strlen(label))); - thisfix->fp_next = ResFixList; - ResFixList = thisfix; - thisfix->fp_loc.p_x = atoi(line[RES_EXT_ATTR_X]); - thisfix->fp_loc.p_y = atoi(line[RES_EXT_ATTR_Y]); - thisfix->fp_ttype = DBTechNoisyNameType(line[RES_EXT_ATTR_TILE]); - thisfix->fp_tile = NULL; - strcpy(thisfix->fp_name, label); - } - fclose(fp); -} - - /* *------------------------------------------------------------------------- * diff --git a/resis/ResRex.c b/resis/ResRex.c index 6ecc7456..befbb73b 100644 --- a/resis/ResRex.c +++ b/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) diff --git a/resis/ResSimple.c b/resis/ResSimple.c index 9eed823f..dc362f40 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -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; diff --git a/resis/resis.h b/resis/resis.h index 1da90a86..ea51b499 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -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();