diff --git a/resis/ResBasic.c b/resis/ResBasic.c index eafc61f6..b471954b 100644 --- a/resis/ResBasic.c +++ b/resis/ResBasic.c @@ -140,6 +140,37 @@ ResMultiPlaneFunc(tile, tpptr) return 0; } +/* + *-------------------------------------------------------------------------- + * + * ResSubstrateFunc--- + * + * If device is found overlapping its substrate type, then generate a new + * device at the center of the tile and add to ResNodeQueue. + * + * Results: + * Always 0 to keep the search going. + * + * Side effects: + * Adds to ResNodeQueue + * + *-------------------------------------------------------------------------- + */ + +int +ResSubstrateFunc(tile, tpptr) + Tile *tile, **tpptr; +{ + Tile *tp = *tpptr; + int xj, yj; + + xj = (LEFT(tile) + RIGHT(tile)) / 2; + yj = (TOP(tile) + BOTTOM(tile)) / 2; + ResNewSubDevice(tp, tile, xj, yj, OTHERPLANE, &ResNodeQueue); + + return 0; +} + /* *-------------------------------------------------------------------------- * @@ -370,6 +401,36 @@ ResEachTile(tile, startpoint) } } + /* Check for substrate under device */ + + if (TTMaskHasType(&ResSubTypesBitMask, t1)) + { + Rect r; + int pNum; + TileTypeBitMask devMask; + + TiToRect(tile, &r); + + for (pNum = 0; pNum < DBNumPlanes; pNum++) + { + if (DBTypeOnPlane(t1, pNum)) continue; + + /* NOTE: This is ridiculously inefficient and should be done + * in a different way. + */ + + TTMaskZero(&devMask); + for (t2 = TT_TECHDEPBASE; t2 < DBNumUserLayers; t2++) + for (devptr = ExtCurStyle->exts_device[t2]; devptr; + devptr = devptr->exts_next) + if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, t1)) + TTMaskSetType(&devMask, t2); + + DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pNum], + &r, &devMask, ResSubstrateFunc, (ClientData)&tile); + } + } + tstructs->tj_status |= RES_TILE_DONE; resAllPortNodes(tile, &ResNodeQueue); @@ -394,7 +455,7 @@ ResEachTile(tile, startpoint) */ int -resSubDevFunc(tile,tp) +resSubDevFunc(tile, tp) Tile *tile, *tp; { tileJunk *junk = (tileJunk *)(tile->ti_client); diff --git a/resis/ResJunct.c b/resis/ResJunct.c index 79328983..f07f9741 100644 --- a/resis/ResJunct.c +++ b/resis/ResJunct.c @@ -95,6 +95,58 @@ ResNewSDDevice(tile, tp, xj, yj, direction, PendingList) NEWBREAK(resptr, tile, xj, yj, NULL); } +/* + *------------------------------------------------------------------------- + * + * ResNewSubDevice -- called when a device is reached via a substrate. + * + * Results:none + * + * Side Effects: Makes new node if node hasn't already been created. + * Allocates breakpoint in current tile for device. + * + *------------------------------------------------------------------------- + */ + +void +ResNewSubDevice(tile, tp, xj, yj, direction, PendingList) + Tile *tile, *tp; + int xj, yj, direction; + resNode **PendingList; +{ + resNode *resptr; + resDevice *resDev; + tElement *tcell; + int newnode; + tileJunk *j; + + newnode = FALSE; + j = (tileJunk *) tp->ti_client; + resDev = j->deviceList; + + if (resDev->rd_fet_subs == (resNode *) NULL) + { + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + newnode = TRUE; + resDev->rd_fet_subs = resptr; + } + else + { + resptr = resDev->rd_fet_subs; + } + + if (newnode) + { + tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); + tcell->te_nextt = NULL; + tcell->te_thist = j->deviceList; + InitializeNode(resptr, xj, yj, RES_NODE_DEVICE); + resptr->rn_te = tcell; + ResAddToQueue(resptr, PendingList); + } + NEWBREAK(resptr, tile, xj, yj, NULL); +} + /* *------------------------------------------------------------------------- * diff --git a/resis/ResMain.c b/resis/ResMain.c index 00d88a20..7a4235bf 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -44,6 +44,7 @@ extern int ResEachTile(); extern int ResLaplaceTile(); extern ResSimNode *ResInitializeNode(); TileTypeBitMask ResSDTypesBitMask; +TileTypeBitMask ResSubTypesBitMask; extern HashTable ResNodeTable; @@ -374,6 +375,21 @@ ResFindNewContactTiles(contacts) for (; contacts != (ResContactPoint *) NULL; contacts = contacts->cp_nextcontact) { DBFullResidueMask(contacts->cp_type, &mask); + + /* Watch for types that connect to the substrate plane or well; */ + /* e.g., psubstratepdiff connects to nwell but not through a */ + /* contact. */ + + if (ExtCurStyle->exts_globSubstratePlane != -1) + { + TileTypeBitMask cMask; + TTMaskAndMask3(&cMask, &DBConnectTbl[contacts->cp_type], + &DBPlaneTypes[ExtCurStyle->exts_globSubstratePlane]); + + if (!TTMaskIsZero(&cMask)) + TTMaskSetMask(&mask, &cMask); + } + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { tile = ResDef->cd_planes[pNum]->pl_hint; @@ -948,6 +964,7 @@ ResExtractNet(node, goodies, cellname) SEL_DO_LABELS, ResUse); TTMaskZero(&ResSDTypesBitMask); + TTMaskZero(&ResSubTypesBitMask); /* Add devices to ResUse from list in node */ DevTiles = NULL; @@ -991,6 +1008,15 @@ ResExtractNet(node, goodies, cellname) devptr = devptr->exts_next) for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) TTMaskSetMask(&ResSDTypesBitMask, &devptr->exts_deviceSDTypes[i]); + + /* Add the substrate types to the mask ResSubTypesBitMask */ + + for (devptr = ExtCurStyle->exts_device[thisDev->type]; devptr; + devptr = devptr->exts_next) + TTMaskSetMask(&ResSubTypesBitMask, &devptr->exts_deviceSubstrateTypes); + + /* TT_SPACE should be removed from ResSubTypesBitMask */ + TTMaskClearType(&ResSubTypesBitMask, TT_SPACE); } DBReComputeBbox(ResUse->cu_def); diff --git a/resis/ResRex.c b/resis/ResRex.c index 4428d54b..2b2170cb 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -590,7 +590,7 @@ typedef enum { /* Do subcircuits (if any) first */ if (!(ResOptionsFlags & ResOpt_Blackbox)) - (void) DBCellSrDefs(0, resSubcircuitFunc, (ClientData) &resisdata); + DBCellEnum(mainDef, resSubcircuitFunc, (ClientData) &resisdata); ExtResisForDef(mainDef, &resisdata); @@ -617,7 +617,9 @@ typedef enum { *------------------------------------------------------------------------- * * resSubcircuitFunc -- - * For each encountered cell, call the resistance extractor. + * For each encountered cell, call the resistance extractor, + * then recursively call resSubcircuitFunc on all children + * of the cell. * * Results: * Always return 0 to keep search alive. @@ -633,12 +635,11 @@ resSubcircuitFunc(cellDef, rdata) CellDef *cellDef; ResisData *rdata; { - if ((cellDef->cd_flags & CDINTERNAL) == CDINTERNAL) - return 0; - - if (cellDef != rdata->mainDef) - if (DBIsSubcircuit(cellDef)) - ExtResisForDef(cellDef, rdata); + if (DBIsSubcircuit(cellDef)) + { + ExtResisForDef(cellDef, rdata); + DBCellEnum(cellDef, resSubcircuitFunc, (ClientData)rdata); + } return 0; } @@ -1202,7 +1203,7 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename) { static char newname[MAXNAME], oldnodename[MAXNAME]; int notdecremented; - resNode *gate, *source, *drain; + resNode *gate, *source, *drain, *subs; /* If we aren't doing output (i.e. this is just a statistical run) */ /* don't patch up networks. This cuts down on memory use. */ @@ -1244,6 +1245,24 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename) layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot, nodename); } + if (simDev->subs == simNode) + { + if ((subs = layoutDev->rd_fet_subs) != NULL) + { + if (subs->rn_name != NULL && notdecremented) + { + resNodeNum--; + notdecremented = FALSE; + } + ResFixDevName(newname, SUBS, simDev, subs); + subs->rn_name = simDev->subs->name; + sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++); + } + else + TxError("Missing substrate connection of device at (%d %d) on net %s\n", + layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot, + nodename); + } if (simDev->source == simNode) { if (simDev->drain == simNode) @@ -1423,6 +1442,10 @@ ResFixDevName(line, type, device, layoutnode) node->oldname = device->drain->name; device->drain = node; break; + case SUBS: + node->oldname = device->subs->name; + device->subs = node; + break; default: TxError("Bad Terminal Specifier\n"); break; diff --git a/resis/ResSimple.c b/resis/ResSimple.c index 060c4392..3639682e 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -395,6 +395,8 @@ ResMoveDevices(node1, node2) { if (device->rd_fet_gate == node1) device->rd_fet_gate = node2; + else if (device->rd_fet_subs == node1) + device->rd_fet_subs = node2; else if (device->rd_fet_source == node1) device->rd_fet_source = node2; else if (device->rd_fet_drain == node1) diff --git a/resis/ResUtils.c b/resis/ResUtils.c index 1320aca4..c519eec5 100644 --- a/resis/ResUtils.c +++ b/resis/ResUtils.c @@ -108,6 +108,26 @@ resMultiPlaneTerm(Tile *tile, tileJunk *junk2) return 0; } +/* + *-------------------------------------------------------------------------- + * + * resSubstrateTerm -- + * + * Callback function to set a junk field + * + *-------------------------------------------------------------------------- + */ + +int +resSubstrateTerm(Tile *tile) +{ + tileJunk *Junk; + + Junk = resAddField(tile); + Junk->tj_status |= RES_TILE_SUBS; + return 0; +} + /* *-------------------------------------------------------------------------- * @@ -165,6 +185,7 @@ ResAddPlumbing(tile, arg) Tile *tp1, *tp2, *source; resDevice *resDev; ExtDevice *devptr; + TileTypeBitMask locDevSubsMask; if (resDevStack == NULL) resDevStack = StackNew(64); @@ -181,7 +202,8 @@ ResAddPlumbing(tile, arg) junk2 = resAddField(tile); if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype)) { - int i, nterms; + int i, nterms, pNum; + Rect r; /* Count SD terminals of the device */ nterms = 0; @@ -288,9 +310,6 @@ ResAddPlumbing(tile, arg) /* other plane (in ResUse) */ if (source == NULL) { - int pNum; - Rect r; - TiToRect(tile, &r); for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { @@ -381,6 +400,22 @@ ResAddPlumbing(tile, arg) } } + /* Find device substrate */ + + TTMaskZero(&locDevSubsMask); + TTMaskSetMask(&locDevSubsMask, &(devptr->exts_deviceSubstrateTypes)); + TTMaskClearType(&locDevSubsMask, TT_SPACE); + + TiToRect(tile, &r); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (TTMaskIntersect(&DBPlaneTypes[pNum], &locDevSubsMask)) + DBSrPaintArea((Tile *)NULL, + ResUse->cu_def->cd_planes[pNum], + &r, &locDevSubsMask, + resSubstrateTerm, (ClientData)NULL); + } + /* find rest of device; search for source edges */ STACKPUSH((ClientData)tile, resDevStack); diff --git a/resis/resis.h b/resis/resis.h index 8bec743a..0f71fcbd 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -461,18 +461,20 @@ typedef struct capval #define RES_DEV_PLUG 0x00000002 /* flags for tiles */ +/* A tile which is part of a substrate region. */ +#define RES_TILE_SUBS 0x01 /* A tile which is part of a source/drain region. */ -#define RES_TILE_SD 0x1 +#define RES_TILE_SD 0x02 /* A tile which is actually a device */ -#define RES_TILE_DEV 0x2 +#define RES_TILE_DEV 0x04 /* Indicates whether the tile has been processed or not */ -#define RES_TILE_DONE 0x4 +#define RES_TILE_DONE 0x08 /*a temporary marking flag */ -#define RES_TILE_MARK 0x8 +#define RES_TILE_MARK 0x10 /* indicates that tile has unidirectional current flow */ #ifdef LAPLACE -#define RES_TILE_1D 0x10 -#define RES_TILE_GDONE 0x20 +#define RES_TILE_1D 0x20 +#define RES_TILE_GDONE 0x40 #endif /* tree walking flags */ #define RES_LOOP_OK 1 @@ -604,6 +606,7 @@ extern int ResTileCount; extern ResSimNode **ResNodeArray; extern CellDef *mainDef; extern TileTypeBitMask ResSDTypesBitMask; +extern TileTypeBitMask ResSubTypesBitMask; extern HashTable ResDevTable; extern TileTypeBitMask ResNoMergeMask[NT]; extern ResGlobalParams gparams;