Implemented non-default rules for DEF reads. This is in preparation

for using such non-default rules for "def write" to capture any
layout geometry that is not a "special net" and does not have the
default wire width.
This commit is contained in:
Tim Edwards 2022-03-23 17:08:39 -04:00
parent 59b68606e0
commit 645a872967
2 changed files with 161 additions and 43 deletions

View File

@ -74,12 +74,13 @@ enum def_netspecial_shape_keys {
DEF_SPECNET_SHAPE_DRCFILL}; DEF_SPECNET_SHAPE_DRCFILL};
char * char *
DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap) DefAddRoutes(rootDef, f, oscale, special, netname, ruleset, defLayerMap)
CellDef *rootDef; /* Cell to paint */ CellDef *rootDef; /* Cell to paint */
FILE *f; /* Input file */ FILE *f; /* Input file */
float oscale; /* Scale factor between LEF and magic units */ float oscale; /* Scale factor between LEF and magic units */
bool special; /* True if this section is SPECIALNETS */ bool special; /* True if this section is SPECIALNETS */
char *netname; /* Name of the net, if net is to be labeled */ char *netname; /* Name of the net, if net is to be labeled */
LefRules *ruleset; /* Non-default rule, or NULL */
LefMapping *defLayerMap; /* magic-to-lef layer mapping array */ LefMapping *defLayerMap; /* magic-to-lef layer mapping array */
{ {
char *token; char *token;
@ -97,12 +98,7 @@ DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
lefLayer *lefl = NULL; lefLayer *lefl = NULL;
lefRule *rule = NULL; lefRule *rule = NULL;
int keyword; int keyword;
bool is_taper = FALSE, end_taper = FALSE;
static char *regnet_keys[] = {
"STYLE",
"TAPER",
"TAPERRULE",
};
static char *specnet_keys[] = { static char *specnet_keys[] = {
"SHAPE", "SHAPE",
@ -189,11 +185,17 @@ DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
DEFAULT_WIDTH * DBLambda[1] / DBLambda[0]; DEFAULT_WIDTH * DBLambda[1] / DBLambda[0];
saveWidth = paintWidth; saveWidth = paintWidth;
} }
else if (rule)
paintWidth = rule->width;
else else
paintWidth = (lefl) ? lefl->info.route.width : {
if (ruleset)
for (rule = ruleset->rule; rule; rule = rule->next)
if (rule->lefInfo == lefl)
break;
paintWidth = (rule) ? rule->width :
(lefl) ? lefl->info.route.width :
DEFAULT_WIDTH * DBLambda[1] / DBLambda[0]; DEFAULT_WIDTH * DBLambda[1] / DBLambda[0];
}
} }
else if ((*token == '+') && (special == TRUE)) else if ((*token == '+') && (special == TRUE))
{ {
@ -250,8 +252,6 @@ DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
case DEF_SPECNET_FIXEDBUMP: case DEF_SPECNET_FIXEDBUMP:
/* Ignore this keyword */ /* Ignore this keyword */
break; break;
} }
} }
else if (!strcmp(token, "RECT")) else if (!strcmp(token, "RECT"))
@ -335,6 +335,7 @@ DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
/* Return to the default width for this layer */ /* Return to the default width for this layer */
paintWidth = (lefl) ? lefl->info.route.width : paintWidth = (lefl) ? lefl->info.route.width :
DEFAULT_WIDTH * DBLambda[1] / DBLambda[0]; DEFAULT_WIDTH * DBLambda[1] / DBLambda[0];
is_taper = TRUE;
} }
else if (!strcmp(token, "TAPERRULE")) else if (!strcmp(token, "TAPERRULE"))
{ {
@ -343,14 +344,28 @@ DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
he = HashLookOnly(&LefNonDefaultRules, token); he = HashLookOnly(&LefNonDefaultRules, token);
if (he != NULL) if (he != NULL)
{ {
rule = (lefRule *)HashGetValue(he); LefRules *tempruleset = (LefRules *)HashGetValue(he);
paintWidth = rule->width; for (rule = tempruleset->rule; rule; rule = rule->next)
if (rule->lefInfo == lefl)
break;
if (rule) paintWidth = rule->width;
is_taper = TRUE;
}
else if (!strcmp(token, "DEFAULT"))
{
paintWidth = (lefl) ? lefl->info.route.width :
DEFAULT_WIDTH * DBLambda[1] / DBLambda[0];
is_taper = TRUE;
} }
else else
LefError(DEF_ERROR, "Unknown nondefault rule \"%s\"\n", token); LefError(DEF_ERROR, "Unknown nondefault rule \"%s\"\n", token);
} }
else if (*token != '(') /* via name */ else if (*token != '(') /* via name */
{ {
/* A via directly after a taper rule would cancel the taper rule */
is_taper = FALSE;
/* A '+' or ';' record ends the route */ /* A '+' or ';' record ends the route */
if (*token == ';' || *token == '+') if (*token == ';' || *token == '+')
break; break;
@ -536,6 +551,8 @@ DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
extend = (int)roundf((2 * z) / oscale); extend = (int)roundf((2 * z) / oscale);
} }
end_taper = ((valid == TRUE) && (is_taper == TRUE)) ? TRUE : FALSE;
/* Indicate that we have a valid reference point */ /* Indicate that we have a valid reference point */
if (valid == FALSE) if (valid == FALSE)
@ -609,6 +626,24 @@ DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
newRoute->r_r.r_ytop >>= 1; newRoute->r_r.r_ytop >>= 1;
} }
/* If a taper rule was in effect and we have a valid */
/* segment, reset the width after creating the segment. */
if (end_taper)
{
is_taper = FALSE;
end_taper = FALSE;
rule = NULL;
if (ruleset)
for (rule = ruleset->rule; rule; rule = rule->next)
if (rule->lefInfo == lefl)
break;
paintWidth = (rule) ? rule->width :
(lefl) ? lefl->info.route.width :
DEFAULT_WIDTH * DBLambda[1] / DBLambda[0];
}
endCoord: endCoord:
/* Find the closing parenthesis for the coordinate pair */ /* Find the closing parenthesis for the coordinate pair */
while (*token != ')') while (*token != ')')
@ -677,7 +712,8 @@ enum def_nondefprop_keys {
DEF_NONDEFPROP_VIA, DEF_NONDEFPROP_VIARULE, DEF_NONDEFPROP_VIA, DEF_NONDEFPROP_VIARULE,
DEF_NONDEFPROP_MINCUTS, DEF_NONDEFPROP_PROPERTY, DEF_NONDEFPROP_MINCUTS, DEF_NONDEFPROP_PROPERTY,
DEF_NONDEFLAYER_WIDTH, DEF_NONDEFLAYER_DIAG, DEF_NONDEFLAYER_WIDTH, DEF_NONDEFLAYER_DIAG,
DEF_NONDEFLAYER_SPACE, DEF_NONDEFLAYER_EXT}; DEF_NONDEFLAYER_SPACE, DEF_NONDEFLAYER_EXT,
DEF_NONDEFPROP_DONE};
void void
DefReadNonDefaultRules(f, rootDef, sname, oscale, total) DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
@ -688,13 +724,14 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
int total; int total;
{ {
char *token; char *token;
char *rulename = NULL;
int keyword, subkey; int keyword, subkey;
int processed = 0; int processed = 0;
HashEntry *he; HashEntry *he;
lefLayer *lefl; lefLayer *lefl;
float fvalue; float fvalue;
LefRules *ruleset = NULL;
lefRule *rule = NULL; lefRule *rule = NULL;
bool inlayer;
static char *nondef_keys[] = { static char *nondef_keys[] = {
"-", "-",
@ -713,6 +750,7 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
"DIAGWIDTH", "DIAGWIDTH",
"SPACING", "SPACING",
"WIREEXT", "WIREEXT",
";",
NULL NULL
}; };
@ -733,16 +771,15 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
/* Get non-default rule name */ /* Get non-default rule name */
token = LefNextToken(f, TRUE); token = LefNextToken(f, TRUE);
rulename = StrDup((char **)NULL, token);
/* Create a hash entry for this nondefault rule */ /* Create a hash entry for this nondefault rule */
/* NOTE: Needs to handle name collisions. */ /* NOTE: Needs to handle name collisions. */
he = HashFind(&LefNonDefaultRules, rulename); he = HashFind(&LefNonDefaultRules, token);
rule = (lefRule *)mallocMagic(sizeof(lefRule)); ruleset = (LefRules *)mallocMagic(sizeof(LefRules));
HashSetValue(he, rule); HashSetValue(he, ruleset);
rule->lefInfo = NULL; ruleset->name = StrDup((char **)NULL, token);
rule->width = 0; ruleset->rule = NULL;
rule->spacing = 0; processed++;
/* Process all properties */ /* Process all properties */
while (token && (*token != ';')) while (token && (*token != ';'))
@ -750,10 +787,15 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
if (*token != '+') if (*token != '+')
{ {
token = LefNextToken(f, TRUE); token = LefNextToken(f, TRUE);
continue; if (!inlayer)
continue;
} }
else else
{
inlayer = FALSE;
rule = NULL;
token = LefNextToken(f, TRUE); token = LefNextToken(f, TRUE);
}
subkey = Lookup(token, nondef_property_keys); subkey = Lookup(token, nondef_property_keys);
if (subkey < 0) if (subkey < 0)
@ -764,6 +806,8 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
} }
switch (subkey) switch (subkey)
{ {
case DEF_NONDEFPROP_DONE:
break;
case DEF_NONDEFPROP_HARDSPACING: case DEF_NONDEFPROP_HARDSPACING:
lefl = NULL; lefl = NULL;
/* Ignore this */ /* Ignore this */
@ -776,11 +820,20 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
token = LefNextToken(f, TRUE); token = LefNextToken(f, TRUE);
he = HashFind(&LefInfo, token); he = HashFind(&LefInfo, token);
lefl = (lefLayer *)HashGetValue(he); lefl = (lefLayer *)HashGetValue(he);
if (rule) if (ruleset)
{
/* Chain new layer rule to linked list */
rule = (lefRule *)mallocMagic(sizeof(lefRule));
rule->lefInfo = lefl; rule->lefInfo = lefl;
rule->width = 0;
rule->spacing = 0;
rule->next = ruleset->rule;
ruleset->rule = rule;
}
else else
LefError(DEF_INFO, "No non-default rule name for \"%s\" " LefError(DEF_INFO, "No non-default rule name for \"%s\" "
"in NONDEFAULTRULE definition!.\n", token); "in NONDEFAULTRULE definition!.\n", token);
inlayer = TRUE;
break; break;
case DEF_NONDEFPROP_MINCUTS: case DEF_NONDEFPROP_MINCUTS:
case DEF_NONDEFPROP_PROPERTY: case DEF_NONDEFPROP_PROPERTY:
@ -790,23 +843,34 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
token = LefNextToken(f, TRUE); token = LefNextToken(f, TRUE);
break; break;
case DEF_NONDEFLAYER_WIDTH: case DEF_NONDEFLAYER_WIDTH:
if (!inlayer)
LefError(DEF_INFO, "WIDTH specified without layer.\n");
token = LefNextToken(f, TRUE); token = LefNextToken(f, TRUE);
sscanf(token, "%f", &fvalue); sscanf(token, "%f", &fvalue);
if (lefl == NULL) if (rule == NULL)
LefError(DEF_INFO, "No rule for non-default width.\n");
else if (lefl == NULL)
LefError(DEF_INFO, "No layer for non-default width.\n"); LefError(DEF_INFO, "No layer for non-default width.\n");
else if (lefl->lefClass == CLASS_ROUTE) else
lefl->info.route.width = (int)roundf(fvalue / oscale); rule->width = (int)roundf(fvalue / oscale);
break; break;
case DEF_NONDEFLAYER_SPACE: case DEF_NONDEFLAYER_SPACE:
if (!inlayer)
LefError(DEF_INFO, "SPACING specified without layer.\n");
token = LefNextToken(f, TRUE); token = LefNextToken(f, TRUE);
sscanf(token, "%f", &fvalue); sscanf(token, "%f", &fvalue);
if (lefl == NULL) if (rule == NULL)
LefError(DEF_INFO, "No layer for non-default width.\n"); LefError(DEF_INFO, "No rule for non-default spacing.\n");
else if (lefl->lefClass == CLASS_ROUTE) else if (lefl == NULL)
lefl->info.route.spacing = (int)roundf(fvalue / oscale); LefError(DEF_INFO, "No layer for non-default spacing.\n");
else
rule->spacing = (int)roundf(fvalue / oscale);
break; break;
case DEF_NONDEFLAYER_DIAG: case DEF_NONDEFLAYER_DIAG:
case DEF_NONDEFLAYER_EXT: case DEF_NONDEFLAYER_EXT:
if (!inlayer)
LefError(DEF_INFO,
"Layer value specified without layer.\n");
/* Absorb token and ignore */ /* Absorb token and ignore */
token = LefNextToken(f, TRUE); token = LefNextToken(f, TRUE);
break; break;
@ -851,9 +915,13 @@ DefReadNonDefaultRules(f, rootDef, sname, oscale, total)
enum def_net_keys {DEF_NET_START = 0, DEF_NET_END}; enum def_net_keys {DEF_NET_START = 0, DEF_NET_END};
enum def_netprop_keys { enum def_netprop_keys {
DEF_NETPROP_USE = 0, DEF_NETPROP_ROUTED, DEF_NETPROP_FIXED, DEF_NETPROP_USE = 0, DEF_NETPROP_ROUTED, DEF_NETPROP_NOSHIELD,
DEF_NETPROP_COVER, DEF_NETPROP_SOURCE, DEF_NETPROP_WEIGHT, DEF_NETPROP_FIXED, DEF_NETPROP_COVER, DEF_NETPROP_SOURCE,
DEF_NETPROP_PROPERTY}; DEF_NETPROP_SHIELDNET, DEF_NETPROP_SUBNET, DEF_NETPROP_VPIN,
DEF_NETPROP_XTALK, DEF_NETPROP_NONDEFRULE, DEF_NETPROP_FIXEDBUMP,
DEF_NETPROP_FREQUENCY, DEF_NETPROP_ORIGINAL, DEF_NETPROP_PATTERN,
DEF_NETPROP_ESTCAP, DEF_NETPROP_WEIGHT, DEF_NETPROP_PROPERTY
};
void void
DefReadNets(f, rootDef, sname, oscale, special, dolabels, total) DefReadNets(f, rootDef, sname, oscale, special, dolabels, total)
@ -870,6 +938,8 @@ DefReadNets(f, rootDef, sname, oscale, special, dolabels, total)
int keyword, subkey; int keyword, subkey;
int processed = 0; int processed = 0;
LefMapping *defLayerMap; LefMapping *defLayerMap;
LefRules *ruleset = NULL;
HashEntry *he;
static char *net_keys[] = { static char *net_keys[] = {
"-", "-",
@ -880,9 +950,20 @@ DefReadNets(f, rootDef, sname, oscale, special, dolabels, total)
static char *net_property_keys[] = { static char *net_property_keys[] = {
"USE", "USE",
"ROUTED", "ROUTED",
"NOSHIELD",
"FIXED", "FIXED",
"COVER", "COVER",
"SOURCE", "SOURCE",
"SHIELDNET",
"SUBNET",
"VPIN",
"XTALK",
"NONDEFAULTRULE",
"FIXEDBUMP",
"FREQUENCY",
"ORIGINAL",
"PATTERN",
"ESTCAP",
"WEIGHT", "WEIGHT",
"PROPERTY", "PROPERTY",
NULL NULL
@ -938,16 +1019,53 @@ DefReadNets(f, rootDef, sname, oscale, special, dolabels, total)
} }
switch (subkey) switch (subkey)
{ {
case DEF_NETPROP_USE:
/* Presently, we ignore this, except to */
/* absorb the following value. */
token = LefNextToken(f, TRUE);
break;
case DEF_NETPROP_ROUTED: case DEF_NETPROP_ROUTED:
case DEF_NETPROP_FIXED: case DEF_NETPROP_FIXED:
case DEF_NETPROP_COVER: case DEF_NETPROP_COVER:
case DEF_NETPROP_NOSHIELD:
token = DefAddRoutes(rootDef, f, oscale, special, token = DefAddRoutes(rootDef, f, oscale, special,
netname, defLayerMap); netname, ruleset, defLayerMap);
ruleset = NULL;
break;
case DEF_NETPROP_NONDEFRULE:
token = LefNextToken(f, TRUE);
/*
* Differs from "TAPERRULE" in that it specifies a non-default
* rule to use for the entire net.
*/
he = HashLookOnly(&LefNonDefaultRules, token);
if (he != NULL)
ruleset = (LefRules *)HashGetValue(he);
else
LefError(DEF_ERROR, "Unknown nondefault rule \"%s\"\n", token);
break;
case DEF_NETPROP_PROPERTY:
/* Ignore except to absorb the next two tokens. */
token = LefNextToken(f, TRUE); /* Drop through */
case DEF_NETPROP_SOURCE:
case DEF_NETPROP_USE:
case DEF_NETPROP_SHIELDNET:
case DEF_NETPROP_SUBNET:
case DEF_NETPROP_XTALK:
case DEF_NETPROP_FREQUENCY:
case DEF_NETPROP_ORIGINAL:
case DEF_NETPROP_PATTERN:
case DEF_NETPROP_ESTCAP:
case DEF_NETPROP_WEIGHT:
/* Ignore except to absorb the next token. */
token = LefNextToken(f, TRUE); /* Drop through */
case DEF_NETPROP_FIXEDBUMP:
/* Ignore this keyword */
break;
case DEF_NETPROP_VPIN:
/* VPIN is an in-line pin not in the PINS section */
/* Need to handle this! */
token = LefNextToken(f, TRUE);
break; break;
} }
} }

View File

@ -103,10 +103,11 @@ typedef struct {
/* Structure used for non-default rules. */ /* Structure used for non-default rules. */
typedef struct { typedef struct _lefRule {
lefLayer *lefInfo; /* Layer or via referenced by the rule */ lefLayer *lefInfo; /* Layer or via referenced by the rule */
int width; /* Non-default width value for layer */ int width; /* Non-default width value for layer */
int spacing; /* Non-default spacing value for layer */ int spacing; /* Non-default spacing value for layer */
struct _lefRule *next;
} lefRule; } lefRule;
/* Structure to hold nondefault rules required by nets */ /* Structure to hold nondefault rules required by nets */
@ -114,7 +115,6 @@ typedef struct {
typedef struct { typedef struct {
char *name; char *name;
lefRule *rule; lefRule *rule;
lefRule *next;
} LefRules; } LefRules;
/* Structure holding the counts of regular and special nets */ /* Structure holding the counts of regular and special nets */