diff --git a/VERSION b/VERSION index 238919a9..9a2a4cfa 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.217 +8.3.218 diff --git a/commands/CmdRS.c b/commands/CmdRS.c index 86fc0760..95c7a05e 100644 --- a/commands/CmdRS.c +++ b/commands/CmdRS.c @@ -570,10 +570,11 @@ CmdSee(w, cmd) /* ARGSUSED */ void -cmdSelectArea(layers, less, option) +cmdSelectArea(layers, less, option, globmatch) char *layers; /* Which layers are to be selected. */ bool less; int option; /* Option from defined list above */ + char *globmatch; /* Optional match string for labels */ { SearchContext scx; TileTypeBitMask mask; @@ -617,7 +618,7 @@ cmdSelectArea(layers, less, option) if (less) { - (void) SelRemoveArea(&scx.scx_area, &mask); + (void) SelRemoveArea(&scx.scx_area, &mask, globmatch); return; } @@ -633,7 +634,7 @@ cmdSelectArea(layers, less, option) TTMaskClearType(&mask, i); } } - SelectArea(&scx, &mask, crec->dbw_bitmask); + SelectArea(&scx, &mask, crec->dbw_bitmask, globmatch); } /* @@ -831,7 +832,7 @@ CmdSelect(w, cmd) * also used to step through multiple uses. */ static bool lessCycle = FALSE, lessCellCycle = FALSE; - char path[200], *printPath, **msg, **optionArgs, *feedtext, *pstr; + char path[200], *printPath, **msg, **optionArgs, *feedtext, *pstr, *globmatch; TerminalPath tpath; CellUse *use; CellDef *rootBoxDef; @@ -854,6 +855,7 @@ CmdSelect(w, cmd) #define MARGIN 2 + globmatch = NULL; bzero(&scx, sizeof(SearchContext)); windCheckOnlyWindow(&w, DBWclientID); if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID)) @@ -977,17 +979,19 @@ CmdSelect(w, cmd) */ case SEL_AREA: - if (cmd->tx_argc > 3) + if (cmd->tx_argc > 4) { usageError: TxError("Bad arguments:\n select %s\n", cmdSelectMsg[option+1]); return; } + if (cmd->tx_argc == 4) + globmatch = optionArgs[2]; /* Label matching by glob */ if (!(more || less)) SelectClear(); - if (cmd->tx_argc == 3) - cmdSelectArea(optionArgs[1], less, option); - else cmdSelectArea("*,label,subcell", less); + if (cmd->tx_argc >= 3) + cmdSelectArea(optionArgs[1], less, option, globmatch); + else cmdSelectArea("*,label,subcell", less, option, globmatch); return; /*-------------------------------------------------------------------- @@ -1000,8 +1004,8 @@ CmdSelect(w, cmd) if (cmd->tx_argc > 3) goto usageError; if (!(more || less)) SelectClear(); if (cmd->tx_argc == 3) - cmdSelectArea(optionArgs[1], less, option); - else cmdSelectArea("*,label,subcell", less, option); + cmdSelectArea(optionArgs[1], less, option, globmatch); + else cmdSelectArea("*,label,subcell", less, option, globmatch); return; /*-------------------------------------------------------------------- diff --git a/database/DBcellcopy.c b/database/DBcellcopy.c index 4b6793d7..9b5d8419 100644 --- a/database/DBcellcopy.c +++ b/database/DBcellcopy.c @@ -27,6 +27,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "utils/malloc.h" #include "tiles/tile.h" #include "utils/hash.h" +#include "utils/utils.h" #include "database/database.h" #include "database/databaseInt.h" #include "textio/textio.h" @@ -83,6 +84,9 @@ struct copyLabelArg * to be filled in with total area of * all labels copied. */ + char *cla_glob; /* If non-NULL, used for glob-style + * matching of labels during copy. + */ }; /* @@ -595,6 +599,7 @@ DBCellCopyAllLabels(scx, mask, xMask, targetUse, pArea) arg.cla_targetUse = targetUse; arg.cla_bbox = pArea; + arg.cla_glob = NULL; if (pArea != NULL) { pArea->r_xbot = 0; @@ -619,6 +624,9 @@ dbCopyAllLabels(scx, lab, tpath, arg) CellDef *def; def = arg->cla_targetUse->cu_def; + if (arg->cla_glob != NULL) + if (!Match(arg->cla_glob, lab->lab_text)) + return 0; if (!GEO_LABEL_IN_AREA(&lab->lab_rect, &(scx->scx_area))) return 0; GeoTransRect(&scx->scx_trans, &lab->lab_rect, &labTargetRect); targetPos = GeoTransPos(&scx->scx_trans, lab->lab_just); @@ -648,6 +656,66 @@ dbCopyAllLabels(scx, lab, tpath, arg) return 0; } +/* + *----------------------------------------------------------------------------- + * + * DBCellCopyGlobLabels -- + * + * Copy labels from the tree rooted at scx->scx_use to targetUse, + * transforming according to the transform in scx. Only labels + * attached to layers of the types specified by mask and which + * match the string "globmatch" by glob-style matching are copied. + * The area to be copied is determined by GEO_LABEL_IN_AREA. + * + * Results: + * None. + * + * Side effects: + * Copies labels to targetUse, clipping against scx->scx_area. + * If pArea is given, store in it the bounding box of all the + * labels copied. + * + *----------------------------------------------------------------------------- + */ + +void +DBCellCopyGlobLabels(scx, mask, xMask, targetUse, pArea, globmatch) + SearchContext *scx; /* Describes root cell to search, area to + * copy, transform from root cell to coords + * of targetUse. + */ + TileTypeBitMask *mask; /* Only labels of these types are copied */ + int xMask; /* Expansion state mask to be used in search */ + CellUse *targetUse; /* Cell into which labels are to be stuffed */ + Rect *pArea; /* If non-NULL, points to a box that will be + * filled in with bbox (in targetUse coords) + * of all labels copied. Will be degenerate + * if nothing was copied. + */ + char *globmatch; /* If non-NULL, only labels matching this + * string by glob-style matching are copied. + */ +{ + int dbCopyAllLabels(); + struct copyLabelArg arg; + + /* DBTeeSrLabels finds all the labels that we want plus some more. + * We'll filter out the ones that we don't need. + */ + + arg.cla_targetUse = targetUse; + arg.cla_bbox = pArea; + arg.cla_glob = globmatch; + if (pArea != NULL) + { + pArea->r_xbot = 0; + pArea->r_xtop = -1; + } + (void) DBTreeSrLabels(scx, mask, xMask, (TerminalPath *) 0, + TF_LABEL_ATTACH, dbCopyAllLabels, + (ClientData) &arg); +} + /* *----------------------------------------------------------------------------- * diff --git a/database/DBlabel.c b/database/DBlabel.c index 7786a3fa..5dde37b8 100644 --- a/database/DBlabel.c +++ b/database/DBlabel.c @@ -228,7 +228,7 @@ DBPutFontLabel(cellDef, rect, font, size, rot, offset, align, text, type, flags) /* * ---------------------------------------------------------------------------- * - * DBEraseLabel -- + * DBEraseGlobLabel -- * * Delete labels attached to tiles of the indicated types that * are in the given area (as determined by the macro GEO_LABEL_IN_AREA). @@ -250,13 +250,13 @@ DBPutFontLabel(cellDef, rect, font, size, rot, offset, align, text, type, flags) * still enough material to keep them around. The rect pointed to * by areaReturn is filled with the area affected by removing the * label, for purposes of redrawing the necessary portions of the -* screen. + * screen. * * ---------------------------------------------------------------------------- */ bool -DBEraseLabel(cellDef, area, mask, areaReturn) +DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch) CellDef *cellDef; /* Cell being modified */ Rect *area; /* Area from which labels are to be erased. * This may be a point; any labels touching @@ -266,6 +266,9 @@ DBEraseLabel(cellDef, area, mask, areaReturn) * be erased. */ Rect *areaReturn; /* Expand this with label bounding box */ + char *globmatch; /* If non-NULL, do glob-style matching of + * any label against this string. + */ { Label *lab, *labPrev; bool erasedAny = FALSE; @@ -289,6 +292,10 @@ DBEraseLabel(cellDef, area, mask, areaReturn) if (DBConnectsTo(newType, lab->lab_type)) goto nextLab; } } + if (globmatch != NULL) + { + if (!Match(globmatch, lab->lab_text)) goto nextLab; + } DBWLabelChanged(cellDef, lab, DBW_ALLWINDOWS); if (labPrev == NULL) @@ -319,6 +326,39 @@ DBEraseLabel(cellDef, area, mask, areaReturn) && (r1)->r_xtop == (r2)->r_xtop \ && (r1)->r_ytop == (r2)->r_ytop) +/* + * ---------------------------------------------------------------------------- + * + * DBEraseLabel --- + * + * Wrapper around DBEraseGlobLabel() with globmatch set to NULL so + * that labels are erased verbatim rather that being matched against + * a glob-style string. + * + * Results: + * Passes back the result of DBEraseGlobLabel() + * + * Side effects: + * See DBEraseGlobLabel() + * + * ---------------------------------------------------------------------------- + */ + +bool +DBEraseLabel(cellDef, area, mask, areaReturn) + CellDef *cellDef; /* Cell being modified */ + Rect *area; /* Area from which labels are to be erased. + * This may be a point; any labels touching + * or overlapping it are erased. + */ + TileTypeBitMask *mask; /* Mask of types from which labels are to + * be erased. + */ + Rect *areaReturn; /* Expand this with label bounding box */ +{ + return DBEraseGlobLabel(cellDef, area, mask, areaReturn, NULL); +} + /* * ---------------------------------------------------------------------------- * diff --git a/database/database.h.in b/database/database.h.in index cb74bc7a..c4334e15 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -783,6 +783,7 @@ extern void DBPathSubstitute(); extern Label *DBPutLabel(); extern Label *DBPutFontLabel(); extern void DBFontLabelSetBBox(); +extern bool DBEraseGlobLabel(); extern bool DBEraseLabel(); extern void DBEraseLabelAll(); extern void DBEraseLabelsByContent(); @@ -875,6 +876,7 @@ extern void DBCellCopyAllPaint(); extern void DBCellCheckCopyAllPaint(); extern void DBCellCopyLabels(); extern void DBCellCopyAllLabels(); +extern void DBCellCopyGlobLabels(); extern void DBCellCopyCells(); extern void DBCellCopyAllCells(); extern Plane *DBCellGenerateSubstrate(); diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 68371be4..e23a2d0f 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -1432,7 +1432,7 @@ lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster) { Rect psetback; GEO_EXPAND(&boundary, -pinonly, &psetback); - SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits); + SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits, NULL); } } @@ -1461,14 +1461,14 @@ lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster) SelectNet(&scx, lab->lab_type, 0, NULL, FALSE); GEO_EXPAND(&boundary, -setback, &carea); - SelRemoveArea(&carea, &DBAllButSpaceAndDRCBits); + SelRemoveArea(&carea, &DBAllButSpaceAndDRCBits, NULL); /* Apply any additional setback from the "-pinonly" option */ if (pinonly > setback) { Rect psetback; GEO_EXPAND(&boundary, -pinonly, &psetback); - SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits); + SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits, NULL); } /* Paint over the label area so that labels do not simply */ @@ -1487,7 +1487,7 @@ lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster) { Rect psetback; GEO_EXPAND(&boundary, -pinonly, &psetback); - SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits); + SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits, NULL); /* Paint over the label area so that labels do not simply */ /* disappear by being inside the setback area. */ diff --git a/resis/ResRex.c b/resis/ResRex.c index dd94b190..6ff91e7a 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -106,7 +106,7 @@ ExtResisForDef(celldef, resisdata) RDev *oldRDev; HashSearch hs; HashEntry *entry; - devPtr *tptr,*oldtptr; + devPtr *tptr, *oldtptr; ResSimNode *node; int result, idx; char *devname; @@ -1495,18 +1495,13 @@ ResFixDevName(line, type, device, layoutnode) } } +#if 1 /* *------------------------------------------------------------------------- * - * ResSortByGate -- sorts device pointers whose terminal field is either - * drain or source by gate node number, then by drain (source) number. - * This places devices with identical connections next to one - * another. - * - * Results: none - * - * Side Effects: modifies order of devices + * Deprecated function. Horribly inefficient. See qsort() version below. + * (Not yet implemented; still under test.) * *------------------------------------------------------------------------- */ @@ -1520,6 +1515,8 @@ ResSortByGate(DevpointerList) devPtr *working, *current; devPtr *last = NULL, *gatelist = NULL; + /* Split out GATE entries into separate list (gatelist) */ + working = *DevpointerList; while (working != NULL) { @@ -1544,6 +1541,9 @@ ResSortByGate(DevpointerList) working = working->nextDev; } } + + /* Sort the SOURCE and DRAIN list (DevpointerList) */ + while (changed == TRUE) { changed = localchange = FALSE; @@ -1599,6 +1599,9 @@ ResSortByGate(DevpointerList) } } } + + /* Add the GATE list back to the end of Devpointerlist */ + if (working == NULL) { *DevpointerList = gatelist; @@ -1612,6 +1615,107 @@ ResSortByGate(DevpointerList) } } +#endif /* 1 */ + +#if 0 + +/* + *------------------------------------------------------------------------- + * + * devSortFunc --- + * + * qsort() sorting function for gates. See description in + * ResSortByGate() below. + * + * Returns: + * 1 or -1 depending on comparison result. The devices are sorted + * by gate first, then source or drain. + * + * Side effects: + * qsort() reorders the indexed list of which dev1 and dev2 are + * components. + * + *------------------------------------------------------------------------- + */ + +int +devSortFunc(dev1, dev2) + devPtr *dev1, *dev2; +{ + RDev *rd1 = dev1->thisDev; + RDev *rd2 = dev2->thisDev; + + if (dev1->terminal == GATE) + return 1; + else if (dev2->terminal == GATE) + return -1; + else if (rd1->gate > rd2->gate) + return 1; + else if (rd1->gate == rd2->gate) + { + if ((dev1->terminal == SOURCE && + dev2->terminal == SOURCE && + rd1->drain > rd2->drain) || + (dev1->terminal == SOURCE && + dev2->terminal == DRAIN && + rd1->drain > rd2->source) || + (dev1->terminal == DRAIN && + dev2->terminal == SOURCE && + rd1->source > rd2->drain) || + (dev1->terminal == DRAIN && + dev2->terminal == DRAIN && + rd1->source > rd2->source)) + { + return 1; + } + } + return -1; +} + +/* + *------------------------------------------------------------------------- + * + * ResSortByGate -- sorts device pointers whose terminal field is either + * drain or source by gate node number, then by drain (source) number. + * This places devices with identical connections next to one + * another. + * + * Results: none + * + * Side Effects: modifies order of devices + * + *------------------------------------------------------------------------- + */ + +void +ResSortByGate(DevpointerList) + devPtr **DevpointerList; +{ + devPtr *working, **Devindexed; + int listlen, listidx; + + /* Linked lists are very slow to sort. Create an indexed list */ + /* and run qsort() to sort, then regenerate the links. */ + + listlen = 0; + for (working = *DevpointerList; working; working = working->nextDev) listlen++; + Devindexed = (devPtr **)mallocMagic(listlen * sizeof(devPtr *)); + listidx = 0; + for (working = *DevpointerList; working; working = working->nextDev) + Devindexed[listidx++] = working; + + qsort(Devindexed, (size_t)listlen, (size_t)sizeof(devPtr *), devSortFunc); + + for (listidx = 0; listidx < listlen - 1; listidx++) + Devindexed[listidx]->nextDev = Devindexed[listidx + 1]; + Devindexed[listidx]->nextDev = NULL; + + *Devpointerlist = Devindexed[0]; + freeMagic(Devindexed); +} + +#endif /* 0 */ + /* *------------------------------------------------------------------------- * diff --git a/select/selCreate.c b/select/selCreate.c index 4a7124a2..dfc5734f 100644 --- a/select/selCreate.c +++ b/select/selCreate.c @@ -413,7 +413,7 @@ SelectIntersect(scx, type, xMask, negate) */ void -SelectArea(scx, types, xMask) +SelectArea(scx, types, xMask, globmatch) SearchContext *scx; /* Describes the area in which material * is to be selected. The resulting * coordinates should map to the coordinates @@ -433,6 +433,10 @@ SelectArea(scx, types, xMask) * considered. 0 means treat everything as * expanded. */ + char *globmatch; /* If non-NULL, and if L_LABELS is among the + * selection types, then do glob-style matching + * of any labels against this string. + */ { Rect labelArea, cellArea; @@ -457,8 +461,13 @@ SelectArea(scx, types, xMask) /* Select labels. */ if (TTMaskHasType(types, L_LABEL)) - (void) DBCellCopyAllLabels(scx, &DBAllTypeBits, xMask, - SelectUse, &labelArea); + { + if (globmatch != NULL) + DBCellCopyGlobLabels(scx, &DBAllTypeBits, xMask, SelectUse, &labelArea, + globmatch); + else + DBCellCopyAllLabels(scx, &DBAllTypeBits, xMask, SelectUse, &labelArea); + } else (void) DBCellCopyAllLabels(scx, types, xMask, SelectUse, &labelArea); /* Select unexpanded cell uses. */ @@ -803,7 +812,7 @@ chunkdone: if (less) { - SelRemoveArea(&bestChunk, &typeMask); + SelRemoveArea(&bestChunk, &typeMask, NULL); } else { @@ -813,7 +822,7 @@ chunkdone: if (DBIsContact(type)) TTMaskSetOnlyType(&typeMask, type); - SelectArea(&newscx, &typeMask, xMask); + SelectArea(&newscx, &typeMask, xMask, NULL); } if (pArea != NULL) *pArea = bestChunk; diff --git a/select/selUnselect.c b/select/selUnselect.c index 40564d91..823b0827 100644 --- a/select/selUnselect.c +++ b/select/selUnselect.c @@ -117,9 +117,10 @@ selRemoveCellFunc(scx, cdarg) */ void -SelRemoveArea(area, mask) - Rect *area; - TileTypeBitMask *mask; +SelRemoveArea(area, mask, globmatch) + Rect *area; + TileTypeBitMask *mask; + char *globmatch; { SearchContext scx; Rect bbox, areaReturn; @@ -134,7 +135,12 @@ SelRemoveArea(area, mask) areaReturn = *area; if (TTMaskHasType(mask, L_LABEL)) - DBEraseLabel(SelectDef, area, &DBAllTypeBits, &areaReturn); + { + if (globmatch != NULL) + DBEraseGlobLabel(SelectDef, area, &DBAllTypeBits, &areaReturn, globmatch); + else + DBEraseLabel(SelectDef, area, &DBAllTypeBits, &areaReturn); + } else DBEraseLabel(SelectDef, area, mask, &areaReturn); diff --git a/wiring/wireOps.c b/wiring/wireOps.c index c44666b1..c551ed19 100644 --- a/wiring/wireOps.c +++ b/wiring/wireOps.c @@ -230,7 +230,7 @@ WirePickType(type, width) SelectClear(); scx.scx_area = box; TTMaskSetOnlyType(&mask, WireType); - SelectArea(&scx, &mask, crec->dbw_bitmask); + SelectArea(&scx, &mask, crec->dbw_bitmask, NULL); DBWSetBox(scx.scx_use->cu_def, &box); TxPrintf("Using %s wires %d units wide.\n", DBTypeLongName(WireType), WireWidth); @@ -989,18 +989,18 @@ WireAddContact(newType, newWidth) GEO_EXPAND(&contactArea, -oldOverlap, &tmp); scx.scx_area = tmp; TTMaskSetOnlyType(&mask, contact->con_type); - SelectArea(&scx, &mask, 0); + SelectArea(&scx, &mask, 0, NULL); if (conSurround1 != 0) { GEO_EXPAND(&tmp, conSurround1, &scx.scx_area); TTMaskSetOnlyType(&mask, contact->con_layer1); - SelectArea(&scx, &mask, 0); + SelectArea(&scx, &mask, 0, NULL); } if (conSurround2 != 0) { GEO_EXPAND(&tmp, conSurround2, &scx.scx_area); TTMaskSetOnlyType(&mask, contact->con_layer2); - SelectArea(&scx, &mask, 0); + SelectArea(&scx, &mask, 0, NULL); } }