Substantially overhauled the way that the DRC checker finds and

processes "interaction areas".  This should eliminate weirdnesses
where errors will fail to show up in a subcell that does not
interact with paint or other subcells in the top level edit cell.
These errors cannot be reported directly in the top level cell,
but a new error message has been created to direct the user to
check the subcell for errors.  Also:  Modified the toolkit procedures
to force DRC to be run on newly created or modified parameterized
cell layouts.  There is some oddity about the process that causes
DRC errors to be delayed unless a print statement is put before the
DRC check;  I would like to investigate this further.
This commit is contained in:
Tim Edwards 2020-10-15 17:31:20 -04:00
parent 5cb645e2d5
commit 2a4baa82c3
7 changed files with 113 additions and 21 deletions

View File

@ -98,7 +98,7 @@ install-tcl-real: install-tcl-dirs
clean:
for dir in ${MODULES} ${PROGRAMS} ${TECH} ${UNUSED_MODULES}; do \
(cd $$dir && ${MAKE} clean); done
${RM} *.tmp */*.tmp *.sav */*.sav *.log TAGS tags */Depend
${RM} *.tmp */*.tmp *.sav */*.sav *.log TAGS tags
distclean:
touch defs.mak
@ -107,7 +107,7 @@ distclean:
${RM} ${MAGICDIR}/scripts/default.conf
${RM} ${MAGICDIR}/scripts/config.log ${MAGICDIR}/scripts/config.status
${RM} scripts/magic.spec magic-`cat VERSION` magic-`cat VERSION`.tgz
${RM} *.log
${RM} *.log */Depend
dist:
${RM} scripts/magic.spec magic-`cat VERSION` magic-`cat VERSION`.tgz

View File

@ -197,10 +197,13 @@ DRCCheckThis (celldef, operation, area)
* of CellDefs waiting for DRC
*/
/* Ignore read-only, internal, and vendor GDS cells. None of these */
/* can contain DRC errors that could be fixed in magic. */
/* Ignore internal GDS cells. */
/* Note that this rescinds the former behavior of ignoring DRC on */
/* vendor and read-only cells. Such cells will be flattened in */
/* interaction areas and show errors anyway, so not showing errors */
/* in the cell is just confusing. */
if (celldef->cd_flags & (CDVENDORGDS | CDNOEDIT | CDINTERNAL)) return;
if (celldef->cd_flags & CDINTERNAL) return;
/* Insert celldef into list of Defs waiting to be checked, unless */
/* it is already there. */
@ -683,7 +686,7 @@ drcCheckTile(tile, arg)
DRCErrorType = TT_ERROR_S;
(void) DRCInteractionCheck(celldef, &square, &erasebox,
drcPaintError, (ClientData) drcTempPlane);
drcPaintError, (ClientData)drcTempPlane);
/* Check #3: check for array formation errors in the area. */

View File

@ -615,11 +615,9 @@ drcWhyFunc(scx, cdarg)
/* Check paint and interactions in this subcell. */
(void) DRCInteractionCheck(def, &scx->scx_area, &scx->scx_area,
(dolist) ? drcListError : drcPrintError,
(ClientData) scx);
(dolist) ? drcListError : drcPrintError, (ClientData) scx);
(void) DRCArrayCheck(def, &scx->scx_area,
(dolist) ? drcListError : drcPrintError,
(ClientData) scx);
(dolist) ? drcListError : drcPrintError, (ClientData) scx);
/* New behavior: Don't search children, instead propagate errors up. */
/* (void) DBCellSrArea(scx, drcWhyFunc, (ClientData)cdarg); */
@ -639,9 +637,9 @@ drcWhyAllFunc(scx, cdarg)
/* Check paint and interactions in this subcell. */
(void) DRCInteractionCheck(def, &scx->scx_area, &scx->scx_area,
drcListallError, (ClientData)scx);
drcListallError, (Plane *)NULL, (ClientData)scx);
(void) DRCArrayCheck(def, &scx->scx_area,
drcListallError, (ClientData)scx);
drcListallError, (Plane *)NULL, (ClientData)scx);
/* New behavior: Don't search children, instead propagate errors up. */
/* (void) DBCellSrArea(scx, drcWhyAllFunc, (ClientData)cdarg); */

View File

