Found a way to work around the problem of having subcell DRC

errors show up as "See error definition in subcell", which has
been the case since I modified the code to prevent showing DRC
errors in subcells that have been resolved by the hierarchy
above them.  DRC errors are now intelligently searched
downward in the heirarchy when enumerated for "drc why".
Also changed the DRC check tile definition to offset such that
there is a tile centered on the origin, instead of the origin
being between four tiles.  Since most layouts are subcells and
most subcells are small relative to the DRC check tile area,
and most subcells are placed near the origin, then most subcells
will appear in only one tile, which speeds up the DRC process
somewhat.
This commit is contained in:
R. Timothy Edwards 2025-10-23 17:11:44 -04:00
parent 42aa06f8f5
commit 0ac4d3a465
4 changed files with 109 additions and 33 deletions

View File

@ -1 +1 @@
8.3.567
8.3.568

View File

@ -277,13 +277,42 @@ drcPrintError (celldef, rect, cptr, scx)
{
HashEntry *h;
int i;
Rect *area, r;
Rect *area;
int drcsave = DRCErrorCount;
/* Forward declaration */
void drcWhyFunc(SearchContext *scx, ClientData cdarg);
ASSERT (cptr != (DRCCookie *) NULL, "drcPrintError");
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
{
SearchContext newscx;
/* Recurse into subcells to find the error being flagged */
/* recursive call is drcWhyFunc, clientdata is FALSE */
newscx.scx_area = *rect;
newscx.scx_use = scx->scx_use;
newscx.scx_x = scx->scx_use->cu_xlo;
newscx.scx_y = scx->scx_use->cu_ylo;
newscx.scx_trans = scx->scx_trans;
DBTreeSrCells(&newscx, 0, drcWhyFunc, (ClientData)FALSE);
}
/* Hack to avoid printing "no errors found" when recursing on
* drcWhyFunc() above. In some cases like run-length rules,
* changing the search area can make the error disappear. If
* that happens, "See error definition in subcell" will be
* printed. The underlying error needs to be fixed, but this
* method provides the information the user needs to find the
* error.
*/
if (drcsave == DRCErrorCount)
{
i = DRCErrorList[cptr->drcc_tag];
if (i == 0)
TxPrintf("%s\n", drcSubstitute(cptr));
@ -292,6 +321,7 @@ drcPrintError (celldef, rect, cptr, scx)
DRCErrorCount += 1;
DRCErrorList[cptr->drcc_tag] = i + 1;
}
}
}
/* Same routine as above, but output goes to a Tcl list and is appended */
@ -309,11 +339,33 @@ drcListError (celldef, rect, cptr, scx)
HashEntry *h;
int i;
Rect *area;
int drcsave = DRCErrorCount;
/* Forward declaration */
void drcWhyFunc(SearchContext *scx, ClientData cdarg);
ASSERT (cptr != (DRCCookie *) NULL, "drcListError");
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
{
SearchContext newscx;
/* Recurse into subcells to find the error being flagged */
/* recursive call is drcWhyFunc, clientdata is TRUE */
newscx.scx_area = *rect;
newscx.scx_use = scx->scx_use;
newscx.scx_x = scx->scx_use->cu_xlo;
newscx.scx_y = scx->scx_use->cu_ylo;
newscx.scx_trans = scx->scx_trans;
DBTreeSrCells(&newscx, 0, drcWhyFunc, (ClientData)TRUE);
}
if (drcsave == DRCErrorCount)
{
i = DRCErrorList[cptr->drcc_tag];
if (i == 0)
{
@ -328,6 +380,7 @@ drcListError (celldef, rect, cptr, scx)
DRCErrorCount += 1;
DRCErrorList[cptr->drcc_tag] = i + 1;
}
}
}
/* Same routine as above, but output for every single error is recorded */
@ -343,6 +396,10 @@ drcListallError (celldef, rect, cptr, scx)
Tcl_Obj *lobj, *pobj;
HashEntry *h;
Rect *area, r;
int drcsave = DRCErrorCount;
/* Forward declaration */
int drcWhyAllFunc(SearchContext *scx, ClientData cdarg);
ASSERT (cptr != (DRCCookie *) NULL, "drcListallError");
@ -350,6 +407,24 @@ drcListallError (celldef, rect, cptr, scx)
GeoTransRect(&scx->scx_trans, rect, &r);
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
{
SearchContext newscx;
/* Recurse into subcells to find the error being flagged */
/* recursive call is drcWhyAllFunc, clientdata is NULL */
newscx.scx_area = *rect;
newscx.scx_use = scx->scx_use;
newscx.scx_x = scx->scx_use->cu_xlo;
newscx.scx_y = scx->scx_use->cu_ylo;
newscx.scx_trans = scx->scx_trans;
DBTreeSrCells(&newscx, 0, drcWhyAllFunc, (ClientData)NULL);
}
if (drcsave == DRCErrorCount)
{
DRCErrorCount += 1;
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
lobj = (Tcl_Obj *) HashGetValue(h);
@ -365,6 +440,7 @@ drcListallError (celldef, rect, cptr, scx)
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
HashSetValue(h, lobj);
}
}
#else

View File

@ -734,9 +734,9 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
* square separately.
*/
x = (area->r_xbot/DRCStepSize) * DRCStepSize;
x = (area->r_xbot/DRCStepSize) * DRCStepSize - (DRCStepSize / 2);
if (x > area->r_xbot) x -= DRCStepSize;
y = (area->r_ybot/DRCStepSize) * DRCStepSize;
y = (area->r_ybot/DRCStepSize) * DRCStepSize - (DRCStepSize / 2);
if (y > area->r_ybot) y -= DRCStepSize;
for (square.r_xbot = x; square.r_xbot < area->r_xtop;
square.r_xbot += DRCStepSize)