예제 #1
0
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;
}
}
예제 #2
0
/*=====================================================================
*   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 */
예제 #3
0
파일: findrcost.c 프로젝트: rubund/graywolf
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 ;
    }
}
}
예제 #4
0
init_unet()
{
    INT maxpin, get_max_pin() ;

    maxpin = get_max_pin() ;
    memoptrS = (PINBOXPTR *)
	Ysafe_malloc( (++maxpin) * sizeof(PINBOXPTR) ) ;

} /* end init_unet */
예제 #5
0
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 */
예제 #6
0
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 */
예제 #7
0
파일: sortpin.c 프로젝트: rubund/graywolf
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 */
예제 #8
0
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 */
예제 #9
0
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 ) ;
}
예제 #10
0
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 ;
    }
}
}
예제 #11
0
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 ;
}
예제 #12
0
파일: globroute.c 프로젝트: Fatsie/graywolf
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 ;
}
예제 #13
0
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 ) ;

}
예제 #14
0
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 );
}
예제 #15
0
파일: netgraph.c 프로젝트: radc/qflow
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 */
}
}
예제 #16
0
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 */
예제 #17
0
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 */
예제 #18
0
/*=====================================================================
*  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 */
예제 #19
0
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 */
예제 #20
0
파일: output.c 프로젝트: rubund/graywolf
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 ;
}
예제 #21
0
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) ;
*/
}