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