From 8c75f81cc41d137acd374aab830be99b575f219f Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 19 Aug 2019 14:11:02 -0400 Subject: [PATCH] Revised the method for multiple extraction models per device type to be more robust and not depend on the ordering of the devices in the techfile. The extraction method now keeps a mask of which properties of the device (source/drain types, substrate type, identifier type) have been found, and will look only for device records that match what is known about the device. Added a device identifier record which is the last record before parameters if the record begins with "+". This allows marker layers to be placed over a device such that it will extract with a different type. This helps reduce the complexity of the techfile and allows certain specialized devices like RF or ESD to be identified without a separate layer type for the device. --- extract/ExtBasic.c | 759 +++++++++++++++++++++++++++++-------------- extract/ExtTech.c | 268 ++++++++------- extract/ExtTest.c | 21 +- extract/ExtTimes.c | 2 +- extract/extractInt.h | 143 ++++---- resis/ResBasic.c | 23 +- resis/ResConDCS.c | 35 +- resis/ResMain.c | 36 +- resis/ResPrint.c | 6 +- resis/ResReadSim.c | 4 +- resis/ResSimple.c | 6 +- resis/ResUtils.c | 25 +- sim/SimExtract.c | 19 +- 13 files changed, 856 insertions(+), 491 deletions(-) diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 381cdcf1..89e32cb7 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -85,8 +85,16 @@ typedef struct /* Position of each terminal (below) tile position */ Point pt; } TermTilePos; +/* Field definitions for tr_devmatch */ +#define MATCH_ID 0x01 /* Device matches identifier in devrec */ +#define MATCH_SUB 0x02 /* Device matches substrate type in devrec */ +#define MATCH_TERM 0x04 /* Device matches terminal in devrec */ +/* (additional fields: bit shifts up by 1 for each defined device terminal) */ + struct transRec { + ExtDevice *tr_devrec; /* Device record in ExtCurStyle */ + int tr_devmatch; /* Fields of tr_devrec that match device */ int tr_nterm; /* Number of terminals */ int tr_gatelen; /* Perimeter of connection to gate */ NodeRegion *tr_gatenode; /* Node region for gate terminal */ @@ -134,6 +142,7 @@ void extOutputNodes(); int extTransTileFunc(); int extTransPerimFunc(); int extTransFindSubs(); +int extTransFindId(); int extAnnularTileFunc(); int extResistorTileFunc(); @@ -214,8 +223,8 @@ extBasic(def, outFile) * the regions. */ transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect, - &ExtCurStyle->exts_transMask, - ExtCurStyle->exts_transConn, + &ExtCurStyle->exts_deviceMask, + ExtCurStyle->exts_deviceConn, extUnInit, extTransFirst, extTransEach); ExtResetTiles(def, extUnInit); @@ -241,7 +250,7 @@ extBasic(def, outFile) scontext.scx_area.r_ur.p_x++; scontext.scx_area.r_ur.p_y++; - if (DBTreeSrTiles(&scontext, &ExtCurStyle->exts_transMask, 0, + if (DBTreeSrTiles(&scontext, &ExtCurStyle->exts_deviceMask, 0, extFoundFunc, (ClientData)def) != 0) reg->treg_type = TT_SPACE; /* Disables the trans record */ } @@ -1429,6 +1438,7 @@ extOutputParameters(def, transList, outFile) TransRegion *reg; TileType t; TileTypeBitMask tmask; + ExtDevice *devptr; TTMaskZero(&tmask); @@ -1450,86 +1460,47 @@ extOutputParameters(def, transList, outFile) { if (TTMaskHasType(&tmask, t)) { - plist = ExtCurStyle->exts_deviceParams[t]; - if (plist != (ParamList *)NULL) + /* Note: If there are multiple variants of a device type, they */ + /* will all be listed even if they are not all present in the */ + /* design. */ + + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) { - fprintf(outFile, "parameters %s", ExtCurStyle->exts_transName[t]); - for (; plist != NULL; plist = plist->pl_next) + plist = devptr->exts_deviceParams; + if (plist != (ParamList *)NULL) { - if (plist->pl_param[1] != '\0') + fprintf(outFile, "parameters %s", devptr->exts_deviceName); + for (; plist != NULL; plist = plist->pl_next) { - if (plist->pl_scale != 1.0) - fprintf(outFile, " %c%c=%s*%g", + if (plist->pl_param[1] != '\0') + { + if (plist->pl_scale != 1.0) + fprintf(outFile, " %c%c=%s*%g", plist->pl_param[0], plist->pl_param[1], plist->pl_name, plist->pl_scale); - else - fprintf(outFile, " %c%c=%s", plist->pl_param[0], + else + fprintf(outFile, " %c%c=%s", plist->pl_param[0], plist->pl_param[1], plist->pl_name); - } - else - { - if (plist->pl_scale != 1.0) - fprintf(outFile, " %c=%s*%g", + } + else + { + if (plist->pl_scale != 1.0) + fprintf(outFile, " %c=%s*%g", plist->pl_param[0], plist->pl_name, plist->pl_scale); - else - fprintf(outFile, " %c=%s", plist->pl_param[0], + else + fprintf(outFile, " %c=%s", plist->pl_param[0], plist->pl_name); + + } } + fprintf(outFile, "\n"); } - fprintf(outFile, "\n"); } } } } -/* - * ---------------------------------------------------------------------------- - * - * extGetNativeResistClass() -- - * - * For the purpose of generating a node area and perimeter value to output - * to a subcircuit call as a passed parameter. The value output is assumed - * to refer only to the part of the whole eletrical node that is the - * actual device node, not to include connected metal, contacts, etc. - * Since area and perimeter information about a node is separated into - * resist classes, we need to figure out which resist class belongs to - * the device terminal type. - * - * "type" is the type identifier for the device (e.g., gate). "term" is - * the index of the terminal for the device. Devices with symmetrical - * terminals (e.g., MOSFETs), may have fewer type masks than terminals. - * - * ---------------------------------------------------------------------------- - */ - -int -extGetNativeResistClass(type, term) - TileType type; - int term; -{ - TileTypeBitMask *tmask, *rmask; - int i, n; - - tmask = NULL; - for (i = 0;; i++) - { - rmask = &ExtCurStyle->exts_transSDTypes[type][i]; - if (TTMaskIsZero(rmask)) break; - tmask = rmask; - if (i == term) break; - } - if (tmask == NULL) return -1; /* Error */ - - for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) - { - rmask = &ExtCurStyle->exts_typesByResistClass[n]; - if (TTMaskIntersect(rmask, tmask)) - return n; - } - return -1; /* Error */ -} - /* * ---------------------------------------------------------------------------- * @@ -1549,16 +1520,16 @@ extGetNativeResistClass(type, term) */ void -extOutputDevParams(reg, t, outFile, length, width) +extOutputDevParams(reg, devptr, outFile, length, width) TransRegion *reg; - TileType t; + ExtDevice *devptr; FILE *outFile; int length; int width; { ParamList *chkParam; - for (chkParam = ExtCurStyle->exts_deviceParams[t]; chkParam + for (chkParam = devptr->exts_deviceParams; chkParam != NULL; chkParam = chkParam->pl_next) { switch(tolower(chkParam->pl_param[0])) @@ -1585,9 +1556,9 @@ extOutputDevParams(reg, t, outFile, length, width) break; case 'c': fprintf(outFile, " %c=%g", chkParam->pl_param[0], - (ExtCurStyle->exts_transGateCap[t] + (extTransRec.tr_devrec->exts_deviceGateCap * reg->treg_area) + - (ExtCurStyle->exts_transSDCap[t] + (extTransRec.tr_devrec->exts_deviceSDCap * extTransRec.tr_perim)); break; case 's': @@ -1625,7 +1596,7 @@ extOutputDevParams(reg, t, outFile, length, width) * None. * * Side effects: - * Writes a number of 'fet' records to the file 'outFile'. + * Writes a number of 'device' records to the file 'outFile'. * * Interruptible. If SigInterruptPending is detected, we stop traversing * the transistor list and return. @@ -1641,6 +1612,7 @@ extOutputDevices(def, transList, outFile) { NodeRegion *node, *subsNode; TransRegion *reg; + ExtDevice *devptr; char *subsName; FindRegion arg; LabelList *ll; @@ -1663,13 +1635,15 @@ extOutputDevices(def, transList, outFile) * them with 'reg', then visit them again re-marking them with * the gate node (extGetRegion(reg->treg_tile)). */ + extTransRec.tr_devrec = (ExtDevice *)NULL; + extTransRec.tr_devmatch = 0; extTransRec.tr_nterm = 0; extTransRec.tr_gatelen = 0; extTransRec.tr_perim = 0; extTransRec.tr_subsnode = (NodeRegion *)NULL; arg.fra_def = def; - arg.fra_connectsTo = ExtCurStyle->exts_transConn; + arg.fra_connectsTo = ExtCurStyle->exts_deviceConn; extTransRec.tr_gatenode = (NodeRegion *) extGetRegion(reg->treg_tile); t = reg->treg_type; @@ -1686,7 +1660,6 @@ extOutputDevices(def, transList, outFile) /* 5/30/09---but, reinitialize the array out to MAXSD, */ /* or devices declaring minterms < maxterms screw up! */ - nsd = ExtCurStyle->exts_transSDCount[t]; for (i = 0; i < MAXSD; i++) extTransRec.tr_termnode[i] = NULL; /* Mark with reg and process each perimeter segment */ @@ -1712,16 +1685,20 @@ extOutputDevices(def, transList, outFile) /* search fails, give up and proceed with the reduced */ /* number of terminals. */ + devptr = extTransRec.tr_devrec; + if (devptr == NULL) continue; /* Bad device; do not output */ + + nsd = devptr->exts_deviceSDCount; while (extTransRec.tr_nterm < nsd) { TileTypeBitMask *tmask; - tmask = &ExtCurStyle->exts_transSDTypes[t][extTransRec.tr_nterm]; + tmask = &devptr->exts_deviceSDTypes[extTransRec.tr_nterm]; if (TTMaskIsZero(tmask)) break; if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])) { node = NULL; - extTransFindSubs(reg->treg_tile, t, tmask, def, &node); + extTransFindSubs(reg->treg_tile, t, tmask, def, &node, NULL); if (node == NULL) break; extTransRec.tr_termnode[extTransRec.tr_nterm++] = node; } @@ -1774,18 +1751,18 @@ extOutputDevices(def, transList, outFile) /* * Output the transistor record. - * The type is ExtCurStyle->exts_transName[t], which should have + * The type is devptr->exts_deviceName, which should have * some meaning to the simulator we are producing this file for. * Use the default substrate node unless the transistor overlaps - * material whose type is in exts_transSubstrateTypes, in which + * material whose type is in exts_deviceSubstrateTypes, in which * case we use the node of the overlapped material. * * Technology files using the "substrate" keyword (magic-8.1 or * newer) should have the text "error" in the substrate node * name. */ - subsName = ExtCurStyle->exts_transSubstrateName[t]; - if (!TTMaskIsZero(&ExtCurStyle->exts_transSubstrateTypes[t]) + subsName = devptr->exts_deviceSubstrateName; + if (!TTMaskIsZero(&devptr->exts_deviceSubstrateTypes) && (subsNode = extTransRec.tr_subsnode)) { subsName = extNodeName(subsNode); @@ -1809,12 +1786,12 @@ extOutputDevices(def, transList, outFile) #endif /* Original-style FET record backward compatibility */ - if (ExtCurStyle->exts_deviceClass[t] != DEV_FET) + if (devptr->exts_deviceClass != DEV_FET) fprintf(outFile, "device "); fprintf(outFile, "%s %s", - extDevTable[ExtCurStyle->exts_deviceClass[t]], - ExtCurStyle->exts_transName[t]); + extDevTable[devptr->exts_deviceClass], + devptr->exts_deviceName); fprintf(outFile, " %d %d %d %d", reg->treg_ll.p_x, reg->treg_ll.p_y, @@ -1830,7 +1807,7 @@ extOutputDevices(def, transList, outFile) /* etc., etc. */ /* Tim, 2/20/03 */ - switch (ExtCurStyle->exts_deviceClass[t]) + switch (devptr->exts_deviceClass) { case DEV_FET: /* old style, perimeter & area */ fprintf(outFile, " %d %d \"%s\"", @@ -1887,7 +1864,7 @@ extOutputDevices(def, transList, outFile) /* because the substrate node (i.e., well) is the */ /* other terminal. */ - if (ExtDoWarn && (ExtCurStyle->exts_transSDCount[t] > 0)) + if (ExtDoWarn && (devptr->exts_deviceSDCount > 0)) extTransBad(def, reg->treg_tile, "Could not determine device boundary"); length = width = 0; @@ -1929,14 +1906,14 @@ extOutputDevices(def, transList, outFile) } - if (ExtCurStyle->exts_deviceClass[t] == DEV_MOSFET || - ExtCurStyle->exts_deviceClass[t] == DEV_ASYMMETRIC || - ExtCurStyle->exts_deviceClass[t] == DEV_BJT) + if (devptr->exts_deviceClass == DEV_MOSFET || + devptr->exts_deviceClass == DEV_ASYMMETRIC || + devptr->exts_deviceClass == DEV_BJT) { fprintf(outFile, " %d %d", length, width); } - extOutputDevParams(reg, t, outFile, length, width); + extOutputDevParams(reg, devptr, outFile, length, width); fprintf(outFile, " \"%s\"", (subsName == NULL) ? "None" : subsName); @@ -1945,14 +1922,14 @@ extOutputDevices(def, transList, outFile) case DEV_DIODE: /* Only handle the optional substrate node */ case DEV_NDIODE: case DEV_PDIODE: - extOutputDevParams(reg, t, outFile, length, width); + extOutputDevParams(reg, devptr, outFile, length, width); if (subsName != NULL) fprintf(outFile, " \"%s\"", subsName); break; case DEV_RES: case DEV_RSUBCKT: - hasModel = strcmp(ExtCurStyle->exts_transName[t], "None"); + hasModel = strcmp(devptr->exts_deviceName, "None"); length = extTransRec.tr_perim; isAnnular = FALSE; @@ -2059,7 +2036,7 @@ extOutputDevices(def, transList, outFile) "Resistor has zero width"); } - if (ExtCurStyle->exts_deviceClass[t] == DEV_RSUBCKT) + if (devptr->exts_deviceClass == DEV_RSUBCKT) { /* nothing */ } @@ -2072,9 +2049,9 @@ extOutputDevices(def, transList, outFile) else /* regular resistor */ fprintf(outFile, " %g", dres / 1000.0); /* mOhms -> Ohms */ - extOutputDevParams(reg, t, outFile, length, width); + extOutputDevParams(reg, devptr, outFile, length, width); - if (ExtCurStyle->exts_deviceClass[t] == DEV_RSUBCKT) + if (devptr->exts_deviceClass == DEV_RSUBCKT) { fprintf(outFile, " \"%s\"", (subsName == NULL) ? "None" : subsName); @@ -2085,7 +2062,7 @@ extOutputDevices(def, transList, outFile) case DEV_CAP: case DEV_CAPREV: case DEV_CSUBCKT: - hasModel = strcmp(ExtCurStyle->exts_transName[t], "None"); + hasModel = strcmp(devptr->exts_deviceName, "None"); if (hasModel) { for (n = 0; n < extTransRec.tr_nterm && @@ -2143,7 +2120,7 @@ extOutputDevices(def, transList, outFile) (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); } - if (ExtCurStyle->exts_deviceClass[t] == DEV_CSUBCKT) + if (devptr->exts_deviceClass == DEV_CSUBCKT) { /* (Nothing) */ } @@ -2163,9 +2140,9 @@ extOutputDevices(def, transList, outFile) fprintf(outFile, " \"%s\"", subsName); } - extOutputDevParams(reg, t, outFile, length, width); + extOutputDevParams(reg, devptr, outFile, length, width); - if (ExtCurStyle->exts_deviceClass[t] == DEV_CSUBCKT) + if (devptr->exts_deviceClass == DEV_CSUBCKT) { fprintf(outFile, " \"%s\"", (subsName == NULL) ? "None" : subsName); @@ -2173,8 +2150,8 @@ extOutputDevices(def, transList, outFile) } else { - dcap = (ExtCurStyle->exts_transGateCap[t] * reg->treg_area) + - (ExtCurStyle->exts_transSDCap[t] * extTransRec.tr_perim); + dcap = (devptr->exts_deviceGateCap * reg->treg_area) + + (devptr->exts_deviceSDCap * extTransRec.tr_perim); fprintf(outFile, " %g", dcap / 1000.0); /* aF -> fF */ } @@ -2191,7 +2168,7 @@ extOutputDevices(def, transList, outFile) /* device is asymmetric, in which case source and drain do not */ /* permute, and the terminal order is fixed. */ - if (TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[t][1])) + if (TTMaskIsZero(&devptr->exts_deviceSDTypes[1])) ExtSortTerminals(&extTransRec, ll); /* each non-gate terminal */ @@ -2203,17 +2180,29 @@ extOutputDevices(def, transList, outFile) } } +/* Structure to hold a node region and a tile type */ + +typedef struct _node_type { + NodeRegion *region; + TileType layer; +} NodeAndType; + int -extTransFindSubs(tile, t, mask, def, sn) +extTransFindSubs(tile, t, mask, def, sn, layerptr) Tile *tile; TileType t; TileTypeBitMask *mask; CellDef *def; NodeRegion **sn; + TileType *layerptr; { Rect tileArea; int pNum; int extTransFindSubsFunc1(); /* Forward declaration */ + NodeAndType noderec; + + noderec.region = (NodeRegion *)NULL; + noderec.layer = TT_SPACE; TiToRect(tile, &tileArea); for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) @@ -2221,7 +2210,65 @@ extTransFindSubs(tile, t, mask, def, sn) if (TTMaskIntersect(&DBPlaneTypes[pNum], mask)) { if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &tileArea, - mask, extTransFindSubsFunc1, (ClientData)sn)) + mask, extTransFindSubsFunc1, (ClientData)&noderec)) + { + *sn = noderec.region; + if (layerptr) *layerptr = noderec.layer; + return 1; + } + } + } + return 0; +} + +int +extTransFindSubsFunc1(tile, noderecptr) + Tile *tile; + NodeAndType *noderecptr; +{ + TileType type; + + /* Report split substrate region errors (two different substrate + * regions under the same device) + */ + + if (tile->ti_client != (ClientData) extUnInit) + { + if ((noderecptr->region != (NodeRegion *)NULL) && + (noderecptr->region != tile->ti_client)) + TxError("Warning: Split substrate under device at (%d %d)\n", + tile->ti_ll.p_x, tile->ti_ll.p_y); + if (IsSplit(tile)) + type = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + else + type = TiGetTypeExact(tile); + + noderecptr->region = (NodeRegion *)tile->ti_client; + noderecptr->layer = type; + return 1; + } + return 0; +} + +int +extTransFindId(tile, mask, def, idtypeptr) + Tile *tile; + TileTypeBitMask *mask; + CellDef *def; + TileType *idtypeptr; +{ + TileType type; + Rect tileArea; + int pNum; + int extTransFindIdFunc1(); /* Forward declaration */ + + TiToRect(tile, &tileArea); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (TTMaskIntersect(&DBPlaneTypes[pNum], mask)) + { + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &tileArea, + mask, extTransFindIdFunc1, (ClientData)idtypeptr)) return 1; } } @@ -2229,24 +2276,92 @@ extTransFindSubs(tile, t, mask, def, sn) } int -extTransFindSubsFunc1(tile, sn) +extTransFindIdFunc1(tile, idtypeptr) Tile *tile; - NodeRegion **sn; + TileType *idtypeptr; { - /* Report split substrate region errors (two different substrate - * regions under the same device) + /* + * ID Layer found overlapping device area, so return 1 to halt search. */ + if (IsSplit(tile)) + *idtypeptr = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + else + *idtypeptr = TiGetTypeExact(tile); - if (tile->ti_client != (ClientData) extUnInit) + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * extDevFindMatch -- + * + * Find and return the next matching device record. extTransRec is queried + * to find how many fields have been matched to the device already. Then + * it finds the next record with the same matching fields. Because records + * are in no specific order, it will loop to the beginning of the records + * after reaching the end. It is the responsibility of the calling routine to + * determine if all matching devices have been tested. + * + * deventry is the record position to start the search. + * t is the tile type of the device. + * ---------------------------------------------------------------------------- + */ + +ExtDevice * +extDevFindMatch(deventry, t) + ExtDevice *deventry; + TileType t; +{ + ExtDevice *devptr; + int i, j, matchflags; + bool match; + + matchflags = extTransRec.tr_devmatch; + + if (deventry->exts_next == NULL) + devptr = ExtCurStyle->exts_device[t]; + else + devptr = deventry->exts_next; + + for (; devptr != deventry; + devptr = (devptr->exts_next) ? devptr->exts_next : + ExtCurStyle->exts_device[t]) { - if ((*sn != (NodeRegion *)NULL) && (*sn != tile->ti_client)) - TxError("Warning: Split substrate under device at (%d %d)\n", - tile->ti_ll.p_x, tile->ti_ll.p_y); + if (matchflags == 0) break; /* Always return next entry */ - *sn = (NodeRegion *) tile->ti_client; - return 1; + if (matchflags & MATCH_ID) /* Must have the same identifier */ + if (!TTMaskEqual(&devptr->exts_deviceIdentifierTypes, + &deventry->exts_deviceIdentifierTypes)) continue; + + if (matchflags & MATCH_SUB) /* Must have the same substrate type */ + if (!TTMaskEqual(&devptr->exts_deviceSubstrateTypes, + &deventry->exts_deviceSubstrateTypes)) continue; + + j = MATCH_TERM; + match = True; + for (i = 0; i < MAXSD; i++) + { + if (extTransRec.tr_termnode[i] == NULL) break; + if (matchflags & j) /* Must have the same terminal type */ + { + if (TTMaskIsZero(&devptr->exts_deviceSDTypes[i])) + { + match = False; + break; + } + if (!TTMaskEqual(&devptr->exts_deviceSDTypes[i], + &deventry->exts_deviceSDTypes[i])) + { + match = False; + break; + } + } + j >>= 1; + } + if (match) break; } - return 0; + return (devptr == deventry) ? NULL : devptr; } /* @@ -2273,10 +2388,12 @@ extTransTileFunc(tile, pNum, arg) int pNum; FindRegion *arg; { - TileTypeBitMask mask; - TileType loctype; - int perim; + TileTypeBitMask mask, cmask, *smask; + TileType loctype, idlayer, sublayer; + int perim, result; bool allow_globsubsnode; + ExtDevice *devptr, *deventry, *devtest; + NodeRegion *region; LabelList *ll; Label *lab; @@ -2306,7 +2423,7 @@ extTransTileFunc(tile, pNum, arg) else loctype = TiGetTypeExact(tile); - mask = ExtCurStyle->exts_transConn[loctype]; + mask = ExtCurStyle->exts_deviceConn[loctype]; TTMaskCom(&mask); /* NOTE: DO NOT USE extTransRec.tr_perim += extEnumTilePerim(...) */ @@ -2317,32 +2434,146 @@ extTransTileFunc(tile, pNum, arg) extTransPerimFunc, (ClientData)NULL); extTransRec.tr_perim += perim; - allow_globsubsnode = FALSE; - if (extTransRec.tr_subsnode == (NodeRegion *)NULL) - { - TileTypeBitMask *smask; + devptr = extTransRec.tr_devrec; + if (devptr == NULL) return 0; /* No matching devices, so forget it. */ - smask = &ExtCurStyle->exts_transSubstrateTypes[loctype]; - if (TTMaskHasType(smask, TT_SPACE)) - { - allow_globsubsnode = TRUE; - TTMaskClearType(smask, TT_SPACE); - } - extTransFindSubs(tile, loctype, smask, arg->fra_def, &extTransRec.tr_subsnode); - if (allow_globsubsnode) - TTMaskSetType(smask, TT_SPACE); + allow_globsubsnode = FALSE; + + /* Create a mask of all substrate types of all device records, and */ + /* search for substrate types on this combined mask. */ + + TTMaskZero(&cmask); + for (devtest = ExtCurStyle->exts_device[loctype]; devtest; + devtest = devtest->exts_next) + TTMaskSetMask(&cmask, &devtest->exts_deviceSubstrateTypes); + + if (TTMaskHasType(&cmask, TT_SPACE)) + { + allow_globsubsnode = TRUE; + TTMaskClearType(&cmask, TT_SPACE); } - /* If the transistor does not connect to a defined node, and - * the substrate types include "space", then it is assumed to - * connect to the global substrate. - */ - if (extTransRec.tr_subsnode == (NodeRegion *)NULL) - if (allow_globsubsnode) - extTransRec.tr_subsnode = glob_subsnode; + { + sublayer = TT_SPACE; + region = NULL; + extTransFindSubs(tile, loctype, &cmask, arg->fra_def, ®ion, &sublayer); - return (0); + /* If the device does not connect to a defined node, and + * the substrate types include "space", then it is assumed to + * connect to the global substrate. + */ + + if (region == (NodeRegion *)NULL) + if (allow_globsubsnode) + region = glob_subsnode; + + extTransRec.tr_subsnode = region; + + if ((region != (NodeRegion *)NULL) && + !(TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer))) + { + /* A substrate layer was found but is not compatible with the */ + /* current device. Find a device record with the substrate */ + /* layer that was found, and set the substrate match flag. */ + + deventry = devptr; + while (devptr != NULL) + { + devptr = extDevFindMatch(devptr, loctype); + if ((devptr == NULL) || (devptr == deventry)) + { + TxError("No matching device for %s with substrate layer %s\n", + DBTypeLongNameTbl[loctype], DBTypeLongNameTbl[sublayer]); + devptr = NULL; + break; + } + if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer)) + { + extTransRec.tr_devmatch |= MATCH_SUB; + break; + } + } + } + else if (region == (NodeRegion *)NULL) + { + TxError("Device %s does not have a compatible substrate node!\n", + DBTypeLongNameTbl[loctype]); + devptr = NULL; + } + } + extTransRec.tr_devrec = devptr; + if (devptr == NULL) return 0; /* No matching devices, so forget it. */ + + /* If at least one device type declares an ID layer, then make a */ + /* mask of all device ID types, and search on the area of the */ + /* device to see if any device identifier layers are found. */ + + TTMaskZero(&cmask); + for (devtest = ExtCurStyle->exts_device[loctype]; devtest; + devtest = devtest->exts_next) + TTMaskSetMask(&cmask, &devtest->exts_deviceIdentifierTypes); + + if (!TTMaskIsZero(&cmask)) + { + idlayer = TT_SPACE; + extTransFindId(tile, &cmask, arg->fra_def, &idlayer); + + if ((idlayer == TT_SPACE) && !TTMaskIsZero(&devptr->exts_deviceIdentifierTypes)) + { + /* Device expected an ID layer but none was present. Find a device */ + /* record with no ID layer, and set the ID match flag. */ + + deventry = devptr; + while (devptr != NULL) + { + devptr = extDevFindMatch(devptr, loctype); + if ((devptr == NULL) || (devptr == deventry)) + { + TxError("No matching device for %s with no ID layer\n", + DBTypeLongNameTbl[loctype]); + devptr = NULL; + break; + } + if (TTMaskIsZero(&devptr->exts_deviceIdentifierTypes)) + { + extTransRec.tr_devmatch |= MATCH_ID; + break; + } + } + } + else if ((idlayer != TT_SPACE) && + !TTMaskHasType(&devptr->exts_deviceIdentifierTypes, idlayer)) + { + /* Device expected no ID layer but one was present. Find a device */ + /* record with the ID layer and set the ID match flag. If there is */ + /* a valid device without the ID layer, then ignore the ID layer */ + /* and flag a warning. */ + + deventry = devptr; + while (devptr != NULL) + { + devptr = extDevFindMatch(devptr, loctype); + if ((devptr == NULL) || (devptr == deventry)) + { + TxError("ID layer %s on non-matching device %s was ignored.\n", + DBTypeLongNameTbl[idlayer], DBTypeLongNameTbl[loctype]); + devptr = deventry; + break; + } + if (TTMaskHasType(&devptr->exts_deviceIdentifierTypes, idlayer)) + { + extTransRec.tr_devmatch |= MATCH_ID; + break; + } + } + } + else + extTransRec.tr_devmatch |= MATCH_ID; + } + extTransRec.tr_devrec = devptr; + + return 0; } int @@ -2352,6 +2583,7 @@ extTransPerimFunc(bp) TileType tinside, toutside; Tile *tile; NodeRegion *diffNode = (NodeRegion *) extGetRegion(bp->b_outside); + ExtDevice *devptr, *deventry; int i, len = BoundaryLength(bp); int thisterm; LabelList *ll; @@ -2370,115 +2602,138 @@ extTransPerimFunc(bp) else toutside = TiGetTypeExact(bp->b_outside); - for (i = 0; !TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][i]); i++) + if (extTransRec.tr_devrec != NULL) + devptr = extTransRec.tr_devrec; + else + devptr = ExtCurStyle->exts_device[tinside]; + + deventry = devptr; + while(devptr) { - /* TT_SPACE is allowed, for declaring that a device terminal is */ - /* the substrate. However, it should not be in the plane of */ - /* the device identifier layer, so space tiles should never be */ - /* flagged during a device perimeter search. */ - - if (toutside == TT_SPACE) break; - - if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[tinside][i], toutside)) + extTransRec.tr_devrec = devptr; + for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) { - /* - * It's a diffusion terminal (source or drain). See if the node is - * already in our table; add it if it wasn't already there. - * Asymmetric devices must have terminals in order. - */ - if (TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][1])) + /* TT_SPACE is allowed, for declaring that a device terminal is */ + /* the substrate. However, it should not be in the plane of */ + /* the device identifier layer, so space tiles should never be */ + /* flagged during a device perimeter search. */ + + if (toutside == TT_SPACE) break; + + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) { - for (thisterm = 0; thisterm < extTransRec.tr_nterm; thisterm++) - if (extTransRec.tr_termnode[thisterm] == diffNode) - break; - } - else - thisterm = i; - - if (extTransRec.tr_termnode[thisterm] == NULL) - { - extTransRec.tr_nterm++; - extTransRec.tr_termnode[thisterm] = diffNode; - extTransRec.tr_termlen[thisterm] = 0; - extTransRec.tr_termvector[thisterm].p_x = 0; - extTransRec.tr_termvector[thisterm].p_y = 0; - extTransRec.tr_termpos[thisterm].pnum = DBPlane(toutside); - extTransRec.tr_termpos[thisterm].pt = bp->b_outside->ti_ll; - - /* Find the total area of this terminal */ - } - else if (extTransRec.tr_termnode[thisterm] == diffNode) - { - TermTilePos *pos = &(extTransRec.tr_termpos[thisterm]); - Tile *otile = bp->b_outside; - - /* update the region tile position */ - - if( DBPlane(TiGetType(otile)) < pos->pnum ) + /* + * It's a diffusion terminal (source or drain). See if the node is + * already in our table; add it if it wasn't already there. + * Asymmetric devices must have terminals in order. + */ + if (TTMaskIsZero(&devptr->exts_deviceSDTypes[1])) { - pos->pnum = DBPlane(TiGetType(otile)); - pos->pt = otile->ti_ll; + for (thisterm = 0; thisterm < extTransRec.tr_nterm; thisterm++) + if (extTransRec.tr_termnode[thisterm] == diffNode) + break; } - else if( DBPlane(TiGetType(otile)) == pos->pnum ) + else + thisterm = i; + + if (extTransRec.tr_termnode[thisterm] == NULL) { - if( LEFT(otile) < pos->pt.p_x ) + extTransRec.tr_nterm++; + extTransRec.tr_termnode[thisterm] = diffNode; + extTransRec.tr_termlen[thisterm] = 0; + extTransRec.tr_termvector[thisterm].p_x = 0; + extTransRec.tr_termvector[thisterm].p_y = 0; + extTransRec.tr_termpos[thisterm].pnum = DBPlane(toutside); + extTransRec.tr_termpos[thisterm].pt = bp->b_outside->ti_ll; + + /* Find the total area of this terminal */ + } + else if (extTransRec.tr_termnode[thisterm] == diffNode) + { + TermTilePos *pos = &(extTransRec.tr_termpos[thisterm]); + Tile *otile = bp->b_outside; + + /* update the region tile position */ + + if( DBPlane(TiGetType(otile)) < pos->pnum ) + { + pos->pnum = DBPlane(TiGetType(otile)); pos->pt = otile->ti_ll; - else if( LEFT(otile) == pos->pt.p_x && + } + else if( DBPlane(TiGetType(otile)) == pos->pnum ) + { + if( LEFT(otile) < pos->pt.p_x ) + pos->pt = otile->ti_ll; + else if( LEFT(otile) == pos->pt.p_x && BOTTOM(otile) < pos->pt.p_y ) - pos->pt.p_y = BOTTOM(otile); + pos->pt.p_y = BOTTOM(otile); + } } - } - else - { - TxError("Error: Asymmetric device with multiple terminals!\n"); - } - - /* Add the length to this terminal's perimeter */ - extTransRec.tr_termlen[thisterm] += len; - - /* Update the boundary traversal vector */ - switch(bp->b_direction) { - case BD_LEFT: - extTransRec.tr_termvector[thisterm].p_y += len; - break; - case BD_TOP: - extTransRec.tr_termvector[thisterm].p_x += len; - break; - case BD_RIGHT: - extTransRec.tr_termvector[thisterm].p_y -= len; - break; - case BD_BOTTOM: - extTransRec.tr_termvector[thisterm].p_x -= len; - break; - } - - /* - * Mark this attribute as belonging to this transistor - * if it is either: - * (1) a terminal attribute whose LL corner touches bp->b_segment, - * or (2) a gate attribute that lies inside bp->b_inside. - */ - for (ll = extTransRec.tr_gatenode->nreg_labels; ll; ll = ll->ll_next) - { - /* Skip if already marked */ - if (ll->ll_attr != LL_NOATTR) - continue; - lab = ll->ll_label; - if (GEO_ENCLOSE(&lab->lab_rect.r_ll, &bp->b_segment) - && extLabType(lab->lab_text, LABTYPE_TERMATTR)) + else { - ll->ll_attr = thisterm; + TxError("Error: Asymmetric device with multiple terminals!\n"); } + + /* Add the length to this terminal's perimeter */ + extTransRec.tr_termlen[thisterm] += len; + + /* Update the boundary traversal vector */ + switch(bp->b_direction) { + case BD_LEFT: + extTransRec.tr_termvector[thisterm].p_y += len; + break; + case BD_TOP: + extTransRec.tr_termvector[thisterm].p_x += len; + break; + case BD_RIGHT: + extTransRec.tr_termvector[thisterm].p_y -= len; + break; + case BD_BOTTOM: + extTransRec.tr_termvector[thisterm].p_x -= len; + break; + } + + /* + * Mark this attribute as belonging to this transistor + * if it is either: + * (1) a terminal attribute whose LL corner touches bp->b_segment, + * or (2) a gate attribute that lies inside bp->b_inside. + */ + for (ll = extTransRec.tr_gatenode->nreg_labels; ll; ll = ll->ll_next) + { + /* Skip if already marked */ + if (ll->ll_attr != LL_NOATTR) + continue; + lab = ll->ll_label; + if (GEO_ENCLOSE(&lab->lab_rect.r_ll, &bp->b_segment) + && extLabType(lab->lab_text, LABTYPE_TERMATTR)) + { + ll->ll_attr = thisterm; + } + } + SDterm = TRUE; + extTransRec.tr_devmatch |= (MATCH_TERM << thisterm); + break; } - SDterm = TRUE; + } + + if (SDterm) break; + if (extConnectsTo(tinside, toutside, ExtCurStyle->exts_nodeConn)) + { + /* Not in a terminal, but are in something that connects to gate */ + extTransRec.tr_gatelen += len; break; } - } - if (!SDterm && extConnectsTo(tinside, toutside, ExtCurStyle->exts_nodeConn)) + /* Did not find a matching terminal, so see if a different extraction */ + /* record matches the terminal type. */ + devptr = extDevFindMatch(devptr, tinside); + if (devptr == deventry) devptr = NULL; + } + if (devptr == NULL) { - /* Not in a terminal, but are in something that connects to gate */ - extTransRec.tr_gatelen += len; + TxError("Error: Cannot find valid terminals on device %s!\n", + DBTypeLongNameTbl[tinside]); } /* @@ -2532,7 +2787,7 @@ extAnnularTileFunc(tile, pNum) else loctype = TiGetTypeExact(tile); - mask = ExtCurStyle->exts_transConn[loctype]; + mask = ExtCurStyle->exts_deviceConn[loctype]; TTMaskCom(&mask); extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData) TRUE); return (0); @@ -2569,6 +2824,7 @@ extResistorTileFunc(tile, pNum) { TileTypeBitMask mask; TileType loctype; + ExtDevice *devptr; /* * Visit each segment of the perimeter of this tile that @@ -2581,11 +2837,21 @@ extResistorTileFunc(tile, pNum) else loctype = TiGetTypeExact(tile); - mask = ExtCurStyle->exts_transConn[loctype]; - TTMaskSetMask(&mask, &ExtCurStyle->exts_transSDTypes[loctype][0]); - TTMaskCom(&mask); + mask = ExtCurStyle->exts_deviceConn[loctype]; - extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData)FALSE); + devptr = extTransRec.tr_devrec; + if (devptr == NULL) devptr = ExtCurStyle->exts_device[loctype]; + + while (devptr) + { + TTMaskSetMask(&mask, &devptr->exts_deviceSDTypes[0]); + TTMaskCom(&mask); + + extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData)FALSE); + + if (extSpecialBounds[0] == NULL) devptr = devptr->exts_next; + } + if (devptr != NULL) extTransRec.tr_devrec = devptr; return (0); } @@ -2605,6 +2871,7 @@ extSpecialPerimFunc(bp, sense) NodeRegion *diffNode = (NodeRegion *) extGetRegion(bp->b_outside); int thisterm, extended, i; LinkedBoundary *newBound, *lb, *lastlb; + ExtDevice *devptr; bool needSurvey; /* Note that extEnumTilePerim() assumes for the non-Manhattan case */ @@ -2633,19 +2900,27 @@ extSpecialPerimFunc(bp, sense) break; } + devptr = extTransRec.tr_devrec; + if (devptr == NULL) devptr = ExtCurStyle->exts_device[tinside]; + /* Check all terminal classes for a matching type */ needSurvey = FALSE; - for (i = 0; !TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][i]); i++) + for (; devptr; devptr = devptr->exts_next) { - if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[tinside][i], toutside)) + for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) { - needSurvey = TRUE; - break; + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) + { + needSurvey = TRUE; + break; + } } } if (!sense || needSurvey) { + extTransRec.tr_devrec = devptr; + if (toutside == TT_SPACE) if (glob_subsnode != NULL) diffNode = glob_subsnode; diff --git a/extract/ExtTech.c b/extract/ExtTech.c index c4744879..d778749d 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -299,36 +299,41 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) TileTypeBitMask *rmask, *tmask; int n, i = 0, j; bool repeat; + ExtDevice *devptr; char *locdname; char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *)); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { - locdname = ExtCurStyle->exts_transName[t]; - if (locdname != NULL) + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) { - repeat = FALSE; - for (j = 0; j < i; j++) - if (!strcmp(uniquenamelist[j], locdname)) - { - repeat = TRUE; - break; - } - if (repeat == FALSE) + locdname = devptr->exts_deviceName; + if (locdname != NULL) { - if (i == idx) break; - uniquenamelist[i] = locdname; - i++; + repeat = FALSE; + for (j = 0; j < i; j++) + if (!strcmp(uniquenamelist[j], locdname)) + { + repeat = TRUE; + break; + } + if (repeat == FALSE) + { + if (i == idx) break; + uniquenamelist[i] = locdname; + i++; + } } } } if (t == DBNumTypes) return FALSE; + if (devptr == NULL) return FALSE; *devnameptr = locdname; - *subnameptr = ExtCurStyle->exts_transSubstrateName[t]; + *subnameptr = devptr->exts_deviceSubstrateName; - tmask = &ExtCurStyle->exts_transSDTypes[t][0]; + tmask = &devptr->exts_deviceSDTypes[0]; *sd_rclassptr = (short)(-1); /* NO_RESCLASS */ for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) @@ -341,7 +346,7 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) } } - tmask = &ExtCurStyle->exts_transSubstrateTypes[t]; + tmask = &devptr->exts_deviceSubstrateTypes; *sub_rclassptr = (short)(-1); /* NO_RESCLASS */ for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) @@ -538,23 +543,10 @@ extTechStyleAlloc() TileType r; style = (ExtStyle *) mallocMagic(sizeof (ExtStyle)); - - /* Make sure that the memory for character strings is NULL, */ - /* because we want the Init section to free memory if it */ - /* has been previously allocated. */ - - for (r = 0; r < NT; r++) - { - style->exts_transSubstrateName[r] = (char *) NULL; - style->exts_transName[r] = (char *) NULL; - style->exts_transSDTypes[r] = (TileTypeBitMask *) NULL; - style->exts_deviceParams[r] = (ParamList *) NULL; - style->exts_deviceClass[r] = (char) 0; - style->exts_transResist[r].ht_table = (HashEntry **) NULL; - } return style; } + /* * ---------------------------------------------------------------------------- * @@ -575,7 +567,7 @@ extTechStyleInit(style) style->exts_status = TECH_NOT_LOADED; style->exts_sidePlanes = style->exts_overlapPlanes = 0; - TTMaskZero(&style->exts_transMask); + TTMaskZero(&style->exts_deviceMask); style->exts_activeTypes = DBAllButSpaceAndDRCBits; for (r = 0; r < NP; r++) @@ -589,7 +581,7 @@ extTechStyleInit(style) { TTMaskZero(&style->exts_nodeConn[r]); TTMaskZero(&style->exts_resistConn[r]); - TTMaskZero(&style->exts_transConn[r]); + TTMaskZero(&style->exts_deviceConn[r]); style->exts_allConn[r] = DBAllTypeBits; style->exts_sheetResist[r] = 0; @@ -620,43 +612,41 @@ extTechStyleInit(style) #ifdef ARIEL TTMaskZero(&style->exts_subsTransistorTypes[r]); #endif - if (style->exts_transSDTypes[r] != NULL) - freeMagic(style->exts_transSDTypes[r]); - style->exts_transSDTypes[r] = NULL; - style->exts_transSDCount[r] = 0; - style->exts_transGateCap[r] = (CapValue) 0; - style->exts_transSDCap[r] = (CapValue) 0; - if (style->exts_transSubstrateName[r] != (char *) NULL) + if (style->exts_device[r] != NULL) { - freeMagic(style->exts_transSubstrateName[r]); - style->exts_transSubstrateName[r] = (char *) NULL; - } - if (style->exts_transName[r] != (char *) NULL) - { - freeMagic(style->exts_transName[r]); - style->exts_transName[r] = (char *) NULL; - } - while (style->exts_deviceParams[r] != (ParamList *) NULL) - { - /* Parameter lists are shared. Only free the last one! */ + ExtDevice *devptr; + for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next) + { - if (style->exts_deviceParams[r]->pl_count > 1) - { - style->exts_deviceParams[r]->pl_count--; - style->exts_deviceParams[r] = (ParamList *)NULL; - } - else - { - freeMagic(style->exts_deviceParams[r]->pl_name); - freeMagic(style->exts_deviceParams[r]); - style->exts_deviceParams[r] = style->exts_deviceParams[r]->pl_next; + if (devptr->exts_deviceSDTypes != NULL) + freeMagic(devptr->exts_deviceSDTypes); + if (devptr->exts_deviceSubstrateName != (char *) NULL) + freeMagic(devptr->exts_deviceSubstrateName); + if (devptr->exts_deviceName != (char *) NULL) + freeMagic(devptr->exts_deviceName); + while (devptr->exts_deviceParams != (ParamList *) NULL) + { + /* Parameter lists are shared. Only free the last one! */ + + if (devptr->exts_deviceParams->pl_count > 1) + { + devptr->exts_deviceParams->pl_count--; + devptr->exts_deviceParams = (ParamList *)NULL; + } + else + { + freeMagic(devptr->exts_deviceParams->pl_name); + freeMagic(devptr->exts_deviceParams); + devptr->exts_deviceParams = devptr->exts_deviceParams->pl_next; + } + } + if (devptr->exts_deviceResist.ht_table != (HashEntry **) NULL) + HashKill(&devptr->exts_deviceResist); + + freeMagic(devptr); } + style->exts_device[r] = (ExtDevice *)NULL; } - style->exts_deviceClass[r] = (char)0; - if (style->exts_transResist[r].ht_table != (HashEntry **) NULL) - HashKill(&style->exts_transResist[r]); - HashInit(&style->exts_transResist[r], 8, HT_STRINGKEYS); - style->exts_linearResist[r] = 0; } style->exts_sideCoupleHalo = 0; @@ -798,14 +788,6 @@ ExtTechInit() if (ExtCurStyle != NULL) { extTechStyleInit(ExtCurStyle); - - /* Everything has been freed except the hash tables, which */ - /* were just reinitialized by extTechStyleInit(). */ - for (r = 0; r < NT; r++) - { - if (ExtCurStyle->exts_transResist[r].ht_table != (HashEntry **) NULL) - HashKill(&ExtCurStyle->exts_transResist[r]); - } ExtCurStyle = NULL; } @@ -1569,7 +1551,7 @@ ExtTechLine(sectionName, argc, argv) PlaneMask pshield, pov; CapValue capVal, gscap, gccap; TileTypeBitMask types1, types2, termtypes[MAXSD]; - TileTypeBitMask near, far, ov, shield, subsTypes; + TileTypeBitMask near, far, ov, shield, subsTypes, idTypes; char *subsName, *transName, *cp, *endptr, *paramName; TileType s, t, r, o; keydesc *kp, *dv; @@ -1578,6 +1560,7 @@ ExtTechLine(sectionName, argc, argv) EdgeCap *cnew; ExtKeep *es, *newStyle; ParamList *subcktParams, *newParam; + ExtDevice *devptr; int refcnt; double dhalo; bool bad; @@ -1888,24 +1871,32 @@ ExtTechLine(sectionName, argc, argv) gccap = (argc > 7) ? aToCap(argv[7]) : (CapValue) 0; } - TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1); + TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) if (TTMaskHasType(&types1, t)) { - TTMaskSetMask(ExtCurStyle->exts_transConn+t,&types1); - ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *) + devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice)); + devptr->exts_deviceSDTypes = (TileTypeBitMask *) mallocMagic(2 * sizeof(TileTypeBitMask)); - ExtCurStyle->exts_transSDTypes[t][0] = termtypes[0]; - ExtCurStyle->exts_transSDTypes[t][1] = DBZeroTypeBits; - ExtCurStyle->exts_transSDCount[t] = nterm; - ExtCurStyle->exts_transSDCap[t] = gscap; - ExtCurStyle->exts_transGateCap[t] = gccap; - ExtCurStyle->exts_deviceClass[t] = DEV_FET; - ExtCurStyle->exts_transName[t] = - StrDup((char **) NULL, transName); - ExtCurStyle->exts_transSubstrateName[t] = + devptr->exts_deviceSDTypes[0] = termtypes[0]; + devptr->exts_deviceSDTypes[1] = DBZeroTypeBits; + devptr->exts_deviceSDCount = nterm; + devptr->exts_deviceSDCap = gscap; + devptr->exts_deviceGateCap = gccap; + devptr->exts_deviceClass = DEV_FET; + devptr->exts_deviceName = StrDup((char **) NULL, transName); + devptr->exts_deviceSubstrateName = StrDup((char **) NULL, subsName); - ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes; + devptr->exts_deviceSubstrateTypes = subsTypes; + devptr->exts_deviceIdentifierTypes = DBZeroTypeBits; + devptr->exts_deviceParams = (ParamList *) NULL; + devptr->exts_deviceResist.ht_table = (HashEntry **) NULL; + HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS); + + TTMaskSetMask(ExtCurStyle->exts_deviceConn + t, &types1); + + devptr->exts_next = ExtCurStyle->exts_device[t]; + ExtCurStyle->exts_device[t] = devptr; #ifdef ARIEL { int z; @@ -1941,7 +1932,7 @@ ExtTechLine(sectionName, argc, argv) /* Parse second argument for device type */ - n = LookupStruct(argv[1], (LookupTable *) devTable, sizeof devTable[0]); + n = LookupStruct(argv[1], (LookupTable *)devTable, sizeof devTable[0]); if (n < 0) { TechError("Illegal device. Legal devices are:\n\t"); @@ -1999,6 +1990,18 @@ ExtTechLine(sectionName, argc, argv) argc--; } + /* If the last entry before any parameters starts with '+', */ + /* then use it to set the identity marker. Otherwise, the */ + /* identity marker is NULL. */ + + idTypes = DBZeroTypeBits; + if (*argv[argc - 1] == '+') + { + if ((DBTechNameMask(argv[argc - 1] + 1, &idTypes)) == 0) + idTypes = DBZeroTypeBits; + argc--; + } + /* Check the number of arguments after splitting out */ /* parameter entries. There is no limit on arguments in */ /* DEV_SUBCKT and DEV_MSUBCKT. */ @@ -2194,31 +2197,45 @@ ExtTechLine(sectionName, argc, argv) break; } - TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1); + TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { if (TTMaskHasType(&types1, t)) { - TTMaskSetMask(ExtCurStyle->exts_transConn + t, &types1); + devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice)); for (i = 0; !TTMaskIsZero(&termtypes[i]); i++); - ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *) + devptr->exts_deviceSDTypes = (TileTypeBitMask *) mallocMagic((i + 1) * sizeof(TileTypeBitMask)); for (i = 0; !TTMaskIsZero(&termtypes[i]); i++) - ExtCurStyle->exts_transSDTypes[t][i] = termtypes[i]; - ExtCurStyle->exts_transSDTypes[t][i] = DBZeroTypeBits; + devptr->exts_deviceSDTypes[i] = termtypes[i]; + devptr->exts_deviceSDTypes[i] = DBZeroTypeBits; - ExtCurStyle->exts_transSDCount[t] = nterm; - ExtCurStyle->exts_transSDCap[t] = gscap; - ExtCurStyle->exts_transGateCap[t] = gccap; - ExtCurStyle->exts_deviceClass[t] = class; - ExtCurStyle->exts_transName[t] = - StrDup((char **) NULL, transName); + devptr->exts_deviceSDCount = nterm; + devptr->exts_deviceSDCap = gscap; + devptr->exts_deviceGateCap = gccap; + devptr->exts_deviceClass = class; + devptr->exts_deviceName = StrDup((char **) NULL, transName); if (subsName != NULL) - ExtCurStyle->exts_transSubstrateName[t] = + devptr->exts_deviceSubstrateName = StrDup((char **) NULL, subsName); - ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes; + devptr->exts_deviceSubstrateTypes = subsTypes; + devptr->exts_deviceIdentifierTypes = idTypes; + devptr->exts_deviceParams = (ParamList *) NULL; + if (subcktParams != NULL) + { + devptr->exts_deviceParams = subcktParams; + subcktParams->pl_count++; + } + devptr->exts_deviceResist.ht_table = (HashEntry **) NULL; + HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS); + + devptr->exts_next = ExtCurStyle->exts_device[t]; + ExtCurStyle->exts_device[t] = devptr; + + TTMaskSetMask(ExtCurStyle->exts_deviceConn + t, &types1); #ifdef ARIEL { int z; @@ -2231,11 +2248,6 @@ ExtTechLine(sectionName, argc, argv) } } #endif - if (subcktParams != NULL) - { - ExtCurStyle->exts_deviceParams[t] = subcktParams; - subcktParams->pl_count++; - } } } break; @@ -2249,13 +2261,19 @@ ExtTechLine(sectionName, argc, argv) val = atoi(argv[3]); isLinear = (strcmp(argv[2], "linear") == 0); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + ExtDevice *devptr; if (TTMaskHasType(&types1, t)) { - he = HashFind(&ExtCurStyle->exts_transResist[t], argv[2]); - HashSetValue(he, (spointertype)val); - if (isLinear) - ExtCurStyle->exts_linearResist[t] = val; + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) + { + he = HashFind(&devptr->exts_deviceResist, argv[2]); + HashSetValue(he, (spointertype)val); + if (isLinear) + devptr->exts_linearResist = val; + } } + } break; case HEIGHT: { float height, thick; @@ -2619,7 +2637,7 @@ diffplane: * * Postprocess the technology specific information for extraction. * Builds the connectivity tables exts_nodeConn[], exts_resistConn[], - * and exts_transConn[]. + * and exts_deviceConn[]. * * Results: * None. @@ -2664,9 +2682,9 @@ extTechFinalStyle(style) for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) { maskBits = style->exts_nodeConn[r] = DBConnectTbl[r]; - if (!TTMaskHasType(&style->exts_transMask, r)) + if (!TTMaskHasType(&style->exts_deviceMask, r)) { - TTMaskZero(&style->exts_transConn[r]); + TTMaskZero(&style->exts_deviceConn[r]); } for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) { @@ -2870,10 +2888,15 @@ zinit: for (r = 0; r < DBNumTypes; r++) { - style->exts_areaCap[r] *= sqfac; - style->exts_transSDCap[r] *= sqfac; - style->exts_transGateCap[r] *= sqfac; + ExtDevice *devptr; + for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next) + { + devptr->exts_deviceSDCap *= sqfac; + devptr->exts_deviceGateCap *= sqfac; + } + + style->exts_areaCap[r] *= sqfac; for (s = 0; s < DBNumTypes; s++) { EdgeCap *ec; @@ -2953,13 +2976,18 @@ ExtTechScale(scalen, scaled) for (i = 0; i < DBNumTypes; i++) { + ExtDevice *devptr; + style->exts_areaCap[i] *= sqn; style->exts_areaCap[i] /= sqd; - style->exts_transSDCap[i] *= sqn; - style->exts_transSDCap[i] /= sqd; - style->exts_transGateCap[i] *= sqn; - style->exts_transGateCap[i] /= sqd; + for (devptr = style->exts_device[i]; devptr; devptr = devptr->exts_next) + { + devptr->exts_deviceSDCap *= sqn; + devptr->exts_deviceSDCap /= sqd; + devptr->exts_deviceGateCap *= sqn; + devptr->exts_deviceGateCap /= sqd; + } style->exts_height[i] *= scaled; style->exts_height[i] /= scalen; diff --git a/extract/ExtTest.c b/extract/ExtTest.c index 98f61b06..4428a28c 100644 --- a/extract/ExtTest.c +++ b/extract/ExtTest.c @@ -361,7 +361,7 @@ extShowTech(name) } } - extShowTrans("Transistor", &ExtCurStyle->exts_transMask, out); + extShowTrans("Transistor", &ExtCurStyle->exts_deviceMask, out); fprintf(out, "\nNode resistance and capacitance:\n"); fprintf(out, "type R-ohm/sq AreaC-ff/l**2\n"); @@ -472,7 +472,7 @@ extShowTech(name) extShowConnect("\nNode connectivity", ExtCurStyle->exts_nodeConn, out); extShowConnect("\nResistive region connectivity", ExtCurStyle->exts_resistConn, out); - extShowConnect("\nTransistor connectivity", ExtCurStyle->exts_transConn, out); + extShowConnect("\nTransistor connectivity", ExtCurStyle->exts_deviceConn, out); if (out != stdout) (void) fclose(out); @@ -493,12 +493,17 @@ extShowTrans(name, mask, out) for (t = 0; t < DBNumTypes; t++) if (TTMaskHasType(mask, t)) { - fprintf(out, " %-8.8s %d terminals: ", - DBTypeShortName(t), ExtCurStyle->exts_transSDCount[t]); - extShowMask(&ExtCurStyle->exts_transSDTypes[t][0], out); - fprintf(out, "\n\tcap (gate-sd/gate-ch) = %lf/%lf\n", - ExtCurStyle->exts_transSDCap[t], - ExtCurStyle->exts_transGateCap[t]); + ExtDevice *devptr; + + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) + { + fprintf(out, " %-8.8s %d terminals: ", + DBTypeShortName(t), devptr->exts_deviceSDCount); + extShowMask(&devptr->exts_deviceSDTypes[0], out); + fprintf(out, "\n\tcap (gate-sd/gate-ch) = %lf/%lf\n", + devptr->exts_deviceSDCap, + devptr->exts_deviceGateCap); + } } } diff --git a/extract/ExtTimes.c b/extract/ExtTimes.c index 3e2e0cbc..72c0f33b 100644 --- a/extract/ExtTimes.c +++ b/extract/ExtTimes.c @@ -348,7 +348,7 @@ extTimesCellFunc(cs) /* Count the number of transistors */ transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect, - &ExtCurStyle->exts_transMask, ExtCurStyle->exts_transConn, + &ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn, extUnInit, extTransFirst, extTransEach); ExtResetTiles(def, extUnInit); for (tl = transList; tl; tl = tl->treg_next) diff --git a/extract/extractInt.h b/extract/extractInt.h index ee264862..d5779afa 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -483,6 +483,82 @@ typedef struct extkeep char *exts_name; } ExtKeep; +/* + * Structure used to define transistors and other extracted devices + * One of these records is kept per tile type. However, the record + * can link to additional records through the "exts_next" record, + * so that multiple extraction devices can be defined for the same + * tile type, provided that each definition has a unique combination + * of exts_deviceSDTypes and exts_deviceSubstrateTypes. + */ + +typedef struct extDevice +{ + /* Name of each transistor type as output in .ext file */ + char *exts_deviceName; + + /* List of parameter names for each subcircuit type */ + ParamList *exts_deviceParams; + + /* Device class for each layer type */ + char exts_deviceClass; + + /* + * Per-square resistances for each possible transistor type, + * in the various regions that such a type might operate. + * The only operating region currently used is "linear", + * which the resistance extractor uses in its thresholding + * operation. NOTE: resistances in this table are in OHMS + * per square, not MILLIOHMS! + */ + + HashTable exts_deviceResist; + ResValue exts_linearResist; + + /* + * Mask of the types of tiles that connect to the channel terminals + * of a transistor type. The intent is that these will be the + * diffusion terminals of a transistor, ie, its source and drain. + * UPDATED May, 2008: Record is a list of type masks, allowing + * multiple terminal types in the case of, e.g., high-voltage + * or other asymmetric devices. The last entry in the list should + * be equal to DBSpaceBits. + */ + TileTypeBitMask *exts_deviceSDTypes; + + /* + * Maximum number of terminals (source/drains) per transistor type. + * This table exists to allow the possibility of transistors with + * more than two diffusion terminals at some point in the future. + */ + int exts_deviceSDCount; + + /* Currently unused: gate-source capacitance per unit perimeter */ + CapValue exts_deviceSDCap; + + /* Currently unused: gate-channel capacitance per unit area */ + CapValue exts_deviceGateCap; + + /* + * Each type of transistor has a substrate node. By default, + * it is the one given by exts_deviceSubstrateName[t]. However, + * if the mask exts_deviceSubstrateTypes is non-zero, and if + * the transistor overlaps material of one of the types in the + * mask, then the transistor substrate node is the node of the + * material it overlaps. + */ + char *exts_deviceSubstrateName; + TileTypeBitMask exts_deviceSubstrateTypes; + + /* + * Each device type can have any number of extract models based + * on identifier layers (such as thickox, esd, etc.) + */ + TileTypeBitMask exts_deviceIdentifierTypes; + + struct extDevice *exts_next; +} ExtDevice; + /* * Parameters for the process being extracted. * We try to use use integers here, rather than floats, to be nice to @@ -524,11 +600,11 @@ typedef struct extstyle TileTypeBitMask exts_resistConn[NT]; /* - * Connectivity for determining transistors. - * Each transistor type should connect only to itself. + * Connectivity for determining devices. + * Each devices type should connect only to itself. * Nothing else should connect to anything else. */ - TileTypeBitMask exts_transConn[NT]; + TileTypeBitMask exts_deviceConn[NT]; /* * Set of types to be considered for extraction. Types not in @@ -779,65 +855,14 @@ typedef struct extstyle */ TileTypeBitMask exts_sideEdges[NT]; - /* Transistors */ + /* Devices */ - /* Name of each transistor type as output in .ext file */ - char *exts_transName[NT]; + /* Contains one for each type of device, zero for all other tile types */ + TileTypeBitMask exts_deviceMask; - /* List of parameter names for each subcircuit type */ - ParamList *exts_deviceParams[NT]; + /* All information about a device goes in this record (see above) */ + ExtDevice *exts_device[NT]; - /* Device class for each layer type */ - char exts_deviceClass[NT]; - - /* Contains one for each type of fet, zero for all other types */ - TileTypeBitMask exts_transMask; - - /* - * Per-square resistances for each possible transistor type, - * in the various regions that such a type might operate. - * The only operating region currently used is "linear", - * which the resistance extractor uses in its thresholding - * operation. NOTE: resistances in this table are in OHMS - * per square, not MILLIOHMS! - */ - HashTable exts_transResist[NT]; - ResValue exts_linearResist[NT]; - - /* - * Mask of the types of tiles that connect to the channel terminals - * of a transistor type. The intent is that these will be the - * diffusion terminals of a transistor, ie, its source and drain. - * UPDATED May, 2008: Record is a list of type masks, allowing - * multiple terminal types in the case of, e.g., high-voltage - * or other asymmetric devices. The last entry in the list should - * be equal to DBSpaceBits. - */ - TileTypeBitMask *exts_transSDTypes[NT]; - - /* - * Maximum number of terminals (source/drains) per transistor type. - * This table exists to allow the possibility of transistors with - * more than two diffusion terminals at some point in the future. - */ - int exts_transSDCount[NT]; - - /* Currently unused: gate-source capacitance per unit perimeter */ - CapValue exts_transSDCap[NT]; - - /* Currently unused: gate-channel capacitance per unit area */ - CapValue exts_transGateCap[NT]; - - /* - * Each type of transistor has a substrate node. By default, - * it is the one given by exts_transSubstrateName[t]. However, - * if the mask exts_transSubstrateTypes[t] is non-zero, and if - * the transistor overlaps material of one of the types in the - * mask, then the transistor substrate node is the node of the - * material it overlaps. If exts_transSub - */ - char *exts_transSubstrateName[NT]; - TileTypeBitMask exts_transSubstrateTypes[NT]; #ifdef ARIEL TileTypeBitMask exts_subsTransistorTypes[NT]; #endif /* ARIEL */ diff --git a/resis/ResBasic.c b/resis/ResBasic.c index 24721e10..273133ae 100644 --- a/resis/ResBasic.c +++ b/resis/ResBasic.c @@ -139,6 +139,7 @@ ResEachTile(tile, startpoint) bool merged; tElement *tcell; tileJunk *tstructs= (tileJunk *)(tile->ti_client); + ExtDevice *devptr; ResTileCount++; @@ -165,7 +166,7 @@ ResEachTile(tile, startpoint) resNodeIsPort(resptr, x, y, tile); } - if TTMaskHasType(&(ExtCurStyle->exts_transMask), t1) + if TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t1) { /* * The transistor is put in the center of the tile. This is fine @@ -250,8 +251,9 @@ ResEachTile(tile, startpoint) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetRightType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) /* found transistor */ { xj = LEFT(tile); @@ -272,8 +274,9 @@ ResEachTile(tile, startpoint) for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { t2 = TiGetLeftType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) /* found transistor */ { xj = RIGHT(tile); @@ -294,8 +297,9 @@ ResEachTile(tile, startpoint) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { t2 = TiGetBottomType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) /* found transistor */ { yj = TOP(tile); @@ -315,8 +319,9 @@ ResEachTile(tile, startpoint) for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { t2 = TiGetTopType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) /* found transistor */ { yj = BOTTOM(tile); diff --git a/resis/ResConDCS.c b/resis/ResConDCS.c index aea2ab4a..69adc06a 100644 --- a/resis/ResConDCS.c +++ b/resis/ResConDCS.c @@ -102,6 +102,7 @@ dbcConnectFuncDCS(tile, cx) SearchContext scx2; int pNum; CellDef *def; + ExtDevice *devptr; TiToRect(tile, &tileArea); srArea = &scx->scx_area; @@ -121,8 +122,9 @@ dbcConnectFuncDCS(tile, cx) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { TiToRect(tp, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -137,8 +139,9 @@ dbcConnectFuncDCS(tile, cx) for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { TiToRect(tp, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -153,8 +156,9 @@ dbcConnectFuncDCS(tile, cx) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { TiToRect(tp, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -169,8 +173,9 @@ dbcConnectFuncDCS(tile, cx) for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { TiToRect(tp, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -182,7 +187,7 @@ dbcConnectFuncDCS(tile, cx) } } } - else if TTMaskHasType(&(ExtCurStyle->exts_transMask),t1) + else if TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t1) { TiToRect(tile, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -425,6 +430,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) ResTranTile *CurrentT; CellDef *def = destUse->cu_def; TileType newtype; + ExtDevice *devptr; csa2.csa2_use = destUse; csa2.csa2_xMask = xMask; @@ -443,13 +449,14 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) TTMaskZero(&ResSubsTypeBitMask); for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) { - tran_name = (ExtCurStyle->exts_transName)[tran]; + devptr = ExtCurStyle->exts_device[tran]; + tran_name = devptr->exts_deviceName; if ((tran_name != NULL) && (strcmp(tran_name, "None"))) { TTMaskSetMask(&DiffTypeBitMask, - &(ExtCurStyle->exts_transSDTypes[tran][0])); + &(devptr->exts_deviceSDTypes[0])); TTMaskSetMask(&ResSubsTypeBitMask, - &(ExtCurStyle->exts_transSubstrateTypes[tran])); + &(devptr->exts_deviceSubstrateTypes)); } } first = 0; @@ -520,12 +527,14 @@ resSubSearchFunc(tile,cx) ResTranTile *thisTran; Rect tranArea; TileType t = TiGetType(tile); + ExtDevice *devptr; /* Right now, we're only going to extract substrate terminals for devices with only one diffusion terminal, principally bipolar devices. */ - if (ExtCurStyle->exts_transSDCount[t] >1) return 0; + devptr = ExtCurStyle->exts_device[t] + if (devptr->exts_deviceSDCount >1) return 0; TiToRect(tile, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); GeoTransRect(&cx->tc_scx->scx_trans, &tranArea, &thisTran->area); diff --git a/resis/ResMain.c b/resis/ResMain.c index 1548be5e..33657767 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -53,7 +53,7 @@ extern HashTable ResNodeTable; * ResInitializeConn-- * * Sets up mask by Source/Drain type of transistors. This is - * exts_transSDtypes turned inside out. + * exts_deviceSDtypes turned inside out. * * Results: none * @@ -67,18 +67,20 @@ ResInitializeConn() { TileType tran, diff; char *tran_name; + ExtDevice *devptr; for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) { - tran_name = (ExtCurStyle->exts_transName)[tran]; + devptr = ExtCurStyle->exts_device[tran]; + tran_name = devptr->exts_deviceName; if ((tran_name != NULL) && (strcmp(tran_name, "None"))) { for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[tran][0]), diff) + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), diff) TTMaskSetType(&ResConnectWithSD[diff],tran); - if TTMaskHasType(&(ExtCurStyle->exts_transSubstrateTypes[tran]),diff) + if TTMaskHasType(&(devptr->exts_deviceSubstrateTypes),diff) TTMaskSetType(&ResConnectWithSD[diff],tran); } } @@ -163,7 +165,7 @@ ResDissolveContacts(contacts) { if (TTMaskHasType(&residues, t)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, t)) + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, t)) continue; DBPaint(ResUse->cu_def, &(contacts->cp_rect), t); } @@ -824,6 +826,7 @@ FindStartTile(goodies, SourcePoint) Point workingPoint; Tile *tile, *tp; int pnum, t1, t2; + ExtDevice *devptr; workingPoint.p_x = goodies->rg_tranloc->p_x; workingPoint.p_y = goodies->rg_tranloc->p_y; @@ -868,12 +871,12 @@ FindStartTile(goodies, SourcePoint) if (IsSplit(tile)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetLeftType(tile)) != 0) + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile)) != 0) { t1 = TiGetLeftType(tile); TiSetBody(tile, t1 & ~TT_SIDE); } - else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetRightType(tile)) != 0) + else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile)) != 0) { t1 = TiGetRightType(tile); TiSetBody(tile, t1 & TT_SIDE); @@ -885,7 +888,7 @@ FindStartTile(goodies, SourcePoint) return(NULL); } } - else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetType(tile)) == 0) + else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)) == 0) { TxError("Couldn't find transistor at %d %d\n", goodies->rg_tranloc->p_x, goodies->rg_tranloc->p_y); @@ -894,11 +897,12 @@ FindStartTile(goodies, SourcePoint) else t1 = TiGetType(tile); + devptr = ExtCurStyle->exts_device[t1]; /* left */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetRightType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2)) { SourcePoint->p_x = LEFT(tile); SourcePoint->p_y = (MIN(TOP(tile),TOP(tp))+ @@ -911,7 +915,7 @@ FindStartTile(goodies, SourcePoint) for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { t2 = TiGetLeftType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2)) { SourcePoint->p_x = RIGHT(tile); SourcePoint->p_y = (MIN(TOP(tile),TOP(tp))+ @@ -924,7 +928,7 @@ FindStartTile(goodies, SourcePoint) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { t2 = TiGetBottomType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2)) { SourcePoint->p_y = TOP(tile); SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp))+ @@ -937,7 +941,7 @@ FindStartTile(goodies, SourcePoint) for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { t2 = TiGetTopType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2)) { SourcePoint->p_y = BOTTOM(tile); SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp))+ @@ -977,7 +981,7 @@ ResGetTransistor(pt) for (pnum= PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++) { - if (TTMaskIntersect(&ExtCurStyle->exts_transMask,&DBPlaneTypes[pnum]) == 0) + if (TTMaskIntersect(&ExtCurStyle->exts_deviceMask,&DBPlaneTypes[pnum]) == 0) { continue; } @@ -987,11 +991,11 @@ ResGetTransistor(pt) if (IsSplit(tile)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetLeftType(tile)) - || TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetRightType(tile))) + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile)) + || TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile))) return(((tileJunk *)tile->ti_client)->transistorList); } - else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetType(tile))) + else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile))) { return(((tileJunk *)tile->ti_client)->transistorList); } diff --git a/resis/ResPrint.c b/resis/ResPrint.c index 0c93cfcd..1423bfac 100644 --- a/resis/ResPrint.c +++ b/resis/ResPrint.c @@ -114,6 +114,7 @@ ResPrintExtTran(outextfile, transistors) { TileType t; char *subsName; + ExtDevice *devptr; for (; transistors != NULL; transistors = transistors->nextTran) { @@ -122,7 +123,8 @@ ResPrintExtTran(outextfile, transistors) if (ResOptionsFlags & ResOpt_DoExtFile) { t = transistors->layout->rt_trantype; - subsName = ExtCurStyle->exts_transSubstrateName[t]; + devptr = ExtCurStyle->exts_device[t]; + subsName = devptr->exts_deviceSubstrateName; #ifdef MAGIC_WRAPPER /* Substrate variable name substitution */ @@ -139,7 +141,7 @@ ResPrintExtTran(outextfile, transistors) /* fet type xl yl xh yh area perim sub gate t1 t2 */ fprintf(outextfile,"fet %s %d %d %d %d %d %d " "%s \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n", - ExtCurStyle->exts_transName[t], + devptr->exts_deviceName, transistors->layout->rt_inside.r_ll.p_x, transistors->layout->rt_inside.r_ll.p_y, transistors->layout->rt_inside.r_ll.p_x + 1, diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index fd7ce8bb..6cb38633 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -187,8 +187,10 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc) else if (fettype != MINFINITY) { float sheetr; + ExtDevice *devptr; - sheetr=(float)ExtCurStyle->exts_linearResist[fettype]; + devptr = ExtCurStyle->exts_device[fettype]; + sheetr=(float)devptr->exts_linearResist; result = (*fetproc)(line,sheetr,fettype); } if (result != 0) diff --git a/resis/ResSimple.c b/resis/ResSimple.c index b4147523..2e55b033 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -732,6 +732,7 @@ ResCalculateChildCapacitance(me) float childcap; tElement *tptr; int t; + ExtDevice *devptr; if (me->rn_client != (ClientData) NULL) /* we have a loop */ @@ -752,12 +753,13 @@ ResCalculateChildCapacitance(me) t = TiGetType(tran->rt_tile); if (tran->rt_gate == me) { + devptr = ExtCurStyle->exts_device[t]; myC->rc_Cdownstream += tran->rt_length* tran->rt_width* - ExtCurStyle->exts_transGateCap[t]+ + devptr->exts_deviceGateCap+ (tran->rt_width+tran->rt_width)* - ExtCurStyle->exts_transSDCap[t]; + devptr->exts_deviceSDCap; } } diff --git a/resis/ResUtils.c b/resis/ResUtils.c index 5548f4e1..e292a3fb 100644 --- a/resis/ResUtils.c +++ b/resis/ResUtils.c @@ -144,6 +144,7 @@ ResAddPlumbing(tile, arg) TileType loctype, t1; Tile *tp1,*tp2,*source; resTransistor *resFet; + ExtDevice *devptr; if (resTransStack == NULL) { @@ -159,8 +160,9 @@ ResAddPlumbing(tile, arg) else loctype = TiGetTypeExact(tile); + devptr = ExtCurStyle->exts_device[loctype]; junk2 = resAddField(tile); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask), loctype)) + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype)) { resFet = (resTransistor *) mallocMagic((unsigned)(sizeof(resTransistor))); { @@ -191,7 +193,7 @@ ResAddPlumbing(tile, arg) /* top */ for (tp2= RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2)) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetBottomType(tp2)) { junk2->sourceEdge |= TOPEDGE; @@ -206,7 +208,7 @@ ResAddPlumbing(tile, arg) if (source == NULL) for (tp2= LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2)) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetTopType(tp2)) { junk2->sourceEdge |= BOTTOMEDGE; @@ -221,7 +223,7 @@ ResAddPlumbing(tile, arg) if (source == NULL) for (tp2= TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2)) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetLeftType(tp2)) { junk2->sourceEdge |= RIGHTEDGE; @@ -236,7 +238,7 @@ ResAddPlumbing(tile, arg) if (source == NULL) for (tp2= BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2)) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetRightType(tp2)) { source = tp2; @@ -339,6 +341,7 @@ ResAddPlumbing(tile, arg) else t1 = TiGetTypeExact(tp1); + devptr = ExtCurStyle->exts_device[t1]; j0 = (tileJunk *) tp1->ti_client; /* top */ for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) @@ -352,7 +355,7 @@ ResAddPlumbing(tile, arg) Junk->tj_status |= RES_TILE_TRAN; } - else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetBottomType(tp2)) { Junk = resAddField(tp2); @@ -373,7 +376,7 @@ ResAddPlumbing(tile, arg) Junk->transistorList = resFet; Junk->tj_status |= RES_TILE_TRAN; } - else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetTopType(tp2)) { Junk = resAddField(tp2); @@ -394,7 +397,7 @@ ResAddPlumbing(tile, arg) Junk->transistorList = resFet; Junk->tj_status |= RES_TILE_TRAN; } - else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetLeftType(tp2)) { Junk = resAddField(tp2); @@ -415,7 +418,7 @@ ResAddPlumbing(tile, arg) Junk->transistorList = resFet; Junk->tj_status |= RES_TILE_TRAN; } - else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetRightType(tp2)) { Junk = resAddField(tp2); @@ -577,7 +580,7 @@ ResPreProcessTransistors(TileList, TransistorList, Def) { if (TTMaskHasType(&ttresidues, residue)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, residue)) + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, residue)) { pNum = DBPlane(residue); break; @@ -594,7 +597,7 @@ ResPreProcessTransistors(TileList, TransistorList, Def) tt = TiGetType(tile); tstruct = (tileJunk *) tile->ti_client; - if (!TTMaskHasType(&ExtCurStyle->exts_transMask, tt) || + if (!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt) || tstruct->transistorList == NULL) { TxError("Bad Transistor Location at %d,%d\n", diff --git a/sim/SimExtract.c b/sim/SimExtract.c index 5678f360..dfc1faad 100644 --- a/sim/SimExtract.c +++ b/sim/SimExtract.c @@ -239,16 +239,18 @@ SimFreeNodeRegs() int SimInitConnTables() { int i, t, sd, p; + ExtDevice *devptr; - SimTransMask = ExtCurStyle->exts_transMask; + SimTransMask = ExtCurStyle->exts_deviceMask; TTMaskZero( &SimSDMask ); for( t = TT_TECHDEPBASE; t < DBNumTypes; t++ ) { - for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + devptr = ExtCurStyle->exts_device[t]; + for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i], TT_SPACE); i++) { - TTMaskSetMask( &SimSDMask, &ExtCurStyle->exts_transSDTypes[t][i] ); + TTMaskSetMask( &SimSDMask, &devptr->exts_deviceSDTypes[i] ); TTMaskZero( &SimFetMask[t] ); } } @@ -258,12 +260,13 @@ int SimInitConnTables() { if (TTMaskHasType(&SimTransMask, t)) { + devptr = ExtCurStyle->exts_device[t]; for (sd = TT_TECHDEPBASE; sd < DBNumTypes; sd++) { - for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i], TT_SPACE); i++) { - if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], sd)) + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], sd)) { TTMaskSetType(&SimFetMask[sd], t); SimFetPlanes |= PlaneNumToMaskBit(DBPlane(t)); @@ -471,14 +474,16 @@ SimTransistorTile(tile, pNum, arg) { int i; TileType t; + ExtDevice *devptr; extSetNodeNum((LabRegion *)&transistor, pNum, tile); if (transistor.t_do_terms) { t = TiGetType(tile); - for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + devptr = ExtCurStyle->exts_device[t]; + for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i], TT_SPACE); i++) - extEnumTilePerim(tile, ExtCurStyle->exts_transSDTypes[t][i], + extEnumTilePerim(tile, devptr->exts_deviceSDTypes[i], SimTransTerms, (ClientData) &transistor ); }