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:
parent
f756825828
commit
17227ee427
|
|
@ -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))
|
||||
|
|
|
|||
24
lef/lefCmd.c
24
lef/lefCmd.c
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue