Discovered that the non-Euclidean distance checks had not been

completely implemented for the "cifwidth" and "cifspacing" rules,
resulting in those rules being Manhattan distance checks.  Finished
the implementation (duplicating code from DRCbasic.c, with
appropriate scaling to CIF coordinates).
This commit is contained in:
Tim Edwards 2024-04-06 16:36:31 -04:00
parent 8b3524575f
commit 71f4dd2f9f
3 changed files with 102 additions and 18 deletions

View File

@ -61,7 +61,7 @@ extern MaxRectsData *drcCanonicalMaxwidth();
/*
*-----------------------------------------------------------------------
*
* point_to_segment
* drcCifPointToSegment
*
* Euclidean-distance point-to-segment distance (squared)
* calculation (borrowed from XCircuit)
@ -77,7 +77,7 @@ extern MaxRectsData *drcCanonicalMaxwidth();
*/
long
point_to_segment(px, py, s1x, s1y, s2x, s2y)
drcCifPointToSegment(px, py, s1x, s1y, s2x, s2y)
int px, py; /* The position of the point */
int s1x, s1y; /* One endpoint of the line segment */
int s2x, s2y; /* The other endpoint of the line segment */
@ -187,7 +187,7 @@ areaCheck(tile, arg)
return 0;
else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile))
{
sstest = point_to_segment(arg->dCD_constraint->r_xbot + sdist,
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
arg->dCD_constraint->r_ytop - sdist,
LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile));
if (sstest > ssdist) return 0;
@ -202,7 +202,7 @@ areaCheck(tile, arg)
return 0;
else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile))
{
sstest = point_to_segment(arg->dCD_constraint->r_xtop - sdist,
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
arg->dCD_constraint->r_ytop - sdist,
LEFT(tile), TOP(tile), RIGHT(tile), BOTTOM(tile));
if (sstest > ssdist) return 0;
@ -218,7 +218,7 @@ areaCheck(tile, arg)
return 0;
else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile))
{
sstest = point_to_segment(arg->dCD_constraint->r_xbot + sdist,
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
arg->dCD_constraint->r_ybot + sdist,
LEFT(tile), TOP(tile), RIGHT(tile), BOTTOM(tile));
if (sstest > ssdist) return 0;
@ -234,7 +234,7 @@ areaCheck(tile, arg)
return 0;
else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile))
{
sstest = point_to_segment(arg->dCD_constraint->r_xtop - sdist,
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
arg->dCD_constraint->r_ybot + sdist,
LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile));
if (sstest > ssdist) return 0;

View File

