Fixed some errors in DEF read/write and added behavior to "def write"
to treat unlabeled/unconnected layout as blockage statements in the output.
This commit is contained in:
parent
645a872967
commit
cf39fb102c
119
lef/defRead.c
119
lef/defRead.c
|
|
@ -1515,6 +1515,119 @@ DefReadPins(f, rootDef, sname, oscale, total)
|
||||||
"the number declared (%d).\n", processed, total);
|
"the number declared (%d).\n", processed, total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DefReadBlockages --
|
||||||
|
*
|
||||||
|
* Read a BLOCKAGES section from a DEF file.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side Effects:
|
||||||
|
* Generates layout
|
||||||
|
*
|
||||||
|
*------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum def_block_keys {DEF_BLOCK_START = 0, DEF_BLOCK_END};
|
||||||
|
enum def_block_prop_keys {
|
||||||
|
DEF_BLOCK_PROP_RECT = 0, DEF_BLOCK_PROP_LAYER};
|
||||||
|
|
||||||
|
void
|
||||||
|
DefReadBlockages(f, rootDef, sname, oscale, total)
|
||||||
|
FILE *f;
|
||||||
|
CellDef *rootDef;
|
||||||
|
char *sname;
|
||||||
|
float oscale;
|
||||||
|
int total;
|
||||||
|
{
|
||||||
|
char *token;
|
||||||
|
int keyword, subkey, values;
|
||||||
|
int processed = 0;
|
||||||
|
TileType curlayer;
|
||||||
|
Rect *currect;
|
||||||
|
lefLayer *lefl;
|
||||||
|
HashEntry *he;
|
||||||
|
|
||||||
|
static char *block_keys[] = {
|
||||||
|
"-",
|
||||||
|
"END",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *block_property_keys[] = {
|
||||||
|
"RECT",
|
||||||
|
"LAYER",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
while ((token = LefNextToken(f, TRUE)) != NULL)
|
||||||
|
{
|
||||||
|
keyword = Lookup(token, block_keys);
|
||||||
|
|
||||||
|
if (keyword < 0)
|
||||||
|
{
|
||||||
|
LefError(DEF_INFO, "Unknown keyword \"%s\" in BLOCKAGES "
|
||||||
|
"definition; ignoring.\n", token);
|
||||||
|
LefEndStatement(f);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (keyword)
|
||||||
|
{
|
||||||
|
case DEF_BLOCK_START: /* "-" keyword */
|
||||||
|
|
||||||
|
/* Update the record of the number of blockages */
|
||||||
|
/* processed and spit out a message for every 5% done. */
|
||||||
|
|
||||||
|
LefEstimate(processed++, total, "blockages");
|
||||||
|
|
||||||
|
while ((token = LefNextToken(f, TRUE)) != NULL)
|
||||||
|
{
|
||||||
|
if (*token == ';')
|
||||||
|
break;
|
||||||
|
|
||||||
|
subkey = Lookup(token, block_property_keys);
|
||||||
|
if (subkey < 0)
|
||||||
|
{
|
||||||
|
LefError(DEF_INFO, "Unknown blockage property \"%s\" in "
|
||||||
|
"BLOCKAGES definition; ignoring.\n", token);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (subkey)
|
||||||
|
{
|
||||||
|
case DEF_BLOCK_PROP_LAYER:
|
||||||
|
curlayer = LefReadLayer(f, TRUE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEF_BLOCK_PROP_RECT:
|
||||||
|
currect = LefReadRect(f, curlayer, oscale);
|
||||||
|
DBPaint(rootDef, currect, curlayer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEF_BLOCK_END:
|
||||||
|
if (!LefParseEndStatement(f, sname))
|
||||||
|
{
|
||||||
|
LefError(DEF_ERROR, "Blockage END statement missing.\n");
|
||||||
|
keyword = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (keyword == DEF_BLOCK_END) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed == total)
|
||||||
|
TxPrintf(" Processed %d blockage%s.\n", processed,
|
||||||
|
((processed > 1) ? "s" : ""));
|
||||||
|
else
|
||||||
|
LefError(DEF_WARNING, "Number of blockages read (%d) does not match "
|
||||||
|
"the number declared (%d).\n", processed, total);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*------------------------------------------------------------
|
*------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -2259,7 +2372,11 @@ DefRead(inName, dolabels)
|
||||||
LefSkipSection(f, sections[DEF_EXTENSION]);
|
LefSkipSection(f, sections[DEF_EXTENSION]);
|
||||||
break;
|
break;
|
||||||
case DEF_BLOCKAGES:
|
case DEF_BLOCKAGES:
|
||||||
LefSkipSection(f, sections[DEF_BLOCKAGES]);
|
token = LefNextToken(f, TRUE);
|
||||||
|
if (sscanf(token, "%d", &total) != 1) total = 0;
|
||||||
|
LefEndStatement(f);
|
||||||
|
DefReadBlockages(f, rootDef, sections[DEF_BLOCKAGES],
|
||||||
|
oscale, total);
|
||||||
break;
|
break;
|
||||||
case DEF_END:
|
case DEF_END:
|
||||||
if (!LefParseEndStatement(token, "DESIGN"))
|
if (!LefParseEndStatement(token, "DESIGN"))
|
||||||
|
|
|
||||||
280
lef/defWrite.c
280
lef/defWrite.c
|
|
@ -52,6 +52,14 @@ typedef struct {
|
||||||
unsigned char specialmode; /* What nets to write as SPECIALNETS */
|
unsigned char specialmode; /* What nets to write as SPECIALNETS */
|
||||||
} DefData;
|
} DefData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CellDef *def;
|
||||||
|
int nlayers;
|
||||||
|
char **baseNames;
|
||||||
|
TileTypeBitMask *blockMasks;
|
||||||
|
LinkedRect **blockData;
|
||||||
|
} DefObsData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float scale;
|
float scale;
|
||||||
int total;
|
int total;
|
||||||
|
|
@ -207,6 +215,7 @@ defCountNets(rootDef, allSpecial)
|
||||||
|
|
||||||
total.regular = (allSpecial) ? -1 : 0;
|
total.regular = (allSpecial) ? -1 : 0;
|
||||||
total.special = 0;
|
total.special = 0;
|
||||||
|
total.blockages = 0;
|
||||||
total.numrules = 0;
|
total.numrules = 0;
|
||||||
total.rules = NULL;
|
total.rules = NULL;
|
||||||
total.has_nets = TRUE;
|
total.has_nets = TRUE;
|
||||||
|
|
@ -253,6 +262,10 @@ defnodeCount(node, res, cap, total)
|
||||||
char ndn[256];
|
char ndn[256];
|
||||||
char *cp, clast;
|
char *cp, clast;
|
||||||
|
|
||||||
|
/* Ignore the substrate node if it is not connected to any routing */
|
||||||
|
if (node->efnode_type == TT_SPACE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Ignore power and ground lines, which we will treat */
|
/* Ignore power and ground lines, which we will treat */
|
||||||
/* as SPECIALNETS types. */
|
/* as SPECIALNETS types. */
|
||||||
|
|
||||||
|
|
@ -310,6 +323,8 @@ defnodeCount(node, res, cap, total)
|
||||||
|
|
||||||
if ((node->efnode_flags & EF_SPECIAL) || (node->efnode_flags & EF_PORT))
|
if ((node->efnode_flags & EF_SPECIAL) || (node->efnode_flags & EF_PORT))
|
||||||
total->special++;
|
total->special++;
|
||||||
|
else
|
||||||
|
total->blockages++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -319,6 +334,8 @@ defnodeCount(node, res, cap, total)
|
||||||
total->special++;
|
total->special++;
|
||||||
else if (node->efnode_flags & EF_PORT)
|
else if (node->efnode_flags & EF_PORT)
|
||||||
total->regular++;
|
total->regular++;
|
||||||
|
else
|
||||||
|
total->blockages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; /* Keep going. . . */
|
return 0; /* Keep going. . . */
|
||||||
|
|
@ -625,6 +642,8 @@ defnodeVisit(node, res, cap, defdata)
|
||||||
{
|
{
|
||||||
if (!(node->efnode_flags & EF_PORT))
|
if (!(node->efnode_flags & EF_PORT))
|
||||||
return 0;
|
return 0;
|
||||||
|
else if (node->efnode_flags & EF_SPECIAL)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else if (defdata->specialmode == DO_SPECIAL)
|
else if (defdata->specialmode == DO_SPECIAL)
|
||||||
{
|
{
|
||||||
|
|
@ -646,6 +665,10 @@ defnodeVisit(node, res, cap, defdata)
|
||||||
TxError("Node mismatch: %s vs. %s\n", ndn, ndn2);
|
TxError("Node mismatch: %s vs. %s\n", ndn, ndn2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Avoid attempting to extract an implicit substrate into DEF */
|
||||||
|
if (node->efnode_type == TT_SPACE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
fprintf(f, " - %s", ndn);
|
fprintf(f, " - %s", ndn);
|
||||||
defdata->outcolumn = 5 + strlen(ndn);
|
defdata->outcolumn = 5 + strlen(ndn);
|
||||||
|
|
||||||
|
|
@ -697,9 +720,6 @@ defnodeVisit(node, res, cap, defdata)
|
||||||
TTMaskZero(&tmask);
|
TTMaskZero(&tmask);
|
||||||
TTMaskSetMask(&tmask, &DBConnectTbl[magictype]);
|
TTMaskSetMask(&tmask, &DBConnectTbl[magictype]);
|
||||||
|
|
||||||
/* Avoid attempting to extract an implicit substrate into DEF */
|
|
||||||
if (node->efnode_type == TT_SPACE) return 0;
|
|
||||||
|
|
||||||
DBSrConnect(def, &node->efnode_loc, &tmask, DBConnectTbl,
|
DBSrConnect(def, &node->efnode_loc, &tmask, DBConnectTbl,
|
||||||
&TiPlaneRect, defNetGeometryFunc,
|
&TiPlaneRect, defNetGeometryFunc,
|
||||||
(ClientData)defdata);
|
(ClientData)defdata);
|
||||||
|
|
@ -1519,7 +1539,7 @@ defCountViaFunc(tile, cviadata)
|
||||||
{
|
{
|
||||||
cviadata->total++; /* Increment the count of uses */
|
cviadata->total++; /* Increment the count of uses */
|
||||||
lefl = (lefLayer *)mallocMagic(sizeof(lefLayer));
|
lefl = (lefLayer *)mallocMagic(sizeof(lefLayer));
|
||||||
lefl->type = ttype;
|
lefl->type = ctype;
|
||||||
lefl->obsType = -1;
|
lefl->obsType = -1;
|
||||||
lefl->lefClass = CLASS_VIA;
|
lefl->lefClass = CLASS_VIA;
|
||||||
lefl->info.via.area = r;
|
lefl->info.via.area = r;
|
||||||
|
|
@ -1664,6 +1684,12 @@ defWriteVias(f, rootDef, oscale, lefMagicToLefLayer)
|
||||||
int i, j, nAc, nUp, pitch, left;
|
int i, j, nAc, nUp, pitch, left;
|
||||||
Rect square, *r = &lefl->info.via.area;
|
Rect square, *r = &lefl->info.via.area;
|
||||||
|
|
||||||
|
/* Scale the area to CIF units */
|
||||||
|
lefl->info.via.area.r_xbot *= oscale;
|
||||||
|
lefl->info.via.area.r_ybot *= oscale;
|
||||||
|
lefl->info.via.area.r_xtop *= oscale;
|
||||||
|
lefl->info.via.area.r_ytop *= oscale;
|
||||||
|
|
||||||
pitch = size + sep;
|
pitch = size + sep;
|
||||||
nAc = (r->r_xtop - r->r_xbot + sep - (2 * border)) / pitch;
|
nAc = (r->r_xtop - r->r_xbot + sep - (2 * border)) / pitch;
|
||||||
if (nAc == 0)
|
if (nAc == 0)
|
||||||
|
|
@ -1701,13 +1727,13 @@ defWriteVias(f, rootDef, oscale, lefMagicToLefLayer)
|
||||||
{
|
{
|
||||||
square.r_xtop = square.r_xbot + size;
|
square.r_xtop = square.r_xbot + size;
|
||||||
|
|
||||||
fprintf(f, "\n + RECT %s ( %.10g %.10g )"
|
fprintf(f, "\n + RECT %s ( %.10g %.10g ) "
|
||||||
" ( %.10g %.10g )",
|
"( %.10g %.10g )",
|
||||||
lefMagicToLefLayer[lefl->type].lefName,
|
lefMagicToLefLayer[lefl->type].lefName,
|
||||||
(float)(square.r_xbot) * oscale / 2,
|
(float)(square.r_xbot / 2),
|
||||||
(float)(square.r_ybot) * oscale / 2,
|
(float)(square.r_ybot / 2),
|
||||||
(float)(square.r_xtop) * oscale / 2,
|
(float)(square.r_xtop / 2),
|
||||||
(float)(square.r_ytop) * oscale / 2);
|
(float)(square.r_ytop / 2));
|
||||||
square.r_xbot += pitch;
|
square.r_xbot += pitch;
|
||||||
}
|
}
|
||||||
square.r_ybot += pitch;
|
square.r_ybot += pitch;
|
||||||
|
|
@ -1837,9 +1863,10 @@ defCountPins(rootDef)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
defWritePins(f, rootDef, oscale)
|
defWritePins(f, rootDef, lefMagicToLefLayer, oscale)
|
||||||
FILE *f; /* File to write to */
|
FILE *f; /* File to write to */
|
||||||
CellDef *rootDef; /* Cell definition to use */
|
CellDef *rootDef; /* Cell definition to use */
|
||||||
|
LefMapping *lefMagicToLefLayer; /* Magic to LEF layer name mapping */
|
||||||
float oscale; /* Output scale factor */
|
float oscale; /* Output scale factor */
|
||||||
{
|
{
|
||||||
Label *lab;
|
Label *lab;
|
||||||
|
|
@ -1902,9 +1929,10 @@ defWritePins(f, rootDef, oscale)
|
||||||
dcenterx = lab->lab_rect.r_xtop + lab->lab_rect.r_xbot;
|
dcenterx = lab->lab_rect.r_xtop + lab->lab_rect.r_xbot;
|
||||||
dcentery = lab->lab_rect.r_ytop + lab->lab_rect.r_ybot;
|
dcentery = lab->lab_rect.r_ytop + lab->lab_rect.r_ybot;
|
||||||
|
|
||||||
|
|
||||||
fprintf(f, " + PORT\n");
|
fprintf(f, " + PORT\n");
|
||||||
fprintf(f, " + LAYER %s ( %.10g %.10g ) ( %.10g %.10g )",
|
fprintf(f, " + LAYER %s ( %.10g %.10g ) ( %.10g %.10g )",
|
||||||
DBTypeLongNameTbl[lab->lab_type],
|
lefMagicToLefLayer[lab->lab_type].lefName,
|
||||||
oscale * (float)(-lwidth) / 2.0, oscale * (float)(-lheight) / 2.0,
|
oscale * (float)(-lwidth) / 2.0, oscale * (float)(-lheight) / 2.0,
|
||||||
oscale * (float)lwidth / 2.0, oscale * (float)lheight / 2.0);
|
oscale * (float)lwidth / 2.0, oscale * (float)lheight / 2.0);
|
||||||
fprintf(f, " + PLACED ( %.10g %.10g ) N ;\n",
|
fprintf(f, " + PLACED ( %.10g %.10g ) N ;\n",
|
||||||
|
|
@ -1913,6 +1941,222 @@ defWritePins(f, rootDef, oscale)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* defWriteNets --
|
||||||
|
*
|
||||||
|
* Output the NETS section of a DEF file. We make use of
|
||||||
|
* the connectivity search routines used by "getnode" to
|
||||||
|
* determine unique notes and assign a net name to each.
|
||||||
|
* Then, we generate the geometry output for each NET
|
||||||
|
* entry.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side Effects:
|
||||||
|
* Output written to the DEF output file.
|
||||||
|
*
|
||||||
|
*------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
defWriteBlockages(f, rootDef, oscale, MagicToLefTable)
|
||||||
|
FILE *f; /* File to write to */
|
||||||
|
CellDef *rootDef; /* Cell definition to use */
|
||||||
|
float oscale; /* Output scale factor */
|
||||||
|
LefMapping *MagicToLefTable; /* Magic to LEF layer mapping */
|
||||||
|
{
|
||||||
|
DefObsData defobsdata;
|
||||||
|
lefLayer *lefl;
|
||||||
|
int i, numblocks, nonempty;
|
||||||
|
LinkedRect *lr;
|
||||||
|
HashSearch hs;
|
||||||
|
HashEntry *he;
|
||||||
|
|
||||||
|
int defblockageVisit();
|
||||||
|
|
||||||
|
defobsdata.def = rootDef;
|
||||||
|
defobsdata.nlayers = 0;
|
||||||
|
|
||||||
|
/* Blockages are done by layer. Create one blockage per route */
|
||||||
|
/* layer, and ignore vias. */
|
||||||
|
|
||||||
|
numblocks = 0;
|
||||||
|
if (LefInfo.ht_table != (HashEntry **) NULL)
|
||||||
|
{
|
||||||
|
HashStartSearch(&hs);
|
||||||
|
while (he = HashNext(&LefInfo, &hs))
|
||||||
|
{
|
||||||
|
lefl = (lefLayer *)HashGetValue(he);
|
||||||
|
if ((lefl->lefClass == CLASS_ROUTE) || (lefl->lefClass == CLASS_VIA))
|
||||||
|
numblocks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
defobsdata.nlayers = numblocks;
|
||||||
|
defobsdata.blockMasks = (TileTypeBitMask *)mallocMagic(numblocks *
|
||||||
|
sizeof(TileTypeBitMask));
|
||||||
|
defobsdata.blockData = (LinkedRect **)mallocMagic(numblocks *
|
||||||
|
sizeof(LinkedRect *));
|
||||||
|
defobsdata.baseNames = (char **)mallocMagic(numblocks *
|
||||||
|
sizeof(char *));
|
||||||
|
|
||||||
|
if (numblocks > 0)
|
||||||
|
{
|
||||||
|
numblocks = 0;
|
||||||
|
HashStartSearch(&hs);
|
||||||
|
while (he = HashNext(&LefInfo, &hs))
|
||||||
|
{
|
||||||
|
lefl = (lefLayer *)HashGetValue(he);
|
||||||
|
if ((lefl->lefClass == CLASS_ROUTE) || (lefl->lefClass == CLASS_VIA))
|
||||||
|
{
|
||||||
|
char *llayer;
|
||||||
|
if (lefl->lefClass == CLASS_ROUTE)
|
||||||
|
llayer = lefl->canonName;
|
||||||
|
else
|
||||||
|
llayer = MagicToLefTable[lefl->type].lefName;
|
||||||
|
|
||||||
|
defobsdata.baseNames[numblocks] = llayer;
|
||||||
|
TTMaskSetOnlyType(&defobsdata.blockMasks[numblocks], lefl->type);
|
||||||
|
if (lefl->obsType != -1)
|
||||||
|
TTMaskSetType(&defobsdata.blockMasks[numblocks], lefl->obsType);
|
||||||
|
defobsdata.blockData[numblocks] = NULL;
|
||||||
|
numblocks++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numblocks > 0)
|
||||||
|
EFVisitNodes(defblockageVisit, (ClientData)&defobsdata);
|
||||||
|
|
||||||
|
/* Quick check for presence of data to write */
|
||||||
|
|
||||||
|
nonempty = 0;
|
||||||
|
for (i = 0; i < numblocks; i++)
|
||||||
|
if (defobsdata.blockData[i] != NULL)
|
||||||
|
nonempty++;
|
||||||
|
|
||||||
|
if (nonempty > 0)
|
||||||
|
{
|
||||||
|
fprintf(f, "BLOCKAGES %d ;\n", nonempty);
|
||||||
|
|
||||||
|
for (i = 0; i < numblocks; i++)
|
||||||
|
{
|
||||||
|
if (defobsdata.blockData[i] == NULL) continue;
|
||||||
|
fprintf(f, " - LAYER %s\n", defobsdata.baseNames[i]);
|
||||||
|
for (lr = defobsdata.blockData[i]; lr; lr = lr->r_next)
|
||||||
|
{
|
||||||
|
fprintf(f, " RECT %.10g %.10g %.10g %.10g\n",
|
||||||
|
(float)(lr->r_r.r_xbot * oscale),
|
||||||
|
(float)(lr->r_r.r_ybot * oscale),
|
||||||
|
(float)(lr->r_r.r_xtop * oscale),
|
||||||
|
(float)(lr->r_r.r_ytop * oscale));
|
||||||
|
freeMagic(lr);
|
||||||
|
}
|
||||||
|
fprintf(f, ";\n");
|
||||||
|
}
|
||||||
|
fprintf(f, "END BLOCKAGES\n\n");
|
||||||
|
}
|
||||||
|
freeMagic(defobsdata.blockData);
|
||||||
|
freeMagic(defobsdata.blockMasks);
|
||||||
|
freeMagic(defobsdata.baseNames);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
defblockageVisit(node, res, cap, defobsdata)
|
||||||
|
EFNode *node;
|
||||||
|
int res;
|
||||||
|
EFCapValue cap;
|
||||||
|
DefObsData *defobsdata;
|
||||||
|
{
|
||||||
|
CellDef *def = defobsdata->def;
|
||||||
|
TileType magictype;
|
||||||
|
TileTypeBitMask tmask;
|
||||||
|
int defBlockageGeometryFunc(); /* Forward declaration */
|
||||||
|
|
||||||
|
/* For regular nets, only count those nodes having port */
|
||||||
|
/* connections. For special nets, only count those nodes */
|
||||||
|
/* that were marked with the EF_SPECIAL flag while counting */
|
||||||
|
/* nets. */
|
||||||
|
|
||||||
|
if ((node->efnode_flags & EF_PORT) || (node->efnode_flags & EF_SPECIAL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
magictype = DBTechNameType(EFLayerNames[node->efnode_type]);
|
||||||
|
TTMaskZero(&tmask);
|
||||||
|
TTMaskSetMask(&tmask, &DBConnectTbl[magictype]);
|
||||||
|
|
||||||
|
/* Avoid attempting to extract an implicit substrate into DEF */
|
||||||
|
if (node->efnode_type == TT_SPACE) return 0;
|
||||||
|
|
||||||
|
DBSrConnect(def, &node->efnode_loc, &tmask, DBConnectTbl,
|
||||||
|
&TiPlaneRect, defBlockageGeometryFunc,
|
||||||
|
(ClientData)defobsdata);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Callback function for generating a linked list of blockage geometry */
|
||||||
|
/* for a net. */
|
||||||
|
|
||||||
|
int
|
||||||
|
defBlockageGeometryFunc(tile, plane, defobsdata)
|
||||||
|
Tile *tile; /* Tile being visited */
|
||||||
|
int plane; /* Plane of the tile being visited */
|
||||||
|
DefObsData *defobsdata; /* Data passed to this function */
|
||||||
|
{
|
||||||
|
TileType ttype = TiGetTypeExact(tile);
|
||||||
|
TileType loctype;
|
||||||
|
Rect r;
|
||||||
|
LinkedRect *lr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (IsSplit(tile))
|
||||||
|
loctype = (ttype & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
|
else
|
||||||
|
loctype = ttype;
|
||||||
|
|
||||||
|
if (loctype == TT_SPACE) return 0;
|
||||||
|
|
||||||
|
/* Dissolve stacked contacts */
|
||||||
|
|
||||||
|
if (loctype >= DBNumUserLayers)
|
||||||
|
{
|
||||||
|
TileTypeBitMask *rMask;
|
||||||
|
TileType rtype;
|
||||||
|
|
||||||
|
rMask = DBResidueMask(loctype);
|
||||||
|
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
|
||||||
|
if (TTMaskHasType(rMask, rtype))
|
||||||
|
if (DBPlane(rtype) == plane)
|
||||||
|
{
|
||||||
|
loctype = rtype;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rtype == DBNumUserLayers)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < defobsdata->nlayers; i++)
|
||||||
|
if (TTMaskHasType(&(defobsdata->blockMasks[i]), loctype))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i < defobsdata->nlayers)
|
||||||
|
{
|
||||||
|
TiToRect(tile, &r);
|
||||||
|
|
||||||
|
lr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
|
||||||
|
lr->r_next = defobsdata->blockData[i];
|
||||||
|
lr->r_type = loctype;
|
||||||
|
lr->r_r = r;
|
||||||
|
defobsdata->blockData[i] = lr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*------------------------------------------------------------
|
*------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -2153,7 +2397,7 @@ DefWriteCell(def, outName, allSpecial, units)
|
||||||
total = defCountPins(def);
|
total = defCountPins(def);
|
||||||
fprintf(f, "PINS %d ;\n", total);
|
fprintf(f, "PINS %d ;\n", total);
|
||||||
if (total > 0)
|
if (total > 0)
|
||||||
defWritePins(f, def, scale);
|
defWritePins(f, def, lefMagicToLefLayer, scale);
|
||||||
fprintf(f, "END PINS\n\n");
|
fprintf(f, "END PINS\n\n");
|
||||||
|
|
||||||
/* Count the number of nets and "special" nets */
|
/* Count the number of nets and "special" nets */
|
||||||
|
|
@ -2193,14 +2437,18 @@ DefWriteCell(def, outName, allSpecial, units)
|
||||||
fprintf(f, "END NETS\n\n");
|
fprintf(f, "END NETS\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Blockages */
|
||||||
|
if (nets.blockages > 0)
|
||||||
|
defWriteBlockages(f, def, scale, lefMagicToLefLayer);
|
||||||
|
|
||||||
|
fprintf(f, "END DESIGN\n\n");
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
if (nets.has_nets) {
|
if (nets.has_nets) {
|
||||||
EFFlatDone(NULL);
|
EFFlatDone(NULL);
|
||||||
EFDone(NULL);
|
EFDone(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(f, "END DESIGN\n\n");
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
freeMagic((char *)lefMagicToLefLayer);
|
freeMagic((char *)lefMagicToLefLayer);
|
||||||
lefRemoveGeneratedVias();
|
lefRemoveGeneratedVias();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int regular;
|
int regular;
|
||||||
int special;
|
int special;
|
||||||
|
int blockages;
|
||||||
int numrules;
|
int numrules;
|
||||||
LefRules *rules;
|
LefRules *rules;
|
||||||
bool has_nets;
|
bool has_nets;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue