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:
parent
5cb645e2d5
commit
2a4baa82c3
4
Makefile
4
Makefile
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
||||
|
|
|
|||
|
|
@ -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); */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue