Made a few corrections to recent code additions. Also added

more points to accept interrupts during DRC checks, and
modified the tech file parser to allow the full syntax for
magic layers that is allowed elsewhere (e.g., "(*ndiff,poly)/a")
(this applies to magic layers, not GDS layers).  Fixed a
clipping error in the bloat-all function which was causing
non-manhattan geometry to produce bad results, which would
cause false-positive DRC errors when used in a CIF-DRC rule.
This commit is contained in:
R. Timothy Edwards 2025-10-31 17:37:02 -04:00
parent 246c0ea7a4
commit f3adea8c65
4 changed files with 64 additions and 20 deletions

View File

@ -1 +1 @@
8.3.571 8.3.572

View File

@ -28,6 +28,7 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "utils/signals.h"
#include "tiles/tile.h" #include "tiles/tile.h"
#include "utils/hash.h" #include "utils/hash.h"
#include "database/database.h" #include "database/database.h"
@ -1478,19 +1479,28 @@ cifBloatAllFunc(
if (op->co_distance > 0) if (op->co_distance > 0)
{ {
Rect cifarea;
cifarea.r_xbot = area.r_xbot;
cifarea.r_ybot = area.r_ybot;
cifarea.r_xtop = area.r_xtop;
cifarea.r_ytop = area.r_ytop;
/* Note: This is non-optimal, as it causes all tiles /* Note: This is non-optimal, as it causes all tiles
* in the "bloat" group to be re-processed for each * in the "bloat" group to be re-processed for each
* tile processed in the search group. However, it * tile processed in the search group. However, it
* is difficult to find an optimal method. * is difficult to find an optimal method.
*/ */
STACKPUSH(t, ResetStack); STACKPUSH(t, ResetStack);
GeoClip(&area, &clipArea); GeoClip(&cifarea, &clipArea);
if (GEO_RECTNULL(&area)) if (GEO_RECTNULL(&cifarea))
continue; continue;
} }
/* Diagonal: If expanding across the edge of a diagonal, */ /* Diagonal: If expanding across the edge of a diagonal, then */
/* then just fill the whole tile. */ /* just fill the whole tile. Note that diagonal tiles are not */
/* clipped; the clipping only determines if the tile is */
/* outside the clip area. */
if (IsSplit(t)) if (IsSplit(t))
{ {
@ -1505,8 +1515,11 @@ cifBloatAllFunc(
CIFPaintTable, (PaintUndoInfo *) NULL); CIFPaintTable, (PaintUndoInfo *) NULL);
} }
else else
{
GeoClip(&area, &clipArea);
DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area, DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area,
CIFPaintTable, (PaintUndoInfo *) NULL); CIFPaintTable, (PaintUndoInfo *) NULL);
}
/* Top */ /* Top */
for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp))
@ -1547,6 +1560,7 @@ cifBloatAllFunc(
TiSetClient(t, CIF_UNPROCESSED); TiSetClient(t, CIF_UNPROCESSED);
} }
if (SigInterruptPending) return 1;
return 0; /* Keep the search alive. . . */ return 0; /* Keep the search alive. . . */
} }
@ -4695,12 +4709,13 @@ cifBridgeLimFunc2(
void void
cifInteractingRegions( cifInteractingRegions(
CIFOp *op, CIFOp *op,
const Rect *area, /* Area of interest to check */
CellDef *cellDef, CellDef *cellDef,
Plane *temps[], /* Planes to use for temporaries. */ Plane *temps[], /* Planes to use for temporaries. */
Plane *plane) Plane *plane)
{ {
Tile *tile = NULL, *t, *tp; Tile *tile = NULL, *t, *tp;
Rect area; Rect rect;
int i; int i;
TileType type; TileType type;
bool interacts; bool interacts;
@ -4709,7 +4724,7 @@ cifInteractingRegions(
if (RegStack == (Stack *)NULL) if (RegStack == (Stack *)NULL)
RegStack = StackNew(64); RegStack = StackNew(64);
while (DBSrPaintArea((Tile *)tile, plane, &TiPlaneRect, &CIFSolidBits, while (DBSrPaintArea((Tile *)tile, plane, area, &CIFSolidBits,
cifSquaresInitFunc, (ClientData)NULL) != 0) cifSquaresInitFunc, (ClientData)NULL) != 0)
{ {
/* Now, search for (nontrivially) connected tiles in all */ /* Now, search for (nontrivially) connected tiles in all */
@ -4729,7 +4744,10 @@ cifInteractingRegions(
TiSetClientINT(t, CIF_PROCESSED); TiSetClientINT(t, CIF_PROCESSED);
/* Get tile area for interaction search */ /* Get tile area for interaction search */
TiToRect(t, &area); TiToRect(t, &rect);
/* Ignore tiles outside of the search area */
if (!GEO_SURROUND(area, &rect)) continue;
/* "interacting" includes touching as well as overlapping, so expand /* "interacting" includes touching as well as overlapping, so expand
* search by one unit in every direction and then check overlap. * search by one unit in every direction and then check overlap.
@ -4738,10 +4756,10 @@ cifInteractingRegions(
*/ */
if ((pointertype)op->co_client & CIFOP_INT_TOUCHING) if ((pointertype)op->co_client & CIFOP_INT_TOUCHING)
{ {
area.r_xbot -= 1; rect.r_xbot -= 1;
area.r_xtop += 1; rect.r_xtop += 1;
area.r_ybot -= 1; rect.r_ybot -= 1;
area.r_ytop += 1; rect.r_ytop += 1;
} }
/* Check if this tile interacts with the rule's types, or skip */ /* Check if this tile interacts with the rule's types, or skip */
@ -4749,7 +4767,7 @@ cifInteractingRegions(
if (!interacts) if (!interacts)
{ {
if (cifSrTiles2(op, &area, cellDef, temps, cifInteractFunc, (ClientData)NULL)) if (cifSrTiles2(op, &rect, cellDef, temps, cifInteractFunc, (ClientData)NULL))
interacts = TRUE; interacts = TRUE;
} }
@ -4802,8 +4820,8 @@ cifInteractingRegions(
if (interacts) if (interacts)
{ {
TiToRect(t, &area); TiToRect(t, &rect);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *)NULL); DBPaintPlane(cifPlane, &rect, CIFPaintTable, (PaintUndoInfo *)NULL);
} }
/* Top */ /* Top */
@ -4838,6 +4856,9 @@ cifInteractingRegions(
STACKPUSH(tp, RegStack); STACKPUSH(tp, RegStack);
} }
} }
/* Allow interrupts here */
if (SigInterruptPending) break;
} }
} }
@ -5313,7 +5334,7 @@ CIFGenLayer(
DBClearPaintPlane(nextPlane); DBClearPaintPlane(nextPlane);
cifPlane = nextPlane; cifPlane = nextPlane;
cifInteractingRegions(op, cellDef, temps, curPlane); cifInteractingRegions(op, area, cellDef, temps, curPlane);
temp = curPlane; temp = curPlane;
curPlane = nextPlane; curPlane = nextPlane;
nextPlane = temp; nextPlane = temp;

View File

@ -234,7 +234,7 @@ cifParseLayers(
*/ */
{ {
TileTypeBitMask curCifMask, curPaintMask; TileTypeBitMask curCifMask, curPaintMask;
char curLayer[40], *p, *cp; char curLayer[512], *p, *cp;
TileType paintType; TileType paintType;
int i; int i;
bool allResidues; bool allResidues;
@ -246,6 +246,10 @@ cifParseLayers(
{ {
p = curLayer; p = curLayer;
if (*string == '(')
while ((*string != ')') && (*string != 0))
*p++ = *string++;
if (*string == '*') if (*string == '*')
{ {
allResidues = TRUE; allResidues = TRUE;
@ -263,7 +267,22 @@ cifParseLayers(
if (paintMask != NULL) if (paintMask != NULL)
{ {
paintType = DBTechNameTypes(curLayer, &curPaintMask); if (*curLayer == '(')
{
TileType t;
/* Layer groups with parentheses can only be paint types,
* and will be parsed accordingly. Residues will be
* handled within the group. Set paintType to -3, which
* is flagged and handled below.
*/
DBTechNoisyNameMask(curLayer, &curPaintMask);
paintType = -3;
allResidues = FALSE;
}
else
paintType = DBTechNameTypes(curLayer, &curPaintMask);
if (paintType >= 0) goto okpaint; if (paintType >= 0) goto okpaint;
} }
else paintType = -2; else paintType = -2;
@ -299,7 +318,7 @@ okpaint:
TechError("Ambiguous layer (type) \"%s\".\n", curLayer); TechError("Ambiguous layer (type) \"%s\".\n", curLayer);
continue; continue;
} }
if (paintType >= 0) if ((paintType >= 0) || (paintType == -3))
{ {
if (paintType == TT_SPACE && spaceOK ==0) if (paintType == TT_SPACE && spaceOK ==0)
TechError("\"Space\" layer not permitted in CIF rules.\n"); TechError("\"Space\" layer not permitted in CIF rules.\n");

View File

@ -27,6 +27,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/magic.h" #include "utils/magic.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/signals.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "tiles/tile.h" #include "tiles/tile.h"
#include "utils/hash.h" #include "utils/hash.h"
@ -134,7 +135,7 @@ drcFindOtherCells(use, area)
* different for "drc why" commands than for "drc check". * different for "drc why" commands than for "drc check".
* *
* Returns: * Returns:
* 0 to keep the search going. * 0 to keep the search going. In case of an interrupt, return 1.
* *
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -156,6 +157,9 @@ drcSubCopyErrors(tile, cxp)
arg->dCD_clientData); arg->dCD_clientData);
(*(arg->dCD_errors))++; (*(arg->dCD_errors))++;
/* Allow a break here */
if (SigInterruptPending) return 1;
return 0; return 0;
} }