diff --git a/VERSION b/VERSION index 02017a7a..b61a571b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.371 +8.3.372 diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index cd4fae57..7190cb5a 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -1407,9 +1407,14 @@ portFindLabel(editDef, port, unique, nonEdit) int complabel(const void *one, const void *two) { + /* Natural sort order routine from DBcellname.c + * replaces strcasecmp(). + */ + int strcmpbynum(); + Label *l1 = *((Label **)one); Label *l2 = *((Label **)two); - return strcasecmp(l1->lab_text, l2->lab_text); + return strcmpbynum(l1->lab_text, l2->lab_text); } /* @@ -2027,6 +2032,8 @@ CmdPort(w, cmd) * order of the label text). NOTE: Because SPICE is * case-insensitive, case-insensitive alphabetical order * is used. + * Update (2/26/2023): Use *natural sort* order so that + * indexes get sorted in numerical, not alphabetical, order. */ { int numlabels, n, p; diff --git a/database/DBcellcopy.c b/database/DBcellcopy.c index 9de59762..6167b6e0 100644 --- a/database/DBcellcopy.c +++ b/database/DBcellcopy.c @@ -820,6 +820,89 @@ DBCellGenerateSubstrate(scx, subType, notSubMask, subShieldMask, targetDef) return tempPlane; } +/* + *----------------------------------------------------------------------------- + * + * DBCellGenerateSimpleSubstrate -- + * + * This function is used by the extraction code in "extresist". + * It is similar to DBCellGenerateSubstrate(), above. It finds space + * tiles on the substrate plane and converts them to a substrate type + * in the target, clipped to the cell boundary. This allows the + * extraction to find and record all common (global) substrate regions, + * without requiring a physical substrate type to be drawn into all cells. + * + * Unlike normal paint copying, this can only be done by painting the + * substrate type over the entire cell area and then erasing all areas + * belonging to not-substrate types in the source. + * + * Returns: + * Nothing. + * + * Side Effects: + * Paints into the targetUse's CellDef. This only happens if two + * conditions are met: + * (1) The techfile has defined "substrate" + * (2) The techfile defines a type corresponding to the substrate + * + * ---------------------------------------------------------------------------- + */ + +Plane * +DBCellGenerateSimpleSubstrate(scx, subType, notSubMask, targetDef) + SearchContext *scx; + TileType subType; /* Substrate paint type */ + TileTypeBitMask *notSubMask; /* Mask of types that are not substrate */ + CellDef *targetDef; +{ + struct dbCopySubData csd; + Plane *tempPlane; + int plane; + Rect rect; + TileTypeBitMask allButSubMask; + TileTypeBitMask defaultSubTypeMask; + int dbEraseSubFunc(); + int dbPaintSubFunc(); + int dbEraseNonSub(); + int dbCopySubFunc(); + + GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &rect); + + /* Clip to bounding box of the top level cell */ + GEOCLIP(&rect, &scx->scx_use->cu_def->cd_bbox); + + plane = DBPlane(subType); + + tempPlane = DBNewPlane((ClientData) TT_SPACE); + DBClearPaintPlane(tempPlane); + + csd.csd_subtype = subType; + csd.csd_plane = tempPlane; + csd.csd_pNum = plane; + csd.csd_modified = FALSE; + + /* Paint the substrate type in the temporary plane over the area of */ + /* the entire cell. */ + DBPaintPlane(tempPlane, &rect, DBStdPaintTbl(subType, plane), + (PaintUndoInfo *)NULL); + + /* Now erase all areas that are non-substrate types in the source */ + DBTreeSrTiles(scx, notSubMask, 0, dbEraseNonSub, (ClientData)&csd); + + /* Finally, copy the destination plane contents onto tempPlane, */ + /* ignoring the substrate type. */ + TTMaskZero(&allButSubMask); + TTMaskSetMask(&allButSubMask, &DBAllButSpaceBits); + TTMaskClearType(&allButSubMask, subType); + DBSrPaintArea((Tile *)NULL, targetDef->cd_planes[plane], &TiPlaneRect, + &allButSubMask, dbCopySubFunc, (ClientData)&csd); + + /* Now we have a plane where the substrate type occupies the whole */ + /* area of the cell except where there are conflicting types (e.g., */ + /* nwell). Return this plane. */ + return tempPlane; +} + /* * Callback function for DBCellGenerateSubstrate() * Finds tiles in the source def that belong to the type that represents diff --git a/database/DBcellname.c b/database/DBcellname.c index 944c6a60..6f159245 100644 --- a/database/DBcellname.c +++ b/database/DBcellname.c @@ -637,7 +637,7 @@ DBTopPrint(mw, dolist) int strcmpbynum(const char *s1, const char *s2) { - /* Like strcmp() but compare sequences of digits numerically */ + /* Like strcasecmp() but compare sequences of digits numerically */ for (;;) { if (*s2 == '\0') @@ -646,8 +646,11 @@ int strcmpbynum(const char *s1, const char *s2) return 1; else if (!(isdigit(*s1) && isdigit(*s2))) { - if (*s1 != *s2) - return (int)*s1 - (int)*s2; + char c1, c2; + c1 = tolower(*s1); + c2 = tolower(*s2); + if (c1 != c2) + return (int)c1 - (int)c2; else { ++s1; diff --git a/database/database.h.in b/database/database.h.in index 808ea983..477da56a 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -894,6 +894,7 @@ extern void DBCellCopyCells(); extern void DBCellCopyAllCells(); extern void DBFlatCopyMaskHints(); extern Plane *DBCellGenerateSubstrate(); +extern Plane *DBCellGenerateSimpleSubstrate(); /* Contact image handling */ extern TileType DBPlaneToResidue(); diff --git a/extract/ExtCell.c b/extract/ExtCell.c index 89257185..beb741a8 100644 --- a/extract/ExtCell.c +++ b/extract/ExtCell.c @@ -292,10 +292,10 @@ extPrepSubstrate(def) TTMaskCom2(¬SubMask, &subMask); TTMaskAndMask(¬SubMask, &DBPlaneTypes[ExtCurStyle->exts_globSubstratePlane]); - /* Generate the full flattened substrate into ha->ha_cumFlat (which */ - /* was empty initially). This adds layer geometry for the */ - /* substrate in the typical case where the substrate may be space */ - /* (implicitly defined substrate). */ + /* Generate the full flattened substrate into a new plane structure */ + /* (called subPlane). This adds layer geometry for the substrate */ + /* in the typical case where the substrate may be space (implicitly */ + /* defined substrate). */ scx.scx_trans = GeoIdentityTransform; scx.scx_area = def->cd_bbox; @@ -316,6 +316,81 @@ extPrepSubstrate(def) return NULL; } +/* + * ---------------------------------------------------------------------------- + * + * extResPrepSubstrate --- + * + * This works similarly to extPrepSubstrate above, but is used for the + * "extresist" command, where the method is to make sure that the whole + * substrate area of the cell has non-space tiles, so that these can be + * used to estimate the resistance of the substrate from point to point, + * and to eliminate isolated substrate regions, since those represent an + * idealized cutoff of resistance that "extresist" is supposed to be + * replacing with an accurate resitance network. + * + * Results: + * Returns a Plane structure that is the original substrate plane from + * CellDef "def", with the entire substrate region filled with the + * substrate tile type. If a substrate plane or substrate type is not + * defined by the technology, then the routine returns NULL. + * + * Side effects: + * All modifications are limited to the returned plane structure. + * + * ---------------------------------------------------------------------------- + */ + +Plane * +extResPrepSubstrate(def) + CellDef *def; +{ + SearchContext scx; + CellUse dummy; + TileType subType; + TileTypeBitMask subMask, notSubMask; + Plane *subPlane, *savePlane; + int pNum; + + /* Determine if substrate copying is required. */ + + if (ExtCurStyle->exts_globSubstratePlane == -1) return NULL; + + /* Find a type to use for the substrate, and the mask of all types */ + /* in the same plane as the substrate that are not connected to the */ + /* substrate. If there is not a simple type representing the substrate */ + /* then do not attempt to resolve substrate regions. */ + + if ((subType = ExtCurStyle->exts_globSubstrateDefaultType) == -1) return NULL; + + TTMaskZero(&subMask); + TTMaskSetMask(&subMask, &ExtCurStyle->exts_globSubstrateTypes); + TTMaskCom2(¬SubMask, &subMask); + TTMaskAndMask(¬SubMask, &DBPlaneTypes[ExtCurStyle->exts_globSubstratePlane]); + + /* Generate the full flattened substrate into a new plane structure */ + /* (called subPlane). This adds layer geometry for the substrate */ + /* in the typical case where the substrate may be space (implicitly */ + /* defined substrate). */ + + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = def->cd_bbox; + scx.scx_use = &dummy; + dummy.cu_def = def; + dummy.cu_id = NULL; + + subPlane = DBCellGenerateSimpleSubstrate(&scx, subType, ¬SubMask, def); + if (subPlane != NULL) + { + pNum = ExtCurStyle->exts_globSubstratePlane; + savePlane = def->cd_planes[pNum]; + def->cd_planes[pNum] = subPlane; + return savePlane; + } + else + return NULL; +} + /* * ---------------------------------------------------------------------------- * diff --git a/resis/ResBasic.c b/resis/ResBasic.c index cd40077e..77a7e117 100644 --- a/resis/ResBasic.c +++ b/resis/ResBasic.c @@ -282,19 +282,24 @@ ResEachTile(tile, startpoint) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetRightType(tp); - devptr = ExtCurStyle->exts_device[t2]; - if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && - TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) - /* found device */ + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2)) { - xj = LEFT(tile); - yj = (TOP(tp) + BOTTOM(tp)) >> 1; - ResNewSDDevice(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue); + devptr = ExtCurStyle->exts_device[t2]; + for (i = 0; i < devptr->exts_deviceSDCount; i++) + { + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t1)) + { + /* found device */ + xj = LEFT(tile); + yj = (TOP(tp) + BOTTOM(tp)) >> 1; + ResNewSDDevice(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue); + break; + } + } } if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2) - /* tile is junction */ { - /*junction rn_loc */ + /* tile is junction */ xj = LEFT(tile); yj = (MAX(BOTTOM(tile), BOTTOM(tp)) + MIN(TOP(tile), TOP(tp))) >> 1; (void) ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue); @@ -304,20 +309,25 @@ ResEachTile(tile, startpoint) /* right */ for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { - t2 = TiGetLeftType(tp); - devptr = ExtCurStyle->exts_device[t2]; - if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && - TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) - /* found device */ + t2 = TiGetLeftType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2)) { - xj = RIGHT(tile); - yj = (TOP(tp)+BOTTOM(tp))>>1; - ResNewSDDevice(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue); + devptr = ExtCurStyle->exts_device[t2]; + for (i = 0; i < devptr->exts_deviceSDCount; i++) + { + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t1)) + { + /* found device */ + xj = RIGHT(tile); + yj = (TOP(tp) + BOTTOM(tp)) >> 1; + ResNewSDDevice(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue); + break; + } + } } if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2) - /* tile is junction */ { - /*junction rn_loc */ + /* tile is junction */ xj = RIGHT(tile); yj = (MAX(BOTTOM(tile),BOTTOM(tp)) + MIN(TOP(tile), TOP(tp))) >> 1; (void)ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue); @@ -327,19 +337,25 @@ ResEachTile(tile, startpoint) /* top */ for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { - t2 = TiGetBottomType(tp); - devptr = ExtCurStyle->exts_device[t2]; - if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && - TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) - /* found device */ + t2 = TiGetBottomType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2)) { - yj = TOP(tile); - xj = (LEFT(tp)+RIGHT(tp))>>1; - ResNewSDDevice(tile, tp, xj, yj, BOTTOMEDGE, &ResNodeQueue); + devptr = ExtCurStyle->exts_device[t2]; + for (i = 0; i < devptr->exts_deviceSDCount; i++) + { + if(TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t1)) + { + /* found device */ + yj = TOP(tile); + xj = (LEFT(tp)+RIGHT(tp))>>1; + ResNewSDDevice(tile, tp, xj, yj, BOTTOMEDGE, &ResNodeQueue); + break; + } + } } if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1],t2) - /* tile is junction */ { + /* tile is junction */ yj = TOP(tile); xj = (MAX(LEFT(tile),LEFT(tp)) + MIN(RIGHT(tile),RIGHT(tp))) >> 1; ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue); @@ -349,19 +365,25 @@ ResEachTile(tile, startpoint) /* bottom */ for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { - t2 = TiGetTopType(tp); - devptr = ExtCurStyle->exts_device[t2]; - if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && - TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) - /* found device */ + t2 = TiGetTopType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2)) { - yj = BOTTOM(tile); - xj = (LEFT(tp) + RIGHT(tp)) >> 1; - ResNewSDDevice(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue); + devptr = ExtCurStyle->exts_device[t2]; + for (i = 0; i < devptr->exts_deviceSDCount; i++) + { + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t1)) + { + /* found device */ + yj = BOTTOM(tile); + xj = (LEFT(tp) + RIGHT(tp)) >> 1; + ResNewSDDevice(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue); + break; + } + } } if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2) - /* tile is junction */ { + /* tile is junction */ yj = BOTTOM(tile); xj = (MAX(LEFT(tile),LEFT(tp)) + MIN(RIGHT(tile),RIGHT(tp))) >> 1; ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue); diff --git a/resis/ResMain.c b/resis/ResMain.c index abbba4e1..a4a1687d 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -1162,11 +1162,42 @@ ResCleanUpEverything() DBCellClearDef(ResUse->cu_def); } +/* + *------------------------------------------------------------------------- + * + * ResGetTileFunc -- + * + * Callback function used by FindStartTile() when searching for + * terminal connections of a device that may be on planes other + * than the plane of the device identifier type. Ignore space + * tiles. Otherwise, for any tile found, record the tile in + * the client data record and return 1 to stop the search. + * + * Results: + * Return 0 if tile is a space tile, to keep the search going. + * Return 1 otherwise to stop the search immediately because + * a valid start tile has been found. + * + *------------------------------------------------------------------------- + */ + +int +ResGetTileFunc(tile, tpptr) + Tile *tile, **tpptr; +{ + if (TiGetType(tile) != TT_SPACE) + { + *tpptr = tile; + return 1; + } + return 0; +} + /* *------------------------------------------------------------------------- * * FindStartTile-- To start the extraction, we need to find the first driver. - * The sim file gives us the location of a point in or near (within 1 + * The sim file gives us the location of a point in or near (within 1 * unit) of the device. FindStartTile looks for the device, then * for adjoining diffusion. The diffusion tile is returned. * @@ -1186,8 +1217,9 @@ FindStartTile(goodies, SourcePoint) { Point workingPoint; Tile *tile, *tp; - int pnum, t1, t2; + int pnum, t1, t2, i; ExtDevice *devptr; + Rect r; /* If the drive point is on a contact, check for the contact residues */ /* first, then the contact type itself. */ @@ -1284,57 +1316,80 @@ FindStartTile(goodies, SourcePoint) devptr = ExtCurStyle->exts_device[t1]; - /* left */ - for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + for (i = 0; i < devptr->exts_deviceSDCount; i++) { - t2 = TiGetRightType(tp); - if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t2)) + /* left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) { - SourcePoint->p_x = LEFT(tile); - SourcePoint->p_y = (MIN(TOP(tile),TOP(tp)) + + t2 = TiGetRightType(tp); + if ((t2 != TT_SPACE) && TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t2)) + { + SourcePoint->p_x = LEFT(tile); + SourcePoint->p_y = (MIN(TOP(tile),TOP(tp)) + MAX(BOTTOM(tile), BOTTOM(tp))) >> 1; - return(tp); + return(tp); + } } - } - /* right */ - for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) - { - t2 = TiGetLeftType(tp); - if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t2)) + /* right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) { - SourcePoint->p_x = RIGHT(tile); - SourcePoint->p_y = (MIN(TOP(tile), TOP(tp))+ + t2 = TiGetLeftType(tp); + if ((t2 != TT_SPACE) && TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t2)) + { + SourcePoint->p_x = RIGHT(tile); + SourcePoint->p_y = (MIN(TOP(tile), TOP(tp))+ MAX(BOTTOM(tile), BOTTOM(tp))) >> 1; - return(tp); + return(tp); + } + } + + /* top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + { + t2 = TiGetBottomType(tp); + if ((t2 != TT_SPACE) && TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t2)) + { + SourcePoint->p_y = TOP(tile); + SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp)) + + MAX(LEFT(tile), LEFT(tp))) >> 1; + return(tp); + } + } + + /* bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + t2 = TiGetTopType(tp); + if ((t2 != TT_SPACE) && TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t2)) + { + SourcePoint->p_y = BOTTOM(tile); + SourcePoint->p_x = (MIN(RIGHT(tile), RIGHT(tp)) + + MAX(LEFT(tile), LEFT(tp))) >> 1; + return(tp); + } } } - /* top */ - for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + /* Didn't find a terminal (S/D) type tile in the perimeter search. */ + /* Check if S/D types are in a different plane from the identifier. */ + + TiToRect(tile, &r); + tp = NULL; + for (i = 0; i < devptr->exts_deviceSDCount; i++) { - t2 = TiGetBottomType(tp); - if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t2)) + for (pnum = 0; pnum < DBNumPlanes; pnum++) { - SourcePoint->p_y = TOP(tile); - SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp)) + - MAX(LEFT(tile), LEFT(tp))) >> 1; - return(tp); + DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pnum], + &r, &(devptr->exts_deviceSDTypes[i]), ResGetTileFunc, &tp); + if (tp != NULL) return tp; } } - /* bottom */ - for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) - { - t2 = TiGetTopType(tp); - if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t2)) - { - SourcePoint->p_y = BOTTOM(tile); - SourcePoint->p_x = (MIN(RIGHT(tile), RIGHT(tp)) + - MAX(LEFT(tile), LEFT(tp))) >> 1; - return(tp); - } - } + /* Didn't find a terminal (S/D) type tile anywhere. Flag an error. */ + + TxError("Couldn't find a terminal of the device at %d %d\n", + goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); return((Tile *) NULL); } diff --git a/resis/ResRex.c b/resis/ResRex.c index ba424c05..026f934f 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -83,13 +83,24 @@ int ResPortIndex; /* Port ordering to backannotate into magic */ extern ResSimNode *ResInitializeNode(); extern CellUse *CmdGetSelectedCell(); +/* 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. */ + +struct saveList { + Plane *sl_plane; + CellDef *sl_def; + struct saveList *sl_next; +}; + /* Structure stores information required to be sent to ExtResisForDef() */ typedef struct { - float tolerance; - float tdiTolerance; - float frequency; - CellDef *mainDef; + float tolerance; + float tdiTolerance; + float frequency; + struct saveList *savePlanes; + CellDef *mainDef; } ResisData; /* @@ -114,6 +125,7 @@ ExtResisForDef(celldef, resisdata) ResSimNode *node; int result, idx; char *devname; + Plane *savePlane; ResRDevList = NULL; ResOriginalNodes = NULL; @@ -122,6 +134,18 @@ ExtResisForDef(celldef, resisdata) 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)) @@ -227,6 +251,7 @@ CmdExtResis(win, cmd) CellUse *selectedUse; ResisData resisdata; char *endptr; /* for use with strtod() */ + struct saveList *sl; extern int resSubcircuitFunc(); /* Forward declaration */ @@ -627,6 +652,7 @@ typedef enum { resisdata.tdiTolerance = tdiTolerance; resisdata.frequency = fhFrequency; resisdata.mainDef = mainDef; + resisdata.savePlanes = (struct saveList *)NULL; /* Do subcircuits (if any) first */ HashInit(&ResProcessedTable, INITFLATSIZE, HT_STRINGKEYS); @@ -636,6 +662,13 @@ typedef enum { ExtResisForDef(mainDef, &resisdata); HashKill(&ResProcessedTable); + /* Revert substrate planes */ + for (sl = resisdata.savePlanes; sl; sl = sl->sl_next) + { + ExtRevertSubstrate(sl->sl_def, sl->sl_plane); + freeMagic(sl); + } + /* turn back on undo stuff */ UndoEnable(); #ifdef LAPLACE @@ -1337,6 +1370,14 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename) if (simDev->drain == simNode) { + if ((layoutDev->rd_fet_source != NULL) && + (layoutDev->rd_fet_drain == NULL)) + { + /* Handle source/drain-tied devices */ + if (simDev->drain == simDev->source) + layoutDev->rd_fet_drain = layoutDev->rd_fet_source; + } + if (((source = layoutDev->rd_fet_source) != NULL) && ((drain = layoutDev->rd_fet_drain) != NULL)) { diff --git a/resis/resis.h b/resis/resis.h index e4adff4a..aabee014 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -634,6 +634,7 @@ extern void ResSortByGate(); extern void ResFixDevName(); extern void ResWriteLumpFile(); extern void ResSortBreaks(); +extern Plane *extResPrepSubstrate(); /* C99 compat */ extern void ResAddToQueue();