diff --git a/VERSION b/VERSION index f0293101..d53f7713 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.325 +8.3.326 diff --git a/database/DBconnect.c b/database/DBconnect.c index 7be8e222..33a6da2b 100644 --- a/database/DBconnect.c +++ b/database/DBconnect.c @@ -36,6 +36,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "utils/signals.h" #include "utils/malloc.h" +/* Global variable */ +Stack *dbConnectStack = (Stack *)NULL; + /* General note for DBSrConnect: * * The connectivity extractor works in two passes, in order to avoid @@ -319,6 +322,32 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData) return result; } +/* + * ---------------------------------------------------------------------------- + * + * dbcFindTileFunc -- + * + * Simple callback used by dbSrConnectFunc to return any tile found + * matching the search type mask. + * + * Results: + * Always 1. + * + * Side effects: + * Fill client data with a pointer to the tile found. + * + * ---------------------------------------------------------------------------- + */ + +int +dbcFindTileFunc(tile, arg) + Tile *tile; + ClientData arg; +{ + Tile **tptr = (Tile **)arg; + *tptr = tile; + return 1; +} /* * ---------------------------------------------------------------------------- @@ -346,6 +375,10 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData) * passes, so "seen before" is a function both of the ti_client * field in the tile and the csa_clear value. * + * 9/21/2022: Changed from being a recursive routine to using a + * stack method, as large power/ground networks were causing stack + * smashing. + * * ---------------------------------------------------------------------------- */ @@ -356,206 +389,235 @@ dbSrConnectFunc(tile, csa) { Tile *t2; Rect tileArea; - int i; + int i, pNum; + int result = 0; TileTypeBitMask *connectMask; TileType loctype, checktype; PlaneMask planes; - TiToRect(tile, &tileArea); + if (dbConnectStack == (Stack *)NULL) + dbConnectStack = StackNew(256); - /* Make sure this tile overlaps the area we're interested in. */ + /* Drop the first entry on the stack */ + pNum = csa->csa_pNum; + STACKPUSH((ClientData)tile, dbConnectStack); + STACKPUSH((ClientData)pNum, dbConnectStack); - if (!GEO_OVERLAP(&tileArea, &csa->csa_bounds)) return 0; - - /* See if we've already been here before, and mark the tile as already - * visited. - */ - - if (csa->csa_clear) + while (!StackEmpty(dbConnectStack)) { - if (tile->ti_client == (ClientData) CLIENTDEFAULT) return 0; - tile->ti_client = (ClientData) CLIENTDEFAULT; - } - else - { - if (tile->ti_client != (ClientData) CLIENTDEFAULT) return 0; - tile->ti_client = (ClientData) 1; - } + pNum = (int)STACKPOP(dbConnectStack); + tile = (Tile *)STACKPOP(dbConnectStack); + if (result == 1) continue; - /* Call the client function, if there is one. */ + TiToRect(tile, &tileArea); - if (csa->csa_clientFunc != NULL) - { - if ((*csa->csa_clientFunc)(tile, csa->csa_pNum, csa->csa_clientData) != 0) - return 1; - } + /* Make sure this tile overlaps the area we're interested in. */ - /* Now search around each of the four sides of this tile for - * connected tiles. For each one found, call ourselves - * recursively. - */ + if (!GEO_OVERLAP(&tileArea, &csa->csa_bounds)) continue; - if (IsSplit(tile)) - { - if (SplitSide(tile)) - loctype = SplitRightType(tile); - else - loctype = SplitLeftType(tile); - } - else - loctype = TiGetTypeExact(tile); - connectMask = &csa->csa_connect[loctype]; + /* See if we've already been here before, and mark the tile as already + * visited. + */ - /* Left side: */ - - if (IsSplit(tile) && SplitSide(tile)) goto bottomside; - - for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2)) - { - if (IsSplit(t2)) + if (csa->csa_clear) { - checktype = SplitRightType(t2); + if (tile->ti_client == (ClientData) CLIENTDEFAULT) continue; + tile->ti_client = (ClientData) CLIENTDEFAULT; } else - checktype = TiGetTypeExact(t2); - if (TTMaskHasType(connectMask, checktype)) { - if (csa->csa_clear) + if (tile->ti_client != (ClientData) CLIENTDEFAULT) continue; + tile->ti_client = (ClientData) 1; + } + + /* Call the client function, if there is one. */ + + if (csa->csa_clientFunc != NULL) + { + if ((*csa->csa_clientFunc)(tile, pNum, csa->csa_clientData) != 0) { - if (t2->ti_client == (ClientData) CLIENTDEFAULT) continue; + result = 1; + continue; } - else if (t2->ti_client != (ClientData) CLIENTDEFAULT) continue; - if (IsSplit(t2)) - TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE)); /* bit set */ - if (dbSrConnectFunc(t2, csa) != 0) return 1; } - } - /* Bottom side: */ + /* Now search around each of the four sides of this tile for + * connected tiles. For each one found, call ourselves + * recursively. + */ + + if (IsSplit(tile)) + { + if (SplitSide(tile)) + loctype = SplitRightType(tile); + else + loctype = SplitLeftType(tile); + } + else + loctype = TiGetTypeExact(tile); + connectMask = &csa->csa_connect[loctype]; + + /* Left side: */ + + if (IsSplit(tile) && SplitSide(tile)) goto bottomside; + + for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2)) + { + if (IsSplit(t2)) + { + checktype = SplitRightType(t2); + } + else + checktype = TiGetTypeExact(t2); + if (TTMaskHasType(connectMask, checktype)) + { + if (csa->csa_clear) + { + if (t2->ti_client == (ClientData) CLIENTDEFAULT) continue; + } + else if (t2->ti_client != (ClientData) CLIENTDEFAULT) continue; + if (IsSplit(t2)) + TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE)); /* bit set */ + STACKPUSH((ClientData)t2, dbConnectStack); + STACKPUSH((ClientData)pNum, dbConnectStack); + } + } + + /* Bottom side: */ bottomside: - if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile)))) - goto rightside; + if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile)))) + goto rightside; - for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2)) - { - if (IsSplit(t2)) + for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2)) { - checktype = SplitTopType(t2); - } - else - checktype = TiGetTypeExact(t2); - if (TTMaskHasType(connectMask, checktype)) - { - if (csa->csa_clear) - { - if (t2->ti_client == (ClientData) CLIENTDEFAULT) continue; - } - else if (t2->ti_client != (ClientData) CLIENTDEFAULT) continue; if (IsSplit(t2)) { - if (SplitDirection(t2)) - TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE)); /* bit set */ - else - TiSetBody(t2, (ClientData)(t2->ti_body & ~TT_SIDE)); /* bit clear */ + checktype = SplitTopType(t2); + } + else + checktype = TiGetTypeExact(t2); + if (TTMaskHasType(connectMask, checktype)) + { + if (csa->csa_clear) + { + if (t2->ti_client == (ClientData) CLIENTDEFAULT) continue; + } + else if (t2->ti_client != (ClientData) CLIENTDEFAULT) continue; + if (IsSplit(t2)) + { + if (SplitDirection(t2)) + /* bit set */ + TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE)); + else + /* bit clear */ + TiSetBody(t2, (ClientData)(t2->ti_body & ~TT_SIDE)); + } + STACKPUSH((ClientData)t2, dbConnectStack); + STACKPUSH((ClientData)pNum, dbConnectStack); } - if (dbSrConnectFunc(t2, csa) != 0) return 1; } - } - /* Right side: */ + /* Right side: */ rightside: - if (IsSplit(tile) && !SplitSide(tile)) goto topside; + if (IsSplit(tile) && !SplitSide(tile)) goto topside; - for (t2 = TR(tile); ; t2 = LB(t2)) - { - if (IsSplit(t2)) + for (t2 = TR(tile); ; t2 = LB(t2)) { - checktype = SplitLeftType(t2); - } - else - checktype = TiGetTypeExact(t2); - if (TTMaskHasType(connectMask, checktype)) - { - if (csa->csa_clear) - { - if (t2->ti_client == (ClientData) CLIENTDEFAULT) goto nextRight; - } - else if (t2->ti_client != (ClientData) CLIENTDEFAULT) goto nextRight; if (IsSplit(t2)) - TiSetBody(t2, (ClientData)(t2->ti_body & ~TT_SIDE)); /* bit clear */ - if (dbSrConnectFunc(t2, csa) != 0) return 1; + { + checktype = SplitLeftType(t2); + } + else + checktype = TiGetTypeExact(t2); + if (TTMaskHasType(connectMask, checktype)) + { + if (csa->csa_clear) + { + if (t2->ti_client == (ClientData) CLIENTDEFAULT) goto nextRight; + } + else if (t2->ti_client != (ClientData) CLIENTDEFAULT) goto nextRight; + if (IsSplit(t2)) + TiSetBody(t2, (ClientData)(t2->ti_body & ~TT_SIDE)); /* bit clear */ + STACKPUSH((ClientData)t2, dbConnectStack); + STACKPUSH((ClientData)pNum, dbConnectStack); + } + nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break; } - nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break; - } - /* Top side: */ + /* Top side: */ topside: - if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto donesides; + if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto donesides; - for (t2 = RT(tile); ; t2 = BL(t2)) - { - if (IsSplit(t2)) + for (t2 = RT(tile); ; t2 = BL(t2)) { - checktype = SplitBottomType(t2); - } - else - checktype = TiGetTypeExact(t2); - if (TTMaskHasType(connectMask, checktype)) - { - if (csa->csa_clear) - { - if (t2->ti_client == (ClientData) CLIENTDEFAULT) goto nextTop; - } - else if (t2->ti_client != (ClientData) CLIENTDEFAULT) goto nextTop; if (IsSplit(t2)) { - if (SplitDirection(t2)) - TiSetBody(t2, (ClientData)(t2->ti_body & ~TT_SIDE)); /* bit clear */ - else - TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE)); /* bit set */ + checktype = SplitBottomType(t2); } - if (dbSrConnectFunc(t2, csa) != 0) return 1; + else + checktype = TiGetTypeExact(t2); + if (TTMaskHasType(connectMask, checktype)) + { + if (csa->csa_clear) + { + if (t2->ti_client == (ClientData) CLIENTDEFAULT) goto nextTop; + } + else if (t2->ti_client != (ClientData) CLIENTDEFAULT) goto nextTop; + if (IsSplit(t2)) + { + if (SplitDirection(t2)) + /* bit clear */ + TiSetBody(t2, (ClientData)(t2->ti_body & ~TT_SIDE)); + else + /* bit set */ + TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE)); + } + STACKPUSH((ClientData)t2, dbConnectStack); + STACKPUSH((ClientData)pNum, dbConnectStack); + } + nextTop: if (LEFT(t2) <= tileArea.r_xbot) break; } - nextTop: if (LEFT(t2) <= tileArea.r_xbot) break; - } donesides: - /* Lastly, check to see if this tile connects to anything on - * other planes. If so, search those planes. - */ + /* Lastly, check to see if this tile connects to anything on + * other planes. If so, search those planes. + */ - planes = DBConnPlanes[loctype]; - planes &= ~(PlaneNumToMaskBit(csa->csa_pNum)); - if (planes != 0) - { - struct conSrArg newcsa; - Rect newArea; - - newcsa = *csa; - TiToRect(tile, &newArea); - GEO_EXPAND(&newArea, 1, &newArea); - for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) + planes = DBConnPlanes[loctype]; + planes &= ~(PlaneNumToMaskBit(pNum)); + if (planes != 0) { - if (!PlaneMaskHasPlane(planes, i)) continue; - newcsa.csa_pNum = i; - if (IsSplit(tile)) + Rect newArea; + GEO_EXPAND(&tileArea, 1, &newArea); + + for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) { - if (DBSrPaintNMArea((Tile *) NULL, csa->csa_def->cd_planes[i], - TiGetTypeExact(tile), &newArea, connectMask, - dbSrConnectFunc, (ClientData) &newcsa) != 0) - return 1; + if (!PlaneMaskHasPlane(planes, i)) continue; + if (IsSplit(tile)) + { + if (DBSrPaintNMArea((Tile *) NULL, csa->csa_def->cd_planes[i], + TiGetTypeExact(tile), &newArea, connectMask, + dbcFindTileFunc, (ClientData)&t2) != 0) + { + STACKPUSH((ClientData)t2, dbConnectStack); + STACKPUSH((ClientData)i, dbConnectStack); + } + } + else if (DBSrPaintArea((Tile *) NULL, csa->csa_def->cd_planes[i], + &newArea, connectMask, dbcFindTileFunc, + (ClientData)&t2) != 0) + { + STACKPUSH((ClientData)t2, dbConnectStack); + STACKPUSH((ClientData)i, dbConnectStack); + } } - else if (DBSrPaintArea((Tile *) NULL, csa->csa_def->cd_planes[i], - &newArea, connectMask, dbSrConnectFunc, - (ClientData) &newcsa) != 0) return 1; } } - - return 0; + return result; } diff --git a/lef/defRead.c b/lef/defRead.c index 4840df29..c9e73fe7 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -917,6 +917,7 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total) break; } } + inlayer = FALSE; break; case DEF_NONDEF_END: diff --git a/lef/defWrite.c b/lef/defWrite.c index 0100e265..6a8584d7 100644 --- a/lef/defWrite.c +++ b/lef/defWrite.c @@ -65,6 +65,7 @@ typedef struct { CellDef *def; float scale; int total; + int plane; TileTypeBitMask *mask; LefMapping *MagicToLefTbl; HashTable *defViaTable; @@ -218,8 +219,6 @@ defCountNets(rootDef, allSpecial) total.regular = (allSpecial) ? -1 : 0; total.special = 0; total.blockages = 0; - total.numrules = 0; - total.rules = NULL; total.has_nets = TRUE; TxPrintf("Diagnostic: Finding all nets in cell %s\n", rootDef->cd_name); @@ -844,7 +843,7 @@ defNetGeometryFunc(tile, plane, defdata) int routeWidth, w, h, midlinex2, topClip, botClip; float x1, y1, x2, y2, extlen; lefLayer *lefType, *lefl; - char *lefName, viaName[128], posstr[24]; + char *lefName, *taperName, viaName[128], posstr[24]; HashEntry *he; HashTable *defViaTable = defdata->defViaTable; LefMapping *MagicToLefTable = defdata->MagicToLefTbl; @@ -883,34 +882,13 @@ defNetGeometryFunc(tile, plane, defdata) return 0; /* Boundary search on stacked contact types to include any */ - /* tile areas belonging to ttype. */ - - for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) /* Top */ - { - r2type = TiGetBottomType(tp); - if (r2type == ttype) - { - if (!rMask) return 0; - TiToRect(tp, &r2); - GeoInclude(&r2, &r); - } - else if (r2type >= DBNumUserLayers) - { - r2Mask = DBResidueMask(r2type); - if (TTMaskHasType(r2Mask, ttype)) - return 0; - } - } + /* tile areas belonging to ttype. ONLY check top and right. */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) /* Left */ { r2type = TiGetRightType(tp); if (r2type == ttype) - { - if (!rMask) return 0; - TiToRect(tp, &r2); - GeoInclude(&r2, &r); - } + return 0; else if (r2type >= DBNumUserLayers) { r2Mask = DBResidueMask(r2type); @@ -923,11 +901,7 @@ defNetGeometryFunc(tile, plane, defdata) { r2type = TiGetTopType(tp); if (r2type == ttype) - { - if (!rMask) return 0; - TiToRect(tp, &r2); - GeoInclude(&r2, &r); - } + return 0; else if (r2type >= DBNumUserLayers) { r2Mask = DBResidueMask(r2type); @@ -936,12 +910,13 @@ defNetGeometryFunc(tile, plane, defdata) } } - for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) /* Right */ + /* Extend boundary to top and right */ + + for (tp = RT(tile); ; tp = RT(tp)) /* Top */ { - r2type = TiGetLeftType(tp); + r2type = TiGetBottomType(tp); if (r2type == ttype) { - if (!rMask) return 0; TiToRect(tp, &r2); GeoInclude(&r2, &r); } @@ -949,8 +924,34 @@ defNetGeometryFunc(tile, plane, defdata) { r2Mask = DBResidueMask(r2type); if (TTMaskHasType(r2Mask, ttype)) - return 0; + { + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else break; } + else break; + } + + for (tp = TR(tile); ; tp = TR(tp)) /* Right */ + { + r2type = TiGetLeftType(tp); + if (r2type == ttype) + { + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (r2type >= DBNumUserLayers) + { + r2Mask = DBResidueMask(r2type); + if (TTMaskHasType(r2Mask, ttype)) + { + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else break; + } + else break; } } rorig = r; @@ -960,6 +961,7 @@ defNetGeometryFunc(tile, plane, defdata) lefName = MagicToLefTable[ttype].lefName; if (lefName == NULL) return 0; /* Do not write types not in LEF definition */ lefType = MagicToLefTable[ttype].lefInfo; + taperName = NULL; orient = GEO_EAST; w = r.r_xtop - r.r_xbot; @@ -997,8 +999,7 @@ defNetGeometryFunc(tile, plane, defdata) } } - /* Warn if the route is not equal to the default route width--- */ - /* This means a regular net should have been a special net. */ + /* Check for non-default widths */ if ((h != routeWidth) && (w != routeWidth)) { /* Handle slivers. There are two main cases: @@ -1038,11 +1039,36 @@ defNetGeometryFunc(tile, plane, defdata) if (h < routeWidth) return 0; } - /* Diagnostic */ - if ((h != routeWidth) && (w != routeWidth)) + /* Handle non-default width regular nets (use TAPERRULE) */ + if ((h != routeWidth) && (w != routeWidth) && + (defdata->specialmode == DO_REGULAR)) + { + int ndv = (h > w) ? w : h; + char ndname[100]; + LefRules *ruleset; + lefRule *rule; + + /* TxPrintf("Net at (%d, %d) has width %d, default width is %d\n", r.r_xbot, r.r_ybot, (h < w) ? h : w, routeWidth); + */ + + /* Create a nondefault rule. Use one rule per layer and width */ + sprintf(ndname, "%s_width_%d", lefName, (int)((float)ndv * oscale)); + he = HashFind(&LefNonDefaultRules, ndname); + ruleset = (LefRules *)HashGetValue(he); + if (ruleset == NULL) + { + ruleset = (LefRules *)mallocMagic(sizeof(LefRules)); + HashSetValue(he, ruleset); + ruleset->name = StrDup((char **)NULL, ndname); + ruleset->rule = (lefRule *)mallocMagic(sizeof(lefRule)); + ruleset->rule->lefInfo = lefType; + ruleset->rule->width = ndv; + } + taperName = ruleset->name; + } /* Set orientation based on longest side */ if (h > w) @@ -1170,6 +1196,9 @@ defNetGeometryFunc(tile, plane, defdata) sameroute = FALSE; } } + else if (taperName != NULL) + /* TAPERRULE can only be put after a NEW layer line */ + sameroute = FALSE; else sameroute = TRUE; } @@ -1277,6 +1306,8 @@ defNetGeometryFunc(tile, plane, defdata) defCheckForBreak(strlen(rName) + 1, defdata); fprintf(f, "%s ", rName); + if (taperName != NULL) + fprintf(f, "TAPERRULE %s ", taperName); if (defdata->specialmode != DO_REGULAR) defWriteRouteWidth(defdata, routeWidth); defWriteCoord(defdata, x1, y1, GEO_CENTER); @@ -1303,6 +1334,8 @@ defNetGeometryFunc(tile, plane, defdata) { defCheckForBreak(strlen(lefName) + 1, defdata); fprintf(f, "%s ", lefName); + if (taperName != NULL) + fprintf(f, "TAPERRULE %s ", taperName); if (defdata->specialmode != DO_REGULAR) defWriteRouteWidth(defdata, routeWidth); @@ -1487,6 +1520,7 @@ defCountVias(rootDef, MagicToLefTable, defViaTable, oscale) } } cviadata.mask = &contactMask; + cviadata.plane = pNum; DBSrPaintArea((Tile *)NULL, rootDef->cd_planes[pNum], &TiPlaneRect, &contactMask, @@ -1531,13 +1565,14 @@ defCountViaFunc(tile, cviadata) /* case we would need to initialize the hash table. */ if (LefInfo.ht_table == (HashEntry **) NULL) LefTechInit(); - /* Find the canonical type */ + /* If type is a stacked contact, find the residue on the search plane */ if (ttype >= DBNumUserLayers) { rmask = DBResidueMask(ttype); for (ctype = TT_TECHDEPBASE; ctype < DBNumUserLayers; ctype++) if (TTMaskHasType(rmask, ctype)) - break; + if (DBPlane(ctype) == cviadata->plane) + break; if (ctype == DBNumUserLayers) return 1; /* Error condition */ } @@ -1559,34 +1594,16 @@ defCountViaFunc(tile, cviadata) /* of regular and/or stacked types. This whole thing should be */ /* replaced by calls to generate layers via the CIF/Calma code. */ - /* Top */ - for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) - { - rtype = TiGetBottomType(tp); - if (rtype == ctype) - { - if (!rmask) return 0; /* ignore tile but continue search */ - TiToRect(tp, &r2); - GeoInclude(&r2, &r); - } - else if (rtype >= DBNumUserLayers) - { - rmask2 = DBResidueMask(rtype); - if (TTMaskHasType(rmask2, ctype)) - return 0; - } - } + /* If any matching tile exists to left or bottom, then return */ + /* immediately. Only expand areas for which this is the bottom and */ + /* left-most contact tile. */ /* Left */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) { rtype = TiGetRightType(tp); if (rtype == ctype) - { - if (!rmask) return 0; /* ignore tile but continue search */ - TiToRect(tp, &r2); - GeoInclude(&r2, &r); - } + return 0; else if (rtype >= DBNumUserLayers) { rmask2 = DBResidueMask(rtype); @@ -1600,11 +1617,7 @@ defCountViaFunc(tile, cviadata) { rtype = TiGetTopType(tp); if (rtype == ctype) - { - if (!rmask) return 0; /* ignore tile but continue search */ - TiToRect(tp, &r2); - GeoInclude(&r2, &r); - } + return 0; else if (rtype >= DBNumUserLayers) { rmask2 = DBResidueMask(rtype); @@ -1613,13 +1626,14 @@ defCountViaFunc(tile, cviadata) } } - /* Right */ - for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + /* Expand to top and right until the whole contact area has been found */ + + /* Top */ + for (tp = RT(tile); ; tp = RT(tp)) { - rtype = TiGetLeftType(tp); + rtype = TiGetBottomType(tp); if (rtype == ctype) { - if (!rmask) return 0; /* ignore tile but continue search */ TiToRect(tp, &r2); GeoInclude(&r2, &r); } @@ -1627,8 +1641,35 @@ defCountViaFunc(tile, cviadata) { rmask2 = DBResidueMask(rtype); if (TTMaskHasType(rmask2, ctype)) - return 0; + { + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else break; } + else break; + } + + /* Right */ + for (tp = TR(tile); ; tp = TR(tp)) + { + rtype = TiGetLeftType(tp); + if (rtype == ctype) + { + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (rtype >= DBNumUserLayers) + { + rmask2 = DBResidueMask(rtype); + if (TTMaskHasType(rmask2, ctype)) + { + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else break; + } + else break; } /* All values for the via rect are in 1/2 lambda to account */ @@ -2651,10 +2692,11 @@ DefWriteCell(def, outName, allSpecial, units) bool allSpecial; /* Treat all nets as SPECIALNETS? */ int units; /* Force units to this value (default 1000) */ { - char *filename; - FILE *f; + char *filename, *filename1, *filename2; + char line[2048]; + FILE *f, *f2; /* Break output file into parts */ NetCount nets; - int total; + int total, numrules; float scale; HashTable defViaTable; @@ -2662,6 +2704,7 @@ DefWriteCell(def, outName, allSpecial, units) int i; lefLayer *lefl; HashEntry *he; + HashSearch hs; /* Note that "1" corresponds to "1000" in the header UNITS line, */ /* or units of nanometers. 10 = centimicrons, 1000 = microns. */ @@ -2689,6 +2732,7 @@ DefWriteCell(def, outName, allSpecial, units) #endif return; } + filename1 = StrDup((char **)NULL, filename); defWriteHeader(def, f, scale, units); @@ -2720,39 +2764,89 @@ DefWriteCell(def, outName, allSpecial, units) /* Count the number of nets and "special" nets */ nets = defCountNets(def, allSpecial); - /* Nondefault rules */ -#if 0 - /* Not yet implemented */ - if (nets.numrules > 0) + /* Not done yet with output, so keep this file open. . . */ + + f2 = lefFileOpen(def, outName, ".def.part", "w", &filename); + + if (f2 == NULL) { - NetRule *nrule; - fprintf(f, "NONDEFAULTRULES %d ;\n", nets.numrules); - for (nrule = nets.rules; nrule; nrule = nrule->next) - { - fprintf(f, " - %s\n", nrule->name); - fprintf(f, " + LAYER %s WIDTH %.10g\n", nrule->rule->name, - ((float)nrule->rule->info.route.width * scale)); - } - fprintf(f, "END NONDEFAULTRULES\n\n"); - } +#ifdef MAGIC_WRAPPER + TxError("Cannot open output file %s (%s).\n", filename, + strerror(errno)); +#else + TxError("Cannot open output file: "); + perror(filename); #endif + /* If part 2 cannot be opened, remove part 1 */ + fclose(f); + unlink(filename1); + freeMagic(filename1); + return; + } + filename2 = StrDup((char **)NULL, filename); /* "Special" nets---nets matching $GND, $VDD, or $globals(*) */ if (nets.special > 0) { - fprintf(f, "SPECIALNETS %d ;\n", nets.special); - defWriteNets(f, def, scale, lefMagicToLefLayer, &defViaTable, + fprintf(f2, "SPECIALNETS %d ;\n", nets.special); + defWriteNets(f2, def, scale, lefMagicToLefLayer, &defViaTable, (allSpecial) ? ALL_SPECIAL : DO_SPECIAL); - fprintf(f, "END SPECIALNETS\n\n"); + fprintf(f2, "END SPECIALNETS\n\n"); } /* "Regular" nets */ if (nets.regular > 0) { - fprintf(f, "NETS %d ;\n", nets.regular); - defWriteNets(f, def, scale, lefMagicToLefLayer, &defViaTable, DO_REGULAR); - fprintf(f, "END NETS\n\n"); + fprintf(f2, "NETS %d ;\n", nets.regular); + defWriteNets(f2, def, scale, lefMagicToLefLayer, &defViaTable, DO_REGULAR); + fprintf(f2, "END NETS\n\n"); } + fclose(f2); + + /* Now that nets have been written, the nondefault rules can be generated */ + + /* Nondefault rules */ + numrules = LefNonDefaultRules.ht_nEntries; + if (numrules > 0) + { + LefRules *nrules; + + fprintf(f, "NONDEFAULTRULES %d ;\n", numrules); + HashStartSearch(&hs); + while (he = HashNext(&LefNonDefaultRules, &hs)) + { + nrules = (LefRules *)HashGetValue(he); + + fprintf(f, " - %s\n", nrules->name); + fprintf(f, " + LAYER %s WIDTH %.10g ;\n", + nrules->rule->lefInfo->canonName, + ((float)nrules->rule->width * scale)); + } + fprintf(f, "END NONDEFAULTRULES\n\n"); + } + + /* Append contents of file with NETS and SPECIALNETS sections */ + + f2 = lefFileOpen(def, outName, ".def.part", "r", &filename); + if (f2 == NULL) + { + /* This should not happen because the file was just written. . . */ +#ifdef MAGIC_WRAPPER + TxError("Cannot open input file %s (%s).\n", filename, + strerror(errno)); +#else + TxError("Cannot open input file: "); + perror(filename); +#endif + /* If part 2 cannot be opened, remove part 1 */ + fclose(f); + unlink(filename1); + freeMagic(filename1); + freeMagic(filename2); + return; + } + while (dbFgets(line, sizeof line, f2) != NULL) fprintf(f, "%s", line); + fclose(f2); /* Blockages */ if (nets.blockages > 0) @@ -2761,11 +2855,19 @@ DefWriteCell(def, outName, allSpecial, units) fprintf(f, "END DESIGN\n\n"); fclose(f); + /* Remove the temporary file of nets */ + unlink(filename2); + + freeMagic(filename1); + freeMagic(filename2); + if (nets.has_nets) { EFFlatDone(NULL); EFDone(NULL); } + /* To do: Clean up nondefault rules tables */ + freeMagic((char *)lefMagicToLefLayer); HashKill(&defViaTable); lefRemoveGeneratedVias(); diff --git a/lef/lefInt.h b/lef/lefInt.h index 949f73ba..02d125b8 100644 --- a/lef/lefInt.h +++ b/lef/lefInt.h @@ -123,8 +123,6 @@ typedef struct { int regular; int special; int blockages; - int numrules; - LefRules *rules; bool has_nets; } NetCount;