From 7a8e6352a31942eef3ea9eef2a90dafb44155fd7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 15 Jul 2020 17:29:56 -0400 Subject: [PATCH] Two changes to "lef write": (1) Added support for generating output for geometry on MASTERSLICE layers (which was inadvertantly broken), and (2) Added option "lef write -toplayer", which outputs pin geometry only for the topmost layer belonging to a pin, with connected layers underneath being designated as obstructions. --- VERSION | 2 +- lef/defWrite.c | 10 ++++---- lef/lefCmd.c | 18 +++++++++++++-- lef/lefWrite.c | 63 ++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/VERSION b/VERSION index e3f7510e..2c358a89 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.32 +8.3.33 diff --git a/lef/defWrite.c b/lef/defWrite.c index 4d2c9a26..a3702703 100644 --- a/lef/defWrite.c +++ b/lef/defWrite.c @@ -902,7 +902,7 @@ defNetGeometryFunc(tile, plane, defdata) /* Layer names are taken from the LEF database. */ lefName = MagicToLefTable[ttype].lefName; - ASSERT(lefName, "Valid ttype"); + if (lefName == NULL) return 0; /* Do not write types not in LEF definition */ lefType = MagicToLefTable[ttype].lefInfo; orient = GEO_EAST; @@ -1393,6 +1393,7 @@ defCountViaFunc(tile, cviadata) /* Generate a via name from the layer name and tile size */ lname = MagicToLefTable[ctype].lefName; + if (lname == NULL) return 0; /* Do not output undefined LEF layers */ TiToRect(tile, &r); /* Boundary search. WARNING: This code is quite naive. The */ @@ -1551,7 +1552,8 @@ defGetType(ttype, lefptr) while (he = HashNext(&LefInfo, &hs)) { lefl = (lefLayer *)HashGetValue(he); - if (lefl && (contact == lefl->lefClass)) + if (lefl && ((contact == lefl->lefClass) || + ((contact == CLASS_ROUTE) && (lefl->lefClass == CLASS_MASTER)))) if ((lefl->type == ttype) || (lefl->obsType == ttype)) { if (lefptr) *lefptr = lefl; @@ -1560,9 +1562,9 @@ defGetType(ttype, lefptr) } } - /* If we got here, there is no entry; use the database name */ + /* If we got here, there is no entry; return NULL. */ if (lefptr) *lefptr = (lefLayer *)NULL; - return DBTypeLongNameTbl[ttype]; + return NULL; } /* diff --git a/lef/lefCmd.c b/lef/lefCmd.c index b1336bc5..f4c9bd83 100644 --- a/lef/lefCmd.c +++ b/lef/lefCmd.c @@ -87,6 +87,10 @@ CmdLef(w, cmd) * the macro other than pin area * immediately surrounding labels. */ + bool lefTopLayer = False; /* If TRUE, only output the topmost + * layer used by a pin, and make + * all layers below it obstructions. + */ bool recurse = FALSE; /* If TRUE, recurse on all subcells * during "writeall". By default, * only the immediate children of the @@ -208,13 +212,16 @@ CmdLef(w, cmd) lefTech = TRUE; else if (!strncmp(cmd->tx_argv[i], "-hide", 5)) lefHide = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-toplayer", 9)) + lefTopLayer = TRUE; else if (!strncmp(cmd->tx_argv[i], "-all", 4)) recurse = TRUE; else goto wrongNumArgs; } else goto wrongNumArgs; } - LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, recurse); + LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, lefTopLayer, + recurse); } break; case LEF_WRITE: @@ -245,6 +252,13 @@ CmdLef(w, cmd) else TxPrintf("The \"-hide\" option is only for lef write\n"); } + else if (!strncmp(cmd->tx_argv[i], "-toplayer", 9)) + { + if (is_lef) + lefTopLayer = TRUE; + else + TxPrintf("The \"-toplayer\" option is only for lef write\n"); + } else if (!strncmp(cmd->tx_argv[i], "-units", 5)) { if (is_lef) @@ -284,7 +298,7 @@ CmdLef(w, cmd) DefWriteCell(selectedUse->cu_def, namep, allSpecial, units); else LefWriteCell(selectedUse->cu_def, namep, selectedUse->cu_def - == EditRootDef, lefTech, lefHide); + == EditRootDef, lefTech, lefHide, lefTopLayer); break; case LEF_HELP: wrongNumArgs: diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 63124498..848f7ab6 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -503,7 +503,12 @@ lefEraseGeometry(tile, cdata) ttype = otype; /* Erase the tile area out of lefFlat */ - DBErase(flatDef, &area, ttype); + /* Use DBNMPaintPlane, NOT DBErase(). This erases contacts one */ + /* plane at a time, which normally is bad, but since every plane */ + /* gets erased eventually during "lef write", this is okay. */ + /* DBErase(flatDef, &area, ttype); */ + DBNMPaintPlane(flatDef->cd_planes[lefdata->pNum], otype, &area, + DBStdEraseTbl(ttype, lefdata->pNum), NULL); return 0; } @@ -563,6 +568,25 @@ lefAccumulateArea(tile, cdata) return 0; } +/* + * ---------------------------------------------------------------------------- + * + * lefFindTopmost -- + * + * Function called to find the topmost layer used by a pin network + * + * Return 0 to keep the search going. + * ---------------------------------------------------------------------------- + */ + +int +lefFindTopmost(tile, cdata) + Tile *tile; + ClientData cdata; +{ + return 1; /* Stop processing on the first tile found */ +} + /* * ---------------------------------------------------------------------------- * @@ -630,7 +654,7 @@ lefYankGeometry(tile, cdata) while (ttype < DBNumUserLayers) { lefMagicToLefLayer = lefdata->lefMagicMap; - if (lefMagicToLefLayer[ttype].lefInfo != NULL) + if (lefMagicToLefLayer[ttype].lefName != NULL) { if (IsSplit(tile)) // Set only the side being yanked @@ -793,7 +817,7 @@ lefWriteGeometry(tile, cdata) lefdata->numWrites++; if (ttype != lefdata->lastType) - if (lefMagicToLefLayer[ttype].lefInfo != NULL) + if (lefMagicToLefLayer[ttype].lefName != NULL) { fprintf(f, IN2 "LAYER %s ;\n", lefMagicToLefLayer[ttype].lefName); @@ -1064,11 +1088,12 @@ LefWritePinHeader(f, lab) */ void -lefWriteMacro(def, f, scale, hide) +lefWriteMacro(def, f, scale, hide, toplayer) CellDef *def; /* Def for which to generate LEF output */ FILE *f; /* Output to this file */ float scale; /* Output distance units conversion factor */ bool hide; /* If TRUE, hide all detail except pins */ + bool toplayer; /* If TRUE, only output topmost layer of pins */ { bool propfound, ispwrrail; char *propvalue, *class = NULL; @@ -1080,7 +1105,7 @@ lefWriteMacro(def, f, scale, hide) TileTypeBitMask lmask, boundmask, *lrmask, gatetypemask, difftypemask; TileType ttype; lefClient lc; - int idx, pNum, maxport, curport; + int idx, pNum, pTop, maxport, curport; char leffmt[2][10]; char *LEFtext; HashSearch hs; @@ -1410,6 +1435,17 @@ lefWriteMacro(def, f, scale, hide) if (antdiffarea > 0) break; } + if (toplayer) + { + for (pTop = DBNumPlanes - 1; pTop >= PL_TECHDEPBASE; pTop--) + { + if (DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pTop], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, + lefFindTopmost, (ClientData)NULL) == 1) + break; + } + } + // For all geometry in the selection, write LEF records, // and mark the corresponding tiles in lefFlatDef as // visited. @@ -1418,6 +1454,11 @@ lefWriteMacro(def, f, scale, hide) lc.lastType = TT_SPACE; for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { + /* Option to output only the topmost layer of a network */ + /* as PIN geometry. All layers below it are considered */ + /* obstructions. */ + if (toplayer) pNum = pTop; + lc.pNum = pNum; DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum], &TiPlaneRect, &DBAllButSpaceAndDRCBits, @@ -1458,6 +1499,8 @@ lefWriteMacro(def, f, scale, hide) &TiPlaneRect, &lc.rmask, lefWriteGeometry, (ClientData) &lc); lc.lefMode = LEF_MODE_PORT; + + if (toplayer) break; /* Stop after processing topmost layer */ } DBCellClearDef(lc.lefYank); lab->lab_flags |= PORT_VISITED; @@ -1777,11 +1820,12 @@ lefGetProperties(stackItem, i, clientData) */ void -LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse) +LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, lefTopLayer, recurse) CellUse *rootUse; bool writeTopCell; bool lefTech; bool lefHide; + bool lefTopLayer; bool recurse; { HashTable propHashTbl, siteHashTbl; @@ -1847,7 +1891,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse) { def->cd_client = (ClientData) 0; if (!SigInterruptPending) - lefWriteMacro(def, f, scale, lefHide); + lefWriteMacro(def, f, scale, lefHide, lefTopLayer); } /* End the LEF file */ @@ -1911,12 +1955,13 @@ lefDefPushFunc(use, recurse) */ void -LefWriteCell(def, outName, isRoot, lefTech, lefHide) +LefWriteCell(def, outName, isRoot, lefTech, lefHide, lefTopLayer) CellDef *def; /* Cell being written */ char *outName; /* Name of output file, or NULL. */ bool isRoot; /* Is this the root cell? */ bool lefTech; /* Output layer information if TRUE */ bool lefHide; /* Hide detail other than pins if TRUE */ + bool lefTopLayer; /* Use only topmost layer of pin if TRUE */ { char *filename; FILE *f; @@ -1950,7 +1995,7 @@ LefWriteCell(def, outName, isRoot, lefTech, lefHide) HashKill(&propHashTbl); HashKill(&siteHashTbl); } - lefWriteMacro(def, f, scale, lefHide); + lefWriteMacro(def, f, scale, lefHide, lefTopLayer); fclose(f); }