/* * DRCcif.c -- * ****************************************************************************** * Copyright (C) 1989 Digital Equipment Corporation * 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. Digital Equipment Corporation * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. **************************************************************************** * */ #ifndef lint static char rcsid[] = "$Header: /ufs/repository/magic/drc/DRCcif.c,v 1.2 2001/01/12 22:12:28 jsolomon Exp $"; #endif #include #include #include "misc/magic.h" #include "utils/geometry.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "dbwind/dbwtech.h" #include "drc/drc.h" #include "cif/cif.h" #include "cif/CIFint.h" #include "signals/signals.h" #include "utils/stack.h" #include "utils/malloc.h" #include "utils/utils.h" #ifdef DRC_CIF_EXTENSIONS extern char *drcWhyDup(); extern Stack *DRCstack; #define PUSHTILE(tp) \ if ((tp)->ti_client == (ClientData) DRC_UNPROCESSED) { \ (tp)->ti_client = (ClientData) DRC_PENDING; \ STACKPUSH((ClientData) (tp), DRCstack); \ } extern CIFStyle *drcCifStyle; TileTypeBitMask drcCifGenLayers; int drcCifTile(); extern int areaCifCheck(); typedef struct drccifcookie { int drcc_dist; /* Extent of rule from edge. */ TileTypeBitMask drcc_mask; /* Legal types on RHS */ TileTypeBitMask drcc_corner; /* Types that trigger corner check */ struct drccifcookie * drcc_next; char * drcc_why; /* Explanation of error found */ int drcc_cdist; /* Size of corner extension. */ int drcc_flags; /* Miscellaneous flags, see below. */ int drcc_plane; } DRCCifCookie; DRCCifCookie *drcCifRules[MAXCIFLAYERS][2]; int drcCifValid = FALSE; #define DRC_CIF_SPACE 0 #define DRC_CIF_SOLID 1 DRCCifCookie *drcCifCur=NULL; #define ASSIGN(cookie,dist,next,mask,corner,why,cdist,flags,layer) \ ((cookie)->drcc_dist = dist, \ (cookie)->drcc_next = next, \ (cookie)->drcc_mask = mask, \ (cookie)->drcc_corner = corner, \ (cookie)->drcc_why = why, \ (cookie)->drcc_cdist = cdist, \ (cookie)->drcc_flags = flags, \ (cookie)->drcc_plane = layer) /* The following DRC cookie is used when there are tiles of type * TT_ERROR_S found during the basic DRC. These arise during * hierarchical checking when there are illegal overlaps. */ /* * ---------------------------------------------------------------------------- * * drcCifWidth -- same this as drcCifWidth, except that it works on * cif layers * * Results: * Returns distance. * * Side effects: * Updates the DRC technology variables. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ drcCifWidth(argc, argv) int argc; char *argv[]; { char *layername = argv[1]; int scalefactor; int centidistance = atoi(argv[2]); char *why = drcWhyDup(argv[3]); TileTypeBitMask set, setC, tmp1; int thislayer = -1; DRCCifCookie *dpnew,*dpnext; TileType i; if (drcCifStyle == NULL) { TechError("Missing cif style for drc\n"); return 0; } for (i = 0; i < drcCifStyle->cs_nLayers;i++) { CIFLayer *layer = drcCifStyle->cs_layers[i]; if (strcmp(layer->cl_name,layername) == 0) { thislayer = i; break; } } if (thislayer == -1) { TechError("Unknown cif layer: %s\n",layername); return (0); } scalefactor = drcCifStyle->cs_scaleFactor; dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,centidistance,dpnext,CIFSolidBits, CIFSolidBits,why,centidistance,DRC_FORWARD,thislayer); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; return ((centidistance+scalefactor-1)/scalefactor); } /* * ---------------------------------------------------------------------------- * * drcCifSpacing -- same this as drcSpacing, except that it works on cif layers. * * Results: * Returns distance. * * Side effects: * Updates the DRC technology variables. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ drcCifSpacing(argc, argv) int argc; char *argv[]; { char *adjacency = argv[4]; char *why = drcWhyDup(argv[5]); DRCCifCookie *dpnext, *dpnew; int needReverse = FALSE; TileType i, j; int scalefactor; int centidistance = atoi(argv[3]); char *layers[2]; TileType layer[2]; TileTypeBitMask cmask; int k; layers[0] = argv[1]; layers[1] = argv[2]; if (drcCifStyle == NULL) { TechError("Missing cif style for drc\n"); return 0; } for (k=0; k!= 2;k++) { for (i = 0; i < drcCifStyle->cs_nLayers;i++) { CIFLayer *l = drcCifStyle->cs_layers[i]; if (strcmp(l->cl_name,layers[k]) == 0) { layer[k]=i; break; } } if (i == drcCifStyle->cs_nLayers || layer[k] == -1) { TechError("Unknown cif layer: %s",layers[k]); return (0); } } if (strcmp (adjacency, "touching_ok") == 0) { /* If touching is OK, everything must fall in the same plane. */ if (layer[0] != layer[1]) { TechError( "Spacing check with touching ok must all be in one plane.\n"); return (0); } cmask = DBSpaceBits; } else if (strcmp (adjacency, "touching_illegal") == 0) { cmask = DBAllTypeBits; needReverse = TRUE; /* nothing for now */ } else { TechError("Badly formed drc spacing line\n"); return (0); } scalefactor = drcCifStyle->cs_scaleFactor; dpnext = drcCifRules[layer[0]][DRC_CIF_SOLID]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,centidistance,dpnext,DBSpaceBits, cmask,why,centidistance,DRC_FORWARD,layer[1]); drcCifRules[layer[0]][DRC_CIF_SOLID] = dpnew; if (needReverse) { dpnew->drcc_flags |= DRC_BOTHCORNERS|DRC_XPLANE; dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,centidistance,dpnext,DBSpaceBits, cmask,why,centidistance, DRC_XPLANE|DRC_FORWARD|DRC_BOTHCORNERS,layer[0]); drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew; if (layer[0] == layer[1]) { dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,centidistance,dpnext,DBSpaceBits, cmask,why,centidistance, DRC_XPLANE|DRC_REVERSE|DRC_BOTHCORNERS,layer[0]); drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,centidistance,dpnext,DBSpaceBits, cmask,why,centidistance, DRC_XPLANE|DRC_REVERSE|DRC_BOTHCORNERS,layer[1]); drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; } } if (layer[0] != layer[1]) /* make sure they don't overlap exactly */ { dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,scalefactor,dpnext,DBSpaceBits, DBZeroTypeBits,why,scalefactor, DRC_FORWARD,layer[0]); drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,scalefactor,dpnext,DBSpaceBits, DBZeroTypeBits,why,scalefactor, DRC_FORWARD,layer[1]); drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; } return ((centidistance+scalefactor-1)/scalefactor); } drcCifInit() { int i; for (i=0; i != MAXCIFLAYERS; i++) { drcCifRules[i][DRC_CIF_SPACE] = NULL; drcCifRules[i][DRC_CIF_SOLID] = NULL; } drcCifValid= FALSE; TTMaskZero(&drcCifGenLayers); } drcCifFinal() { int i; for (i=0; i != MAXCIFLAYERS; i++) { DRCCifCookie *dp; for (dp = drcCifRules[i][DRC_CIF_SPACE];dp;dp=dp->drcc_next) { drcCifValid= TRUE; TTMaskSetType(&drcCifGenLayers,i); TTMaskSetType(&drcCifGenLayers,dp->drcc_plane); } for (dp = drcCifRules[i][DRC_CIF_SOLID];dp;dp=dp->drcc_next) { drcCifValid= TRUE; TTMaskSetType(&drcCifGenLayers,i); TTMaskSetType(&drcCifGenLayers,dp->drcc_plane); } } } drcCifCheck(arg) struct drcClientData *arg; { Rect *checkRect = arg->dCD_rect; Rect cifrect; int scale; CIFStyle *tmp; int i,j; int oldTiles; if (drcCifValid == FALSE) return; scale = drcCifStyle->cs_scaleFactor; tmp = CIFCurStyle; CIFCurStyle = drcCifStyle; cifrect = *checkRect; cifrect.r_xbot *= scale; cifrect.r_xtop *= scale; cifrect.r_ybot *= scale; cifrect.r_ytop *= scale; arg->dCD_rect = &cifrect; oldTiles = DRCstatTiles; /* CIFGen(arg->dCD_celldef,checkRect,CIFPlanes,&drcCifGenLayers,TRUE,FALSE); */ CIFGen(arg->dCD_celldef,checkRect,CIFPlanes,&DBAllTypeBits,TRUE,TRUE); for (i = 0; i < drcCifStyle->cs_nLayers;i++) { for (j = 0; j != 2;j++) { for (drcCifCur=drcCifRules[i][j]; drcCifCur;drcCifCur=drcCifCur->drcc_next) { Plane *plane = CIFPlanes[i]; TileTypeBitMask *mask; mask = (j == DRC_CIF_SOLID)?(&DBSpaceBits):&CIFSolidBits; DBSrPaintArea((Tile *) NULL,plane,&cifrect,mask, drcCifTile, arg); } } } arg->dCD_rect = checkRect; CIFCurStyle = tmp; DRCstatCifTiles += DRCstatTiles - oldTiles; } /* * ---------------------------------------------------------------------------- * * drcCifTile -- * * Results: * Zero (so that the search will continue), unless an interrupt * occurs, in which case 1 is returned to stop the check. * * Side effects: * Calls the client's error function if errors are found. * * ---------------------------------------------------------------------------- */ int drcCifTile (tile, arg) register Tile *tile; /* Tile being examined */ struct drcClientData *arg; { register DRCCifCookie *cptr; /* Current design rule on list */ register Tile *tp; /* Used for corner checks */ Rect *rect = arg->dCD_rect; /* Area being checked */ Rect errRect; /* Area checked for an individual rule */ TileTypeBitMask tmpMask; arg->dCD_constraint = &errRect; /* * If we were interrupted, we want to * abort the check as quickly as possible. */ if (SigInterruptPending) return 1; DRCstatTiles++; /* * Check design rules along a vertical boundary between two tiles. * * 1 | 4 * T * | * tpleft | tile * | * B * 2 | 3 * * The labels "T" and "B" indicate pointT and pointB respectively. * * If a rule's direction is FORWARD, then check from left to right. * * * Check the top right corner if the 1x1 lambda square * on the top left corner (1) of pointT matches the design * rule's "corner" mask. * * * Check the bottom right corner if the rule says check * BOTHCORNERS and the 1x1 lambda square on the bottom left * corner (2) of pointB matches the design rule's "corner" mask. * * If a rule's direction is REVERSE, then check from right to left. * * * Check the bottom left corner if the 1x1 lambda square * on the bottom right corner (3) of pointB matches the design * rule's "corner" mask. * * * Check the top left corner if the rule says check BOTHCORNERS * and the 1x1 lambda square on the top right corner (4) of * pointT matches the design rule's "corner" mask. */ if (drcCifCur->drcc_flags & DRC_AREA) { drcCheckCifArea(tile,arg,drcCifCur); return 0; } if (drcCifCur->drcc_flags & DRC_MAXWIDTH) { drcCheckCifMaxwidth(tile,arg,drcCifCur); return 0; } if (LEFT(tile) >= rect->r_xbot) /* check tile against rect */ { register Tile *tpleft; int edgeTop, edgeBot; int top = MIN(TOP(tile), rect->r_ytop); int bottom = MAX(BOTTOM(tile), rect->r_ybot); int edgeX = LEFT(tile); for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft)) { /* Don't check synthetic edges, i.e. edges with same type on * both sides. Such "edges" have no physical significance, and * depend on internal-details of how paint is spit into tiles. * Thus checking them just leads to confusion. (When edge rules * involving such edges are encountered during technology readin * the user is warned that such edges are not checked). */ if(TiGetType(tpleft) == TiGetType(tile)) continue; /* * Go through list of design rules triggered by the * left-to-right edge. */ edgeTop = MIN(TOP (tpleft), top); edgeBot = MAX(BOTTOM(tpleft), bottom); if (edgeTop <= edgeBot) continue; /* do this more intelligently later XXX */ cptr = drcCifCur; { errRect.r_ytop = edgeTop; errRect.r_ybot = edgeBot; if (cptr->drcc_flags & DRC_REVERSE) { /* * Determine corner extensions. * Find the point (3) to the bottom right of pointB */ for (tp = tile; BOTTOM(tp) >= errRect.r_ybot; tp = LB(tp)) /* Nothing */; if (TTMaskHasType(&cptr->drcc_corner, TiGetType(tp))) errRect.r_ybot -= cptr->drcc_cdist; if (cptr->drcc_flags & DRC_BOTHCORNERS) { /* * Check the other corner by finding the * point (4) to the top right of pointT. */ if (TOP(tp = tile) <= errRect.r_ytop) for (tp = RT(tp); LEFT(tp) > edgeX; tp = BL(tp)) /* Nothing */; if (TTMaskHasType(&cptr->drcc_corner, TiGetType(tp))) errRect.r_ytop += cptr->drcc_cdist; } /* * Just for grins, see if we could avoid a messy search * by looking only at tpleft. */ errRect.r_xbot = edgeX - cptr->drcc_dist; if (LEFT(tpleft) <= errRect.r_xbot && BOTTOM(tpleft) <= errRect.r_ybot && TOP(tpleft) >= errRect.r_ytop && !(cptr->drcc_flags & DRC_XPLANE) && TTMaskHasType(&cptr->drcc_mask, TiGetType(tpleft))) continue; errRect.r_xtop = edgeX; arg->dCD_initial = tile; } else { /* * Determine corner extensions. * Find the point (1) to the top left of pointT */ for (tp = tpleft; TOP(tp) <= errRect.r_ytop; tp = RT(tp)) /* Nothing */; if (TTMaskHasType(&cptr->drcc_corner, TiGetType(tp))) errRect.r_ytop += cptr->drcc_cdist; if (cptr->drcc_flags & DRC_BOTHCORNERS) { /* * Check the other corner by finding the * point (2) to the bottom left of pointB. */ if (BOTTOM(tp = tpleft) >= errRect.r_ybot) for (tp = LB(tp); RIGHT(tp) < edgeX; tp = TR(tp)) /* Nothing */; if (TTMaskHasType(&cptr->drcc_corner, TiGetType(tp))) errRect.r_ybot -= cptr->drcc_cdist; } /* * Just for grins, see if we could avoid a messy search * by looking only at tile. */ errRect.r_xtop = edgeX + cptr->drcc_dist; if (RIGHT(tile) >= errRect.r_xtop && BOTTOM(tile) <= errRect.r_ybot && TOP(tile) >= errRect.r_ytop && !(cptr->drcc_flags & DRC_XPLANE) && TTMaskHasType(&cptr->drcc_mask, TiGetType(tile))) continue; errRect.r_xbot = edgeX; arg->dCD_initial= tpleft; } DRCstatSlow++; arg->dCD_cptr = (DRCCookie *)cptr; TTMaskCom2(&tmpMask, &cptr->drcc_mask); (void) DBSrPaintArea((Tile *) NULL, CIFPlanes[cptr->drcc_plane], &errRect, &tmpMask, areaCifCheck, (ClientData) arg); } DRCstatEdges++; } } /* * Check design rules along a horizontal boundary between two tiles. * * 4 tile 3 * --L----------------R-- * 1 tpbot 2 * * The labels "L" and "R" indicate pointL and pointR respectively. * If a rule's direction is FORWARD, then check from bottom to top. * * * Check the top left corner if the 1x1 lambda square on the bottom * left corner (1) of pointL matches the design rule's "corner" mask. * * * Check the top right corner if the rule says check BOTHCORNERS and * the 1x1 lambda square on the bottom right (2) corner of pointR * matches the design rule's "corner" mask. * * If a rule's direction is REVERSE, then check from top to bottom. * * * Check the bottom right corner if the 1x1 lambda square on the top * right corner (3) of pointR matches the design rule's "corner" * mask. * * * Check the bottom left corner if the rule says check BOTHCORNERS * and the 1x1 lambda square on the top left corner (4) of pointL * matches the design rule's "corner" mask. */ if (BOTTOM(tile) >= rect->r_ybot) { register Tile *tpbot; int edgeLeft, edgeRight; int left = MAX(LEFT(tile), rect->r_xbot); int right = MIN(RIGHT(tile), rect->r_xtop); int edgeY = BOTTOM(tile); /* Go right across bottom of tile */ for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot)) { /* Don't check synthetic edges, i.e. edges with same type on * both sides. Such "edges" have no physical significance, and * depend on internal-details of how paint is spit into tiles. * Thus checking them just leads to confusion. (When edge rules * involving such edges are encountered during technology readin * the user is warned that such edges are not checked). */ if(TiGetType(tpbot) == TiGetType(tile)) continue; /* * Check to insure that we are inside the clip area. * Go through list of design rules triggered by the * bottom-to-top edge. */ edgeLeft = MAX(LEFT(tpbot), left); edgeRight = MIN(RIGHT(tpbot), right); if (edgeLeft >= edgeRight) continue; cptr = drcCifCur; { DRCstatRules++; errRect.r_xbot = edgeLeft; errRect.r_xtop = edgeRight; /* top to bottom */ if (cptr->drcc_flags & DRC_REVERSE) { /* * Determine corner extensions. * Find the point (3) to the top right of pointR */ if (RIGHT(tp = tile) <= errRect.r_xtop) for (tp = TR(tp); BOTTOM(tp) > edgeY; tp = LB(tp)) /* Nothing */; if (TTMaskHasType(&cptr->drcc_corner, TiGetType(tp))) errRect.r_xtop += cptr->drcc_cdist; if (cptr->drcc_flags & DRC_BOTHCORNERS) { /* * Check the other corner by finding the * point (4) to the top left of pointL. */ for (tp = tile; LEFT(tp) >= errRect.r_xbot; tp = BL(tp)) /* Nothing */; if (TTMaskHasType(&cptr->drcc_corner, TiGetType(tp))) errRect.r_xbot -= cptr->drcc_cdist; } /* * Just for grins, see if we could avoid * a messy search by looking only at tpbot. */ errRect.r_ybot = edgeY - cptr->drcc_dist; if (BOTTOM(tpbot) <= errRect.r_ybot && LEFT(tpbot) <= errRect.r_xbot && RIGHT(tpbot) >= errRect.r_xtop && !(cptr->drcc_flags & DRC_XPLANE) && TTMaskHasType(&cptr->drcc_mask, TiGetType(tpbot))) continue; errRect.r_ytop = edgeY; arg->dCD_initial = tile; } else { /* * Determine corner extensions. * Find the point (1) to the bottom left of pointL */ if (LEFT(tp = tpbot) >= errRect.r_xbot) for (tp = BL(tp); TOP(tp) < edgeY; tp = RT(tp)) /* Nothing */; if (TTMaskHasType(&cptr->drcc_corner, TiGetType(tp))) errRect.r_xbot -= cptr->drcc_cdist; if (cptr->drcc_flags & DRC_BOTHCORNERS) { /* * Check the other corner by finding the * point (2) to the bottom right of pointR. */ for (tp=tpbot; RIGHT(tp) <= errRect.r_xtop; tp=TR(tp)) /* Nothing */; if (TTMaskHasType(&cptr->drcc_corner, TiGetType(tp))) errRect.r_xtop += cptr->drcc_cdist; } /* * Just for grins, see if we could avoid * a messy search by looking only at tile. */ errRect.r_ytop = edgeY + cptr->drcc_dist; if (TOP(tile) >= errRect.r_ytop && LEFT(tile) <= errRect.r_xbot && RIGHT(tile) >= errRect.r_xtop && !(cptr->drcc_flags & DRC_XPLANE) && TTMaskHasType(&cptr->drcc_mask, TiGetType(tile))) continue; errRect.r_ybot = edgeY; arg->dCD_initial = tpbot; } DRCstatSlow++; arg->dCD_cptr = (DRCCookie *)cptr; TTMaskCom2(&tmpMask, &cptr->drcc_mask); (void) DBSrPaintArea((Tile *) NULL, CIFPlanes[cptr->drcc_plane], &errRect, &tmpMask, areaCifCheck, (ClientData) arg); } DRCstatEdges++; } } return (0); } /* * ---------------------------------------------------------------------------- * * areaCifCheck -- * * Call the function passed down from DRCBasicCheck() if the current tile * violates the rule in the given DRCCookie. If the rule's connectivity * flag is set, then make sure the violating material isn't connected * to what's on the initial side of the edge before calling the client * error function. * * This function is called from DBSrPaintArea(). * * Results: * Zero (so that the search will continue). * * Side effects: * Applies the function passed as an argument. * * ---------------------------------------------------------------------------- */ int areaCifCheck(tile, arg) register Tile *tile; register struct drcClientData *arg; { Rect rect; /* Area where error is to be recorded. */ int scale = drcCifStyle->cs_scaleFactor; /* If the tile has a legal type, then return. */ if (TTMaskHasType(&arg->dCD_cptr->drcc_mask, TiGetType(tile))) return 0; /* Only consider the portion of the suspicious tile that overlaps * the clip area for errors. */ TiToRect(tile, &rect); GeoClip(&rect, arg->dCD_constraint); if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop)) return 0; rect.r_xbot /= scale; rect.r_xtop /= scale; if (rect.r_xbot == rect.r_xtop) { if (rect.r_xbot < 0) rect.r_xbot--; else rect.r_xtop++; } rect.r_ybot /= scale; rect.r_ytop /= scale; if (rect.r_ybot == rect.r_ytop) { if (rect.r_ybot < 0) rect.r_ybot--; else rect.r_ytop++; } GeoClip(&rect, arg->dCD_clip); if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop)) return 0; (*(arg->dCD_function)) (arg->dCD_celldef, &rect, arg->dCD_cptr, arg->dCD_clientData); (*(arg->dCD_errors))++; return (0); } /* * ---------------------------------------------------------------------------- * * drcCifArea -- * * Process an area rule. * This is of the form: * * cifarea layers distance why * * e.g, * * cifarea VIA 4 "via area must be at least 4" * * Results: * Returns distance. * * Side effects: * Updates the DRC technology variables. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ drcCifArea(argc, argv) int argc; char *argv[]; { char *layers = argv[1]; int centidistance = atoi(argv[2]); int centihorizon = atoi(argv[3]); char *why = drcWhyDup(argv[4]); TileTypeBitMask set, setC, tmp1; DRCCifCookie *dpnext, *dpnew; TileType i, j; int plane; int thislayer; int scalefactor; if (drcCifStyle == NULL) { TechError("Missing cif style for drc\n"); return 0; } for (i = 0; i < drcCifStyle->cs_nLayers;i++) { CIFLayer *layer = drcCifStyle->cs_layers[i]; if (strcmp(layer->cl_name,layers) == 0) { thislayer = i; break; } } if (thislayer == -1) { TechError("Unknown cif layer: %s\n",layers); return (0); } scalefactor = drcCifStyle->cs_scaleFactor; dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,centihorizon,dpnext,CIFSolidBits, CIFSolidBits,why,centidistance,DRC_AREA|DRC_FORWARD,thislayer); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; return ((centihorizon+scalefactor-1)/scalefactor); } /* * ---------------------------------------------------------------------------- * * drcCifMaxwidth -- cif version of drc list. * * Results: * Returns distance. * * Side effects: * Updates the DRC technology variables. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ drcCifMaxwidth(argc, argv) int argc; char *argv[]; { char *layers = argv[1]; int centidistance = atoi(argv[2]); char *bends = argv[3]; char *why = drcWhyDup(argv[4]); TileTypeBitMask set, setC, tmp1; DRCCifCookie *dpnext, *dpnew; TileType i, j; int plane; int bend; int thislayer; int scalefactor; if (drcCifStyle == NULL) { TechError("Missing cif style for drc\n"); return 0; } for (i = 0; i < drcCifStyle->cs_nLayers;i++) { CIFLayer *layer = drcCifStyle->cs_layers[i]; if (strcmp(layer->cl_name,layers) == 0) { thislayer = i; break; } } if (thislayer == -1) { TechError("Unknown cif layer: %s\n",layers); return (0); } if (strcmp(bends,"bend_illegal") == 0) bend =0; else if (strcmp(bends,"bend_ok") == 0) bend =DRC_BENDS; else { TechError("unknown bend option %s\n",bends); return (0); } scalefactor = drcCifStyle->cs_scaleFactor; dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; MALLOC(DRCCifCookie *, dpnew, sizeof (DRCCifCookie)); ASSIGN(dpnew,centidistance,dpnext,CIFSolidBits, CIFSolidBits,why,centidistance,DRC_MAXWIDTH|bend,thislayer); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; return ((centidistance+scalefactor-1)/scalefactor); } /* *------------------------------------------------------------------------- * * drcCifCheckArea- checks to see that a collection of cif tiles * have more than a minimum area. * * Results: none * * Side Effects: may cause errors to be painted. * *------------------------------------------------------------------------- */ drcCheckCifArea(starttile,arg,cptr) Tile *starttile; struct drcClientData *arg; DRCCifCookie *cptr; { int arealimit = cptr->drcc_cdist; int area=0; TileTypeBitMask *oktypes = &cptr->drcc_mask; Tile *tile,*tp; Rect *cliprect = arg->dCD_rect; int scale = drcCifStyle->cs_scaleFactor; arg->dCD_cptr = (DRCCookie *)cptr; if (DRCstack == (Stack *) NULL) DRCstack = StackNew(64); /* Mark this tile as pending and push it */ PUSHTILE(starttile); while (!StackEmpty(DRCstack)) { tile = (Tile *) STACKPOP(DRCstack); if (tile->ti_client != (ClientData)DRC_PENDING) continue; area += (RIGHT(tile)-LEFT(tile))*(TOP(tile)-BOTTOM(tile)); tile->ti_client = (ClientData)DRC_PROCESSED; /* are we at the clip boundary? If so, skip to the end */ if (RIGHT(tile) == cliprect->r_xtop || LEFT(tile) == cliprect->r_xbot || BOTTOM(tile) == cliprect->r_ybot || TOP(tile) == cliprect->r_ytop) goto forgetit; if (area >= arealimit) goto forgetit; /* Top */ for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); /* Left */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); /* Bottom */ for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); /* Right */ for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); } if (area dCD_clip); if (!GEO_RECTNULL(&rect)) { (*(arg->dCD_function)) (arg->dCD_celldef, &rect, arg->dCD_cptr, arg->dCD_clientData); /*** DBWAreaChanged(arg->dCD_celldef,&rect, DBW_ALLWINDOWS, &DBAllButSpaceBits); ***/ (*(arg->dCD_errors))++; } } forgetit: /* reset the tiles */ starttile->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(starttile, DRCstack); while (!StackEmpty(DRCstack)) { tile = (Tile *) STACKPOP(DRCstack); /* Top */ for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) if (tp->ti_client != (ClientData)DRC_UNPROCESSED) { tp->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(tp,DRCstack); } /* Left */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) if (tp->ti_client != (ClientData)DRC_UNPROCESSED) { tp->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(tp,DRCstack); } /* Bottom */ for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) if (tp->ti_client != (ClientData)DRC_UNPROCESSED) { tp->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(tp,DRCstack); } /* Right */ for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) if (tp->ti_client != (ClientData)DRC_UNPROCESSED) { tp->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(tp,DRCstack); } } return 0; } /* *------------------------------------------------------------------------- * * drcCheckCifMaxwidth - checks to see that at least one dimension of a region * does not exceed some amount. * * Results: none * * Side Effects: may cause errors to be painted. * *------------------------------------------------------------------------- */ drcCheckCifMaxwidth(starttile,arg,cptr) Tile *starttile; struct drcClientData *arg; DRCCifCookie *cptr; { int edgelimit = cptr->drcc_dist; Rect boundrect; TileTypeBitMask *oktypes = &cptr->drcc_mask; Tile *tile,*tp; int scale = drcCifStyle->cs_scaleFactor; arg->dCD_cptr = (DRCCookie *)cptr; if (DRCstack == (Stack *) NULL) DRCstack = StackNew(64); /* if bends are allowed, just check on a tile-by-tile basis that one dimension is the max. This is pretty stupid, but it correctly calculates the trench width rule. dcs 12.06.89 */ if (cptr->drcc_flags & DRC_BENDS) { Rect rect; TiToRect(starttile,&rect); if (rect.r_xtop-rect.r_xbot > edgelimit && rect.r_ytop-rect.r_ybot > edgelimit) { rect.r_xbot /= scale; rect.r_xtop /= scale; rect.r_ybot /= scale; rect.r_ytop /= scale; GeoClip(&rect, arg->dCD_clip); if (!GEO_RECTNULL(&rect)) { (*(arg->dCD_function)) (arg->dCD_celldef, &rect, arg->dCD_cptr, arg->dCD_clientData); /*** DBWAreaChanged(arg->dCD_celldef,&rect, DBW_ALLWINDOWS, &DBAllButSpaceBits); ***/ (*(arg->dCD_errors))++; } } return 0; } /* Mark this tile as pending and push it */ PUSHTILE(starttile); TiToRect(starttile,&boundrect); while (!StackEmpty(DRCstack)) { tile = (Tile *) STACKPOP(DRCstack); if (tile->ti_client != (ClientData)DRC_PENDING) continue; if (boundrect.r_xbot > LEFT(tile)) boundrect.r_xbot = LEFT(tile); if (boundrect.r_xtop < RIGHT(tile)) boundrect.r_xtop = RIGHT(tile); if (boundrect.r_ybot > BOTTOM(tile)) boundrect.r_ybot = BOTTOM(tile); if (boundrect.r_ytop < TOP(tile)) boundrect.r_ytop = TOP(tile); tile->ti_client = (ClientData)DRC_PROCESSED; if (boundrect.r_xtop - boundrect.r_xbot > edgelimit && boundrect.r_ytop - boundrect.r_ybot > edgelimit) break; /* Top */ for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); /* Left */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); /* Bottom */ for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); /* Right */ for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); } if (boundrect.r_xtop - boundrect.r_xbot > edgelimit && boundrect.r_ytop - boundrect.r_ybot > edgelimit) { Rect rect; TiToRect(starttile,&rect); { rect.r_xbot /= scale; rect.r_xtop /= scale; rect.r_ybot /= scale; rect.r_ytop /= scale; GeoClip(&rect, arg->dCD_clip); if (!GEO_RECTNULL(&rect)) { (*(arg->dCD_function)) (arg->dCD_celldef, &rect, arg->dCD_cptr, arg->dCD_clientData); /*** DBWAreaChanged(arg->dCD_celldef,&rect, DBW_ALLWINDOWS, &DBAllButSpaceBits); ***/ (*(arg->dCD_errors))++; } } } /* reset the tiles */ starttile->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(starttile, DRCstack); while (!StackEmpty(DRCstack)) { tile = (Tile *) STACKPOP(DRCstack); /* Top */ for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) if (tp->ti_client != (ClientData)DRC_UNPROCESSED) { tp->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(tp,DRCstack); } /* Left */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) if (tp->ti_client != (ClientData)DRC_UNPROCESSED) { tp->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(tp,DRCstack); } /* Bottom */ for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) if (tp->ti_client != (ClientData)DRC_UNPROCESSED) { tp->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(tp,DRCstack); } /* Right */ for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) if (tp->ti_client != (ClientData)DRC_UNPROCESSED) { tp->ti_client = (ClientData)DRC_UNPROCESSED; STACKPUSH(tp,DRCstack); } } return 0; } #endif