diff --git a/VERSION b/VERSION index df4da1ab..9bbbb99b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.554 +8.3.555 diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index 59531c39..06a66590 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -387,6 +387,15 @@ calmaParseStructure( he = HashFind(&calmaDefInitHash, strname); if ((def = (CellDef *)HashGetValue(he)) != NULL) { + if (def->cd_flags & CDPRELOADED) + { + /* Cell definition was read ahead due to option "flatten" */ + /* or "flatglob". Do not complain about seeing it again. */ + def->cd_flags &= ~CDPRELOADED; + calmaNextCell(); + return TRUE; + } + if (def->cd_flags & CDPROCESSEDGDS) { /* If cell definition was marked as processed, then skip */ @@ -396,6 +405,7 @@ calmaParseStructure( if (!CalmaPostOrder && !CalmaRewound) { + cifReadCellDef = def; CalmaReadError("Cell \"%s\" was already defined in this file.\n", strname); CalmaReadError("Ignoring duplicate definition\n"); @@ -407,6 +417,7 @@ calmaParseStructure( { char *newname; + cifReadCellDef = def; CalmaReadError("Cell \"%s\" was already defined in this file.\n", strname); newname = (char *)mallocMagic(strlen(strname) + 20); @@ -773,6 +784,7 @@ calmaElementSref( bool madeinst = FALSE; char *sname = NULL; bool isArray = FALSE; + bool dolookahead = FALSE; Transform trans, tinv; Point refarray[3], refunscaled[3], p; CellUse *use; @@ -798,7 +810,38 @@ calmaElementSref( */ def = calmaLookCell(sname); - if (!def && (CalmaPostOrder || CalmaFlattenUses || (CalmaFlattenUsesByName != NULL))) + + /* + * If the "flatten" option is set, then we always have to seek + * ahead and read the structure in order to determine if it + * meets the requirement of being flattened or not. If the + * "flatglob" option is set, then we need to read ahead and + * read the cell definition so that it can be flatten. This + * requires pattern-matching the cell def. + */ + + dolookahead = (CalmaPostOrder || CalmaFlattenUses) ? TRUE : FALSE; + if ((!dolookahead) && (CalmaFlattenUsesByName != NULL)) + { + char *pattern; + + i = 0; + while (TRUE) + { + pattern = CalmaFlattenUsesByName[i]; + if (pattern == NULL) break; + i++; + + /* Check pattern against strname */ + if (Match(pattern, sname)) + { + dolookahead = TRUE; + break; + } + } + } + + if (!def && dolookahead) { /* Force the GDS parser to read the cell definition in * post-order. If cellname "sname" is not defined before @@ -832,6 +875,7 @@ calmaElementSref( FSEEK(calmaInputFile, originalFilePos, SEEK_SET); cifReadCellDef = calmaLookCell(currentSname); def = calmaLookCell(sname); + def->cd_flags |= CDPRELOADED; cifCurReadPlanes = savePlanes; calmaLayerHash = OrigCalmaLayerHash; if (crsMultiplier != cifCurReadStyle->crs_multiplier) diff --git a/database/database.h.in b/database/database.h.in index 2496263b..96da5cf3 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -403,6 +403,9 @@ typedef struct celldef * is added to the magic database. The flag is used to identify * whether the cell has been processed when forcing the GDS * stream data to be read in post-order. + * CDPRELOADED is similar to CDPROCESSEDGDS but is used in cases + * other than forced post-order reading, such as flattening + * or flatten-by-name. * CDVENDORGDS indicates that the cell was read from a GDS stream * with the option "gds readonly true". * CDVISITED indicates that at least one instance of the cell was @@ -434,12 +437,13 @@ typedef struct celldef #define CDFLATGDS 0x00400 #define CDFLATTENED 0x00800 #define CDPROCESSEDGDS 0x01000 -#define CDVENDORGDS 0x02000 -#define CDVISITED 0x04000 -#define CDDEREFERENCE 0x08000 -#define CDFIXEDSTAMP 0x10000 -#define CDNOEXTRACT 0x20000 -#define CDDONTUSE 0x40000 +#define CDPRELOADED 0x02000 +#define CDVENDORGDS 0x04000 +#define CDVISITED 0x08000 +#define CDDEREFERENCE 0x10000 +#define CDFIXEDSTAMP 0x20000 +#define CDNOEXTRACT 0x40000 +#define CDDONTUSE 0x80000 #include "database/arrayinfo.h" /* ArrayInfo */ diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 093ef71d..8d8a7e7e 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -371,11 +371,11 @@ spcHierWriteParams( break; case 'r': fprintf(esSpiceF, " %s=", plist->parm_name); - fprintf(esSpiceF, "%f", (double)(dev->dev_res)); + esSIvalue(esSpiceF, (double)(dev->dev_res)); break; case 'c': fprintf(esSpiceF, " %s=", plist->parm_name); - fprintf(esSpiceF, "%ff", (double)(dev->dev_cap)); + esSIvalue(esSpiceF, (double)(dev->dev_cap)); break; } plist = plist->parm_next; @@ -840,6 +840,8 @@ spcdevHierVisit( subnode->efnode_name->efnn_hier, dev->dev_type, esSpiceF); } + /* Support for CDL format */ + if (esFormat == CDL) fprintf(esSpiceF, " /"); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); /* Write all requested parameters to the subcircuit call. */ diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index a32320e5..b5646af7 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -284,7 +284,7 @@ CmdExtToSpice( static int LocResistThreshold = INFINITE_THRESHOLD; static const char * const spiceFormats[] = { - "SPICE2", "SPICE3", "HSPICE", "NGSPICE", NULL + "SPICE2", "SPICE3", "HSPICE", "NGSPICE", "CDL", NULL }; static const char * const cmdExtToSpcOption[] = { @@ -330,6 +330,7 @@ CmdExtToSpice( "spice3", "hspice", "ngspice", + "cdl", NULL }; @@ -663,10 +664,10 @@ CmdExtToSpice( { #ifdef MAGIC_WRAPPER Tcl_SetResult(magicinterp, "Bad format type. Formats are:" - "spice2, spice3, hspice, and ngspice.", NULL); + "spice2, spice3, hspice, ngspice, and cdl.", NULL); #else TxError("Bad format type. Formats are:" - "spice2, spice3, hspice, and ngspice."); + "spice2, spice3, hspice, ngspice, and cdl."); #endif return; } @@ -876,7 +877,12 @@ runexttospice: */ if (spcesOutName == spcesDefaultOut) - sprintf(spcesDefaultOut, "%s.spice", inName); + { + if (esFormat == CDL) + sprintf(spcesDefaultOut, "%s.cdl", inName); + else + sprintf(spcesDefaultOut, "%s.spice", inName); + } /* Read the hierarchical description of the input circuit */ if (EFReadFile(inName, esDoHierarchy, esDoExtResis, FALSE, TRUE) @@ -963,8 +969,11 @@ runexttospice: locsubname = StrDup(NULL, subname); - bangptr = locsubname + strlen(locsubname) - 1; - if (*bangptr == '!') *bangptr = '\0'; + if (esFormat != CDL) + { + bangptr = locsubname + strlen(locsubname) - 1; + if (*bangptr == '!') *bangptr = '\0'; + } // Ad-hoc check: Global names with "Error", "err", etc. // should be rejected from the list. Also node name @@ -993,6 +1002,42 @@ runexttospice: } } + if (esFormat == CDL) + { + /* In CDL format, if the global substrate ends with "!" then + * add it to the list of globals; likewise for VDD and GND. + */ + char *glbstr; + globalList *glptr; + + glbstr = (char *)Tcl_GetVar(magicinterp, "SUB", TCL_GLOBAL_ONLY); + if ((glbstr != NULL) && (*(glbstr + strlen(glbstr) - 1) == '!')) + { + glptr = (globalList *)mallocMagic(sizeof(globalList)); + glptr->gll_name = StrDup((char **)NULL, glbstr); + glptr->gll_next = glist; + glist = glptr; + } + + glbstr = (char *)Tcl_GetVar(magicinterp, "VDD", TCL_GLOBAL_ONLY); + if ((glbstr != NULL) && (*(glbstr + strlen(glbstr) - 1) == '!')) + { + glptr = (globalList *)mallocMagic(sizeof(globalList)); + glptr->gll_name = StrDup((char **)NULL, glbstr); + glptr->gll_next = glist; + glist = glptr; + } + + glbstr = (char *)Tcl_GetVar(magicinterp, "GND", TCL_GLOBAL_ONLY); + if ((glbstr != NULL) && (*(glbstr + strlen(glbstr) - 1) == '!')) + { + glptr = (globalList *)mallocMagic(sizeof(globalList)); + glptr->gll_name = StrDup((char **)NULL, glbstr); + glptr->gll_next = glist; + glist = glptr; + } + } + #ifdef MAGIC_WRAPPER if (EFCompat == TRUE) { @@ -1027,6 +1072,8 @@ runexttospice: if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; if (esFormat == HSPICE) EFOutputFlags |= EF_TRIMLOCAL; + if (esFormat == CDL) + EFOutputFlags &= ~EF_TRIMGLOB; /* Write globals under a ".global" card */ @@ -1226,7 +1273,13 @@ main( */ if (spcesOutName == spcesDefaultOut) - sprintf(spcesDefaultOut, "%s.spice", inName); + { + if (esFormat == CDL) + sprintf(spcesDefaultOut, "%s.cdl", inName); + else + sprintf(spcesDefaultOut, "%s.spice", inName); + } + if ((esSpiceF = fopen(spcesOutName, "w")) == NULL) { @@ -1363,7 +1416,7 @@ spcParseArgs( const char usage_text[] = "Usage: ext2spice " "[-B] [-o spicefile] [-M|-m] [-J flat|hier]\n" - "[-f spice2|spice3|hspice|ngspice] [-M] [-m] " + "[-f spice2|spice3|hspice|ngspice|cdl] [-M] [-m] " "[file]\n"; switch (argv[0][1]) @@ -1407,6 +1460,8 @@ spcParseArgs( } else if (strcasecmp(ftmp, "NGSPICE") == 0) esFormat = NGSPICE; + else if (strcasecmp(ftmp, "CDL") == 0) + esFormat = CDL; else goto usage; break; @@ -1677,6 +1732,7 @@ subcktVisit( } if (tchars > 80) fprintf(esSpiceF, "\n+"); + if (esFormat == CDL) fprintf(esSpiceF, " /"); fprintf(esSpiceF, " %s", subcktname); /* subcircuit model name */ // Check for a "device parameter" defined with the name of the cell. @@ -2256,11 +2312,11 @@ spcWriteParams( break; case 'r': fprintf(esSpiceF, " %s=", plist->parm_name); - fprintf(esSpiceF, "%f", (double)(dev->dev_res)); + esSIvalue(esSpiceF, (double)dev->dev_res); break; case 'c': fprintf(esSpiceF, " %s=", plist->parm_name); - fprintf(esSpiceF, "%ff", (double)(dev->dev_cap)); + esSIvalue(esSpiceF, (double)dev->dev_cap); break; } plist = plist->parm_next; @@ -2777,6 +2833,9 @@ spcdevVisit( subnode->efnode_name->efnn_hier, dev->dev_type, esSpiceF); } + + /* CDL format support: Output a slash followed by a space. */ + if (esFormat == CDL) fprintf(esSpiceF, " /"); fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); /* Write all requested parameters to the subcircuit call. */ diff --git a/ext2spice/ext2spice.h b/ext2spice/ext2spice.h index 8eaba2f2..2284bfee 100644 --- a/ext2spice/ext2spice.h +++ b/ext2spice/ext2spice.h @@ -173,6 +173,7 @@ typedef struct { #define SPICE3 1 #define HSPICE 2 #define NGSPICE 3 +#define CDL 4 #define AUTO 2 /* TRUE | FALSE | AUTO for esDoSubckt */ diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 24ab6f63..3458552d 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -1152,7 +1152,7 @@ ExtSortTerminals(tran, ll) * one terminal. * * Results: - * None + * TRUE if L and W were computed, FALSE if not. * * Side Effects: * Puts effective length and width into the pointers @@ -1160,7 +1160,7 @@ ExtSortTerminals(tran, ll) *---------------------------------------------------------------------- */ -void +bool extComputeCapLW(rlengthptr, rwidthptr) int *rlengthptr, *rwidthptr; { @@ -1174,7 +1174,7 @@ extComputeCapLW(rlengthptr, rwidthptr) if (lb == NULL) { TxError("extract: Can't get capacitor L and W\n"); - return; /* error condition */ + return FALSE; /* error condition */ } bbox = lb->r; for (lb = extSpecialBounds[0]; lb != NULL; lb = lb->b_next) @@ -1182,6 +1182,7 @@ extComputeCapLW(rlengthptr, rwidthptr) *rwidthptr = bbox.r_xtop - bbox.r_xbot; *rlengthptr = bbox.r_ytop - bbox.r_ybot; + return TRUE; } /* @@ -1789,6 +1790,8 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec) int *perimvec; { ParamList *chkParam; + HashEntry *he; + ResValue resvalue; for (chkParam = devptr->exts_deviceParams; chkParam != NULL; chkParam = chkParam->pl_next) @@ -1863,6 +1866,39 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec) (extTransRec.tr_devrec->exts_deviceSDCap * extTransRec.tr_perim)); break; + case 'r': + /* If the device has an "area" resistance specified + * by "devresist" in the tech file, use that. If + * it has a "perimeter" resistance specified, use + * that as well. If neither, then find the sheet + * resistance of the device identifier layer and + * use that. + */ + resvalue = (ResValue)0.0; + he = HashLookOnly(&extTransRec.tr_devrec->exts_deviceResist, "area"); + if (he != NULL) + { + resvalue = (ResValue)(pointertype)HashGetValue(he); + resvalue /= (ResValue)reg->treg_area; + + he = HashLookOnly(&extTransRec.tr_devrec->exts_deviceResist, + "perimeter"); + if (he != NULL) + { + ResValue perimr; + perimr = (ResValue)(pointertype)HashGetValue(he); + perimr /= (ResValue)extTransRec.tr_perim; + resvalue += perimr; + } + } + else + { + resvalue = ExtCurStyle->exts_sheetResist[reg->treg_type] + * (double)length / (double)width; + } + + fprintf(outFile, " %c=%g", chkParam->pl_param[0], (float)resvalue); + break; case 's': case 'x': case 'y': @@ -2143,10 +2179,11 @@ extOutputDevices(def, transList, outFile) NodeRegion *node, *subsNode; TransRegion *reg; ExtDevice *devptr, *deventry; - char *subsName; + ParamList *chkParam; FindRegion arg; LabelList *ll; TileType t; + char *subsName; int nsd, length, width, n, i, ntiles, corners, tn, rc, termcount; double dres, dcap; char mesg[256]; @@ -2668,7 +2705,70 @@ extOutputDevices(def, transList, outFile) case DEV_DIODE: /* Only handle the optional substrate node */ case DEV_NDIODE: case DEV_PDIODE: + /* Diode length and width are computed like capacitor */ + /* length and width. This operation is expensive, so */ + /* do this ONLY if length and width are specified as */ + /* parameters. */ + devptr = extDevFindParamMatch(devptr, length, width); + for (chkParam = devptr->exts_deviceParams; chkParam != NULL; + chkParam = chkParam->pl_next) + { + char param0; + + if (chkParam->pl_name == NULL) continue; + param0 = tolower(chkParam->pl_param[0]); + if (param0 == 'l' || param0 == 'w') break; + } + + if (chkParam != NULL) + { + for (n = 0; n < extTransRec.tr_nterm && + extTransRec.tr_termnode[n] != NULL; n++); + + if (n > 0) + { + LinkedBoundary *lb; + + extSpecialBounds = (LinkedBoundary **)mallocMagic(n * + sizeof(LinkedBoundary *)); + + for (i = 0; i < n; i++) extSpecialBounds[i] = NULL; + + /* Mark with reg and process each perimeter segment */ + + arg.fra_uninit = (ClientData) extTransRec.tr_gatenode; + arg.fra_region = (ExtRegion *) reg; + arg.fra_each = extAnnularTileFunc; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + + if (extComputeCapLW(&length, &width) == FALSE) + { + /* May be a complex area; fall back on + * computing an equivalent square area. + */ + length = (int)(sqrt((double)extTransRec.tr_termarea[0]) + + 0.5); + width = length; + } + + /* Free the lists */ + + for (i = 0; i < n; i++) + for (lb = extSpecialBounds[i]; lb != NULL; lb = lb->b_next) + freeMagic((char *)lb); + freeMagic((char *)extSpecialBounds); + + /* Put the region list back the way we found it: */ + /* Re-mark with extTransRec.tr_gatenode */ + + arg.fra_uninit = (ClientData) reg; + arg.fra_region = (ExtRegion *) extTransRec.tr_gatenode; + arg.fra_each = (int (*)()) NULL; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + } + } + fprintf(outFile, "%s %s", extDevTable[(unsigned char)devptr->exts_deviceClass], devptr->exts_deviceName); @@ -2885,7 +2985,15 @@ extOutputDevices(def, transList, outFile) arg.fra_each = extAnnularTileFunc; (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); - extComputeCapLW(&length, &width); + if (extComputeCapLW(&length, &width) == FALSE) + { + /* May be a complex area; fall back on + * computing an equivalent square area. + */ + length = (int)(sqrt((double)extTransRec.tr_termarea[0]) + + 0.5); + width = length; + } /* Free the lists */ @@ -2907,7 +3015,7 @@ extOutputDevices(def, transList, outFile) { /* (Nothing) */ } - else /* SPICE semiconductor resistor */ + else /* SPICE semiconductor capacitor */ { if ((length * width) > reg->treg_area) { diff --git a/extract/ExtTech.c b/extract/ExtTech.c index bdb512a6..60a906d0 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -81,7 +81,7 @@ typedef enum AREAC, CONTACT, CSCALE, DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP, DEFAULTSIDEWALL, - DEVICE, FET, FETRESIST, FRINGESHIELDHALO, + DEVICE, DEVRESIST, FET, FETRESIST, FRINGESHIELDHALO, HEIGHT, ANTENNA, MODEL, TIEDOWN, LAMBDA, OVERC, PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP, SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT @@ -122,7 +122,10 @@ static const keydesc keyTable[] = { "types plane capacitance [offset]"}, {"device", DEVICE, 4, 10, -"device dev-type types options..."}, +"dev-type dev-name types options..."}, + + {"devresist", DEVRESIST, 4, 4, +"type region ohms-per-square"}, {"fet", FET, 8, 9, "types terminal-types min-#-terminals name [subs-types] subs-node gscap gate-chan-cap"}, @@ -1958,7 +1961,6 @@ ExtTechLine(sectionName, argc, argv) char *subsName, *transName, *cp, *endptr, *paramName; TileType s, t, r, o; const keydesc *kp, *dv; - bool isLinear; HashEntry *he; EdgeCap *cnew; ExtKeep *es, *newStyle; @@ -2183,6 +2185,7 @@ ExtTechLine(sectionName, argc, argv) case CONTACT: case FET: case FETRESIST: + case DEVRESIST: case HEIGHT: case ANTENNA: case TIEDOWN: @@ -2545,11 +2548,17 @@ ExtTechLine(sectionName, argc, argv) argc--; } + class = dv->k_key; + + /* Note: This check has been removed. Parameters for non- */ + /* subcircuit devices are allowed for support of CDL */ + /* netlists, which uses arbitrary subcircuit-like */ + /* parameters combined with a SPICE-like device prefix. */ +#if 0 /* Check the number of arguments after splitting out */ /* parameter entries. There is no limit on arguments in */ /* DEV_SUBCKT, DEV_MSUBCKT, and DEV_VERILOGA. */ - class = dv->k_key; switch (class) { case DEV_SUBCKT: @@ -2575,6 +2584,7 @@ ExtTechLine(sectionName, argc, argv) } break; } +#endif gscap = (CapValue) 0; gccap = (CapValue) 0; @@ -2765,14 +2775,16 @@ ExtTechLine(sectionName, argc, argv) TTMaskSetMask(allExtractTypes, &termtypes[0]); termtypes[1] = DBZeroTypeBits; - if ((argc > 5) && strcmp(argv[5], "None")) + if ((argc > 5) && strcmp(argv[5], "None") && + (strchr(argv[5], '=') == NULL)) { DBTechNoisyNameMask(argv[5], &subsTypes); /* substrate */ TTMaskSetMask(allExtractTypes, &subsTypes); } else subsTypes = DBZeroTypeBits; - if (argc > 6) subsName = argv[6]; + if ((argc > 6) && (strchr(argv[6], '=') == NULL)) + subsName = argv[6]; break; } @@ -2812,7 +2824,6 @@ ExtTechLine(sectionName, argc, argv) } devptr->exts_deviceResist.ht_table = (HashEntry **) NULL; HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS); - devptr->exts_linearResist = 0; devptr->exts_next = ExtCurStyle->exts_device[t]; ExtCurStyle->exts_device[t] = devptr; @@ -2834,14 +2845,14 @@ ExtTechLine(sectionName, argc, argv) } break; + case DEVRESIST: case FETRESIST: - if (!StrIsInt(argv[3])) + if (!StrIsNumeric(argv[3])) { - TechError("Fet resistivity %s must be numeric\n", argv[3]); + TechError("Device resistivity %s must be numeric\n", argv[3]); break; } resVal = aToRes(argv[3]); - isLinear = (strcmp(argv[2], "linear") == 0); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { ExtDevice *devptr; @@ -2851,8 +2862,6 @@ ExtTechLine(sectionName, argc, argv) { he = HashFind(&devptr->exts_deviceResist, argv[2]); HashSetValue(he, (spointertype)resVal); - if (isLinear) - devptr->exts_linearResist = resVal; } } } @@ -3696,6 +3705,8 @@ zinit: for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next) { ParamList *chkParam; + HashEntry *he; + ResValue res; devptr->exts_deviceSDCap *= sqfac; devptr->exts_deviceGateCap *= sqfac; @@ -3723,6 +3734,28 @@ zinit: chkParam->pl_minimum /= dscale; } } + + he = HashLookOnly(&devptr->exts_deviceResist, "area"); + if (he != NULL) + { + res = (ResValue)(spointertype)(HashGetValue(he)); + res /= dsq; + HashSetValue(he, (spointertype)res); + } + he = HashLookOnly(&devptr->exts_deviceResist, "perimeter"); + if (he != NULL) + { + res = (ResValue)(spointertype)(HashGetValue(he)); + res /= dscale; + HashSetValue(he, (spointertype)res); + } + he = HashLookOnly(&devptr->exts_deviceResist, "linear"); + if (he != NULL) + { + res = (ResValue)(spointertype)(HashGetValue(he)); + res /= dscale; + HashSetValue(he, (spointertype)res); + } } style->exts_areaCap[r] *= sqfac; diff --git a/extract/extractInt.h b/extract/extractInt.h index 33f2396a..ff4711b7 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -506,7 +506,6 @@ typedef struct extDevice */ HashTable exts_deviceResist; - ResValue exts_linearResist; /* * Mask of the types of tiles that connect to the channel terminals diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index 2f61dc88..aabafb04 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -211,9 +211,14 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc) { float sheetr; ExtDevice *devptr; + HashEntry *he; devptr = ExtCurStyle->exts_device[fettype]; - sheetr = (float)devptr->exts_linearResist; + he = HashLookOnly(&devptr->exts_deviceResist, "linear"); + if (he != NULL) + sheetr = (ResValue)(spointertype)HashGetValue(he); + else + sheetr = (ResValue)0.0; result = (*fetproc)(line, sheetr, devptr); } if (result != 0) @@ -441,9 +446,14 @@ ResSimSubckt(line) if (lptr != NULL && wptr != NULL) { + HashEntry *he; float rpersquare; - rpersquare =(float)devptr->exts_linearResist; + he = HashLookOnly(&devptr->exts_deviceResist, "linear"); + if (he != NULL) + rpersquare = (ResValue)(spointertype)HashGetValue(he); + else + rpersquare = (ResValue)0.0; /* Subcircuit types may not have a length or width value, in which */ /* case it is zero. Don't induce a divide-by-zero error. */ if (MagAtof(wptr) == 0) diff --git a/utils/tech.c b/utils/tech.c index 9603c368..5b3ce861 100644 --- a/utils/tech.c +++ b/utils/tech.c @@ -66,7 +66,9 @@ global bool TechOverridesDefault; typedef struct FStack /* Linked FILE * pointers */ { FILE *file; - struct FStack *next; /* Pointer to another linked rectangle */ + char *filename; /* Keep file name of parent file */ + int linenum; /* Keep line number count at the include line */ + struct FStack *next; /* Pointer to another linked rectangle */ } filestack; int techLineNumber; @@ -537,6 +539,8 @@ TechLoad(filename, initmask) } topfile.file = tf; + topfile.filename = NULL; + topfile.linenum = 0; topfile.next = NULL; fstack = &topfile; @@ -602,15 +606,19 @@ TechLoad(filename, initmask) /* Check for file inclusions (can be nested) */ if ((argc > 1) && (!strcmp(argv[0], "include"))) { - char *sptr; + char *sptr, *increalname; - tf = PaOpen(argv[1], "r", suffix, ".", SysLibPath, NULL); + tf = PaOpen(argv[1], "r", suffix, ".", SysLibPath, &increalname); if (tf != NULL) { newstack = (filestack *)mallocMagic(sizeof(filestack)); newstack->file = tf; + newstack->filename = TechFileName; + newstack->linenum = techLineNumber; newstack->next = fstack; fstack = newstack; + techLineNumber = 0; + TechFileName = StrDup((char **)NULL, increalname); continue; } @@ -620,14 +628,18 @@ TechLoad(filename, initmask) if ((sptr = strrchr(TechFileName, '/')) != NULL) { *sptr = '\0'; - tf = PaOpen(argv[1], "r", suffix, TechFileName, NULL, NULL); + tf = PaOpen(argv[1], "r", suffix, TechFileName, NULL, &increalname); *sptr = '/'; if (tf != NULL) { newstack = (filestack *)mallocMagic(sizeof(filestack)); newstack->file = tf; + newstack->filename = TechFileName; + newstack->linenum = techLineNumber; newstack->next = fstack; fstack = newstack; + techLineNumber = 0; + TechFileName = StrDup((char **)NULL, increalname); continue; } } @@ -747,6 +759,7 @@ skipsection: while ((fstack != NULL) && (fstack != &topfile)) { fclose(fstack->file); + freeMagic(fstack->filename); freeMagic(fstack); fstack = fstack->next; } @@ -968,6 +981,9 @@ start: if ((*fstack)->next != NULL) { fclose((*fstack)->file); + freeMagic(TechFileName); + TechFileName = (*fstack)->filename; + techLineNumber = (*fstack)->linenum; *fstack = (*fstack)->next; file = (*fstack)->file; }