magic/grouter/grouteTile.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);
}