/* * PlowRules3.c -- * * Plowing rules: new sliver-avoidance rules. * These are applied by plowProcessEdge() for each edge that is to be moved. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/plow/PlowRules3.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; #endif /* not lint */ #include #include "utils/magic.h" #include "utils/geometry.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "utils/undo.h" #include "plow/plow.h" #include "plow/plowInt.h" #include "drc/drc.h" /* Imports from other rules files */ extern int plowApplyRule(); /* Forward declarations */ int plowInSliverProc(); int scanDown(), scanUp(); int scanDownError(), scanUpError(); /* Argument passed to above filter functions */ struct inarg { Rect ina_area; /* Area to search for violations */ Edge *ina_moving; /* Edge causing this search */ TileType ina_t0; /* See comments in the procedures */ int (*ina_proc)(); /* Apply to look for rule violations */ /* Used while appling design rules */ PlowRule *ina_rule; /* Plowing design rule being applied */ int ina_incursion; /* Height of biggest DRC error */ bool ina_cantMove; /* TRUE if couldn't fix some error */ }; /* * ---------------------------------------------------------------------------- * * prInSliver -- * * Avoid introducing slivers because the plow is too small. * This rule only applies if the plow height is less than the * maximum design-rule distance DRCTechHalo. * * Results: * None. * * Side effects: * May add edges to the queue of edges to be processed. * * ---------------------------------------------------------------------------- */ void prInSliver(edge) Edge *edge; /* Edge being moved */ { struct inarg inarg; Rect edgeBorder; Plane *plane; if ((edge->e_flags & E_ISINITIAL) == 0 || edge->e_ytop - edge->e_ybot >= DRCTechHalo) return; /* Look down from the top of the edge */ edgeBorder.r_xbot = edge->e_x - 1; edgeBorder.r_xtop = edge->e_newx; edgeBorder.r_ybot = edge->e_ytop; edgeBorder.r_ytop = edge->e_ytop + 1; plane = plowYankDef->cd_planes[edge->e_pNum]; inarg.ina_moving = edge; inarg.ina_t0 = (TileType) -1; inarg.ina_area.r_ytop = edge->e_ybot; inarg.ina_proc = scanDown; plowSrFinalArea(plane, &edgeBorder, &DBAllTypeBits, plowInSliverProc, (ClientData) &inarg); /* Look up from the bottom of the edge */ edgeBorder.r_ybot = edge->e_ybot - 1; edgeBorder.r_ytop = edge->e_ybot; inarg.ina_t0 = (TileType) -1; inarg.ina_area.r_ybot = edge->e_ytop; inarg.ina_proc = scanUp; plowSrFinalArea(plane, &edgeBorder, &DBAllTypeBits, plowInSliverProc, (ClientData) &inarg); } int plowInSliverProc(tile, inarg) Tile *tile; struct inarg *inarg; { Edge *movingEdge = inarg->ina_moving; #ifdef notdef Edge newEdge; #endif /* notdef */ TileType t1; int xtop; /* Is this the first tile we've seen? */ if (inarg->ina_t0 == (TileType) -1) { inarg->ina_t0 = TiGetType(tile); inarg->ina_area.r_xbot = movingEdge->e_x; inarg->ina_area.r_xtop = MIN(movingEdge->e_newx, LEADING(tile)); if (LEADING(tile) >= movingEdge->e_newx) { (*inarg->ina_proc)(inarg, inarg->ina_t0, FALSE); return (1); } return (0); } /* Is this still the same material? */ if (TiGetType(tile) == inarg->ina_t0) { /* Extend the edge to the right */ xtop = MIN(movingEdge->e_newx, LEADING(tile)); if (xtop > inarg->ina_area.r_xtop) inarg->ina_area.r_xtop = xtop; /* Is this the last tile? */ if (LEADING(tile) >= movingEdge->e_newx) { (*inarg->ina_proc)(inarg, inarg->ina_t0, FALSE); return (1); } /* Keep looking */ return (0); } /* New type of material */ t1 = TiGetType(tile); /* Can we not slide past the t0 | t1 edge? */ if ((movingEdge->e_ltype != TT_SPACE && movingEdge->e_rtype != TT_SPACE) || TTMaskHasType(&PlowCoveredTypes, inarg->ina_t0) || TTMaskHasType(&PlowCoveredTypes, t1) || inarg->ina_t0 != movingEdge->e_ltype || t1 != movingEdge->e_rtype) { #ifdef notdef /* Move a 1-lambda high strip of the t0 | t1 edge */ newEdge.e_x = LEFT(tile); newEdge.e_newx = movingEdge->e_newx; newEdge.e_ybot = movingEdge->e_ytop; newEdge.e_ytop = movingEdge->e_ytop + 1; newEdge.e_pNum = movingEdge->e_pNum; newEdge.e_ltype = inarg->ina_t0; newEdge.e_rtype = t1; newEdge.e_use = (CellUse *) NULL; (*plowPropagateProcPtr)(&newEdge); #endif /* notdef */ (*inarg->ina_proc)(inarg, inarg->ina_t0, FALSE); return (1); } /* * Search the t0 edge up to the LHS of t1. * We can only move violation edges to eliminate the errors we find. */ (*inarg->ina_proc)(inarg, inarg->ina_t0, FALSE); /* * Search the t1 edge as well. * Move violation edges if possible, but we can move the * t0 | t1 edge if we can't fix the violations. */ inarg->ina_area.r_xbot = inarg->ina_area.r_xtop; inarg->ina_area.r_xtop = movingEdge->e_newx; (*inarg->ina_proc)(inarg, t1, TRUE); return (1); } int scanDown(inarg, type, canMoveInargEdge) struct inarg *inarg; TileType type; bool canMoveInargEdge; { TileType ltype = inarg->ina_moving->e_ltype; Edge *movingEdge = inarg->ina_moving; TileTypeBitMask badTypes; PlowRule *pr; int height; inarg->ina_incursion = 0; inarg->ina_cantMove = FALSE; height = movingEdge->e_ytop - movingEdge->e_ybot; for (pr = plowSpacingRulesTbl[type][ltype]; pr; pr = pr->pr_next) { if ((pr->pr_flags & PR_PENUMBRAONLY) || pr->pr_dist <= height) continue; inarg->ina_area.r_ybot = movingEdge->e_ytop - pr->pr_dist; inarg->ina_rule = pr; TTMaskCom2(&badTypes, &pr->pr_oktypes); plowSrFinalArea(plowYankDef->cd_planes[pr->pr_pNum], &inarg->ina_area, &badTypes, scanDownError, (ClientData) inarg); } for (pr = plowWidthRulesTbl[type][ltype]; pr; pr = pr->pr_next) { if ((pr->pr_flags & PR_PENUMBRAONLY) || pr->pr_dist <= height) continue; inarg->ina_area.r_ybot = movingEdge->e_ytop - pr->pr_dist; inarg->ina_rule = pr; TTMaskCom2(&badTypes, &pr->pr_oktypes); plowSrFinalArea(plowYankDef->cd_planes[pr->pr_pNum], &inarg->ina_area, &badTypes, scanDownError, (ClientData) inarg); } #ifdef notdef /* Move the top edge if necessary */ if (canMoveInargEdge && inarg->ina_cantMove) { struct applyRule ar; Rect shadowRect; shadowRect.r_xbot = inarg->ina_area.r_xbot - 1; shadowRect.r_ybot = movingEdge->e_ytop; shadowRect.r_xtop = movingEdge->e_newx; shadowRect.r_ytop = movingEdge->e_ytop + inarg->ina_incursion; ar.ar_moving = movingEdge; ar.ar_rule = (PlowRule *) NULL; plowSrShadow(movingEdge->e_pNum, &shadowRect, &DBZeroTypeBits, plowApplyRule, (ClientData) &ar); } #endif /* notdef */ return 0; } int scanDownError(tile, inarg) Tile *tile; struct inarg *inarg; { Rect atomRect; int incursion; incursion = MIN(TOP(tile), inarg->ina_area.r_ytop) - inarg->ina_area.r_ybot; if (incursion > inarg->ina_incursion) inarg->ina_incursion = incursion; /* * The following relies on maximal horizontal strips. * If the violating tile extends to the left of the area * we're checking, we can't eliminate the violation by * moving its LHS. */ if (LEFT(tile) < inarg->ina_area.r_xbot) { inarg->ina_cantMove = TRUE; return (0); } /* * Eliminate the violation by moving the LHS of * the violating tile. */ atomRect.r_xbot = LEFT(tile); atomRect.r_xtop = inarg->ina_moving->e_newx; atomRect.r_ybot = MAX(BOTTOM(tile), inarg->ina_area.r_ybot); atomRect.r_ytop = MIN(TOP(tile), inarg->ina_area.r_ytop); (void) plowAtomize(inarg->ina_rule->pr_pNum, &atomRect, plowPropagateProcPtr, (ClientData) NULL); return (0); } int scanUp(inarg, type, canMoveInargEdge) struct inarg *inarg; TileType type; bool canMoveInargEdge; { TileType ltype = inarg->ina_moving->e_ltype; Edge *movingEdge = inarg->ina_moving; TileTypeBitMask badTypes; PlowRule *pr; int height; inarg->ina_incursion = 0; inarg->ina_cantMove = FALSE; height = movingEdge->e_ytop - movingEdge->e_ybot; for (pr = plowSpacingRulesTbl[type][ltype]; pr; pr = pr->pr_next) { if ((pr->pr_flags & PR_PENUMBRAONLY) || pr->pr_dist <= height) continue; inarg->ina_area.r_ytop = movingEdge->e_ybot + pr->pr_dist; inarg->ina_rule = pr; TTMaskCom2(&badTypes, &pr->pr_oktypes); plowSrFinalArea(plowYankDef->cd_planes[pr->pr_pNum], &inarg->ina_area, &badTypes, scanUpError, (ClientData) inarg); } for (pr = plowWidthRulesTbl[type][ltype]; pr; pr = pr->pr_next) { if ((pr->pr_flags & PR_PENUMBRAONLY) || pr->pr_dist <= height) continue; inarg->ina_area.r_ytop = movingEdge->e_ybot + pr->pr_dist; inarg->ina_rule = pr; TTMaskCom2(&badTypes, &pr->pr_oktypes); plowSrFinalArea(plowYankDef->cd_planes[pr->pr_pNum], &inarg->ina_area, &badTypes, scanUpError, (ClientData) inarg); } #ifdef notdef /* Move the bottom edge if necessary */ if (canMoveInargEdge && inarg->ina_cantMove) { struct applyRule ar; Rect shadowRect; shadowRect.r_xbot = inarg->ina_area.r_xbot - 1; shadowRect.r_ybot = movingEdge->e_ybot - inarg->ina_incursion; shadowRect.r_xtop = movingEdge->e_newx; shadowRect.r_ytop = movingEdge->e_ybot; ar.ar_moving = movingEdge; ar.ar_rule = (PlowRule *) NULL; plowSrShadow(movingEdge->e_pNum, &shadowRect, &DBZeroTypeBits, plowApplyRule, (ClientData) &ar); } #endif /* notdef */ return 0; } int scanUpError(tile, inarg) Tile *tile; struct inarg *inarg; { Rect atomRect; int incursion; incursion = inarg->ina_area.r_ytop; incursion -= MAX(BOTTOM(tile), inarg->ina_area.r_ybot); if (incursion > inarg->ina_incursion) inarg->ina_incursion = incursion; /* * The following relies on maximal horizontal strips. * If the violating tile extends to the left of the area * we're checking, we can't eliminate the violation by * moving its LHS. */ if (LEFT(tile) < inarg->ina_area.r_xbot) { inarg->ina_cantMove = TRUE; return (0); } /* * Eliminate the violation by moving the LHS of * the violating tile. */ atomRect.r_xbot = LEFT(tile); atomRect.r_xtop = inarg->ina_moving->e_newx; atomRect.r_ybot = MAX(BOTTOM(tile), inarg->ina_area.r_ybot); atomRect.r_ytop = MIN(TOP(tile), inarg->ina_area.r_ytop); (void) plowAtomize(inarg->ina_rule->pr_pNum, &atomRect, plowPropagateProcPtr, (ClientData) NULL); return (0); } int plowSrFinalArea(plane, area, okTypes, proc, cdata) Plane *plane; Rect *area; TileTypeBitMask *okTypes; int (*proc)(); ClientData cdata; { return (DBSrPaintArea((Tile *) NULL, plane, area, okTypes, proc, cdata)); }