diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index 4bd57ecc..e782005d 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -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)) diff --git a/lef/lefCmd.c b/lef/lefCmd.c index f280562f..eea65a2b 100644 --- a/lef/lefCmd.c +++ b/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: diff --git a/lef/lefWrite.c b/lef/lefWrite.c index b6453d45..881c2b32 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -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); }