diff --git a/VERSION b/VERSION
index 0e432872..55e52029 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-8.3.593
+8.3.594
diff --git a/commands/CmdE.c b/commands/CmdE.c
index 402ebe09..650a8b5d 100644
--- a/commands/CmdE.c
+++ b/commands/CmdE.c
@@ -930,6 +930,7 @@ cmdExpandFunc(
#define DORESISTANCE 6
#define DOLABELCHECK 7
#define DOALIASES 8
+#define DOUNIQUE 9
#define LENCLEAR 0
#define LENDRIVER 1
@@ -977,6 +978,7 @@ CmdExtract(
"resistance estimate resistance",
"labelcheck check for connections through sticky labels",
"aliases output all net name aliases",
+ "unique ensure unique node names during extraction",
NULL
};
static const char * const cmdExtLength[] =
@@ -1280,6 +1282,7 @@ CmdExtract(
TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE));
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
+ TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE));
return;
#undef OPTSET
}
@@ -1309,6 +1312,7 @@ 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 DOLOCAL:
/* "extract do local" and "extract no local" are kept for
* backwards compatibility, but now effectively implement
diff --git a/database/database.h.in b/database/database.h.in
index 6801a7cd..a7a089a1 100644
--- a/database/database.h.in
+++ b/database/database.h.in
@@ -303,9 +303,14 @@ typedef struct label
#define PORT_SHAPE_RING 0x1000 /* Port is a ring shape */
#define PORT_SHAPE_THRU 0x1800 /* Port is a feedthrough shape */
-#define PORT_VISITED 0x2000 /* Bit for checking if a port */
+#define LABEL_STICKY 0x2000 /* Label does not change layers */
+#define LABEL_UNIQUE 0x4000 /* Temporary unique label */
+
+/* The last two flags are never used at the same time and so can share
+ * a flag bit.
+ */
+#define PORT_VISITED 0x8000 /* Bit for checking if a port */
/* has been previously visited. */
-#define LABEL_STICKY 0x4000 /* Label does not change layers */
#define LABEL_GENERATE 0x8000 /* Auto-generated label */
/*
diff --git a/doc/html/extract.html b/doc/html/extract.html
index 6f9e4896..3dfa4755 100644
--- a/doc/html/extract.html
+++ b/doc/html/extract.html
@@ -99,6 +99,16 @@ 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
+ (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".
These options (except for "local") determine how much
diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c
index 45690838..a9ca61c7 100644
--- a/extflat/EFbuild.c
+++ b/extflat/EFbuild.c
@@ -907,6 +907,9 @@ efBuildDevice(
case DEV_FET:
case DEV_MOSFET:
case DEV_ASYMMETRIC:
+ /* Terminals start after L and W values, substrate, and parameters */
+ termstart = 3;
+ break;
case DEV_BJT:
/* Terminals start after L and W values, plus parameters */
termstart = 2;
diff --git a/extract/ExtCell.c b/extract/ExtCell.c
index 98bc5898..26fa5cb9 100644
--- a/extract/ExtCell.c
+++ b/extract/ExtCell.c
@@ -486,6 +486,12 @@ extCellFile(def, f, doLength)
UndoDisable();
+ /* If "extract do unique" was specified, then make labels in the
+ * cell unique.
+ */
+ if (ExtOptions & EXT_DOUNIQUE)
+ extUniqueCell(def, EXT_UNIQ_TEMP);
+
/* Prep any isolated substrate areas */
saveSub = extPrepSubstrate(def);
diff --git a/extract/ExtMain.c b/extract/ExtMain.c
index 73db17b6..c502d998 100644
--- a/extract/ExtMain.c
+++ b/extract/ExtMain.c
@@ -806,12 +806,13 @@ ExtractOneCell(def, outName, doLength)
savePlane = ExtCell(def, outName, doLength);
- /* Restore all modified substrate planes */
+ /* Restore all modified substrate planes and modified labels */
if (savePlane != NULL) ExtRevertSubstrate(def, savePlane);
free_magic1_t mm1 = freeMagic1_init();
for (; sl; sl = sl->sl_next)
{
+ if (EXT_DOUNIQUE) ExtRevertUniqueCell(sl->sl_def);
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
freeMagic1(&mm1, sl);
}
@@ -1026,10 +1027,12 @@ extExtractStack(stack, doExtract, rootDef)
}
}
- /* Replace any modified substrate planes */
+ /* Replace any modified substrate planes and modified labels */
free_magic1_t mm1 = freeMagic1_init();
for (; sl; sl = sl->sl_next)
{
+ if (EXT_DOUNIQUE) ExtRevertUniqueCell(sl->sl_def);
+
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
sl->sl_def->cd_flags &= ~CDNOEXTRACT;
freeMagic1(&mm1, sl);
diff --git a/extract/ExtTech.c b/extract/ExtTech.c
index d585f259..973c8179 100644
--- a/extract/ExtTech.c
+++ b/extract/ExtTech.c
@@ -2747,24 +2747,34 @@ ExtTechLine(sectionName, argc, argv)
DBTechNoisyNameMask(argv[4], &termtypes[0]); /* bottom */
TTMaskSetMask(allExtractTypes, &termtypes[0]);
termtypes[1] = DBZeroTypeBits;
-
- if (argc > 5)
- gccap = aToCap(argv[argc - 1]); /* area cap */
- if ((argc > 6) && StrIsNumeric(argv[argc - 2]))
- {
- gscap = aToCap(argv[argc - 2]); /* perimeter cap */
- argc--;
- }
nterm = 1;
- if ((argc > 6) && strcmp(argv[5], "None"))
+ /* If argv[argc - 1] is a numerical value, then it is
+ * an area cap value and may be followed by another
+ * numerical value, the perimeter cap.
+ */
+
+ if ((argc > 5) && StrIsNumeric(argv[argc - 1]))
{
- DBTechNoisyNameMask(argv[5], &subsTypes); /* substrate */
+ gccap = aToCap(argv[argc - 1]); /* area cap */
+ argc--;
+
+ if ((argc > 5) && StrIsNumeric(argv[argc - 1]))
+ {
+ gscap = aToCap(argv[argc - 1]); /* perimeter cap */
+ argc--;
+ }
+ }
+
+ if ((argc > 5) && strcmp(argv[5], "None"))
+ {
+ /* substrate */
+ DBTechNoisyNameMask(argv[5], &subsTypes);
TTMaskSetMask(allExtractTypes, &subsTypes);
}
else
subsTypes = DBZeroTypeBits;
- if (argc > 7) subsName = argv[6];
+ if (argc > 6) subsName = argv[6];
break;
case DEV_SUBCKT:
diff --git a/extract/ExtUnique.c b/extract/ExtUnique.c
index c3716a0a..93726a13 100644
--- a/extract/ExtUnique.c
+++ b/extract/ExtUnique.c
@@ -61,6 +61,11 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
* names that don't end in '!'.
* If option is EXT_UNIQ_NOPORTS, then generate unique names as for
* option 0 only if the label is not a port.
+ * If option is EXT_UNIQ_TEMP, then generate unique names as for
+ * EXT_UNIQ_ALL, but also set the LABEL_UNIQUE flag for the
+ * 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.
*
* Results:
* Returns the number of warnings generated.
@@ -219,7 +224,7 @@ extMakeUnique(def, ll, lreg, lregList, labelHash, option)
* changes a label to make it unique.
*/
text = ll->ll_label->lab_text;
- if (option == EXT_UNIQ_ALL)
+ 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))
@@ -320,8 +325,11 @@ makeUnique:
lab = ll2->ll_label;
saveLab = *lab;
+ /* Flag this label as having been modified */
+ if (option == EXT_UNIQ_TEMP) flags |= LABEL_UNIQUE;
+
DBRemoveLabel(def, lab);
- (void) DBPutFontLabel(def, &saveLab.lab_rect,
+ DBPutFontLabel(def, &saveLab.lab_rect,
saveLab.lab_font, saveLab.lab_size, saveLab.lab_rotate,
&saveLab.lab_offset, saveLab.lab_just, name2,
saveLab.lab_type, flags, (unsigned int)portno);
@@ -334,3 +342,64 @@ makeUnique:
return 0;
}
+
+/*
+ * ----------------------------------------------------------------------------
+ *
+ * extRevertUniqueCell --
+ *
+ * For the cell 'def', look for labels marked with LABEL_UNIQUE and
+ * remove the unique suffix. If the label is a port, then revert
+ * the port index back to the original port number.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the label records in the cell def.
+ *
+ * ----------------------------------------------------------------------------
+ */
+
+void
+ExtRevertUniqueCell(CellDef *def)
+{
+ Label *lab, *tlab;
+ char *uptr;
+
+ for (lab = def->cd_labels; lab; lab = lab->lab_next)
+ {
+ if (lab->lab_flags & LABEL_UNIQUE)
+ {
+ /* There is no need to regenerate the label. We are
+ * only reducing the string length, so just drop a null
+ * at the last underscore and leave it at that.
+ */
+
+ lab->lab_flags &= ~LABEL_UNIQUE; /* Clear the flag */
+
+ /* Place a null at the last underscore */
+ uptr = strrchr(lab->lab_text, '_');
+ if (uptr != NULL) /* should always be true */
+ *uptr = '\0';
+
+ /* If the label is a port, then find the first unmodified
+ * version of the label and change the port back to its
+ * port number
+ */
+ if (lab->lab_flags & PORT_DIR_MASK)
+ {
+ for (tlab = def->cd_labels; tlab; tlab = tlab->lab_next)
+ {
+ if (tlab == lab) continue;
+ else if (!strcmp(tlab->lab_text, lab->lab_text))
+ {
+ lab->lab_port = tlab->lab_port;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/extract/extract.h b/extract/extract.h
index fd3d27ea..e0dd2f53 100644
--- a/extract/extract.h
+++ b/extract/extract.h
@@ -74,6 +74,7 @@ extern const char * const extDevTable[];
#define EXT_DOALL 0x03f /* ALL OF THE ABOVE */
#define EXT_DOLABELCHECK 0x040 /* Check for connections by label */
#define EXT_DOALIASES 0x080 /* Output all node aliases */
+#define EXT_DOUNIQUE 0x100 /* Force unique nodes during extraction */
extern int ExtOptions; /* Bitmask of above */
extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */
@@ -83,6 +84,7 @@ extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */
#define EXT_UNIQ_TAGGED 1
#define EXT_UNIQ_NOPORTS 2
#define EXT_UNIQ_NOTOPPORTS 3
+#define EXT_UNIQ_TEMP 4 /* Used only with "EXT_DOUNIQUE" */
extern bool ExtTechLine();
extern void ExtTechInit();
diff --git a/extract/extractInt.h b/extract/extractInt.h
index dc584298..23368c2e 100644
--- a/extract/extractInt.h
+++ b/extract/extractInt.h
@@ -1126,6 +1126,7 @@ extern int extMakeUnique();
extern void extEnumTerminal();
extern void extEnumTerminal(Tile *tile, TileType dinfo,
TileTypeBitMask *connect, void (*func)(), ClientData clientData);
+extern void ExtRevertUniqueCell(CellDef *def);
/* ------------------ Connectivity table management ------------------- */