diff --git a/commands/CmdE.c b/commands/CmdE.c index df4bc2f1..f3b0a148 100644 --- a/commands/CmdE.c +++ b/commands/CmdE.c @@ -1096,7 +1096,7 @@ CmdExtract( "lumped estimate lumped resistance", "labelcheck check for connections through sticky labels", "aliases output all net name aliases", - "unique ensure unique node names during extraction", + "unique [notopports] ensure unique node names during extraction", "resistance extract resistance (same as \"do extresist\")", NULL }; @@ -1403,6 +1403,7 @@ CmdExtract( TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK)); TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES)); TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE)); + TxPrintf("%s unique notopports\n", OPTSET(EXT_DOUNIQNOTOPPORTS)); TxPrintf("%s resistance (extresist)\n", OPTSET(EXT_DOEXTRESIST)); return; #undef OPTSET @@ -1433,9 +1434,19 @@ CmdExtract( case DORESISTANCE: option = EXT_DORESISTANCE; break; case DOLABELCHECK: option = EXT_DOLABELCHECK; break; case DOALIASES: option = EXT_DOALIASES; break; - case DOUNIQUE: option = EXT_DOUNIQUE; break; case DOEXTRESIST: case DOEXTRESIST2: option = EXT_DOEXTRESIST; break; + case DOUNIQUE: + if (argc == 4) + { + if (!strncmp(argv[3], "notop", 5)) + option = EXT_DOUNIQNOTOPPORTS | EXT_DOUNIQUE; + else + TxError("Usage: extract do unique [notopports]\n"); + } + else + option = EXT_DOUNIQUE; + break; case DOLOCAL: /* "extract do local" and "extract no local" are kept for * backwards compatibility, but now effectively implement diff --git a/doc/html/extract.html b/doc/html/extract.html index 101ab739..b1926498 100644 --- a/doc/html/extract.html +++ b/doc/html/extract.html @@ -102,16 +102,17 @@ Circuit netlist extractor but will usually just slow down processing by commands like "ext2spice" that use the .ext file contents, so it is disabled by default. -
unique +
unique [notopports]
(Added in magic version 8.3.594) This setting replaces - the use of the command option "extract unique". Instead - of changing labels in the design, unique labels are - generated for the duration of the extraction, and then - reverted back to the original text. The "extract unique" - command option is maintained for backwards compatibility. - Note the difference: "extract unique" is a command that - runs immediately, and cannot be undone; - "extract do unique" is an option setting for "extract". + the use of the command option "extract unique" (and + "extract unique notopports"). Instead of changing labels + in the design, unique labels are generated for the duration + of the extraction, and then reverted back to the original + text. The "extract unique" command option is maintained + for backwards compatibility. Note the difference: + "extract unique" is a command that runs immediately, and + cannot be undone; "extract do unique" is an option setting + for "extract".
resistance
(Added in magic version 8.3.597) This setting replaces the use of the standalone command "extresist". The diff --git a/doc/html/extresist.html b/doc/html/extresist.html index b69e256b..7d33854a 100644 --- a/doc/html/extresist.html +++ b/doc/html/extresist.html @@ -43,8 +43,7 @@ information.
With no value given, returns the current delay time threshold used to determine if a network will or will not be analyzed for resistance extraction, in picoseconds. The default - mindelay value is zero, indicating that delay time is - not used for determining extraction. If value is given, + mindelay value is 1ps. If value is given, then set the delay threshold to value picoseconds.
minres [value]
With no value given, returns the current absolute resistance diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 3885ac80..a9ca1fdd 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -629,6 +629,8 @@ extSetResist(reg) for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) { + ResValue resnew, restot; + reg->nreg_pa[n].pa_area = area = extResistArea[n]; reg->nreg_pa[n].pa_perim = perim = extResistPerim[n]; if (area > 0 && perim > 0) @@ -639,8 +641,15 @@ extSetResist(reg) if (v < 0) s = 0; else s = sqrt(v); fperim = (float) perim; - reg->nreg_resist += (fperim + s) / (fperim - s) - * ExtCurStyle->exts_resistByResistClass[n]; + resnew = (fperim + s) / (fperim - s) * + ExtCurStyle->exts_resistByResistClass[n]; + restot = reg->nreg_resist + resnew; + + /* Check for integer overflow. There is no point in trying + * to accommodate huge resistance values for an estimate. + * The value just saturates at the maximum integer value. + */ + if (restot > 0) reg->nreg_resist = restot; } /* Reset for the next pass */ diff --git a/extract/ExtCell.c b/extract/ExtCell.c index 994b47cb..46be433e 100644 --- a/extract/ExtCell.c +++ b/extract/ExtCell.c @@ -76,14 +76,10 @@ void extHeader(); */ Plane * -ExtCell(def, outName, doLength) +ExtCell(def, outName, isTop) CellDef *def; /* Cell being extracted */ char *outName; /* Name of output file; if NULL, derive from def name */ - bool doLength; /* If TRUE, extract pathlengths from drivers to - * receivers (the names are stored in ExtLength.c). - * Should only be TRUE for the root cell in a - * hierarchy. - */ + bool isTop; /* If TRUE, cell is the top level cell */ { char *filename; FILE *f = NULL; @@ -116,7 +112,7 @@ ExtCell(def, outName, doLength) } extNumErrors = extNumWarnings = 0; - savePlane = extCellFile(def, f, doLength); + savePlane = extCellFile(def, f, isTop); if (f != NULL) fclose(f); if (extNumErrors > 0 || extNumWarnings > 0) @@ -476,13 +472,10 @@ ExtRevertSubstrate(def, savePlane) */ Plane * -extCellFile(def, f, doLength) +extCellFile(def, f, isTop) CellDef *def; /* Def to be extracted */ FILE *f; /* Output to this file */ - bool doLength; /* TRUE if we should extract driver-receiver path - * length information for this cell (see ExtCell - * for more details). - */ + bool isTop; /* TRUE if the cell is the top level cell */ { NodeRegion *reg; Plane *saveSub; @@ -493,8 +486,19 @@ extCellFile(def, f, doLength) /* If "extract do unique" was specified, then make labels in the * cell unique. */ + if (ExtOptions & EXT_DOUNIQUE) - extUniqueCell(def, EXT_UNIQ_TEMP); + { + if (ExtOptions & EXT_DOUNIQNOTOPPORTS) + { + if (isTop) + extUniqueCell(def, EXT_UNIQ_TEMP_NOPORTS); + else + extUniqueCell(def, EXT_UNIQ_TEMP); + } + else + extUniqueCell(def, EXT_UNIQ_TEMP); + } /* Prep any isolated substrate areas */ if (ExtOptions & EXT_DOEXTRESIST) @@ -524,7 +528,7 @@ extCellFile(def, f, doLength) ExtResetTiles(def, CLIENTDEFAULT); /* Final pass: extract length information if desired */ - if (!SigInterruptPending && doLength && (ExtOptions & EXT_DOLENGTH)) + if (!SigInterruptPending && isTop && (ExtOptions & EXT_DOLENGTH)) extLength(extParentUse, f); UndoEnable(); diff --git a/extract/ExtMain.c b/extract/ExtMain.c index bdc594af..ec1f475d 100644 --- a/extract/ExtMain.c +++ b/extract/ExtMain.c @@ -473,6 +473,19 @@ ExtUnique(rootUse, option) /* Fix up bounding boxes if they've changed */ DBFixMismatch(); + /* Because the "extract unique" does the same thing as "extract do unique" + * but the options may be different, disable "extract do unique" when + * "extract unique" is run, on the assumption that no user would + * intentionally use both methods. If "do unique" was set and got + * disabled, then flag a warning. + */ + if (ExtOptions & EXT_DOUNIQUE) + { + ExtOptions &= ~EXT_DOUNIQUE; + TxPrintf("Warning: Extract option \"do unique\" disabled because " + "\"extract unique\" was run.\n"); + } + /* Mark all defs as being unvisited */ (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); diff --git a/extract/ExtUnique.c b/extract/ExtUnique.c index 93726a13..82f4772d 100644 --- a/extract/ExtUnique.c +++ b/extract/ExtUnique.c @@ -66,6 +66,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ * label. This way, the unique label form can be used by the * extraction code but labels (and port indexes) can be reverted * afterward, and no permanent change is made to the circuit. + * Option EXT_UNIQ_TEMP_NOPORTS is a combination of EXT_UNIQ_TEMP and + * EXT_UNIQ_NOPORTS. * * Results: * Returns the number of warnings generated. @@ -226,8 +228,9 @@ extMakeUnique(def, ll, lreg, lregList, labelHash, option) text = ll->ll_label->lab_text; if (option == EXT_UNIQ_ALL || option == EXT_UNIQ_TEMP) goto makeUnique; - else if ((option == EXT_UNIQ_NOPORTS || option == EXT_UNIQ_NOTOPPORTS) - && !(ll->ll_label->lab_flags & PORT_DIR_MASK)) + else if ((option == EXT_UNIQ_NOPORTS || option == EXT_UNIQ_NOTOPPORTS || + option == EXT_UNIQ_TEMP_NOPORTS) && + !(ll->ll_label->lab_flags & PORT_DIR_MASK)) goto makeUnique; cpend = strchr(text, '\0'); @@ -326,7 +329,8 @@ makeUnique: saveLab = *lab; /* Flag this label as having been modified */ - if (option == EXT_UNIQ_TEMP) flags |= LABEL_UNIQUE; + if ((option == EXT_UNIQ_TEMP) || (option == EXT_UNIQ_TEMP_NOPORTS)) + flags |= LABEL_UNIQUE; DBRemoveLabel(def, lab); DBPutFontLabel(def, &saveLab.lab_rect, diff --git a/extract/extract.h b/extract/extract.h index 19242f65..43cd687b 100644 --- a/extract/extract.h +++ b/extract/extract.h @@ -76,6 +76,7 @@ extern const char * const extDevTable[]; #define EXT_DOLABELCHECK 0x040 /* Check for connections by label */ #define EXT_DOALIASES 0x080 /* Output all node aliases */ #define EXT_DOEXTRESIST 0x200 /* Do full R-C extraction */ +#define EXT_DOUNIQNOTOPPORTS 0x400 /* Ignore top cell ports w/EXT_DOUNIQUE */ extern int ExtOptions; /* Bitmask of above */ extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */ @@ -86,6 +87,7 @@ extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */ #define EXT_UNIQ_NOPORTS 2 #define EXT_UNIQ_NOTOPPORTS 3 #define EXT_UNIQ_TEMP 4 /* Used only with "EXT_DOUNIQUE" */ +#define EXT_UNIQ_TEMP_NOPORTS 5 /* Used only with "EXT_DOUNIQUE" */ extern bool ExtTechLine(); extern void ExtTechInit(); diff --git a/resis/ResMain.c b/resis/ResMain.c index 9c90ac53..a30f5fdb 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -1382,8 +1382,6 @@ ResExtractNet(node, resisdata, cellname) } DBReComputeBbox(ResUse->cu_def); - ExtResetTiles(scx.scx_use->cu_def, CLIENTDEFAULT); - /* To avoid issues with overlapping stacked contact types and */ /* double-counting contacts on multiple planes, erase the top */ /* contact layers of all contacts. ExtFindRegions() will still */ diff --git a/resis/ResReadExt.c b/resis/ResReadExt.c index 12fc35e4..6b2cbedc 100644 --- a/resis/ResReadExt.c +++ b/resis/ResReadExt.c @@ -519,6 +519,7 @@ ResReadNode(int argc, char *argv[]) { HashEntry *entry; ResExtNode *node; + int noderesist; entry = HashFind(&ResNodeTable, argv[NODES_NODENAME]); node = ResExtInitNode(entry); @@ -526,7 +527,10 @@ ResReadNode(int argc, char *argv[]) node->location.p_x = atoi(argv[NODES_NODEX]); node->location.p_y = atoi(argv[NODES_NODEY]); node->type = DBTechNameType(argv[NODES_NODETYPE]); - node->resistance = atoi(argv[NODES_NODERES]); + noderesist = atoi(argv[NODES_NODERES]); + if (noderesist < 0) noderesist = INFINITY; + /* Make sure node resistance is in units of milliohms */ + node->resistance = (float)noderesist * (float)ExtCurStyle->exts_resistScale; if (node->type == -1) { diff --git a/resis/ResRex.c b/resis/ResRex.c index 7f9743cb..51c77528 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -218,11 +218,11 @@ ResInit() /* Defaults: * (1) rthresh: Only extract networks with a lumped resistance > 10 ohms * (2) minres: Prune resistors < 1 ohm when possible - * (3) mindelay: Do not gate extraction based on calculated delay. + * (3) mindelay: Only extract networks with a calculated delay > 1 ps */ resisdata->rthresh = 10000.0; resisdata->minres = 1000.0; - resisdata->mindelay = 0.0; + resisdata->mindelay = 1.0e9; /* 1ps = 1.0e9zs resisdata->frequency = 10e6; /* 10 MHz default */ HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS); @@ -407,7 +407,8 @@ typedef enum { Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)resisdata->rthresh)); #else - TxPrintf("Minimum resistor threshold is %g.\n", resisdata->rthresh); + TxPrintf("Minimum resistor threshold is %g mohms.\n", + resisdata->rthresh); #endif } return; @@ -1907,9 +1908,17 @@ ResWriteExtFile(celldef, node, resisdata, nidx, eidx) if (!(ResOptionsFlags & ResOpt_RunSilent)) { - TxPrintf("Adding %s; (Tnew = %.2fps ; Tmin = %.2fps)\n", - node->name, resisdata->rg_Tdi * Z_TO_P, - resisdata->mindelay * Z_TO_P); + float ftdi, fdmin; + + ftdi = resisdata->rg_Tdi * Z_TO_P; + fdmin = resisdata->mindelay * Z_TO_P; + + if ((ftdi < 0.01) || ((fdmin < 0.01) && (resisdata->mindelay > 0))) + TxPrintf("Adding %s; (Tnew = %.2ffs ; Tmin = %.2ffs)\n", + node->name, ftdi * 1000, fdmin * 1000); + else + TxPrintf("Adding %s; (Tnew = %.2fps ; Tmin = %.2fps)\n", + node->name, ftdi, fdmin); } for (ptr = node->devices; ptr != NULL; ptr = ptr->nextDev)