From 49d98115bb4d0849a262c308bf57ecf333b85a81 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 3 Jul 2019 13:58:13 -0400 Subject: [PATCH 1/5] Added a number of enhancements to the DEF reading to handle various forms of syntax found in the LEF/DEF spec up to version 5.8. Handles vias formed by parameter and a number of syntax variations that mess up the usual parsing. Corrected an error in the calculation of wire extensions when wires are given with three coordinates. --- lef/defRead.c | 335 +++++++++++++++++++++++++++++++++++++++++++++++--- lef/lefInt.h | 1 + lef/lefRead.c | 94 ++++++++++++++ 3 files changed, 415 insertions(+), 15 deletions(-) diff --git a/lef/defRead.c b/lef/defRead.c index a8477fcc..5dadbfd4 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -53,6 +53,25 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ *------------------------------------------------------------ */ +enum def_netspecial_keys {DEF_SPECNET_SHAPE = 0, DEF_SPECNET_STYLE, + DEF_SPECNET_USE, DEF_SPECNET_VOLTAGE, DEF_SPECNET_FIXEDBUMP, + DEF_SPECNET_ORIGINAL, DEF_SPECNET_PATTERN, DEF_SPECNET_ESTCAP, + DEF_SPECNET_WEIGHT, DEF_SPECNET_PROPERTY}; + +enum def_netspecial_shape_keys { + DEF_SPECNET_SHAPE_RING = 0, + DEF_SPECNET_SHAPE_PADRING, + DEF_SPECNET_SHAPE_BLOCKRING, + DEF_SPECNET_SHAPE_STRIPE, + DEF_SPECNET_SHAPE_FOLLOWPIN, + DEF_SPECNET_SHAPE_IOWIRE, + DEF_SPECNET_SHAPE_COREWIRE, + DEF_SPECNET_SHAPE_BLOCKWIRE, + DEF_SPECNET_SHAPE_BLOCKAGEWIRE, + DEF_SPECNET_SHAPE_FILLWIRE, + DEF_SPECNET_SHAPE_FILLWIREOPC, + DEF_SPECNET_SHAPE_DRCFILL}; + char * DefAddRoutes(rootDef, f, oscale, special, defLayerMap) CellDef *rootDef; /* Cell to paint */ @@ -67,11 +86,43 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) bool valid = FALSE; /* is there a valid reference point? */ bool initial = TRUE; Rect locarea; + int extend; float x, y, z, w; int routeWidth, paintWidth, saveWidth; TileType routeLayer, paintLayer; HashEntry *he; lefLayer *lefl; + int keyword; + + static char *specnet_keys[] = { + "SHAPE", + "STYLE", + "USE", + "VOLTAGE", + "FIXEDBUMP", + "ORIGINAL", + "PATTERN", + "ESTCAP", + "WEIGHT", + "PROPERTY", + NULL + }; + + static char *specnet_shape_keys[] = { + "RING", + "PADRING", + "BLOCKRING", + "STRIPE", + "FOLLOWPIN", + "IOWIRE", + "COREWIRE", + "BLOCKWIRE", + "BLOCKAGEWIRE", + "FILLWIRE", + "FILLWIREOPC", + "DRCFILL", + NULL + }; while (initial || (token = LefNextToken(f, TRUE)) != NULL) { @@ -130,6 +181,135 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) paintWidth = (lefl) ? lefl->info.route.width : DEFAULT_WIDTH * DBLambda[1] / DBLambda[0]; } + else if ((*token == '+') && (special == TRUE)) + { + int netstyle; + + /* Check for SHAPE, STYLE, or USE keywords */ + token = LefNextToken(f, TRUE); + keyword = Lookup(token, specnet_keys); + if (keyword < 0) + { + LefError(DEF_INFO, "Unknown keyword \"%s\" in SPECIALNET " + "definition; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch(keyword) + { + case DEF_SPECNET_STYLE: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &netstyle) != 1) + { + LefError(DEF_INFO, "Net style \"%s\" in SPECIALNET " + "definition is not a number; ignoring.\n", token); + LefEndStatement(f); + continue; + } + break; + + case DEF_SPECNET_SHAPE: + token = LefNextToken(f, TRUE); + keyword = Lookup(token, specnet_shape_keys); + if (keyword < 0) + { + LefError(DEF_INFO, "Unknown SHAPE \"%s\" in SPECIALNET " + "definition; ignoring.\n", token); + LefEndStatement(f); + continue; + } + break; + + case DEF_SPECNET_PROPERTY: + /* Ignore except to absorb the next two tokens. */ + token = LefNextToken(f, TRUE); /* Drop through */ + + case DEF_SPECNET_USE: + case DEF_SPECNET_VOLTAGE: + case DEF_SPECNET_ORIGINAL: + case DEF_SPECNET_PATTERN: + case DEF_SPECNET_ESTCAP: + case DEF_SPECNET_WEIGHT: + /* Ignore except to absorb the next token. */ + token = LefNextToken(f, TRUE); /* Drop through */ + + case DEF_SPECNET_FIXEDBUMP: + /* Ignore this keyword */ + break; + + + } + } + else if (!strcmp(token, "RECT")) + { + /* NOTE: Use of "RECT" in NETS is not in the LEF/DEF spec. */ + /* However, its use has been seen. So "special" is not */ + /* checked here. */ + + /* Read an (llx lly urx ury) rectangle */ + token = LefNextToken(f, TRUE); /* read llx */ + if (*token == '(') token = LefNextToken(f, TRUE); + if (sscanf(token, "%f", &x) == 1) + { + locarea.r_xbot = (int)roundf((2 * x) / oscale); + } + else + { + LefError(DEF_ERROR, "Cannot parse X coordinate in RECT.\n"); + goto endCoord; + } + + token = LefNextToken(f, TRUE); /* read lly */ + if (sscanf(token, "%f", &y) == 1) + { + locarea.r_ybot = (int)roundf((2 * y) / oscale); + } + else + { + LefError(DEF_ERROR, "Cannot parse Y coordinate in RECT.\n"); + goto endCoord; + } + + token = LefNextToken(f, TRUE); /* read urx */ + if (sscanf(token, "%f", &x) == 1) + { + locarea.r_xtop = (int)roundf((2 * x) / oscale); + } + else + { + LefError(DEF_ERROR, "Cannot parse X coordinate in RECT.\n"); + goto endCoord; + } + token = LefNextToken(f, TRUE); /* read ury */ + if (sscanf(token, "%f", &y) == 1) + { + locarea.r_ytop = (int)roundf((2 * y) / oscale); + } + else + { + LefError(DEF_ERROR, "Cannot parse Y coordinate in RECT.\n"); + goto endCoord; + } + token = LefNextToken(f, TRUE); /* read closing parens */ + if (*token != ')') + { + LefError(DEF_ERROR, "Bad coordinates in RECT.\n"); + goto endCoord; + } + } + else if (!strcmp(token, "POLYGON")) + { + LefError(DEF_ERROR, "Route has POLYGON entries, this is not handled!\n", + token); + token = LefNextToken(f, TRUE); /* read opening parens */ + goto endCoord; + } + else if (!strcmp(token, "VIRTUAL")) + { + /* Is this a LEF 5.8 thing? Not sure if it should be ignored! */ + /* Should the whole wire leg be ignored? */ + continue; + } else if (*token != '(') /* via name */ { /* A '+' or ';' record ends the route */ @@ -256,7 +436,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) locarea.r_xbot = refp.p_x; locarea.r_ybot = refp.p_y; - /* Read an (X Y) point */ + /* Read an (X Y [extend]) point */ token = LefNextToken(f, TRUE); /* read X */ if (*token == '*') { @@ -301,7 +481,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) /* is apparently how everyone interprets it, and is true for */ /* 5.6 spec. */ - z = (special) ? 0 : paintWidth; + extend = (special) ? 0 : paintWidth; token = LefNextToken(f, TRUE); if (*token != ')') { @@ -313,7 +493,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) /* to multiply up by 2 now. */ else - z *= 2; + extend = (int)roundf((2 * z) / oscale); } /* Indicate that we have a valid reference point */ @@ -351,8 +531,8 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) } else { - newRoute->r_r.r_xbot -= z; - newRoute->r_r.r_xtop += z; + newRoute->r_r.r_xbot -= extend; + newRoute->r_r.r_xtop += extend; } if (newRoute->r_r.r_ybot == newRoute->r_r.r_ytop) @@ -362,8 +542,8 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) } else { - newRoute->r_r.r_ybot -= z; - newRoute->r_r.r_ytop += z; + newRoute->r_r.r_ybot -= extend; + newRoute->r_r.r_ytop += extend; } /* If we don't have integer units here, we should */ @@ -431,8 +611,8 @@ endCoord: enum def_net_keys {DEF_NET_START = 0, DEF_NET_END}; enum def_netprop_keys { DEF_NETPROP_USE = 0, DEF_NETPROP_ROUTED, DEF_NETPROP_FIXED, - DEF_NETPROP_COVER, DEF_NETPROP_SOURCE, DEF_NETPROP_SHAPE, - DEF_NETPROP_WEIGHT, DEF_NETPROP_PROPERTY}; + DEF_NETPROP_COVER, DEF_NETPROP_SOURCE, DEF_NETPROP_WEIGHT, + DEF_NETPROP_PROPERTY}; void DefReadNets(f, rootDef, sname, oscale, special, total) @@ -460,7 +640,6 @@ DefReadNets(f, rootDef, sname, oscale, special, total) "FIXED", "COVER", "SOURCE", - "SHAPE", "WEIGHT", "PROPERTY", NULL @@ -517,7 +696,6 @@ DefReadNets(f, rootDef, sname, oscale, special, total) switch (subkey) { case DEF_NETPROP_USE: - case DEF_NETPROP_SHAPE: /* Presently, we ignore this, except to */ /* absorb the following value. */ token = LefNextToken(f, TRUE); @@ -697,7 +875,8 @@ enum def_pins_keys {DEF_PINS_START = 0, DEF_PINS_END}; enum def_pins_prop_keys { DEF_PINS_PROP_NET = 0, DEF_PINS_PROP_DIR, DEF_PINS_PROP_LAYER, DEF_PINS_PROP_USE, - DEF_PINS_PROP_PLACED, DEF_PINS_PROP_FIXED}; + DEF_PINS_PROP_PLACED, DEF_PINS_PROP_FIXED, + DEF_PINS_PROP_PORT, DEF_PINS_PROP_SPECIAL}; void DefReadPins(f, rootDef, sname, oscale, total) @@ -718,6 +897,7 @@ DefReadPins(f, rootDef, sname, oscale, total) Transform t; lefLayer *lefl; bool pending = FALSE; + bool hasports = FALSE; static char *pin_keys[] = { "-", @@ -732,6 +912,8 @@ DefReadPins(f, rootDef, sname, oscale, total) "USE", "PLACED", "FIXED", + "PORT", + "SPECIAL", NULL }; @@ -768,6 +950,7 @@ DefReadPins(f, rootDef, sname, oscale, total) switch (keyword) { case DEF_PINS_START: /* "-" keyword */ + hasports = FALSE; // Flag an error if a pin was waiting on a layer // specification that was never given. @@ -804,12 +987,24 @@ DefReadPins(f, rootDef, sname, oscale, total) subkey = Lookup(token, pin_property_keys); if (subkey < 0) { - LefError(DEF_ERROR, "Unknown pin property \"%s\" in " + LefError(DEF_INFO, "Unknown pin property \"%s\" in " "PINS definition; ignoring.\n", token); continue; } switch (subkey) { + case DEF_PINS_PROP_SPECIAL: + /* Ignore this */ + break; + case DEF_PINS_PROP_PORT: + /* Ignore this, except that each port adds to */ + /* the count of total pins processed. Note */ + /* that since "processed" is incremented before */ + /* the first PORT is seen, then "processed" */ + /* should not be incremented until the 2nd PORT */ + if (hasports) processed++; + hasports = TRUE; + break; case DEF_PINS_PROP_USE: case DEF_PINS_PROP_NET: /* Get the net name, but ignore it */ @@ -909,7 +1104,10 @@ DefReadPins(f, rootDef, sname, oscale, total) enum def_vias_keys {DEF_VIAS_START = 0, DEF_VIAS_END}; enum def_vias_prop_keys { - DEF_VIAS_PROP_RECT = 0}; + DEF_VIAS_PROP_RECT = 0, DEF_VIAS_PROP_VIARULE, + DEF_VIAS_PROP_CUTSIZE, DEF_VIAS_PROP_LAYERS, + DEF_VIAS_PROP_CUTSPACING, DEF_VIAS_PROP_ENCLOSURE, + DEF_VIAS_PROP_ROWCOL}; void DefReadVias(f, sname, oscale, total) @@ -927,6 +1125,13 @@ DefReadVias(f, sname, oscale, total) lefLayer *lefl; HashEntry *he; + /* For generated vias */ + bool generated = FALSE; + int sizex, sizey, spacex, spacey; + int encbx, encby, enctx, encty; + int rows = 1, cols = 1; + TileType tlayer, clayer, blayer; + static char *via_keys[] = { "-", "END", @@ -935,6 +1140,12 @@ DefReadVias(f, sname, oscale, total) static char *via_property_keys[] = { "RECT", + "VIARULE", + "CUTSIZE", + "LAYERS", + "CUTSPACING", + "ENCLOSURE", + "ROWCOL", NULL }; @@ -991,7 +1202,17 @@ DefReadVias(f, sname, oscale, total) while ((token = LefNextToken(f, TRUE)) != NULL) { - if (*token == ';') break; + if (*token == ';') { + if (generated == TRUE) { + /* Complete the generated via */ + LefGenViaGeometry(f, lefl, + sizex, sizey, spacex, spacey, + encbx, encby, enctx, encty, + rows, cols, tlayer, clayer, blayer, + oscale); + } + break; + } if (*token != '+') continue; token = LefNextToken(f, TRUE); @@ -1008,6 +1229,90 @@ DefReadVias(f, sname, oscale, total) curlayer = LefReadLayer(f, FALSE); LefAddViaGeometry(f, lefl, curlayer, oscale); break; + + case DEF_VIAS_PROP_VIARULE: + token = LefNextToken(f, TRUE); + /* Ignore this. To do: Parse VIARULE statements */ + /* and use the rule to fill any missing values. */ + break; + case DEF_VIAS_PROP_CUTSIZE: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &sizex) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for CUTSIZE.\n"); + /* To do: Get cut size from DRC ruleset */ + } + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &sizey) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for CUTSIZE.\n"); + /* To do: Get cut size from DRC ruleset */ + } + generated = TRUE; + break; + case DEF_VIAS_PROP_LAYERS: + blayer = LefReadLayer(f, FALSE); + clayer = LefReadLayer(f, FALSE); + tlayer = LefReadLayer(f, FALSE); + generated = TRUE; + break; + case DEF_VIAS_PROP_CUTSPACING: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &spacex) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for CUTSPACING.\n"); + /* To do: Get cut spacing from DRC ruleset */ + } + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &spacey) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for CUTSPACING.\n"); + /* To do: Get cut spacing from DRC ruleset */ + } + generated = TRUE; + break; + case DEF_VIAS_PROP_ENCLOSURE: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &enctx) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for ENCLOSURE.\n"); + /* To do: Get cut enclosures from DRC ruleset */ + } + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &encty) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for ENCLOSURE.\n"); + /* To do: Get cut enclosures from DRC ruleset */ + } + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &encbx) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for ENCLOSURE.\n"); + /* To do: Get cut enclosures from DRC ruleset */ + } + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &encby) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for ENCLOSURE.\n"); + /* To do: Get cut enclosures from DRC ruleset */ + } + generated = TRUE; + break; + case DEF_VIAS_PROP_ROWCOL: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &rows) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for ROWCOL.\n"); + rows = 1; + } + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &cols) != 1) + { + LefError(DEF_ERROR, "Invalid syntax for ROWCOL.\n"); + cols = 1; + } + generated = TRUE; + break; } } break; diff --git a/lef/lefInt.h b/lef/lefInt.h index 8f069404..9c31dd80 100644 --- a/lef/lefInt.h +++ b/lef/lefInt.h @@ -126,6 +126,7 @@ LinkedRect *LefReadGeometry(); void LefEstimate(); lefLayer *LefRedefined(); void LefAddViaGeometry(); +void LefGenViaGeometry(); Rect *LefReadRect(); TileType LefReadLayer(); diff --git a/lef/lefRead.c b/lef/lefRead.c index 43ef32d9..95479743 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -1729,6 +1729,100 @@ origin_error: &DBAllButSpaceBits); } +/* + *------------------------------------------------------------ + * + * LefGenViaGeometry -- + * + * Create geometry for a VIA section from a DEF file + * using via generation parameters. + * + * Results: + * None. + * + * Side Effects: + * Adds to the lefLayer record for a via definition. + * + *------------------------------------------------------------ + */ + +void +LefGenViaGeometry(f, lefl, sizex, sizey, spacex, spacey, + encbx, encby, enctx, encty, rows, cols, + tlayer, clayer, blayer, oscale) + FILE *f; /* LEF file being read */ + lefLayer *lefl; /* pointer to via info */ + int sizex, sizey; /* cut size */ + int spacex, spacey; /* cut spacing */ + int encbx, encby; /* bottom enclosure of cuts */ + int enctx, encty; /* top enclosure of cuts */ + int rows, cols; /* number of cut rows and columns */ + TileType tlayer; /* Top layer type */ + TileType clayer; /* Cut layer type */ + TileType blayer; /* Bottom layer type */ + float oscale; /* output scaling */ +{ + Rect rect; + int i, j, x, y, w, h, sw, sh; + LinkedRect *viaLR; + + /* Compute top layer rect */ + + w = (sizex * cols) + (spacex * (cols - 1)) + 2 * enctx; + h = (sizey * rows) + (spacey * (rows - 1)) + 2 * encty; + + rect.r_xtop = (int)roundf(w / oscale); + rect.r_xbot = -rect.r_xtop; + rect.r_ytop = (int)roundf(h / oscale); + rect.r_ybot = -rect.r_ytop; + + /* Set via area to the top layer */ + lefl->info.via.area = rect; + lefl->type = tlayer; + + /* Compute bottom layer rect */ + + w = (sizex * cols) + (spacex * (cols - 1)) + 2 * encbx; + h = (sizey * rows) + (spacey * (rows - 1)) + 2 * encby; + + rect.r_xtop = (int)roundf(w / oscale); + rect.r_xbot = -rect.r_xtop; + rect.r_ytop = (int)roundf(h / oscale); + rect.r_ybot = -rect.r_ytop; + + viaLR = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + viaLR->r_next = lefl->info.via.lr; + lefl->info.via.lr = viaLR; + viaLR->r_type = tlayer; + viaLR->r_r = rect; + + w = (sizex * cols) + (spacex * (cols - 1)); + h = (sizey * rows) + (spacey * (rows - 1)); + x = -w / 2; + y = -h / 2; + + for (i = 0; i < cols; i++) + { + for (j = 0; j < rows; j++) + { + rect.r_xbot = (int)roundf(x / oscale); + rect.r_ybot = (int)roundf(y / oscale); + rect.r_xtop = rect.r_xbot + (int)roundf(sizex / oscale); + rect.r_ytop = rect.r_ybot + (int)roundf(sizey / oscale); + + viaLR = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + viaLR->r_next = lefl->info.via.lr; + lefl->info.via.lr = viaLR; + viaLR->r_type = clayer; + viaLR->r_r = rect; + + y += sizey + spacey; + } + x += sizex + spacex; + y = -h / 2; + } +} + /* *------------------------------------------------------------ * From 38fa141db57ff29c5c1a113a13a0256b91357b59 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 3 Jul 2019 14:05:01 -0400 Subject: [PATCH 2/5] One minor correction to the creation of generated vias in defRead.c. --- lef/lefRead.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lef/lefRead.c b/lef/lefRead.c index 95479743..6986135c 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -1765,6 +1765,7 @@ LefGenViaGeometry(f, lefl, sizex, sizey, spacex, spacey, Rect rect; int i, j, x, y, w, h, sw, sh; LinkedRect *viaLR; + float hscale = oscale / 2; /* Compute top layer rect */ @@ -1805,10 +1806,10 @@ LefGenViaGeometry(f, lefl, sizex, sizey, spacex, spacey, { for (j = 0; j < rows; j++) { - rect.r_xbot = (int)roundf(x / oscale); - rect.r_ybot = (int)roundf(y / oscale); - rect.r_xtop = rect.r_xbot + (int)roundf(sizex / oscale); - rect.r_ytop = rect.r_ybot + (int)roundf(sizey / oscale); + rect.r_xbot = (int)roundf(x / hscale); + rect.r_ybot = (int)roundf(y / hscale); + rect.r_xtop = rect.r_xbot + (int)roundf(sizex / hscale); + rect.r_ytop = rect.r_ybot + (int)roundf(sizey / hscale); viaLR = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); viaLR->r_next = lefl->info.via.lr; From 5ba84b068abb29c3ebcbb3566c93a43e91ac03a5 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 3 Jul 2019 14:24:52 -0400 Subject: [PATCH 3/5] Was missing needed expansion of via cut sizes to match magic's internal definition of via areas, when reading parameterized vias from a DEF file. --- lef/lefRead.c | 181 ++++++++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 81 deletions(-) diff --git a/lef/lefRead.c b/lef/lefRead.c index 6986135c..3b5e7cbf 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -1729,6 +1729,101 @@ origin_error: &DBAllButSpaceBits); } +/* + *------------------------------------------------------------ + * + * LefGrowVia --- + * + * For LEF contact types matching magic contact types, size the + * LEF contact cut to cover the minimum rectangle in the other + * layers that satisfies the CIF/GDS contact generation. Use + * the "cifinput" style to determine how much the via layer + * needs to grow to make a contact area. If the "cifinput" + * style is not defined, then determine rules from "cifoutput". + * + *------------------------------------------------------------ + */ + +void LefGrowVia(curlayer, currect, lefl) + TileType curlayer; + Rect *currect; + lefLayer *lefl; +{ + if (DBIsContact(curlayer) && cifCurReadStyle != NULL) + { + int growSize; + + /* Get the amount (in magic units) that the layer needs to */ + /* expand according to the "cifinput" style rules to convert */ + /* a contact cut to a magic contact layer. */ + + growSize = CIFReadGetGrowSize(curlayer); + + /* All internal LEF via geometry values are doubled */ + growSize <<= 1; + + if (growSize % cifCurReadStyle->crs_scaleFactor == 0) + growSize /= cifCurReadStyle->crs_scaleFactor; + else + growSize = growSize / cifCurReadStyle->crs_scaleFactor + 1; + + if (growSize > 0) + { + /* cifinput styles expect the cut size to be correct, so */ + /* there is no check for correctness of the layer. */ + + currect->r_xbot = currect->r_xbot - growSize; + currect->r_ybot = currect->r_ybot - growSize; + currect->r_xtop = currect->r_xtop + growSize; + currect->r_ytop = currect->r_ytop + growSize; + } + } + else if (DBIsContact(curlayer) && CIFCurStyle != NULL) + { + int edgeSize = 0, contSize, halfSize; + + /* Get the minimum size of a contact (cut + borders) from cifoutput */ + contSize = CIFGetContactSize(curlayer, &edgeSize, NULL, NULL); + + /* All internal LEF via geometry values are doubled */ + contSize <<= 1; + edgeSize <<= 1; + + if (contSize % CIFCurStyle->cs_scaleFactor == 0) + contSize /= CIFCurStyle->cs_scaleFactor; + else + contSize = contSize / CIFCurStyle->cs_scaleFactor + 1; + + if (edgeSize % CIFCurStyle->cs_scaleFactor == 0) + edgeSize /= CIFCurStyle->cs_scaleFactor; + else + edgeSize = edgeSize / CIFCurStyle->cs_scaleFactor + 1; + + if (edgeSize > 0 && contSize > 0) + { + /* Flag a warning if the cut size is different from what's expected */ + if ((currect->r_xtop - currect->r_xbot != edgeSize) || + (currect->r_ytop - currect->r_ybot != edgeSize)) + { + LefError(LEF_WARNING, "Cut size for magic type \"%s\" (%d x %d) does " + "not match LEF/DEF\n", + DBTypeLongNameTbl[lefl->type], + edgeSize, edgeSize); + LefError(LEF_WARNING, "Via cut size (%d x %d). Magic layer " + "cut size will be used!\n", + currect->r_xtop - currect->r_xbot, + currect->r_ytop - currect->r_ybot); + } + + halfSize = contSize >> 1; + currect->r_xbot = ((currect->r_xbot + currect->r_xtop) / 2) - halfSize; + currect->r_ybot = ((currect->r_ybot + currect->r_ytop) / 2) - halfSize; + currect->r_xtop = currect->r_xbot + contSize; + currect->r_ytop = currect->r_ybot + contSize; + } + } +} + /* *------------------------------------------------------------ * @@ -1811,6 +1906,9 @@ LefGenViaGeometry(f, lefl, sizex, sizey, spacex, spacey, rect.r_xtop = rect.r_xbot + (int)roundf(sizex / hscale); rect.r_ytop = rect.r_ybot + (int)roundf(sizey / hscale); + /* Expand via to the size used by magic */ + LefGrowVia(clayer, &rect, lefl); + viaLR = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); viaLR->r_next = lefl->info.via.lr; lefl->info.via.lr = viaLR; @@ -1858,87 +1956,8 @@ LefAddViaGeometry(f, lefl, curlayer, oscale) /* Don't create any geometry for unknown layers! */ if (curlayer < 0) return; - /* For LEF contact types matching magic contact types, */ - /* size the LEF contact cut to cover the minimum */ - /* rectangle in the other layers that satisfies the */ - /* CIF/GDS contact generation. Use the "cifinput" style */ - /* to determine how much the via layer needs to grow to */ - /* make a contact area. If the "cifinput" style is not */ - /* defined, then determine rules from "cifoutput". */ - - if (DBIsContact(curlayer) && cifCurReadStyle != NULL) - { - int growSize; - - /* Get the amount (in magic units) that the layer needs to */ - /* expand according to the "cifinput" style rules to convert */ - /* a contact cut to a magic contact layer. */ - - growSize = CIFReadGetGrowSize(curlayer); - - /* All internal LEF via geometry values are doubled */ - growSize <<= 1; - - if (growSize % cifCurReadStyle->crs_scaleFactor == 0) - growSize /= cifCurReadStyle->crs_scaleFactor; - else - growSize = growSize / cifCurReadStyle->crs_scaleFactor + 1; - - if (growSize > 0) - { - /* cifinput styles expect the cut size to be correct, so */ - /* there is no check for correctness of the layer. */ - - currect->r_xbot = currect->r_xbot - growSize; - currect->r_ybot = currect->r_ybot - growSize; - currect->r_xtop = currect->r_xtop + growSize; - currect->r_ytop = currect->r_ytop + growSize; - } - } - else if (DBIsContact(curlayer) && CIFCurStyle != NULL) - { - int edgeSize = 0, contSize, halfSize; - - /* Get the minimum size of a contact (cut + borders) from cifoutput */ - contSize = CIFGetContactSize(curlayer, &edgeSize, NULL, NULL); - - /* All internal LEF via geometry values are doubled */ - contSize <<= 1; - edgeSize <<= 1; - - if (contSize % CIFCurStyle->cs_scaleFactor == 0) - contSize /= CIFCurStyle->cs_scaleFactor; - else - contSize = contSize / CIFCurStyle->cs_scaleFactor + 1; - - if (edgeSize % CIFCurStyle->cs_scaleFactor == 0) - edgeSize /= CIFCurStyle->cs_scaleFactor; - else - edgeSize = edgeSize / CIFCurStyle->cs_scaleFactor + 1; - - if (edgeSize > 0 && contSize > 0) - { - /* Flag a warning if the cut size is different from what's expected */ - if ((currect->r_xtop - currect->r_xbot != edgeSize) || - (currect->r_ytop - currect->r_ybot != edgeSize)) - { - LefError(LEF_WARNING, "Cut size for magic type \"%s\" (%d x %d) does " - "not match LEF/DEF\n", - DBTypeLongNameTbl[lefl->type], - edgeSize, edgeSize); - LefError(LEF_WARNING, "Via cut size (%d x %d). Magic layer " - "cut size will be used!\n", - currect->r_xtop - currect->r_xbot, - currect->r_ytop - currect->r_ybot); - } - - halfSize = contSize >> 1; - currect->r_xbot = ((currect->r_xbot + currect->r_xtop) / 2) - halfSize; - currect->r_ybot = ((currect->r_ybot + currect->r_ytop) / 2) - halfSize; - currect->r_xtop = currect->r_xbot + contSize; - currect->r_ytop = currect->r_ybot + contSize; - } - } + /* Expand via to the size used by magic */ + LefGrowVia(curlayer, currect, lefl); if (GEO_SAMERECT(lefl->info.via.area, GeoNullRect)) { From 0141ca8c95fc4a661ae29fd9d83501b74eb9605a Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 3 Jul 2019 14:52:22 -0400 Subject: [PATCH 4/5] Corrected error in generated vias (set top layer type on bottom, so bottom layer went missing). --- lef/defRead.c | 25 ++++++++++++++++++++----- lef/lefRead.c | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lef/defRead.c b/lef/defRead.c index 5dadbfd4..ed824a25 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -86,7 +86,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) bool valid = FALSE; /* is there a valid reference point? */ bool initial = TRUE; Rect locarea; - int extend; + int extend, lextend, hextend; float x, y, z, w; int routeWidth, paintWidth, saveWidth; TileType routeLayer, paintLayer; @@ -435,6 +435,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) /* Record current reference point */ locarea.r_xbot = refp.p_x; locarea.r_ybot = refp.p_y; + lextend = extend; /* Read an (X Y [extend]) point */ token = LefNextToken(f, TRUE); /* read X */ @@ -510,6 +511,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) LefError(DEF_ERROR, "Can't deal with nonmanhattan geometry in route.\n"); locarea.r_xbot = refp.p_x; locarea.r_ybot = refp.p_y; + lextend = extend; } else { @@ -522,6 +524,19 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) locarea.r_xtop = refp.p_x; locarea.r_ytop = refp.p_y; + /* Change route segment to a canonical rectangle. If */ + /* the route is flipped relative to canonical coords, */ + /* then the wire extentions have to be swapped as well. */ + + if ((locarea.r_xtop < locarea.r_xbot) || + (locarea.r_ytop < locarea.r_ybot)) + { + hextend = lextend; + lextend = extend; + } + else + hextend = extend; + GeoCanonicalRect(&locarea, &newRoute->r_r); if (newRoute->r_r.r_xbot == newRoute->r_r.r_xtop) @@ -531,8 +546,8 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) } else { - newRoute->r_r.r_xbot -= extend; - newRoute->r_r.r_xtop += extend; + newRoute->r_r.r_xbot -= lextend; + newRoute->r_r.r_xtop += hextend; } if (newRoute->r_r.r_ybot == newRoute->r_r.r_ytop) @@ -542,8 +557,8 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) } else { - newRoute->r_r.r_ybot -= extend; - newRoute->r_r.r_ytop += extend; + newRoute->r_r.r_ybot -= lextend; + newRoute->r_r.r_ytop += hextend; } /* If we don't have integer units here, we should */ diff --git a/lef/lefRead.c b/lef/lefRead.c index 3b5e7cbf..a212aecf 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -1889,7 +1889,7 @@ LefGenViaGeometry(f, lefl, sizex, sizey, spacex, spacey, viaLR = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); viaLR->r_next = lefl->info.via.lr; lefl->info.via.lr = viaLR; - viaLR->r_type = tlayer; + viaLR->r_type = blayer; viaLR->r_r = rect; w = (sizex * cols) + (spacex * (cols - 1)); From d839cc26e287dd07ef705c71921ee15134b25b63 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 3 Jul 2019 15:36:21 -0400 Subject: [PATCH 5/5] One last problem fixed, as RECT entries in nets are relative, not absolute. --- lef/defRead.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lef/defRead.c b/lef/defRead.c index ed824a25..ab8cdfda 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -246,12 +246,17 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) /* However, its use has been seen. So "special" is not */ /* checked here. */ + /* The rectangle coordinates are relative to the current */ + /* reference point, not absolute. */ + + newRoute = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + /* Read an (llx lly urx ury) rectangle */ token = LefNextToken(f, TRUE); /* read llx */ if (*token == '(') token = LefNextToken(f, TRUE); if (sscanf(token, "%f", &x) == 1) { - locarea.r_xbot = (int)roundf((2 * x) / oscale); + locarea.r_xbot = (refp.p_x / 2) + (int)roundf(x / oscale); } else { @@ -262,7 +267,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) token = LefNextToken(f, TRUE); /* read lly */ if (sscanf(token, "%f", &y) == 1) { - locarea.r_ybot = (int)roundf((2 * y) / oscale); + locarea.r_ybot = (refp.p_y / 2) + (int)roundf(y / oscale); } else { @@ -273,7 +278,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) token = LefNextToken(f, TRUE); /* read urx */ if (sscanf(token, "%f", &x) == 1) { - locarea.r_xtop = (int)roundf((2 * x) / oscale); + locarea.r_xtop = (refp.p_x / 2) + (int)roundf(x / oscale); } else { @@ -283,7 +288,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) token = LefNextToken(f, TRUE); /* read ury */ if (sscanf(token, "%f", &y) == 1) { - locarea.r_ytop = (int)roundf((2 * y) / oscale); + locarea.r_ytop = (refp.p_y / 2) + (int)roundf(y / oscale); } else { @@ -296,6 +301,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) LefError(DEF_ERROR, "Bad coordinates in RECT.\n"); goto endCoord; } + GeoCanonicalRect(&locarea, &newRoute->r_r); } else if (!strcmp(token, "POLYGON")) {