mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-29 17:39:28 +02:00
and forcing it to be passed as an argument to all the callback functions for the search routines that require it. Magic now compiles and runs with the new code, but there are a number of known issues that need to be fixed up. Committing now so that I can rebase on the last update to the master branch.
707 lines
19 KiB
C
707 lines
19 KiB
C
/*
|
|
* gaSimple.c -
|
|
*
|
|
* Code to try very simple stems
|
|
* (straight line connection from pin to terminal
|
|
* with a possible contact at or near each end)
|
|
*
|
|
* *********************************************************************
|
|
* * 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/garouter/gaSimple.c,v 1.2 2009/05/13 15:03:16 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "utils/magic.h"
|
|
#include "utils/geometry.h"
|
|
#include "utils/geofast.h"
|
|
#include "utils/hash.h"
|
|
#include "utils/heap.h"
|
|
#include "tiles/tile.h"
|
|
#include "database/database.h"
|
|
#include "windows/windows.h"
|
|
#include "utils/main.h"
|
|
#include "dbwind/dbwind.h"
|
|
#include "utils/signals.h"
|
|
#include "netmenu/netmenu.h"
|
|
#include "gcr/gcr.h"
|
|
#include "router/router.h"
|
|
#include "grouter/grouter.h"
|
|
#include "garouter/garouter.h"
|
|
#include "utils/netlist.h"
|
|
#include "textio/textio.h"
|
|
#include "utils/styles.h"
|
|
#include "utils/malloc.h"
|
|
#include "drc/drc.h"
|
|
#include "debug/debug.h"
|
|
#include "extract/extract.h"
|
|
#include "extract/extractInt.h"
|
|
|
|
bool gaIsClear();
|
|
|
|
/*--- Externals referenced in this file and not declared in include files ---*/
|
|
extern int gaMetalClear;
|
|
extern int gaPolyClear;
|
|
extern int gaContactClear;
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* gaStemSimpleInit --
|
|
*
|
|
* Initialize the SimpleStem struct to contain information on what
|
|
* simple routes are possible.
|
|
*
|
|
* Simple routes are grid aligned straight routes from the terminal
|
|
* to the pin, with a possible contact at the terminal and another near
|
|
* the pin on the grid line just before the channel edge.
|
|
*
|
|
* If this routine returns TRUE, gaStemSimpleRoute() must still be called
|
|
* to determine if a simple route is possible (and optionally to paint the
|
|
* route into a cell).
|
|
*
|
|
* Results:
|
|
* TRUE if successful, FALSE if it was not possible to make a
|
|
* grid-aligned route.
|
|
*
|
|
* Side effects:
|
|
* Fills in the fields of *simple.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
gaStemSimpleInit(routeUse, term, pinPoint, pinSide, simple)
|
|
CellUse *routeUse; /* Search this cell for obstacles */
|
|
NLTermLoc *term; /* Route from term->nloc_rect */
|
|
Point *pinPoint; /* Crossing point to reach */
|
|
int pinSide; /* Direction of pin from term. */
|
|
SimpleStem *simple; /* Fill this in */
|
|
{
|
|
|
|
SimpleWire *sMetal = &simple->ss_metalWire;
|
|
SimpleWire *sPoly = &simple->ss_polyWire;
|
|
Rect *cTerm = &simple->ss_cTerm;
|
|
Rect *cPin = &simple->ss_cPin;
|
|
Rect *termLoc = &term->nloc_rect;
|
|
|
|
/*
|
|
* Check that the start terminal is big enough for the route to be
|
|
* grid-aligned. The start terminal has to be big enough
|
|
* to hold a grid-aligned wire on each of the routing types.
|
|
*/
|
|
{
|
|
int bot, top;
|
|
|
|
switch (pinSide)
|
|
{
|
|
case GEO_NORTH:
|
|
case GEO_SOUTH:
|
|
{
|
|
bot = pinPoint->p_x;
|
|
top = termLoc->r_xtop;
|
|
if (bot < termLoc->r_xbot)
|
|
return (FALSE);
|
|
break;
|
|
}
|
|
|
|
case GEO_EAST:
|
|
case GEO_WEST:
|
|
{
|
|
bot = pinPoint->p_y;
|
|
top = termLoc->r_ytop;
|
|
if (bot < termLoc->r_ybot)
|
|
return (FALSE);
|
|
break;
|
|
}
|
|
}
|
|
if (bot + RtrMetalWidth > top || bot + RtrPolyWidth > top)
|
|
return (FALSE);
|
|
}
|
|
|
|
/* Misc initialization */
|
|
{
|
|
simple->ss_dir = pinSide;
|
|
simple->ss_pinPoint = *pinPoint;
|
|
simple->ss_termArea = term->nloc_rect;
|
|
simple->ss_termType = term->nloc_label->lab_type;
|
|
|
|
sMetal->sw_type = RtrMetalType;
|
|
sPoly->sw_type = RtrPolyType;
|
|
}
|
|
|
|
/* Determine which types connect to terminal directly
|
|
* (without adding a contact)
|
|
*/
|
|
if (simple->ss_termType == RtrContactType)
|
|
{
|
|
TTMaskSetOnlyType(&(simple->ss_termMask), RtrMetalType);
|
|
TTMaskSetType(&(simple->ss_termMask), RtrPolyType);
|
|
}
|
|
else
|
|
{
|
|
TTMaskSetOnlyType(&(simple->ss_termMask), simple->ss_termType);
|
|
}
|
|
|
|
/*
|
|
* Compute contact and wire areas.
|
|
* Defn of areas:
|
|
* - long wires run from terminal to pin,
|
|
* - short wires run from terminal to contact near pin,
|
|
* - pinStubs run from pinContact to pin.
|
|
*/
|
|
{
|
|
switch (pinSide)
|
|
{
|
|
case GEO_NORTH:
|
|
/* pin is directly above terminal */
|
|
{
|
|
/* compute terminal contact location */
|
|
cTerm->r_xbot = pinPoint->p_x + RtrContactOffset;
|
|
cTerm->r_ybot = termLoc->r_ytop - RtrContactWidth;
|
|
cTerm->r_xtop = cTerm->r_xbot + RtrContactWidth;
|
|
cTerm->r_ytop = cTerm->r_ybot + RtrContactWidth;
|
|
|
|
/* compute pin contact location */
|
|
cPin->r_xbot = pinPoint->p_x + RtrContactOffset;
|
|
cPin->r_ybot = (RTR_GRIDDOWN(pinPoint->p_y, RtrOrigin.p_y)
|
|
+ RtrContactOffset);
|
|
cPin->r_xtop = cPin->r_xbot + RtrContactWidth;
|
|
cPin->r_ytop = cPin->r_ybot + RtrContactWidth;
|
|
|
|
/* compute poly pin stub location */
|
|
sPoly->sw_pinStub.r_xbot = pinPoint->p_x;
|
|
sPoly->sw_pinStub.r_ybot = cPin->r_ytop;
|
|
sPoly->sw_pinStub.r_xtop = pinPoint->p_x + RtrPolyWidth;
|
|
sPoly->sw_pinStub.r_ytop = pinPoint->p_y;
|
|
|
|
/* compute metal pin stub location */
|
|
sMetal->sw_pinStub.r_xbot = pinPoint->p_x;
|
|
sMetal->sw_pinStub.r_ybot = cPin->r_ytop;
|
|
sMetal->sw_pinStub.r_xtop = pinPoint->p_x + RtrMetalWidth;
|
|
sMetal->sw_pinStub.r_ytop = pinPoint->p_y;
|
|
|
|
/* compute short metal wire */
|
|
sMetal->sw_short.r_xbot = pinPoint->p_x;
|
|
sMetal->sw_short.r_ybot = termLoc->r_ytop;
|
|
sMetal->sw_short.r_xtop = pinPoint->p_x + RtrMetalWidth;
|
|
sMetal->sw_short.r_ytop = cPin->r_ybot;
|
|
|
|
/* compute short poly wire */
|
|
sPoly->sw_short.r_xbot = pinPoint->p_x;
|
|
sPoly->sw_short.r_xtop = pinPoint->p_x + RtrPolyWidth;
|
|
sPoly->sw_short.r_ybot = termLoc->r_ytop;
|
|
sPoly->sw_short.r_ytop = cPin->r_ybot;
|
|
|
|
/* compute long metal wire */
|
|
sMetal->sw_long = sMetal->sw_short;
|
|
sMetal->sw_long.r_ytop = pinPoint->p_y;
|
|
|
|
/* compute long poly wire */
|
|
sPoly->sw_long = sPoly->sw_short;
|
|
sPoly->sw_long.r_ytop = pinPoint->p_y;
|
|
break;
|
|
}
|
|
|
|
case GEO_SOUTH:
|
|
/* pin is directly below terminal */
|
|
{
|
|
/* compute terminal contact location */
|
|
cTerm->r_xbot = pinPoint->p_x + RtrContactOffset;
|
|
cTerm->r_ybot = termLoc->r_ybot;
|
|
cTerm->r_xtop = cTerm->r_xbot + RtrContactWidth;
|
|
cTerm->r_ytop = cTerm->r_ybot + RtrContactWidth;
|
|
|
|
/* compute pin contact location */
|
|
cPin->r_xbot = pinPoint->p_x + RtrContactOffset;
|
|
cPin->r_ybot = (RTR_GRIDUP(pinPoint->p_y, RtrOrigin.p_y)
|
|
+ RtrContactOffset);
|
|
cPin->r_xtop = cPin->r_xbot + RtrContactWidth;
|
|
cPin->r_ytop = cPin->r_ybot + RtrContactWidth;
|
|
|
|
/* compute poly pin stub location */
|
|
sPoly->sw_pinStub.r_xbot = pinPoint->p_x;
|
|
sPoly->sw_pinStub.r_ybot = pinPoint->p_y;
|
|
sPoly->sw_pinStub.r_xtop = pinPoint->p_x + RtrPolyWidth;
|
|
sPoly->sw_pinStub.r_ytop = cPin->r_ybot;
|
|
|
|
/* compute metal pin stub location */
|
|
sMetal->sw_pinStub.r_xbot = pinPoint->p_x;
|
|
sMetal->sw_pinStub.r_ybot = pinPoint->p_y;
|
|
sMetal->sw_pinStub.r_xtop = pinPoint->p_x + RtrMetalWidth;
|
|
sMetal->sw_pinStub.r_ytop = cPin->r_ybot;
|
|
|
|
/* compute short metal wire */
|
|
sMetal->sw_short.r_xbot = pinPoint->p_x;
|
|
sMetal->sw_short.r_ybot = cPin->r_ytop;
|
|
sMetal->sw_short.r_xtop = pinPoint->p_x + RtrMetalWidth;
|
|
sMetal->sw_short.r_ytop = termLoc->r_ybot;
|
|
|
|
/* compute short poly wire */
|
|
sPoly->sw_short.r_xbot = pinPoint->p_x;
|
|
sPoly->sw_short.r_ybot = cPin->r_ytop;
|
|
sPoly->sw_short.r_xtop = pinPoint->p_x + RtrPolyWidth;
|
|
sPoly->sw_short.r_ytop = termLoc->r_ybot;
|
|
|
|
/* long metal wire */
|
|
sMetal->sw_long = sMetal->sw_short;
|
|
sMetal->sw_long.r_ybot = pinPoint->p_y;
|
|
|
|
/* long poly wire */
|
|
sPoly->sw_long = sPoly->sw_short;
|
|
sPoly->sw_long.r_ybot = pinPoint->p_y;
|
|
|
|
break;
|
|
}
|
|
|
|
case GEO_EAST:
|
|
/* pin is directly to right of terminal */
|
|
{
|
|
/* compute terminal contact location */
|
|
cTerm->r_xbot = termLoc->r_xtop - RtrContactWidth;
|
|
cTerm->r_ybot = pinPoint->p_y + RtrContactOffset;
|
|
cTerm->r_xtop = cTerm->r_xbot + RtrContactWidth;
|
|
cTerm->r_ytop = cTerm->r_ybot + RtrContactWidth;
|
|
|
|
/* compute pin contact location */
|
|
cPin->r_xbot = (RTR_GRIDDOWN(pinPoint->p_x, RtrOrigin.p_x)
|
|
+ RtrContactOffset);
|
|
cPin->r_ybot = pinPoint->p_y + RtrContactOffset;
|
|
cPin->r_xtop = cPin->r_xbot + RtrContactWidth;
|
|
cPin->r_ytop = cPin->r_ybot + RtrContactWidth;
|
|
|
|
/* compute poly pin stub location */
|
|
sPoly->sw_pinStub.r_xbot = cPin->r_xtop;
|
|
sPoly->sw_pinStub.r_ybot = pinPoint->p_y;
|
|
sPoly->sw_pinStub.r_xtop = pinPoint->p_x;
|
|
sPoly->sw_pinStub.r_ytop = pinPoint->p_y + RtrPolyWidth;
|
|
|
|
/* compute metal pin stub location */
|
|
sMetal->sw_pinStub.r_xbot = cPin->r_xtop;
|
|
sMetal->sw_pinStub.r_ybot = pinPoint->p_y;
|
|
sMetal->sw_pinStub.r_xtop = pinPoint->p_x;
|
|
sMetal->sw_pinStub.r_ytop = pinPoint->p_y + RtrMetalWidth;
|
|
|
|
/* compute short metal wire */
|
|
sMetal->sw_short.r_xbot = termLoc->r_xtop;
|
|
sMetal->sw_short.r_ybot = pinPoint->p_y;
|
|
sMetal->sw_short.r_xtop = cPin->r_xbot;
|
|
sMetal->sw_short.r_ytop = pinPoint->p_y + RtrMetalWidth;
|
|
|
|
/* compute short poly wire */
|
|
sPoly->sw_short.r_xbot = termLoc->r_xtop;
|
|
sPoly->sw_short.r_ybot = pinPoint->p_y;
|
|
sPoly->sw_short.r_xtop = cPin->r_xbot;
|
|
sPoly->sw_short.r_ytop = pinPoint->p_y + RtrPolyWidth;
|
|
|
|
/* compute long metal wire */
|
|
sMetal->sw_long = sMetal->sw_short;
|
|
sMetal->sw_long.r_xtop = pinPoint->p_x;
|
|
|
|
/* compute long poly wire */
|
|
sPoly->sw_long = sPoly->sw_short;
|
|
sPoly->sw_long.r_xtop = pinPoint->p_x;
|
|
break;
|
|
}
|
|
|
|
case GEO_WEST:
|
|
/* pin is directly to left of terminal */
|
|
{
|
|
/* compute terminal contact location */
|
|
cTerm->r_xbot = termLoc->r_xbot;
|
|
cTerm->r_ybot = pinPoint->p_y + RtrContactOffset;
|
|
cTerm->r_xtop = cTerm->r_xbot + RtrContactWidth;
|
|
cTerm->r_ytop = cTerm->r_ybot + RtrContactWidth;
|
|
|
|
/* compute pin contact location */
|
|
cPin->r_xbot = (RTR_GRIDUP(pinPoint->p_x, RtrOrigin.p_x)
|
|
+ RtrContactOffset);
|
|
cPin->r_ybot = pinPoint->p_y + RtrContactOffset;
|
|
cPin->r_xtop = cPin->r_xbot + RtrContactWidth;
|
|
cPin->r_ytop = cPin->r_ybot + RtrContactWidth;
|
|
|
|
/* compute poly pin stub location */
|
|
sPoly->sw_pinStub.r_xbot = pinPoint->p_x;
|
|
sPoly->sw_pinStub.r_ybot = pinPoint->p_y;
|
|
sPoly->sw_pinStub.r_xtop = cPin->r_xbot;
|
|
sPoly->sw_pinStub.r_ytop = pinPoint->p_y + RtrPolyWidth;
|
|
|
|
/* compute metal pin stub location */
|
|
sMetal->sw_pinStub.r_xbot = pinPoint->p_x;
|
|
sMetal->sw_pinStub.r_ybot = pinPoint->p_y;
|
|
sMetal->sw_pinStub.r_xtop = cPin->r_xbot;
|
|
sMetal->sw_pinStub.r_ytop = pinPoint->p_y + RtrMetalWidth;
|
|
|
|
/* compute short metal wire */
|
|
sMetal->sw_short.r_xbot = cPin->r_xtop;
|
|
sMetal->sw_short.r_ybot = pinPoint->p_y;
|
|
sMetal->sw_short.r_xtop = termLoc->r_xbot;
|
|
sMetal->sw_short.r_ytop = pinPoint->p_y + RtrMetalWidth;
|
|
|
|
/* compute short poly wire */
|
|
sPoly->sw_short.r_xbot = cPin->r_xtop;
|
|
sPoly->sw_short.r_ybot = pinPoint->p_y;
|
|
sPoly->sw_short.r_xtop = termLoc->r_xbot;
|
|
sPoly->sw_short.r_ytop = pinPoint->p_y + RtrPolyWidth;
|
|
|
|
/* long metal wire */
|
|
sMetal->sw_long = sMetal->sw_short;
|
|
sMetal->sw_long.r_xbot = pinPoint->p_x;
|
|
|
|
/* long poly wire */
|
|
sPoly->sw_long = sPoly->sw_short;
|
|
sPoly->sw_long.r_xbot = pinPoint->p_x;
|
|
|
|
break;
|
|
}
|
|
|
|
} /* end switch */
|
|
}
|
|
|
|
/* check which wires and contacts are blocked */
|
|
{
|
|
Rect rTerm, rPin, rShortMetal, rShortPoly, rLongMetal, rLongPoly;
|
|
Rect rStubMetal, rStubPoly;
|
|
|
|
/*
|
|
* bloat wire and contact areas to produce the areas that must
|
|
* be clear of obstacles in order for a route to be possible.
|
|
*/
|
|
{
|
|
GEO_EXPAND(cTerm, gaContactClear, &rTerm);
|
|
GEO_EXPAND(cPin, gaContactClear, &rPin);
|
|
GEO_EXPAND(&sMetal->sw_short, gaMetalClear, &rShortMetal);
|
|
GEO_EXPAND(&sMetal->sw_long, gaMetalClear, &rLongMetal);
|
|
GEO_EXPAND(&sMetal->sw_pinStub, gaMetalClear, &rStubMetal);
|
|
GEO_EXPAND(&sPoly->sw_short, gaPolyClear, &rShortPoly);
|
|
GEO_EXPAND(&sPoly->sw_long, gaPolyClear, &rLongPoly);
|
|
GEO_EXPAND(&sPoly->sw_pinStub, gaPolyClear, &rStubPoly);
|
|
}
|
|
|
|
/*
|
|
* Prune check areas at terminal and pin to allow prexisting
|
|
* material at the connection points.
|
|
*
|
|
* (NOTE the terminal contact area is not trimmed, but will
|
|
* only be checked on the layer (if any) that is not part
|
|
* of the terminal)
|
|
*/
|
|
{
|
|
Rect pruneR;
|
|
|
|
/* compute prune area */
|
|
{
|
|
pruneR = routeUse->cu_bbox;
|
|
switch (pinSide)
|
|
{
|
|
case GEO_NORTH:
|
|
{
|
|
pruneR.r_ybot = termLoc->r_ytop;
|
|
pruneR.r_ytop = pinPoint->p_y;
|
|
break;
|
|
}
|
|
|
|
case GEO_SOUTH:
|
|
{
|
|
pruneR.r_ybot = pinPoint->p_y;
|
|
pruneR.r_ytop = termLoc->r_ybot;
|
|
break;
|
|
}
|
|
|
|
case GEO_EAST:
|
|
{
|
|
pruneR.r_xbot = termLoc->r_xtop;
|
|
pruneR.r_xtop = pinPoint->p_x;
|
|
break;
|
|
}
|
|
|
|
case GEO_WEST:
|
|
{
|
|
pruneR.r_xbot = pinPoint->p_x;
|
|
pruneR.r_xtop = termLoc->r_xbot;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* prune the areas (accept for rTerm) */
|
|
{
|
|
GEOCLIP(&rPin, &pruneR);
|
|
GEOCLIP(&rShortMetal, &pruneR);
|
|
GEOCLIP(&rLongMetal, &pruneR);
|
|
GEOCLIP(&rStubMetal, &pruneR);
|
|
GEOCLIP(&rShortPoly, &pruneR);
|
|
GEOCLIP(&rLongPoly, &pruneR);
|
|
GEOCLIP(&rStubPoly, &pruneR);
|
|
}
|
|
}
|
|
|
|
/* check areas for obstacles */
|
|
{
|
|
/* terminal contact */
|
|
{
|
|
if(!TTMaskHasType(&simple->ss_termMask, RtrMetalType))
|
|
{
|
|
simple->ss_cTermOK = gaIsClear(routeUse,
|
|
&rTerm,
|
|
&RtrMetalObstacles);
|
|
}
|
|
if(!TTMaskHasType(&simple->ss_termMask, RtrPolyType))
|
|
{
|
|
simple->ss_cTermOK = gaIsClear(routeUse,
|
|
&rTerm,
|
|
&RtrPolyObstacles);
|
|
}
|
|
}
|
|
|
|
/* pin contact */
|
|
{
|
|
TileTypeBitMask allObs;
|
|
|
|
TTMaskSetMask3(&allObs, &RtrPolyObstacles, &RtrMetalObstacles);
|
|
simple->ss_cPinOK = gaIsClear(routeUse, &rPin, &allObs);
|
|
}
|
|
|
|
/* short metal wire
|
|
* (a short wire is only ok if both the short wire itself and
|
|
* the complementary stub are clear)
|
|
*/
|
|
sMetal->sw_shortOK = (gaIsClear(routeUse,
|
|
&rShortMetal,
|
|
&RtrMetalObstacles)
|
|
&&
|
|
gaIsClear(routeUse,
|
|
&rStubPoly,
|
|
&RtrPolyObstacles));
|
|
|
|
|
|
/* long metal wire */
|
|
sMetal->sw_longOK = gaIsClear(routeUse,
|
|
&rLongMetal,
|
|
&RtrMetalObstacles);
|
|
|
|
/* short poly wire */
|
|
sPoly->sw_shortOK = (gaIsClear(routeUse,
|
|
&rShortPoly,
|
|
&RtrPolyObstacles)
|
|
&&
|
|
gaIsClear(routeUse,
|
|
&rStubMetal,
|
|
&RtrMetalObstacles));
|
|
|
|
/* long poly wire */
|
|
sPoly->sw_longOK = gaIsClear(routeUse,
|
|
&rLongPoly,
|
|
&RtrPolyObstacles);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* gaIsClear --
|
|
*
|
|
*
|
|
* Check that r is clear of all material of types in mask.
|
|
*
|
|
* Results:
|
|
* TRUE if the area is clear, FALSE if not.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
gaIsClear(use, r, mask)
|
|
CellUse *use;
|
|
Rect *r;
|
|
TileTypeBitMask *mask;
|
|
{
|
|
int gaIsClearFunc();
|
|
SearchContext scx;
|
|
|
|
scx.scx_use = use;
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
scx.scx_area = *r;
|
|
if (DebugIsSet(gaDebugID, gaDebStems))
|
|
{
|
|
ShowRect(use->cu_def, r, STYLE_OUTLINEHIGHLIGHTS);
|
|
TxMore("Checking clear area");
|
|
ShowRect(use->cu_def, r, STYLE_ERASEHIGHLIGHTS);
|
|
}
|
|
if (DBTreeSrTiles(&scx, mask, 0, gaIsClearFunc, (ClientData) NULL))
|
|
return (FALSE);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* gaIsClearFunc --
|
|
*
|
|
* Called for tiles whose type matches 'mask' underneath the area
|
|
* 'r' in gaIsClear() above.
|
|
*
|
|
* Results:
|
|
* Always returns 1 since we only need a single obstacle to not have
|
|
* a clear area.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
gaIsClearFunc(tile, dinfo, cxp)
|
|
Tile *tile;
|
|
TileType dinfo;
|
|
TreeContext *cxp;
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* gaStemSimpleRoute --
|
|
*
|
|
* See if a simple type of route is possible given the pinLayer.
|
|
* All other information describing the simple route is
|
|
* present in *simple.
|
|
*
|
|
* Results:
|
|
* TRUE if a route was possible, FALSE if not.
|
|
*
|
|
* Side effects:
|
|
* Paints the path into 'def' if 'def' is non-NULL.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
gaStemSimpleRoute(simple, pinLayer, def)
|
|
SimpleStem *simple; /* Describes the route */
|
|
TileType pinLayer; /* Connect to pin on this layer */
|
|
CellDef *def; /* If non-NULL, paint to this def */
|
|
{
|
|
SimpleWire *wPin, *wOther;
|
|
|
|
/*
|
|
* Determine which wire corresponds to pin
|
|
* and which corresponds to the other route layer.
|
|
*/
|
|
if (pinLayer == RtrPolyType)
|
|
{
|
|
wPin = &simple->ss_polyWire;
|
|
wOther = &simple->ss_metalWire;
|
|
}
|
|
else if (pinLayer == RtrMetalType)
|
|
{
|
|
wPin = &simple->ss_metalWire;
|
|
wOther = &simple->ss_polyWire;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(FALSE, "gaStemSimpleRoute: bad destType");
|
|
}
|
|
|
|
if(TTMaskHasType(&simple->ss_termMask, pinLayer))
|
|
/* layer of pin also OK for final connection at terminal */
|
|
{
|
|
if(wPin->sw_longOK)
|
|
/* No contact connection */
|
|
{
|
|
if(def)
|
|
{
|
|
DBPaint(def, &wPin->sw_long, wPin->sw_type);
|
|
}
|
|
return TRUE;
|
|
}
|
|
/* contact at pin only */
|
|
else if (TTMaskHasType(&simple->ss_termMask, wOther->sw_type) &&
|
|
wOther->sw_shortOK &&
|
|
simple->ss_cPinOK)
|
|
{
|
|
if(def)
|
|
{
|
|
DBPaint(def, &wOther->sw_short, wOther->sw_type);
|
|
RtrPaintContact(def, &simple->ss_cPin);
|
|
DBPaint(def, &wPin->sw_pinStub, wPin->sw_type);
|
|
}
|
|
return TRUE;
|
|
}
|
|
else if (simple->ss_cTermOK &&
|
|
wOther->sw_shortOK &&
|
|
simple->ss_cPinOK)
|
|
/* two contact route */
|
|
{
|
|
if(def)
|
|
{
|
|
RtrPaintContact(def, &simple->ss_cTerm);
|
|
DBPaint(def, &wOther->sw_short, wOther->sw_type);
|
|
RtrPaintContact(def, &simple->ss_cPin);
|
|
DBPaint(def, &wPin->sw_pinStub, wPin->sw_type);
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
/* No simple route */
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
/* pin and terminal connections on opposite layers */
|
|
{
|
|
if(simple->ss_cTermOK &&
|
|
wPin->sw_longOK)
|
|
/* contact at terminal only */
|
|
{
|
|
if(def)
|
|
{
|
|
RtrPaintContact(def, &simple->ss_cTerm);
|
|
DBPaint(def, &wPin->sw_long, wPin->sw_type);
|
|
}
|
|
return TRUE;
|
|
}
|
|
else if(wOther->sw_shortOK &&
|
|
simple->ss_cPinOK)
|
|
/* contact at pin only */
|
|
{
|
|
if(def)
|
|
{
|
|
DBPaint(def, &wOther->sw_short, wOther->sw_type);
|
|
RtrPaintContact(def, &simple->ss_cPin);
|
|
DBPaint(def, &wPin->sw_pinStub, wPin->sw_type);
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
/* No simple route */
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|