@ -61,6 +61,19 @@ static DRCCookie drcSubcellCookie = {
(DRCCookie *) NULL
};
/* The cookie below is dummied up to provide an error message for
* errors that are in a subcell non-interaction area and have been
* copied up into the parent without flattening
*/
static DRCCookie drcInSubCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
DRC_IN_SUBCELL_TAG,
(DRCCookie *) NULL
};
extern int DRCErrorType;
/*
@ -94,6 +107,33 @@ drcFindOtherCells(use, area)
return 0;
}
/* For each tile found in drcCopyErrorsFunc(), translate the */
/* tile position into the coordinate system of the parent cell */
/* (represented by the drcTemp plane in ClientData) and */
/* copy (paint) into it. */
int
drcSubCopyErrors(tile, cxp)
Tile *tile;
TreeContext *cxp;
{
Rect area;
Rect destArea;
struct drcClientData *arg = (struct drcClientData *)cxp->tc_filter->tf_arg;
// DBTreeSrTiles() checks its own tiles, which we want to ignore.
if (arg->dCD_celldef == cxp->tc_scx->scx_use->cu_def) return 0;
TiToRect(tile, &area);
GeoClip(&area, &cxp->tc_scx->scx_area);
GeoTransRect(&cxp->tc_scx->scx_trans, &area, &destArea);
(*(arg->dCD_function))(arg->dCD_celldef, &destArea, arg->dCD_cptr,
arg->dCD_clientData);
(*(arg->dCD_errors))++;
return 0;
}
/*
* ----------------------------------------------------------------------------
@ -146,12 +186,24 @@ drcSubcellFunc(subUse, propagate)
/* all cells are checked and errors propagate to the top level. */
subIntArea = GeoNullRect;
#if (0)
/* NOTE: DRC errors inside a subcell should be ignored for */
/* the purpose of finding interactions. Errors should only */
/* be copied up into the parent when in a non-interaction */
/* area. This is done below in DRCFindInteractions(). */
/* (Method added by Tim, 10/15/2020) */
/* Maybe S and PS errors should be pulled here? */
DBSrPaintArea((Tile *) NULL, subUse->cu_def->cd_planes[PL_DRC_ERROR],
&TiPlaneRect, &DBAllButSpaceBits, drcIncludeArea,
(ClientData) &subIntArea);
GeoTransRect(&(subUse->cu_transform), &subIntArea, &locIntArea);
GeoInclude(&locIntArea, &intArea);
#endif
if (!GEO_RECTNULL(&subIntArea)) *propagate = TRUE;
drcCurSub = subUse;
@ -555,12 +607,17 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
void (*savedPaintPlane)();
struct drcClientData arg;
SearchContext scx;
TileTypeBitMask drcMask;
drcSubFunc = func;
drcSubClientData = cdarg;
oldTiles = DRCstatTiles;
count = 0;
/* Create a mask with only TT_ERROR_P in it */
TTMaskZero(&drcMask);
TTMaskSetType(&drcMask, TT_ERROR_P);
/* Divide the area to be checked up into squares. Process each
* square separately.
*/
@ -585,6 +642,16 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
cliparea = square;
GeoClip(&cliparea, area);
/* Prepare for subcell search */
DRCDummyUse->cu_def = def;
scx.scx_use = DRCDummyUse;
scx.scx_trans = GeoIdentityTransform;
arg.dCD_celldef = def;
arg.dCD_errors = &count;
arg.dCD_cptr = &drcInSubCookie;
arg.dCD_function = func;
arg.dCD_clientData = cdarg;
/* Find all the interactions in the square, and clip to the error
* area we're interested in. */
@ -600,6 +667,11 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
errorSaveType = DRCErrorType;
DRCErrorType = TT_ERROR_P; // Basic check is always ERROR_P
DRCBasicCheck(def, &intArea, &subArea, func, cdarg);
/* Copy errors up from all non-interacting children */
scx.scx_area = subArea;
DBTreeSrTiles(&scx, &drcMask, 0, drcSubCopyErrors, &arg);
DRCErrorType = errorSaveType;
continue;
}
@ -632,6 +704,9 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
subArea.r_ybot = intArea.r_ytop;
GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo);
DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg);
/* Copy errors up from all non-interacting children */
scx.scx_area = subArea;
DBTreeSrTiles(&scx, &drcMask, 0, drcSubCopyErrors, &arg);
}
/* check below */
if (intArea.r_ybot > eraseClip.r_ybot)
@ -640,6 +715,9 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
subArea.r_ytop = intArea.r_ybot;
GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo);
DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg);
/* Copy errors up from all non-interacting children */
scx.scx_area = subArea;
DBTreeSrTiles(&scx, &drcMask, 0, drcSubCopyErrors, &arg);
}
subArea.r_ytop = intArea.r_ytop;
subArea.r_ybot = intArea.r_ybot;
@ -650,6 +728,9 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
subArea.r_xbot = intArea.r_xtop;
GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo);
DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg);
/* Copy errors up from all non-interacting children */
scx.scx_area = subArea;
DBTreeSrTiles(&scx, &drcMask, 0, drcSubCopyErrors, &arg);
}
/* check left */
if (intArea.r_xbot > eraseClip.r_xbot)
@ -658,6 +739,9 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
subArea.r_xbot = eraseClip.r_xbot;
GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo);
DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg);
/* Copy errors up from all non-interacting children */
scx.scx_area = subArea;
DBTreeSrTiles(&scx, &drcMask, 0, drcSubCopyErrors, &arg);
}
DRCErrorType = errorSaveType;
}
@ -672,9 +756,6 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
DRCstatInteractions += 1;
GEO_EXPAND(&intArea, DRCTechHalo, &scx.scx_area);
DRCDummyUse->cu_def = def;
scx.scx_use = DRCDummyUse;
scx.scx_trans = GeoIdentityTransform;
DBCellClearDef(DRCdef);
savedPaintTable = DBNewPaintTable(DRCCurStyle->DRCPaintTable);
@ -696,15 +777,10 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
/* Check for illegal partial overlaps. */
scx.scx_use = DRCDummyUse;
scx.scx_area = intArea;
scx.scx_trans = GeoIdentityTransform;
arg.dCD_celldef = DRCdef;
arg.dCD_clip = &intArea;
arg.dCD_errors = &count;
arg.dCD_celldef = DRCdef;
arg.dCD_cptr = &drcSubcellCookie;
arg.dCD_function = func;
arg.dCD_clientData = cdarg;
(void) DBTreeSrUniqueTiles(&scx, &DRCCurStyle->DRCExactOverlapTypes,
0, drcExactOverlapTile, (ClientData) &arg);
}

