magic/router/rtrHazards.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;
}
}