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);
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------
|
||||
*
|
||||
* 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]);
|
||||
break;
|
||||
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;
|
||||
case DEF_END:
|
||||
if (!LefParseEndStatement(token, "DESIGN"))
|
||||
|
|
|
|||
276
lef/defWrite.c
276
lef/defWrite.c
|
|
@ -52,6 +52,14 @@ typedef struct {
|
|||
unsigned char specialmode; /* What nets to write as SPECIALNETS */
|
||||
} DefData;
|
||||
|
||||
typedef struct {
|
||||
CellDef *def;
|
||||
int nlayers;
|
||||
char **baseNames;
|
||||
TileTypeBitMask *blockMasks;
|
||||
LinkedRect **blockData;
|
||||
} DefObsData;
|
||||
|
||||
typedef struct {
|
||||
float scale;
|
||||
int total;
|
||||
|
|
@ -207,6 +215,7 @@ defCountNets(rootDef, allSpecial)
|
|||
|
||||
total.regular = (allSpecial) ? -1 : 0;
|
||||
total.special = 0;
|
||||
total.blockages = 0;
|
||||
total.numrules = 0;
|
||||
total.rules = NULL;
|
||||
total.has_nets = TRUE;
|
||||
|
|
@ -253,6 +262,10 @@ defnodeCount(node, res, cap, total)
|
|||
char ndn[256];
|
||||
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 */
|
||||
/* as SPECIALNETS types. */
|
||||
|
||||
|
|
@ -310,6 +323,8 @@ defnodeCount(node, res, cap, total)
|
|||
|
||||
if ((node->efnode_flags & EF_SPECIAL) || (node->efnode_flags & EF_PORT))
|
||||
total->special++;
|
||||
else
|
||||
total->blockages++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -319,6 +334,8 @@ defnodeCount(node, res, cap, total)
|
|||
total->special++;
|
||||
else if (node->efnode_flags & EF_PORT)
|
||||
total->regular++;
|
||||
else
|
||||
total->blockages++;
|
||||
}
|
||||
|
||||
return 0; /* Keep going. . . */
|
||||
|
|
@ -625,6 +642,8 @@ defnodeVisit(node, res, cap, defdata)
|
|||
{
|
||||
if (!(node->efnode_flags & EF_PORT))
|
||||
return 0;
|
||||
else if (node->efnode_flags & EF_SPECIAL)
|
||||
return 0;
|
||||
}
|
||||
else if (defdata->specialmode == DO_SPECIAL)
|
||||
{
|
||||
|
|
@ -646,6 +665,10 @@ defnodeVisit(node, res, cap, defdata)
|
|||
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);
|
||||
defdata->outcolumn = 5 + strlen(ndn);
|
||||
|
||||
|
|
@ -697,9 +720,6 @@ defnodeVisit(node, res, cap, defdata)
|
|||
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, defNetGeometryFunc,
|
||||
(ClientData)defdata);
|
||||
|
|
@ -1519,7 +1539,7 @@ defCountViaFunc(tile, cviadata)
|
|||
{
|
||||
cviadata->total++; /* Increment the count of uses */
|
||||
lefl = (lefLayer *)mallocMagic(sizeof(lefLayer));
|
||||
lefl->type = ttype;
|
||||
lefl->type = ctype;
|
||||
lefl->obsType = -1;
|
||||
lefl->lefClass = CLASS_VIA;
|
||||
lefl->info.via.area = r;
|
||||
|
|
@ -1664,6 +1684,12 @@ defWriteVias(f, rootDef, oscale, lefMagicToLefLayer)
|
|||
int i, j, nAc, nUp, pitch, left;
|
||||
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;
|
||||
nAc = (r->r_xtop - r->r_xbot + sep - (2 * border)) / pitch;
|
||||
if (nAc == 0)
|
||||
|
|
@ -1704,10 +1730,10 @@ defWriteVias(f, rootDef, oscale, lefMagicToLefLayer)
|
|||
fprintf(f, "\n + RECT %s ( %.10g %.10g ) "
|
||||
"( %.10g %.10g )",
|
||||
lefMagicToLefLayer[lefl->type].lefName,
|
||||
(float)(square.r_xbot) * oscale / 2,
|
||||
(float)(square.r_ybot) * oscale / 2,
|
||||
(float)(square.r_xtop) * oscale / 2,
|
||||
(float)(square.r_ytop) * oscale / 2);
|
||||
(float)(square.r_xbot / 2),
|
||||
(float)(square.r_ybot / 2),
|
||||
(float)(square.r_xtop / 2),
|
||||
(float)(square.r_ytop / 2));
|
||||
square.r_xbot += pitch;
|
||||
}
|
||||
square.r_ybot += pitch;
|
||||
|
|
@ -1837,9 +1863,10 @@ defCountPins(rootDef)
|
|||
*/
|
||||
|
||||
void
|
||||
defWritePins(f, rootDef, oscale)
|
||||
defWritePins(f, rootDef, lefMagicToLefLayer, oscale)
|
||||
FILE *f; /* File to write to */
|
||||
CellDef *rootDef; /* Cell definition to use */
|
||||
LefMapping *lefMagicToLefLayer; /* Magic to LEF layer name mapping */
|
||||
float oscale; /* Output scale factor */
|
||||
{
|
||||
Label *lab;
|
||||
|
|
@ -1902,9 +1929,10 @@ defWritePins(f, rootDef, oscale)
|
|||
dcenterx = lab->lab_rect.r_xtop + lab->lab_rect.r_xbot;
|
||||
dcentery = lab->lab_rect.r_ytop + lab->lab_rect.r_ybot;
|
||||
|
||||
|
||||
fprintf(f, " + PORT\n");
|
||||
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);
|
||||
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);
|
||||
fprintf(f, "PINS %d ;\n", total);
|
||||
if (total > 0)
|
||||
defWritePins(f, def, scale);
|
||||
defWritePins(f, def, lefMagicToLefLayer, scale);
|
||||
fprintf(f, "END PINS\n\n");
|
||||
|
||||
/* Count the number of nets and "special" nets */
|
||||
|
|
@ -2193,14 +2437,18 @@ DefWriteCell(def, outName, allSpecial, units)
|
|||
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) {
|
||||
EFFlatDone(NULL);
|
||||
EFDone(NULL);
|
||||
}
|
||||
|
||||
fprintf(f, "END DESIGN\n\n");
|
||||
fclose(f);
|
||||
|
||||
freeMagic((char *)lefMagicToLefLayer);
|
||||
lefRemoveGeneratedVias();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
int regular;
|
||||
int special;
|
||||
int blockages;
|
||||
int numrules;
|
||||
LefRules *rules;
|
||||
bool has_nets;
|
||||
|
|
|
|||
Loading…
Reference in New Issue