View File

@ -582,6 +582,11 @@ DRCTechStyleInit()
/* (see DRCsubcell.c). */
drcWhyCreate("This layer can't abut or partially overlap between subcells");
/* Fourth DRC entry is associated with the statically-allocated */
/* drcSubcellCookie and has a tag of DRC_IN_SUBCELL_TAG = 4 */
/* (see DRCsubcell.c). */
drcWhyCreate("See error definition in the subcell");
DRCTechHalo = 0;
/* Put a dummy rule at the beginning of the rules table for each entry */
@ -2000,6 +2005,9 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency,
TTMaskClearMask3(&tmp1, &DBPlaneTypes[plane2], set1);
TTMaskAndMask3(&tmp2, &DBPlaneTypes[plane], &setRreverse);
/* NOTE: This is needed for some situation, but I */
/* do not recall the exact nature of it. In other */
/* cases only the simple rule check is needed. */
if (needtrigger)
{
DRCCookie *dptrig;
@ -2036,6 +2044,7 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency,
dp = drcFindBucket(j, i, distance);
dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie));
/* See above */
if (needtrigger)
{
DRCCookie *dptrig;

View File

@ -47,6 +47,7 @@ typedef struct drccookie
#define DRC_ARRAY_OVERLAP_TAG 1
#define DRC_OVERLAP_TAG 2
#define DRC_SUBCELL_OVERLAP_TAG 3
#define DRC_IN_SUBCELL_TAG 4
/* *This is size "int" because it holds an area for DRC_AREA rules, */
/* and therefore may have twice the bit length of a normal rule distance. */
@ -266,6 +267,7 @@ extern DRCCountList *DRCCount();
extern int DRCFind();
extern void DRCCatchUp();
extern bool DRCFindInteractions();
extern int DRCBasicCheck();
extern void DRCPrintStyle();
extern void DRCSetStyle();

View File

@ -363,6 +363,8 @@ proc magic::gencell_change {instname gencell_type library parameters} {
eval "box values $savebox"
snap $snaptype
resumeall
puts stdout "Done."
drc check
redraw
}
@ -472,6 +474,8 @@ proc magic::gencell_create {gencell_type library parameters} {
snap $snaptype
resumeall
redraw
puts stdout "Done."
drc check
return $instname
}