diff --git a/Makefile b/Makefile index cf262b42..e1d61fbd 100644 --- a/Makefile +++ b/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 diff --git a/drc/DRCcontin.c b/drc/DRCcontin.c index efb7ec43..41e97133 100644 --- a/drc/DRCcontin.c +++ b/drc/DRCcontin.c @@ -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. */ diff --git a/drc/DRCmain.c b/drc/DRCmain.c index b211adca..6a2e9ade 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -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); */ diff --git a/drc/DRCsubcell.c b/drc/DRCsubcell.c index eea576c0..6fb049a9 100644 --- a/drc/DRCsubcell.c +++ b/drc/DRCsubcell.c @@ -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); } diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 7bd7e1ab..6f477424 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -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; diff --git a/drc/drc.h b/drc/drc.h index 390a3cde..061a1ce2 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -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(); diff --git a/tcltk/toolkit.tcl b/tcltk/toolkit.tcl index 75fa12cd..1ec0778e 100644 --- a/tcltk/toolkit.tcl +++ b/tcltk/toolkit.tcl @@ -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 }