magic/gcr/gcrFeas.c

249 lines
7.1 KiB
C
Raw Normal View History

/* 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;
}