From 0fb19e568c0f00a711115614bff8a516d0a081e0 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Wed, 13 Aug 2025 11:34:29 -0400 Subject: [PATCH] Extended the "spacing" and "edge"/"edge4way" rules to take an option "manhattan_dist" that causes corner checks to assume a manhattan distance measure. This is useful for checking distances involving generated edges that are created by a CIF "grow" operator. For "spacing", "manhattan_dist" is equivalent to "touching_illegal", as a use-case for forcing manhattan distance measurements in corners has not been found for other "spacing" options. --- VERSION | 2 +- drc/DRCbasic.c | 18 ++++++++------ drc/DRCtech.c | 66 ++++++++++++++++++++++++++++++++++++-------------- drc/drc.h | 3 ++- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/VERSION b/VERSION index 056d2468..600ba498 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.539 +8.3.540 diff --git a/drc/DRCbasic.c b/drc/DRCbasic.c index d62e8bc0..f75b4522 100644 --- a/drc/DRCbasic.c +++ b/drc/DRCbasic.c @@ -823,7 +823,7 @@ drcTile (tile, arg) if (TTMaskHasType(&cptr->drcc_corner, TiGetTopType(tpr))) { errRect.r_ybot -= cdist; - if (DRCEuclidean) + if (DRCEuclidean && !(cptr->drcc_flags & DRC_MANHATTAN)) arg->dCD_radial |= RADIAL_SW; } } @@ -851,7 +851,8 @@ drcTile (tile, arg) TiGetBottomType(tpr))) { errRect.r_ytop += cdist; - if (DRCEuclidean) + if (DRCEuclidean && + !(cptr->drcc_flags & DRC_MANHATTAN)) arg->dCD_radial |= RADIAL_NW; } } @@ -897,7 +898,7 @@ drcTile (tile, arg) if (TTMaskHasType(&cptr->drcc_corner, TiGetBottomType(tpl))) { errRect.r_ytop += cdist; - if (DRCEuclidean) + if (DRCEuclidean && !(cptr->drcc_flags & DRC_MANHATTAN)) arg->dCD_radial |= RADIAL_NE; } } @@ -924,7 +925,8 @@ drcTile (tile, arg) if (TTMaskHasType(&cptr->drcc_corner, TiGetTopType(tpl))) { errRect.r_ybot -= cdist; - if (DRCEuclidean) + if (DRCEuclidean && + !(cptr->drcc_flags & DRC_MANHATTAN)) arg->dCD_radial |= RADIAL_SE; } } @@ -1196,7 +1198,7 @@ drcTile (tile, arg) if (TTMaskHasType(&cptr->drcc_corner, TiGetBottomType(tpx))) { errRect.r_xtop += cdist; - if (DRCEuclidean) + if (DRCEuclidean && !(cptr->drcc_flags & DRC_MANHATTAN)) arg->dCD_radial |= RADIAL_SE; } @@ -1213,7 +1215,7 @@ drcTile (tile, arg) if (TTMaskHasType(&cptr->drcc_corner, TiGetBottomType(tpx))) { errRect.r_xbot -= cdist; - if (DRCEuclidean) + if (DRCEuclidean && !(cptr->drcc_flags & DRC_MANHATTAN)) arg->dCD_radial |= RADIAL_SW; } } @@ -1250,7 +1252,7 @@ drcTile (tile, arg) if (TTMaskHasType(&cptr->drcc_corner, TiGetTopType(tpx))) { errRect.r_xbot -= cdist; - if (DRCEuclidean) + if (DRCEuclidean && !(cptr->drcc_flags & DRC_MANHATTAN)) arg->dCD_radial |= RADIAL_NW; } @@ -1266,7 +1268,7 @@ drcTile (tile, arg) if (TTMaskHasType(&cptr->drcc_corner, TiGetTopType(tpx))) { errRect.r_xtop += cdist; - if (DRCEuclidean) + if (DRCEuclidean && !(cptr->drcc_flags & DRC_MANHATTAN)) arg->dCD_radial |= RADIAL_NE; } } diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 9a6422b4..9d5364e1 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -1031,10 +1031,10 @@ DRCTechAddRule(sectionName, argc, argv) } ruleKeys[] = { {"angles", 4, 4, drcAngles, "layers 45|90 why"}, - {"edge", 8, 9, drcEdge, - "layers1 layers2 distance okTypes cornerTypes cornerDistance why [plane]"}, - {"edge4way", 8, 9, drcEdge, - "layers1 layers2 distance okTypes cornerTypes cornerDistance why [plane]"}, + {"edge", 8, 10, drcEdge, + "layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"}, + {"edge4way", 8, 10, drcEdge, + "layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"}, {"exact_overlap", 2, 2, drcExactOverlap, "layers"}, {"extend", 5, 6, drcExtend, @@ -1985,6 +1985,10 @@ drcSpacing3(argc, argv) * Side effects: * Adds rules to the DRC rule table. * + * Notes: + * 8/13/2025: Added "manhattan_dist" as an option indicating + * that corner checks should assume manhattan distance. Otherwise + * the rule type is the same as "touching_illegal". *------------------------------------------------------------------- */ @@ -2010,6 +2014,7 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency, bool touchingok = TRUE; bool cornerok = FALSE; bool surroundok = FALSE; + unsigned short flags = 0; if (!strcmp(adjacency, "surround_ok")) { @@ -2065,6 +2070,12 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency, touchingok = FALSE; needtrigger = FALSE; } + else if (!strcmp(adjacency, "manhattan_dist")) + { + touchingok = FALSE; + needtrigger = FALSE; + flags = DRC_MANHATTAN; + } else { TechError("Badly formed drc spacing line: need \"touching_ok\", " @@ -2198,7 +2209,7 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency, else { drcAssign(dpnew, distance, dp->drcc_next, &tmp1, - &tmp2, why, wwidth, DRC_FORWARD, plane2, plane); + &tmp2, why, wwidth, DRC_FORWARD | flags, plane2, plane); dp->drcc_next = dpnew; } @@ -2267,7 +2278,8 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency, { drcAssign(dpnew,distance,dp->drcc_next, &tmp1, &tmp2, why, wwidth, - DRC_REVERSE | DRC_BOTHCORNERS, plane2, plane); + DRC_REVERSE | DRC_BOTHCORNERS | flags, + plane2, plane); dp->drcc_next = dpnew; } } @@ -2320,7 +2332,8 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency, else { drcAssign(dpnew, distance, dp->drcc_next, &tmp1, &tmp2, - why, distance, DRC_FORWARD, plane2, plane); + why, distance, DRC_FORWARD | flags, + plane2, plane); dp->drcc_next = dpnew; } @@ -2358,7 +2371,8 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency, { drcAssign(dpnew, distance, dp->drcc_next, &tmp1, &tmp2, why, distance, - DRC_REVERSE | DRC_BOTHCORNERS, plane2, plane); + DRC_REVERSE | DRC_BOTHCORNERS | flags, + plane2, plane); dp->drcc_next = dpnew; } } @@ -2418,7 +2432,7 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency, TTMaskZero(&tmp2); drcAssign(dpnew, 1, dp->drcc_next, &tmp1, &tmp2, why, - distance, DRC_FORWARD, plane2, plane); + distance, DRC_FORWARD | flags, plane2, plane); dp->drcc_next = dpnew; } } @@ -2640,8 +2654,8 @@ drcSpacing(argc, argv) * Process a primitive edge rule. * This is of the form: * - * edge layers1 layers2 dist OKtypes cornerTypes cornerDist why [plane] - * or edge4way layers1 layers2 dist OKtypes cornerTypes cornerDist why [plane] + * edge layers1 layers2 dist OKtypes cornerTypes cornerDist [option] why [plane] + * or edge4way layers1 layers2 dist OKtypes cornerTypes cornerDist [option] why [plane] * * e.g, * @@ -2650,6 +2664,9 @@ drcSpacing(argc, argv) * An "edge" rule is applied only down and to the left. * An "edge4way" rule is applied in all four directions. * + * "option" can be "manhattan_dist", which forces the corner areas to be + * checked per manhattan distance rules, not euclidean distance rules. + * * Results: * Returns greater of dist and cdist. * @@ -2668,14 +2685,30 @@ drcEdge(argc, argv) int distance = atoi(argv[3]); char *okTypes = argv[4], *cornerTypes = argv[5]; int cdist = atoi(argv[6]); - int why = drcWhyCreate(argv[7]); + unsigned short flags = 0; + int why; bool fourway = (strcmp(argv[0], "edge4way") == 0); TileTypeBitMask set1, set2, setC, setM; DRCCookie *dp, *dpnew; - int plane, checkPlane, tmpPlane; + int plane, checkPlane, tmpPlane = 0; PlaneMask pMask1, pMaskM, pMaskC, pset, ptest; TileType i, j; + if ((argc > 7) && (!strcmp(argv[7], "manhattan_dist"))) + { + flags = DRC_MANHATTAN; + why = drcWhyCreate(argv[8]); + if (argc == 10) + tmpPlane = DBTechNoisyNamePlane(argv[9]); + argc--; + } + else + { + why = drcWhyCreate(argv[7]); + if (argc == 9) + tmpPlane = DBTechNoisyNamePlane(argv[8]); + } + /* * Edge4way rules produce [j][i] entries as well as [i][j] * ones, and check both corners rather than just one corner. @@ -2708,9 +2741,6 @@ drcEdge(argc, argv) return (0); } - if (argc == 9) - tmpPlane = DBTechNoisyNamePlane(argv[8]); - /* * OKtypes determine the checkPlane. If checkPlane exists, it should * only be used to check against the plane of OKtypes. @@ -2786,7 +2816,7 @@ drcEdge(argc, argv) dp = drcFindBucket(i, j, distance); dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); drcAssign(dpnew, distance, dp->drcc_next, &setM, &setC, - why, cdist, DRC_FORWARD, checkPlane, plane); + why, cdist, DRC_FORWARD | flags, checkPlane, plane); if (fourway) dpnew->drcc_flags |= DRC_BOTHCORNERS; dp->drcc_next = dpnew; @@ -2796,7 +2826,7 @@ drcEdge(argc, argv) dp = drcFindBucket(j, i, distance); dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); drcAssign(dpnew,distance,dp->drcc_next, &setM, &setC, - why, cdist, DRC_REVERSE, checkPlane, plane); + why, cdist, DRC_REVERSE | flags, checkPlane, plane); dpnew->drcc_flags |= DRC_BOTHCORNERS; dp->drcc_next = dpnew; } diff --git a/drc/drc.h b/drc/drc.h index c62b8019..346fab7c 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -80,11 +80,12 @@ typedef struct drccookie #define DRC_ANGLES_90 0x0800 #define DRC_SPLITTILE 0x1000 #define DRC_RUNLENGTH 0x2000 +#define DRC_MANHATTAN 0x4000 #define DRC_NONSTANDARD (DRC_AREA|DRC_MAXWIDTH|DRC_RECTSIZE\ |DRC_ANGLES_90|DRC_OFFGRID) /* More flags for indicating what the rule type represents */ -#define DRC_CIFRULE 0x4000 +#define DRC_CIFRULE 0x8000 #define DRC_PENDING 0 #define DRC_UNPROCESSED CLIENTDEFAULT