diff --git a/VERSION b/VERSION index ad509384..4c3f6945 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.658 +8.3.659 diff --git a/resis/ResBasic.c b/resis/ResBasic.c index 73b8856e..65c42644 100644 --- a/resis/ResBasic.c +++ b/resis/ResBasic.c @@ -230,9 +230,9 @@ ResStartTile(tile, x, y) #define IGNORE_BOTTOM 8 bool -ResEachTile(tile, devTiles) +ResEachTile(tile, devNodeTable) Tile *tile; /* Tile being processed */ - ResDevTile *devTiles; /* List of device tiles for reference */ + HashTable *devNodeTable; /* Table of tiles connected to devices */ { Tile *tp; resNode *resptr; @@ -244,6 +244,7 @@ ResEachTile(tile, devTiles) resInfo *tstructs = (resInfo *)TiGetClientPTR(tile); ExtDevice *devptr; int sides; + HashEntry *he; ResTileCount++; @@ -457,6 +458,41 @@ ResEachTile(tile, devTiles) /* Note: Need to tag these tiles per device to avoid checking through */ /* the device list for each tile. (To be done) */ + he = HashLookOnly(devNodeTable, (char *)tile); + if (he != NULL) + { + resDevTerm *resdevRec, *resdevList; + Tile *devtile; + + resdevList = (resDevTerm *)HashGetValue(he); + while (resdevList != NULL) + { + resdevRec = resdevList; + /* Set the position from the device, not the current tile */ + devtile = resdevRec->rdt_tile; + xj = (RIGHT(devtile) + LEFT(devtile)) / 2; + yj = (TOP(devtile) + BOTTOM(devtile)) / 2; + if (resdevRec->rdt_term == -1) /* Substrate */ + { + ResNewSubDevice(tile, resdevRec->rdt_tile, xj, yj, + OTHERPLANE, &ResNodeQueue); + } + else /* Terminal */ + { + ResNewTermDevice(tile, resdevRec->rdt_tile, resdevRec->rdt_term, + xj, yj, OTHERPLANE, &ResNodeQueue); + } + resdevList = resdevList->rdt_next; + freeMagic(resdevRec); + } + HashSetValue(he, (char *)NULL); /* Done with hash record */ + } + +#if 0 + /* Deprecated: Searching through all devices for all tiles is + * irresponsibly slow. Do not do this. + */ + if (TTMaskHasType(&ResTermTypesBitMask, t1)) { Rect r; @@ -527,6 +563,7 @@ ResEachTile(tile, devTiles) } } } +#endif /* 0 */ tstructs->ri_status |= RES_TILE_DONE; diff --git a/resis/ResMain.c b/resis/ResMain.c index fb4ce0b5..62ba6d6d 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -697,10 +697,10 @@ ResFindNewContactTiles(contacts) */ int -ResProcessTiles(resisdata, origin, devices) +ResProcessTiles(resisdata, origin, devNodeTable) ResisData *resisdata; Point *origin; - ResDevTile *devices; + HashTable *devNodeTable; { Tile *startTile; int tilenum, merged; @@ -718,7 +718,7 @@ ResProcessTiles(resisdata, origin, devices) return 1; resCurrentNode = NULL; ResStartTile(startTile, origin->p_x, origin->p_y); - (void) ResEachTile(startTile, devices); + (void) ResEachTile(startTile, devNodeTable); } #ifdef PARANOID else @@ -755,7 +755,7 @@ ResProcessTiles(resisdata, origin, devices) if ((ri->ri_status & RES_TILE_DONE) == 0) { resCurrentNode = resptr2; - merged |= ResEachTile(tile, devices); + merged |= ResEachTile(tile, devNodeTable); } } rj->rj_status = TRUE; @@ -781,7 +781,7 @@ ResProcessTiles(resisdata, origin, devices) if (cp->cp_cnode[tilenum] == resptr2) { resCurrentNode = resptr2; - merged |= ResEachTile(tile, devices); + merged |= ResEachTile(tile, devNodeTable); } else { @@ -1210,6 +1210,9 @@ ResExtractNet(node, resisdata, cellname) int resMakeDevFunc(); int resExpandDevFunc(); int result; + HashTable DevNodeTable; + HashSearch hs; + HashEntry *he; /* Make sure all global network variables are reset */ @@ -1453,11 +1456,29 @@ ResExtractNet(node, resisdata, cellname) /* Finish preprocessing. */ ResFindNewContactTiles(ResContactList); - ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def); + + HashInit(&DevNodeTable, HT_DEFAULTSIZE, HT_CLIENTKEYS); + ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def, &DevNodeTable); /* do extraction */ - result = ResProcessTiles(resisdata, &startpoint, DevTiles); - ResFreeDevTiles(DevTiles); + result = ResProcessTiles(resisdata, &startpoint, &DevNodeTable); + + /* Free remaining table entries (if any) */ + HashStartSearch(&hs); + while ((he = HashNext(&DevNodeTable, &hs)) != NULL) + { + resDevTerm *resdevList, *resdevNext; + + resdevList = (resDevTerm *)HashGetValue(he); + while (resdevList) + { + resdevNext = resdevList->rdt_next; + freeMagic((char *)resdevList); + resdevList = resdevNext; + } + } + HashKill(&DevNodeTable); + if (result != 0) return TRUE; return FALSE; } diff --git a/resis/ResMakeRes.c b/resis/ResMakeRes.c index d9ea3222..3264d867 100644 --- a/resis/ResMakeRes.c +++ b/resis/ResMakeRes.c @@ -186,6 +186,9 @@ ResCalcEastWest(tile, pendingList, doneList, resList) p2->br_this->rn_float.rn_area += height * (p2->br_loc.p_x - LEFT(tile)); while (p2->br_next != NULL) { + p1 = p2; + p2 = p2->br_next; + /* Has the node been recorded as needing to be replaced? */ if (count >= 16) { @@ -196,8 +199,7 @@ ResCalcEastWest(tile, pendingList, doneList, resList) p2->br_this = (resNode *)HashGetValue(he); } } - p1 = p2; - p2 = p2->br_next; + if (p2->br_loc.p_x == p1->br_loc.p_x) { if (p2->br_this == p1->br_this) @@ -396,6 +398,9 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) p2->br_this->rn_float.rn_area += width * (p2->br_loc.p_y - BOTTOM(tile)); while (p2->br_next != NULL) { + p1 = p2; + p2 = p2->br_next; + /* Has the node been recorded as needing to be replaced? */ if (count >= 16) { @@ -406,8 +411,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) p2->br_this = (resNode *)HashGetValue(he); } } - p1 = p2; - p2 = p2->br_next; + if (p1->br_loc.p_y == p2->br_loc.p_y) { if (p2->br_this == p1->br_this) diff --git a/resis/ResUtils.c b/resis/ResUtils.c index 8dcd21d2..bd65b092 100644 --- a/resis/ResUtils.c +++ b/resis/ResUtils.c @@ -858,12 +858,17 @@ ResFreeDevTiles(TileList) /* *------------------------------------------------------------------------- * - * ResPreProcessDevices-- Given a list of all the device tiles and - * a list of all the devices, this procedure calculates the width and - * length. The width is set equal to the sum of all edges that touch - * diffusion divided by 2. The length is the remaining perimeter divided by - * 2*tiles. The perimeter and area fields of device structures are also - * fixed. + * ResPreProcessDevices -- + * + * Given a list of all the device tiles and a list of all the devices, this + * procedure calculates the width and length. The width is set equal to the + * sum of all edges that touch diffusion divided by 2. The length is the + * remaining perimeter divided by 2*tiles. The perimeter and area fields of + * device structures are also fixed. + * + * Each device is checked for terminals and substrate on a plane other than + * the plane of the device type. If so, find the tile on that plane + * directly under the device. * * Results: none * @@ -873,20 +878,21 @@ ResFreeDevTiles(TileList) */ void -ResPreProcessDevices(TileList, DeviceList, Def) +ResPreProcessDevices(TileList, DeviceList, Def, devNodeTable) ResDevTile *TileList; resDevice *DeviceList; CellDef *Def; + HashTable *devNodeTable; { Tile *tile; - ResDevTile *devTile; + ResDevTile *oldTile; resInfo *tstruct; TileType tt, residue; int pNum; - for (devTile = TileList; devTile; devTile = devTile->nextDev) + while (TileList != (ResDevTile *)NULL) { - tt = devTile->type; + tt = TileList->type; if (DBIsContact(tt)) { /* Find which residue of the contact is a device. */ @@ -910,7 +916,7 @@ ResPreProcessDevices(TileList, DeviceList, Def) pNum = DBPlane(tt); /* always correct for non-contact types */ tile = PlaneGetHint(Def->cd_planes[pNum]); - GOTOPOINT(tile, &(devTile->area.r_ll)); + GOTOPOINT(tile, &(TileList->area.r_ll)); PlaneSetHint(Def->cd_planes[pNum], tile); tt = TiGetType(tile); @@ -921,20 +927,103 @@ ResPreProcessDevices(TileList, DeviceList, Def) !TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt)) { TxError("Bad Device Location at %d,%d\n", - devTile->area.r_ll.p_x, - devTile->area.r_ll.p_y); + TileList->area.r_ll.p_x, + TileList->area.r_ll.p_y); } else if ((tstruct->ri_status & RES_TILE_MARK) == 0) { resDevice *rd = tstruct->deviceList; + ExtDevice *devptr; + int i; + Tile *tp; + TileType ttype; + PlaneMask pmask; + TileTypeBitMask termMask, subMask; + resDevTerm *resdevRec, *resdevList; + HashEntry *he; tstruct->ri_status |= RES_TILE_MARK; - rd->rd_perim += devTile->perim; - rd->rd_length += devTile->overlap; - rd->rd_area += (devTile->area.r_xtop - devTile->area.r_xbot) - * (devTile->area.r_ytop - devTile->area.r_ybot); + rd->rd_perim += TileList->perim; + rd->rd_length += TileList->overlap; + rd->rd_area += (TileList->area.r_xtop - TileList->area.r_xbot) + * (TileList->area.r_ytop - TileList->area.r_ybot); rd->rd_tiles++; + + /* Get the device record */ + devptr = TileList->devptr; + TTMaskZero(&subMask); + TTMaskSetMask(&subMask, &devptr->exts_deviceSubstrateTypes); + /* Remove TT_SPACE from mask or else all planes will be flagged */ + TTMaskClearType(&subMask, TT_SPACE); + pmask = DBTechTypesToPlanes(&subMask); + if ((pmask != 0) && !PlaneMaskHasPlane(pmask, DBPlane(tt))) + { + /* Record substrate tile if it exists */ + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (PlaneMaskHasPlane(pmask, pNum)) + { + tp = PlaneGetHint(Def->cd_planes[pNum]); + GOTOPOINT(tp, &(TileList->area.r_ll)); + PlaneSetHint(Def->cd_planes[pNum], tp); + + ttype = TiGetType(tp); + if (TTMaskHasType(&subMask, ttype)) + { + he = HashFind(devNodeTable, (char *)tp); + resdevList = (resDevTerm *)HashGetValue(he); + resdevRec = (resDevTerm *)mallocMagic(sizeof(resDevTerm)); + resdevRec->rdt_term = -1; /* Indicates substrate */ + resdevRec->rdt_tile = tile; + resdevRec->rdt_next = resdevList; + HashSetValue(he, (char *)resdevRec); + } + } + } + } + + /* Record terminal tiles on other planes, if they exist */ + + for (i = 0; i < devptr->exts_deviceSDCount; i++) + { + TTMaskZero(&termMask); + TTMaskSetMask(&termMask, &devptr->exts_deviceSDTypes[i]); + /* Remove TT_SPACE from mask or else all planes will be flagged */ + TTMaskClearType(&termMask, TT_SPACE); + pmask = DBTechTypesToPlanes(&termMask); + if ((pmask != 0) && !PlaneMaskHasPlane(pmask, DBPlane(tt))) + { + /* Record terminal tile if it exists */ + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (PlaneMaskHasPlane(pmask, pNum)) + { + tp = PlaneGetHint(Def->cd_planes[pNum]); + GOTOPOINT(tp, &(TileList->area.r_ll)); + PlaneSetHint(Def->cd_planes[pNum], tp); + + ttype = TiGetType(tp); + if (TTMaskHasType(&termMask, ttype)) + { + he = HashFind(devNodeTable, (char *)tp); + resdevList = (resDevTerm *)HashGetValue(he); + resdevRec = (resDevTerm *)mallocMagic(sizeof(resDevTerm)); + resdevRec->rdt_term = i; + resdevRec->rdt_tile = tile; + resdevRec->rdt_next = resdevList; + HashSetValue(he, (char *)resdevRec); + } + } + } + } + } } + + /* Free up memory from the devTile list */ + + oldTile = TileList; + TileList = TileList->nextDev; + freeMagic((char *)oldTile); } for (; DeviceList != NULL; DeviceList = DeviceList->rd_nextDev) @@ -965,7 +1054,6 @@ ResPreProcessDevices(TileList, DeviceList, Def) } } - /* *------------------------------------------------------------------------- * diff --git a/resis/resis.h b/resis/resis.h index c2a2ce0b..ae72e488 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -51,6 +51,17 @@ typedef struct resistor #define rr_connection1 rr_node[0] #define rr_connection2 rr_node[1] +/* The resDevTerm structure holds information needed to quickly check */ +/* if a tile belongs to a terminal of a device in a plane other than */ +/* the plane of the device. */ + +typedef struct resdevterm +{ + struct resdevterm *rdt_next; /* next connected device in the list */ + Tile *rdt_tile; /* the tile of the device */ + int rdt_term; /* terminal number, or -1 for substrate */ +} resDevTerm; + /* Definitions for old FET-style MOSFET devices. Actual devices may have * any number of terminals. "GATE" is the identifying type; "SUBS" is * the substrate/well connection (if it exists), and the other terminals