From 6b8239e25898cc2ba8eb0837850428dc4ff4db89 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sun, 14 Jan 2024 15:19:39 -0500 Subject: [PATCH] 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). --- VERSION | 2 +- drc/DRCtech.c | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 7d55d153..20e0d3ec 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.457 +8.3.458 diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 1771b974..d5242355 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -3686,14 +3686,30 @@ drcScaleDown(style, scalefactor) } if (dp->drcc_cdist > 0) { + int cmod; int locscale = scalefactor; if (dp->drcc_flags & DRC_AREA) locscale *= scalefactor; dist = dp->drcc_cdist; 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++; + 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 *= scalefactor; if (dp->drcc_flags & DRC_AREA) + { 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; } }