1 /*
2  * DRCsubcell.c --
3  *
4  * This file provides the facilities for finding design-rule
5  * violations that occur as a result of interactions between
6  * subcells and either paint or other subcells.
7  *
8  *     *********************************************************************
9  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
10  *     * Permission to use, copy, modify, and distribute this              *
11  *     * software and its documentation for any purpose and without        *
12  *     * fee is hereby granted, provided that the above copyright          *
13  *     * notice appear in all copies.  The University of California        *
14  *     * makes no representations about the suitability of this            *
15  *     * software for any purpose.  It is provided "as is" without         *
16  *     * express or implied warranty.  Export of this software outside     *
17  *     * of the United States of America may require an export license.    *
18  *     *********************************************************************
19  */
20 
21 #ifndef	lint
22 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCsubcell.c,v 1.4 2009/05/01 18:59:44 tim Exp $";
23 #endif	/* not lint */
24 
25 #include <stdio.h>
26 #include <sys/types.h>
27 
28 #include "utils/magic.h"
29 #include "textio/textio.h"
30 #include "utils/geometry.h"
31 #include "tiles/tile.h"
32 #include "utils/hash.h"
33 #include "database/database.h"
34 #include "drc/drc.h"
35 #include "windows/windows.h"
36 #include "commands/commands.h"
37 #include "utils/undo.h"
38 
39 /* The variables below are made owns so that they can be used to
40  * pass information to the various search functions.
41  */
42 
43 static Rect drcSubIntArea;	/* Accumulates area of interactions. */
44 static CellDef *drcSubDef;	/* Cell definition we're checking. */
45 static int drcSubRadius;	/* Interaction radius. */
46 static CellUse *drcCurSub;	/* Holds current use while searching for interactions */
47 static Rect drcSubLookArea;	/* Area where we're looking for interactions */
48 static void (*drcSubFunc)();	/* Error function. */
49 static ClientData drcSubClientData;
50 				/* To be passed to error function. */
51 
52 /* The cookie below is dummied up to provide an error message for
53  * errors that occur because of inexact overlaps between subcells.
54  */
55 
56 static DRCCookie drcSubcellCookie = {
57     0, 0, 0, 0,
58     { 0 }, { 0 },
59     0, 0, 0,
60     DRC_SUBCELL_OVERLAP_TAG,
61     (DRCCookie *) NULL
62 };
63 
64 /* The cookie below is dummied up to provide an error message for
65  * errors that are in a subcell non-interaction area and have been
66  * copied up into the parent without flattening
67  */
68 
69 static DRCCookie drcInSubCookie = {
70     0, 0, 0, 0,
71     { 0 }, { 0 },
72     0, 0, 0,
73     DRC_IN_SUBCELL_TAG,
74     (DRCCookie *) NULL
75 };
76 
77 /* The following DRC cookie is used when flattening non-Manhattan
78  * shapes results in a non-integer coordinate.  Because the non-
79  * integer coordinate cannot be represented in magic, the position
80  * is flagged as a DRC error.
81  */
82 
83 static DRCCookie drcOffGridCookie = {
84     0, 0, 0, 0,
85     { 0 }, { 0 },
86     0, 0, 0,
87     DRC_OFFGRID_TAG,
88     (DRCCookie *) NULL
89 };
90 
91 extern int DRCErrorType;
92 extern CellDef *DRCErrorDef;
93 
94 /*
95  * ----------------------------------------------------------------------------
96  *
97  * drcFindOtherCells --
98  *
99  *	This is a search function invoked when looking around a given
100  *	cell for interactions.  If a cell use is found other than drcCurSub,
101  *	then it constitutes an interaction, and its area is included into
102  *	the area parameter.
103  *
104  * Results:
105  *	Always returns 0 to keep the search alive.
106  *
107  * Side effects:
108  *	The area parameter may be modified by including the area
109  *	of the current use.
110  *
111  * ----------------------------------------------------------------------------
112  */
113 
114 int
drcFindOtherCells(use,area)115 drcFindOtherCells(use, area)
116     CellUse *use;
117     Rect *area;
118 {
119     if (use != drcCurSub)
120     	GeoInclude(&use->cu_bbox, area);
121 
122     return 0;
123 }
124 
125 /*
126  * ----------------------------------------------------------------------------
127  *
128  * drcSubCopyErrors ---
129  *
130  *  For each tile found in drcCopyErrorsFunc(), translate the tile position
131  *  into the coordinate system of the parent cell (represented by the drcTemp
132  *  plane in ClientData) and apply the function passed in the filter, which is
133  *  whatever function handles DRC errors inside an error tile (which is
134  *  different for "drc why" commands than for "drc check".
135  *
136  *  Returns:
137  *	0 to keep the search going.
138  *
139  * ----------------------------------------------------------------------------
140  */
141 
142 int
drcSubCopyErrors(tile,cxp)143 drcSubCopyErrors(tile, cxp)
144     Tile *tile;
145     TreeContext *cxp;
146 {
147     Rect area;
148     Rect destArea;
149     struct drcClientData *arg = (struct drcClientData *)cxp->tc_filter->tf_arg;
150 
151     TiToRect(tile, &area);
152     GeoClip(&area, &cxp->tc_scx->scx_area);
153     GeoTransRect(&cxp->tc_scx->scx_trans, &area, &destArea);
154 
155     (*(arg->dCD_function))(arg->dCD_celldef, &destArea, arg->dCD_cptr,
156 		arg->dCD_clientData);
157     (*(arg->dCD_errors))++;
158 
159     return 0;
160 }
161 
162 /*
163  * ----------------------------------------------------------------------------
164  *
165  * drcSubCopyFunc ---
166  *
167  *  This routine is applied for each subcell of a parent def.  It calls
168  *  DBNoTreeSrTiles() with the above routine drcSubCopyErrors(), which
169  *  copies all error tiles from the child cell up into the parent.
170  *  This is used only within areas found to be non-interacting with the
171  *  parent, such that any error found in the child cell is guaranteed to
172  *  be a real error, and not one that might be resolved by additional
173  *  material found in the parent or a sibling cell.
174  *
175  *  Added 11/10/2020:  Moved drcArrayFunc() here; this limits the array
176  *  checks to non-interaction areas in the parent cell.
177  *  8/20/2021:  Realized that TT_ERROR_S and (maybe?) TT_ERROR_PS tiles
178  *  are also error types that must be copied up.
179  *
180  *  Returns:
181  *	Whatever DBNoTreeSrTiles() returns.
182  *
183  * ----------------------------------------------------------------------------
184  */
185 
186 int
drcSubCopyFunc(scx,cdarg)187 drcSubCopyFunc(scx, cdarg)
188     SearchContext *scx;
189     ClientData cdarg;
190 {
191     TileTypeBitMask drcMask;
192 
193     /* Create a mask with all of the DRC error types in it */
194     TTMaskZero(&drcMask);
195     TTMaskSetType(&drcMask, TT_ERROR_P);
196     TTMaskSetType(&drcMask, TT_ERROR_S);
197     TTMaskSetType(&drcMask, TT_ERROR_PS);
198 
199     /* Use DBNoTreeSrTiles() because we want to search only one level down */
200     return DBNoTreeSrTiles(scx, &drcMask, 0, drcSubCopyErrors, cdarg);
201 }
202 
203 /*
204  * ----------------------------------------------------------------------------
205  *
206  * drcSubcellFunc --
207  *
208  * 	Called by DBSrCellPlaneArea when looking for interactions in
209  *	a given area.  It sees if this subcell participates
210  *	in any interactions in the area we're rechecking.
211  *
212  * Results:
213  *	Always returns 0 to keep the search alive.
214  *
215  * Side effects:
216  *	The area drcSubIntArea is modified to include interactions
217  *	stemming from this subcell.
218  *
219  * ----------------------------------------------------------------------------
220  */
221 
222 int
drcSubcellFunc(subUse,propagate)223 drcSubcellFunc(subUse, propagate)
224     CellUse *subUse;		/* Subcell instance. */
225     bool *propagate;		/* Errors to propagate up */
226 {
227     Rect area, haloArea, intArea, subIntArea, locIntArea;
228     int i;
229 
230     /* To determine interactions, find the bounding box of
231      * all paint and other subcells within one halo of this
232      * subcell (and also within the original area where
233      * we're recomputing errors).
234      */
235 
236     area = subUse->cu_bbox;
237 
238     GEO_EXPAND(&area, drcSubRadius, &haloArea);
239     GeoClip(&haloArea, &drcSubLookArea);
240 
241     intArea = GeoNullRect;
242     for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
243     {
244 	(void) DBSrPaintArea((Tile *) NULL, drcSubDef->cd_planes[i],
245 	    &haloArea, &DBAllButSpaceBits, drcIncludeArea,
246 	    (ClientData) &intArea);
247     }
248 
249     /* DRC error tiles in a subcell are automatically pulled into the	*/
250     /* interaction area of the parent.	Ultimately this is recursive as	*/
251     /* all cells are checked and errors propagate to the top level.	*/
252 
253     subIntArea = GeoNullRect;
254 
255 #if (0)
256     /* NOTE:  DRC errors inside a subcell should be ignored for	*/
257     /* the purpose of finding interactions.  Errors should only	*/
258     /* be copied up into the parent when in a non-interaction	*/
259     /* area.  This is done below in DRCFindInteractions().	*/
260     /* (Method added by Tim, 10/15/2020)			*/
261 
262     /* Maybe S and PS errors should be pulled here? */
263 
264     DBSrPaintArea((Tile *) NULL, subUse->cu_def->cd_planes[PL_DRC_ERROR],
265 		&TiPlaneRect, &DBAllButSpaceBits, drcIncludeArea,
266 		(ClientData) &subIntArea);
267 
268     GeoTransRect(&(subUse->cu_transform), &subIntArea, &locIntArea);
269     GeoInclude(&locIntArea, &intArea);
270 #endif
271 
272     if (!GEO_RECTNULL(&subIntArea)) *propagate = TRUE;
273 
274     drcCurSub = subUse;
275     (void) DBSrCellPlaneArea(drcSubDef->cd_cellPlane, &haloArea,
276 		drcFindOtherCells, (ClientData)(&intArea));
277     if (GEO_RECTNULL(&intArea)) return 0;
278 
279     GEO_EXPAND(&intArea, drcSubRadius, &intArea);
280     GeoClip(&intArea, &haloArea);
281     (void) GeoInclude(&intArea, &drcSubIntArea);
282     return 0;
283 }
284 
285 /*
286  * ----------------------------------------------------------------------------
287  *
288  * drcAlwaysOne --
289  *
290  * 	This is a utility procedure that always returns 1 when it
291  *	is called.  It aborts searches and notifies the invoker that
292  *	an item was found during the search.
293  *
294  * Results:
295  *	Always returns 1 to abort searches.
296  *
297  * Side effects:
298  *	None.
299  *
300  * ----------------------------------------------------------------------------
301  */
302 
303 int
drcAlwaysOne()304 drcAlwaysOne()
305 {
306     return 1;
307 }
308 
309 /*
310  * ----------------------------------------------------------------------------
311  *
312  * drcSubCheckPaint --
313  *
314  * 	This procedure is invoked once for each subcell in a
315  *	particular interaction area.  It checks to see whether the
316  *	subcell's subtree actually contains some paint in the potential
317  *	interaction area.  As soon as the second such subcell is found,
318  *	it aborts the search.
319  *
320  * Results:
321  *	Returns 0 to keep the search alive, unless we've found the
322  *	second subcell containing paint in the interaction area.
323  *	When this occurs, the search is aborted by returning 1.
324  *
325  * Side effects:
326  *	When the first use with paint is found, curUse is modified
327  *	to contain its address.
328  *
329  * ----------------------------------------------------------------------------
330  */
331 
332 int
drcSubCheckPaint(scx,curUse)333 drcSubCheckPaint(scx, curUse)
334     SearchContext *scx;		/* Contains information about the celluse
335 				 * that was found.
336 				 */
337     CellUse **curUse;		/* Points to a celluse, or NULL, or -1.  -1
338 				 * means paint was found in the root cell,
339 				 * and non-NULL means some other celluse had
340 				 * paint in it.  If we find another celluse
341 				 * with paint, when this is non-NULL, it
342 				 * means there really are two cells with
343 				 * interacting paint, so we abort the
344 				 * search to tell the caller to really check
345 				 * this area.
346 				 */
347 {
348     if (DBTreeSrTiles(scx, &DBAllButSpaceAndDRCBits, 0, drcAlwaysOne,
349 	(ClientData) NULL) != 0)
350     {
351 	/* This subtree has stuff under the interaction area. */
352 
353 	if (*curUse != NULL) return 1;
354 	*curUse = scx->scx_use;
355     }
356     return 0;
357 }
358 
359 /*
360  * ----------------------------------------------------------------------------
361  *
362  * DRCFindInteractions --
363  *
364  * 	This procedure finds the bounding box of all subcell-subcell
365  *	or subcell-paint interactions in a given area of a given cell.
366  *
367  * Results:
368  *	Returns TRUE if there were any interactions in the given
369  *	area, FALSE if there were none.
370  *
371  * Side effects:
372  *	The parameter interaction is set to contain the bounding box
373  *	of all places in area where one subcell comes within radius
374  *	of another subcell, or where paint in def comes within radius
375  *	of a subcell.  Interactions between elements of array are not
376  *	considered here, but interactions between arrays and other
377  *	things are considered.  This routine is a bit clever, in that
378  *	it not only checks for bounding boxes interacting, but also
379  *	makes sure the cells really contain material in the interaction
380  *	area.
381  * ----------------------------------------------------------------------------
382  */
383 
384 bool
DRCFindInteractions(def,area,radius,interaction)385 DRCFindInteractions(def, area, radius, interaction)
386     CellDef *def;		/* Cell to check for interactions. */
387     Rect *area;			/* Area of def to check for interacting
388 				 * material.
389 				 */
390     int radius;			/* How close two pieces of material must be
391 				 * to be considered interacting.  Two pieces
392 				 * radius apart do NOT interact, but if they're
393 				 * close than this they do.
394 				 */
395     Rect *interaction;		/* Gets filled in with the bounding box of
396 				 * the interaction area, if any.  Doesn't
397 				 * have a defined value when FALSE is returned.
398 				 */
399 {
400     int i;
401     CellUse *use;
402     SearchContext scx;
403     bool propagate;
404 
405     drcSubDef = def;
406     drcSubRadius = radius;
407     DRCDummyUse->cu_def = def;
408 
409     /* Find all the interactions in the area and compute the
410      * outer bounding box of all those interactions.  An interaction
411      * exists whenever material in one cell approaches within radius
412      * of material in another cell.  As a first approximation, assume
413      * each cell has material everywhere within its bounding box.
414      */
415 
416     drcSubIntArea = GeoNullRect;
417     GEO_EXPAND(area, radius, &drcSubLookArea);
418     propagate = FALSE;
419     (void) DBSrCellPlaneArea(def->cd_cellPlane, &drcSubLookArea,
420 		drcSubcellFunc, (ClientData)(&propagate));
421 
422     /* If there seems to be an interaction area, make a second pass
423      * to make sure there's more than one cell with paint in the
424      * area.  This will save us a lot of work where two cells
425      * have overlapping bounding boxes without overlapping paint.
426      */
427 
428     if (GEO_RECTNULL(&drcSubIntArea)) return FALSE;
429     use = NULL;
430 
431     /* If errors are being propagated up from child to parent,	*/
432     /* then the interaction area is always valid.		*/
433 
434     if (propagate == FALSE)
435     {
436 	for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
437 	{
438 	    if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i],
439 			&drcSubIntArea, &DBAllButSpaceBits, drcAlwaysOne,
440 			(ClientData) NULL) != 0)
441 	    {
442 		use = (CellUse *) -1;
443 		break;
444 	    }
445 	}
446 	scx.scx_use = DRCDummyUse;
447 	scx.scx_trans = GeoIdentityTransform;
448 	scx.scx_area = drcSubIntArea;
449 	if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0)
450 	    return FALSE;
451     }
452 
453     /* OK, no more excuses, there's really an interaction area here. */
454 
455     *interaction = drcSubIntArea;
456     GeoClip(interaction, area);
457     if (GEO_RECTNULL(interaction)) return FALSE;
458     return TRUE;
459 }
460 
461 /*
462  * ----------------------------------------------------------------------------
463  *
464  * drcExactOverlapCheck --
465  *
466  * 	This procedure is invoked to check for overlap violations.
467  *	It is invoked by DBSrPaintArea from drcExactOverlapTile.
468  *	Any tiles passed to this procedure must lie within
469  *	arg->dCD_rect, or an error is reported.
470  *
471  * Results:
472  *	Always returns 0 to keep the search alive.
473  *
474  * Side effects:
475  *	If an error occurs, the client error function is called and
476  *	the error count is incremented.
477  *
478  * ----------------------------------------------------------------------------
479  */
480 
481 int
drcExactOverlapCheck(tile,arg)482 drcExactOverlapCheck(tile, arg)
483     Tile *tile;			/* Tile to check. */
484     struct drcClientData *arg;	/* How to detect and process errors. */
485 {
486     Rect rect;
487 
488     TiToRect(tile, &rect);
489     GeoClip(&rect, arg->dCD_clip);
490     if (GEO_RECTNULL(&rect)) return 0;
491 
492     (*(arg->dCD_function)) (arg->dCD_celldef, &rect, arg->dCD_cptr,
493 	arg->dCD_clientData);
494     (*(arg->dCD_errors))++;
495     return 0;
496 }
497 
498 /*
499  * ----------------------------------------------------------------------------
500  *
501  * drcExactOverlapTile --
502  *
503  * 	This procedure is invoked by DBTreeSrTiles for each tile
504  *	in each constituent cell of a subcell interaction.  It
505  *	makes sure that if this tile overlaps other tiles of the
506  *	same type in other cells, then the overlaps are EXACT:
507  *	each cell contains exactly the same information.
508  *
509  * Results:
510  *	Always returns 0 to keep the search alive.
511  *
512  * Side effects:
513  *	If there are errors, the client error handling routine
514  *	is invoked and the count in the drcClientData record is
515  *	incremented.
516  *
517  * ----------------------------------------------------------------------------
518  */
519 
520 int
drcExactOverlapTile(tile,cxp)521 drcExactOverlapTile(tile, cxp)
522     Tile *tile;			/* Tile that must overlap exactly. */
523     TreeContext *cxp;		/* Tells how to translate out of subcell.
524 				 * The client data must be a drcClientData
525 				 * record, and the caller must have filled
526 				 * in the celldef, clip, errors, function,
527 				 * cptr, and clientData fields.
528 				 */
529 {
530     struct drcClientData *arg;
531     TileTypeBitMask typeMask, invMask, *rmask;
532     TileType type, t;
533     Tile *tp;
534     Rect r1, r2, r3, rex;
535     int i;
536 
537     arg = (struct drcClientData *) cxp->tc_filter->tf_arg;
538     TiToRect(tile, &r1);
539     GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r2);
540 
541     GEO_EXPAND(&r2, 1, &rex); 	/* Area includes abutting tiles */
542     GeoClip(&rex, arg->dCD_clip);	/* Except areas outside search area */
543 
544     type = TiGetType(tile);
545     TTMaskSetOnlyType(&typeMask, type);
546     if (type < DBNumUserLayers)
547     {
548 	for (t = DBNumUserLayers; t < DBNumTypes; t++)
549 	{
550 	    rmask = DBResidueMask(t);
551 	    if (TTMaskHasType(rmask, type))
552 		TTMaskSetType(&typeMask, t);
553 	}
554 	TTMaskCom2(&invMask, &typeMask);
555     }
556     else
557     {
558 	rmask = DBResidueMask(type);
559 	TTMaskSetMask(&typeMask, rmask);    // Add residue types for inverse only
560 	TTMaskCom2(&invMask, &typeMask);
561 	TTMaskSetOnlyType(&typeMask, type); // Restore original type mask
562     }
563 
564     for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
565     {
566         if (DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i],
567 	    &rex, &typeMask, drcAlwaysOne, (ClientData) NULL))
568 	{
569 	    /* There is an overlap or abutment of ExactOverlap types. */
570 	    /* 1) Check if any invalid type is under this tile.	*/
571 
572 	    arg->dCD_rect = &r2;
573 	    DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i], &r2,
574 			&invMask, drcExactOverlapCheck, (ClientData) arg);
575 
576 	    /* 2) Search the neighboring tiles for types that do not	*/
577 	    /* match the exact overlap type, and flag abutment errors.	*/
578 
579 	    /* Search bottom */
580 	    arg->dCD_rect = &r3;
581 	    for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
582 		if (TTMaskHasType(&invMask, TiGetType(tp)))
583 		{
584 		    TiToRect(tp, &r1);
585 		    GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r3);
586 		    GeoClip(&r3, &rex);
587 		    if (!GEO_RECTNULL(&r3))
588 			DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i],
589 				&r3, &typeMask, drcExactOverlapCheck,
590 				(ClientData) arg);
591 		}
592 
593 	    /* Search right */
594 	    for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
595 		if (TTMaskHasType(&invMask, TiGetType(tp)))
596 		{
597 		    TiToRect(tp, &r1);
598 		    GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r3);
599 		    GeoClip(&r3, &rex);
600 		    if (!GEO_RECTNULL(&r3))
601 			DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i],
602 				&r3, &typeMask, drcExactOverlapCheck,
603 				(ClientData) arg);
604 		}
605 
606 	    /* Search top */
607 	    for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
608 		if (TTMaskHasType(&invMask, TiGetType(tp)))
609 		{
610 		    TiToRect(tp, &r1);
611 		    GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r3);
612 		    GeoClip(&r3, &rex);
613 		    if (!GEO_RECTNULL(&r3))
614 			DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i],
615 				&r3, &typeMask, drcExactOverlapCheck,
616 				(ClientData) arg);
617 		}
618 
619 	    /* Search left */
620 	    for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
621 		if (TTMaskHasType(&invMask, TiGetType(tp)))
622 		{
623 		    TiToRect(tp, &r1);
624 		    GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r3);
625 		    GeoClip(&r3, &rex);
626 		    if (!GEO_RECTNULL(&r3))
627 			DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i],
628 				&r3, &typeMask, drcExactOverlapCheck,
629 				(ClientData) arg);
630 		}
631 	}
632     }
633     return 0;
634 }
635 
636 /*
637  * ----------------------------------------------------------------------------
638  *
639  * DRCOffGridError ---
640  *
641  * Function to call when a call to DBCellCheckCopyAllPaint() flags an error
642  * indicating that a subcell overlap of non-Manhattan geometry resolves to
643  * an off-grid intersection point.  Note that this is different from the
644  * DRC off-grid check, which checks for geometry that does not match the
645  * manufacturing grid pitch.  This checks for the case of geometry that
646  * is finer than the underlying database grid, which can only happen for
647  * two non-Manhattan shapes interacting between two different cells, and
648  * can only be caught during the process of flattening the cell contents.
649  *
650  * Results:
651  *	None.
652  *
653  * Side effects:
654  *	Creates a DRC error or prints the DRC error message, depending on
655  *	the value of drcSubFunc.
656  *
657  * ----------------------------------------------------------------------------
658  */
659 
660 void
DRCOffGridError(rect)661 DRCOffGridError(rect)
662     Rect      *rect;            /* Area of error */
663 {
664     if (drcSubFunc == NULL) return;
665     (*drcSubFunc)(DRCErrorDef, rect, &drcOffGridCookie, drcSubClientData);
666 }
667 
668 /*
669  * ----------------------------------------------------------------------------
670  *
671  * DRCInteractionCheck --
672  *
673  * 	This is the top-level procedure that performs subcell interaction
674  *	checks.  All interaction rule violations in area of def are
675  *	found, and func is called for each one.
676  *
677  * Results:
678  *	The number of errors found.
679  *
680  * Side effects:
681  *	The procedure func is called for each violation found.  See
682  *	the header for DRCBasicCheck for information about how func
683  *	is called.  The violations passed to func are expressed in
684  *	the coordinates of def.  Only violations stemming from
685  *	interactions in def, as opposed to def's children, are reported.
686  *
687  * Design Note:
688  *	This procedure is trickier than you think.  The problem is that
689  *	DRC must be guaranteed to produce EXACTLY the same collection
690  *	of errors in an area, no matter how the area is checked.  Checking
691  *	it all as one big area should produce the same results as
692  *	checking it in several smaller pieces.  Otherwise, "drc why"
693  *	won't work correctly, and the error configuration will depend
694  *	on how the chip was checked, which is intolerable.  This problem
695  *	is solved here by dividing the world up into squares along a grid
696  *	of dimension DRCStepSize aligned at the origin.  Interaction areas
697  *	are always computed by considering everything inside one grid square
698  *	at a time.  We may have to consider several grid squares in order
699  *	to cover the area passed in by the client.
700  * ----------------------------------------------------------------------------
701  */
702 
703 int
DRCInteractionCheck(def,area,erasebox,func,cdarg)704 DRCInteractionCheck(def, area, erasebox, func, cdarg)
705     CellDef *def;		/* Definition in which to do check. */
706     Rect *area;			/* Area in which all errors are to be found. */
707     Rect *erasebox;		/* Smaller area containing DRC check tiles */
708     void (*func)();		/* Function to call for each error. */
709     ClientData cdarg;		/* Extra info to be passed to func. */
710 {
711     int oldTiles, count, x, y, errorSaveType;
712     Rect intArea, square, cliparea, subArea;
713     PaintResultType (*savedPaintTable)[NT][NT];
714     int (*savedPaintPlane)();
715     struct drcClientData arg;
716     SearchContext scx;
717 
718     drcSubFunc = func;
719     drcSubClientData = cdarg;
720     oldTiles = DRCstatTiles;
721     count = 0;
722 
723     /* Divide the area to be checked up into squares.  Process each
724      * square separately.
725      */
726 
727     x = (area->r_xbot/DRCStepSize) * DRCStepSize;
728     if (x > area->r_xbot) x -= DRCStepSize;
729     y = (area->r_ybot/DRCStepSize) * DRCStepSize;
730     if (y > area->r_ybot) y -= DRCStepSize;
731     for (square.r_xbot = x; square.r_xbot < area->r_xtop;
732 	 square.r_xbot += DRCStepSize)
733 	for (square.r_ybot = y; square.r_ybot < area->r_ytop;
734 	     square.r_ybot += DRCStepSize)
735 	{
736 	    square.r_xtop = square.r_xbot + DRCStepSize;
737 	    square.r_ytop = square.r_ybot + DRCStepSize;
738 
739 	    /* Limit square to erasebox.  Otherwise, a huge processing	*/
740 	    /* penalty is incurred for finding a single error (e.g.,	*/
741 	    /* using "drc find" or "drc why" in a large design with a	*/
742 	    /* large step size.						*/
743 
744             cliparea = square;
745 	    GeoClip(&cliparea, area);
746 
747 	    /* Prepare for subcell search */
748 	    DRCDummyUse->cu_def = def;
749 	    scx.scx_use = DRCDummyUse;
750 	    scx.scx_trans = GeoIdentityTransform;
751 	    arg.dCD_celldef = def;
752 	    arg.dCD_errors = &count;
753 	    arg.dCD_cptr = &drcInSubCookie;
754 	    arg.dCD_function = func;
755 	    arg.dCD_clientData = cdarg;
756 
757 	    /* Find all the interactions in the square, and clip to the error
758 	     * area we're interested in. */
759 
760 	    if (!DRCFindInteractions(def, &cliparea, DRCTechHalo, &intArea))
761 	    {
762 		/* Added May 4, 2008---if there are no subcells, run the
763 		 * basic check over the area of the erasebox.
764 		 */
765 		subArea = *erasebox;
766 		GeoClip(&subArea, &cliparea);
767 		GEO_EXPAND(&subArea, DRCTechHalo, &intArea);
768 
769 		errorSaveType = DRCErrorType;
770 		DRCErrorType = TT_ERROR_P;	// Basic check is always ERROR_P
771                 DRCBasicCheck(def, &intArea, &subArea, func, cdarg);
772 
773 		/* Copy errors up from all non-interacting children	*/
774 		scx.scx_area = subArea;
775 	    	arg.dCD_clip = &subArea;
776 		DBCellSrArea(&scx, drcSubCopyFunc, &arg);
777 		DBCellSrArea(&scx, drcArrayFunc, &arg);
778 
779 		DRCErrorType = errorSaveType;
780 		continue;
781 	    }
782 	    else
783 	    {
784 		/* Added March 6, 2012:  Any area(s) outside the
785 		 * interaction area are processed with the basic
786 		 * check.  This avoids unnecessary copying, so it
787 		 * speeds up the DRC without requiring that geometry
788 		 * passes DRC rules independently of subcell geometry
789 	         * around it.
790 		 *
791 		 * As intArea can be smaller than square, we may have
792 		 * to process as many as four independent rectangles.
793 		 * NOTE that the area of (intArea + halo) will be checked
794 		 * in the subcell interaction check, so we can ignore
795 		 * that.
796 		 */
797 		Rect eraseClip, eraseHalo, subArea;
798 
799 		errorSaveType = DRCErrorType;
800 		DRCErrorType = TT_ERROR_P;	// Basic check is always ERROR_P
801 		eraseClip = *erasebox;
802 		GeoClip(&eraseClip, &cliparea);
803 		subArea = eraseClip;
804 	    	arg.dCD_clip = &subArea;
805 
806 		/* check above */
807 		if (intArea.r_ytop < eraseClip.r_ytop)
808 		{
809 		    subArea.r_ybot = intArea.r_ytop;
810 		    GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo);
811                     DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg);
812 		    /* Copy errors up from all non-interacting children	*/
813 		    scx.scx_area = subArea;
814 		    DBCellSrArea(&scx, drcSubCopyFunc, &arg);
815 		    DBCellSrArea(&scx, drcArrayFunc, &arg);
816 		}
817 		/* check below */
818 		if (intArea.r_ybot > eraseClip.r_ybot)
819 		{
820 		    subArea.r_ybot = eraseClip.r_ybot;
821 		    subArea.r_ytop = intArea.r_ybot;
822 		    GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo);
823                     DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg);
824 		    /* Copy errors up from all non-interacting children	*/
825 		    scx.scx_area = subArea;
826 		    DBCellSrArea(&scx, drcSubCopyFunc, &arg);
827 		    DBCellSrArea(&scx, drcArrayFunc, &arg);
828 		}
829 		subArea.r_ytop = intArea.r_ytop;
830 		subArea.r_ybot = intArea.r_ybot;
831 
832 		/* check right */
833 		if (intArea.r_xtop < eraseClip.r_xtop)
834 		{
835 		    subArea.r_xbot = intArea.r_xtop;
836 		    GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo);
837                     DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg);
838 		    /* Copy errors up from all non-interacting children	*/
839 		    scx.scx_area = subArea;
840 		    DBCellSrArea(&scx, drcSubCopyFunc, &arg);
841 		    DBCellSrArea(&scx, drcArrayFunc, &arg);
842 		}
843 		/* check left */
844 		if (intArea.r_xbot > eraseClip.r_xbot)
845 		{
846 		    subArea.r_xtop = intArea.r_xbot;
847 		    subArea.r_xbot = eraseClip.r_xbot;
848 		    GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo);
849                     DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg);
850 		    /* Copy errors up from all non-interacting children	*/
851 		    scx.scx_area = subArea;
852 		    DBCellSrArea(&scx, drcSubCopyFunc, &arg);
853 		    DBCellSrArea(&scx, drcArrayFunc, &arg);
854 		}
855 		DRCErrorType = errorSaveType;
856 	    }
857 
858  	    /* Clip interaction area against subArea-expanded-by-halo */
859 
860 	    subArea = *erasebox;
861 	    GEO_EXPAND(&subArea, DRCTechHalo, &cliparea);
862 	    GeoClip(&intArea, &cliparea);
863 
864 	    /* Flatten the interaction area. */
865 
866 	    DRCstatInteractions += 1;
867 	    GEO_EXPAND(&intArea, DRCTechHalo, &scx.scx_area);
868 	    DBCellClearDef(DRCdef);
869 
870 	    savedPaintTable = DBNewPaintTable(DRCCurStyle->DRCPaintTable);
871 	    savedPaintPlane = DBNewPaintPlane(DBPaintPlaneMark);
872 
873 	    (void) DBCellCheckCopyAllPaint(&scx, &DBAllButSpaceBits, 0,
874 			DRCuse, func);
875 
876 	    (void) DBNewPaintTable(savedPaintTable);
877 	    (void) DBNewPaintPlane(savedPaintPlane);
878 
879 	    /* Run the basic checker over the interaction area. */
880 
881 	    count += DRCBasicCheck(DRCdef, &scx.scx_area, &intArea,
882 		func, cdarg);
883 	    /* TxPrintf("Interaction area: (%d, %d) (%d %d)\n",
884 		intArea.r_xbot, intArea.r_ybot,
885 		intArea.r_xtop, intArea.r_ytop);
886 	    */
887 
888 	    /* Check for illegal partial overlaps. */
889 
890 	    scx.scx_area = intArea;
891 	    arg.dCD_clip = &intArea;
892 	    arg.dCD_celldef = DRCdef;
893 	    arg.dCD_cptr = &drcSubcellCookie;
894 	    (void) DBTreeSrUniqueTiles(&scx, &DRCCurStyle->DRCExactOverlapTypes,
895 			0, drcExactOverlapTile, (ClientData) &arg);
896 	}
897 
898     /* Update count of interaction tiles processed. */
899 
900     DRCstatIntTiles += DRCstatTiles - oldTiles;
901     return count;
902 }
903 
904 void
DRCFlatCheck(use,area)905 DRCFlatCheck(use, area)
906     CellUse *use;
907     Rect *area;
908 {
909     int x, y;
910     Rect chunk;
911     SearchContext scx;
912     void drcIncCount();
913     PaintResultType (*savedPaintTable)[NT][NT];
914     int (*savedPaintPlane)();
915     int drcFlatCount = 0;
916 
917     UndoDisable();
918     for (y = area->r_ybot; y < area->r_ytop;  y += 300)
919     {
920 	for (x = area->r_xbot; x < area->r_xtop; x += 300)
921 	{
922 	    chunk.r_xbot = x;
923 	    chunk.r_ybot = y;
924 	    chunk.r_xtop = x+300;
925 	    chunk.r_ytop = y+300;
926 	    if (chunk.r_xtop > area->r_xtop) chunk.r_xtop = area->r_xtop;
927 	    if (chunk.r_ytop > area->r_ytop) chunk.r_ytop = area->r_ytop;
928 	    GEO_EXPAND(&chunk, DRCTechHalo, &scx.scx_area);
929 	    scx.scx_use = use;
930 	    scx.scx_trans = GeoIdentityTransform;
931 	    DBCellClearDef(DRCdef);
932 
933 	    savedPaintTable = DBNewPaintTable(DRCCurStyle->DRCPaintTable);
934 	    savedPaintPlane = DBNewPaintPlane(DBPaintPlaneMark);
935 
936 	    (void) DBCellCopyAllPaint(&scx, &DBAllButSpaceBits, 0, DRCuse);
937 
938 	    (void) DBNewPaintTable(savedPaintTable);
939 	    (void) DBNewPaintPlane(savedPaintPlane);
940 
941 	    (void) DRCBasicCheck(DRCdef, &scx.scx_area, &chunk,
942 		drcIncCount, (ClientData) &drcFlatCount);
943 	}
944     }
945     TxPrintf("%d total errors found.\n", drcFlatCount);
946     UndoEnable();
947 }
948 
949 void
drcIncCount(def,area,rule,count)950 drcIncCount(def, area, rule, count)
951     CellDef *def;
952     Rect *area;
953     DRCCookie *rule;
954     int *count;
955 {
956     *count++;
957 }
958