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:
Tim Edwards 2022-03-24 17:58:05 -04:00
parent 645a872967
commit cf39fb102c
4 changed files with 384 additions and 18 deletions

View File

@ -1 +1 @@
8.3.279
8.3.280

View File

@ -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"))

View File

@ -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();
}

View File

@ -122,6 +122,7 @@ typedef struct {
typedef struct {
int regular;
int special;
int blockages;
int numrules;
LefRules *rules;
bool has_nets;