Merge branch 'work' into tomerge
This commit is contained in:
commit
5e28e84336
|
|
@ -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