Corrected the LEF technology setup, where LEF layers (routes and
contacts) take default values from the DRC section. Since both are in lambda, but the DRC section uses a two-part integer and modulus representation, if default values are taken before scaling, the LEF layers may get rounded values. This has been solved by marking values with -1 to indicate that they require defaults, and then set those defaults (from scaled DRC rules) after scaling all other tech values.
This commit is contained in:
parent
18fc328289
commit
0f05bb1356
|
|
@ -4165,6 +4165,16 @@ DRCGetDefaultLayerWidth(ttype)
|
||||||
for (cptr = DRCCurStyle->DRCRulesTbl[TT_SPACE][ttype]; cptr != (DRCCookie *) NULL;
|
for (cptr = DRCCurStyle->DRCRulesTbl[TT_SPACE][ttype]; cptr != (DRCCookie *) NULL;
|
||||||
cptr = cptr->drcc_next)
|
cptr = cptr->drcc_next)
|
||||||
{
|
{
|
||||||
|
/* Skip triggered and triggering rules */
|
||||||
|
if (cptr->drcc_flags & DRC_TRIGGER)
|
||||||
|
{
|
||||||
|
cptr = cptr->drcc_next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip area rule */
|
||||||
|
if (cptr->drcc_flags & DRC_AREA) continue;
|
||||||
|
|
||||||
/* FORWARD rules only, and no MAXWIDTH */
|
/* FORWARD rules only, and no MAXWIDTH */
|
||||||
if ((cptr->drcc_flags & (DRC_REVERSE | DRC_MAXWIDTH)) == 0)
|
if ((cptr->drcc_flags & (DRC_REVERSE | DRC_MAXWIDTH)) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -4219,6 +4229,10 @@ DRCGetDefaultLayerSpacing(ttype1, ttype2)
|
||||||
cptr = cptr->drcc_next;
|
cptr = cptr->drcc_next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip area rule */
|
||||||
|
if (cptr->drcc_flags & DRC_AREA) continue;
|
||||||
|
|
||||||
if ((cptr->drcc_flags & DRC_REVERSE) == 0) /* FORWARD only */
|
if ((cptr->drcc_flags & DRC_REVERSE) == 0) /* FORWARD only */
|
||||||
{
|
{
|
||||||
set = &cptr->drcc_mask;
|
set = &cptr->drcc_mask;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
extern void LefTechInit();
|
extern void LefTechInit();
|
||||||
extern bool LefTechLine();
|
extern bool LefTechLine();
|
||||||
extern void LefTechScale();
|
extern void LefTechScale();
|
||||||
|
extern void LefTechSetDefaults();
|
||||||
|
|
||||||
/* Initialization: */
|
/* Initialization: */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -339,10 +339,10 @@ LefTechLine(sectionName, argc, argv)
|
||||||
break;
|
break;
|
||||||
case LEFTECH_CONTACT:
|
case LEFTECH_CONTACT:
|
||||||
newlefl->lefClass = CLASS_VIA;
|
newlefl->lefClass = CLASS_VIA;
|
||||||
newlefl->info.via.area.r_xtop = DRCGetDefaultLayerWidth(mtype);
|
newlefl->info.via.area.r_xbot = -1;
|
||||||
newlefl->info.via.area.r_ytop = newlefl->info.via.area.r_xtop;
|
newlefl->info.via.area.r_ybot = -1;
|
||||||
newlefl->info.via.area.r_xbot = -newlefl->info.via.area.r_xtop;
|
newlefl->info.via.area.r_xtop = -1;
|
||||||
newlefl->info.via.area.r_ybot = -newlefl->info.via.area.r_ytop;
|
newlefl->info.via.area.r_ytop = -1; /* To be filled */
|
||||||
newlefl->info.via.cell = (CellDef *)NULL;
|
newlefl->info.via.cell = (CellDef *)NULL;
|
||||||
newlefl->info.via.lr = (LinkedRect *)NULL;
|
newlefl->info.via.lr = (LinkedRect *)NULL;
|
||||||
newlefl->info.via.obsType = mtype2;
|
newlefl->info.via.obsType = mtype2;
|
||||||
|
|
@ -350,13 +350,19 @@ LefTechLine(sectionName, argc, argv)
|
||||||
case LEFTECH_ROUTE:
|
case LEFTECH_ROUTE:
|
||||||
case LEFTECH_ROUTING:
|
case LEFTECH_ROUTING:
|
||||||
newlefl->lefClass = CLASS_ROUTE;
|
newlefl->lefClass = CLASS_ROUTE;
|
||||||
|
/* Set provisional width (to be removed) */
|
||||||
newlefl->info.route.width = DRCGetDefaultLayerWidth(mtype);
|
newlefl->info.route.width = DRCGetDefaultLayerWidth(mtype);
|
||||||
if (newlefl->info.route.width == 0)
|
if (newlefl->info.route.width == 0)
|
||||||
newlefl->info.route.width = DEFAULT_WIDTH;
|
newlefl->info.route.width = DEFAULT_WIDTH;
|
||||||
|
else
|
||||||
|
newlefl->info.route.width = -1; /* To be filled */
|
||||||
|
/* Set provisional spacing (to be removed) */
|
||||||
newlefl->info.route.spacing =
|
newlefl->info.route.spacing =
|
||||||
DRCGetDefaultLayerSpacing(mtype, mtype);
|
DRCGetDefaultLayerSpacing(mtype, mtype);
|
||||||
if (newlefl->info.route.spacing == 0)
|
if (newlefl->info.route.spacing == 0)
|
||||||
newlefl->info.route.spacing = DEFAULT_SPACING;
|
newlefl->info.route.spacing = DEFAULT_SPACING;
|
||||||
|
else
|
||||||
|
newlefl->info.route.spacing = -1; /* To be filled */
|
||||||
newlefl->info.route.pitch = 0;
|
newlefl->info.route.pitch = 0;
|
||||||
newlefl->info.route.hdirection = TRUE;
|
newlefl->info.route.hdirection = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
@ -453,3 +459,57 @@ LefTechScale(scalen, scaled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-----------------------------------------------------------------------------
|
||||||
|
* LefTechSetDefaults --
|
||||||
|
*
|
||||||
|
* Change parameters of the LEF section after scaling (see above)
|
||||||
|
* to set default values for each route and contact layer (width and
|
||||||
|
* spacing have been set to -1). This is because the value is in
|
||||||
|
* lambda, and calling the DRC defaults before scaling can produce
|
||||||
|
* a rounded value which is then incorrect when scaled.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
LefTechSetDefaults()
|
||||||
|
{
|
||||||
|
HashSearch hs;
|
||||||
|
HashEntry *he;
|
||||||
|
lefLayer *lefl;
|
||||||
|
|
||||||
|
if (LefInfo.ht_table != (HashEntry **) NULL)
|
||||||
|
{
|
||||||
|
HashStartSearch(&hs);
|
||||||
|
while (he = HashNext(&LefInfo, &hs))
|
||||||
|
{
|
||||||
|
lefl = (lefLayer *)HashGetValue(he);
|
||||||
|
if (!lefl) continue;
|
||||||
|
|
||||||
|
if (lefl->lefClass == CLASS_VIA)
|
||||||
|
{
|
||||||
|
if ((lefl->info.via.area.r_xbot == -1) &&
|
||||||
|
(lefl->info.via.area.r_ybot == -1) &&
|
||||||
|
(lefl->info.via.area.r_xtop == -1) &&
|
||||||
|
(lefl->info.via.area.r_ytop == -1))
|
||||||
|
{
|
||||||
|
lefl->info.via.area.r_xtop =
|
||||||
|
DRCGetDefaultLayerWidth(lefl->type);
|
||||||
|
lefl->info.via.area.r_ytop = lefl->info.via.area.r_xtop;
|
||||||
|
lefl->info.via.area.r_xbot = -lefl->info.via.area.r_xtop;
|
||||||
|
lefl->info.via.area.r_ybot = -lefl->info.via.area.r_ytop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lefl->lefClass == CLASS_ROUTE)
|
||||||
|
{
|
||||||
|
if (lefl->info.route.width = -1)
|
||||||
|
lefl->info.route.width = DRCGetDefaultLayerWidth(lefl->type);
|
||||||
|
if (lefl->info.route.spacing = -1)
|
||||||
|
lefl->info.route.width = DRCGetDefaultLayerSpacing(lefl->type,
|
||||||
|
lefl->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -772,6 +772,7 @@ skipsection:
|
||||||
WireTechScale(d, n);
|
WireTechScale(d, n);
|
||||||
#ifdef LEF_MODULE
|
#ifdef LEF_MODULE
|
||||||
LefTechScale(d, n);
|
LefTechScale(d, n);
|
||||||
|
LefTechSetDefaults();
|
||||||
#endif
|
#endif
|
||||||
#ifdef ROUTE_MODULE
|
#ifdef ROUTE_MODULE
|
||||||
RtrTechScale(d, n);
|
RtrTechScale(d, n);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue