Added new option "-hide" to the "lef write" command, which causes

the output to have an obstruction area over the entire cell except
for a keep-out area around each pin.  Instead of marking every
part of the pin geometry, only the "chunk" (largest immediate
rectangle) surrounding the port label is output as part of port
LEF geometry.  This avoids making unnecessarily complicated
abstract views, and makes it easier for other tools to read and
manage the same abstract views.
This commit is contained in:
Tim Edwards 2018-11-19 15:01:20 -05:00
parent f756825828
commit 17227ee427
3 changed files with 120 additions and 25 deletions

View File

@ -141,6 +141,7 @@ int calmaPaintLayerType;
* Hash table used to determine which GDS libraries have been output
*/
HashTable calmaLibHash;
HashTable calmaPrefixHash;
/* Imports */
extern time_t time();
@ -292,6 +293,7 @@ CalmaWrite(rootDef, f)
}
HashInit(&calmaLibHash, 32, 0);
HashInit(&calmaPrefixHash, 32, 0);
/*
* Make sure that the entire hierarchy rooted at rootDef is
@ -343,6 +345,7 @@ CalmaWrite(rootDef, f)
if (CalmaContactArrays) calmaDelContacts();
HashFreeKill(&calmaLibHash);
HashKill(&calmaPrefixHash);
return (good);
}
@ -596,7 +599,7 @@ calmaFullDump(def, fi, cellstart, outf, filename)
char *filename;
{
int version, rval, i;
char *libname = NULL, uniqlibname[5];
char *libname = NULL, uniqlibname[3];
char *sptr;
HashTable calmaDefHash;
HashEntry *he;
@ -626,15 +629,32 @@ calmaFullDump(def, fi, cellstart, outf, filename)
// Record the GDS library so it will not be processed again.
he = HashFind(&calmaLibHash, filename);
// Generate a SHORT name for this cell (else it is easy to run into the
// GDS 32-character cellname limit). Save it in the hash record.
for (i = 0; i < 4; i++) {
rval = random() % 62;
rval = (rval < 26) ? ('A' + rval) : ((rval < 52) ? ('a' + rval - 26) :
/* Generate a SHORT name for this cell (else it is easy to run into the
* GDS 32-character cellname limit). Save it in the hash record. The
* chance of generating the same prefix for a library that has items
* with conflicting names is vanishingly small, but to be pedantic, store
* the prefix in a hash table and check to make sure that uniqueness is
* ensured.
*/
while (TRUE)
{
HashEntry *he2;
for (i = 0; i < 2; i++) {
rval = random() % 62;
rval = (rval < 26) ? ('A' + rval) : ((rval < 52) ? ('a' + rval - 26) :
('0' + rval - 52));
uniqlibname[i] = (char)(rval & 127);
uniqlibname[i] = (char)(rval & 127);
}
uniqlibname[2] = '\0';
he2 = HashLookOnly(&calmaPrefixHash, uniqlibname);
if (he2 == NULL)
{
he2 = HashFind(&calmaPrefixHash, uniqlibname);
break;
}
}
uniqlibname[4] = '\0';
HashSetValue(he, StrDup(NULL, uniqlibname));
while (calmaDumpStructure(def, cellstart, outf, &calmaDefHash, filename))

View File

@ -61,7 +61,7 @@ CmdLef(w, cmd)
MagWindow *w;
TxCommand *cmd;
{
int option, i;
int option, i, cargs;
char **msg, *namep;
CellUse *selectedUse;
CellDef *selectedDef;
@ -83,12 +83,17 @@ CmdLef(w, cmd)
* will be output along with the
* lef macro.
*/
bool lefHide = FALSE; /* If TRUE, hide all details of
* the macro other than pin area
* immediately surrounding labels.
*/
static char *cmdLefOption[] =
{
"read [filename] read a LEF file filename[.lef]\n"
" read [filename] -import read a LEF file; import cells from .mag files",
"write [filename] [-tech] write LEF for current cell",
"write [filename] [-tech] write LEF for current cell\n"
" write [filename] -hide hide all details other than ports",
"writeall write all cells including the top-level cell\n"
" writeall -notop write all subcells of the top-level cell",
"help print this help information",
@ -188,6 +193,7 @@ CmdLef(w, cmd)
break;
case LEF_WRITE:
allSpecial = FALSE;
cargs = cmd->tx_argc;
for (i = 2; i < cmd->tx_argc; i++)
{
if (*(cmd->tx_argv[i]) == '-')
@ -206,18 +212,26 @@ CmdLef(w, cmd)
else
TxPrintf("The \"-tech\" option is only for lef write\n");
}
else if (!strncmp(cmd->tx_argv[i], "-hide", 5))
{
if (is_lef)
lefHide = TRUE;
else
TxPrintf("The \"-hide\" option is only for def write\n");
}
else goto wrongNumArgs;
cargs--;
}
else if (i != 2) /* Is argument a filename? */
goto wrongNumArgs;
}
if (cmd->tx_argc != 2 && cmd->tx_argc != 3) goto wrongNumArgs;
if (cargs != 2 && cargs != 3) goto wrongNumArgs;
if (selectedUse == NULL)
{
TxError("No cell selected\n");
return;
}
if (cmd->tx_argc == 2)
if (cargs == 2)
namep = selectedUse->cu_def->cd_name;
else
namep = cmd->tx_argv[2];
@ -225,7 +239,7 @@ CmdLef(w, cmd)
DefWriteCell(selectedUse->cu_def, namep, allSpecial);
else
LefWriteCell(selectedUse->cu_def, namep, selectedUse->cu_def
== EditRootDef, lefTech);
== EditRootDef, lefTech, lefHide);
break;
case LEF_HELP:
wrongNumArgs:

