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 ); }