diff --git a/VERSION b/VERSION index d7e92369..ad509384 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.646 +8.3.658 diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 0536078d..57014937 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -4171,12 +4171,21 @@ cifSrTiles2( } cifScale = 1; - for (t = 0; t < TT_MAXTYPES; t++, temps++) - if (TTMaskHasType(&cifOp->co_cifMask, t)) - if (DBSrPaintArea((Tile *)NULL, *temps, area, + if (TTMaskIsZero(&cifOp->co_cifMask) && TTMaskIsZero(&cifOp->co_paintMask)) + { + /* Current CIF plane is in *temps */ + if (DBSrPaintArea((Tile *)NULL, *temps, area, &CIFSolidBits, func, (ClientData)cdArg)) - return 1; - + return 1; + } + else + { + for (t = 0; t < TT_MAXTYPES; t++, temps++) + if (TTMaskHasType(&cifOp->co_cifMask, t)) + if (DBSrPaintArea((Tile *)NULL, *temps, area, + &CIFSolidBits, func, (ClientData)cdArg)) + return 1; + } return 0; } @@ -5454,7 +5463,6 @@ CIFGenLayer( if (bloats->bl_plane < 0) /* Bloat types are CIF types */ { - bls.temps = temps; for (ttype = 0; ttype < TT_MAXTYPES; ttype++, bls.temps++) if (bloats->bl_distance[ttype] > 0) (void) DBSrPaintArea((Tile *)NULL, *bls.temps, &TiPlaneRect, @@ -5660,6 +5668,20 @@ CIFGenLayer( bloats->bl_distance[ttype] = 0; } } + else + { + /* Operate on the existing plane. */ + + bloats->bl_distance[0] = 1; + for (ttype = 1; ttype < TT_MAXTYPES; ttype++) + bloats->bl_distance[ttype] = 0; + + bloats->bl_plane = -1; + bls.temps = &curPlane; + + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + } /* Replace the client data with the bloat record */ op->co_client = (ClientData)bloats; @@ -5680,15 +5702,33 @@ CIFGenLayer( } for (label = cellDef->cd_labels; label; label = label->lab_next) + { if (!strcmp(label->lab_text, text)) - cifSrTiles2(op, &label->lab_rect, cellDef, temps, + { + Rect labr = label->lab_rect; + + /* Since cifSrTiles2() searches over an area, the + * area must not be degenerate. + */ + if (labr.r_xbot == labr.r_xtop) + { + labr.r_xbot--; + labr.r_xtop++; + } + if (labr.r_ybot == labr.r_ytop) + { + labr.r_ybot--; + labr.r_ytop++; + } + cifSrTiles2(op, &labr, cellDef, bls.temps, cifBloatAllFunc, (ClientData)&bls); + } + } /* Reset marked tiles */ if (bloats->bl_plane < 0) /* Bloat types are CIF types */ { - bls.temps = temps; for (ttype = 0; ttype < TT_MAXTYPES; ttype++, bls.temps++) if (bloats->bl_distance[ttype] > 0) (void) DBSrPaintArea((Tile *)NULL, *bls.temps, &TiPlaneRect, @@ -5706,6 +5746,15 @@ CIFGenLayer( /* Replace the client data */ op->co_client = (ClientData)text; + /* If operating on the current plane, swap the current + * and next planes. + */ + if (TTMaskIsZero(&op->co_cifMask) && TTMaskIsZero(&op->co_paintMask)) + { + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + } break; case CIFOP_BOUNDARY: diff --git a/cif/CIFrdtech.c b/cif/CIFrdtech.c index 6157e480..efe5ee5e 100644 --- a/cif/CIFrdtech.c +++ b/cif/CIFrdtech.c @@ -1032,9 +1032,10 @@ CIFReadTechLine( newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]); break; case CIFOP_TAGGED: - if (argc != 3) goto wrongNumArgs; + if ((argc != 2) && (argc != 3)) goto wrongNumArgs; newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]); - CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE); + if (argc == 3) + CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE); break; } diff --git a/cif/CIFtech.c b/cif/CIFtech.c index 9d01468b..f9f983a7 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -1360,10 +1360,11 @@ bloatCheck: case CIFOP_NET: case CIFOP_TAGGED: - if (argc != 3) goto wrongNumArgs; + if ((argc != 2) && (argc != 3)) goto wrongNumArgs; newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]); - cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask, - &newOp->co_cifMask, FALSE); + if (argc == 3) + cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask, + &newOp->co_cifMask, FALSE); break; case CIFOP_MASKHINTS: 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/commands/CmdLQ.c b/commands/CmdLQ.c index 2c9006d2..6b3245b3 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -2324,7 +2324,7 @@ CmdDoProperty( TxCommand *cmd, int argstart) { - PropertyRecord *proprec; + PropertyRecord *proprec = NULL; char *value; bool propfound, dolist; int proptype, proplen, propvalue, i; @@ -2662,31 +2662,31 @@ CmdDoProperty( * the valid number of arguments, then again to parse the * values, once the property record has been allocated */ - if (proptype == PROPERTY_TYPE_PLANE) + value = cmd->tx_argv[argstart + 1]; + for (proplen = 0; *value != '\0'; ) { - proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); - plane = DBNewPlane((ClientData)TT_SPACE); - proprec->prop_value.prop_plane = plane; - } - else - { - value = cmd->tx_argv[argstart + 1]; - for (proplen = 0; *value != '\0'; ) + if (isspace(*value) && (*value != '\0')) value++; + if (!isspace(*value)) { - if (isspace(*value) && (*value != '\0')) value++; - if (!isspace(*value)) - { - proplen++; - while (!isspace(*value) && (*value != '\0')) value++; - } + proplen++; + while (!isspace(*value) && (*value != '\0')) value++; } - if (proplen > 0) + } + if (proplen > 0) + { + if (proptype == PROPERTY_TYPE_PLANE) + { + proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); + plane = DBNewPlane((ClientData)TT_SPACE); + proprec->prop_value.prop_plane = plane; + } else { proprec = (PropertyRecord *)mallocMagic( sizeof(PropertyRecord) + (proplen - 2) * sizeof(int)); + } + proprec->prop_type = proptype; + proprec->prop_len = proplen; } - proprec->prop_type = proptype; - proprec->prop_len = proplen; /* Second pass */ value = cmd->tx_argv[argstart + 1]; diff --git a/commands/CmdRS.c b/commands/CmdRS.c index 4ed1f16b..89f30ace 100644 --- a/commands/CmdRS.c +++ b/commands/CmdRS.c @@ -647,6 +647,9 @@ cmdSelectArea( if (!(crec->dbw_flags & DBW_SEELABELS)) TTMaskClearType(&mask, L_LABEL); if (!(crec->dbw_flags & DBW_SEECELLS)) TTMaskClearType(&mask, L_CELL); } + else if (option == SEL_AREA) + TTMaskSetType(&mask, L_LABEL); + SelectArea(&scx, &mask, crec->dbw_bitmask, globmatch); } diff --git a/database/DBconnect.c b/database/DBconnect.c index c8c767ed..a9c7bfdb 100644 --- a/database/DBconnect.c +++ b/database/DBconnect.c @@ -1037,7 +1037,13 @@ dbcConnectFunc(tile, dinfo, cx) if (++csa2->csa2_top == CSA2_LIST_SIZE) { /* Reached list size limit---need to push the list and */ - /* start a new one. */ + /* start a new one. NOTE: Setting lasttop to -1 means */ + /* that some entries may be duplicated between the */ + /* stacks, which is a small inefficiency. In theory, */ + /* lasttop could be left as is, then if lasttop > top */ + /* when searching the last 5 entries, pop the stack, do */ + /* the search, and then push the stack again. But it's */ + /* a lot easier just to be slightly inefficient. */ conSrArea *newlist; @@ -1045,6 +1051,7 @@ dbcConnectFunc(tile, dinfo, cx) StackPush((ClientData)csa2->csa2_list, csa2->csa2_stack); csa2->csa2_list = newlist; csa2->csa2_top = 0; + csa2->csa2_lasttop = -1; } csa2->csa2_list[csa2->csa2_top].area = newarea; diff --git a/database/DBlabel.c b/database/DBlabel.c index a77bdf18..f8e0f58a 100644 --- a/database/DBlabel.c +++ b/database/DBlabel.c @@ -574,7 +574,8 @@ DBReOrientLabel(cellDef, area, newPos) * dbGetLabelArea --- * * Callback function used by DBAdjustLabels. Find all material under a label - * that is *not* the label type, and return the + * that is *not* the label type, and return the label area adjusted to leave + * out that amount. * * Note: This clips in a regular order, and does not consider what is the * largest rectangular area outside the area that has been clipped out. @@ -604,6 +605,26 @@ dbGetLabelArea(tile, dinfo, area) return 0; } +/* + * ---------------------------------------------------------------------------- + * + * dbLabelNotEmpty --- + * + * Callback function used by DBAdjustLabels. Finds any material under a + * label that is the label type, and returns 1 to stop the search. + * + * ---------------------------------------------------------------------------- + */ + +int +dbLabelNotEmpty(tile, dinfo, clientData) + Tile *tile; /* Tile found. */ + TileType dinfo; /* Split tile information (unused) */ + ClientData clientData; /* (unused) */ +{ + return 1; +} + /* * ---------------------------------------------------------------------------- * @@ -661,28 +682,37 @@ DBAdjustLabels(def, area) TTMaskSetOnlyType(&lmask, lab->lab_type); /* To do: Add compatible types (contact, residue) */ - TTMaskCom(&lmask); - r = lab->lab_rect; - DBSrPaintArea((Tile *) NULL, def->cd_planes[DBPlane(lab->lab_type)], - &lab->lab_rect, &lmask, dbGetLabelArea, (ClientData) &r); - - if (!GEO_RECTNULL(&r)) + /* If there is no material left inside the label area, then + * the label gets reassigned to space. + */ + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[DBPlane(lab->lab_type)], + &lab->lab_rect, &lmask, dbLabelNotEmpty, (ClientData)NULL) == 1) { - if ((DBVerbose >= DB_VERBOSE_ALL) && ((def->cd_flags & CDINTERNAL) == 0)) - { - TxPrintf("Adjusting size of label \"%s\" in cell %s.\n", - lab->lab_text, def->cd_name); - } + TTMaskCom(&lmask); - DBUndoEraseLabel(def, lab); - DBWLabelChanged(def, lab, DBW_ALLWINDOWS); - lab->lab_rect = r; - DBFontLabelSetBBox(lab); - DBUndoPutLabel(def, lab); - DBWLabelChanged(def, lab, DBW_ALLWINDOWS); - modified = TRUE; - adjusted = TRUE; + r = lab->lab_rect; + DBSrPaintArea((Tile *) NULL, def->cd_planes[DBPlane(lab->lab_type)], + &lab->lab_rect, &lmask, dbGetLabelArea, (ClientData) &r); + + if (!GEO_RECTNULL(&r)) + { + if ((DBVerbose >= DB_VERBOSE_ALL) && + ((def->cd_flags & CDINTERNAL) == 0)) + { + TxPrintf("Adjusting size of label \"%s\" in cell %s.\n", + lab->lab_text, def->cd_name); + } + + DBUndoEraseLabel(def, lab); + DBWLabelChanged(def, lab, DBW_ALLWINDOWS); + lab->lab_rect = r; + DBFontLabelSetBBox(lab); + DBUndoPutLabel(def, lab); + DBWLabelChanged(def, lab, DBW_ALLWINDOWS); + modified = TRUE; + adjusted = TRUE; + } } } diff --git a/database/database.h.in b/database/database.h.in index d1e7385b..3f184c10 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -578,6 +578,20 @@ typedef struct extRectList struct extRectList *r_next; } ExtRectList; +/* Structure similar to the above, but adding a pointer to a cell use ID + * and a client data record which can be used to hold a region pointer. + */ + +typedef struct extConnList +{ + char *r_useid; /* Cell Use being connected to */ + TileType r_type; /* Connecting tile type in the parent */ + Rect r_r; /* Area of connection */ + ClientData r_upnode; /* Parent node making the connection */ + ClientData r_downnode; /* Child node making the connection */ + struct extConnList *r_next; /* Next item in the linked list */ +} ExtConnList; + /* -------------------- Search context information -------------------- */ /* Search contexts are used in hierarchical searches */ 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. -
where option may be one of the following:-
@@ -79,9 +102,9 @@ information.- tolerance value -
- Set the ratio between resistor and transistor tolerance - for determining when to insert resistance into a network route.
- all
- Extract all the nets. +
- threshold [value] +
- With no value given, returns the current lumped resistance + threshold used to determine if a network will or will not be + analyzed for resistance extraction, in milliohms. The default + threshold value is 10000 milliohms (10 ohms). If + value is given, then set the lumped resistance threshold + to value milliohms. +
- mindelay [value] +
- 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 1ps. If value is given, + then set the delay threshold to value picoseconds. +
- minres [value] +
- With no value given, returns the current absolute resistance + threshold used to prune small resistances from a network when + simplifying, in milliohms. The default minres value + is 1000 milliohms (1 ohm). If value is given, then set + the absolute resistance threshold to value milliohms. + Note that resistances smaller than value may still + appear in the output netlist if the algorithm is unable to + simplify the network around the resistor.
- simplify [on|off]
- Turn on/off simplification of resistor nets.
- extout [on|off] @@ -42,7 +61,9 @@ information.
- lumped [on|off]
- Turn on/off writing of updated lumped resistances.
- silent [on|off] -
- Turn off/on printing of net statistics. +
- Turn off/on printing of nets being processed. +
- debug [on|off] +
- Turn off/on additional diagnostic information.
- skip mask
- Don't extract types indicated in the comma-separated list mask
- ignore [netname|none] @@ -69,6 +90,8 @@ information. .fh file. If freq is specified, the file will be customized for fasthenry analysis at the indicated frequency (in Hz). +
- tolerance value +
- Deprecated! This option is no longer used by extresist.
- help
- Print help information
The normal flow through layout extraction into a simulation file treats routes as nonphysical entities, that is, with infinitesimal - impedence through the wires. Extraction for digital simulation - using irsim generates "lumped resistances", a single - resistance per network node that, along with the node capacitance + impedence through the wires. Standard extraction generates "lumped + resistance" values, a single resistance per network node that, along + with the node capacitance to substrate, provides an RC time constant to approximately model the delay from point to point in the network node. The lumped resistance model is inappropriate for analog (i.e., SPICE) @@ -96,10 +119,9 @@ information. Using extresist as a standalone command is a multi-step process. It is first necessary to run extract to get - the initial netlist. - After a .ext file has been generated, the - extresist command may be run. The output is - a file .res.ext for each cell in the hierarchy. + the initial netlist. After a .ext file has been generated, + the extresist command may be run. The output is a file + .res.ext for each cell in the hierarchy. Finally, with the option extresist on set, ext2spice will generate the final, detailed simulation file.@@ -110,7 +132,42 @@ information. magic version 8.3.597 an option extract do resistance that runs the resistance extraction in sequence with the regular extraction, producing both the .ext and .res.ext - files. + files. When extract do resistance is used, there is no need + to run extresist as a separate command. However, + extresist may be run prior to extract to set the + options that affect resistance network extraction, such as + extresist threshold, extresist minres, etc.
+ + As of magic version 8.3.653, the extresist tolerance option + is deprecated and has no effect on network resistance extraction. + Instead, extraction is controlled by three main options:
+ + extresist threshold (value in milliohms) sets a cutoff for + considering a network for detailed resistance extraction based on + the lumped resistance estimate (see above). For point-to-point + wires, the lumped resistance is approximately equal to the actual + wire resistance. For branching networks, it will generally be an + over-estimate. The default threshold value is set to + 10 ohms.
+ + extresist minres (value in milliohms) sets a cutoff for + individual resistors in the detailed resistor network. Resistors + below this threshold will get pruned out of the network if the + simplification algorithm is able to remove them. The default + minres value is set to 1 ohm.
+ + extresist mindelay (value in picoseconds) sets a cutoff for + considering a network for detailed resistance extraction based on + the end-to-end delay calculated from the lumped resistance + estimate. Once the network has been extracted, the mindelay + value is again evaluated against a revised calculation of the + delay to determine if the extracted detailed network should be + output. The default mindelay value is set to 0, indicating + that only the lumped resistance threshold should be used for + determining when to extract a detailed resistance network. + mindelay may be used in place of threshold, or both + may be used together, in which case a network is only extracted + if both threshold and mindelay are exceeded.
More details on using extresist can be found in magic Tutorial number 8. @@ -134,6 +191,6 @@ information.
Return to command index - Last updated: October 4, 2021 at 3:32pm
+
Last updated: May 29, 2026 at 11:33am