View File

@ -625,10 +625,11 @@ MakeLegalLEFSyntax(text)
*/
void
lefWriteMacro(def, f, scale)
lefWriteMacro(def, f, scale, hide)
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 propfound;
char *propvalue, *class = NULL;
@ -689,6 +690,7 @@ lefWriteMacro(def, f, scale)
TTMaskZero(&lc.rmask);
TTMaskZero(&boundmask);
TTMaskZero(&lmask);
/* Any layer which has a port label attached to it should by */
/* necessity be considered a routing layer. Usually this will not */
@ -711,6 +713,8 @@ lefWriteMacro(def, f, scale)
lrmask = DBResidueMask(lefl->type);
TTMaskSetMask(&lc.rmask, lrmask);
}
if ((lefl->lefClass == CLASS_ROUTE) && (lefl->obsType != -1))
TTMaskSetType(&lmask, lefl->type);
}
if (lefl->obsType != -1)
TTMaskSetType(&lc.rmask, lefl->obsType);
@ -909,16 +913,17 @@ lefWriteMacro(def, f, scale)
labr.r_ybot--;
}
// TTMaskSetOnlyType(&lmask, lab->lab_type);
// Avoid errors caused by labels attached to space or
// various technology file issues.
TTMaskClearType(&lc.rmask, TT_SPACE);
ttype = TT_SPACE;
scx.scx_area = labr;
SelectClear();
SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
if (hide)
SelectChunk(&scx, lab->lab_type, 0, NULL, FALSE);
else
SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
// For all geometry in the selection, write LEF records,
// and mark the corresponding tiles in lefFlatDef as
@ -981,13 +986,68 @@ lefWriteMacro(def, f, scale)
/* Restrict to routing planes only */
if (hide)
{
/* If details of the cell are to be hidden, then first paint */
/* all route layers with an obstruction rectangle the size of */
/* the cell bounding box. Then recompute the label chunk */
/* regions used above to write the ports, expand each chunk by */
/* the route metal spacing width, and erase that area from the */
/* obstruction. */
for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++)
if (TTMaskHasType(&lmask, ttype))
DBPaint(lc.lefYank, &boundary, ttype);
scx.scx_use = &lefSourceUse;
for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
{
Rect carea;
int lspace;
labr = lab->lab_rect;
/* Force label area to be non-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++;
}
if (lab->lab_flags & PORT_DIR_MASK)
{
scx.scx_area = labr;
SelectClear();
SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE);
lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type);
carea.r_xbot -= lspace;
carea.r_ybot -= lspace;
carea.r_xtop += lspace;
carea.r_ytop += lspace;
DBErase(lc.lefYank, &carea, lab->lab_type);
}
}
}
else
{
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
lc.pNum = pNum;
DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
&TiPlaneRect, &DBAllButSpaceAndDRCBits,
lefYankGeometry, (ClientData) &lc);
}
}
/* Write all the geometry just generated */
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
lc.pNum = pNum;
DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
&TiPlaneRect, &DBAllButSpaceAndDRCBits,
lefYankGeometry, (ClientData) &lc);
DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
&TiPlaneRect, &lc.rmask,
lefWriteGeometry, (ClientData) &lc);
@ -1140,11 +1200,12 @@ lefDefPushFunc(use)
*/
void
LefWriteCell(def, outName, isRoot, lefTech)
LefWriteCell(def, outName, isRoot, lefTech, lefHide)
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 */
{
char *filename;
FILE *f;
@ -1168,7 +1229,7 @@ LefWriteCell(def, outName, isRoot, lefTech)
if (isRoot)
lefWriteHeader(def, f, lefTech);
lefWriteMacro(def, f, scale);
lefWriteMacro(def, f, scale, lefHide);
fclose(f);
}