Merge branch 'master' into magic-8.2
This commit is contained in:
commit
6d7da2a3da
356
lef/defRead.c
356
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, lextend, hextend;
|
||||
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,141 @@ 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. */
|
||||
|
||||
/* 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 = (refp.p_x / 2) + (int)roundf(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 = (refp.p_y / 2) + (int)roundf(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 = (refp.p_x / 2) + (int)roundf(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 = (refp.p_y / 2) + (int)roundf(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;
|
||||
}
|
||||
GeoCanonicalRect(&locarea, &newRoute->r_r);
|
||||
}
|
||||
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 */
|
||||
|
|
@ -255,8 +441,9 @@ 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) point */
|
||||
/* Read an (X Y [extend]) point */
|
||||
token = LefNextToken(f, TRUE); /* read X */
|
||||
if (*token == '*')
|
||||
{
|
||||
|
|
@ -301,7 +488,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 +500,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 */
|
||||
|
|
@ -330,6 +517,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
|
||||
{
|
||||
|
|
@ -342,6 +530,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)
|
||||
|
|
@ -351,8 +552,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 -= lextend;
|
||||
newRoute->r_r.r_xtop += hextend;
|
||||
}
|
||||
|
||||
if (newRoute->r_r.r_ybot == newRoute->r_r.r_ytop)
|
||||
|
|
@ -362,8 +563,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 -= lextend;
|
||||
newRoute->r_r.r_ytop += hextend;
|
||||
}
|
||||
|
||||
/* If we don't have integer units here, we should */
|
||||
|
|
@ -431,8 +632,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 +661,6 @@ DefReadNets(f, rootDef, sname, oscale, special, total)
|
|||
"FIXED",
|
||||
"COVER",
|
||||
"SOURCE",
|
||||
"SHAPE",
|
||||
"WEIGHT",
|
||||
"PROPERTY",
|
||||
NULL
|
||||
|
|
@ -517,7 +717,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 +896,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 +918,7 @@ DefReadPins(f, rootDef, sname, oscale, total)
|
|||
Transform t;
|
||||
lefLayer *lefl;
|
||||
bool pending = FALSE;
|
||||
bool hasports = FALSE;
|
||||
|
||||
static char *pin_keys[] = {
|
||||
"-",
|
||||
|
|
@ -732,6 +933,8 @@ DefReadPins(f, rootDef, sname, oscale, total)
|
|||
"USE",
|
||||
"PLACED",
|
||||
"FIXED",
|
||||
"PORT",
|
||||
"SPECIAL",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -768,6 +971,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 +1008,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 +1125,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 +1146,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 +1161,12 @@ DefReadVias(f, sname, oscale, total)
|
|||
|
||||
static char *via_property_keys[] = {
|
||||
"RECT",
|
||||
"VIARULE",
|
||||
"CUTSIZE",
|
||||
"LAYERS",
|
||||
"CUTSPACING",
|
||||
"ENCLOSURE",
|
||||
"ROWCOL",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -991,7 +1223,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 +1250,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;
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ LinkedRect *LefReadGeometry();
|
|||
void LefEstimate();
|
||||
lefLayer *LefRedefined();
|
||||
void LefAddViaGeometry();
|
||||
void LefGenViaGeometry();
|
||||
Rect *LefReadRect();
|
||||
TileType LefReadLayer();
|
||||
|
||||
|
|
|
|||
180
lef/lefRead.c
180
lef/lefRead.c
|
|
@ -1732,45 +1732,23 @@ origin_error:
|
|||
/*
|
||||
*------------------------------------------------------------
|
||||
*
|
||||
* LefAddViaGeometry --
|
||||
* LefGrowVia ---
|
||||
*
|
||||
* Read in geometry for a VIA section from a LEF or DEF
|
||||
* file.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Adds to the lefLayer record for a via definition.
|
||||
* 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
|
||||
LefAddViaGeometry(f, lefl, curlayer, oscale)
|
||||
FILE *f; /* LEF file being read */
|
||||
lefLayer *lefl; /* pointer to via info */
|
||||
TileType curlayer; /* current tile type */
|
||||
float oscale; /* output scaling */
|
||||
{
|
||||
void LefGrowVia(curlayer, currect, lefl)
|
||||
TileType curlayer;
|
||||
Rect *currect;
|
||||
LinkedRect *viaLR;
|
||||
|
||||
/* Rectangles for vias are read in units of 1/2 lambda */
|
||||
currect = LefReadRect(f, curlayer, (oscale / 2));
|
||||
if (currect == NULL) return;
|
||||
|
||||
/* 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". */
|
||||
|
||||
lefLayer *lefl;
|
||||
{
|
||||
if (DBIsContact(curlayer) && cifCurReadStyle != NULL)
|
||||
{
|
||||
int growSize;
|
||||
|
|
@ -1844,6 +1822,142 @@ LefAddViaGeometry(f, lefl, curlayer, oscale)
|
|||
currect->r_ytop = currect->r_ybot + contSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------
|
||||
*
|
||||
* 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;
|
||||
float hscale = oscale / 2;
|
||||
|
||||
/* 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 = blayer;
|
||||
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 / 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);
|
||||
|
||||
/* 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;
|
||||
viaLR->r_type = clayer;
|
||||
viaLR->r_r = rect;
|
||||
|
||||
y += sizey + spacey;
|
||||
}
|
||||
x += sizex + spacex;
|
||||
y = -h / 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------
|
||||
*
|
||||
* LefAddViaGeometry --
|
||||
*
|
||||
* Read in geometry for a VIA section from a LEF or DEF
|
||||
* file.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Adds to the lefLayer record for a via definition.
|
||||
*
|
||||
*------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
LefAddViaGeometry(f, lefl, curlayer, oscale)
|
||||
FILE *f; /* LEF file being read */
|
||||
lefLayer *lefl; /* pointer to via info */
|
||||
TileType curlayer; /* current tile type */
|
||||
float oscale; /* output scaling */
|
||||
{
|
||||
Rect *currect;
|
||||
LinkedRect *viaLR;
|
||||
|
||||
/* Rectangles for vias are read in units of 1/2 lambda */
|
||||
currect = LefReadRect(f, curlayer, (oscale / 2));
|
||||
if (currect == NULL) return;
|
||||
|
||||
/* Don't create any geometry for unknown layers! */
|
||||
if (curlayer < 0) return;
|
||||
|
||||
/* Expand via to the size used by magic */
|
||||
LefGrowVia(curlayer, currect, lefl);
|
||||
|
||||
if (GEO_SAMERECT(lefl->info.via.area, GeoNullRect))
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue