1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
|
/*
* DRCarray.c --
*
* This file provides routines that check arrays to be sure
* there are no unpleasant interactions between adjacent
* elements. Note: the routines in this file are NOT generally
* re-entrant.
*
* *********************************************************************
* * 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-7.5/drc/DRCarray.c,v 1.2 2007/12/25 01:06:24 tim Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <stdio.h>
#include "utils/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "drc/drc.h"
#include "windows/windows.h"
#include "commands/commands.h"
/* Forward references: */
extern int drcArrayYankFunc(), drcArrayOverlapFunc();
/* Dummy DRC cookie used to pass the error message to DRC error
* routines.
*/
static DRCCookie drcArrayCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
"This layer can't abut or partially overlap between array elements",
(DRCCookie *) NULL
};
/* Static variables used to pass information between DRCArrayCheck
* and drcArrayFunc:
*/
static int drcArrayCount; /* Count of number of errors found. */
static void (*drcArrayErrorFunc)(); /* Function to call on violations. */
static ClientData drcArrayClientData; /* Extra parameter to pass to func. */
/*
* ----------------------------------------------------------------------------
*
* drcArrayFunc --
*
* This procedure is invoked by DBCellSrArea once for each cell
* overlapping the area being checked. If the celluse is for
* an array, then it is checked for array correctness.
*
* Results:
* Always returns 2, to skip the remaining instances in the
* current array.
*
* Side effects:
* Design rules are checked for the subcell, if it is an array,
* and the count of errors is added into drcSubCount.
*
* Design:
* To verify that an array is correct, we only have to check
* four interaction areas, shaded as A, B, C, and D in the diagram
* below. The exact size of the interaction areas depends on
* how much overlap there is. In the extreme cases, there may be
* no areas to check at all (instances widely separated), or there
* may even be areas with more than four instances overlapping
* (spacing less than half the size of the instance).
*
* --------------DDDDD------------------------------
* | DDDDD | |
* | | | |
* | | | |
* | | | |
* -------------------------------------------------
* | | | |
* | | | |
* | | | |
* AAAAAAAAAAAAAAAAAAA | CCC
* AAAAAAAAAAAAAAAAAAA---------------------------CCC
* AAAAAAAAAAAAAAAAAAA | CCC
* | BBBBB | |
* | BBBBB | |
* | BBBBB | |
* --------------BBBBB------------------------------
*
* ----------------------------------------------------------------------------
*/
int
drcArrayFunc(scx, area)
SearchContext *scx; /* Information about the search. */
Rect *area; /* Area in which errors are to be
* regenerated.
*/
{
int xsep, ysep;
int xsize, ysize;
Rect errorArea, yankArea, tmp, tmp2;
CellUse *use = scx->scx_use;
struct drcClientData arg;
if ((use->cu_xlo == use->cu_xhi) && (use->cu_ylo == use->cu_yhi))
return 2;
/* Set up the client data that will be passed down during
* checks for exact overlaps.
*/
arg.dCD_celldef = DRCdef;
arg.dCD_errors = &drcArrayCount;
arg.dCD_clip = &errorArea;
arg.dCD_cptr = &drcArrayCookie;
arg.dCD_function = drcArrayErrorFunc;
arg.dCD_clientData = drcArrayClientData;
/* Compute the sizes and separations of elements, in coordinates
* of the parend. If the array is 1-dimensional, we set the
* corresponding spacing to an impossibly large distance.
*/
tmp.r_xbot = 0;
tmp.r_ybot = 0;
if (use->cu_xlo == use->cu_xhi)
tmp.r_xtop = DRCTechHalo + use->cu_def->cd_bbox.r_xtop
- use->cu_def->cd_bbox.r_xbot;
else tmp.r_xtop = use->cu_xsep;
if (use->cu_ylo == use->cu_yhi)
tmp.r_ytop = DRCTechHalo + use->cu_def->cd_bbox.r_ytop
- use->cu_def->cd_bbox.r_ybot;
else tmp.r_ytop = use->cu_ysep;
GeoTransRect(&use->cu_transform, &tmp, &tmp2);
xsep = tmp2.r_xtop - tmp2.r_xbot;
ysep = tmp2.r_ytop - tmp2.r_ybot;
GeoTransRect(&use->cu_transform, &use->cu_def->cd_bbox, &tmp2);
xsize = tmp2.r_xtop - tmp2.r_xbot;
ysize = tmp2.r_ytop - tmp2.r_ybot;
/* Check each of the four areas A, B, C, and D. Remember that
* absolutely arbitrary overlaps between cells are allowed.
* Skip some or all of the areas if the cell isn't arrayed in
* that direction or if the instances are widely spaced.
*/
if (ysep < ysize + DRCTechHalo)
{
/* A */
errorArea.r_xbot = use->cu_bbox.r_xbot;
errorArea.r_xtop = use->cu_bbox.r_xbot + xsize + DRCTechHalo;
errorArea.r_ybot = use->cu_bbox.r_ybot + ysep - DRCTechHalo;
errorArea.r_ytop = use->cu_bbox.r_ybot + ysize + DRCTechHalo;
GeoClip(&errorArea, area);
if (!GEO_RECTNULL(&errorArea))
{
GEO_EXPAND(&errorArea, DRCTechHalo, &yankArea);
DBCellClearDef(DRCdef);
(void) DBArraySr(use, &yankArea, drcArrayYankFunc,
(ClientData) &yankArea);
drcArrayCount += DRCBasicCheck(DRCdef, &yankArea, &errorArea,
drcArrayErrorFunc, drcArrayClientData);
(void) DBArraySr(use, &errorArea, drcArrayOverlapFunc,
(ClientData) &arg);
}
/* C */
errorArea.r_xtop = use->cu_bbox.r_xtop;
errorArea.r_xbot = use->cu_bbox.r_xtop - DRCTechHalo;
GeoClip(&errorArea, area);
if (!GEO_RECTNULL(&errorArea))
{
GEO_EXPAND(&errorArea, DRCTechHalo, &yankArea);
DBCellClearDef(DRCdef);
(void) DBArraySr(use, &yankArea, drcArrayYankFunc,
(ClientData) &yankArea);
drcArrayCount += DRCBasicCheck(DRCdef, &yankArea, &errorArea,
drcArrayErrorFunc, drcArrayClientData);
(void) DBArraySr(use, &errorArea, drcArrayOverlapFunc,
(ClientData) &arg);
}
}
if (xsep < xsize + DRCTechHalo)
{
/* B */
errorArea.r_xbot = use->cu_bbox.r_xbot + xsep - DRCTechHalo;
errorArea.r_xtop = use->cu_bbox.r_xbot + xsize + DRCTechHalo;
errorArea.r_ybot = use->cu_bbox.r_ybot;
errorArea.r_ytop = errorArea.r_ybot + ysep - DRCTechHalo;
GeoClip(&errorArea, area);
if (!GEO_RECTNULL(&errorArea))
{
GEO_EXPAND(&errorArea, DRCTechHalo, &yankArea);
DBCellClearDef(DRCdef);
(void) DBArraySr(use, &yankArea, drcArrayYankFunc,
(ClientData) &yankArea);
drcArrayCount += DRCBasicCheck(DRCdef, &yankArea, &errorArea,
drcArrayErrorFunc, drcArrayClientData);
(void) DBArraySr(use, &errorArea, drcArrayOverlapFunc,
(ClientData) &arg);
}
/* D */
errorArea.r_ytop = use->cu_bbox.r_ytop;
errorArea.r_ybot = use->cu_bbox.r_ytop - DRCTechHalo;
GeoClip(&errorArea, area);
if (!GEO_RECTNULL(&errorArea))
{
GEO_EXPAND(&errorArea, DRCTechHalo, &yankArea);
DBCellClearDef(DRCdef);
(void) DBArraySr(use, &yankArea, drcArrayYankFunc,
(ClientData) &yankArea);
drcArrayCount += DRCBasicCheck(DRCdef, &yankArea, &errorArea,
drcArrayErrorFunc, drcArrayClientData);
(void) DBArraySr(use, &errorArea, drcArrayOverlapFunc,
(ClientData) &arg);
}
}
return 2;
}
/*
* ----------------------------------------------------------------------------
* DRCArrayCheck --
*
* This procedure finds all DRC errors in a given area of
* a given cell that stem from array formation errors in
* children of that cell. Func is called for each violation
* found. Func should have the same form as in DRCBasicCheck.
* Note: the def passed to func is the dummy DRC definition,
* and the errors are all expressed in coordinates of celluse.
*
* Results:
* The number of errors found.
*
* Side effects:
* Whatever is done by func.
*
* ----------------------------------------------------------------------------
*/
int
DRCArrayCheck(def, area, func, cdarg)
CellDef *def; /* Parent cell containing the arrays to
* be rechecked.
*/
Rect *area; /* Area, in def's coordinates, where all
* array violations are to be regenerated.
*/
void (*func)(); /* Function to call for each error. */
ClientData cdarg; /* Client data to be passed to func. */
{
SearchContext scx;
int oldTiles;
PaintResultType (*savedPaintTable)[NT][NT];
PaintResultType (*savedEraseTable)[NT][NT];
void (*savedPaintPlane)();
/* Use DRCDummyUse to fake up a celluse for searching purposes. */
DRCDummyUse->cu_def = def;
drcArrayErrorFunc = func;
drcArrayClientData = cdarg;
drcArrayCount = 0;
oldTiles = DRCstatTiles;
scx.scx_area = *area;
scx.scx_use = DRCDummyUse;
scx.scx_trans = GeoIdentityTransform;
/* During array processing, switch the paint table to catch
* illegal overlaps.
*/
/*
savedPaintTable = DBNewPaintTable(DRCPaintTable);
savedPaintPlane = DBNewPaintPlane(DBPaintPlaneMergeOnce);
*/
(void) DBCellSrArea(&scx, drcArrayFunc, (ClientData) area);
/*
(void) DBNewPaintTable(savedPaintTable);
(void) DBNewPaintPlane(savedPaintPlane);
*/
/* Update count of array tiles processed. */
DRCstatArrayTiles += DRCstatTiles - oldTiles;
return drcArrayCount;
}
/*
* ----------------------------------------------------------------------------
*
* drcArrayYankFunc --
*
* Search action function called while yanking pieces of an array.
*
* Results:
* Always returns 0, to keep the search going.
*
* Side effects:
* Yanks from an array element into the DRC yank buffer.
*
* ----------------------------------------------------------------------------
*/
/* ARGSUSED */
int
drcArrayYankFunc(use, transform, x, y, yankArea)
CellUse *use; /* CellUse being array-checked. */
Transform *transform; /* Transform from instance to parent.*/
int x, y; /* Element indices (not used). */
Rect *yankArea; /* Area to yank (in parent coords). */
{
SearchContext scx;
Transform tinv;
GeoInvertTrans(transform, &tinv);
GeoTransRect(&tinv, yankArea, &scx.scx_area);
scx.scx_use = use;
scx.scx_trans = *transform;
(void) DBCellCopyAllPaint(&scx, &DBAllButSpaceBits, 0, DRCuse);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* drcArrayOverlapFunc --
*
* This is a search action function called while checking pieces
* of an array to be sure that there aren't any illegal partial
* overlaps. It just invokes overlap checking facilities in
* DRCsubcell.c
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* The client's error function may be invoked.
*
* ----------------------------------------------------------------------------
*/
/* ARGSUSED */
int
drcArrayOverlapFunc(use, transform, x, y, arg)
CellUse *use; /* CellUse for array element. */
Transform *transform; /* Transform from use to parent. */
int x, y; /* Indices of element. */
struct drcClientData *arg; /* Information used in overlap
* checking. See drcExactOverlapTile.
*/
{
Transform tinv;
SearchContext scx;
GeoInvertTrans(transform, &tinv);
GeoTransRect(&tinv, arg->dCD_clip, &scx.scx_area);
scx.scx_use = use;
scx.scx_trans = *transform;
(void) DBTreeSrTiles(&scx, &DRCCurStyle->DRCExactOverlapTypes, 0,
drcExactOverlapTile, (ClientData) arg);
return 0;
}
|