/* print out the current cost to the user */ void prnt_cost( char * out_string ) { INT xspan ; INT yspan ; funccostG = findcost() ; OUT2("%s", out_string ) ; OUT2(" routing cost :%d\n", funccostG ) ; OUT2(" overlap penalty :%d\n", binpenalG); OUT2(" lapFactor * overlap :%d\n", penaltyG); OUT2(" timing penalty :%d\n", timingpenalG ); OUT2("+ timeFactor * timepen:%d\n", timingcostG ); OUT1("-------------------------------------\n" ) ; OUT2(" total cost :%d\n", (funccostG + penaltyG + timingcostG) ) ; wirecosts() ; find_core_boundary( &blocklG, &blockrG, &blockbG, &blocktG ) ; OUT5("\n\nCORE Bounding Box: l:%d r:%d b:%d t:%d\n", blocklG , blockrG , blockbG , blocktG ) ; xspan = blockrG - blocklG ; yspan = blocktG - blockbG ; OUT2( " xspan = %d\n", xspan ) ; OUT2( " yspan = %d\n", yspan ) ; OUT2( " core area = %4.2le\n\n", (DOUBLE) xspan * (DOUBLE) yspan ); OUT1("-------------------------------------\n" ) ; Ymessage_flush() ; }/* end print_current_cost */
void initpop() { int i,j,k,*p,t; for(i=0;i<POP;i++) { pop[i].dataptr=i; p=popdata+i*chips; /* generate random permutation */ for(j=0;j<chips;j++) p[j]=j; for(j=chips-1;j>=1;j--) { k=rand()%(j+1); t=p[k]; p[k]=p[j]; p[j]=t; } fixind(p); pop[i].cost=findcost(p); pop[i].fitness=calcfitness(pop[i].cost); } }
finalout() { INT c ; INT bbtop, bbbottom, bbleft, bbright ; /* dump the results of the placement to graphics file */ G( graphics_dump() ) ; G( TWsetMode(1) ) ; G( draw_the_data() ) ; G( TWsetMode(0) ) ; /* we known wire area at this point don't need to estimate */ turn_wireest_on(FALSE) ; /* let the user know which pins we couldn't place */ set_pin_verbosity( TRUE ) ; /* before channel graph generation and global routing let use tweak */ /* placement if desired */ if( doGraphicsG && wait_for_userG ){ G( TWmessage( "TimberWolfMC waiting for your response" ) ) ; G( process_graphics() ) ; } savewolf( TRUE ) ; /* for debug purposes force save to occur */ if( scale_dataG > 1 ){ /* end of the line for scaled case - will return to parent to continue using saved placement. */ closegraphics() ; YexitPgm( PGMOK ) ; } grid_cells() ; /* force cells to grid locations */ compact(VIOLATIONSONLY); /* remove cell overlap */ /* if this is a partitioning run determine row placement */ if( doPartitionG && !(quickrouteG) ){ set_determine_side( FALSE ) ; /* allow SC to pick side */ G( set_graphic_context( PARTITION_PLACEMENT ) ) ; config_rows() ; print_paths() ; /* print path information */ Output( 0 ) ; return ; } /* do final placement of pads using virtual core to insure pads */ /* are outside of core */ setVirtualCore( TRUE ) ; placepads() ; /* before channel graph generation and global routing let use tweak */ /* placement if desired */ check_graphics() ; if( !scale_dataG ){ /* reload bins to get new overlap penalty */ loadbins(FALSE) ; /* wireArea not known */ } prnt_cost( "\nFINAL PLACEMENT RESULTS AFTER VIOLATION REMOVAL ARE:\n" ) ; print_paths() ; /* print path information */ Output( 0 ) ; if( doCompactionG > 0 || quickrouteG ) { gmain( CHANNELGRAPH ) ; rmain( NOCONSTRAINTS ) ; gmain( UPDATE_ROUTING ) ; adapt_wire_estimator() ; check_graphics() ; if( quickrouteG ){ return ; } for( c = 1 ; c <= doCompactionG ; c++ ) { funccostG = findcost() ; sprintf(YmsgG,"\n\nCompactor Pass Number: %d begins with:\n", c ) ; prnt_cost( YmsgG ) ; wirecosts() ; grid_cells() ; /* force cells to grid locations */ compact(COMPACT); /* remove white space */ reorigin() ; check_graphics() ; sprintf(YmsgG,"\n\nCompactor Pass Number: %d after cost:\n", c ) ; prnt_cost( YmsgG ) ; Output( c ) ; gmain( CHANNELGRAPH ) ; if( c == doCompactionG ){ rmain( CONSTRAINTS ) ; } else { rmain( NOCONSTRAINTS ) ; gmain( UPDATE_ROUTING ) ; adapt_wire_estimator() ; check_graphics() ; } } /* end compaction - global route loop */ } else { if( doChannelGraphG ) { gmain( CHANNELGRAPH ) ; } if( doGlobalRouteG ) { rmain( CONSTRAINTS ) ; } } prnt_cost("\nTIMBERWOLFMC FINAL RESULTS ARE:\n" ) ; return ; } /* end finalout */
void ga() { static char taken[MAXCHIPS]; double prob; int gen=1,i,j,k,ix,iy,a,b,t,*p,*q,*r,rev; int best=-1; popdata=malloc(sizeof(int)*chips*(POP+CAND)); if(!popdata) error("out of memory"); initpop(); while(1) { if(gen%100==0) printf("start of generation %d\n",gen); gen++; qsort(pop,POP,sizeof(ind_t),compo); if(best!=pop[0].cost) { best=pop[0].cost; printind(0); } normalizecumul(); nextp=POP; for(i=0;i<CAND;i++) { again: prob=rand01(); if(prob<UNI1) { /* mutation operator 1: swap 2 nodes */ ix=pickparent(); copyind(POP+i,ix); /* swap 2 random elements */ a=rand()%chips; do b=rand()%chips; while(a==b); p=popdata+pop[POP+i].dataptr*chips; t=p[a]; p[a]=p[b]; p[b]=t; fixind(p); if(!compo(pop+POP+i,pop+ix)) goto again; /* if no change, discard */ pop[POP+i].cost=findcost(p); pop[POP+i].fitness=calcfitness(pop[POP+i].cost); nextp++; } else if(prob<UNI1+UNI2) { /* mutation operator 2: move 1 node */ ix=pickparent(); copyind(POP+i,ix); /* pick random element, and new position for it */ a=rand()%chips; do b=rand()%chips; while(a==b); p=popdata+pop[ix].dataptr*chips; q=popdata+pop[POP+i].dataptr*chips; for(j=0;j<chips;j++) q[j]=-1; q[b]=p[a]; for(j=k=0;j<chips;j++) if(j!=a) { while(k<chips && q[k]>-1) k++; if(k==chips) printf("sanity error"); q[k++]=p[j]; } fixind(q); pop[POP+i].cost=findcost(p); pop[POP+i].fitness=calcfitness(pop[POP+i].cost); nextp++; } else { /* crossover operator: copy substring from parent 1, take remaining nodes from parent 2 in order of occurrence */ ix=pickparent(); do iy=pickparent(); while(ix==iy); copyind(POP+i,iy); a=rand()%chips; b=rand()%chips; if(a>b) t=a,a=b,b=t; b++; do t=rand()%chips; while(t+b-a>chips); rev=rand()&1; p=popdata+pop[ix].dataptr*chips; q=popdata+pop[iy].dataptr*chips; r=popdata+pop[POP+i].dataptr*chips; for(k=0;k<chips;k++) r[k]=-1; for(k=0;k<chips;k++) taken[k]=0; if(rev) for(j=0;j<b-a;j++) taken[p[j+a]]++,r[t+b-a-j-1]=p[j+a]; else for(k=a;k<b;k++) taken[p[k]]++,r[k+t-a]=p[k]; for(k=j=0;k<chips;k++) if(!taken[q[k]]) { while(j<chips && r[j]>-1) j++; if(j==chips) printf("sanity error"); r[j++]=q[k]; } fixind(r); if(!compo(pop+POP+i,pop+ix)) goto again; /* if no change, discard */ if(!compo(pop+POP+i,pop+iy)) goto again; /* if no change, discard */ pop[POP+i].cost=findcost(r); pop[POP+i].fitness=calcfitness(pop[POP+i].cost); nextp++; } } /* sort all children */ qsort(pop+POP,CAND,sizeof(ind_t),compo); /* ensure we only have unique elitists */ /* here shallow copy is ok! */ if(ELITISM) for(j=i=1;i<ELITISM;i++) { if(compo(pop+i,pop+i-1)) pop[j++]=pop[i]; } else j=0; pop[j++]=pop[POP]; /* ensure we only have unique children */ for(i=POP+1;j<POP && i<POP+CAND;i++) if(compo(pop+i,pop+i-1)) pop[j++]=pop[i]; if(j<POP) error("ga failed, need more unique children"); compress(); } }
/* perform a low temperature anneal on pins */ final_pin_place() { INT i ; /* counter */ INT attempts ; /* number of moves made */ INT nummoves ; /* number of moves to do on a cell */ INT selection ; /* select a cell with softpins */ INT nsoftpin_cells ; /* number of cells with softpins */ CELLBOXPTR acellptr; /* current cell with softpins */ /* don't perform if cost only is specified in input file */ /* scale data variable is necessary for recursive TimberWolfMC call */ if( /* cost_onlyG || */ scale_dataG > 1 ){ return ; } /* now check to see if we have any soft pins if not return */ if( (nsoftpin_cells = (int) softPinArrayG[HOWMANY] ) == 0 ){ return ; } /* make new site arrays for pins */ for( i = 1; i <= nsoftpin_cells; i++ ){ update_sites( softPinArrayG[i] ) ; } findcost() ; /* continue with a low Temp anneal */ TG = 10.0 ; attempts = 0 ; if( overpenalG ){ /* make pinFactor 1 order more important than wirelength */ pinFactorG = 10.0 * (DOUBLE) funccostG / (DOUBLE) overpenalG ; /* also set softPinArrayG to look at cells with overlap */ } else { /* otherwise use previous pinFactorG */ /* make 1 order more important */ pinFactorG *= 10.0 ; } while( attempts < attmaxG ) { /* to make pin moves more efficient, use softPinArrayG */ /* which keeps track of all softcells which have pins */ /* which can move. softPinArrayG[0] holds size of array */ selection = PICK_INT( 1, (int) softPinArrayG[HOWMANY] ); /* now get cellptr */ acellptr = softPinArrayG[selection] ; /* pick number of pins moves to be attempted */ /* PIN_MOVE is beginning of sequence. */ if( overpenalG && !(doPartitionG) ){ /* if a penalty exists do many moves */ nummoves = acellptr->numsoftpins ; } else { nummoves = 1 ; /* no penalty try to reduce wirelen */ } /* *********** NOW EVALUATE THE PROPOSED MOVE ********* */ /* now try softpin moves */ for( i=1; i<= nummoves; i++ ){ selectpin( acellptr ) ; } /* *********** END OF PROPOSED MOVE EVALUATION ********* */ attempts++ ; D( "finalpin", checkcost() ) ; /* if debug on check cost after each move */ } /* ****** END OF ANNEALING LOOP **************** */ /* verify incremental and current costs after each iteration */ D( "finalpin", checkcost() ) ; /* ----------------------------------------------------------------- now output statistics for this temperature. */ OUT1("\n\nPin place optimizer\n"); OUT1("\nI T funccost overpen x pinFact = overfill pinflips\n"); OUT2("%3d ",iterationG ); OUT2("%4.2le ",TG ); OUT2("%4.2le ",(DOUBLE) funccostG ); OUT2("%4.2le ",(DOUBLE) overpenalG ); OUT2("%4.2le ",(DOUBLE) pinFactorG ); OUT2("%4.2le ",(DOUBLE) overfillG ); OUT3("%3d/%3d\n\n",flippG,attpG ); FLUSHOUT() ; return ; } /* end final_pin_place */