Corrected a recently-discovered error in the "minimum area" DRC rule.

The fractional part of the rule distance (modulus after scaling)
does not fit in the unsigned char variable unless it is first
divided by the scalefactor (also requires multiplying up by the same
amount when scaling the other direction).  The truncation of the
unsigned char value was causing the minimum area value to be off by
a small amount, causing false negatives (no DRC violation is shown
when metal area is slightly smaller than the minimum allowed).
This commit is contained in:
Tim Edwards 2024-01-14 15:19:39 -05:00
parent a816da60f9
commit 6b8239e258
2 changed files with 26 additions and 3 deletions

View File

@ -1 +1 @@
8.3.457 8.3.458

View File

@ -3686,14 +3686,30 @@ drcScaleDown(style, scalefactor)
} }
if (dp->drcc_cdist > 0) if (dp->drcc_cdist > 0)
{ {
int cmod;
int locscale = scalefactor; int locscale = scalefactor;
if (dp->drcc_flags & DRC_AREA) if (dp->drcc_flags & DRC_AREA)
locscale *= scalefactor; locscale *= scalefactor;
dist = dp->drcc_cdist; dist = dp->drcc_cdist;
dp->drcc_cdist /= locscale; dp->drcc_cdist /= locscale;
if ((dp->drcc_cmod = (unsigned char)(dist % locscale)) != 0)
/* Save the amount by which the distance needs to be
* corrected when multiplied back to the original
* scale. For area, the modulus will always be
* a multiple of the scalefactor, so it can be
* divided by the scalefactor so it still fits in an
* unsigned char.
*/
if ((cmod = (dist % locscale)) != 0)
{
dp->drcc_cdist++; dp->drcc_cdist++;
if (dp->drcc_flags & DRC_AREA)
dp->drcc_cmod = (unsigned char)(cmod / scalefactor);
else
dp->drcc_cmod = (unsigned char)cmod;
}
} }
} }
} }
@ -3748,8 +3764,15 @@ drcScaleUp(style, scalefactor)
dp->drcc_cdist--; dp->drcc_cdist--;
dp->drcc_cdist *= scalefactor; dp->drcc_cdist *= scalefactor;
if (dp->drcc_flags & DRC_AREA) if (dp->drcc_flags & DRC_AREA)
{
dp->drcc_cdist *= scalefactor; dp->drcc_cdist *= scalefactor;
dp->drcc_cdist += (short)dp->drcc_cmod; /* See note above on how cmod is divided by the
* scalefactor for area values.
*/
dp->drcc_cdist += (short)(dp->drcc_cmod * scalefactor);
}
else
dp->drcc_cdist += (short)dp->drcc_cmod;
dp->drcc_cmod = 0; dp->drcc_cmod = 0;
} }
} }