598 lines
18 KiB
C
598 lines
18 KiB
C
/* rtrHazards.c -
|
||
*
|
||
* Code to set hazard flags at each grid point in a channel. These flags
|
||
* are used during channel routing and global routing.
|
||
*
|
||
* HAZARD FLAGS indicate that the channel router should try to move
|
||
* tracks out of the flagged areas, in order to avoid routing over
|
||
* blocked areas or obstacles which are wider than they are tall. The
|
||
* hazards cover the obstacle, an area immediately ahead of the obstacle,
|
||
* and one grid line above and below the obstacle (considering the
|
||
* direction of routing) which allows for column contacts.
|
||
* The size of the hazard is the product of the global variable
|
||
* GCRObstDist and the height of the obstacle.
|
||
*
|
||
* Hazards are generated for each of the four possible routing directions
|
||
* across the channel, though the channel will be routed from left to.
|
||
* right. Hazards in the other orientations are used only by the global
|
||
* router, in choosing channel-to-channel crossings.
|
||
*
|
||
* *********************************************************************
|
||
* * 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/router/rtrHazards.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
||
#endif /* not lint */
|
||
|
||
#include <stdio.h>
|
||
|
||
#include "utils/magic.h"
|
||
#include "utils/geometry.h"
|
||
#include "tiles/tile.h"
|
||
#include "gcr/gcr.h"
|
||
#include "utils/malloc.h"
|
||
|
||
/* Forward declarations */
|
||
|
||
extern void rtrFindEnds();
|
||
extern void rtrFlag();
|
||
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* RtrHazards --
|
||
*
|
||
* Scan the channel obstacle map. Set flags for hazards. Mark left and
|
||
* right hazards in one pass, since the height to width ratio is the
|
||
* same regardless of direction. Similarly, mark top and bottom hazards
|
||
* in another pass.
|
||
*
|
||
* For left and right hazards:
|
||
* Use a top to bottom, left to right point by point scan, comparing the
|
||
* width of an obstacle to its height at each grid location. If the
|
||
* width is greater than the height, or if the location is blocked:
|
||
* (1) Find the height of the obstacle by finding the lowest consecutive
|
||
* location for which the condition holds;
|
||
* (2) Find the width of the obstacle by extending the line of height to
|
||
* the left and right, until some edge of the obstacle is found;
|
||
* (3) Paint a hazard over the obstacle plus extensions. Extend left
|
||
* a distance proportional to the height of the obstacle. Extend up
|
||
* and down by 1 grid line.
|
||
*
|
||
* For top and bottom hazards:
|
||
* As above, with "top" and "bottom" interchanged with "left" and "right",
|
||
* and GCRVU and GCRVD substituted for GCRVR and GCRVL.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Memory is allocated and released.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
RtrHazards(ch)
|
||
GCRChannel *ch; /* The channel to be flagged */
|
||
{
|
||
short **map, **rtrHeights(), **rtrWidths(), **height, **width;
|
||
short *hcol, *wcol, *mcol;
|
||
int row, col, bot, top, left, right, maxcol;
|
||
|
||
height = rtrHeights(ch);
|
||
width = rtrWidths(ch);
|
||
|
||
/*
|
||
* Scan the channel, looking for a place where obstacle height < width or
|
||
* blocked on both layers, and not previously marked. For each such point,
|
||
* find the tallest, then widest rectangle containing the point.
|
||
*/
|
||
map = ch->gcr_result;
|
||
for (col = 1; col <= ch->gcr_length; col++)
|
||
{
|
||
/*
|
||
* If there is an obstacle over the crossing, set the Size field of the
|
||
* crossing point to indicate how large the obstacle is in the direction
|
||
* of the net's travel. This could not be done at the time the GCROBST
|
||
* flag was set (RtrChannelObstacles), since heights and widths were not
|
||
* yet computed. Extend the obstacle marking outwards 1 grid.
|
||
*/
|
||
if (ch->gcr_bPins[col].gcr_pFlags == GCROBST)
|
||
ch->gcr_bPins[col].gcr_pSize = height[col][1];
|
||
else if (ch->gcr_bPins[col-1].gcr_pFlags == GCROBST)
|
||
ch->gcr_bPins[col].gcr_pFlags |= GCRTCC;
|
||
else if (ch->gcr_bPins[col+1].gcr_pFlags == GCROBST)
|
||
ch->gcr_bPins[col].gcr_pFlags |= GCRTCC;
|
||
|
||
if (ch->gcr_tPins[col].gcr_pFlags == GCROBST)
|
||
ch->gcr_tPins[col].gcr_pSize = height[col][ch->gcr_width];
|
||
else if (ch->gcr_tPins[col-1].gcr_pFlags == GCROBST)
|
||
ch->gcr_tPins[col].gcr_pFlags |= GCRTCC;
|
||
else if (ch->gcr_tPins[col+1].gcr_pFlags == GCROBST)
|
||
ch->gcr_tPins[col].gcr_pFlags |= GCRTCC;
|
||
|
||
hcol = height[col];
|
||
wcol = width[col];
|
||
mcol = map[col];
|
||
for (row = 1; row <= ch->gcr_width; row++)
|
||
{
|
||
if ((hcol[row] < wcol[row] && !(mcol[row]&GCRVL))
|
||
|| BLOCK(mcol[row]))
|
||
{
|
||
/*
|
||
* Find the far side of the region where height < width.
|
||
* This is not necessarily row - height - 1 since the
|
||
* width may vary.
|
||
*/
|
||
for (bot = row; row <= ch->gcr_width; row++)
|
||
if (hcol[row] >= wcol[row] && !BLOCK(mcol[row]))
|
||
break;
|
||
top = row - 1;
|
||
|
||
/*
|
||
* Extend left and right through contiguous material.
|
||
* Mark the hazard flags.
|
||
*/
|
||
left = col;
|
||
rtrFindEnds(ch, TRUE, bot, top, &left, &right);
|
||
rtrFlag(ch, left, right, bot, top, TRUE);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Go the other way to get the upper and lower flags */
|
||
for (row = 1; row <= ch->gcr_width; row++)
|
||
{
|
||
/*
|
||
* If there is an obstacle over the crossing, set the Size field of the
|
||
* crossing point to indicate how large the obstacle is in the direction
|
||
* of the net's travel. This could not be done at the time the GCROBST
|
||
* flag was set (RtrChannelObstacles), since heights and widths were not
|
||
* yet computed. Put GCRTCC markings at the edges.
|
||
*/
|
||
if (ch->gcr_lPins[row].gcr_pFlags == GCROBST)
|
||
ch->gcr_lPins[row].gcr_pSize = width[1][row];
|
||
else if (ch->gcr_lPins[row-1].gcr_pFlags == GCROBST)
|
||
ch->gcr_lPins[row].gcr_pFlags |= GCRTCC;
|
||
else if (ch->gcr_lPins[row+1].gcr_pFlags == GCROBST)
|
||
ch->gcr_lPins[row].gcr_pFlags |= GCRTCC;
|
||
|
||
if (ch->gcr_rPins[row].gcr_pFlags == GCROBST)
|
||
ch->gcr_rPins[row].gcr_pSize = width[ch->gcr_length][row];
|
||
else if (ch->gcr_rPins[row-1].gcr_pFlags == GCROBST)
|
||
ch->gcr_rPins[row].gcr_pFlags |= GCRTCC;
|
||
else if (ch->gcr_rPins[row+1].gcr_pFlags == GCROBST)
|
||
ch->gcr_rPins[row].gcr_pFlags |= GCRTCC;
|
||
|
||
for (col = 1; col <= ch->gcr_length; col++)
|
||
{
|
||
if ((height[col][row] > width[col][row] && !(map[col][row]&GCRVU))
|
||
|| BLOCK(map[col][row]))
|
||
{
|
||
/*
|
||
* Find the far side of the region where height > width.
|
||
* This is not necessarily col + width - 1 since the width
|
||
* may vary.
|
||
*/
|
||
for (left = col; col <= ch->gcr_length; col++)
|
||
if (height[col][row] <= width[col][row] &&
|
||
!BLOCK(map[col][row]))
|
||
break;
|
||
right = col - 1;
|
||
|
||
/*
|
||
* Extend up and down through contiguous material.
|
||
* Mark the hazard flags.
|
||
*/
|
||
bot = row;
|
||
rtrFindEnds(ch, FALSE, left, right, &bot, &top);
|
||
rtrFlag(ch, left, right, bot, top, FALSE);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Free storage for height and width */
|
||
maxcol = ch->gcr_length + 1;
|
||
for (col = 0; col <= maxcol; col++)
|
||
{
|
||
freeMagic((char *) height[col]);
|
||
freeMagic((char *) width[col]);
|
||
}
|
||
freeMagic((char *) height);
|
||
freeMagic((char *) width);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* rtrHeights --
|
||
*
|
||
* Find the heights of all obstacles in the given channel.
|
||
*
|
||
* Results:
|
||
* A pointer to an array of obstacle heights for the given channel.
|
||
*
|
||
* Side effects:
|
||
* Mallocs the memory for the heights array.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
short **
|
||
rtrHeights(ch)
|
||
GCRChannel * ch; /* Channel to be processed */
|
||
{
|
||
short **heights, *obstacles, *hcol;
|
||
int i, row;
|
||
int col, start, n;
|
||
unsigned lenWds, widWds;
|
||
|
||
/*
|
||
* Malloc and initialize an array to hold the obstacle height
|
||
* at each point.
|
||
*/
|
||
lenWds = ch->gcr_length + 2;
|
||
widWds = ch->gcr_width + 2;
|
||
heights = (short **) mallocMagic((unsigned) (lenWds * sizeof (short *)));
|
||
for (col = 0; col < (int) lenWds; col++)
|
||
{
|
||
heights[col] = (short *) mallocMagic((unsigned) (widWds * sizeof (short)));
|
||
for (row = 0; row < (int) widWds; row++)
|
||
heights[col][row] = 0;
|
||
}
|
||
|
||
/*
|
||
* Scan over the obstacle map.
|
||
* At the start of an obstacle, scan downward to find the height
|
||
* of contiguous material on either or both of the layers. Set
|
||
* the obstacle height for every location in the vertical strip
|
||
* just scanned.
|
||
*/
|
||
for (col = 1; col <= ch->gcr_length; col++)
|
||
{
|
||
hcol = heights[col];
|
||
obstacles = ch->gcr_result[col];
|
||
for (row = 1; row <= ch->gcr_width; row++)
|
||
{
|
||
obstacles++;
|
||
if (CLEAR(*obstacles)) continue;
|
||
|
||
/* Found an obstacle of some sort, so scan to its end */
|
||
for (start = row; row <= ch->gcr_width && !CLEAR(*obstacles); row++)
|
||
obstacles++;
|
||
|
||
/*
|
||
* Set height values at every grid point touched
|
||
* in this column by the obstacle.
|
||
*/
|
||
n = row - start;
|
||
for (i = start; i < row; i++)
|
||
hcol[i] = n;
|
||
}
|
||
}
|
||
|
||
return (heights);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* rtrWidths --
|
||
*
|
||
* Find the widths of all obstacles in the given channel.
|
||
*
|
||
* Results:
|
||
* A pointer to an array of obstacle widths for the given channel.
|
||
*
|
||
* Side effects:
|
||
* Mallocs the memory for the widths array.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
short **
|
||
rtrWidths(ch)
|
||
GCRChannel * ch;
|
||
{
|
||
short **widths, **map;
|
||
int col, i;
|
||
unsigned lenWds, widWds;
|
||
int row, start, n;
|
||
|
||
/*
|
||
* Malloc and initialize an array to hold the obstacle width
|
||
* at each point.
|
||
*/
|
||
lenWds = ch->gcr_length + 2;
|
||
widWds = ch->gcr_width + 2;
|
||
widths = (short **) mallocMagic((unsigned) (lenWds * sizeof (short *)));
|
||
for (col = 0; col < (int) lenWds; col++)
|
||
{
|
||
widths[col] = (short *) mallocMagic((unsigned) (widWds * sizeof (short)));
|
||
for (row = 0; row < (int) widWds; row++)
|
||
widths[col][row] = 0;
|
||
}
|
||
map = ch->gcr_result;
|
||
|
||
/*
|
||
* Scan over the obstacle map.
|
||
* At the start of an obstacle, scan right to find the width
|
||
* of contiguous material on either or both of the layers.
|
||
* Set the obstacle width for every location in the horizontal
|
||
* strip just scanned.
|
||
*/
|
||
for (row = 1; row <= ch->gcr_width; row++)
|
||
{
|
||
for (col = 1; col <= ch->gcr_length; col++)
|
||
{
|
||
if (CLEAR(map[col][row])) continue;
|
||
|
||
/* Found an obstacle of some sort, so scan to its end */
|
||
for (start = col; col <= ch->gcr_length; col++)
|
||
if (CLEAR(map[col][row]))
|
||
break;
|
||
|
||
/* Set width values at every grid point touched in this column
|
||
* by the obstacle.
|
||
*/
|
||
n = col - start;
|
||
for (i = start; i < col; i++)
|
||
widths[i][row] = n;
|
||
}
|
||
}
|
||
|
||
return(widths);
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* rtrFindEnds --
|
||
*
|
||
* Given the top and bottom y values for an obstacle, extend left and right
|
||
* to find edges (isHoriz == TRUE).
|
||
*
|
||
* Given the left and right x values for an obstacle, extend up and down
|
||
* to find edges (isHoriz == FALSE).
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Returns the two values in * lo and * hi.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
rtrFindEnds(ch, isHoriz, bot, top, lo, hi)
|
||
GCRChannel *ch;
|
||
int isHoriz; /* 1 if to find horizontal ends */
|
||
int bot; /* Low range to be scanned */
|
||
int top; /* High range to be scanned */
|
||
int *lo; /* Low range of result. Also starting col or row. */
|
||
int *hi; /* High range of result */
|
||
{
|
||
int col, row;
|
||
short **map;
|
||
|
||
map = ch->gcr_result;
|
||
if (isHoriz)
|
||
{
|
||
/*
|
||
* Extend right, through contiguous vertical material from bot to top.
|
||
* In this and the next loop "bot" and "top" refer to the lower and
|
||
* upper ranges of the vertical strip whose left and right edges are
|
||
* sought.
|
||
*/
|
||
for (col = *lo + 1; col <= ch->gcr_length; col++)
|
||
for (row = bot; row <= top; row++)
|
||
if (CLEAR(map[col][row]))
|
||
goto gotHH;
|
||
|
||
gotHH:
|
||
/* Found the right edge of material */
|
||
*hi = col - 1;
|
||
|
||
/*
|
||
* Extend left, through contiguous vertical material
|
||
* from bot to top.
|
||
*/
|
||
for (col = *lo - 1; col > 0; col--)
|
||
for (row = bot; row <= top; row++)
|
||
if (CLEAR(map[col][row]))
|
||
goto gotHL;
|
||
|
||
gotHL:
|
||
/* Found the left edge of material */
|
||
*lo = col + 1;
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Extend up, through contiguous horizontal material from bot to top.
|
||
* In this and the next loop, "bot" and "top" actually refer to the
|
||
* left and right limits of the material whose end is sought.
|
||
*/
|
||
for (row = *lo + 1; row <= ch->gcr_width; row++)
|
||
for (col = bot; col <= top; col++)
|
||
if (CLEAR(map[col][row]))
|
||
goto gotVH;
|
||
gotVH:
|
||
/* Found the upper edge of material */
|
||
*hi = row - 1;
|
||
|
||
/*
|
||
* Extend down, through contiguous horizontal material
|
||
* from bot to top.
|
||
*/
|
||
for (row = *lo - 1; row > 0; row--)
|
||
for (col = bot; col <= top; col++)
|
||
if(CLEAR(map[col][row]))
|
||
goto gotVL;
|
||
gotVL:
|
||
/* Found the lower edge of material */
|
||
*lo = row + 1;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
*
|
||
* rtrFlag --
|
||
*
|
||
* 1. Set hazard flags in the channel flag array for a given hazard generating
|
||
* region and surrounding area. For horizontal regions (isHoriz==TRUE)
|
||
* set flags for left to right routing and for right to left routing.
|
||
* For vertical regions set flags for top to bottom routing and for
|
||
* bottom to top routing.
|
||
*
|
||
* For a given direction set the hazard flags in the region itself, in an
|
||
* area ahead of the region and on one track on either side of the region.
|
||
* The size of the area ahead of the region is a product of the height
|
||
* of the region and the global variable GCRObstDist.
|
||
*
|
||
* The boxed area generates flags in the area outlined in 'x'.
|
||
*
|
||
* xxxxxxxxxxxxxx xxxxxxxxxxxxxx
|
||
* --------- x ---------x ---------- x--------- x
|
||
* | | x | x | | x | x
|
||
* --------- x ---------x ---------- x--------- x
|
||
* xxxxxxxxxxxxxx xxxxxxxxxxxxxx
|
||
*
|
||
* 2. Set GCRHAZRD flags, obstacle size, and obstacle distance for each
|
||
* pin which falls in the shadow of a hazard. The size measure says how
|
||
* much material there is in the direction the net travels, while the
|
||
* distance measure says how far the material is from the pin. Obstacle
|
||
* information (for covered pins) is handled in another location.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
rtrFlag(ch, cl, cr, rb, rt, isHoriz)
|
||
GCRChannel * ch; /* Channel whose flag array is to be set */
|
||
int cl, cr; /* Left and right limits of columns to be set */
|
||
int rb, rt; /* Bottom and top limits of rows to be set */
|
||
bool isHoriz; /* TRUE if left/right flags, else top/bottom */
|
||
{
|
||
int extra, limit, r, c;
|
||
short ** map;
|
||
|
||
map = ch->gcr_result;
|
||
if(isHoriz)
|
||
{
|
||
extra = 0.99999 + GCRObstDist * (rt - rb + 1);
|
||
limit = cl - extra;
|
||
if(limit <= 0)
|
||
{
|
||
/* Hazard extends over the left edge of the channel. Mark the pins.
|
||
* When setting distance to the nearest obstacle, rely on the left to
|
||
* right sweep so the closest hazard is found first.
|
||
*/
|
||
for(r = rb - 1; r <= rt + 1; r++)
|
||
if(!ch->gcr_lPins[r].gcr_pFlags)
|
||
{
|
||
ch->gcr_lPins[r].gcr_pFlags = GCRHAZRD;
|
||
ch->gcr_lPins[r].gcr_pDist = cl;
|
||
ch->gcr_lPins[r].gcr_pSize = cr - cl;
|
||
}
|
||
limit = 0;
|
||
}
|
||
for(c = limit; c < cl; c++)
|
||
for(r = rb - 1; r <= rt + 1; r++)
|
||
map[c][r] |= GCRVL;
|
||
|
||
for(c = cl; c <= cr; c++)
|
||
for(r = rb - 1; r <= rb + 1; r++)
|
||
map[c][r] |= (GCRVL | GCRVR);
|
||
|
||
limit = cr + extra;
|
||
if(limit >= ch->gcr_length)
|
||
{
|
||
/* Hazard extends over the right edge of the channel. Mark the pins.
|
||
* When setting distance to the nearest obstacle, rely on the left to
|
||
* right sweep so the closest hazard is found last.
|
||
*/
|
||
for(r = rb - 1; r <= rt + 1; r++)
|
||
{
|
||
if(!ch->gcr_rPins[r].gcr_pFlags)
|
||
ch->gcr_rPins[r].gcr_pFlags = GCRHAZRD;
|
||
if(ch->gcr_rPins[r].gcr_pFlags == GCRHAZRD)
|
||
{
|
||
ch->gcr_rPins[r].gcr_pDist = ch->gcr_length - cr;
|
||
ch->gcr_rPins[r].gcr_pSize = cr - cl;
|
||
}
|
||
}
|
||
limit = ch->gcr_length;
|
||
}
|
||
for(c = cr + 1; c <= limit; c++)
|
||
for(r = rb - 1; r <= rt + 1; r++)
|
||
map[c][r] |= GCRVR;
|
||
}
|
||
else
|
||
{
|
||
extra = 0.99999 + GCRObstDist * (cr - cl + 1);
|
||
limit = rb - extra;
|
||
if(limit < 0)
|
||
{
|
||
/* Hazard extends over the bottom edge of the channel. Mark the pins.
|
||
*/
|
||
for(c = cl - 1; c <= cr + 1; c++)
|
||
if(!ch->gcr_bPins[c].gcr_pFlags)
|
||
{
|
||
ch->gcr_bPins[c].gcr_pFlags = GCRHAZRD;
|
||
ch->gcr_bPins[c].gcr_pDist = rb;
|
||
ch->gcr_bPins[c].gcr_pSize = rt - rb;
|
||
}
|
||
limit = 0;
|
||
}
|
||
for(r = limit; r < rb; r++)
|
||
for(c = cl - 1 ; c <= cr + 1; c++)
|
||
map[c][r] |= GCRVD;
|
||
|
||
for(r = rb; r <= rt; r++)
|
||
for(c = cl - 1; c <= cr + 1; c++)
|
||
map[c][r] |= (GCRVD | GCRVU);
|
||
|
||
limit = rt + extra;
|
||
if(limit >= ch->gcr_width)
|
||
{
|
||
/* Hazard extends over the top edge of the channel. Mark the pins.
|
||
*/
|
||
for(c = cl - 1; c <= cr + 1; c++)
|
||
{
|
||
if(!ch->gcr_tPins[c].gcr_pFlags)
|
||
ch->gcr_tPins[c].gcr_pFlags = GCRHAZRD;
|
||
if(ch->gcr_tPins[c].gcr_pFlags == GCRHAZRD)
|
||
{
|
||
ch->gcr_tPins[c].gcr_pDist = ch->gcr_width - rt;
|
||
ch->gcr_tPins[c].gcr_pSize = rt - rb;
|
||
}
|
||
}
|
||
limit = ch->gcr_width;
|
||
}
|
||
for(r = rt + 1; r <= limit; r++)
|
||
for(c = cl - 1 ; c <= cr + 1; c++)
|
||
map[c][r] |= GCRVU;
|
||
}
|
||
}
|