magic/extract/ExtInter.c

489 lines
14 KiB
C

/*
* ExtInteraction.c --
*
* Circuit extraction.
* Finds interaction areas.
*
* *********************************************************************
* * 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/extract/ExtInter.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/geofast.h"
#include "utils/undo.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "utils/malloc.h"
#include "textio/textio.h"
#include "debug/debug.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
#include "utils/signals.h"
#include "utils/styles.h"
/* Local data */
CellUse *extInterUse = (CellUse *) NULL; /* Subtree being processed */
Plane *extInterPlane; /* Paint into this plane */
int extInterHalo; /* Elements closer than this
* constitute an interaction.
*/
int extInterBloat; /* Bloat by this much when
* painting into result plane.
*/
/* Forward declarations */
int extInterOverlapSubtree();
int extInterOverlapTile();
int extInterSubtree();
int extInterSubtreeClip();
int extInterSubtreeElement();
int extInterSubtreeTile();
int extInterSubtreePaint();
#define BLOATBY(r, h) ( (r)->r_xbot -= (h), (r)->r_ybot -= (h), \
(r)->r_xtop += (h), (r)->r_ytop += (h) )
/*
* ----------------------------------------------------------------------------
*
* ExtFindInteractions --
*
* Paint into the supplied tile plane 'resultPlane' TT_ERROR_P tiles
* for each area in the CellDef 'def' that must be processed for
* interactions.
*
* Each interaction arises from paint in two different subtrees
* being less than (but not equal to) 'halo' units away from
* each other. In this definition, a subtree refers to a single
* CellUse, which may be either a single cell or an entire array.
*
* If 'bloat' is non-zero, each interaction area is bloated by
* this amount when being painted into the result plane.
*
* Results:
* None.
*
* Side effects:
* Paints into the plane 'resultPlane'.
*
* ----------------------------------------------------------------------------
*/
void
ExtFindInteractions(def, halo, bloatby, resultPlane)
CellDef *def; /* Find interactions among children of def */
int halo; /* Interaction is elements closer than halo */
int bloatby; /* Bloat each interaction area by this amount when
* painting into resultPlane.
*/
Plane *resultPlane; /* Paint interaction areas into this plane */
{
SearchContext scx;
UndoDisable();
extInterPlane = resultPlane;
extInterHalo = halo;
extInterBloat = bloatby;
extParentUse->cu_def = def;
scx.scx_use = extParentUse;
scx.scx_trans = GeoIdentityTransform;
scx.scx_area = def->cd_bbox;
/*
* Process each child subtree.
* This involves comparing all the paint in the subtree
* with all the paint in all other subtrees up to, but
* not including, the subtree under consideration.
*/
extInterUse = (CellUse *) NULL;
(void) DBCellSrArea(&scx, extInterSubtree, (ClientData) NULL);
/*
* Process parent paint if there were any subcells.
* We compare each paint rectangle with all the paint in
* all the subtrees, to see if there is an overlap.
*/
if (extInterUse)
{
extInterUse = (CellUse *) NULL;
(void) DBCellSrArea(&scx, extInterSubtreePaint, (ClientData) def);
}
UndoEnable();
}
int
extInterSubtreePaint(scx, def)
SearchContext *scx;
CellDef *def;
{
Rect r;
int pNum;
r = scx->scx_use->cu_bbox;
BLOATBY(&r, extInterHalo);
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &r,
&DBAllButSpaceAndDRCBits, extInterSubtreeTile, (ClientData) NULL);
return (2);
}
/*
* ----------------------------------------------------------------------------
*
* extInterSubtree --
*
* Called for each immediate child use of the cell being processed
* for interactions. Our job is to process all the paint in this
* use against all other subtrees overlapping this one.
*
* Results:
* Returns 2 to abort after the first array element.
*
* Side effects:
* Sets extInterUse to scx->scx_use.
* Children may paint into extInterPlane.
*
* ----------------------------------------------------------------------------
*/
int
extInterSubtree(scx)
SearchContext *scx;
{
CellUse *oldUse = extInterUse;
SearchContext parentScx;
extInterUse = scx->scx_use;
if (oldUse)
{
/* Find all other subtrees overlapping this cell */
parentScx.scx_area = scx->scx_use->cu_bbox;
BLOATBY(&parentScx.scx_area, extInterHalo);
parentScx.scx_trans = GeoIdentityTransform;
parentScx.scx_use = extParentUse;
(void) DBCellSrArea(&parentScx, extInterSubtreeClip, (ClientData) scx);
}
return (2);
}
int
extInterSubtreeClip(overlapScx, scx)
SearchContext *overlapScx, *scx;
{
Rect r, r2;
/* Only search as far as extInterUse */
if (overlapScx->scx_use == extInterUse)
return (2);
/*
* Only process the overlap between overlapScx and scx,
* bloating both by extInterHalo.
*/
r = overlapScx->scx_use->cu_bbox;
BLOATBY(&r, extInterHalo);
r2 = scx->scx_use->cu_bbox;
BLOATBY(&r2, extInterHalo);
GEOCLIP(&r, &r2);
(void) DBArraySr(scx->scx_use, &r, extInterSubtreeElement,
(ClientData) &r);
return (2);
}
/*
* ----------------------------------------------------------------------------
*
* extInterSubtreeElement --
*
* Called for each element in the array forming the use passed to
* extInterSubtree(). See extInterSubtree() for comments.
*
* Results:
* Returns 0 always.
*
* Side effects:
* See ExtFindInteractions.
*
* ----------------------------------------------------------------------------
*/
int
extInterSubtreeElement(use, trans, x, y, r)
CellUse *use;
Transform *trans;
int x, y;
Rect *r;
{
SearchContext scx;
Transform tinv;
scx.scx_use = use;
scx.scx_trans = *trans;
scx.scx_x = x;
scx.scx_y = y;
GEOINVERTTRANS(trans, &tinv);
GEOTRANSRECT(&tinv, r, &scx.scx_area);
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
extInterSubtreeTile, (ClientData) NULL);
return (0);
}
/*
* ----------------------------------------------------------------------------
*
* extInterSubtreeTile --
*
* Called for each tile in the subtree being processed by
* extInterSubtree(). Transform this tile to root coordinates,
* bloating by extInterHalo, and then call extInterOverlapSubtree
* to process all the other subtrees for paint overlapping
* this bloated area. If the argument 'cxp' is non-NULL, we
* use cxp->tc_scx->scx_trans to transform the area of tile to
* root coordinates; otherwise, we don't transform it at all.
*
* Results:
* Returns 0 always.
*
* Side effects:
* See extInterOverlapTile.
*
* ----------------------------------------------------------------------------
*/
int
extInterSubtreeTile(tile, cxp)
Tile *tile;
TreeContext *cxp;
{
SearchContext newscx;
Rect r;
TITORECT(tile, &r);
BLOATBY(&r, extInterHalo);
if (cxp)
{
GEOTRANSRECT(&cxp->tc_scx->scx_trans, &r, &newscx.scx_area);
}
else newscx.scx_area = r;
newscx.scx_trans = GeoIdentityTransform;
newscx.scx_use = extParentUse;
(void) DBCellSrArea(&newscx, extInterOverlapSubtree, (ClientData) NULL);
return (0);
}
/*
* ----------------------------------------------------------------------------
*
* extInterOverlapSubtree --
*
* Called for each subcell of the root that overlaps the piece
* of paint found by extInterSubtreeTile() above. We stop
* as soon as we see extInterUse; otherwise, search all the
* cells in the subtree rooted at scx->scx_use for paint
* overlapping scx->scx_area.
*
* Results:
* Returns 2 if we see extInterUse; otherwise, returns 0.
*
* Side effects:
* Paints into the plane 'resultPlane'; see extInterOverlapTile.
*
* ----------------------------------------------------------------------------
*/
int
extInterOverlapSubtree(scx)
SearchContext *scx;
{
if (extInterUse == scx->scx_use)
return (2);
(void) extTreeSrPaintArea(scx, extInterOverlapTile, (ClientData) NULL);
return (0);
}
/*
* ----------------------------------------------------------------------------
*
* extInterOverlapTile --
*
* Called for each piece of paint overlapping the piece found
* by extInterSubtreeTile(). Bloat the found piece by extInterHalo,
* then clip to the area of the overlapping piece of paint in root
* coordinates. If the result is non-empty, paint it into the
* plane extInterPlane.
*
* Results:
* Returns 0 always.
*
* Side effects:
* Paints into the plane 'resultPlane'.
*
* ----------------------------------------------------------------------------
*/
int
extInterOverlapTile(tile, cxp)
Tile *tile;
TreeContext *cxp;
{
SearchContext *scx = cxp->tc_scx;
Rect r, rootr;
TITORECT(tile, &r);
BLOATBY(&r, extInterHalo);
GEOCLIP(&r, &scx->scx_area);
if (GEO_RECTNULL(&r))
return (0);
GEOTRANSRECT(&scx->scx_trans, &r, &rootr);
BLOATBY(&rootr, extInterBloat);
DBPaintPlane(extInterPlane, &rootr, DBStdWriteTbl(TT_ERROR_P),
(PaintUndoInfo *) NULL);
return (0);
}
/*
*-----------------------------------------------------------------------------
*
* extTreeSrPaintArea --
*
* Recursively search downward from the supplied CellUse for
* all paint tiles.
*
* The procedure should be of the following form:
*
* int
* func(tile, scx, cdata)
* Tile *tile;
* SearchContext *scx;
* ClientData cdata;
* {
* }
*
* The SearchContext is stored in cxp->tc_scx, and the user's arg is stored
* in cxp->tc_filter->tf_arg.
*
* In the above, the scx transform is the net transform from the coordinates
* of tile to "world" coordinates (or whatever coordinates the initial
* transform supplied to extTreeSrTiles was a transform to). Func returns
* 0 under normal conditions. If 1 is returned, it is a request to
* abort the search.
*
* *** WARNING ***
*
* The client procedure should not modify any of the paint planes in
* the cells visited by extTreeSrTiles, because we use DBSrPaintArea
* as our paint-tile enumeration function.
*
* Results:
* 0 is returned if the search finished normally. 1 is returned
* if the search was aborted.
*
* Side effects:
* Whatever side effects are brought about by applying the
* procedure supplied.
*
*-----------------------------------------------------------------------------
*/
int
extTreeSrPaintArea(scx, func, cdarg)
SearchContext *scx; /* Pointer to search context specifying
* a cell use to search, an area in the
* coordinates of the cell's def, and a
* transform back to "root" coordinates.
*/
int (*func)(); /* Function to apply at each qualifying tile */
ClientData cdarg; /* Client data for above function */
{
int extTreeSrFunc();
CellDef *def = scx->scx_use->cu_def;
TreeContext context;
TreeFilter filter;
int pNum;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
filter.tf_func = func;
filter.tf_arg = cdarg;
context.tc_scx = scx;
context.tc_filter = &filter;
/*
* Apply the function first to any of the tiles in the planes
* for this CellUse's CellDef that match the mask.
*/
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
&scx->scx_area, &DBAllButSpaceAndDRCBits, func,
(ClientData) &context))
return (1);
/* Visit our children recursively */
return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) &filter));
}
/*
* extTreeSrFunc --
*
* Filter procedure applied to subcells by extTreeSrPaintArea().
*/
int
extTreeSrFunc(scx, fp)
SearchContext *scx;
TreeFilter *fp;
{
CellDef *def = scx->scx_use->cu_def;
TreeContext context;
int pNum;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return (0);
}
context.tc_scx = scx;
context.tc_filter = fp;
/*
* Apply the function first to any of the tiles in the planes
* for this CellUse's CellDef that match the mask.
*/
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
&scx->scx_area, &DBAllButSpaceAndDRCBits,
fp->tf_func, (ClientData) &context))
return (1);
/* Visit our children recursively */
return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) fp));
}