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.
This commit is contained in:
Tim Edwards 2020-07-15 17:29:56 -04:00
parent 72b4053774
commit 7a8e6352a3
4 changed files with 77 additions and 16 deletions

View File

@ -1 +1 @@
8.3.32 8.3.33

View File

@ -902,7 +902,7 @@ defNetGeometryFunc(tile, plane, defdata)
/* Layer names are taken from the LEF database. */ /* Layer names are taken from the LEF database. */
lefName = MagicToLefTable[ttype].lefName; 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; lefType = MagicToLefTable[ttype].lefInfo;
orient = GEO_EAST; orient = GEO_EAST;
@ -1393,6 +1393,7 @@ defCountViaFunc(tile, cviadata)
/* Generate a via name from the layer name and tile size */ /* Generate a via name from the layer name and tile size */
lname = MagicToLefTable[ctype].lefName; lname = MagicToLefTable[ctype].lefName;
if (lname == NULL) return 0; /* Do not output undefined LEF layers */
TiToRect(tile, &r); TiToRect(tile, &r);
/* Boundary search. WARNING: This code is quite naive. The */ /* Boundary search. WARNING: This code is quite naive. The */
@ -1551,7 +1552,8 @@ defGetType(ttype, lefptr)
while (he = HashNext(&LefInfo, &hs)) while (he = HashNext(&LefInfo, &hs))
{ {
lefl = (lefLayer *)HashGetValue(he); 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 ((lefl->type == ttype) || (lefl->obsType == ttype))
{ {
if (lefptr) *lefptr = lefl; 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; if (lefptr) *lefptr = (lefLayer *)NULL;
return DBTypeLongNameTbl[ttype]; return NULL;
} }
/* /*

View File

@ -87,6 +87,10 @@ CmdLef(w, cmd)
* the macro other than pin area * the macro other than pin area
* immediately surrounding labels. * 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 bool recurse = FALSE; /* If TRUE, recurse on all subcells
* during "writeall". By default, * during "writeall". By default,
* only the immediate children of the * only the immediate children of the
@ -208,13 +212,16 @@ CmdLef(w, cmd)
lefTech = TRUE; lefTech = TRUE;
else if (!strncmp(cmd->tx_argv[i], "-hide", 5)) else if (!strncmp(cmd->tx_argv[i], "-hide", 5))
lefHide = TRUE; lefHide = TRUE;
else if (!strncmp(cmd->tx_argv[i], "-toplayer", 9))
lefTopLayer = TRUE;
else if (!strncmp(cmd->tx_argv[i], "-all", 4)) else if (!strncmp(cmd->tx_argv[i], "-all", 4))
recurse = TRUE; recurse = TRUE;
else goto wrongNumArgs; else goto wrongNumArgs;
} }
else goto wrongNumArgs; else goto wrongNumArgs;
} }
LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, recurse); LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, lefTopLayer,
recurse);
} }
break; break;
case LEF_WRITE: case LEF_WRITE:
@ -245,6 +252,13 @@ CmdLef(w, cmd)
else else
TxPrintf("The \"-hide\" option is only for lef write\n"); 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)) else if (!strncmp(cmd->tx_argv[i], "-units", 5))
{ {
if (is_lef) if (is_lef)
@ -284,7 +298,7 @@ CmdLef(w, cmd)
DefWriteCell(selectedUse->cu_def, namep, allSpecial, units); DefWriteCell(selectedUse->cu_def, namep, allSpecial, units);
else else
LefWriteCell(selectedUse->cu_def, namep, selectedUse->cu_def LefWriteCell(selectedUse->cu_def, namep, selectedUse->cu_def
== EditRootDef, lefTech, lefHide); == EditRootDef, lefTech, lefHide, lefTopLayer);
break; break;
case LEF_HELP: case LEF_HELP:
wrongNumArgs: wrongNumArgs:

View File

@ -503,7 +503,12 @@ lefEraseGeometry(tile, cdata)
ttype = otype; ttype = otype;
/* Erase the tile area out of lefFlat */ /* 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; return 0;
} }
@ -563,6 +568,25 @@ lefAccumulateArea(tile, cdata)
return 0; 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) while (ttype < DBNumUserLayers)
{ {
lefMagicToLefLayer = lefdata->lefMagicMap; lefMagicToLefLayer = lefdata->lefMagicMap;
if (lefMagicToLefLayer[ttype].lefInfo != NULL) if (lefMagicToLefLayer[ttype].lefName != NULL)
{ {
if (IsSplit(tile)) if (IsSplit(tile))
// Set only the side being yanked // Set only the side being yanked
@ -793,7 +817,7 @@ lefWriteGeometry(tile, cdata)
lefdata->numWrites++; lefdata->numWrites++;
if (ttype != lefdata->lastType) if (ttype != lefdata->lastType)
if (lefMagicToLefLayer[ttype].lefInfo != NULL) if (lefMagicToLefLayer[ttype].lefName != NULL)
{ {
fprintf(f, IN2 "LAYER %s ;\n", fprintf(f, IN2 "LAYER %s ;\n",
lefMagicToLefLayer[ttype].lefName); lefMagicToLefLayer[ttype].lefName);
@ -1064,11 +1088,12 @@ LefWritePinHeader(f, lab)
*/ */
void void
lefWriteMacro(def, f, scale, hide) lefWriteMacro(def, f, scale, hide, toplayer)
CellDef *def; /* Def for which to generate LEF output */ CellDef *def; /* Def for which to generate LEF output */
FILE *f; /* Output to this file */ FILE *f; /* Output to this file */
float scale; /* Output distance units conversion factor */ float scale; /* Output distance units conversion factor */
bool hide; /* If TRUE, hide all detail except pins */ bool hide; /* If TRUE, hide all detail except pins */
bool toplayer; /* If TRUE, only output topmost layer of pins */
{ {
bool propfound, ispwrrail; bool propfound, ispwrrail;
char *propvalue, *class = NULL; char *propvalue, *class = NULL;
@ -1080,7 +1105,7 @@ lefWriteMacro(def, f, scale, hide)
TileTypeBitMask lmask, boundmask, *lrmask, gatetypemask, difftypemask; TileTypeBitMask lmask, boundmask, *lrmask, gatetypemask, difftypemask;
TileType ttype; TileType ttype;
lefClient lc; lefClient lc;
int idx, pNum, maxport, curport; int idx, pNum, pTop, maxport, curport;
char leffmt[2][10]; char leffmt[2][10];
char *LEFtext; char *LEFtext;
HashSearch hs; HashSearch hs;
@ -1410,6 +1435,17 @@ lefWriteMacro(def, f, scale, hide)
if (antdiffarea > 0) break; 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, // For all geometry in the selection, write LEF records,
// and mark the corresponding tiles in lefFlatDef as // and mark the corresponding tiles in lefFlatDef as
// visited. // visited.
@ -1418,6 +1454,11 @@ lefWriteMacro(def, f, scale, hide)
lc.lastType = TT_SPACE; lc.lastType = TT_SPACE;
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) 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; lc.pNum = pNum;
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum], DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
&TiPlaneRect, &DBAllButSpaceAndDRCBits, &TiPlaneRect, &DBAllButSpaceAndDRCBits,
@ -1458,6 +1499,8 @@ lefWriteMacro(def, f, scale, hide)
&TiPlaneRect, &lc.rmask, &TiPlaneRect, &lc.rmask,
lefWriteGeometry, (ClientData) &lc); lefWriteGeometry, (ClientData) &lc);
lc.lefMode = LEF_MODE_PORT; lc.lefMode = LEF_MODE_PORT;
if (toplayer) break; /* Stop after processing topmost layer */
} }
DBCellClearDef(lc.lefYank); DBCellClearDef(lc.lefYank);
lab->lab_flags |= PORT_VISITED; lab->lab_flags |= PORT_VISITED;
@ -1777,11 +1820,12 @@ lefGetProperties(stackItem, i, clientData)
*/ */
void void
LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse) LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, lefTopLayer, recurse)
CellUse *rootUse; CellUse *rootUse;
bool writeTopCell; bool writeTopCell;
bool lefTech; bool lefTech;
bool lefHide; bool lefHide;
bool lefTopLayer;
bool recurse; bool recurse;
{ {
HashTable propHashTbl, siteHashTbl; HashTable propHashTbl, siteHashTbl;
@ -1847,7 +1891,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse)
{ {
def->cd_client = (ClientData) 0; def->cd_client = (ClientData) 0;
if (!SigInterruptPending) if (!SigInterruptPending)
lefWriteMacro(def, f, scale, lefHide); lefWriteMacro(def, f, scale, lefHide, lefTopLayer);
} }
/* End the LEF file */ /* End the LEF file */
@ -1911,12 +1955,13 @@ lefDefPushFunc(use, recurse)
*/ */
void void
LefWriteCell(def, outName, isRoot, lefTech, lefHide) LefWriteCell(def, outName, isRoot, lefTech, lefHide, lefTopLayer)
CellDef *def; /* Cell being written */ CellDef *def; /* Cell being written */
char *outName; /* Name of output file, or NULL. */ char *outName; /* Name of output file, or NULL. */
bool isRoot; /* Is this the root cell? */ bool isRoot; /* Is this the root cell? */
bool lefTech; /* Output layer information if TRUE */ bool lefTech; /* Output layer information if TRUE */
bool lefHide; /* Hide detail other than pins if TRUE */ bool lefHide; /* Hide detail other than pins if TRUE */
bool lefTopLayer; /* Use only topmost layer of pin if TRUE */
{ {
char *filename; char *filename;
FILE *f; FILE *f;
@ -1950,7 +1995,7 @@ LefWriteCell(def, outName, isRoot, lefTech, lefHide)
HashKill(&propHashTbl); HashKill(&propHashTbl);
HashKill(&siteHashTbl); HashKill(&siteHashTbl);
} }
lefWriteMacro(def, f, scale, lefHide); lefWriteMacro(def, f, scale, lefHide, lefTopLayer);
fclose(f); fclose(f);
} }