From bf4364da445965851e067e90e3d9bbed7f020b8b Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 16 Jun 2020 22:54:48 -0400 Subject: [PATCH] Corrected an error in the GDS output hierarchical adjustments code caused by the new bloat-all with templayers, which used the distance record in the bloat structure differently than the other bloat functions, and therefore was messing up the enumeration of layers needing to be handled by the hierarchical output. This was probably also wrong for the existing bloat-all function, which might explain some problems recently with the GDS output. --- cif/CIFgen.c | 2 + cif/CIFtech.c | 9 ++++- lef/lefRead.c | 7 +--- lef/lefWrite.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 104 insertions(+), 13 deletions(-) diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 3ef1974c..4e268327 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -4148,6 +4148,7 @@ CIFGenLayer(op, area, cellDef, origDef, temps, clientdata) bbox.r_xtop *= cifScale; bbox.r_ybot *= cifScale; bbox.r_ytop *= cifScale; + cifScale = 1; DBNMPaintPlane(cifPlane, CIF_SOLIDTYPE, &bbox, CIFPaintTable, (PaintUndoInfo *)NULL); } @@ -4183,6 +4184,7 @@ CIFGenLayer(op, area, cellDef, origDef, temps, clientdata) bbox.r_xtop *= cifScale; bbox.r_ybot *= cifScale; bbox.r_ytop *= cifScale; + cifScale = 1; DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox, CIFPaintTable, (PaintUndoInfo *)NULL); break; diff --git a/cif/CIFtech.c b/cif/CIFtech.c index 701dd369..8a55c73d 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -1902,11 +1902,18 @@ CIFTechFinal() case CIFOP_BLOAT: case CIFOP_BLOATMAX: case CIFOP_BLOATMIN: + bloats = (BloatData *)op->co_client; + for (j = 0; j < TT_MAXTYPES; j++) + if (bloats->bl_distance[j] != bloats->bl_distance[TT_SPACE]) + TTMaskSetType(&ourYank, j); + needThisLayer = TRUE; + break; + case CIFOP_BLOATALL: bloats = (BloatData *)op->co_client; for (j = 0; j < TT_MAXTYPES; j++) { - if (bloats->bl_distance[j] != bloats->bl_distance[TT_SPACE]) + if (bloats->bl_distance[j] != 0) { if (bloats->bl_plane < 0) TTMaskSetType(&ourDepend, j); diff --git a/lef/lefRead.c b/lef/lefRead.c index 625ecea7..22346bdb 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -2687,12 +2687,6 @@ LefRead(inName, importForeign) case LEF_SECTION_SPACING: LefSkipSection(f, sections[LEF_SECTION_SPACING]); break; - case LEF_SECTION_SITE: - token = LefNextToken(f, TRUE); - LefError(LEF_INFO, "Defines site %s (ignored)\n", token); - sprintf(tsave, "%.127s", token); - LefSkipSection(f, tsave); - break; case LEF_NOISETABLE: LefSkipSection(f, sections[LEF_NOISETABLE]); break; @@ -2711,6 +2705,7 @@ LefRead(inName, importForeign) case LEF_EXTENSION: LefSkipSection(f, sections[LEF_EXTENSION]); break; + case LEF_SECTION_SITE: case LEF_MACRO: token = LefNextToken(f, TRUE); /* Diagnostic */ diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 3070c2a8..63124498 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -238,11 +238,12 @@ lefFileOpen(def, file, suffix, mode, prealfile) */ void -lefWriteHeader(def, f, lefTech, propTable) +lefWriteHeader(def, f, lefTech, propTable, siteTable) CellDef *def; /* Def for which to generate LEF output */ FILE *f; /* Output to this file */ bool lefTech; /* If TRUE, write layer information */ HashTable *propTable; /* Hash table of property definitions */ + HashTable *siteTable; /* Hash table of sites used */ { TileType type; HashSearch hs; @@ -296,7 +297,55 @@ lefWriteHeader(def, f, lefTech, propTable) /* This has not been implemented; only string types are supported */ fprintf(f, IN0 "MACRO %s STRING ;\n", (char *)he->h_key.h_name); } - if (nprops > 0) fprintf(f, "END PROPERTYDEFINITIONS\n"); + if (nprops > 0) fprintf(f, "END PROPERTYDEFINITIONS\n\n"); + + HashStartSearch(&hs); + while (he = HashNext(siteTable, &hs)) + { + /* Output the SITE as a macro */ + CellDef *siteDef; + float scale; + char leffmt[2][10]; + bool propfound; + char *propvalue; + Rect boundary; + + siteDef = DBCellLookDef((char *)he->h_key.h_name); + if (siteDef) + { + fprintf(f, "SITE %s\n", siteDef->cd_name); + + propvalue = (char *)DBPropGet(siteDef, "LEFsymmetry", &propfound); + if (propfound) + fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue); + else + /* Usually core cells have symmetry Y only. */ + fprintf(f, IN0 "SYMMETRY Y ;\n"); + + propvalue = (char *)DBPropGet(siteDef, "LEFclass", &propfound); + if (propfound) + fprintf(f, IN0 "CLASS %s ;\n", propvalue); + else + /* Needs a class of some kind. Use CORE as default if not defined */ + fprintf(f, IN0 "CLASS CORE ;\n"); + + boundary = siteDef->cd_bbox; + if (siteDef->cd_flags & CDFIXEDBBOX) + { + propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound); + if (propfound) + sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot, + &boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop); + } + + scale = CIFGetOutputScale(1000); /* conversion to microns */ + fprintf(f, IN0 "SIZE " FP " BY " FP " ;\n", + lefPrint(leffmt[0], scale * (float)(boundary.r_xtop - boundary.r_xbot)), + lefPrint(leffmt[1], scale * (float)(boundary.r_ytop - boundary.r_ybot))); + + fprintf(f, "END %s\n\n", siteDef->cd_name); + } + } if (!lefTech) return; @@ -1614,6 +1663,36 @@ lefWriteMacro(def, f, scale, hide) UndoEnable(); } +/* + *------------------------------------------------------------ + * + * lefGetSites --- + * + * Pull SITE instances from multiple cells into a list of + * unique entries to be written to the LEF header of an + * output LEF file. + * + *------------------------------------------------------------ + */ +int +lefGetSites(stackItem, i, clientData) + ClientData stackItem; + int i; + ClientData clientData; +{ + CellDef *def = (CellDef *)stackItem; + HashTable *lefSiteTbl = (HashTable *)clientData; + HashEntry *he; + bool propfound; + char *propvalue; + + propvalue = (char *)DBPropGet(def, "LEFsite", &propfound); + if (propfound) + he = HashFind(lefSiteTbl, propvalue); + + return 0; +} + /* *------------------------------------------------------------ * @@ -1705,7 +1784,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse) bool lefHide; bool recurse; { - HashTable propHashTbl; + HashTable propHashTbl, siteHashTbl; CellDef *def, *rootdef; FILE *f; char *filename; @@ -1753,11 +1832,16 @@ LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse) HashInit(&propHashTbl, 4, HT_STRINGKEYS); StackEnum(lefDefStack, lefGetProperties, &propHashTbl); + /* For all cells, collect any sites */ + HashInit(&siteHashTbl, 4, HT_STRINGKEYS); + StackEnum(lefDefStack, lefGetSites, &siteHashTbl); + /* Now generate LEF output for all the cells we just found */ - lefWriteHeader(rootdef, f, lefTech, &propHashTbl); + lefWriteHeader(rootdef, f, lefTech, &propHashTbl, &siteHashTbl); HashKill(&propHashTbl); + HashKill(&siteHashTbl); while (def = (CellDef *) StackPop(lefDefStack)) { @@ -1856,12 +1940,15 @@ LefWriteCell(def, outName, isRoot, lefTech, lefHide) if (isRoot) { - HashTable propHashTbl; + HashTable propHashTbl, siteHashTbl; HashInit(&propHashTbl, 4, HT_STRINGKEYS); lefGetProperties((ClientData)def, 0, (ClientData)&propHashTbl); - lefWriteHeader(def, f, lefTech, &propHashTbl); + HashInit(&siteHashTbl, 4, HT_STRINGKEYS); + lefGetSites((ClientData)def, 0, (ClientData)&siteHashTbl); + lefWriteHeader(def, f, lefTech, &propHashTbl, &siteHashTbl); HashKill(&propHashTbl); + HashKill(&siteHashTbl); } lefWriteMacro(def, f, scale, lefHide); fclose(f);