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);
|
|
}
|