magic/gcr/gcrLib.c

457 lines
10 KiB
C
Raw Normal View History

/* gcrLib.c -
*
* Miscellaneous stuff for the greedy router.
*
* *********************************************************************
* * 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/gcr/gcrLib.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 */
void gcrUnlinkTrack();
/*
* ----------------------------------------------------------------------------
*
* gcrBlocked --
*
* See if a given location is blocked for a vertical run.
*
* Results:
* TRUE if the location is blocked.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
bool
gcrBlocked(col, i, net, last)
GCRColEl *col; /* Current column information */
int i; /* Which element */
GCRNet *net; /* Net we're interested in processing: locations
* that already contain this net aren't considered
* to be blocked; all others are.
*/
int last;
{
GCRColEl *colptr = &col[i];
/* True if already wired vertically */
if (colptr->gcr_v != net && colptr->gcr_v)
return (TRUE);
/* True if column ended */
if ((colptr->gcr_flags & GCRCE) && i != last && colptr->gcr_h != net)
return (TRUE);
/* True if poly and metal blocked and not this net */
if ((colptr->gcr_flags & (GCRBLKP|GCRBLKM|GCRCC))
&& colptr->gcr_h && colptr->gcr_h != net)
return (TRUE);
/* Blocked if there's a contact there */
if (colptr->gcr_flags & GCRX)
return (TRUE);
/* All clear */
return (FALSE);
}
/*
* ----------------------------------------------------------------------------
*
* gcrMoveTrack --
*
* Move a net to a new track. Add it to the occupied net list for the
* given net. If the destination track belongs to the same net, then
* just remove the duplicate.
*
* Results:
* None.
*
* Side effects:
* Adds vertical paint for the track.
*
* ----------------------------------------------------------------------------
*/
void
gcrMoveTrack(column, net, from, to)
GCRColEl * column;
GCRNet * net; /* Net to be assigned to a track */
int from;
int to;
{
int i, last;
/* Paint vertical segments. Delete tracks already assigned to this net */
if(from==to)
return;
if(net==(GCRNet *) NULL)
if(column[from].gcr_wanted!=(GCRNet *) NULL)
net=column[from].gcr_wanted;
last=from;
if(from<to) /* Paint an ascending jog into the column */
{
for(i=from+1; i<to; i++)
{
/* Paint a vertical segment. Free intermediate tracks assigned to
* to the net, unless those tracks are needed for right edge pins.
*/
column[i].gcr_v=net;
if(column[i].gcr_h==net)
{
if(column[i].gcr_wanted!=net)
gcrUnlinkTrack(column, i);
else
{
column[ i].gcr_lOk=TRUE;
column[last].gcr_hOk=TRUE;
last=i;
}
}
if(column[i].gcr_flags&GCRCC)
column[i].gcr_flags|=(GCRX|GCRBLKM|GCRBLKP);
}
/* Added to fix the track extension bug */
if((column[to].gcr_wanted==net) ||
(!column[to].gcr_hOk && !column[to].gcr_lOk))
column[to].gcr_h=net;
else
{
column[to].gcr_h=(GCRNet *) NULL;
column[to].gcr_hOk=FALSE;
column[to].gcr_lOk=FALSE;
column[to].gcr_hi=column[to].gcr_lo= EMPTY;
}
if(column[from].gcr_wanted!=net)
{
/* Replace the "from" track with the "to" track*/
column[to].gcr_lo=column[from].gcr_lo;
if(column[from].gcr_lo!= EMPTY)
column[column[from].gcr_lo].gcr_hi=to;
if(to<column[from].gcr_hi)
{
column[to].gcr_hi=column[from].gcr_hi;
if(column[from].gcr_hi!= EMPTY)
column[column[from].gcr_hi].gcr_lo=to;
}
column[from].gcr_lo=column[from].gcr_hi= EMPTY;
}
else
{
column[from].gcr_hi=to;
column[to ].gcr_lo=from;
column[from].gcr_hOk=TRUE;
column[to ].gcr_lOk=TRUE;
}
}
else
{
for(i=from-1; i>to; i--) /*Paint a descending vertica jog*/
{
column[i].gcr_v=net;
if(column[i].gcr_h==net)
{
if(column[i].gcr_wanted!=net)
gcrUnlinkTrack(column, i);
else
{
column[last].gcr_lOk=TRUE;
column[ i].gcr_hOk=TRUE;
last=i;
}
}
if(column[i].gcr_flags&GCRCC)
column[i].gcr_flags|=(GCRX|GCRBLKM|GCRBLKP);
}
/* Added to fix the track extension bug */
if((column[to].gcr_wanted==net) ||
(!column[to].gcr_hOk && !column[to].gcr_lOk))
column[ to].gcr_h=net;
else
{
column[to].gcr_h=(GCRNet *) NULL;
column[to].gcr_hOk=FALSE;
column[to].gcr_lOk=FALSE;
column[to].gcr_hi=column[to].gcr_lo= EMPTY;
}
if(column[from].gcr_wanted!=net)
{
column[to].gcr_hi=column[from].gcr_hi;
if(column[from].gcr_hi!= EMPTY)
column[column[from].gcr_hi].gcr_lo=to;
if(column[from].gcr_lo<to)
{
column[to].gcr_lo=column[from].gcr_lo;
if(column[from].gcr_lo!= EMPTY)
column[column[from].gcr_lo].gcr_hi=to;
}
column[from].gcr_lo=column[from].gcr_hi= EMPTY;
}
else
{
column[from].gcr_lo=to;
column[to ].gcr_hi=from;
column[from].gcr_lOk=TRUE;
column[to ].gcr_hOk=TRUE;
}
}
column[from].gcr_v=net; /*Paint a vertical segment */
column[ to].gcr_v=net;
/* Don't free a track that is needed for a right or left edge connection
*/
if(column[from].gcr_wanted!=net)
{
column[from].gcr_h=(GCRNet *) NULL;
column[from].gcr_hOk=FALSE;
column[from].gcr_lOk=FALSE;
column[from].gcr_hi=column[from].gcr_lo= EMPTY;
}
}
/*
* ----------------------------------------------------------------------------
*
* gcrUnlinkTrack --
*
* Unlink a track from the linked list for the net. This involves
* updating the two-way links for the column element and its next
* and previous list element.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrUnlinkTrack(col, toUnlink)
GCRColEl *col;
int toUnlink;
{
GCRColEl *colPtr = &col[toUnlink];
if (colPtr->gcr_hi != EMPTY)
col[colPtr->gcr_hi].gcr_lo = colPtr->gcr_lo;
if (colPtr->gcr_lo != EMPTY)
col[colPtr->gcr_lo].gcr_hi = colPtr->gcr_hi;
colPtr->gcr_lo = colPtr->gcr_hi = EMPTY;
colPtr->gcr_h = (GCRNet *) NULL;
}
/*
* ----------------------------------------------------------------------------
*
* gcrShellSort --
*
* The shell sort from page 116 of Kernighan and Ritchie. Sorts in
* increasing or decreasing order, depending on whether the flag is set.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
gcrShellSort(v, n, isUp)
GCRNet **v;
int n;
bool isUp;
{
int gap, i, j, a1, a2;
GCRNet * net;
for(gap=n/2; gap>0; gap/=2)
for(i=gap; i<n; i++)
for(j=i-gap; j>=0; j-=gap)
{
a1=v[ j]->gcr_sortKey;
a2=v[j+gap]->gcr_sortKey;
if(isUp)
if(a1>a2)
{
net=v[j+gap];
v[j+gap]=v[j];
v[j]=net;
}
else ;
else
if(a1<a2)
{
net=v[j+gap];
v[j+gap]=v[j];
v[j]=net;
}
}
}
/*
* ----------------------------------------------------------------------------
*
* gcrVertClear --
*
* See if there is a clear run from "from" to "to" in the given column.
*
* Results:
* Return TRUE if clear, else FALSE.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
bool
gcrVertClear(col, from, to)
GCRColEl * col;
int from;
int to;
{
int i, flags;
GCRNet * net;
net=col[from].gcr_h;
if(from>to)
{
i=from;
from=to;
to=i;
}
for(i=from; i<=to; i++)
{
flags=col[i].gcr_flags;
if((col[i].gcr_v!=net)&&(col[i].gcr_v!=(GCRNet *) NULL))
return(FALSE); /* Already wired vertically */
else
if((flags & GCRCE) && (i!=to))
return(FALSE); /* Column ended */
else
if( (flags & (GCRBLKP|GCRBLKM|GCRX|GCRCC)) &&
(col[i].gcr_h!=net) && (col[i].gcr_h!=(GCRNet *) NULL) )
return(FALSE); /* Poly and metal blocked */
}
return(TRUE);
}
/*
* ----------------------------------------------------------------------------
*
* gcrCopyCol --
*
* Make a copy of the given column array.
*
* Results:
* A pointer to a newly malloc'ed column array of the given size.
*
* Side effects:
* Allocates memory.
*
* ----------------------------------------------------------------------------
*/
GCRColEl *
gcrCopyCol(col, size)
GCRColEl *col;
int size;
{
GCRColEl * result;
int i, limit;
result = (GCRColEl *) mallocMagic((unsigned) ((size+2) * sizeof (GCRColEl)));
limit = size + 2;
for (i = 0; i < limit; i++)
result[i] = col[i];
return (result);
}
/*
* ----------------------------------------------------------------------------
*
* gcrLinkTrack --
*
* Establishes hi and lo links when a net gets assigned to a track
* the hard way.
*
* Results:
* None.
*
* Side effects:
* Changes links in the column.
*
* ----------------------------------------------------------------------------
*/
void
gcrLinkTrack(col, net, track, width)
GCRColEl *col;
GCRNet *net;
int track, width;
{
int i;
ASSERT(col[track].gcr_hi == EMPTY, "LinkTrack");
ASSERT(col[track].gcr_lo == EMPTY, "LinkTrack");
col[track].gcr_h = net;
col[track].gcr_hi = EMPTY;
for (i = track + 1; i <= width; i++)
if (col[i].gcr_h == net)
{
col[track].gcr_hi = i;
col[i].gcr_lo = track;
break;
}
col[track].gcr_lo = EMPTY;
for (i = track - 1; i > 0; i--)
if (col[i].gcr_h == net)
{
col[track].gcr_lo = i;
col[i].gcr_hi = track;
break;
}
}