From 308224109fb387237f71f225e5d6b10461e87cbb Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Thu, 22 Jan 2026 11:20:20 -0500 Subject: [PATCH] Multiple fixes and updates: (1) Fixed an error that was introduced in version 8.3.590 with a patch that should have been applied only for the case of BJT devices, and not for MOSFETs. The patch will cause devices generated by "device mosfet" or "device asymmetric" to be read incorrectly from a .ext file during "ext2spice". (2) Fixed an error in the tech file reading, where using CDL parameters on a capacitor device would cause the tech file loader to print an error message. The parsing was correct and only the message should not have been printed. (3) Added a new feature with the new command option "extract do unique". This replaces the "extract unique" command by running the same code within the extraction, but has the additional effect of reverting the label changes afterward. This prevents the user from inadvertently writing the altered labels back to the database file. --- VERSION | 2 +- commands/CmdE.c | 4 +++ database/database.h.in | 9 ++++-- doc/html/extract.html | 10 ++++++ extflat/EFbuild.c | 3 ++ extract/ExtCell.c | 6 ++++ extract/ExtMain.c | 7 ++-- extract/ExtTech.c | 32 +++++++++++------- extract/ExtUnique.c | 73 ++++++++++++++++++++++++++++++++++++++++-- extract/extract.h | 2 ++ extract/extractInt.h | 1 + 11 files changed, 131 insertions(+), 18 deletions(-) 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 ------------------- */