@ -77,6 +77,13 @@ char *drcNeedStyle = NULL;
#define DRC_CIF_SPACE 0
#define DRC_CIF_SOLID 1
/* Define Euclidean distance checks */
#define RADIAL_NW 0x1000
#define RADIAL_NE 0x8000
#define RADIAL_SW 0x2000
#define RADIAL_SE 0x4000
/*
* ----------------------------------------------------------------------------
*
@ -715,7 +722,7 @@ drcCifTile (tile, arg)
{
errRect.r_ybot -= cptr->drcc_cdist;
if (DRCEuclidean)
arg->dCD_radial |= 0x1000;
arg->dCD_radial |= RADIAL_SW;
}
if (cptr->drcc_flags & DRC_BOTHCORNERS)
@ -731,7 +738,7 @@ drcCifTile (tile, arg)
{
errRect.r_ytop += cptr->drcc_cdist;
if (DRCEuclidean)
arg->dCD_radial |= 0x2000;
arg->dCD_radial |= RADIAL_NW;
}
}
@ -761,7 +768,7 @@ drcCifTile (tile, arg)
{
errRect.r_ytop += cptr->drcc_cdist;
if (DRCEuclidean)
arg->dCD_radial |= 0x8000;
arg->dCD_radial |= RADIAL_NE;
}
if (cptr->drcc_flags & DRC_BOTHCORNERS)
@ -777,7 +784,7 @@ drcCifTile (tile, arg)
{
errRect.r_ybot -= cptr->drcc_cdist;
if (DRCEuclidean)
arg->dCD_radial |= 0x4000;
arg->dCD_radial |= RADIAL_SE;
}
}
@ -797,7 +804,7 @@ drcCifTile (tile, arg)
}
if (arg->dCD_radial)
{
arg->dCD_radial &= 0xf0000;
arg->dCD_radial &= 0xf000;
arg->dCD_radial |= (0xfff & cptr->drcc_cdist);
}
@ -902,7 +909,7 @@ tbcheck:
{
errRect.r_xtop += cptr->drcc_cdist;
if (DRCEuclidean)
arg->dCD_radial |= 0x4000;
arg->dCD_radial |= RADIAL_SE;
}
if (cptr->drcc_flags & DRC_BOTHCORNERS)
@ -917,7 +924,7 @@ tbcheck:
{
errRect.r_xbot -= cptr->drcc_cdist;
if (DRCEuclidean)
arg->dCD_radial |= 0x1000;
arg->dCD_radial |= RADIAL_SW;
}
}
@ -949,7 +956,7 @@ tbcheck:
{
errRect.r_xbot -= cptr->drcc_cdist;
if (DRCEuclidean)
arg->dCD_radial |= 0x2000;
arg->dCD_radial |= RADIAL_NW;
}
if (cptr->drcc_flags & DRC_BOTHCORNERS)
@ -964,7 +971,7 @@ tbcheck:
{
errRect.r_xtop += cptr->drcc_cdist;
if (DRCEuclidean)
arg->dCD_radial |= 0x8000;
arg->dCD_radial |= RADIAL_NE;
}
}
@ -1029,6 +1036,7 @@ areaCifCheck(tile, arg)
struct drcClientData *arg;
{
Rect rect; /* Area where error is to be recorded. */
Rect cifrect; /* rect, in CIF coordinates */
int scale = drcCifStyle->cs_scaleFactor;
/* If the tile has a legal type, then return. */
@ -1039,10 +1047,11 @@ areaCifCheck(tile, arg)
* the clip area for errors.
*/
TiToRect(tile, &rect);
GeoClip(&rect, arg->dCD_constraint);
if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop))
TiToRect(tile, &cifrect);
GeoClip(&cifrect, arg->dCD_constraint);
if ((cifrect.r_xbot >= cifrect.r_xtop) || (cifrect.r_ybot >= cifrect.r_ytop))
return 0;
rect = cifrect;
rect.r_xbot /= scale;
rect.r_xtop /= scale;
if (rect.r_xbot == rect.r_xtop)
@ -1059,6 +1068,80 @@ areaCifCheck(tile, arg)
if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop))
return 0;
/*
* Euclidean distance checks
*/
if (arg->dCD_radial != 0)
{
unsigned int i;
int sqx, sqy;
int sdist = arg->dCD_radial & 0xfff;
long sstest, ssdist = sdist * sdist;
if ((arg->dCD_radial & RADIAL_NW) != 0)
{
if (((sqx = arg->dCD_constraint->r_xbot + sdist
- cifrect.r_xtop) >= 0) && ((sqy = cifrect.r_ybot
- arg->dCD_constraint->r_ytop + sdist) >= 0)
&& ((sqx * sqx + sqy * sqy) >= ssdist))
return 0;
else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile))
{
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
arg->dCD_constraint->r_ytop - sdist,
LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile));
if (sstest > ssdist) return 0;
}
}
if ((arg->dCD_radial & RADIAL_NE) != 0)
{
if (((sqx = cifrect.r_xbot - arg->dCD_constraint->r_xtop
+ sdist) >= 0) && ((sqy = cifrect.r_ybot
- arg->dCD_constraint->r_ytop + sdist) >= 0)
&& ((sqx * sqx + sqy * sqy) >= ssdist))
return 0;
else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile))
{
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
arg->dCD_constraint->r_ytop - sdist,
LEFT(tile), TOP(tile), RIGHT(tile), BOTTOM(tile));
if (sstest > ssdist) return 0;
}
}
if ((arg->dCD_radial & RADIAL_SW) != 0)
{
if (((sqx = arg->dCD_constraint->r_xbot + sdist
- cifrect.r_xtop) >= 0) &&
((sqy = arg->dCD_constraint->r_ybot
+ sdist - cifrect.r_ytop) >= 0)
&& ((sqx * sqx + sqy * sqy) >= ssdist))
return 0;
else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile))
{
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
arg->dCD_constraint->r_ybot + sdist,
LEFT(tile), TOP(tile), RIGHT(tile), BOTTOM(tile));
if (sstest > ssdist) return 0;
}
}
if ((arg->dCD_radial & RADIAL_SE) != 0)
{
if (((sqx = cifrect.r_xbot - arg->dCD_constraint->r_xtop
+ sdist) >= 0) &&
((sqy = arg->dCD_constraint->r_ybot
+ sdist - cifrect.r_ytop) >= 0)
&& ((sqx * sqx + sqy * sqy) >= ssdist))
return 0;
else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile))
{
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
arg->dCD_constraint->r_ybot + sdist,
LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile));
if (sstest > ssdist) return 0;
}
}
}
(*(arg->dCD_function)) (arg->dCD_celldef, &rect,
arg->dCD_cptr, arg->dCD_clientData);
(*(arg->dCD_errors))++;

View File

@ -309,6 +309,7 @@ extern void drcCheckRectSize();
extern void drcCheckOffGrid();
extern int LowestMaskBit();
extern void drcCifScale();
extern long drcCifPointToSegment();
/* The following macro can be used by the outside world to see if
* the background checker needs to be called.