249 lines
7.2 KiB
C
249 lines
7.2 KiB
C
/* gcrFeas.c -
|
||
*
|
||
* The greed router: Making feasible top and bottom connections.
|
||
* This includes the initial attempt and widening if a
|
||
* connection could not be made.
|
||
*
|
||
* *********************************************************************
|
||
* * 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/gcrFeas.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/hash.h"
|
||
#include "database/database.h"
|
||
#include "router/router.h"
|
||
|
||
extern int gcrStandalone;
|
||
extern int gcrRouterErrors;
|
||
|
||
/* Forward declarations */
|
||
void gcrMakeFeasible();
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
* gcrFeasible --
|
||
*
|
||
* Make feasible top and bottom connections in a minimal manner, running
|
||
* to the first track that is either empty or already assigned to the net.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* *failedTop and *failedBot get set true or false, depending on whether
|
||
* the connections from the top and bottom are successful or not.
|
||
* Updates the structs for the nets to delete the pins.
|
||
* Updates the column data structure to reflect the track assignment.
|
||
* column[0].gcr_hi=column[width+1].gcr_lo=EMPTY at conclusion.
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
gcrFeasible(ch, col)
|
||
GCRChannel * ch;
|
||
int col; /* Column for feasible connections */
|
||
{
|
||
GCRColEl * column;
|
||
GCRNet * topNet, *botNet;
|
||
int i, topTarget, botTarget;
|
||
int failedTop;
|
||
int failedBot;
|
||
|
||
topNet=ch->gcr_tPins[col].gcr_pId;
|
||
botNet=ch->gcr_bPins[col].gcr_pId;
|
||
column=ch->gcr_lCol;
|
||
|
||
/* The order in which pins are unlinked is important. This is because
|
||
* the unlinker checks to see that pins are unlinked in order of their
|
||
* position on the list.
|
||
*/
|
||
gcrUnlinkPin(&ch->gcr_bPins[col]);
|
||
gcrUnlinkPin(&ch->gcr_tPins[col]);
|
||
|
||
if (topNet)
|
||
{
|
||
/* There is a top pin at this column */
|
||
failedTop=TRUE;
|
||
|
||
/* Look for the first track to which this net can run. It must either
|
||
* be empty or else already assigned to the topNet.
|
||
*/
|
||
for(i=ch->gcr_width; i>0; i--)
|
||
if(gcrBlocked(column, i, topNet, 0))
|
||
break;
|
||
else
|
||
if((column[i].gcr_h==(GCRNet *) NULL) || (column[i].gcr_h==topNet))
|
||
{
|
||
topTarget=i;
|
||
failedTop=FALSE;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
failedTop=FALSE;
|
||
|
||
if(botNet!=(GCRNet *) NULL)
|
||
{
|
||
failedBot=TRUE;
|
||
column[0].gcr_lo=column[0].gcr_hi= EMPTY;
|
||
for(i=1; i<=ch->gcr_width; i++)
|
||
if(gcrBlocked(column, i, botNet, ch->gcr_width))
|
||
break;
|
||
else
|
||
if((column[i].gcr_h==(GCRNet *) NULL) || (column[i].gcr_h==botNet))
|
||
{
|
||
botTarget= i;
|
||
failedBot=FALSE;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
failedBot=FALSE;
|
||
|
||
/* If there are no empty tracks and net topNet==botNet!=0 is a net which
|
||
* has connections in this column only, then run a vertical wire from top
|
||
* to bottom of this column.
|
||
*/
|
||
if( failedTop && failedBot &&
|
||
(topNet==botNet) && (topNet!=(GCRNet *) NULL) &&
|
||
(topNet->gcr_lPin==(GCRPin *) NULL) )
|
||
{
|
||
/* ... but only do this if there isn't some block */
|
||
for(i = 1; i <= ch->gcr_width; i++)
|
||
if(gcrBlocked(column, i, botNet, ch->gcr_width)) return;
|
||
gcrMoveTrack(column, topNet, ch->gcr_width+1, 0);
|
||
failedBot= failedTop=FALSE;
|
||
}
|
||
else
|
||
|
||
/* If there is a conflict in the wiring, then just wire the one with the
|
||
* shortest connection.
|
||
*/
|
||
if( !(failedBot) && (topNet!=(GCRNet *) NULL) &&
|
||
!(failedTop) && (botNet!=(GCRNet *) NULL) && (botTarget>=topTarget) )
|
||
if(topNet==botNet)
|
||
{
|
||
gcrMakeFeasible(column, topNet, ch->gcr_width+1, topTarget,
|
||
ch->gcr_width);
|
||
gcrMakeFeasible(column, botNet, 0, botTarget, ch->gcr_width);
|
||
gcrWanted(ch, topTarget, col);
|
||
}
|
||
else
|
||
if( botTarget > (ch->gcr_width-topTarget-1) )
|
||
{
|
||
gcrMakeFeasible(column, topNet, ch->gcr_width+1, topTarget,
|
||
ch->gcr_width);
|
||
failedBot=TRUE;
|
||
gcrWanted(ch, topTarget, col);
|
||
}
|
||
else
|
||
{
|
||
gcrMakeFeasible(column, botNet, 0, botTarget, ch->gcr_width);
|
||
failedTop=TRUE;
|
||
gcrWanted(ch, botTarget, col);
|
||
}
|
||
else
|
||
|
||
/* Make successful connections. Leave unsuccessful connections for later. */
|
||
{
|
||
if( (! failedTop) && (topNet!=(GCRNet *) NULL) )
|
||
{
|
||
gcrMakeFeasible(column, topNet, ch->gcr_width+1, topTarget,
|
||
ch->gcr_width);
|
||
gcrWanted(ch, topTarget, col);
|
||
}
|
||
if( (! failedBot) && (botNet!=(GCRNet *) NULL) )
|
||
{
|
||
gcrMakeFeasible(column, botNet, 0, botTarget, ch->gcr_width);
|
||
gcrWanted(ch, botTarget, col);
|
||
}
|
||
}
|
||
if(failedTop)
|
||
{
|
||
RtrChannelError(ch, col, ch->gcr_width,
|
||
"Can't make top connection",
|
||
ch->gcr_tPins[col].gcr_pId->gcr_Id);
|
||
gcrRouterErrors++;
|
||
}
|
||
if(failedBot)
|
||
{
|
||
RtrChannelError(ch, col, 1, "Can't make bottom connection",
|
||
ch->gcr_bPins[col].gcr_pId->gcr_Id);
|
||
gcrRouterErrors++;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* ----------------------------------------------------------------------------
|
||
* gcrMakeFeasible --
|
||
*
|
||
* Run a feasible connection from the bottom or top to the given target
|
||
* track.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Have to fiddle around with column[0] and column[width+1].
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
gcrMakeFeasible(col, net, from, target, width)
|
||
GCRColEl * col; /* Describes current column structure. */
|
||
GCRNet * net; /* Net being brought into column. */
|
||
int from; /* Pin location for net (0 or width+1). */
|
||
int target; /* Target track for net. */
|
||
int width; /* Width of column. */
|
||
{
|
||
int i;
|
||
|
||
/* Find the index of the first track occupied by net. Pass it to
|
||
* gcrMoveTrack through column[from].gcr_lo or gcr_hi.
|
||
*/
|
||
col[from].gcr_lo=col[from].gcr_hi= EMPTY;
|
||
if(col[target].gcr_h==net) /*run to occupied track*/
|
||
{
|
||
col[from].gcr_lo= col[target].gcr_lo;
|
||
col[from].gcr_hi= col[target].gcr_hi;
|
||
}
|
||
else
|
||
if(from!=0) /*Run to empty track. Connect from the top*/
|
||
for(i=target-1; i>0; i--)
|
||
if(col[i].gcr_h==net)
|
||
{
|
||
col[from].gcr_lo=i;
|
||
col[i].gcr_hi=target;
|
||
break;
|
||
}
|
||
else /*nothing*/;
|
||
else /*Run to empty track. Connect from bottom.*/
|
||
for(i=target+1; i<=width; i++)
|
||
if(col[i].gcr_h==net)
|
||
{
|
||
col[0].gcr_hi=i;
|
||
col[i].gcr_lo=target;
|
||
break;
|
||
}
|
||
gcrMoveTrack(col, net, from, target);
|
||
col[from].gcr_lo=col[from].gcr_hi= EMPTY;
|
||
}
|