From a4c5945d608b317b3ed63a300c011131e49772bc Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 31 Mar 2022 20:02:12 -0400 Subject: [PATCH] Corrected parsing of NONDEFAULTRULES in a LEF file. Modified the DEF reading to use vector fonts on PIN labels, with some ad hoc rules for size and rotation (may need refinement). Modified the DEF annotation (def read -annotate) so that the preferred position of labels is on a wire leading out from a pin connection, which is a "safer" place to put it, in case the layout was manually edited between the DEF read and annotation. Fixed another two crash conditions related to read-only views. Corrected a startup error caused by an uninitialized variable used by the "wiring" section of the tech file. --- lef/defRead.c | 148 +++++++++++++++++++++++++++++++++++++++++++--- lef/lefRead.c | 5 +- select/selOps.c | 12 ++++ wiring/wireTech.c | 2 +- 4 files changed, 157 insertions(+), 10 deletions(-) diff --git a/lef/defRead.c b/lef/defRead.c index b0b97c2f..9ec6a150 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -937,6 +937,40 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total) "the number declared (%d).\n", processed, total); } +/* + *------------------------------------------------------------ + * + * defFoundOneFunc -- + * + * Simple callback function for DefReadNets() when using + * the "def read -annoatate" option. Attempts to find + * paint in the top level in the area of a pin that is + * part of the net. + * + * Note: The routine does not search on connected tiles + * and so could miss the connecting material, although + * there are multiple fall-back chances to succeed. + * + * Returns: + * 1 to stop the search, as we just take the first tile + * found and run with it. + * + * Side effects: + * Copies a pointer to the tile found into the client + * data record. + * + *------------------------------------------------------------ + */ + +int +defFoundOneFunc(tile, tret) + Tile *tile; + Tile **tret; +{ + *tret = tile; + return 1; +} + /* *------------------------------------------------------------ * @@ -976,12 +1010,13 @@ DefReadNets(f, rootDef, sname, oscale, special, dolabels, annotate, total) int total; { char *token; - char *netname = NULL; + char *netname = NULL, *prnet; int keyword, subkey; int processed = 0; LefMapping *defLayerMap; LefRules *ruleset = NULL; HashEntry *he; + bool needanno; static char *net_keys[] = { "-", @@ -1031,6 +1066,7 @@ DefReadNets(f, rootDef, sname, oscale, special, dolabels, annotate, total) /* Get net name */ token = LefNextToken(f, TRUE); if (dolabels) netname = StrDup((char **)NULL, token); + needanno = annotate; /* Update the record of the number of nets processed */ /* and spit out a message for every 5% finished. */ @@ -1041,6 +1077,62 @@ DefReadNets(f, rootDef, sname, oscale, special, dolabels, annotate, total) /* Process all properties */ while (token && (*token != ';')) { + if (needanno) + { + char *compname, *termname; + + /* Annotation only---when back-annotating */ + /* labels into a layout, the safest place to */ + /* put labels is on a terminal position */ + + if (*token == '(') + { + token = LefNextToken(f, TRUE); + if (!strcmp(token, "PIN")) + needanno = FALSE; + else + { + Rect r; + bool isvalid; + TileType ttype; + Tile *tp; + + compname = StrDup((char **)NULL, token); + token = LefNextToken(f, TRUE); + termname = (char *)mallocMagic(strlen(compname) + + strlen(token) + 3); + sprintf(termname, "%s/%s", compname, token); + ttype = CmdFindNetProc(termname, EditCellUse, &r, + FALSE, &isvalid); + if (isvalid) + { + /* The pin was found. However, there may not be + * paint on the top level over the whole pin. + * Search the area (+1) for attached paint, then + * label inside that tile. + */ + tp = NULL; + DBSrPaintArea((Tile *)NULL, + rootDef->cd_planes[DBPlane(ttype)], + &r, &DBConnectTbl[ttype], + defFoundOneFunc, (ClientData)&tp); + + if (tp != NULL) + { + TiToRect(tp, &r); + r.r_xbot = r.r_xtop = (r.r_xbot + r.r_xtop) / 2; + r.r_ybot = r.r_ytop = (r.r_ybot + r.r_ytop) / 2; + DBPutLabel(rootDef, &r, GEO_CENTER, netname, + ttype, 0, 0); + needanno = FALSE; + } + } + freeMagic(termname); + freeMagic(compname); + } + } + } + /* All connections are ignored, and we go */ /* go directly to the first property ("+") key */ @@ -1065,8 +1157,11 @@ DefReadNets(f, rootDef, sname, oscale, special, dolabels, annotate, total) case DEF_NETPROP_FIXED: case DEF_NETPROP_COVER: case DEF_NETPROP_NOSHIELD: + prnet = NULL; + if (dolabels && (needanno || (!annotate))) + prnet = netname; token = DefAddRoutes(rootDef, f, oscale, special, - netname, ruleset, defLayerMap, annotate); + prnet, ruleset, defLayerMap, annotate); ruleset = NULL; break; @@ -1309,6 +1404,7 @@ DefReadPins(f, rootDef, sname, oscale, total) int pinDir = PORT_CLASS_DEFAULT; int pinUse = PORT_USE_DEFAULT; int pinNum = 0; + int width, height, rot, size; TileType curlayer = -1; LinkedRect *rectList = NULL, *newRect; Rect *currect, topRect; @@ -1495,9 +1591,27 @@ DefReadPins(f, rootDef, sname, oscale, total) { GeoTransRect(&t, &rectList->r_r, &topRect); DBPaint(rootDef, &topRect, rectList->r_type); - DBPutLabel(rootDef, &topRect, -1, pinname, - rectList->r_type, - pinDir | pinUse | flags, pinNum); + // DBPutLabel(rootDef, &topRect, -1, pinname, + // rectList->r_type, + // pinDir | pinUse | flags, pinNum); + width = (topRect.r_xtop - topRect.r_xbot); + height = (topRect.r_ytop - topRect.r_ybot); + rot = 0; + if (height > (width * 2)) + { + int temp = height; + height = width; + width = temp; + rot = 90; + } + size = DRCGetDefaultLayerWidth(rectList->r_type); + while ((size << 1) < height) size <<= 1; + size <<= 3; /* Fonts are in 8x units */ + DBPutFontLabel(rootDef, &topRect, + 0, size, rot, &GeoOrigin, + GEO_CENTER, pinname, + rectList->r_type, + pinDir | pinUse | flags, pinNum); freeMagic(rectList); rectList = rectList->r_next; } @@ -1524,9 +1638,27 @@ DefReadPins(f, rootDef, sname, oscale, total) { GeoTransRect(&t, &rectList->r_r, &topRect); DBPaint(rootDef, &topRect, rectList->r_type); - DBPutLabel(rootDef, &topRect, -1, pinname, - rectList->r_type, - pinDir | pinUse | flags, pinNum); + // DBPutLabel(rootDef, &topRect, -1, pinname, + // rectList->r_type, + // pinDir | pinUse | flags, pinNum); + width = (topRect.r_xtop - topRect.r_xbot); + height = (topRect.r_ytop - topRect.r_ybot); + rot = 0; + if (height > (width * 2)) + { + int temp = height; + height = width; + width = temp; + rot = 90; + } + size = DRCGetDefaultLayerWidth(rectList->r_type); + while ((size << 1) < height) size <<= 1; + size <<= 3; /* Fonts are in 8x units */ + DBPutFontLabel(rootDef, &topRect, + 0, size, rot, &GeoOrigin, + GEO_CENTER, pinname, + rectList->r_type, + pinDir | pinUse | flags, pinNum); freeMagic(rectList); rectList = rectList->r_next; } diff --git a/lef/lefRead.c b/lef/lefRead.c index 0ef420c4..ca50d783 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -1868,7 +1868,8 @@ newrule: LefError(LEF_INFO, "No layer for non-default width.\n"); else rule->width = (int)roundf(fvalue / oscale); - break; + LefEndStatement(f); + break; case LEF_NONDEFLAYER_SPACE: if (!inlayer) LefError(DEF_INFO, "SPACING specified without layer.\n"); @@ -1880,6 +1881,7 @@ newrule: LefError(LEF_INFO, "No layer for non-default spacing.\n"); else rule->spacing = (int)roundf(fvalue / oscale); + LefEndStatement(f); break; case LEF_NONDEFLAYER_DIAG: case LEF_NONDEFLAYER_EXT: @@ -1888,6 +1890,7 @@ newrule: "Layer value specified without layer.\n"); /* Absorb token and ignore */ token = LefNextToken(f, TRUE); + LefEndStatement(f); break; } diff --git a/select/selOps.c b/select/selOps.c index 824899bc..cb2034f7 100644 --- a/select/selOps.c +++ b/select/selOps.c @@ -228,6 +228,12 @@ SelectCopy(transform) { SearchContext scx; + if (EditCellUse == NULL) + { + TxError("The current cell is not editable.\n"); + return; + } + /* Copy from SelectDef to Select2Def while transforming, then * let SelectAndCopy2 do the rest of the work. Don't record * anything involving Select2Def for undo-ing. @@ -1439,6 +1445,12 @@ SelectStretch(x, y) if ((x == 0) && (y == 0)) return; + if (EditCellUse == NULL) + { + TxError("The current cell is not editable.\n"); + return; + } + /* First of all, copy from SelectDef to Select2Def, moving the * selection along the way. */ diff --git a/wiring/wireTech.c b/wiring/wireTech.c index b1555a2b..1b4b9e15 100644 --- a/wiring/wireTech.c +++ b/wiring/wireTech.c @@ -36,7 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$"; #include "utils/malloc.h" /* Linked list to store contact information collected by this module: */ -Contact *WireContacts; +Contact *WireContacts = NULL; int WireUnits; // Units per lambda for wiring sizes