assigncells_to_parts() { static int tile,cell; static PTILEPTR tileptr; for (tile = 1; tile <= num_ptileG; tile++) { tileptr = tarrayG[tile]; if (tileptr->legal || tileptr->capacity == 0) continue; part = tileptr->partition_id; partptr = partarrayG[part]; if (!partptr->carray){ partptr->carray = (CBOXPTR *) Ysafe_malloc( (tileptr->cells +1) * sizeof( CBOXPTR ) ) ; } else { partptr->carray = (CBOXPTR *) Ysafe_realloc(partptr->carray, (partptr->cells + tileptr->cells +1) *sizeof( CBOXPTR ) ) ; } for (cell = 1; cell <= tileptr->cells; cell++) { partptr->cells++; partptr->carray[partptr->cells] = (CBOXPTR) Ysafe_malloc( sizeof(CBOX) ); partptr->carray[partptr->cells] = tileptr->carray[cell]; } partptr->celllen += tileptr->celllen; } }
/*===================================================================== * This function makes an array for the netlist for quick access. =====================================================================*/ void assign_net_internal() { int i; int j; int length; NETDRPTR Pnet; OFSETPTR Pedge; Pnet = netlist; narray = (NETDRPTR *) Ysafe_malloc((numnets+1) * sizeof(NETDRPTR)); for (i = 1; i <= numnets; i++) { narray[i] = Pnet; length = Pnet->num_of_routes; for (j = 1; j <= length; j++) { Pedge = Pnet->Aroute[j]->Pedge; while (Pedge) { Pedge->width = dearray[Pedge->edge]->width; Pedge = Pedge->next; } } Pnet = Pnet->next; } return; } /* end of assign_net */
void set_cedgebin() { CBOXPTR cellptr ; INT channel , row , bin , bin_rite_edge , crite ; INT most_left , most_rite , rite , i ; cedgebinS = (INT **)Ysafe_malloc( ( numChansG + 1 ) * sizeof(INT *) ) ; cedge_binwidthS = (INT)( 2.0 * mean_widthG ) ; cellptr = carrayG[ pairArrayG[1][ pairArrayG[1][0] ] ] ; most_rite = cellptr->cxcenter + cellptr->tileptr->right ; for( row = 2 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; rite = cellptr->cxcenter + cellptr->tileptr->right ; if( rite > most_rite ) { most_rite = rite ; } } num_edgebinS = ( most_rite - blkleftG ) / cedge_binwidthS + 1 ; for( channel = 1 ; channel <= numChansG ; channel++ ) { cedgebinS[ channel ] = (INT *)Ysafe_malloc( ( num_edgebinS + 1 ) * sizeof( INT ) ) ; } for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][1] ] ; most_left = cellptr->cxcenter + cellptr->tileptr->left ; bin_rite_edge = most_left + cedge_binwidthS ; cedgebinS[row][1] = 1 ; bin = 1 ; for( i = 1 ; i <= pairArrayG[row][0] ; i++ ) { cellptr = carrayG[ pairArrayG[row][i] ] ; crite = cellptr->cxcenter + cellptr->tileptr->right ; if( bin_rite_edge < crite ) { while( bin_rite_edge <= crite ) { cedgebinS[row][++bin] = i ; bin_rite_edge += cedge_binwidthS ; } } } for( ++bin ; bin <= num_edgebinS ; bin++ ) { cedgebinS[row][bin] = 0 ; } } }
init_unet() { INT maxpin, get_max_pin() ; maxpin = get_max_pin() ; memoptrS = (PINBOXPTR *) Ysafe_malloc( (++maxpin) * sizeof(PINBOXPTR) ) ; } /* end init_unet */
sortpin() { INT cell ; /* current cell */ INT maxpins ; /* maximum numpins over all pins */ CBOXPTR ptr ; /* current cell */ BOOL pin_groups ; /* true if swappable gates occur */ /* find the maximum number of pins on a cell for allocation */ /* also see if pin groups exist on any of the cells */ maxpins = INT_MIN ; pin_groups = FALSE ; for( cell = 1; cell <= numcellsG; cell++ ){ ptr = carrayG[cell] ; maxpins = MAX( ptr->numterms, maxpins ) ; if( ptr->num_pin_group > 0 ){ pin_groups = TRUE ; } } sortArrayS = (PINBOXPTR *) Ysafe_malloc( (maxpins+2)*sizeof(PINBOXPTR) ); for( cell = 1 ; cell <= numcellsG ; cell++ ) { sortpin1( cell ) ; } if( pin_groups ){ /* we we have swappable gates we need to create second array */ /* and leave first one allocated */ sortArraySwapS = (PINBOXPTR *) Ysafe_malloc( (maxpins+2)*sizeof(PINBOXPTR) ); } else { /* in the normal case we are done with sorting free array */ Ysafe_free( sortArrayS ) ; } } /* end sortpin */
MDATAPTR make_node() { MDATAPTR node ; if (Phead) { node = Phead ; Phead = Phead->next ; } else { node = (MDATAPTR) Ysafe_malloc(sizeof(MDATA)) ; } return(node) ; } /* end of make_node */
void sortpins() { INT j , n , cell ; CELLBOXPTR ptr ; PINBOXPTR pin, *xpptr ; /* static INT comparePin() ;*/ INT maxpins ; /* find maximum number of pins on a cell for allocation */ maxpins = INT_MIN ; for( cell = 1 ; cell <= totalcellsG ; cell++ ) { ptr = cellarrayG[ cell ] ; maxpins = MAX( ptr->numpins, maxpins ) ; } /* allocate array for sort */ xpptr = (PINBOXPTR *) Ysafe_malloc((maxpins+1) * sizeof(PINBOXPTR) ) ; /* now go thru all cells sorting pins */ for( cell = 1 ; cell <= totalcellsG ; cell++ ) { ptr = cellarrayG[ cell ] ; n = 0 ; for( pin = ptr->pinptr ; pin ; pin = pin->nextpin ) { xpptr[ n++ ] = pin ; } /* net number then by pin name */ Yquicksort( (char *)xpptr, n, sizeof(PINBOXPTR),comparePin ) ; /* terminate list */ xpptr[ n ] = NIL(PINBOXPTR) ; ptr->pinptr = xpptr[ 0 ] ; for( j = 0 ; j < n ; j++ ) { xpptr[j]->nextpin = xpptr[j+1] ; } } Ysafe_free( xpptr ) ; } /* end sortpins */
void make_arrays() { register int number ; number = h_numnodes ; Adist = (int *) Ysafe_malloc( number * sizeof(int) ) ; Amember = (int *) Ysafe_malloc( number * sizeof(int) ) ; h_parent = (int *) Ysafe_malloc( number * sizeof(int) ) ; v_parent = (int *) Ysafe_malloc( number * sizeof(int) ) ; Aqueue = (int *) Ysafe_malloc( number * sizeof(int) ) ; h_critical = (char *) Ysafe_malloc( (numedges+1) * sizeof(char) ) ; v_critical = (char *) Ysafe_malloc( (numedges+1) * sizeof(char) ) ; for( number = 1 ; number <= numedges ; number++ ) { h_critical[number] = FALSE ; v_critical[number] = FALSE ; } } /* end of make_arrays */
findcostf() { TIBOXPTR tileptr1 ; CBOXPTR cellptr1 ; BINPTR bptr ; INT left , right ; INT bin , LoBin , HiBin ; INT block , cell , blk ; INT startx , endx ; INT cost ; INT k , cbin , row ; blkleftG = INT_MAX ; blkriteG = INT_MIN ; for( block = 1 ; block <= numRowsG ; block++ ) { if( barrayG[ block ]->bxcenter + barrayG[ block ]->bleft < blkleftG ) { blkleftG = barrayG[ block ]->bxcenter + barrayG[ block ]->bleft ; } if( barrayG[ block ]->bxcenter + barrayG[ block ]->bright > blkriteG ) { blkriteG = barrayG[ block ]->bxcenter + barrayG[ block ]->bright ; } } binOffstG = blkleftG ; max_blklengthG = blkriteG - blkleftG ; old_numBinS = numBinsG ; numBinsG = (INT)( ( blkriteG - binOffstG ) / binWidthG ) ; if( ( blkriteG - binOffstG ) > ( numBinsG * binWidthG ) ) { numBinsG++ ; } if( numBinsG > old_numBinS ) { for( row = 1 ; row <= numRowsG ; row++ ) { bin_configG[row] = (INT *) Ysafe_realloc( bin_configG[row] , (1 + numBinsG) * sizeof(INT) ) ; for( bin = old_numBinS + 1 ; bin <= numBinsG ; bin++ ) { bin_configG[row][bin] = 0 ; } } } cost = recompute_wirecost() ; binpenalG = 0 ; rowpenalG = 0 ; penaltyG = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= old_numBinS ; bin++ ) { Ysafe_free( binptrG[block][bin]->cell ) ; Ysafe_free( binptrG[block][bin] ) ; } Ysafe_free( binptrG[block] ) ; } for( block = 1 ; block <= numRowsG ; block++ ) { binptrG[block] = (BINPTR * ) Ysafe_malloc( (numBinsG + 1) * sizeof( BINPTR ) ) ; left = barrayG[ block ]->bleft + barrayG[ block ]->bxcenter ; right = barrayG[ block ]->bleft + barrayG[ block ]->bxcenter + barrayG[ block ]->desire ; /* set barray->oldsize to zero for upcoming calculation */ barrayG[ block ]->oldsize = 0 ; LoBin = SetBin( left ) ; HiBin = SetBin( right ) ; for( bin = 0 ; bin <= numBinsG ; bin++ ) { binptrG[block][bin] = (BINBOX *) Ysafe_malloc( sizeof(BINBOX) ) ; binptrG[block][bin]->cell = (INT *)Ysafe_malloc( 10 * sizeof(INT) ); bptr = binptrG[block][bin] ; bptr->cell[0] = 0 ; bptr->right = binOffstG + bin * binWidthG ; bptr->left = bptr->right - binWidthG ; if( bin == LoBin ) { bptr->penalty = left - bptr->right ; } else if( bin == HiBin ) { bptr->penalty = bptr->left - right ; } else if( bin > HiBin || bin < LoBin ) { bptr->penalty = 0 ; } else { bptr->penalty = - binWidthG ; } } } installf() ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { cellptr1 = carrayG[ cell ] ; tileptr1 = cellptr1->tileptr ; block = cellptr1->cblock ; startx = cellptr1->cxcenter + tileptr1->left ; endx = cellptr1->cxcenter + tileptr1->right ; barrayG[block]->oldsize += endx - startx ; cbin = SetBin( cellptr1->cxcenter ) ; LoBin = SetBin( startx ) ; HiBin = SetBin( endx ) ; k = ++(binptrG[block][cbin]->cell[0]) ; if( k % 10 == 0 ) { binptrG[block][cbin]->cell = (INT *) Ysafe_realloc( binptrG[block][cbin]->cell, (k + 10) * sizeof( INT ) ) ; } binptrG[block][cbin]->cell[k] = cell ; if( LoBin == HiBin ) { binptrG[block][LoBin]->penalty += ( endx - startx ) ; } else { bptr = binptrG[block][LoBin] ; bptr->penalty += ( bptr->right - startx ) ; bptr = binptrG[block][HiBin] ; bptr->penalty += ( endx - bptr->left ) ; if( LoBin + 1 < HiBin ) { for( bin = LoBin + 1 ; bin <= HiBin - 1 ; bin++ ) { binptrG[block][bin]->penalty += binWidthG ; } } } } for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { binpenalG += ABS( binptrG[block][bin]->penalty ) ; } } for( blk = 1 ; blk <= numRowsG ; blk++ ) { rowpenalG += ABS(barrayG[blk]->oldsize - barrayG[blk]->desire) ; } penaltyG = (INT)( binpenConG * (DOUBLE) binpenalG + roLenConG * (DOUBLE) rowpenalG ) ; timingcostG = recompute_timecost() ; return( cost ) ; }
findrcost() { SEGBOXPTR segptr ; CHANGRDPTR gdptr ; DENSITYPTR *hdptr , headptr , dptr ; INT chan ; INT trackG , max_trk , k ; INT net ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ initial_tracks( segptr ) ; } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 0 ) ; } } DboxHeadG = ( DENSITYPTR ** )Ysafe_calloc( numChansG + 1, sizeof( DENSITYPTR * ) ) ; maxTrackG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; nmaxTrackG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; max_tdensityG = 0 ; tracksG = 0 ; if( uneven_cell_heightG ) { set_cedgebin( ) ; reset_track( ) ; } for( chan = 1 ; chan <= numChansG ; chan++ ) { max_trk = 0 ; for( gdptr = BeginG[ chan ] ; gdptr != GRDNULL ; gdptr = gdptr->nextgrd ) { if( gdptr->tracks > max_trk ) { max_trk = gdptr->tracks ; } } maxTrackG[ chan ] = max_trk ; if( max_trk > max_tdensityG ) { max_tdensityG = max_trk ; } tracksG += max_trk ; } printf(" the starting value of tracks = %4d\n" , tracksG ) ; k = max_tdensityG + 100 ; for( chan = 1 ; chan <= numChansG ; chan++ ) { DboxHeadG[ chan ] = hdptr = ( DENSITYPTR *)Ysafe_calloc( k + 1, sizeof( DENSITYPTR) ) ; for( trackG = 0 ; trackG <= k ; trackG++ ) { hdptr[trackG] = ( DENSITYPTR )Ysafe_calloc( 1, sizeof(DENSITYBOX)); } for( gdptr = BeginG[ chan ] ; gdptr ; gdptr = gdptr->nextgrd ) { trackG = gdptr->tracks ; gdptr->dptr = dptr = ( DENSITYPTR )Ysafe_calloc( 1,sizeof(DENSITYBOX) ) ; headptr = hdptr[trackG] ; if( headptr->next ) { dptr->next = headptr->next ; dptr->next->back = dptr ; headptr->next = dptr ; dptr->back = headptr; } else { headptr->next = dptr ; dptr->back = headptr ; } dptr->grdptr = gdptr ; } } }
findcost() { INT block , bin ; FILE *fp ; TIBOXPTR tile , tileptr1 ; CBOXPTR cellptr1 , ptr ; DBOXPTR dimptr ; PINBOXPTR netptr , termptr ; BINPTR bptr ; char filename[256] ; INT left , right , corient , val ; INT LoBin , HiBin ; INT cell , net , blk ; INT startx , endx ; INT x , y , t , cost=0 ; INT temp , n , k , cbin ; INT sum, npins ; INT net_pin_num[ MAXNUMPINS + 1 ] , *adjust_left ; DOUBLE deviation ; INT pathcount , shortest_cell , count, length ; INT layer ; PATHPTR path ; GLISTPTR net_of_path ; extern char *find_layer() ; char *pinname ; blkleftG = INT_MAX ; blkriteG = INT_MIN ; adjust_left = (INT *)Ysafe_malloc( ( numRowsG + 1 ) * sizeof(INT) ) ; for( block = 1 ; block <= numRowsG ; block++ ) { /* ------------- finding the absolute left (blkleftG) and ----------- ------------- the absolute right (blkriteG) positions ----------- */ if( barrayG[ block ]->bxcenter + barrayG[ block ]->bleft < blkleftG ) { blkleftG = barrayG[ block ]->bxcenter + barrayG[ block ]->bleft ; } if( barrayG[ block ]->bxcenter + barrayG[ block ]->bright > blkriteG ) { blkriteG = barrayG[ block ]->bxcenter + barrayG[ block ]->bright ; } adjust_left[ block ] = INT_MAX ; } binOffstG = blkleftG ; max_blklengthG = blkriteG - blkleftG ; deviation = 0 ; temp = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { temp += carrayG[ cell ]->clength ; } mean_widthG = temp / (numcellsG - extra_cellsG) ; fprintf(fpoG,"Original Average Cell Width:%f\n", mean_widthG ) ; /* modification by Carl 10/5/89 */ /* an attempt to rectify a large cell problem */ shortest_cell = INT_MAX ; count = 0 ; temp = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cclass < 0 ) { continue ; } count++ ; if( carrayG[cell]->clength <= 2.0 * mean_widthG ) { temp += carrayG[ cell ]->clength ; } if( carrayG[cell]->clength < shortest_cell ) { shortest_cell = carrayG[cell]->clength ; } } if( gate_arrayG && rigidly_fixed_cellsG ) { mean_widthG = shortest_cell ; } else { if( count > 0 ) { mean_widthG = temp / count ; } else { /* this is only used if all cells are fixed */ count = 0 ; temp = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { count++ ; temp += carrayG[ cell ]->clength ; } mean_widthG = temp / count ; } } fprintf(fpoG,"Adjusted Average Cell Width:%f\n", mean_widthG ) ; t = 0 ; for( cell = numcellsG + 1 ; cell <= lastpadG ; cell++ ) { t += carrayG[cell]->numterms ; } /* New by Carl 9/11/89 to get the proper pin sep avg's */ temp = 0 ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { temp += carrayG[cell]->clength ; } /* **** */ average_pin_sepG = temp / ( maxtermG - t ) ; if( implicit_feed_countG ) { average_feed_sepG = temp / implicit_feed_countG ; if( average_feed_sepG > 4 * average_pin_sepG ) { average_feed_sepG = 4 * average_pin_sepG ; } } else { average_feed_sepG = 4 * average_pin_sepG ; } #ifdef MITLL average_feed_sep *= 2 ; #endif for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { deviation += ( carrayG[ cell ]->clength - mean_widthG ) * ( carrayG[ cell ]->clength - mean_widthG ) ; } deviation = sqrt( deviation / (numcellsG - extra_cellsG) ) ; binWidthG = ( INT ) ( mean_widthG ) ; if(!(Equal_Width_CellsG)){ while (1) { numBinsG = ( blkriteG - binOffstG ) / binWidthG ; if( ( blkriteG - binOffstG ) > ( numBinsG * binWidthG ) ) { numBinsG++ ; } if( (DOUBLE) (numBinsG * numRowsG - (numcellsG - extra_cellsG) ) / (DOUBLE)(numcellsG - extra_cellsG) > EXTRA_BIN) break; binWidthG --; } } else { while ( (numBinsG * numRowsG) < (numcellsG - extra_cellsG) ){ numBinsG++ ; } } fprintf( fpoG , "numBinsG automatically set to:%d\n", numBinsG); fprintf( fpoG , "binWidthG = %d\n",binWidthG ) ; fprintf( fpoG , "average_cell_width is:%g\n",mean_widthG ) ; fprintf( fpoG , "standard deviation of cell length is:%g\n", deviation ) ; if( gate_arrayG ) { cells_per_clusterG = 1 ; num_clustersG = extra_cellsG / cells_per_clusterG ; cluster_widthG = cells_per_clusterG * spacer_widthG ; fprintf(fpoG,"\nAdded %d spacer clusters to the gate array\n", num_clustersG); fprintf(fpoG,"cluster width: %d\n", cluster_widthG ) ; } else { num_clustersG = 0 ; } minxspanG = (INT)(mean_widthG + 3.0 * deviation) ; #ifdef OLD_WAY if( gate_arrayG ) { minxspanG = (INT)(mean_widthG + 4.0 * deviation) ; /* factor = 0.0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cclass < 0 ) { factor += (DOUBLE) carrayG[cell]->clength ; } } factor += (DOUBLE)(num_clusters * cluster_width) ; if( total_row_length > (INT) factor ) { factor = (DOUBLE) total_row_length / ((DOUBLE) total_row_length - factor) ; factor = (DOUBLE) minxspanG * factor ; fprintf(fpoG,"\nminxspanG INCREASED from %d to %d\n", minxspanG,(INT)factor); minxspanG = (INT) factor ; } else { fprintf(fpoG,"\nSTRANGE COMPUTATION OF MINXSPAN IN FINDCOST\n"); minxspanG *= 3 ; } */ } #endif /* OLD_WAY */ /*********************************************************** */ if( connection_machineG != 3 ) { sprintf( filename , "%s.res" , cktNameG ) ; fp = TWOPEN( filename , "r", NOABORT) ; } else { sprintf( filename , "%s.cmi" , cktNameG ) ; fp = TWOPEN ( filename , "r", ABORT ) ; } if( !(fp) ) { /* * Could not open the file cktName.res */ if( resume_runG == YES ) { fprintf(fpoG,"Could not use resume file: %s ", filename ) ; fprintf(fpoG,"since it could not be found\n"); } else { fprintf(fpoG,"TimberWolfSC starting from the beginning\n"); } } else if( resume_runG == NO ) { fprintf(fpoG,"Use of resume file: %s was not requested\n", filename); } else { if( connection_machineG != 3 ) { fprintf( fpoG, "Resuming TimberWolfSC from previous saved "); fprintf( fpoG, "placement in %s\n", filename ); TW_oldin( fp ) ; /* findunlap(0); */ TWCLOSE( fp ) ; } else { fprintf( fpoG, "Starting TimberWolfSC with connection "); fprintf( fpoG, "machine placement in %s\n", filename ); incm( fp ) ; TWCLOSE( fp ) ; } } sortpin() ; for( cell = 1 ; cell <= lastpadG ; cell++ ) { ptr = carrayG[ cell ] ; corient = ptr->corient ; block = ptr->cblock ; tile = ptr->tileptr ; if( cell <= numcellsG - extra_cellsG ) { ptr->cycenter = barrayG[block]->bycenter ; if( adjust_left[block] > ptr->cxcenter + tile->left ) { adjust_left[block] = ptr->cxcenter + tile->left ; } for( termptr = ptr->pins;termptr;termptr =termptr->nextpin ) { termptr->xpos = termptr->txpos[corient/2] + ptr->cxcenter; termptr->ypos = termptr->typos[corient%2] + ptr->cycenter; } } else if( cell > numcellsG ) { for( termptr = ptr->pins;termptr;termptr =termptr->nextpin ) { termptr->xpos = termptr->txpos[1] + ptr->cxcenter; termptr->ypos = termptr->typos[1] + ptr->cycenter; } } } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ /* @@@ calculate the initial wire cost of user's placement @@@ */ iwirexS = 0 ; iwireyS = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; if( !(netptr = dimptr->pins)) { continue ; } dimptr->xmin = dimptr->xmax = netptr->xpos ; dimptr->ymin = dimptr->ymax = netptr->ypos ; for( netptr = netptr->next ; netptr ; netptr = netptr->next ) { x = netptr->xpos ; y = netptr->ypos ; if( x < dimptr->xmin ) { dimptr->xmin = x ; } else if( x > dimptr->xmax ) { dimptr->xmax = x ; } if( y < dimptr->ymin ) { dimptr->ymin = y ; } else if( y > dimptr->ymax ) { dimptr->ymax = y ; } } cost += dimptr->halfPx = dimptr->newhalfPx = dimptr->xmax - dimptr->xmin ; dimptr->halfPy = dimptr->newhalfPy = dimptr->ymax - dimptr->ymin ; cost = cost + (INT)( vertical_wire_weightG * (DOUBLE) dimptr->halfPy ) ; iwirexS += dimptr->xmax - dimptr->xmin ; iwireyS += dimptr->ymax - dimptr->ymin ; } fprintf( fpoG, "\n\n\nTHIS IS THE ROUTE COST OF THE "); fprintf( fpoG, "ORIGINAL PLACEMENT: %d\n" , cost ) ; /* @@@@@@@@@@@@@@@@@@@@@@ calculation end @@@@@@@@@@@@@@@@@@@@ */ /* $$$$$$$$$$$ move the cells in each block such that $$$$$$$ */ /* $$$$$$$$$$$ they line up with the left edge of block $$$$$$$ */ if( resume_runG == NO ) { for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { ptr = carrayG[cell] ; corient = ptr->corient ; block = ptr->cblock ; ptr->cxcenter -= adjust_left[block] - barrayG[block]->bxcenter - barrayG[block]->bleft ; for( termptr = ptr->pins ;termptr;termptr = termptr->nextpin ) { termptr->xpos = termptr->txpos[corient/2] + ptr->cxcenter; termptr->ypos = termptr->typos[corient%2] + ptr->cycenter; } } } /* $$$$$$$$$$$$$$$$$$$$$$ adjustment end $$$$$$$$$$$$$$$$$$$$$$ */ for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->fence != NULL ) { carrayG[cell]->fence->min_xpos = carrayG[cell]->cxcenter - approximately_fixed_factorG * minxspanG ; carrayG[cell]->fence->max_xpos = carrayG[cell]->cxcenter + approximately_fixed_factorG * minxspanG ; } } /*********************************************************** */ cost = 0 ; iwirexS = 0 ; iwireyS = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; if( netptr = dimptr->pins ) { while( carrayG[netptr->cell]->ECO_flag ) { fprintf(fpoG,"ECO pin skipped for net <%s>\n", netarrayG[netptr->net]->name ) ; netptr = netptr->next ; if( netptr == NULL ) { break ; } } if( netptr == NULL ) { continue ; } dimptr->xmin = dimptr->xmax = netptr->xpos ; dimptr->ymin = dimptr->ymax = netptr->ypos ; dimptr->Lnum = dimptr->Rnum = 1 ; dimptr->Bnum = dimptr->Tnum = 1 ; netptr = netptr->next ; } n = 1 ; for( ; netptr ; netptr = netptr->next ) { while( carrayG[netptr->cell]->ECO_flag ) { fprintf(fpoG,"ECO pin skipped for net <%s>\n", netarrayG[netptr->net]->name ) ; netptr = netptr->next ; if( netptr == NULL ) { break ; } } if( netptr == NULL ) { break ; } x = netptr->xpos ; y = netptr->ypos ; if( x < dimptr->xmin ) { dimptr->xmin = x ; dimptr->Lnum = 1 ; } else if( x == dimptr->xmin ) { dimptr->Lnum++ ; if( x == dimptr->xmax ) { dimptr->Rnum++ ; } } else if( x > dimptr->xmax ) { dimptr->xmax = x ; dimptr->Rnum = 1 ; } else if( x == dimptr->xmax ) { dimptr->Rnum++ ; } if( y < dimptr->ymin ) { dimptr->ymin = y ; dimptr->Bnum = 1 ; } else if( y == dimptr->ymin ) { dimptr->Bnum++ ; if( y == dimptr->ymax ) { dimptr->Tnum++ ; } } else if( y > dimptr->ymax ) { dimptr->ymax = y ; dimptr->Tnum = 1 ; } else if( y == dimptr->ymax ) { dimptr->Tnum++ ; } n++ ; } dimptr->numpins = n ; if( dimptr->ignore == 1 ){ continue ; } cost += dimptr->halfPx = dimptr->newhalfPx = dimptr->xmax - dimptr->xmin ; dimptr->halfPy = dimptr->newhalfPy = dimptr->ymax - dimptr->ymin ; cost = cost + (INT)( vertical_wire_weightG * (DOUBLE) dimptr->halfPy ) ; D( "twsc/findcost", fprintf( fpoG, "net:%5d cum cost:%10d\n", net, cost ) ; fflush( fpoG ) ; ) ; iwirexS += dimptr->xmax - dimptr->xmin ; iwireyS += dimptr->ymax - dimptr->ymin ; }
globroute() { INT flips , attempts , net ; INT pick , number , attlimit ; INT found , trys , maxtrys ; INT x , x1 , x2 , channel ; SEGBOXPTR segptr , *segment ; DENSITYPTR denptr ; PINBOXPTR netptr1 , netptr2 ; changrid( ) ; pre_findrcost( ) ; findrcost() ; fprintf(fpoG,"\n\nTHIS IS THE ORIGINAL NUMBER OF TRACKS: %d\n\n\n" , tracksG ) ; fflush(fpoG); flips = 0 ; attempts = 0 ; attlimit = 25 * numnetsG ; segment = ( SEGBOXPTR *)Ysafe_malloc( ( Max_numPinsG + 1 ) * sizeof( SEGBOXPTR ) ) ; while( ++attempts < attlimit ) { if( attempts % 1000 == 0 ) { printf(" tracks = %3d at attempts = %5d\n" ,tracksG ,attempts ) ; } do { net = (INT) ( (DOUBLE) numnetsG * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( net == numnetsG + 1 ) ; number = 0 ; for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 1 ) ; if( segptr->switchvalue != nswLINE ) { segment[ ++number ] = segptr ; } } maxtrys = 4 * number ; trys = 0 ; while( ++trys <= maxtrys ) { do { pick = (INT) ( (DOUBLE) number * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( pick == number + 1 ) ; segptr = segment[ pick ] ; netptr1 = segptr->pin1ptr ; netptr2 = segptr->pin2ptr ; if( segptr->switchvalue == swUP ) { channel = netptr1->row + 1 ; } else { channel = netptr2->row ; } x1 = netptr1->xpos ; x2 = netptr2->xpos ; found = NO ; for( denptr = DboxHeadG[ channel ][ maxTrackG[channel] ]->next ; denptr != DENSENULL ; denptr = denptr->next ) { x = denptr->grdptr->netptr->xpos ; if( x1 <= x && x2 >= x ) { found = YES ; break ; } } if( !found ) { continue ; } if( urcost( segptr ) ) { flips++ ; } } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 0 ) ; } } Ysafe_free( segment ); fprintf(fpoG,"no. of accepted flips: %d\n", flips ) ; fprintf(fpoG,"no. of attempted flips: %d\n", attempts ) ; fprintf(fpoG,"THIS IS THE NUMBER OF TRACKS: %d\n\n\n" , tracksG ) ; fflush(fpoG); return ; }
feedest() { DOUBLE ratio ; INT net , row , toprow , botrow, maxdesire ; DBOXPTR dimptr ; PINBOXPTR ptr ; fd_estimateS = (DOUBLE *)Ysafe_calloc( numChansG + 1, sizeof(DOUBLE) ) ; min_feedS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; row_flagS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; rowfeed_penaltyG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof(INT) ) ; est_min_ratioS = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; maxdesire = barrayG[1]->desire ; for( row = 2 ; row <= numRowsG ; row++ ) { if( maxdesire < barrayG[row]->desire ) { maxdesire = barrayG[row]->desire ; } } ratio = (DOUBLE)(maxdesire) / (DOUBLE)( barrayG[numRowsG]->bycenter - barrayG[1]->bycenter + rowHeightG ) ; ratio = 1.0 / ratio ; /* to fix Kai-Win's bug */ if( absolute_minimum_feedsG ) { if( ratio >= 1.0 ) { chip_width_penaltyS = barrayG[numRowsG]->bycenter - barrayG[1]->bycenter + rowHeightG ; } else { chip_width_penaltyS = maxdesire ; } } else { /* chip_width_penaltyS = 2.0 * (DOUBLE) rowHeightG ; */ chip_width_penaltyS = 6.9 * (DOUBLE) rowHeightG ; } if( !absolute_minimum_feedsG ) { add_Lcorner_feedG = TRUE ; /* Carl */ for( row = 1 ; row <= numRowsG ; row++ ) { if( FeedInRowG[row] == 0 ) { add_Lcorner_feedG = FALSE ; break ; } } /* Carl */ } else { add_Lcorner_feedG = FALSE ; } for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; if( !(dimptr->pins) ) { continue ; } switch( dimptr->numpins ) { case 0 : case 1 : break ; case 2 : ptr = dimptr->pins ; toprow = ptr->row ; botrow = ptr->next->row ; if( toprow > botrow ) { for( row = botrow + 1 ; row < toprow ; row++ ) { fd_estimateS[row]++ ; min_feedS[row]++ ; } if( ABS( ptr->xpos - ptr->next->xpos ) >= average_feed_sepG ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } } else if( toprow < botrow ) { for( row = toprow + 1 ; row < botrow ; row++ ) { fd_estimateS[row]++ ; min_feedS[row]++ ; } if( ABS( ptr->xpos - ptr->next->xpos ) >= average_feed_sepG ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; case 3 : case 4 : case 5 : ptr = dimptr->pins ; toprow = botrow = ptr->row ; row_flagS[toprow] = 1 ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { row = ptr->row ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } row_flagS[row] = 1 ; } for( row = botrow + 1 ; row < toprow ; row++ ) { if( row_flagS[row] ) { fd_estimateS[row]++ ; row_flagS[row] = 0 ; } else { fd_estimateS[row] += 1.5 ; min_feedS[row]++ ; } } if( toprow > botrow ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; default : ptr = dimptr->pins ; toprow = botrow = ptr->row ; row_flagS[toprow] = 1 ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { row = ptr->row ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } row_flagS[row] = 1 ; } for( row = botrow + 1 ; row < toprow ; row++ ) { if( row_flagS[row] ) { fd_estimateS[row]++ ; row_flagS[row] = 0 ; } else { fd_estimateS[row] += 1.5 ; min_feedS[row]++ ; } } if( toprow > botrow ) { fd_estimateS[botrow]++ ; fd_estimateS[toprow]++ ; } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; } } estimate_pass_thru_penalty( 1 , numRowsG ) ; }
DOUBLE analyze() { INT **number , i , net , net1 , net2 , num , cell ; INT *count , different , cnum , c2num , *arraynet ; INT num_nets , tot_cels ; DOUBLE C , C1 , C2 , C3 , wireRatio ; PINBOXPTR pinptr ; INT comparex() ; DOUBLE weight_past_runs( /* wireRatio */ ) ; count = (INT *) Ysafe_malloc( (1 + numcellsG) * sizeof( INT ) ) ; number = (INT **) Ysafe_malloc( (1 + numnetsG) * sizeof( INT *) ) ; howmanyS = (INT *) Ysafe_malloc( (1 + numnetsG) * sizeof( INT ) ) ; arraynet = (INT *) Ysafe_malloc( (1 + numnetsG) * sizeof( INT ) ) ; for( net = 0 ; net <= numnetsG ; net++ ) { number[net] = (INT *) Ysafe_malloc( (1 + numcellsG) * sizeof(INT) ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { for( cell = 0 ; cell <= numcellsG ; cell++ ) { count[cell] = 0 ; number[net][cell] = 0 ; } for( pinptr=netarrayG[net]->pins;pinptr; pinptr = pinptr->next ){ if( pinptr->cell <= numcellsG ) { count[pinptr->cell] = 1 ; } } /* * I would like to find the number of distinct nets */ for( cell = 1 ; cell <= numcellsG ; cell++ ) { if( count[cell] == 1 ) { number[net][ ++number[net][0] ] = cell ; } } } /* ********************************************************** */ num_nets = 0 ; tot_cels = 0 ; for( net1 = 1 ; net1 <= numnetsG ; net1++ ) { if( number[net1][0] <= 1 ) { continue ; } num_nets++ ; tot_cels += number[net1][0] ; } OUT1("\n\n*************************************\n"); OUT2("AVERAGE NUMBER OF CELLS PER NET: %f\n", ( (DOUBLE) tot_cels / (DOUBLE) num_nets ) ) ; OUT1("*************************************\n\n\n"); /* ********************************************************** */ for( net1 = 1 ; net1 <= numnetsG ; net1++ ) { if( number[net1][0] == 0 ) { howmanyS[net1] = 0 ; continue ; } if( number[net1][0] == 1 ) { number[net1][0] = 0 ; howmanyS[net1] = 0 ; continue ; } howmanyS[net1] = 1 ; for( net2 = net1 + 1 ; net2 <= numnetsG ; net2++ ) { if( number[net2][0] != number[net1][0] ) { continue ; } different = 0 ; for( i = 1 ; i <= numcellsG ; i++ ) { if( number[net2][i] != number[net1][i] ) { different = 1 ; break ; } } if( ! different ) { number[net2][0] = 0 ; howmanyS[net1]++ ; } } } arraynet[0] = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { if( howmanyS[net] <= 0 ) { continue ; } arraynet[ ++arraynet[0] ] = net ; } num = arraynet[0] ; arraynet[0] = arraynet[ arraynet[0] ] ; Yquicksort( (char *) arraynet , num , sizeof( INT ), comparex ) ; /* sorted: most occurrences first */ num = 0 ; cnum = 0 ; c2num = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { if( number[net][0] > 0 ) { cnum += number[net][0] - 1 ; c2num += number[net][0] ; num++ ; } } C = (DOUBLE) num / (DOUBLE) numcellsG ; C1 = (DOUBLE) cnum / (DOUBLE) num ; C2 = (DOUBLE) c2num / (DOUBLE) num ; C3 = (DOUBLE) cnum / (DOUBLE)(numcellsG - 1) ; OUT1("\n\n\n**********************************************\n\n"); OUT1("The average number of distinct nets per cell is\n"); OUT2("given by: %6.2f\n\n", C ); OUT1("The average number of cells per net is\n"); OUT2("given by: %6.2f\n\n", C2 ); OUT1("The average number of other cells per net is\n"); OUT2("given by: %6.2f\n\n", C1 ); OUT1("The ratio of total cells specified per net to\n"); OUT2("numcells is given by: %6.2f\n\n", C3 ); OUT1("The average number of cells connected to a cell is\n"); OUT2("given by: %6.2f\n\n", C * C1 ); OUT1("**********************************************\n\n\n"); wireRatio = EXPECTEDWIRERATIO ; OUT2("Expected Wire Reduction Relative to Random:%6.2f\n\n",wireRatio); FLUSHOUT(); wireRatio = weight_past_runs( wireRatio ) ; sprintf( YmsgG,"\n\nWire ratio updated to:%4.2f\n\n", wireRatio ) ; M( MSG, "analyze", YmsgG ) ; return( wireRatio ); }
postFeedAssgn() { INT net , i , row , botrow , toprow , last_i ; SEGBOXPTR segptr , nextseg ; PINBOXPTR netptr , nextptr , st_head , stptr ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = nextseg ) { nextseg = segptr->next ; Ysafe_free( segptr ) ; } netsegHeadG[net]->next = NULL ; netptr = netarrayG[net]->pins ; st_head = steinerHeadG[net] ; if( st_head->next ) { /* there are steiner point for this net */ for( stptr = st_head ; stptr->next ; ) { nextptr = stptr->next ; if( nextptr->terminal == 0 || !nextptr->flag ) { /* steiner point in bottom pads or top pads or they are pseudo steiner point. */ stptr->next = nextptr->next ; Ysafe_free( nextptr ) ; } else { stptr = nextptr ; } } stptr->next = netptr ; netarrayG[net]->pins = st_head->next ; /* put all the netbox of the steiner point into the netarrayG linked lists. */ } Ysafe_free( steinerHeadG[net] ) ; } Ysafe_free( steinerHeadG ) ; maxpin_numberS = 0 ; pins_at_rowS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins <= 2 ) { continue ; } botrow = numChansG ; toprow = 0 ; for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { row = netptr->row ; pins_at_rowS[ row ]++ ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } } for( row = botrow ; row <= toprow ; row++ ) { if( pins_at_rowS[row] > maxpin_numberS ) { maxpin_numberS = pins_at_rowS[row] ; } pins_at_rowS[row] = 0 ; } } maxpin_numberS += 3 ; count_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; father_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; root_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; stack_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; first_indexS = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; vertex_G = (PINBOXPTR *)Ysafe_malloc( 2 * Max_numPinsG * sizeof(PINBOXPTR) ); last_i = maxpin_numberS * maxpin_numberS * numRowsG - 1 ; edge_dataS = (EDGE_COST *)Ysafe_malloc( ( last_i + 1 ) * sizeof(EDGE_COST) ) ; for( i = 1 ; i <= last_i ; i++ ) { edge_dataS[i] = (EDGE_COST)Ysafe_malloc( sizeof(EDGE_COST_BOX) ); } z_S = (PINBOXPTR **)Ysafe_malloc( ( numChansG + 1 ) * sizeof(PINBOXPTR *) ) ; for( i = 0 ; i <= numChansG ; i++ ) { z_S[i] = (PINBOXPTR *)Ysafe_malloc( maxpin_numberS * sizeof(PINBOXPTR) ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins <= 1 ) { continue ; } rebuild_netgraph( net ) ; /* find minimum cost tree connection from all the pins of a net */ } }
void construct_segment() { register int i ; register int j ; register int v ; register int v1 ; register int v2 ; int count ; int degree ; int Degree ; int order ; LISTPTR Pnode ; MDATAPTR Pcurrent ; /* vertex of its adjdacent list is searched */ MDATAPTR Plast ; /* last vertex in the segment tree list */ MDATAPTR Pparent ; /* start of the path to current vertex */ MDATAPTR Pnew ; /* temporary pointer for new vertex */ PINPTR Pfirst ; PINPTR Ppin ; STACKPTR Pstack ; STACKPTR Psteiner ; /*********************************************************** * Label all the vertices in the minimum Steiner tree with * one and label the others with zero. ***********************************************************/ numnode = numpins ; numtree_e = 0 ; for (i=1; i<=numnodes; i++) { garray[i]->status = FALSE ; iarray[i] = 0 ; } for (i=numnodes+1; i<=totnodes; i++) { garray[i]->status = TRUE ; iarray[i] = 0 ; } for (i=1; i<=totedges; i++) { earray[i]->numpins = FALSE ; if (earray[i]->intree&MIN_MASK) { earray[i]->numpins = TRUE ; jarray[++numtree_e] = i ; v1 = earray[i]->node[0] ; v2 = earray[i]->node[1] ; if (!garray[v1]->status) { numnode++ ; garray[v1]->status = TRUE ; } if (!garray[v2]->status) { numnode++ ; garray[v2]->status = TRUE ; } } } /*********************************************************** * Initialize field key of parray to be zero. ***********************************************************/ for (i=1; i<=numpins; i++) { parray[i]->key = FALSE ; } i = numnodes + 1 ; /*********************************************************** * Find a pin which is a leaf of the minimum Steiner tree. ***********************************************************/ while (1) { degree = 0 ; Pnode = garray[i]->first ; while (Pnode) { if (earray[Pnode->edge]->numpins) { degree++ ; } Pnode = Pnode->next ; } if (degree==1) { break ; } i++ ; } Pstack = NIL(STACK) ; count = 0 ; order = 1 ; Pcurrent = Plast = Pparent = Proot = make_node() ; Proot->dist = 0 ; Proot->leaf = FALSE ; Proot->order = 1 ; Proot->parent = 0 ; Proot->vertex = i ; Proot->prev = NIL(MDATA) ; Proot->next = NIL(MDATA) ; Proot->f_node = NIL(MDATA) ; if (parray[i-numnodes]->equiv) { Proot->equiv = TRUE ; parray[i-numnodes]->key = TRUE ; } else { Proot->equiv = FALSE ; } if (EQUIVAL==FALSE) { do { degree = 0 ; Pnode = garray[i]->first ; if (!count) { /*********************************************************** * Search the adjacent list of the current vertex to test if * a vertex in the list is a pin or has a degree greater than * two. * count = 0 --- the current vertex is not a Steiner vertex. ***********************************************************/ while (Pnode) { v1 = Pnode->t_vertex ; if (garray[v1]->status && v1!=Pcurrent->parent) { if (earray[Pnode->edge]->intree&MIN_MASK) { j = v1 ; degree++ ; } } Pnode = Pnode->next ; } } else { /*********************************************************** * The search just returns to a Steiner vertex. We need to * go through the number of count times for adjacent vertices * which are in the minimum Steiner tree and add the vertex * into the segment tree. * count!=0 --- the current vertex is a Steiner vertex. ***********************************************************/ while (Pnode) { v1 = Pnode->t_vertex ; if (garray[v1]->status && v1!=Pcurrent->parent) { if (earray[Pnode->edge]->intree&MIN_MASK) { j = v1 ; degree++ ; } if (degree==count) { count = 0 ; break ; } } Pnode = Pnode->next ; } } if (degree) { /*********************************************************** * The current vertex is not a leaf. Generate a new node and * expand the tree. ***********************************************************/ Pnew = make_node() ; Pnew->equiv = FALSE ; Pnew->leaf = FALSE ; Pnew->order = ++order ; Pnew->parent = i ; Pnew->status = 0 ; Pnew->vertex = j ; Plast->next = Pnew ; Pnew->prev = Plast ; Plast = Pnew ; Pnew->next = NIL(MDATA) ; Pnew->f_node = Pparent ; Pcurrent = Pnew ; v = i ; i = j ; } else { Pcurrent->leaf = TRUE ; } if (degree==1 && j>numnodes) { /*********************************************************** * A pin is reached which, with the start vertex i, forms a * segment. Set Pparent to be Pnew and continue the search. ***********************************************************/ Pparent = Pnew ; } else if (degree>1) { /*********************************************************** * A Steiner vertex is reached which, with the start vertex * i, forms a segment. Set Pparent to be Pnew, update the * stack, and continue the search. ***********************************************************/ if (Pstack && Pstack->Pparent->vertex==v) { Pnew->f_node = Pstack->Pparent ; /********************************************************* * The Steiner point is in the stack already. Use goto to * jump over the part of pushing it to the stack. *********************************************************/ goto contin ; } Psteiner = (STACKPTR) Ysafe_malloc(sizeof(STACK)) ; Psteiner->degree = --degree ; Psteiner->Pparent = Pnew->prev ; Psteiner->next = Pstack ; Pstack = Psteiner ; Pnew->f_node = Pnew->prev ; contin: if (j>numnodes) { Pparent = Pnew ; } else { Pparent = Pnew->f_node ; } } else if (!degree) { /*********************************************************** * A leaf is reached. Pop a vertex from the stack and continue * the search from that vertex. ***********************************************************/ Psteiner = Pstack ; Pcurrent = Pparent = Psteiner->Pparent ; count = Psteiner->degree ; i = Pcurrent->vertex ; Psteiner->degree-- ; if (!Psteiner->degree) { Pstack = Pstack->next ; Ysafe_free(Psteiner) ; } } } while (order<numnode) ; } else { do { degree = 0 ; Pnode = garray[i]->first ; if (!count) { /*********************************************************** * Search the adjacent list of the current vertex to test if * a vertex in the list is a pin or has a degree greater than * two. * count = 0 --- the current vertex is not a Steiner vertex. ***********************************************************/ while (Pnode) { v1 = Pnode->t_vertex ; if (garray[v1]->status && v1!=Pcurrent->parent) { if (earray[Pnode->edge]->intree&MIN_MASK) { j = v1 ; degree++ ; } } Pnode = Pnode->next ; } } else { /*********************************************************** * The search just returns to a Steiner vertex. We need to * go through the number of count times for adjacent vertices * which are in the minimum Steiner tree and add the vertex * into the segment tree. * count!=0 --- the current vertex is a Steiner vertex. ***********************************************************/ while (Pnode) { v1 = Pnode->t_vertex ; if (garray[v1]->status && v1!=Pcurrent->parent) { if (earray[Pnode->edge]->intree&MIN_MASK) { j = v1 ; degree++ ; } if (degree==count) { count = 0 ; break ; } } Pnode = Pnode->next ; } } if (i>numnodes && parray[i-numnodes]->equiv) { /*********************************************************** * The vertex is an equivalent pin. Scan through all its * equivalent pins. If one is an isolated equivalent pin, * then created a node in the segment tree for it and skip * it; otherwise, create a node in the segment tree for it * and push it into the stack. ***********************************************************/ Pcurrent->equiv = TRUE ; Pfirst = parray[i-numnodes] ; Pfirst->key = TRUE ; Ppin = Pfirst->next ; while (Ppin!=Pfirst) { if (Ppin->key==TRUE) { Ppin = Ppin->next ; continue ; } else { Ppin->key = TRUE ; } Pnew = make_node() ; Pnew->equiv = TRUE ; Pnew->leaf = TRUE ; Pnew->order = ++order ; Pnew->parent = i ; Pnew->status = 0 ; Pnew->vertex = Ppin->vertex + numnodes ; Pnew->f_node = Pcurrent ; Plast->next = Pnew ; Pnew->prev = Plast ; Pnew->next = NIL(MDATA) ; Plast = Pnew ; Degree = 0 ; Pnode = garray[Ppin->vertex+numnodes]->first ; while (Pnode) { if (earray[Pnode->edge]->numpins) { Degree++ ; } Pnode = Pnode->next ; } if (Degree) { /***************************************************** * The pin is not isolated. Push it into the stack. *****************************************************/ Pnew->leaf = FALSE ; Psteiner = (STACKPTR) Ysafe_malloc(sizeof(STACK)) ; Psteiner->degree = Degree ; Psteiner->Pparent = Pnew ; Psteiner->next = Pstack ; Pstack = Psteiner ; } /* Psteiner = (STACKPTR) Ysafe_malloc(sizeof(STACK)) ; Psteiner->degree = Degree ; Psteiner->Pparent = Pnew ; Psteiner->next = Pstack ; Pstack = Psteiner ; */ Ppin = Ppin->next ; } } if (degree) { /*********************************************************** * The current vertex is not a leaf. Generate a new node and * expand the tree. ***********************************************************/ Pnew = make_node() ; Pnew->equiv = FALSE ; Pnew->leaf = FALSE ; Pnew->order = ++order ; Pnew->parent = i ; Pnew->status = 0 ; Pnew->vertex = j ; Plast->next = Pnew ; Pnew->prev = Plast ; Plast = Pnew ; Pnew->next = NIL(MDATA) ; Pnew->f_node = Pparent ; Pcurrent = Pnew ; v = i ; i = j ; } else { /*********************************************************** * If the current vertex is an equivalent pin, then check * whether it has a son. ***********************************************************/ if (Pcurrent->equiv && Pcurrent->next) { v1 = Pcurrent->vertex - numnodes ; v2 = Pcurrent->next->vertex - numnodes ; if (parray[v1]->equiv==parray[v2]->equiv) { Pcurrent->leaf = FALSE ; } } else { Pcurrent->leaf = TRUE ; } } if (degree==1 && j>numnodes) { /*********************************************************** * A pin is reached which, with the start vertex i, forms a * segment. Set Pparent to be Pnew and continue the search. ***********************************************************/ Pparent = Pnew ; } else if (degree>1) { /*********************************************************** * A Steiner vertex is reached which, with the start vertex * i, forms a segment. Set Pparent to be Pnew, update the * stack, and continue the search. ***********************************************************/ if (Pstack && Pstack->Pparent->vertex==v) { Pnew->f_node = Pstack->Pparent ; /********************************************************* * The Steiner point is in the stack already. Use goto to * jump over the part of pushing it to the stack. *********************************************************/ goto contin_equiv ; } Psteiner = (STACKPTR) Ysafe_malloc(sizeof(STACK)) ; Psteiner->degree = --degree ; Psteiner->Pparent = Pnew->prev ; Psteiner->next = Pstack ; Pstack = Psteiner ; Pnew->f_node = Pnew->prev ; contin_equiv: if (j>numnodes) { Pparent = Pnew ; } else { Pparent = Pnew->f_node ; } } else if (!degree && Pstack) { /*********************************************************** * A leaf is reached. Pop a vertex from the stack and continue * the search from that vertex. ***********************************************************/ Psteiner = Pstack ; Pparent = Pcurrent = Psteiner->Pparent ; count = Psteiner->degree ; i = Pcurrent->vertex ; Psteiner->degree-- ; if (!Psteiner->degree) { Pstack = Pstack->next ; Ysafe_free(Psteiner) ; } } } while (order<numnode) ; } /*********************************************************** * Assign the segment tree to an array and set up the index * array for quick access. ***********************************************************/ marray = (MDATAPTR *) Ysafe_malloc((numnode+1) * sizeof(MDATAPTR)) ; marray[0] = NIL(MDATA) ; Pcurrent = Proot ; while (Pcurrent) { i = Pcurrent->order ; marray[i] = Pcurrent ; j = Pcurrent->vertex ; iarray[j] = i ; Pcurrent = Pcurrent->next ; } /*********************************************************** * Assign the distance to the field in each entry of marray. ***********************************************************/ if (EQUIVAL==FALSE) { for (i=2; i<=numnode; i++) { v1 = marray[i-1]->vertex ; v2 = marray[i]->vertex ; Pnode = garray[v1]->first ; while (Pnode && Pnode->t_vertex!=v2) { Pnode = Pnode->next ; } if (Pnode && earray[Pnode->edge]->intree) { marray[i]->dist = marray[i-1]->dist + Pnode->length ; } else { j = marray[i]->f_node->order ; v1 = marray[j]->vertex ; Pnode = garray[v1]->first ; while(Pnode && Pnode->t_vertex!=v2) { Pnode = Pnode->next ; } marray[i]->dist = marray[j]->dist + Pnode->length ; } } } else { for (i=2; i<=numnode; i++) { if (marray[i]->equiv && marray[i]->f_node->equiv) { /*********************************************************** * Both pins are equivalent pins. ***********************************************************/ v1 = marray[i]->vertex - numnodes ; v2 = marray[i]->f_node->vertex - numnodes ; if (parray[v1]->equiv==parray[v2]->equiv) { /********************************************************* * Both pins are in the same group of equivalent pins. *********************************************************/ marray[i]->dist = marray[i]->f_node->dist ; } else { /********************************************************* * Both pins are not in the same group of equivalent pins. *********************************************************/ goto USUAL_CASE ; } } else { USUAL_CASE: v1 = marray[i-1]->vertex ; v2 = marray[i]->vertex ; Pnode = garray[v1]->first ; while (Pnode && Pnode->t_vertex!=v2) { Pnode = Pnode->next ; } if (Pnode && earray[Pnode->edge]->intree) { marray[i]->dist = marray[i-1]->dist + Pnode->length ; } else { j = marray[i]->f_node->order ; v1 = marray[j]->vertex ; Pnode = garray[v1]->first ; while(Pnode && Pnode->t_vertex!=v2) { Pnode = Pnode->next ; } marray[i]->dist = marray[j]->dist + Pnode->length ; } } } } marray[numnode]->leaf = TRUE ; } /* end of construct_segment */
install_clusters() { INT row , n , i , bin , i_error , delta_bin , length_in_row , cell ; INT total ; INT total_actual_clusters ; DOUBLE error , n_DOUBLE , cluster_norm ; fprintf(fpoG,"total number of clusters which should be added in: %d\n", num_clustersG ) ; total_actual_clusters = 0 ; cluster_configS = (INT **) Ysafe_malloc((1 + numRowsG) * sizeof(INT *)) ; for( row = 1 ; row <= numRowsG ; row++ ) { cluster_configS[row] = (INT *) Ysafe_malloc((1+numBinsG)*sizeof(INT)); for( bin = 0 ; bin <= numBinsG ; bin++ ) { cluster_configS[row][bin] = 0 ; } } cluster_norm = (DOUBLE) num_clustersG / (DOUBLE) numRowsG + cluster_norm_offsetS ; if( num_clustersG == 0 ) { return ; } error = 0.0 ; total = 0 ; for( row = 1 ; total < num_clustersG && row <= numRowsG ; row++ ) { length_in_row = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cblock == row ) { if( carrayG[cell]->cclass < 0 ) { length_in_row += carrayG[cell]->clength ; } } } n_DOUBLE = cluster_norm + error ; n = (INT) n_DOUBLE ; if( n_DOUBLE - (DOUBLE) n >= 0.5 ) { n++ ; } error = n_DOUBLE - (DOUBLE) n ; while( total + n > num_clustersG ) { n-- ; } if( length_in_row + n * cluster_widthG > barrayG[row]->desire ) { if( row == numRowsG ) { /* can't fit all the required clusters; increase cluster_norm */ ++cluster_norm_offsetS ; for( row = 1 ; row <= numRowsG ; row++ ) { Ysafe_free( cluster_configS[row] ) ; } Ysafe_free( cluster_configS ) ; install_clusters() ; return ; } n = (barrayG[row]->desire - length_in_row) / cluster_widthG ; if( n < 0 ) { n = 0 ; } error += (DOUBLE)( (INT) n_DOUBLE - n ) ; } if( n == 0 ) { continue ; } total += n ; i_error = 0 ; bin = 0 ; for( i = 0 ; i < n ; i++ ) { delta_bin = (numBinsG + i_error) / n ; bin += delta_bin ; i_error += numBinsG - delta_bin * n ; if( bin < 1 ) bin = 1 ; if( bin > numBinsG ) bin = numBinsG ; cluster_configS[row][bin]++ ; } fprintf(fpoG,"Number of clusters added to row:%d was:%d\n", row,i); total_actual_clusters += i ; for( bin = 1 ; bin <= numBinsG ; bin++ ) { if( cluster_configS[row][bin] >= 1 ) { barrayG[row]->oldsize += cluster_configS[row][bin] * cluster_widthG ; } } } fprintf(fpoG,"actual total number of clusters which were added in: %d\n", total_actual_clusters ) ; return; } /* end install_clusters */
/*===================================================================== * In order to have this file work properly, there must be a blank line * between the records of two consecutive nets and the very first line * can not be a blank line. Also the name of nets can not be over 256 * characters. =====================================================================*/ BOOLEAN read_one_net() { char input[LRECL]; char **tokens; int i; int v1; /* Vertex index */ int v2; /* Vertex index */ int pin; int equiv; INT numtokens; C_LISTPTR Pnew; LISTPTR Pnode; PINPTR Pfirst; /* Header of the pin list */ PINPTR Ppin; EQUIVAL = FALSE; SHIFTED = FALSE; CAP_MATCH = FALSE; MIX_MATCH = FALSE; RES_MATCH = FALSE; COMMON_POINT = FALSE; equiv = 0; numpins = 0; net_type = 0; numcomms = 0; max_volt_drop = 0; Pfirst = NIL(PIN); Plist = NIL(C_LIST); while (fgets(input, LRECL, fin)) { tokens = Ystrparser(input, " \t\n", &numtokens); if (numtokens == 0) { /*********************************************************** * An empty line is reached. A complete record is read in * so quit reading the net. ***********************************************************/ break; } if (strncmp(tokens[0], "net", 3) == STRINGEQ) { /*********************************************************** * The beginning of a digital net is read in. Get the net * name and set the net type to be noisy. ***********************************************************/ (void) strcpy(netName, tokens[1]); DIGITAL = TRUE; net_type = NOISY; } else if (strncmp(tokens[0], "analog_net", 10) == STRINGEQ) { /*********************************************************** * The beginning of an analog net is read in. Get the net * name and read in the capacitance upper bound, resistance * upper bound, maximum value of the voltage drop, plus the * net type specification. Note that not all the parameters * have to be present. ***********************************************************/ (void) strcpy(netName, tokens[1]); if (numtokens < 3) { ERROR1("\n\nThe entry line for an analog net must have "); ERROR1("at least 3 fields!\n"); ERROR2("Net name: %s\n", netName); exit(GP_FAIL); } for (i = 2; i < numtokens; i += 2) { if (strncmp(tokens[i], "cap", 3) == STRINGEQ) { cap_upper_bound = atof(tokens[i+1]); } else if (strncmp(tokens[i], "res", 3) == STRINGEQ) { res_upper_bound = atof(tokens[i+1]); } else if (strncmp(tokens[i], "max_drop", 8) == STRINGEQ) { max_volt_drop = atof(tokens[i+1]); } else if (strncmp(tokens[i], "noisy", 5) == STRINGEQ) { if (net_type == SENSITIVE) { net_type = MIXED; } else if(net_type == SHIELD) { ERROR1("\n\n"); ERROR1("A net can not be NOISY and SHIELDING "); ERROR1("at the same time\n"); ERROR2("Net name: %s\n", netName); exit(GP_FAIL); } else { net_type = NOISY; } i--; } else if(strncmp(tokens[i], "sensitive", 9) == STRINGEQ) { if (net_type == NOISY) { net_type = MIXED; } else if(net_type == SHIELD) { ERROR1("\n\nA net can not be SENSITIVE and "); ERROR1("SHIELDING at the same time\n"); ERROR2("Net name: %s\n", netName); exit(GP_FAIL); } else { net_type = SENSITIVE; } i--; } else if (strncmp(tokens[i], "shielding", 9) == STRINGEQ) { if (net_type == NOISY || net_type == SENSITIVE) { ERROR1("\n\nA net can not be SENSITIVE and "); ERROR1("SHIELDING or NOISY and\n"); ERROR1("SHIELDING at the same time\n"); ERROR2("Net name: %s\n", netName); exit(GP_FAIL); } else { net_type = SHIELD; } i--; } else { ERROR1("\n\n"); ERROR2("Unknown keyword \"%s\" for the ", tokens[i]); ERROR2("net %s.\nNotice that the keywords", netName); ERROR1(" are case-sensitive. DO NOT USE capital"); ERROR1(" letters in the keywords.\n"); exit(GP_FAIL); } } if (!net_type) { ERROR1("\n\nNet type must be specified for analog nets"); ERROR2(".\nNo net type is specified for net %s\n", netName); exit(GP_FAIL); } DIGITAL = FALSE; } else if (strncmp(tokens[0], "common_point", 12) == STRINGEQ) { numcomms++; Pnew = (C_LISTPTR) Ysafe_malloc(sizeof(C_LIST)); Pnew->numpin = atoi(tokens[1]); Pnew->cap_match = FALSE; Pnew->res_match = FALSE; Pnew->next = Plist; Plist = Pnew; COMMON_POINT = TRUE; } else if (strncmp(tokens[0], "pin", 3) == STRINGEQ || strncmp(tokens[0], "equiv", 5) == STRINGEQ) { Ppin = (PINPTR) Ysafe_malloc(sizeof(PIN)); if (tokens[0][0] == 'e') { /********************************************************* * This pin is an equivalent pin of the previous pin(s). *********************************************************/ EQUIVAL = TRUE; if (Pfirst->equiv) { Ppin->equiv = Pfirst->equiv; } else { Ppin->equiv = ++equiv; Pfirst->equiv = equiv; } } else { Ppin->equiv = FALSE; } Ppin->node[0] = v1 = atoi(tokens[5]); Ppin->node[1] = v2 = atoi(tokens[6]); Ppin->shifted = FALSE; Ppin->vertex = ++numpins; Ppin->pin[0] = Ppin->pin[1] = 0; Ppin->dist[0] = atoi(tokens[8]); if (numtokens == ANALOG_PIN) { Ppin->density = atoi(tokens[11]); } else { Ppin->density = 0; } /*********************************************************** * Find the edge index of the channel on which the pin is * located. This is for removing the rectilinear restriction. ***********************************************************/ Pnode = garray[v1]->first; while (Pnode->t_vertex != v2) { Pnode = Pnode->next; } Ppin->dist[1] = Pnode->length - Ppin->dist[0]; /********************************************************* * Check if the pin overlaps with a vertex of the channel * graph. If so, we have to shift the pin along the channel * a bit due to the data structure. *********************************************************/ if (!(Ppin->dist[0])) { /***************************************************** * The pin overlaps with vertex v1 of the channel * graph. *****************************************************/ Ppin->dist[0]++; Ppin->dist[1]--; Ppin->shifted = 1; SHIFTED = TRUE; } if (!(Ppin->dist[1])) { /***************************************************** * The pin overlaps with vertex v2 of the channel * graph. *****************************************************/ Ppin->dist[0]--; Ppin->dist[1]++; Ppin->shifted = -1; SHIFTED = TRUE; } Ppin->next = Pfirst; Pfirst = Ppin; } else if (strncmp(tokens[0], "cap_match", 9) == STRINGEQ) { Pnew->cap_match = TRUE; } else if (strncmp(tokens[0], "res_match", 9) == STRINGEQ) { Pnew->res_match = TRUE; } else { ERROR1("\n\n"); ERROR2("Unknown keyword \"%s\" in the record ", tokens[0]); ERROR2("for the net %s\n", netName); exit(GP_FAIL); } } if (numpins) { /*********************************************************** * Make an array for the list of pins. ***********************************************************/ pin = numpins; parray = (PINPTR *) Ysafe_malloc((numpins+1) * sizeof(PINPTR)); while (Pfirst) { parray[pin--] = Pfirst; Pfirst = Pfirst->next; } } if (EQUIVAL == TRUE) { /*********************************************************** * Make each group of equivalent pins a circular linked list * which will be used to construct the segment tree. ***********************************************************/ for (i = 1; i <= numpins ;) { if (parray[i]->equiv) { v1 = i; v2 = i + 1; pin = parray[i]->equiv; while (v2 <= numpins && parray[v2]->equiv == pin) { parray[v1]->next = parray[v2]; v1++; v2++; } parray[v1]->next = parray[i]; i = v2; } else { parray[i]->next = NIL(PIN); i++; } } /*********************************************************** * Check each set of equivalent pins on their geometric * positions and make sure that they are NOT on top each * other. ***********************************************************/ for (i = 1; i <= numpins; i++) { if (parray[i]->next) { /********************************************************* * A set of equivalent pins is found. Check each pair of * the equivalent pins in the set and make sure that none * of them are on top each other. *********************************************************/ Pfirst = parray[i]; while (Pfirst->next != parray[i]) { for (Ppin = Pfirst->next; Ppin != Pfirst; Ppin = Ppin->next) { if (Pfirst->dist[0] == Ppin->dist[0] && Pfirst->node[0] == Ppin->node[0] && Pfirst->node[1] == Ppin->node[1]) { ERROR1("\n\n"); ERROR1("FATAL ERROR: Equivalent pins are "); ERROR1("on top each other in the net "); ERROR2("%s.\nMust exit. Sorry!\n\n", netName); exit(GP_FAIL); } } Pfirst = Pfirst->next; } } } } else { /*********************************************************** * There are equivalent pins in this net. Clean the field * next in parray. ***********************************************************/ for (i = 1; i <= numpins; i++) { parray[i]->next = NIL(PIN); } } if (COMMON_POINT != FALSE) { /*********************************************************** * There exit common pins in this net. Make sure the common * pins have no equivalent pins to them. Mickey can not * handle common pins with equivalent pins. ***********************************************************/ v1 = 0; Pnew = Plist; while (Pnew) { v2 = Pnew->numpin; for (i = ++v1; i < v2; i++) { if (parray[i]->next) { ERROR1("\n\nMickey can not handle pins which are"); ERROR1(" equivalent pins\n and"); ERROR1(" are to be connected to a common point\n"); exit(GP_FAIL); } parray[i]->next = parray[i+1]; } parray[i]->next = parray[v1]; v1 = i + 1; Pnew = Pnew->next; } while (Plist) { Pnew = Plist; Plist = Plist->next; Ysafe_free((char *) Pnew); } } return(numpins); } /* end of read_one_net */
ERRORPTR buildYGraph() { int i ; /* counter */ int overlapx ; /* overlap conditions in x direction */ int overlapy ; /* overlap conditions in y direction */ int sortbyYX() ; /* sort the tiles Y then X */ int left, right ; /* coordinates of tiles */ int bottom, top ; /* coordinates of tiles */ BOOL firstPick ; /* TRUE if first picket which matches */ BOOL possibleEdgetoSource; /* TRUE if this could be edge to source */ BOOL *yancestorB ; /* TRUE for a cell if cell has B ancestors */ BOOL *yancestorF ; /* TRUE for a cell if cell has F ancestors */ COMPACTPTR candidate ; /* this is the tile in question */ COMPACTPTR t ; /* this is the current picket */ PICKETPTR freepick ; /* used to free the pickets at the end */ PICKETPTR curPick ; /* traverse the pickets */ PICKETPTR lowerLimit ; /* first picket tile overlaps/touches */ PICKETPTR upperLimit ; /* last picket tile overlaps or touches */ ERRORPTR errorPtr ; /* form a list of errors to be processed*/ ERRORPTR lasterror ; /* last error in list */ ERRORPTR violations ; /* head of the error list */ /* initialize error list */ lasterror = NULL ; violations = NULL ; yancestorB = (BOOL *) Ysafe_calloc( last_cellG+1,sizeof(BOOL) ) ; yancestorF = (BOOL *) Ysafe_calloc( last_cellG+1,sizeof(BOOL) ) ; inityPicket() ; /* yGraphG is now initialized */ /* sort by ymin xmin of the bounding box */ /* we give it two chances - second time we expand core if necessary */ for( i=0; i <= 1 ; i++ ){ Yquicksort((char *)yGraphG,numtilesG+2,sizeof(COMPACTPTR),sortbyYX); if( yGraphG[SOURCE]->cell == YSOURCEC && yGraphG[SINK]->cell == YSINKC ){ break ; } else { find_core( &left, &right, &bottom, &top ) ; /* expand core region */ t = tileNodeG[YSOURCE] ; t->b = bottom ; t->t = t->b ; t = tileNodeG[YSINK] ; t->b = top ; t->t = t->b ; } } if( yGraphG[SOURCE]->cell != YSOURCEC || yGraphG[SINK]->cell != YSINKC ){ M( ERRMSG, "ycompact", "Fatal error in configuration\n" ) ; if( graphicsG ){ G( TWcloseGraphics() ) ; } YexitPgm( PGMFAIL ) ; } for( i=1 ; i<= numtilesG ; i++ ){ firstPick = TRUE ; lowerLimit = NULL ; upperLimit = NULL ; possibleEdgetoSource = FALSE ; candidate = yGraphG[i] ; /* search thru picket list for adjacencies */ for( curPick=leftPickS;curPick;curPick=curPick->next){ overlapx = projectX( curPick->pt2.lft, curPick->pt1.rght, candidate->l, candidate->r) ; if( overlapx > 0 ){ /* allow touching */ /* save span of overlap */ if( firstPick ){ lowerLimit = curPick ; firstPick = FALSE ; } upperLimit = curPick ; t = tileNodeG[curPick->node] ; /* multiple tile case - no error possible */ if( candidate->cell == t->cell ){ continue ; } /* check for errors */ overlapy = projectY( t->b, t->t, candidate->b, candidate->t ) ; if( overlapx > 0 && overlapy > 0 ){ /* save violations - add to violation list */ if( lasterror ){ errorPtr = (ERRORPTR) Ysafe_malloc( sizeof(ERRORBOX) ) ; lasterror->next = errorPtr ; lasterror = errorPtr ; } else { violations = errorPtr = lasterror = (ERRORPTR) Ysafe_malloc( sizeof(ERRORBOX) ) ; } errorPtr->next = NULL ; errorPtr->nodeI = candidate->node ; errorPtr->nodeJ = t->node ; /* for debug only : sprintf( YmsgG, Overlap detected: cell %d and cell %d\n", candidate->cell, t->cell ) ; M( MSG, NULL, YmsgG ) ; */ } ASSERT( t->node == curPick->node, "buildCGraph", "tileNodeG != curPick. Problem \n" ) ; /* form edge on only first occurance of cell */ if( t->node == numtilesG+2 ){ /* source node */ /* delay adding this edge */ possibleEdgetoSource = TRUE ; } else { formyEdge( t->node, candidate->node ) ; } } else if( upperLimit ){ /* we are past the upper limit so break & save time */ break ; } } ASSERT( lowerLimit, "compact", "lowerLimit is NULL" ) ; ASSERT( upperLimit, "compact", "lowerLimit is NULL" ) ; if( possibleEdgetoSource && yancestorF[candidate->cell] == FALSE ){ /* no need to make an edge to source if we already */ /* have an ancestor. Always make sure it is one of the lowest */ /* nodes of the multi-tiled cell */ formyEdge( numtilesG+2, cellarrayG[candidate->cell]->ylo ) ; yancestorF[candidate->cell] = TRUE ; } update_ypicket( i, lowerLimit, upperLimit ) ; } /* end for loop */ /* process sink last */ /* search thru picket list for adjacencies */ for( curPick=leftPickS;curPick;curPick=curPick->next){ /* remaining pickets must necessarily overlap sink */ t = tileNodeG[curPick->node] ; ASSERT( t->node == curPick->node, "buildCGraph", "tileNodeG != curPick. Problem \n" ) ; if( curPick->node != numtilesG+2 && /* avoid the source */ yancestorB[t->cell] == FALSE ){ /* no parents */ formyEdge( cellarrayG[t->cell]->yhi, yGraphG[last_tileG]->node ) ; yancestorB[t->cell] = TRUE ; } } /* now add multiple tile edges to graph. Precomputed in multi.c */ add_mtiles_to_ygraph() ; cleanupGraph( YFORWARD ) ; cleanupGraph( YBACKWARD ) ; Ysafe_free( yancestorB ) ; Ysafe_free( yancestorF ) ; /* delete all pickets */ for( curPick = leftPickS; curPick ; ) { freepick = curPick ; curPick = curPick->next ; Ysafe_free( freepick ) ; } return( violations ) ; } /* end buildYGraph */
void output() { FILE *fpp1 , *fpp2 ; INT locx , locy , height , width ; INT xloc , i , cell , block , orient ; INT num ; INT xloc2 , yloc2 , yloc ; INT *array , desire , k , limit ; INT left , right , bottom , top , end ; INT *deleted_feeds ; INT eliminated_feeds ; char filename[LRECL] , ctmp[32] ; CBOXPTR cellptr ; TIBOXPTR tptr ; PADBOXPTR pptr ; /* added on 06/01/90 Sury */ INT length; INT row ; char instance_name[LRECL], tmp_name[LRECL], *tmp_string; deleted_feeds = (INT *) Ysafe_malloc( numcellsG * sizeof(INT) ) ; eliminated_feeds = 0 ; sprintf( filename , "%s.pl1" , cktNameG ) ; fpp1 = TWOPEN( filename , "w", ABORT ) ; sprintf( filename , "%s.pl2" , cktNameG ) ; fpp2 = TWOPEN( filename , "w", ABORT ) ; for( block = 1 ; block <= numRowsG ; block++ ) { left = barrayG[block]->bxcenter + barrayG[block]->bleft ; right = barrayG[block]->bxcenter + barrayG[block]->bright ; bottom = barrayG[block]->bycenter + barrayG[block]->bbottom ; top = barrayG[block]->bycenter + barrayG[block]->btop ; if( restartG == 0 && costonlyG == 1 ) { desire = barrayG[block]->desire ; } else { if( pairArrayG[block][0] > 0 ) { cell = pairArrayG[block][ pairArrayG[block][0] ] ; end = carrayG[cell]->cxcenter + carrayG[cell]->tileptr ->right ; desire = end - left ; } else { desire = 0 ; } } if( barrayG[block]->borient > 0 ) { fprintf(fpp2,"%d %d %d %d %d 0 0\n", block , left, bottom, left + desire, top ) ; } else { fprintf(fpp2,"%d %d %d %d %d 0 0\n", block , left, bottom, right, bottom + desire ) ; } num = pairArrayG[block][0] ; if( num == 0 ) { continue ; } array = pairArrayG[block] + 1 ; for( i = 0 ; i < num ; i++ ) { cell = array[ i ] ; cellptr = carrayG[ cell ] ; if( cellptr->clength == 0 ){ continue ; } if( strcmp( cellptr->cname , "TW_EXCEPT" ) == 0 ) { continue ; } if( stand_cell_as_gate_arrayG ) { if( strcmp( cellptr->cname , "GATE_ARRAY_SPACER" ) == 0 ) { continue ; } } if( unused_feed_name_twspacerG ) { if( strncmp(cellptr->cname,"twfeed",6) == STRINGEQ ) { if( tearrayG[cellptr->imptr->terminal] == NULL ) { strcpy( ctmp , cellptr->cname ) ; cellptr->cname = (char *) Ysafe_realloc( cellptr->cname, (strlen(cellptr->cname)+3) * sizeof(char) ) ; sprintf( cellptr->cname , "%s%s" , "twspacer", strpbrk(ctmp, "0123456789") ) ; } } } orient = cellptr->corient ; xloc = cellptr->cxcenter + cellptr->tileptr->left ; yloc = cellptr->cycenter + cellptr->tileptr->bottom ; xloc2 = cellptr->tileptr->right - cellptr->tileptr->left ; yloc2 = cellptr->tileptr->top - cellptr->tileptr->bottom ; /* The following code was added on 06/01/90 Sury */ #ifdef NSC strcpy( tmp_name , cellptr->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpp1,"%s %d %d %d %d %d %d\n", instance_name, xloc, yloc, xloc + xloc2, yloc + yloc2, orient, block ) ; #else fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , xloc, yloc, xloc + xloc2, yloc + yloc2, orient, block ) ; #endif } } if( deleted_feeds[0] > 0 ) { fprintf(fpoG,"Confirming number of eliminated feeds:%d\n", eliminated_feeds ) ; } /* now output the pads and macros */ for( i = numcellsG + 1 ; i <= lastpadG ; i++ ) { cellptr = carrayG[ i ] ; orient = cellptr->corient ; tptr = cellptr->tileptr ; left = tptr->left ; right = tptr->right ; bottom = tptr->bottom ; top = tptr->top ; YtranslateT( &left, &bottom, &right, &top, orient ) ; locx = cellptr->cxcenter + left ; locy = cellptr->cycenter + bottom ; height = top - bottom ; width = right - left ; /* determine row */ pptr = cellptr->padptr ; if( pptr->macroNotPad ){ row = 0 ; } else { switch( pptr->padside ){ case L: row = - 1 ; break ; case T: row = -4 ; break ; case R: row = - 2 ; break ; case B: row = - 3 ; break ; default: M(ERRMSG,"output", "Unknown padside\n" ) ; } } #ifndef DEC /* The following code was added on 06/01/90 Sury */ #ifdef NSC strcpy( tmp_name , cellptr->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpp1,"%s %d %d %d %d %d %d\n", instance_name, locx, locy, locx + width, locy + height, orient, row ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", instance_name, locx, locy, locx + width, locy + height, orient, row ) ; #else /* normal case */ fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, row ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, row ) ; #endif #else /* DEC case */ fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, -cellptr->padside ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, -cellptr->padside ) ; #endif } TWCLOSE( fpp1 ) ; TWCLOSE( fpp2 ) ; if( create_new_cel_fileG ) { create_cel_file() ; } Ysafe_free( deleted_feeds ) ; return ; }
re_estimate_feed_penalty() { INT i , n , row , row_rite , excess_fd , *old_penalty ; DOUBLE ratio , factor ; FEED_DATA *feedptr ; CBOXPTR cellptr ; old_penalty = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { old_penalty[row] = rowfeed_penaltyG[row] ; feedptr = feedpptrG[row] ; n = 0 ; for( i = 1 ; i <= chan_node_noG ; i++ ) { n += feedptr[i]->needed ; } fd_estimateS[row] = n ; } estimate_pass_thru_penalty( 1 , numRowsG ) ; if( !enough_built_in_feedG ) { return ; } for( row = 1 ; row <= numRowsG ; row++ ) { rowfeed_penaltyG[row] = ( 2 * old_penalty[row] + 3 * rowfeed_penaltyG[row] ) / 5 ; cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; row_rite = cellptr->cxcenter + cellptr->tileptr->right ; if( fdWidthG > 0 ) { excess_fd = fdcel_addedG[row] + 1 - ( right_most_in_classG[ row_rite_classG[row] ] - row_rite ) / fdWidthG; } else { excess_fd = fdcel_addedG[row] + 1 - ( right_most_in_classG[ row_rite_classG[row] ] - row_rite ) ; } if( excess_fd <= 0 ) { continue ; } ratio = (DOUBLE)(fdcel_addedG[row]) / (DOUBLE)(FeedInRowG[row]) ; if( ratio <= 0.01 ) { factor = 4 ; } else if( ratio <= 0.03 ) { factor = 8 ; } else if( ratio <= 0.05 ) { factor = 15 ; } else if( ratio <= 0.08 ) { factor = 25 ; } else if( ratio <= 0.10 ) { factor = 30 ; } else if( ratio <= 0.20 ) { factor = 40 ; } else { factor = 50 ; } rowfeed_penaltyG[row] += factor * ratio * (DOUBLE)(rowHeightG) ; } /* fp = TWOPEN("vcost.dat", "a", ABORT ) ; fprintf(fp, " row newcost oldcost\n" ) ; for( row = 1 ; row <= numRowsG ; row++ ) { fprintf(fp," %3d %7d %7d\n", row, rowfeed_penaltyG[row], old_penalty[row] ) ; } TWCLOSE(fp) ; */ }