395 lines
10 KiB
C
395 lines
10 KiB
C
/* grouteTile.c -
|
||
*
|
||
* Global signal router code for tile and channel related things.
|
||
*
|
||
* *********************************************************************
|
||
* * 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 sccsid[] = "@(#)grouteTile.c 4.3 MAGIC (Berkeley) 10/31/85";
|
||
#endif /* not lint */
|
||
|
||
#include <stdio.h>
|
||
|
||
#include "utils/magic.h"
|
||
#include "utils/geometry.h"
|
||
#include "utils/hash.h"
|
||
#include "utils/heap.h"
|
||
#include "tiles/tile.h"
|
||
#include "database/database.h"
|
||
#include "debug/debug.h"
|
||
#include "gcr/gcr.h"
|
||
#include "windows/windows.h"
|
||
#include "graphics/graphics.h"
|
||
#include "utils/main.h"
|
||
#include "dbwind/dbwind.h"
|
||
#include "utils/signals.h"
|
||
#include "router/router.h"
|
||
#include "grouter/grouter.h"
|
||
#include "utils/styles.h"
|
||
#include "textio/textio.h"
|
||
|
||
bool GlDebugCrossings = FALSE;
|
||
|
||
#define isSpaceTile(tile) (TiGetBody(tile) == NULL)
|
||
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* glAdjacentChannel --
|
||
*
|
||
* Figure out which channel borders the given channel at the given
|
||
* point. If the given channel is NULL, then assume the point is at
|
||
* the edge of a cell, and return the channel adjacent to the cell.
|
||
*
|
||
* Results:
|
||
* Pointer to the adjacent channel, or NULL if none exists.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
GCRChannel *
|
||
glAdjacentChannel(ch, point)
|
||
GCRChannel *ch; /* The tile corresponding to a channel */
|
||
Point *point; /* A point somewhere on the channel edge */
|
||
{
|
||
Point p;
|
||
int side;
|
||
|
||
ASSERT(ch!=(GCRChannel *) NULL, "Null channel in glAdjacentChannel");
|
||
side = glPointToSide(ch, point);
|
||
|
||
p = * point;
|
||
switch(side)
|
||
{
|
||
case GEO_NORTH:
|
||
case GEO_EAST:
|
||
break;
|
||
case GEO_SOUTH:
|
||
p.p_y--;
|
||
break;
|
||
case GEO_WEST:
|
||
p.p_x--;
|
||
break;
|
||
default:
|
||
ASSERT(FALSE, "glAdjacentChannel point not on channel");
|
||
return((GCRChannel *) NULL);
|
||
break;
|
||
}
|
||
|
||
return (glTileToChannel(TiSrPointNoHint(RtrChannelPlane, &p)));
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* glBadChannel --
|
||
*
|
||
* Decide if a prospective channel is okay to use in global routing
|
||
* propagation. If it creates a loop for the particular path under
|
||
* investigation, then forget it. If it doesn't exist, then forget it.
|
||
*
|
||
* Results:
|
||
* FALSE if the channel is okay to use, otherwise TRUE.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
bool
|
||
glBadChannel(oldCh, newCh, entryPt)
|
||
GCRChannel *oldCh; /* The current channel */
|
||
GCRChannel *newCh; /* See if this new one is okay to use */
|
||
GlPoint *entryPt; /* List of previously used points */
|
||
{
|
||
GlPoint *temp;
|
||
|
||
/* Reject a null channel */
|
||
if ((oldCh == (GCRChannel *) NULL) || (newCh == (GCRChannel *) NULL))
|
||
return (TRUE);
|
||
|
||
/* Reject the channel if using it creates a loop in the routing path */
|
||
for (temp = entryPt; temp != (GlPoint *) NULL; temp = temp->gl_parent)
|
||
if (temp->gl_ch == newCh)
|
||
return (TRUE);
|
||
|
||
return (FALSE);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* glDebug --
|
||
*
|
||
* Code to display crossing points on the screen.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
glDebug(point, text, value, size)
|
||
Point *point; /* Location to be marked */
|
||
char *text; /* Text to associate with error paint */
|
||
int value; /* An integer value to go into the text */
|
||
int size; /* How big to make the error paint box */
|
||
{
|
||
char buffer1[1024], buffer2[1024];
|
||
Rect area;
|
||
|
||
if (!GlDebugCrossings)
|
||
return;
|
||
|
||
(void) strcpy(buffer1, text);
|
||
(void) sprintf(buffer2, "(value = %d)", value);
|
||
(void) strcat(buffer1, buffer2);
|
||
area.r_ll.p_x = point->p_x - size;
|
||
area.r_ur.p_x = point->p_x + size;
|
||
area.r_ll.p_y = point->p_y - size;
|
||
area.r_ur.p_y = point->p_y + size;
|
||
DBWFeedbackAdd(&area, buffer1, EditCellUse->cu_def, 1,
|
||
STYLE_PALEHIGHLIGHTS);
|
||
GrFlush();
|
||
(void) sprintf(buffer2, "%s --more--", buffer1);
|
||
(void) TxGetLinePrompt(buffer1, sizeof buffer1, buffer2);
|
||
if (buffer1[0] == 'q')
|
||
GlDebugCrossings = FALSE;
|
||
TxPrintf("\n");
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* glPointToChannel --
|
||
*
|
||
* Given a point and a direction, return a pointer to the channel
|
||
* adjacent to the given point, in the given direction. The point
|
||
* must be on the edge of a channel. If on the edge of a cell, the
|
||
* point location must be the modified location returned by RtrStemTip.
|
||
*
|
||
* Results:
|
||
* Pointer to the channel.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
GCRChannel *
|
||
glPointToChannel(point, dir)
|
||
Point *point; /* The point from which the channel is found */
|
||
int dir; /* The direction in which the search goes */
|
||
{
|
||
Point p;
|
||
|
||
p = *point;
|
||
switch (dir)
|
||
{
|
||
case GEO_NORTH:
|
||
case GEO_EAST:
|
||
break;
|
||
case GEO_SOUTH:
|
||
p.p_y--;
|
||
break;
|
||
case GEO_WEST:
|
||
p.p_x--;
|
||
break;
|
||
default:
|
||
ASSERT(FALSE, "glPointToChannel: bad direction argument");
|
||
return ((GCRChannel *) NULL);
|
||
}
|
||
return (glTileToChannel(TiSrPointNoHint(RtrChannelPlane, &p)));
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* glPointToSide --
|
||
*
|
||
* Given a point somewhere on the perimeter of a channel, determine
|
||
* which side it is on. The channel is given to prevent ambiguity,
|
||
* since the point may fall on a border between two channels.
|
||
*
|
||
* Results:
|
||
* The compass direction corresponding to the side of the channel on
|
||
* which the point lies.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
glPointToSide(ch, pt)
|
||
GCRChannel * ch; /* Channel containing the given point */
|
||
Point * pt; /* The point on some side of the channel*/
|
||
{
|
||
|
||
/* The point is on the left */
|
||
if (ch->gcr_area->r_xbot == pt->p_x)
|
||
return (GEO_WEST);
|
||
|
||
/* The point is on the bottom */
|
||
if (ch->gcr_area->r_ybot == pt->p_y)
|
||
return (GEO_SOUTH);
|
||
|
||
/* The point is on the right */
|
||
if (ch->gcr_area->r_xtop == pt->p_x)
|
||
return (GEO_EAST);
|
||
|
||
/* The point is on the top */
|
||
if (ch->gcr_area->r_ytop == pt->p_y)
|
||
return (GEO_NORTH);
|
||
|
||
ASSERT(FALSE, "glPointToSide point not on edge");
|
||
return (GEO_CENTER);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* glSide --
|
||
*
|
||
* Determine which side of a cell a terminal label is on by looking on
|
||
* the channel plane for channel tiles in each of the quadrants. A
|
||
* terminal label must not fall on space or on a corner. It must lie
|
||
* on a flat edge of a cell tile.
|
||
*
|
||
* Are all these calls to TiSrPoint really necessary? I think so,
|
||
* because a label might fall on the edge of a particular tile but
|
||
* still appear over contiguous cell tiles.
|
||
*
|
||
* Results:
|
||
* A direction GEO_NORTH, SOUTH, EAST, WEST, or CENTER if internal or
|
||
* a corner. This indicates the side of the cell on which the terminal
|
||
* lies.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
glSide(point)
|
||
Point *point; /* The lower left point of the label rectangle */
|
||
{
|
||
int glSrFunc();
|
||
Tile *t;
|
||
Point p;
|
||
|
||
p = *point;
|
||
t = TiSrPoint((Tile *) NULL, RtrChannelPlane, &p);
|
||
|
||
if(TiGetBody(t) != NULL) /* _?|X_ */
|
||
{ /* ?|? */
|
||
p.p_x--;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) != NULL) /* _X|X_ */
|
||
{ /* ?|? */
|
||
p.p_y--;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) != NULL) /* _X|X_ */
|
||
return(GEO_CENTER); /* X|? */
|
||
p.p_x++;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) != NULL) /* _X|X_ */
|
||
return(GEO_CENTER); /* |X */
|
||
else return(GEO_SOUTH);
|
||
}
|
||
else /* __|X_ */
|
||
{ /* ?|? */
|
||
p.p_y--;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) != NULL) /* __|X_ */
|
||
return(GEO_CENTER); /* X|? */
|
||
p.p_x++;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) != NULL) /* __|X_ */
|
||
return(GEO_WEST); /* |X */
|
||
}
|
||
}
|
||
else /* Forget about S or W */
|
||
{
|
||
p.p_x--;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) != NULL) /* _X|__ */
|
||
{ /* ?|? */
|
||
p.p_y--;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) == NULL) /* _X|__ */
|
||
return(GEO_CENTER); /* |? */
|
||
p.p_x++;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) != NULL) /* _X|__ */
|
||
return(GEO_CENTER); /* X|X */
|
||
else return(GEO_EAST);
|
||
}
|
||
else /* __|__ */
|
||
{ /* ?|? */
|
||
p.p_y--;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) == NULL) /* __|__ */
|
||
return(GEO_CENTER); /* |? */
|
||
p.p_x++;
|
||
t = TiSrPoint(t, RtrChannelPlane, &p);
|
||
if(TiGetBody(t) != NULL) /* __|__ */
|
||
return(GEO_NORTH); /* X|X */
|
||
}
|
||
}
|
||
return(GEO_CENTER);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* glTileToChannel --
|
||
*
|
||
* Figure out which channel corresponds to the given tile.
|
||
*
|
||
* Results:
|
||
* Pointer to the channel.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
GCRChannel *
|
||
glTileToChannel(tile)
|
||
Tile *tile; /* Should point to a channel (space) tile */
|
||
{
|
||
HashEntry *he;
|
||
|
||
if (!isSpaceTile(tile))
|
||
return ((GCRChannel *) NULL);
|
||
he = HashLookOnly(&RtrTileToChannel, (char *) tile);
|
||
if (he == (HashEntry *) NULL)
|
||
return ((GCRChannel *) NULL);
|
||
return (GCRChannel *) HashGetValue(he);
|
||
}
|