/* 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 #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(fromto; 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_logcr_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=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(a1to) { 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; } }