Made a small change to the "cifmaxwidth" rule check implementation

to ignore non-Manhattan (split) tiles.  This avoids creating false-
positive DRC results on split tiles which are larger in X and Y
than the max-width distance.  False negatives are possible but
correctly implementing a "maxwidth" rule for non-orthogonal areas
requires a completely different algorithm.
This commit is contained in:
R. Timothy Edwards 2025-08-11 12:10:09 -04:00
parent b4912fd550
commit 5791ae3701
2 changed files with 79 additions and 70 deletions

View File

@ -1 +1 @@
8.3.538 8.3.539

View File

@ -328,7 +328,7 @@ drcCifSpacing(argc, argv)
dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID]; dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
why, centidistance, DRC_FORWARD|DRC_BOTHCORNERS | DRC_CIFRULE, why, centidistance, DRC_FORWARD | DRC_BOTHCORNERS | DRC_CIFRULE,
layer[0], 0); layer[0], 0);
drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew; drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew;
@ -336,7 +336,7 @@ drcCifSpacing(argc, argv)
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
why, centidistance, DRC_REVERSE|DRC_BOTHCORNERS | DRC_CIFRULE, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS | DRC_CIFRULE,
layer[0], 0); layer[0], 0);
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
@ -1432,7 +1432,7 @@ forgetit:
*/ */
void void
drcCheckCifMaxwidth(starttile,arg,cptr) drcCheckCifMaxwidth(starttile, arg, cptr)
Tile *starttile; Tile *starttile;
struct drcClientData *arg; struct drcClientData *arg;
DRCCookie *cptr; DRCCookie *cptr;
@ -1441,7 +1441,7 @@ drcCheckCifMaxwidth(starttile,arg,cptr)
int edgelimit = cptr->drcc_dist; int edgelimit = cptr->drcc_dist;
Rect boundrect; Rect boundrect;
TileTypeBitMask *oktypes = &cptr->drcc_mask; TileTypeBitMask *oktypes = &cptr->drcc_mask;
Tile *tile,*tp; Tile *tile, *tp;
int scale = drcCifStyle->cs_scaleFactor; int scale = drcCifStyle->cs_scaleFactor;
arg->dCD_cptr = (DRCCookie *)cptr; arg->dCD_cptr = (DRCCookie *)cptr;
@ -1458,43 +1458,53 @@ drcCheckCifMaxwidth(starttile,arg,cptr)
if (cptr->drcc_flags & DRC_MAXWIDTH_BOTH) if (cptr->drcc_flags & DRC_MAXWIDTH_BOTH)
{ {
Rect rect; Rect rect;
TiToRect(starttile,&rect); TiToRect(starttile, &rect);
if ((rect.r_xtop-rect.r_xbot > edgelimit) || if ((rect.r_xtop-rect.r_xbot > edgelimit) ||
(rect.r_ytop-rect.r_ybot > edgelimit)) (rect.r_ytop-rect.r_ybot > edgelimit))
{ {
rect.r_xbot /= scale; rect.r_xbot /= scale;
rect.r_xtop /= scale; rect.r_xtop /= scale;
rect.r_ybot /= scale; rect.r_ybot /= scale;
rect.r_ytop /= scale; rect.r_ytop /= scale;
GeoClip(&rect, arg->dCD_clip); GeoClip(&rect, arg->dCD_clip);
if (!GEO_RECTNULL(&rect)) { if (!GEO_RECTNULL(&rect))
(*(arg->dCD_function)) (arg->dCD_celldef, &rect, {
(*(arg->dCD_function)) (arg->dCD_celldef, &rect,
arg->dCD_cptr, arg->dCD_clientData); arg->dCD_cptr, arg->dCD_clientData);
(*(arg->dCD_errors))++; (*(arg->dCD_errors))++;
} }
} }
return; return;
} }
else if (cptr->drcc_flags & DRC_BENDS) else if (cptr->drcc_flags & DRC_BENDS)
{ {
Rect rect; Rect rect;
TiToRect(starttile,&rect);
if (rect.r_xtop-rect.r_xbot > edgelimit && /* Ignore split tiles; this is a limitation but another
rect.r_ytop-rect.r_ybot > edgelimit) * algorithm is needed to check for maximum width in a
{ * non-Manhattan area.
rect.r_xbot /= scale; */
rect.r_xtop /= scale; if (IsSplit(starttile)) return;
rect.r_ybot /= scale;
rect.r_ytop /= scale; TiToRect(starttile, &rect);
GeoClip(&rect, arg->dCD_clip);
if (!GEO_RECTNULL(&rect)) { if (rect.r_xtop-rect.r_xbot > edgelimit &&
(*(arg->dCD_function)) (arg->dCD_celldef, &rect, rect.r_ytop-rect.r_ybot > edgelimit)
{
rect.r_xbot /= scale;
rect.r_xtop /= scale;
rect.r_ybot /= scale;
rect.r_ytop /= scale;
GeoClip(&rect, arg->dCD_clip);
if (!GEO_RECTNULL(&rect))
{
(*(arg->dCD_function)) (arg->dCD_celldef, &rect,
arg->dCD_cptr, arg->dCD_clientData); arg->dCD_cptr, arg->dCD_clientData);
(*(arg->dCD_errors))++; (*(arg->dCD_errors))++;
} }
} }
return; return;
} }
/* Mark this tile as pending and push it */ /* Mark this tile as pending and push it */
@ -1513,12 +1523,12 @@ drcCheckCifMaxwidth(starttile,arg,cptr)
if (boundrect.r_ytop < TOP(tile)) boundrect.r_ytop = TOP(tile); if (boundrect.r_ytop < TOP(tile)) boundrect.r_ytop = TOP(tile);
TiSetClientINT(tile, DRC_PROCESSED); TiSetClientINT(tile, DRC_PROCESSED);
if (boundrect.r_xtop - boundrect.r_xbot > edgelimit && if (boundrect.r_xtop - boundrect.r_xbot > edgelimit &&
boundrect.r_ytop - boundrect.r_ybot > edgelimit) break; boundrect.r_ytop - boundrect.r_ybot > edgelimit) break;
/* Top */ /* Top */
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); if (TTMaskHasType(oktypes, TiGetType(tp)))PUSHTILE(tp);
/* Left */ /* Left */
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
@ -1531,40 +1541,40 @@ drcCheckCifMaxwidth(starttile,arg,cptr)
/* Right */ /* Right */
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp);
} }
if (boundrect.r_xtop - boundrect.r_xbot > edgelimit && if (boundrect.r_xtop - boundrect.r_xbot > edgelimit &&
boundrect.r_ytop - boundrect.r_ybot > edgelimit) boundrect.r_ytop - boundrect.r_ybot > edgelimit)
{ {
Rect rect; Rect rect;
TiToRect(starttile,&rect); TiToRect(starttile, &rect);
{ {
rect.r_xbot /= scale; rect.r_xbot /= scale;
rect.r_xtop /= scale; rect.r_xtop /= scale;
rect.r_ybot /= scale; rect.r_ybot /= scale;
rect.r_ytop /= scale; rect.r_ytop /= scale;
GeoClip(&rect, arg->dCD_clip); GeoClip(&rect, arg->dCD_clip);
if (!GEO_RECTNULL(&rect)) { if (!GEO_RECTNULL(&rect))
(*(arg->dCD_function)) (arg->dCD_celldef, &rect, {
(*(arg->dCD_function)) (arg->dCD_celldef, &rect,
arg->dCD_cptr, arg->dCD_clientData); arg->dCD_cptr, arg->dCD_clientData);
(*(arg->dCD_errors))++; (*(arg->dCD_errors))++;
} }
} }
}
} /* reset the tiles */
/* reset the tiles */ TiSetClient(starttile, DRC_UNPROCESSED);
TiSetClient(starttile, DRC_UNPROCESSED); STACKPUSH(starttile, DRCstack);
STACKPUSH(starttile, DRCstack); while (!StackEmpty(DRCstack))
while (!StackEmpty(DRCstack)) {
{ tile = (Tile *)STACKPOP(DRCstack);
tile = (Tile *) STACKPOP(DRCstack);
/* Top */ /* Top */
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
if (TiGetClient(tp) != DRC_UNPROCESSED) if (TiGetClient(tp) != DRC_UNPROCESSED)
{ {
TiSetClient(tp, DRC_UNPROCESSED); TiSetClient(tp, DRC_UNPROCESSED);
STACKPUSH(tp,DRCstack); STACKPUSH(tp, DRCstack);
} }
/* Left */ /* Left */
@ -1572,7 +1582,7 @@ drcCheckCifMaxwidth(starttile,arg,cptr)
if (TiGetClient(tp) != DRC_UNPROCESSED) if (TiGetClient(tp) != DRC_UNPROCESSED)
{ {
TiSetClient(tp, DRC_UNPROCESSED); TiSetClient(tp, DRC_UNPROCESSED);
STACKPUSH(tp,DRCstack); STACKPUSH(tp, DRCstack);
} }
/* Bottom */ /* Bottom */
@ -1580,7 +1590,7 @@ drcCheckCifMaxwidth(starttile,arg,cptr)
if (TiGetClient(tp) != DRC_UNPROCESSED) if (TiGetClient(tp) != DRC_UNPROCESSED)
{ {
TiSetClient(tp, DRC_UNPROCESSED); TiSetClient(tp, DRC_UNPROCESSED);
STACKPUSH(tp,DRCstack); STACKPUSH(tp, DRCstack);
} }
/* Right */ /* Right */
@ -1588,9 +1598,8 @@ drcCheckCifMaxwidth(starttile,arg,cptr)
if (TiGetClient(tp) != DRC_UNPROCESSED) if (TiGetClient(tp) != DRC_UNPROCESSED)
{ {
TiSetClient(tp, DRC_UNPROCESSED); TiSetClient(tp, DRC_UNPROCESSED);
STACKPUSH(tp,DRCstack); STACKPUSH(tp, DRCstack);
} }
}
}
} }