2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* mzBlock.c --
|
|
|
|
|
*
|
|
|
|
|
* Construction of blockage planes.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* *********************************************************************
|
2017-04-25 14:41:48 +02:00
|
|
|
* * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the *
|
2020-05-23 23:13:14 +02:00
|
|
|
* * 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. *
|
2017-04-25 14:41:48 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
*
|
|
|
|
|
* A blockage plane is used to determine the legal areas for routing.
|
|
|
|
|
* Each point on the interior of a space tile in a blockage plane is
|
|
|
|
|
* a legal position to place the lower-left corner of a piece of wiring.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* To build a blockage plane, each solid mask tile in the
|
2017-04-25 14:41:48 +02:00
|
|
|
* layout is bloated in
|
|
|
|
|
* all four directions and painted into the blockage plane. To the
|
|
|
|
|
* top and right, it is only bloated by the minimum separation from
|
|
|
|
|
* that tile to routing on that plane (s). To the bottom and left,
|
|
|
|
|
* though, it is bloated by this distance PLUS one less than the
|
|
|
|
|
* minimum width of routing on that layer (w-1):
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* s+w-1 s
|
|
|
|
|
* <-------> <-->
|
|
|
|
|
* +---------------------------+ ^
|
|
|
|
|
* | | | s
|
|
|
|
|
* | +---------------+ | v
|
|
|
|
|
* | |. . . . . . . .| |
|
|
|
|
|
* | | . . tile. . . | |
|
|
|
|
|
* | |. . . . . . . .| |
|
|
|
|
|
* | +---------------+ | ^
|
|
|
|
|
* | | |
|
|
|
|
|
* | blockage | | s+w-1
|
|
|
|
|
* | | |
|
|
|
|
|
* +---------------------------+ v
|
|
|
|
|
*
|
|
|
|
|
* Blockage planes are kept for each routeLayer and routeContact. They
|
|
|
|
|
* are part of ther RouteType datastructure.
|
|
|
|
|
*
|
|
|
|
|
* There are two blockage planes for each routeType. One is merged into
|
|
|
|
|
* maximal horizontal strips, and the other
|
|
|
|
|
* into maximal vertical strips. (To be done---there's no reason to
|
|
|
|
|
* have separate routines for maximal vertical strips; just use max
|
|
|
|
|
* horizontal strips routines with x and y appropriately swapped).
|
|
|
|
|
*
|
|
|
|
|
* Start and destination nodes are treated differently, by considering
|
|
|
|
|
* the areas in which a route's lower left corner can be placed that will
|
|
|
|
|
* let the route terminate without DRC errors. This is the following:
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* w-1 w-1
|
2017-04-25 14:41:48 +02:00
|
|
|
* <-----> <---->
|
|
|
|
|
* +-------------+-----+ ^
|
|
|
|
|
* |. . . . . . .|. . .| | w-1
|
2020-05-23 23:13:14 +02:00
|
|
|
* | . . . . . . | . . | |
|
2017-04-25 14:41:48 +02:00
|
|
|
* +-----+. . . . . . .+-----+ v
|
|
|
|
|
* | | . . . . . . . . . |
|
|
|
|
|
* | |. . .tile . . . . .|
|
|
|
|
|
* | | . . . . . . . . . |
|
|
|
|
|
* +-----+-------------+-----+ ^
|
|
|
|
|
* | | |
|
|
|
|
|
* | | | w-1
|
|
|
|
|
* +-------------+ v
|
|
|
|
|
*
|
|
|
|
|
* The upper-right corner of the tile is a keep-out area, where a route
|
|
|
|
|
* would violate width rules. The rest of the tile is valid for placement
|
|
|
|
|
* of a route's lower left corner, as well as two extension areas to the
|
|
|
|
|
* left and bottom.
|
|
|
|
|
*
|
|
|
|
|
* (to be done)---Both start and dest areas should not trim back the
|
|
|
|
|
* upper corners of tiles that are connected to other start/dest tiles,
|
|
|
|
|
* since that would leave unnecessary holes in the routable areas.
|
|
|
|
|
* Not doing this tends to cause troubles when the start/dest nodes are
|
|
|
|
|
* broken up into many tiles.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef lint
|
|
|
|
|
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzBlock.c,v 1.2 2010/10/22 15:02:15 tim Exp $";
|
|
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
#include "utils/magic.h"
|
|
|
|
|
#include "utils/geometry.h"
|
|
|
|
|
#include "utils/geofast.h"
|
|
|
|
|
#include "tiles/tile.h"
|
|
|
|
|
#include "utils/hash.h"
|
|
|
|
|
#include "database/database.h"
|
|
|
|
|
#include "utils/signals.h"
|
|
|
|
|
#include "textio/textio.h"
|
|
|
|
|
#include "windows/windows.h"
|
|
|
|
|
#include "dbwind/dbwind.h"
|
|
|
|
|
#include "utils/malloc.h"
|
|
|
|
|
#include "utils/list.h"
|
|
|
|
|
#include "debug/debug.h"
|
|
|
|
|
#include "textio/textio.h"
|
|
|
|
|
#include "utils/heap.h"
|
|
|
|
|
#include "mzrouter/mzrouter.h"
|
|
|
|
|
#include "mzrouter/mzInternal.h"
|
|
|
|
|
|
|
|
|
|
/* Forward declarations */
|
|
|
|
|
extern void mzPaintBlockType();
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzBuildMaskDataBlocks --
|
|
|
|
|
*
|
|
|
|
|
* Build blockage info from paint in buildArea.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* The design rules are used
|
2017-04-25 14:41:48 +02:00
|
|
|
* to build a map of blocked areas in blockage planes of RouteTypes.
|
|
|
|
|
* This map will consist of TT_SPACE tiles, where a zero-width
|
2020-05-23 23:13:14 +02:00
|
|
|
* path will yield a
|
2017-04-25 14:41:48 +02:00
|
|
|
* legal route when flushed out to wire width paint, and various
|
2020-05-23 23:13:14 +02:00
|
|
|
* types of block tiles. Multiple block types are needed to handle route
|
2017-04-25 14:41:48 +02:00
|
|
|
* termination at the destination node properly.
|
|
|
|
|
*
|
|
|
|
|
* TT_BLOCKED and TT_SAMENODE are generated from the mask data
|
|
|
|
|
* (SAMENODE areas are only blocked by the destination node itself).
|
|
|
|
|
*
|
|
|
|
|
* In addition to blockage planes for route layers, there are
|
2020-05-23 23:13:14 +02:00
|
|
|
* blockage planes for contacts, assumed to connect two planes.
|
|
|
|
|
* Both planes of mask information
|
2017-04-25 14:41:48 +02:00
|
|
|
* are effectively AND-ed together to form the blockage plane for
|
|
|
|
|
* that type of contact.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into Blockage planes in RouteTypes
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mzBuildMaskDataBlocks(buildArea)
|
|
|
|
|
Rect *buildArea; /* Area over which blockage planes will be built */
|
|
|
|
|
{
|
|
|
|
|
Rect searchArea;
|
|
|
|
|
int pNum;
|
|
|
|
|
int mzPaintSameNodeFunc(); /* Fwd declaration */
|
|
|
|
|
|
|
|
|
|
/* search area = build area + context */
|
|
|
|
|
searchArea.r_xbot = buildArea->r_xbot - mzContextRadius;
|
|
|
|
|
searchArea.r_ybot = buildArea->r_ybot - mzContextRadius;
|
|
|
|
|
searchArea.r_xtop = buildArea->r_xtop + mzContextRadius;
|
|
|
|
|
searchArea.r_ytop = buildArea->r_ytop + mzContextRadius;
|
|
|
|
|
|
|
|
|
|
/* Paint SAMENODE on all destination areas */
|
|
|
|
|
/* (all areas that were painted into mzDestAreasUse->cu_def) */
|
|
|
|
|
|
|
|
|
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
|
|
|
|
{
|
|
|
|
|
DBSrPaintArea((Tile *)NULL, mzDestAreasUse->cu_def->cd_planes[pNum],
|
|
|
|
|
&searchArea, &DBAllButSpaceAndDRCBits,
|
|
|
|
|
mzPaintSameNodeFunc, (ClientData)buildArea);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Build the blockage planes on all layers, ignore unexpanded subcells
|
|
|
|
|
* (unexpanded in reference window)
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
int mzBuildBlockFunc();
|
|
|
|
|
SearchContext scx;
|
|
|
|
|
|
|
|
|
|
scx.scx_area = searchArea;
|
|
|
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
|
|
|
scx.scx_use = mzRouteUse;
|
|
|
|
|
|
|
|
|
|
(void) DBTreeSrTiles(
|
2020-05-23 23:13:14 +02:00
|
|
|
&scx,
|
|
|
|
|
&DBAllButSpaceAndDRCBits,
|
2017-04-25 14:41:48 +02:00
|
|
|
mzCellExpansionMask,
|
2020-05-23 23:13:14 +02:00
|
|
|
mzBuildBlockFunc,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) buildArea);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/* Add blocks at unexpanded subcells on all blockage planes
|
2017-04-25 14:41:48 +02:00
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* NOTE: A 0 expansion mask is special cased since
|
|
|
|
|
* the mzrotuer interpets a 0 mask to mean all subcells are
|
2017-04-25 14:41:48 +02:00
|
|
|
* expanded,
|
|
|
|
|
* while DBTreeSrCells() takes a 0 mask to mean all subcells are
|
|
|
|
|
* unexpanded.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if(mzCellExpansionMask != 0)
|
|
|
|
|
{
|
|
|
|
|
int mzBlockSubcellsFunc();
|
|
|
|
|
SearchContext scx;
|
|
|
|
|
|
|
|
|
|
scx.scx_area = searchArea;
|
|
|
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
|
|
|
scx.scx_use = mzRouteUse;
|
|
|
|
|
|
|
|
|
|
DBTreeSrCells(
|
|
|
|
|
&scx,
|
|
|
|
|
mzCellExpansionMask,
|
|
|
|
|
mzBlockSubcellsFunc,
|
|
|
|
|
(ClientData) buildArea);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzBuildBlockFunc --
|
|
|
|
|
*
|
|
|
|
|
* Filter function called via DBTreeSrTiles on behalf of mzBuildBlock()
|
|
|
|
|
* above, for each solid tile in the area of interest. Paints TT_BLOCKED
|
2020-05-23 23:13:14 +02:00
|
|
|
* (TT_SAMENODE if the tile is marked) areas on each of the planes
|
2017-04-25 14:41:48 +02:00
|
|
|
* affected by this tile.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into Blockage Planes in RouteType structures.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzBuildBlockFunc(tile, cxp)
|
|
|
|
|
|
|
|
|
|
Tile *tile;
|
|
|
|
|
TreeContext *cxp;
|
|
|
|
|
{
|
|
|
|
|
SearchContext *scx = cxp->tc_scx;
|
|
|
|
|
Rect *buildArea = (Rect *) (cxp->tc_filter->tf_arg);
|
|
|
|
|
Rect r, rDest;
|
|
|
|
|
|
|
|
|
|
/* Transform to result coordinates */
|
|
|
|
|
TITORECT(tile, &r);
|
|
|
|
|
GEOCLIP(&r, &scx->scx_area);
|
|
|
|
|
GEOTRANSRECT(&scx->scx_trans, &r, &rDest);
|
|
|
|
|
|
|
|
|
|
mzPaintBlockType(&rDest, TiGetType(tile), buildArea, TT_BLOCKED);
|
|
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzBlockSubcellsFunc --
|
|
|
|
|
*
|
|
|
|
|
* Filter function called via DBTreeSrTiles on behalf of mzBuildBlock()
|
2020-05-23 23:13:14 +02:00
|
|
|
* above, for each unexpanded subcell in the area of interest,
|
2017-04-25 14:41:48 +02:00
|
|
|
* a "blocked" area (TT_BLOCKED) is painted on each blockage plane for
|
|
|
|
|
* the bounding box of the subcell, bloated by the maximum design rule
|
|
|
|
|
* spacing on that plane.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into Blockage Planes in RouteType structures.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzBlockSubcellsFunc(scx, cdarg)
|
|
|
|
|
SearchContext *scx;
|
|
|
|
|
ClientData cdarg;
|
|
|
|
|
{
|
|
|
|
|
Rect r, rDest;
|
|
|
|
|
Rect *buildArea = (Rect *) cdarg;
|
|
|
|
|
|
|
|
|
|
/* Transform bounding box to result coords */
|
|
|
|
|
r = scx->scx_use->cu_def->cd_bbox;
|
|
|
|
|
GEOTRANSRECT(&scx->scx_trans, &r, &rDest);
|
|
|
|
|
|
2024-10-21 10:13:23 +02:00
|
|
|
if(scx->scx_use->cu_client != MZ_EXPAND_DEST)
|
2017-04-25 14:41:48 +02:00
|
|
|
/* cell over part of dest node, paint normal blocks onto affected
|
|
|
|
|
* planes.
|
|
|
|
|
* (area is bloated by appropriate spacing on each affected plane)
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
mzPaintBlockType(&rDest, TT_SUBCELL, buildArea, TT_BLOCKED);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/* cell is over part of dest node, paint samenode blocks */
|
|
|
|
|
{
|
|
|
|
|
mzPaintBlockType(&rDest, TT_SUBCELL, buildArea, TT_SAMENODE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzPaintSameNodeFunc --
|
|
|
|
|
*
|
|
|
|
|
* Add TT_SAMENODE paint into the route layer block plane for each
|
|
|
|
|
* tile found in mzDestAreasUse->cu_def
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Always return 0 to keep the search going.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzPaintSameNodeFunc(Tile *t, Rect *buildArea)
|
|
|
|
|
{
|
|
|
|
|
Rect r;
|
|
|
|
|
TileType ttype;
|
|
|
|
|
|
|
|
|
|
ttype = TiGetType(t);
|
|
|
|
|
TiToRect(t, &r);
|
|
|
|
|
|
|
|
|
|
mzPaintBlockType(&r, ttype, buildArea, TT_SAMENODE);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzPaintBlockType --
|
|
|
|
|
*
|
|
|
|
|
* Add "blockType" paint appropriate to data tile of given location
|
|
|
|
|
* and type to blockage planes of all relevant routeTypes.
|
|
|
|
|
*
|
|
|
|
|
* The blockage tiles painted are bloated versions of the data tiles.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Modifies blockage planes in RouteType structures.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mzPaintBlockType(r, type, buildArea, blockType)
|
|
|
|
|
Rect *r;
|
|
|
|
|
TileType type;
|
|
|
|
|
Rect *buildArea;
|
|
|
|
|
TileType blockType;
|
|
|
|
|
{
|
|
|
|
|
RouteType *rT;
|
|
|
|
|
TileType locBlockType;
|
|
|
|
|
|
|
|
|
|
/* process routeTypes */
|
|
|
|
|
for (rT=mzActiveRTs; rT!=NULL; rT=rT->rt_nextActive)
|
|
|
|
|
{
|
|
|
|
|
Rect rblock;
|
|
|
|
|
|
|
|
|
|
/* Added by Tim 7/28/06 --- Ignore those planes that don't interact! */
|
|
|
|
|
|
|
|
|
|
if (!(DBTypePlaneMaskTbl[type] & DBTypePlaneMaskTbl[rT->rt_tileType]))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* if there is a constraint between RouteType and type, paint a block */
|
|
|
|
|
|
|
|
|
|
locBlockType = blockType;
|
|
|
|
|
|
|
|
|
|
if (rT->rt_bloatBot[type] >= 0)
|
|
|
|
|
{
|
|
|
|
|
int bot, top;
|
|
|
|
|
|
|
|
|
|
/* If we're painting TT_BLOCKED, make sure we're not painting */
|
|
|
|
|
/* on top of a start or dest area (has TT_SAMENODE) */
|
|
|
|
|
|
|
|
|
|
if (blockType != TT_SAMENODE)
|
|
|
|
|
{
|
|
|
|
|
RouteContact *rC;
|
2025-02-21 19:15:02 +01:00
|
|
|
Tile *tp = PlaneGetHint(rT->rt_hBlock);
|
2017-04-25 14:41:48 +02:00
|
|
|
GOTOPOINT(tp, &r->r_ll);
|
|
|
|
|
if (TiGetType(tp) == TT_SAMENODE)
|
|
|
|
|
{
|
|
|
|
|
/* This can fail to paint a proper blockage on a */
|
|
|
|
|
/* contact plane when the terminal is in one plane */
|
|
|
|
|
/* and the blocking route is on the other. So, if */
|
|
|
|
|
/* painting into a contact plane, check that the */
|
|
|
|
|
/* tile in the residue layer that is "type" is also */
|
|
|
|
|
/* covered in TT_SAMENODE, or this is a block. */
|
|
|
|
|
|
|
|
|
|
if (DBIsContact(rT->rt_tileType))
|
|
|
|
|
{
|
|
|
|
|
for (rC = mzRouteContacts; rC != NULL; rC = rC->rc_next)
|
|
|
|
|
{
|
|
|
|
|
if (rC->rc_routeType.rt_tileType == rT->rt_tileType)
|
|
|
|
|
{
|
|
|
|
|
Tile *tp2;
|
|
|
|
|
if (rC->rc_rLayer1->rl_routeType.rt_tileType == type)
|
|
|
|
|
{
|
2025-02-21 19:15:02 +01:00
|
|
|
tp2 = PlaneGetHint(rC->rc_rLayer1->
|
|
|
|
|
rl_routeType.rt_hBlock);
|
2017-04-25 14:41:48 +02:00
|
|
|
GOTOPOINT(tp2, &r->r_ll);
|
|
|
|
|
if (TiGetType(tp) == TT_SAMENODE) break;
|
|
|
|
|
}
|
|
|
|
|
else if (rC->rc_rLayer2->rl_routeType.rt_tileType
|
|
|
|
|
== type)
|
|
|
|
|
{
|
2025-02-21 19:15:02 +01:00
|
|
|
tp2 = PlaneGetHint(rC->rc_rLayer2->
|
|
|
|
|
rl_routeType.rt_hBlock);
|
2017-04-25 14:41:48 +02:00
|
|
|
GOTOPOINT(tp2, &r->r_ll);
|
|
|
|
|
if (TiGetType(tp) == TT_SAMENODE) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (rC != NULL) continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-05-23 23:13:14 +02:00
|
|
|
/* If the tile type is a contact of the same
|
2017-04-25 14:41:48 +02:00
|
|
|
* type as the route type, draw a block layer, not SAMENODE.
|
|
|
|
|
* This prevents the maze router from attempting to place
|
|
|
|
|
* a contact too close to an existing one, causing a DRC
|
|
|
|
|
* error.
|
|
|
|
|
*/
|
|
|
|
|
if ((DBIsContact(type)) && (rT->rt_tileType == type))
|
|
|
|
|
locBlockType = TT_BLOCKED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Compute blockage rectangle */
|
|
|
|
|
bot = rT->rt_bloatBot[type];
|
|
|
|
|
top = rT->rt_bloatTop[type];
|
|
|
|
|
|
|
|
|
|
if (locBlockType != TT_SAMENODE)
|
|
|
|
|
{
|
|
|
|
|
rblock.r_xbot = r->r_xbot - bot;
|
|
|
|
|
rblock.r_ybot = r->r_ybot - bot;
|
|
|
|
|
|
|
|
|
|
rblock.r_xtop = r->r_xtop + top;
|
|
|
|
|
rblock.r_ytop = r->r_ytop + top;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int wless = bot - top + 1;
|
|
|
|
|
|
|
|
|
|
/* SAMENODE: valid route can start in one of */
|
|
|
|
|
/* two overlapping rectangles as computed */
|
|
|
|
|
/* below. The left and bottom sides are */
|
|
|
|
|
/* extended by the route width, but the */
|
|
|
|
|
/* corners are prohibited. */
|
|
|
|
|
|
|
|
|
|
rblock.r_xbot = r->r_xbot - wless;
|
|
|
|
|
rblock.r_ybot = r->r_ybot;
|
|
|
|
|
|
|
|
|
|
rblock.r_xtop = r->r_xtop;
|
|
|
|
|
rblock.r_ytop = r->r_ytop - wless;
|
|
|
|
|
|
|
|
|
|
GEOCLIP(&rblock, buildArea);
|
|
|
|
|
if (!GEO_RECTNULL(&rblock))
|
|
|
|
|
{
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlane(rT->rt_hBlock, &rblock,
|
2017-04-25 14:41:48 +02:00
|
|
|
mzBlockPaintTbl[blockType],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlaneVert(rT->rt_vBlock, &rblock,
|
2017-04-25 14:41:48 +02:00
|
|
|
mzBlockPaintTbl[blockType],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rblock.r_xbot = r->r_xbot;
|
|
|
|
|
rblock.r_ybot = r->r_ybot - wless;
|
|
|
|
|
|
|
|
|
|
rblock.r_xtop = r->r_xtop - wless;
|
|
|
|
|
rblock.r_ytop = r->r_ytop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* clip to build area */
|
|
|
|
|
|
|
|
|
|
GEOCLIP(&rblock, buildArea);
|
|
|
|
|
if (!GEO_RECTNULL(&rblock))
|
|
|
|
|
{
|
|
|
|
|
/* and paint it */
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlane(rT->rt_hBlock, &rblock,
|
2017-04-25 14:41:48 +02:00
|
|
|
mzBlockPaintTbl[locBlockType],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlaneVert(rT->rt_vBlock, &rblock,
|
2017-04-25 14:41:48 +02:00
|
|
|
mzBlockPaintTbl[locBlockType],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* mzBuildFenceBlocks --
|
2017-04-25 14:41:48 +02:00
|
|
|
*
|
|
|
|
|
* Blocks regions of fence parity opposite of the destination-point.
|
|
|
|
|
* (Fence boundaries can not be crossed).
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Blockage Planes modified.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mzBuildFenceBlocks(buildArea)
|
|
|
|
|
Rect *buildArea; /* Area over which planes modified */
|
|
|
|
|
{
|
|
|
|
|
int mzBuildFenceBlocksFunc();
|
|
|
|
|
Rect searchArea;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* search area = build area + context */
|
|
|
|
|
searchArea.r_xbot = buildArea->r_xbot - mzContextRadius;
|
|
|
|
|
searchArea.r_ybot = buildArea->r_ybot - mzContextRadius;
|
|
|
|
|
searchArea.r_xtop = buildArea->r_xtop + mzContextRadius;
|
|
|
|
|
searchArea.r_ytop = buildArea->r_ytop + mzContextRadius;
|
|
|
|
|
|
|
|
|
|
/* If route inside fence, gen blocks at space tiles.
|
|
|
|
|
* if route outside fence, gen blocks at fence tiles.
|
|
|
|
|
*/
|
|
|
|
|
if(mzInsideFence)
|
|
|
|
|
{
|
|
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
2020-05-23 23:13:14 +02:00
|
|
|
mzHFencePlane,
|
|
|
|
|
&searchArea,
|
2017-04-25 14:41:48 +02:00
|
|
|
&DBSpaceBits,
|
2020-05-23 23:13:14 +02:00
|
|
|
mzBuildFenceBlocksFunc,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) buildArea);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
2020-05-23 23:13:14 +02:00
|
|
|
mzHFencePlane,
|
|
|
|
|
&searchArea,
|
2017-04-25 14:41:48 +02:00
|
|
|
&DBAllButSpaceBits,
|
2020-05-23 23:13:14 +02:00
|
|
|
mzBuildFenceBlocksFunc,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) buildArea);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzBuildFenceBlocksFunc --
|
|
|
|
|
*
|
|
|
|
|
* Called by DBSrPaintArea for tile in given area on fence plane where routing
|
|
|
|
|
* is prohibited. These areas are blocked,
|
|
|
|
|
* adjusting for wire width on each blockage plane.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into blockage planes.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzBuildFenceBlocksFunc(tile, buildArea)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
Rect *buildArea; /* clip to this area before painting */
|
|
|
|
|
{
|
|
|
|
|
RouteType *rT;
|
|
|
|
|
int d;
|
2020-05-23 23:13:14 +02:00
|
|
|
Rect r, rAdjusted;
|
2017-04-25 14:41:48 +02:00
|
|
|
TileType tt = TiGetType(tile);
|
|
|
|
|
|
|
|
|
|
/* Get boundary of tile */
|
|
|
|
|
TITORECT(tile, &r);
|
|
|
|
|
|
|
|
|
|
for (rT=mzActiveRTs; rT!=NULL; rT=rT->rt_nextActive)
|
|
|
|
|
{
|
|
|
|
|
/* Added by Tim 7/28/06 --- Ignore those planes that don't interact! */
|
|
|
|
|
/* Revised 8/22/06---Fence tiles are supposed to block all layers! */
|
|
|
|
|
|
|
|
|
|
// if (!(DBTypePlaneMaskTbl[tt] & DBTypePlaneMaskTbl[rT->rt_tileType]))
|
|
|
|
|
// continue;
|
|
|
|
|
|
|
|
|
|
/* adjust to compensate for wire width */
|
|
|
|
|
d = rT->rt_effWidth - 1;
|
|
|
|
|
rAdjusted.r_xbot = r.r_xbot - d;
|
|
|
|
|
rAdjusted.r_xtop = r.r_xtop;
|
|
|
|
|
rAdjusted.r_ybot = r.r_ybot - d;
|
|
|
|
|
rAdjusted.r_ytop = r.r_ytop;
|
|
|
|
|
|
|
|
|
|
/* clip to area being generated. */
|
|
|
|
|
GEOCLIP(&rAdjusted, buildArea);
|
|
|
|
|
|
|
|
|
|
/* Paint into blockage planes */
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlane(rT->rt_hBlock,
|
|
|
|
|
&rAdjusted,
|
|
|
|
|
mzBlockPaintTbl[TT_BLOCKED],
|
2017-04-25 14:41:48 +02:00
|
|
|
(PaintUndoInfo *) NULL);
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlaneVert(rT->rt_vBlock,
|
|
|
|
|
&rAdjusted,
|
|
|
|
|
mzBlockPaintTbl[TT_BLOCKED],
|
2017-04-25 14:41:48 +02:00
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* return 0 - to continue search */
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzExtendBlockBoundsR --
|
|
|
|
|
*
|
|
|
|
|
* Generate blockage information around given rect.
|
|
|
|
|
* Info required for radius of twice the bounds-increment around the rect.
|
|
|
|
|
* The gen area is broken down into areas which have not already been gened.
|
|
|
|
|
* Blockage info is generated for these subregions.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into Blockage planes in RouteTypes
|
|
|
|
|
* Updates bounds plane.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mzExtendBlockBoundsR(rect)
|
|
|
|
|
Rect *rect;
|
|
|
|
|
{
|
|
|
|
|
Rect area;
|
|
|
|
|
TileTypeBitMask genMask;
|
|
|
|
|
/* Generate twice the required bounds increment, so we don't have
|
|
|
|
|
* to regenerate as soon as we move from the center of the newly
|
2020-05-23 23:13:14 +02:00
|
|
|
* generated region.
|
2017-04-25 14:41:48 +02:00
|
|
|
*/
|
|
|
|
|
int genBoundsIncrement = mzBoundsIncrement * 2;
|
|
|
|
|
int mzExtendBlockFunc();
|
|
|
|
|
|
|
|
|
|
/* keep stats */
|
|
|
|
|
mzBlockGenCalls++;
|
|
|
|
|
|
|
|
|
|
/* mark area about rect in which blockage plane required to be present */
|
|
|
|
|
area.r_xbot = rect->r_xbot - genBoundsIncrement;
|
|
|
|
|
area.r_ybot = rect->r_ybot - genBoundsIncrement;
|
|
|
|
|
area.r_xtop = rect->r_xtop + genBoundsIncrement;
|
|
|
|
|
area.r_ytop = rect->r_ytop + genBoundsIncrement;
|
|
|
|
|
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlane(mzHBoundsPlane,
|
2017-04-25 14:41:48 +02:00
|
|
|
&area,
|
|
|
|
|
mzBoundsPaintTbl[TT_GENBLOCK],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
|
|
|
|
|
/* Generate blockage planes under each GENBLOCK tile = regions in
|
2020-05-23 23:13:14 +02:00
|
|
|
* new area where blockage planes not previously generated
|
2017-04-25 14:41:48 +02:00
|
|
|
*/
|
|
|
|
|
TTMaskZero(&genMask);
|
|
|
|
|
TTMaskSetType(&genMask,TT_GENBLOCK);
|
2020-05-23 23:13:14 +02:00
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
2017-04-25 14:41:48 +02:00
|
|
|
mzHBoundsPlane,
|
|
|
|
|
&area,
|
|
|
|
|
&genMask,
|
|
|
|
|
mzExtendBlockFunc,
|
|
|
|
|
(ClientData) NULL);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/* Paint area INBOUNDS in both bounds planes
|
|
|
|
|
*(blockage planes now generated here)
|
2017-04-25 14:41:48 +02:00
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlane(mzHBoundsPlane,
|
2017-04-25 14:41:48 +02:00
|
|
|
&area,
|
|
|
|
|
mzBoundsPaintTbl[TT_INBOUNDS],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlaneVert(mzVBoundsPlane,
|
2017-04-25 14:41:48 +02:00
|
|
|
&area,
|
|
|
|
|
mzBoundsPaintTbl[TT_INBOUNDS],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define RECT_AREA(r) \
|
|
|
|
|
((double)(r.r_xtop - r.r_xbot)*(double)(r.r_ytop - r.r_ybot))
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzExtendBlockFunc --
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* Called by DBSrPaintArea for rectangles where blockage info must be
|
2017-04-25 14:41:48 +02:00
|
|
|
* generated.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Return 0 always (to continue the search)
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into Blockage planes in RouteTypes
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzExtendBlockFunc(tile, cdarg)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
ClientData cdarg;
|
|
|
|
|
{
|
|
|
|
|
Rect area;
|
|
|
|
|
|
|
|
|
|
/* Get location of tile */
|
|
|
|
|
TITORECT(tile, &area);
|
|
|
|
|
|
|
|
|
|
/* Don't actually generate blocks outside of user supplied
|
|
|
|
|
* route area hint.
|
|
|
|
|
*/
|
|
|
|
|
if(mzBoundsHint)
|
|
|
|
|
{
|
|
|
|
|
GEOCLIP(&area,mzBoundsHint);
|
|
|
|
|
if((area.r_xbot > area.r_xtop) || (area.r_ybot > area.r_ytop))
|
|
|
|
|
/*no overlap just return */
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Grow clip area by 2 units to take care of boundary conditions. */
|
|
|
|
|
area.r_xbot -= 2;
|
|
|
|
|
area.r_xtop += 2;
|
|
|
|
|
area.r_ybot -= 2;
|
|
|
|
|
area.r_ytop += 2;
|
|
|
|
|
|
|
|
|
|
mzBuildMaskDataBlocks(&area);
|
|
|
|
|
mzBuildFenceBlocks(&area);
|
|
|
|
|
|
|
|
|
|
/* keep stats */
|
|
|
|
|
mzBlockGenArea += RECT_AREA(area);
|
|
|
|
|
|
|
|
|
|
/* return 0 to continue search */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzExtendBlockBounds --
|
|
|
|
|
*
|
|
|
|
|
* Generate blockage information around given point.
|
|
|
|
|
* Info required for radius of twice the bounds-increment around the point.
|
|
|
|
|
* The gen area is broken down into areas which have not already been gened.
|
|
|
|
|
* Blockage info is generated for these subregions.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into Blockage planes in RouteTypes
|
|
|
|
|
* Updates bounds plane.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mzExtendBlockBounds(point)
|
|
|
|
|
Point *point;
|
|
|
|
|
{
|
|
|
|
|
Rect rect;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
rect.r_ll = *point;
|
|
|
|
|
rect.r_ur = *point;
|
|
|
|
|
|
|
|
|
|
mzExtendBlockBoundsR(&rect);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
2017-04-25 14:41:48 +02:00
|
|
|
* This struc is used to store generated walks, since it is necessary
|
|
|
|
|
* to defer painting walks until all are generated.
|
|
|
|
|
*/
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
RouteType * w_rT;
|
|
|
|
|
Rect w_rect;
|
|
|
|
|
TileType w_type;
|
|
|
|
|
} Walk;
|
|
|
|
|
|
|
|
|
|
/* global used to store walks prior to painting them */
|
|
|
|
|
List *mzWalkList;
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzBuildDestAreaBlocks --
|
|
|
|
|
*
|
|
|
|
|
* Generate blockage information around all dest areas, and do special dest
|
|
|
|
|
* area processing (generation of dest area blocks and walks). In addition
|
|
|
|
|
* dest area alignment coords are added to the alignment structures.
|
|
|
|
|
*
|
|
|
|
|
* TT_DEST_AREA and TT_*_WALK regions are generated from the special dest area
|
|
|
|
|
* cell. Dest areas are regions to connect to and walks are regions blocked
|
2020-05-23 23:13:14 +02:00
|
|
|
* only by dest nodes and directly adjacent to a dest area. Walks are
|
2017-04-25 14:41:48 +02:00
|
|
|
* routed through by special termination code.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Modifies blockage planes.
|
|
|
|
|
* Modifies alignment strucs.
|
|
|
|
|
* Updates bounds plane.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mzBuildDestAreaBlocks()
|
|
|
|
|
{
|
|
|
|
|
int mzDestAreaFunc();
|
|
|
|
|
int mzDestWalksFunc();
|
|
|
|
|
int mzLRCWalksFunc();
|
|
|
|
|
int mzUDCWalksFunc();
|
|
|
|
|
SearchContext scx;
|
|
|
|
|
|
|
|
|
|
/* initialize global walk list */
|
|
|
|
|
mzWalkList = NULL;
|
|
|
|
|
|
|
|
|
|
/* Compute bounding box for dest areas cell */
|
|
|
|
|
DBReComputeBbox(mzDestAreasUse->cu_def);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/* Process dest areas in dest area cell one by one.
|
2017-04-25 14:41:48 +02:00
|
|
|
* - generates normal blockage info.
|
|
|
|
|
* - paints dest area into appropriate blockage planes.
|
|
|
|
|
* - generates alignments.
|
|
|
|
|
* - generates list of walks.
|
2020-05-23 23:13:14 +02:00
|
|
|
*
|
|
|
|
|
* Walks are not actually painted yet because existing
|
2017-04-25 14:41:48 +02:00
|
|
|
* walks can interfere with the generation of new ones.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
scx.scx_area = mzBoundingRect;
|
|
|
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
|
|
|
scx.scx_use = mzDestAreasUse;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* clip area to bounding box to avoid overflow during transforms */
|
|
|
|
|
GEOCLIP(&(scx.scx_area), &(mzDestAreasUse->cu_def->cd_bbox));
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
(void) DBTreeSrTiles( &scx, &DBAllButSpaceAndDRCBits,
|
2017-04-25 14:41:48 +02:00
|
|
|
0, mzDestAreaFunc, (ClientData) NULL);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
(void) DBTreeSrTiles( &scx, &DBAllButSpaceAndDRCBits,
|
2017-04-25 14:41:48 +02:00
|
|
|
0, mzDestWalksFunc, (ClientData) NULL);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits,
|
2017-04-25 14:41:48 +02:00
|
|
|
0, mzUDCWalksFunc, (ClientData) NULL);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits,
|
2017-04-25 14:41:48 +02:00
|
|
|
0, mzLRCWalksFunc, (ClientData) NULL);
|
|
|
|
|
|
|
|
|
|
/* Paint walks into blockage planes (and dealloc walk list) */
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
List *l;
|
|
|
|
|
|
|
|
|
|
for(l = mzWalkList; l!= NULL; l=LIST_TAIL(l))
|
|
|
|
|
{
|
|
|
|
|
Walk *walk = (Walk *) LIST_FIRST(l);
|
|
|
|
|
|
|
|
|
|
/* Diagnostic---something is wrong here! */
|
|
|
|
|
if (walk->w_type > TT_MAXROUTETYPES)
|
|
|
|
|
{
|
|
|
|
|
TxError("Fatal: Bad destination walk!\n");
|
|
|
|
|
continue; /* Try to go on anyway */
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
|
|
|
|
DBPaintPlane(walk->w_rT->rt_hBlock,
|
2017-04-25 14:41:48 +02:00
|
|
|
&(walk->w_rect),
|
|
|
|
|
mzBlockPaintTbl[walk->w_type],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
DBPaintPlaneVert(walk->w_rT->rt_vBlock,
|
2017-04-25 14:41:48 +02:00
|
|
|
&(walk->w_rect),
|
|
|
|
|
mzBlockPaintTbl[walk->w_type],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ListDeallocC(mzWalkList);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzDestAreaFunc --
|
|
|
|
|
*
|
|
|
|
|
* Pregenerate blockage info around the destination area
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 on success. In case we are stymied by an incomplete
|
|
|
|
|
* techfile entry for the maze router, return with 1 to stop the
|
|
|
|
|
* whole process.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Generates blockage info.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzDestAreaFunc(tile, cxp)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
TreeContext *cxp;
|
|
|
|
|
{
|
|
|
|
|
SearchContext *scx = cxp->tc_scx;
|
|
|
|
|
TileType type = TiGetType(tile);
|
|
|
|
|
Rect r, rect;
|
|
|
|
|
RouteType *rT;
|
|
|
|
|
|
|
|
|
|
/* Transform to result coordinates */
|
|
|
|
|
TITORECT(tile, &r);
|
|
|
|
|
GEOTRANSRECT(&scx->scx_trans, &r, &rect);
|
|
|
|
|
|
|
|
|
|
mzExtendBlockBoundsR(&rect);
|
|
|
|
|
|
|
|
|
|
/* find route type for this dest area */
|
|
|
|
|
|
|
|
|
|
rT = mzActiveRTs;
|
|
|
|
|
while ((rT != NULL) && (rT->rt_tileType != type))
|
|
|
|
|
rT = rT->rt_nextActive;
|
|
|
|
|
|
|
|
|
|
/* This can happen if the techfile does not completely define */
|
|
|
|
|
/* the gaRoute info. . . */
|
|
|
|
|
if (rT == NULL)
|
|
|
|
|
return 1;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Draw the routable destination area (see comments at top of file). */
|
|
|
|
|
|
|
|
|
|
r.r_xtop = rect.r_xtop - rT->rt_width;
|
|
|
|
|
r.r_ytop = rect.r_ytop;
|
|
|
|
|
r.r_xbot = rect.r_xbot;
|
|
|
|
|
r.r_ybot = rect.r_ybot - rT->rt_width;
|
|
|
|
|
|
|
|
|
|
/* paint dest area into blockage planes of appropriate route type */
|
|
|
|
|
DBPaintPlane(rT->rt_hBlock, &r, mzBlockPaintTbl[TT_DEST_AREA],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
|
|
|
|
|
DBPaintPlaneVert(rT->rt_vBlock, &r, mzBlockPaintTbl[TT_DEST_AREA],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
|
|
|
|
|
r.r_xtop = rect.r_xtop;
|
|
|
|
|
r.r_ytop = rect.r_ytop - rT->rt_width;
|
|
|
|
|
r.r_xbot = rect.r_xbot - rT->rt_width;
|
|
|
|
|
r.r_ybot = rect.r_ybot;
|
|
|
|
|
|
|
|
|
|
/* paint dest area into blockage planes of appropriate route type */
|
|
|
|
|
DBPaintPlane(rT->rt_hBlock, &r, mzBlockPaintTbl[TT_DEST_AREA],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
|
|
|
|
|
DBPaintPlaneVert(rT->rt_vBlock, &r, mzBlockPaintTbl[TT_DEST_AREA],
|
|
|
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
|
|
|
|
|
|
/* continue with next dest area */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzDestWalksFunc --
|
|
|
|
|
*
|
|
|
|
|
* Generate walks around each destination area tile, showing the router
|
|
|
|
|
* the direct "walk" into the destination area from points around the
|
|
|
|
|
* perimeter. This prevents the routing algorithm from having to blindly
|
|
|
|
|
* find the exact destination area; it only has to get close enough to
|
|
|
|
|
* be told how to paint a path directly to the destination node.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 on success. In case we are stymied by an incomplete
|
|
|
|
|
* techfile entry for the maze router, return with 1 to stop the
|
|
|
|
|
* whole process.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Generates walk tiles in the blockage planes
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzDestWalksFunc(tile, cxp)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
TreeContext *cxp;
|
|
|
|
|
{
|
|
|
|
|
SearchContext *scx = cxp->tc_scx;
|
|
|
|
|
TileType type = TiGetType(tile);
|
|
|
|
|
Rect r, rect;
|
|
|
|
|
RouteType *rT;
|
|
|
|
|
int mzHWalksFunc();
|
|
|
|
|
int mzVWalksFunc();
|
|
|
|
|
int mzUDCWalksFunc();
|
|
|
|
|
int mzLRCWalksFunc();
|
|
|
|
|
TileTypeBitMask destAreaMask;
|
|
|
|
|
|
|
|
|
|
/* Transform to result coordinates */
|
|
|
|
|
TITORECT(tile, &r);
|
|
|
|
|
GEOTRANSRECT(&scx->scx_trans, &r, &rect);
|
|
|
|
|
|
|
|
|
|
/* find route type for this dest area */
|
|
|
|
|
|
|
|
|
|
rT = mzActiveRTs;
|
|
|
|
|
while ((rT != NULL) && (rT->rt_tileType != type))
|
|
|
|
|
rT = rT->rt_nextActive;
|
|
|
|
|
|
|
|
|
|
/* This can happen if the techfile does not completely define */
|
|
|
|
|
/* the gaRoute info. . . */
|
|
|
|
|
if (rT == NULL)
|
|
|
|
|
return 1;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Generate alignments and walks for dest areas.
|
|
|
|
|
*
|
|
|
|
|
* Since the above dest area may be partially blocked, the blockage
|
|
|
|
|
* planes are searched for DEST_AREA tiles underneath
|
|
|
|
|
* the dest area painted above to build lists of dest tiles.
|
|
|
|
|
*
|
|
|
|
|
* walks are accumulated into a list for painting after ALL walks
|
|
|
|
|
* have been calculated.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
TTMaskSetOnlyType(&destAreaMask, TT_DEST_AREA);
|
|
|
|
|
|
|
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
2020-05-23 23:13:14 +02:00
|
|
|
rT->rt_hBlock, &rect,
|
|
|
|
|
&destAreaMask, mzHWalksFunc,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) rT);
|
|
|
|
|
|
|
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
2020-05-23 23:13:14 +02:00
|
|
|
rT->rt_vBlock, &rect,
|
|
|
|
|
&destAreaMask, mzVWalksFunc,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) rT);
|
|
|
|
|
|
|
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
2020-05-23 23:13:14 +02:00
|
|
|
rT->rt_hBlock, &rect,
|
|
|
|
|
&destAreaMask, mzLRCWalksFunc,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) rT);
|
|
|
|
|
|
|
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
2020-05-23 23:13:14 +02:00
|
|
|
rT->rt_vBlock, &rect,
|
|
|
|
|
&destAreaMask, mzUDCWalksFunc,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) rT);
|
|
|
|
|
|
|
|
|
|
/* continue with next dest area */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzHWalksFunc --
|
|
|
|
|
*
|
|
|
|
|
* Generate walks to top and bottom, and alignment y-coords for TT_DESTAREA
|
|
|
|
|
* (Walks are added to list for painting after search completes.)
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Adds to walks list and alignment structure.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzHWalksFunc(tile, cdarg)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
ClientData cdarg;
|
|
|
|
|
{
|
|
|
|
|
RouteType *rT = (RouteType *) cdarg;
|
|
|
|
|
|
|
|
|
|
/* Add dest area coordinates to dest alignment structure */
|
|
|
|
|
{
|
|
|
|
|
mzNLInsert(&mzXAlignNL, LEFT(tile));
|
|
|
|
|
mzNLInsert(&mzXAlignNL, RIGHT(tile));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* compute LEFT_WALK(s) */
|
|
|
|
|
{
|
|
|
|
|
Walk *walk;
|
|
|
|
|
Tile *tLeft = BL(tile);
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Build walks for blocks to left of tile */
|
|
|
|
|
while(BOTTOM(tLeft)<TOP(tile))
|
|
|
|
|
{
|
|
|
|
|
if(TiGetType(tLeft)==TT_SAMENODE)
|
|
|
|
|
{
|
|
|
|
|
walk = (Walk *) mallocMagic((unsigned) (sizeof(Walk)));
|
2020-05-23 23:13:14 +02:00
|
|
|
walk->w_rT = rT;
|
2017-04-25 14:41:48 +02:00
|
|
|
walk->w_type = TT_LEFT_WALK;
|
|
|
|
|
walk->w_rect.r_ybot = MAX(BOTTOM(tile),BOTTOM(tLeft));
|
|
|
|
|
walk->w_rect.r_ytop = MIN(TOP(tile),TOP(tLeft));
|
|
|
|
|
walk->w_rect.r_xtop = RIGHT(tLeft);
|
|
|
|
|
walk->w_rect.r_xbot = MAX(LEFT(tLeft),
|
|
|
|
|
RIGHT(tLeft)-mzMaxWalkLength);
|
|
|
|
|
LIST_ADD(walk, mzWalkList);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* move to next tile up */
|
|
|
|
|
tLeft = RT(tLeft);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* compute RIGHT_WALK */
|
|
|
|
|
{
|
|
|
|
|
Walk *walk;
|
|
|
|
|
Tile *tRight = TR(tile);
|
|
|
|
|
|
|
|
|
|
/* Build walks for blocks to right of tile */
|
|
|
|
|
while(TOP(tRight)>BOTTOM(tile))
|
|
|
|
|
{
|
|
|
|
|
if(TiGetType(tRight)==TT_SAMENODE)
|
|
|
|
|
{
|
|
|
|
|
walk = (Walk *) mallocMagic((unsigned) (sizeof(Walk)));
|
2020-05-23 23:13:14 +02:00
|
|
|
walk->w_rT = rT;
|
2017-04-25 14:41:48 +02:00
|
|
|
walk->w_type = TT_RIGHT_WALK;
|
|
|
|
|
walk->w_rect.r_ybot = MAX(BOTTOM(tile),BOTTOM(tRight));
|
|
|
|
|
walk->w_rect.r_ytop = MIN(TOP(tile),TOP(tRight));
|
|
|
|
|
walk->w_rect.r_xbot = LEFT(tRight);
|
2020-05-23 23:13:14 +02:00
|
|
|
walk->w_rect.r_xtop = MIN(RIGHT(tRight),
|
2017-04-25 14:41:48 +02:00
|
|
|
LEFT(tRight)+mzMaxWalkLength);
|
|
|
|
|
LIST_ADD(walk, mzWalkList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* move to next tile down */
|
|
|
|
|
tRight = LB(tRight);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* return 0 - to continue search */
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzVWalksFunc --
|
|
|
|
|
*
|
|
|
|
|
* Generate walks to top and bottom, and alignment y-coords for TT_DESTAREA
|
|
|
|
|
* (Walks are added to list for painting after search completes.)
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Adds to walks list and alignment structure.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzVWalksFunc(tile, cdarg)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
ClientData cdarg;
|
|
|
|
|
{
|
|
|
|
|
RouteType *rT = (RouteType *) cdarg;
|
|
|
|
|
|
|
|
|
|
/* Add dest area coordinates to dest alignment structure */
|
|
|
|
|
{
|
|
|
|
|
mzNLInsert(&mzYAlignNL, BOTTOM(tile));
|
|
|
|
|
mzNLInsert(&mzYAlignNL, TOP(tile));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* compute BOTTOM_WALK */
|
|
|
|
|
{
|
|
|
|
|
Walk *walk;
|
|
|
|
|
Tile *tBelow = LB(tile);
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Build walks for blocks to below tile */
|
|
|
|
|
while(LEFT(tBelow)<RIGHT(tile))
|
|
|
|
|
{
|
|
|
|
|
if(TiGetType(tBelow)==TT_SAMENODE)
|
|
|
|
|
{
|
|
|
|
|
walk = (Walk *) mallocMagic((unsigned) (sizeof(Walk)));
|
|
|
|
|
walk->w_rT = rT;
|
|
|
|
|
walk->w_type = TT_BOTTOM_WALK;
|
|
|
|
|
walk->w_rect.r_xbot = MAX(LEFT(tile),LEFT(tBelow));
|
|
|
|
|
walk->w_rect.r_xtop = MIN(RIGHT(tile),RIGHT(tBelow));
|
|
|
|
|
walk->w_rect.r_ytop = TOP(tBelow);
|
|
|
|
|
walk->w_rect.r_ybot = MAX(BOTTOM(tBelow),
|
|
|
|
|
TOP(tBelow)-mzMaxWalkLength);
|
|
|
|
|
LIST_ADD(walk, mzWalkList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* move to next tile to left */
|
|
|
|
|
tBelow = TR(tBelow);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* compute TOP_WALK */
|
|
|
|
|
{
|
|
|
|
|
Walk *walk;
|
|
|
|
|
Tile *tAbove = RT(tile);
|
2020-05-23 23:13:14 +02:00
|
|
|
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Build walks for blocks above tile */
|
|
|
|
|
while(RIGHT(tAbove)>LEFT(tile))
|
|
|
|
|
{
|
|
|
|
|
if(TiGetType(tAbove)==TT_SAMENODE)
|
|
|
|
|
{
|
|
|
|
|
walk = (Walk *) mallocMagic((unsigned) (sizeof(Walk)));
|
|
|
|
|
walk->w_rT = rT;
|
|
|
|
|
walk->w_type = TT_TOP_WALK;
|
|
|
|
|
walk->w_rect.r_xbot = MAX(LEFT(tile),LEFT(tAbove));;
|
|
|
|
|
walk->w_rect.r_xtop = MIN(RIGHT(tile),RIGHT(tAbove));
|
|
|
|
|
walk->w_rect.r_ybot = BOTTOM(tAbove);
|
2020-05-23 23:13:14 +02:00
|
|
|
walk->w_rect.r_ytop = MIN(TOP(tAbove),
|
2017-04-25 14:41:48 +02:00
|
|
|
BOTTOM(tAbove)+mzMaxWalkLength);
|
|
|
|
|
LIST_ADD(walk, mzWalkList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* move to next tile to right */
|
|
|
|
|
tAbove = BL(tAbove);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* return 0 - to continue search */
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
2017-04-25 14:41:48 +02:00
|
|
|
* Structure to pass data between mzLRCWalksFunc, mzUDCWalksFunc, and mzCWalksFunc2
|
|
|
|
|
*/
|
|
|
|
|
typedef struct walkContactFuncData
|
|
|
|
|
{
|
|
|
|
|
Rect *wd_bounds; /* dest area bounds */
|
|
|
|
|
RouteLayer *wd_rL; /* Route layer of walk_contact */
|
|
|
|
|
int wd_walk; /* TT_ABOVE_*_WALK or TT_BELOW_*_WALK */
|
|
|
|
|
} WalkContactFuncData;
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzLRCWalksFunc --
|
|
|
|
|
*
|
|
|
|
|
* Search dest area for regions where contacts are ok, and paint
|
|
|
|
|
* CONTACT_WALK(s) there in adjacent layers.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into adjacent blocakge planes.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzLRCWalksFunc(tile, cdarg)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
ClientData cdarg;
|
|
|
|
|
{
|
|
|
|
|
RouteType *rT = (RouteType *) cdarg; /* RouteType of this dest area */
|
2020-05-23 23:13:14 +02:00
|
|
|
RouteContact *rC;
|
2017-04-25 14:41:48 +02:00
|
|
|
Rect rect;
|
|
|
|
|
int walkType;
|
|
|
|
|
|
|
|
|
|
/* set rect to boundary of this dest area */
|
|
|
|
|
TITORECT(tile, &rect);
|
|
|
|
|
|
|
|
|
|
/* process contact types that can connect to this dest area */
|
|
|
|
|
for (rC = mzRouteContacts; rC != NULL; rC = rC->rc_next)
|
|
|
|
|
{
|
2020-05-23 23:13:14 +02:00
|
|
|
RouteLayer *rLOther = NULL;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* skip inactive contact types */
|
|
|
|
|
if (!(rC->rc_routeType.rt_active)) continue;
|
|
|
|
|
|
|
|
|
|
/* Find layer connecting to dest area FROM */
|
|
|
|
|
if (&(rC->rc_rLayer1->rl_routeType) == rT)
|
|
|
|
|
{
|
|
|
|
|
rLOther = rC->rc_rLayer2;
|
|
|
|
|
walkType = TT_ABOVE_LR_WALK;
|
|
|
|
|
}
|
|
|
|
|
else if (&(rC->rc_rLayer2->rl_routeType) == rT)
|
|
|
|
|
{
|
|
|
|
|
rLOther = rC->rc_rLayer1;
|
|
|
|
|
walkType = TT_BELOW_LR_WALK;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/* If current contact type (RC) permits connection to dest area,
|
2017-04-25 14:41:48 +02:00
|
|
|
* insert CONTACT_WALK(s) into blockage planes for other layer.
|
|
|
|
|
*/
|
|
|
|
|
if (rLOther)
|
|
|
|
|
{
|
|
|
|
|
/* process contact-OK tiles in blockage plane for this contact */
|
|
|
|
|
int mzCWalksFunc2();
|
|
|
|
|
WalkContactFuncData wD;
|
|
|
|
|
TileTypeBitMask contactOKMask;
|
|
|
|
|
|
|
|
|
|
TTMaskSetOnlyType(&contactOKMask, TT_SPACE);
|
|
|
|
|
TTMaskSetType(&contactOKMask, TT_SAMENODE);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
wD.wd_bounds = ▭
|
2017-04-25 14:41:48 +02:00
|
|
|
wD.wd_rL = rLOther;
|
|
|
|
|
wD.wd_walk = walkType;
|
|
|
|
|
|
|
|
|
|
/* search for OK places for contact in the horizontal plane */
|
|
|
|
|
/* and paint them. */
|
|
|
|
|
|
|
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
|
|
|
|
rC->rc_routeType.rt_hBlock,
|
2020-05-23 23:13:14 +02:00
|
|
|
&rect,
|
2017-04-25 14:41:48 +02:00
|
|
|
&contactOKMask,
|
2020-05-23 23:13:14 +02:00
|
|
|
mzCWalksFunc2,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) &wD);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* return 0 - to continue search */
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzUDCWalksFunc --
|
|
|
|
|
*
|
|
|
|
|
* Search dest area for regions where contacts are ok, and paint
|
|
|
|
|
* CONTACT_WALK(s) there in adjacent layers.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into adjacent blocakge planes.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzUDCWalksFunc(tile, cdarg)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
ClientData cdarg;
|
|
|
|
|
{
|
|
|
|
|
RouteType *rT = (RouteType *) cdarg; /* RouteType of this dest area */
|
2020-05-23 23:13:14 +02:00
|
|
|
RouteContact *rC;
|
2017-04-25 14:41:48 +02:00
|
|
|
Rect rect;
|
|
|
|
|
int walkType;
|
|
|
|
|
|
|
|
|
|
/* set rect to boundary of this dest area */
|
|
|
|
|
TITORECT(tile, &rect);
|
|
|
|
|
|
|
|
|
|
/* process contact types that can connect to this dest area */
|
|
|
|
|
for (rC = mzRouteContacts; rC != NULL; rC = rC->rc_next)
|
|
|
|
|
{
|
2020-05-23 23:13:14 +02:00
|
|
|
RouteLayer *rLOther = NULL;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* skip inactive contact types */
|
|
|
|
|
if (!(rC->rc_routeType.rt_active)) continue;
|
|
|
|
|
|
|
|
|
|
/* Find layer connecting to dest area FROM */
|
|
|
|
|
if (&(rC->rc_rLayer1->rl_routeType) == rT)
|
|
|
|
|
{
|
|
|
|
|
rLOther = rC->rc_rLayer2;
|
|
|
|
|
walkType = TT_ABOVE_UD_WALK;
|
|
|
|
|
}
|
|
|
|
|
else if (&(rC->rc_rLayer2->rl_routeType) == rT)
|
|
|
|
|
{
|
|
|
|
|
rLOther = rC->rc_rLayer1;
|
|
|
|
|
walkType = TT_BELOW_UD_WALK;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/* If current contact type (RC) permits connection to dest area,
|
2017-04-25 14:41:48 +02:00
|
|
|
* insert CONTACT_WALK(s) into blockage planes for other layer.
|
|
|
|
|
*/
|
|
|
|
|
if (rLOther)
|
|
|
|
|
{
|
|
|
|
|
/* process contact-OK tiles in blockage plane for this contact */
|
|
|
|
|
int mzCWalksFunc2();
|
|
|
|
|
WalkContactFuncData wD;
|
|
|
|
|
TileTypeBitMask contactOKMask;
|
|
|
|
|
|
|
|
|
|
TTMaskSetOnlyType(&contactOKMask, TT_SPACE);
|
|
|
|
|
TTMaskSetType(&contactOKMask, TT_SAMENODE);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
wD.wd_bounds = ▭
|
2017-04-25 14:41:48 +02:00
|
|
|
wD.wd_rL = rLOther;
|
|
|
|
|
wD.wd_walk = walkType;
|
|
|
|
|
|
|
|
|
|
/* search for OK places for contact in the vertical plane */
|
|
|
|
|
/* and paint them. */
|
|
|
|
|
|
|
|
|
|
DBSrPaintArea(NULL, /* no hint tile */
|
|
|
|
|
rC->rc_routeType.rt_vBlock,
|
2020-05-23 23:13:14 +02:00
|
|
|
&rect,
|
2017-04-25 14:41:48 +02:00
|
|
|
&contactOKMask,
|
2020-05-23 23:13:14 +02:00
|
|
|
mzCWalksFunc2,
|
2017-04-25 14:41:48 +02:00
|
|
|
(ClientData) &wD);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* return 0 - to continue search */
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* mzCWalksFunc2 --
|
|
|
|
|
*
|
|
|
|
|
* Called for tiles on contact plane where contact is OK that overlap a
|
|
|
|
|
* dest area. We paint a CONTACT_WALK on the blockage planes for the
|
|
|
|
|
* other routeLayer, the one the contact connects to the dest area.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Paints into blockage planes for "other" route layer.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mzCWalksFunc2(tile, cdarg)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
ClientData cdarg;
|
|
|
|
|
{
|
|
|
|
|
WalkContactFuncData *wD = (WalkContactFuncData *) cdarg;
|
|
|
|
|
Rect rect;
|
|
|
|
|
Walk *walk;
|
|
|
|
|
|
|
|
|
|
/* rect = tile clipped dest area bounds. */
|
|
|
|
|
TITORECT(tile, &rect);
|
|
|
|
|
GEOCLIP(&rect, wD->wd_bounds);
|
|
|
|
|
|
|
|
|
|
/* To-do: check if non-square contacts fit? */
|
|
|
|
|
|
|
|
|
|
/* Build walks for contacts above or below the tile */
|
|
|
|
|
{
|
|
|
|
|
walk = (Walk *) mallocMagic((unsigned) (sizeof(Walk)));
|
|
|
|
|
walk->w_rT = &(wD->wd_rL->rl_routeType);
|
|
|
|
|
walk->w_type = wD->wd_walk;
|
|
|
|
|
walk->w_rect = rect;
|
|
|
|
|
LIST_ADD(walk, mzWalkList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* return 0 - to continue search */
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|