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)