⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 place.c

📁 fpga设计评估软件
💻 C
📖 第 1 页 / 共 5 页
字号:
  /*computes net_pin_index array, this array allows us to quickley*/  /*find what pin on the net a block pin corresponds to */  int inet, netpin, blk, iblk, ipin;  /*initialize values to OPEN */  for (iblk=0; iblk<num_blocks; iblk++)    for (ipin=0; ipin < pins_per_clb; ipin++)      net_pin_index[iblk][ipin] = OPEN;  for (inet=0; inet<num_nets; inet++) {    if (is_global[inet])       continue;    for(netpin=0;netpin<net[inet].num_pins;netpin++) {      blk=net[inet].blocks[netpin];      if (block[blk].type == INPAD)	net_pin_index[blk][0] = 0; /*there is only one block pin,so it is 0, and it */                                   /*is driving the net since this is an INPAD*/      else if (block[blk].type == OUTPAD) 	net_pin_index[blk][0] = netpin;  /*there is only one block pin,it is 0*/      else {	net_pin_index[blk][net[inet].blk_pin[netpin]] = netpin;      }      }    }}static double get_std_dev (int n, double sum_x_squared, double av_x) {/* Returns the standard deviation of data set x.  There are n sample points, * * sum_x_squared is the summation over n of x^2 and av_x is the average x.   * * All operations are done in double precision, since round off error can be * * a problem in the initial temp. std_dev calculation for big circuits.      */ double std_dev;  if (n <= 1)     std_dev = 0.; else     std_dev = (sum_x_squared - n * av_x * av_x) / (double) (n - 1); if (std_dev > 0.)        /* Very small variances sometimes round negative */    std_dev = sqrt (std_dev); else    std_dev = 0.; return (std_dev);}static void update_rlim (float *rlim, float success_rat) { /* Update the range limited to keep acceptance prob. near 0.44.  Use *  * a floating point rlim to allow gradual transitions at low temps.  */ float upper_lim; *rlim = (*rlim) * (1. - 0.44 + success_rat); upper_lim = max(nx,ny); *rlim = min(*rlim,upper_lim); *rlim = max(*rlim,1.);  /* *rlim = (float) nx; */}static void update_t (float *t, float std_dev, float rlim,      float success_rat, struct s_annealing_sched annealing_sched) {/* Update the temperature according to the annealing schedule selected. *//*  float fac; */ if (annealing_sched.type == USER_SCHED) {    *t = annealing_sched.alpha_t * (*t); }/* Old standard deviation based stuff is below.  This bogs down hopelessly * * for big circuits (alu4 and especially bigkey_mod).                      *//* #define LAMBDA .7  *//* ------------------------------------ *//* else if (std_dev == 0.) {      *t = 0.; } else {    fac = exp (-LAMBDA*(*t)/std_dev);    fac = max(0.5,fac);       *t = (*t) * fac; }   *//* ------------------------------------- */ else {                             /* AUTO_SCHED */    if (success_rat > 0.96) {       *t = (*t) * 0.5;     }    else if (success_rat > 0.8) {       *t = (*t) * 0.9;    }    else if (success_rat > 0.15 || rlim > 1.) {       *t = (*t) * 0.95;    }    else {       *t = (*t) * 0.8;     } }}static int exit_crit (float t, float cost, struct s_annealing_sched          annealing_sched) {/* Return 1 when the exit criterion is met.                        */ if (annealing_sched.type == USER_SCHED) {    if (t < annealing_sched.exit_t) {       return(1);    }    else {       return(0);    } }   /* Automatic annealing schedule */ if (t < 0.005 * cost / num_nets) {    return(1); } else {    return(0); }}static float starting_t (float *cost_ptr, float *bb_cost_ptr, float *timing_cost_ptr,    int *pins_on_block, int place_cost_type, float **old_region_occ_x,     float **old_region_occ_y, int num_regions, boolean fixed_pins,     struct s_annealing_sched annealing_sched, int max_moves, float rlim,     enum e_place_algorithm place_algorithm, float timing_tradeoff,    float inverse_prev_bb_cost, float inverse_prev_timing_cost, float *delay_cost_ptr) {/* Finds the starting temperature (hot condition).              */ int i, num_accepted, move_lim; double std_dev, av, sum_of_squares;  /* Double important to avoid round off */ if (annealing_sched.type == USER_SCHED)     return (annealing_sched.init_t);   move_lim = min (max_moves, num_blocks); num_accepted = 0; av = 0.; sum_of_squares = 0.;/* Try one move per block.  Set t high so essentially all accepted. */ for (i=0;i<move_lim;i++) {    if (try_swap (1.e30, cost_ptr, bb_cost_ptr, timing_cost_ptr, rlim,               pins_on_block, place_cost_type,              old_region_occ_x, old_region_occ_y, num_regions,               fixed_pins, place_algorithm, timing_tradeoff,	      inverse_prev_bb_cost, inverse_prev_timing_cost,	      delay_cost_ptr) == 1) {       num_accepted++;        av += *cost_ptr;       sum_of_squares += *cost_ptr * (*cost_ptr);    }    }   /* Initial Temp = 20*std_dev. */ if (num_accepted != 0)    av /= num_accepted; else     av = 0.;  std_dev = get_std_dev (num_accepted, sum_of_squares, av); #ifdef DEBUG if (num_accepted != move_lim) {    printf("Warning:  Starting t: %d of %d configurations accepted.\n",        num_accepted, move_lim); }#endif#ifdef VERBOSE    printf("std_dev: %g, average cost: %g, starting temp: %g\n",        std_dev, av, 20. * std_dev);#endif return (20. * std_dev); /* return (15.225523	); */}static int try_swap (float t, float *cost, float *bb_cost, float *timing_cost, 		     float rlim, int *pins_on_block, 		     int place_cost_type, float **old_region_occ_x, 		     float **old_region_occ_y, int num_regions, boolean fixed_pins,		     enum e_place_algorithm place_algorithm, float timing_tradeoff,		     float inverse_prev_bb_cost, float inverse_prev_timing_cost,		     float *delay_cost) {/* Picks some block and moves it to another spot.  If this spot is   * * occupied, switch the blocks.  Assess the change in cost function  * * and accept or reject the move.  If rejected, return 0.  If        * * accepted return 1.  Pass back the new value of the cost function. *  * rlim is the range limiter.  pins_on_block gives the number of     * * pins on each type of block (improves efficiency).                 */ int b_from, x_to, y_to, x_from, y_from, b_to;  int off_from, k, inet, keep_switch, io_num, num_of_pins; int num_nets_affected, bb_index; float delta_c, bb_delta_c, timing_delta_c, delay_delta_c, newcost; static struct s_bb *bb_coord_new = NULL; static struct s_bb *bb_edge_new = NULL; static int *nets_to_update = NULL, *net_block_moved = NULL;/* Allocate the local bb_coordinate storage, etc. only once. */ if (bb_coord_new == NULL) {    bb_coord_new = (struct s_bb *) my_malloc (2 * pins_per_clb *           sizeof (struct s_bb));    bb_edge_new = (struct s_bb *) my_malloc (2 * pins_per_clb *          sizeof (struct s_bb));    nets_to_update = (int *) my_malloc (2 * pins_per_clb * sizeof (int));    net_block_moved = (int *) my_malloc (2 * pins_per_clb * sizeof (int)); }     b_from = my_irand(num_blocks - 1);/* If the pins are fixed we never move them from their initial    * * random locations.  The code below could be made more efficient * * by using the fact that pins appear first in the block list,    * * but this shouldn't cause any significant slowdown and won't be * * broken if I ever change the parser so that the pins aren't     * * necessarily at the start of the block list.                    */ if (fixed_pins == TRUE) {    while (block[b_from].type != CLB) {       b_from = my_irand(num_blocks - 1);    } } x_from = block[b_from].x; y_from = block[b_from].y; find_to (x_from, y_from, block[b_from].type, rlim, &x_to, &y_to);/* Make the switch in order to make computing the new bounding * * box simpler.  If the cost increase is too high, switch them * * back.  (block data structures switched, clbs not switched   * * until success of move is determined.)                       */ if (block[b_from].type == CLB) {    io_num = -1;            /* Don't need, but stops compiler warning. */    if (clb[x_to][y_to].occ == 1) {         /* Occupied -- do a switch */       b_to = clb[x_to][y_to].u.block;       block[b_from].x = x_to;       block[b_from].y = y_to;       block[b_to].x = x_from;       block[b_to].y = y_from;     }        else {       b_to = EMPTY;       block[b_from].x = x_to;       block[b_from].y = y_to;     } } else {   /* io block was selected for moving */    io_num = my_irand(io_rat - 1);    if (io_num >= clb[x_to][y_to].occ) {  /* Moving to an empty location */       b_to = EMPTY;       block[b_from].x = x_to;       block[b_from].y = y_to;    }    else {          /* Swapping two blocks */       b_to = *(clb[x_to][y_to].u.io_blocks+io_num);       block[b_to].x = x_from;       block[b_to].y = y_from;       block[b_from].x = x_to;       block[b_from].y = y_to;    } }/* Now update the cost function.  May have to do major optimizations * * here later.                                                       *//* I'm using negative values of temp_net_cost as a flag, so DO NOT   * * use cost functions that can go negative.                          */ delta_c = 0;                    /* Change in cost due to this swap. */ bb_delta_c = 0; timing_delta_c = 0; num_of_pins = pins_on_block[block[b_from].type];     num_nets_affected = find_affected_nets (nets_to_update, net_block_moved,      b_from, b_to, num_of_pins); if (place_cost_type == NONLINEAR_CONG) {    save_region_occ (old_region_occ_x, old_region_occ_y, num_regions); } bb_index = 0;               /* Index of new bounding box. */ for (k=0;k<num_nets_affected;k++) {    inet = nets_to_update[k];/* If we swapped two blocks connected to the same net, its bounding box * * doesn't change.                                                      */    if (net_block_moved[k] == FROM_AND_TO)        continue;    if (net[inet].num_pins <= SMALL_NET) {       get_non_updateable_bb (inet, &bb_coord_new[bb_index]);    }    else {       if (net_block_moved[k] == FROM)           update_bb (inet, &bb_coord_new[bb_index], &bb_edge_new[bb_index],             x_from, y_from, x_to, y_to);             else          update_bb (inet, &bb_coord_new[bb_index], &bb_edge_new[bb_index],             x_to, y_to, x_from, y_from);          }    if (place_cost_type != NONLINEAR_CONG) {       temp_net_cost[inet] = get_net_cost (inet, &bb_coord_new[bb_index]);       bb_delta_c += temp_net_cost[inet] - net_cost[inet];    }    else {           /* Rip up, then replace with new bb. */       update_region_occ (inet, &bb_coords[inet], -1, num_regions);         update_region_occ (inet, &bb_coord_new[bb_index],1, num_regions);    }    bb_index++; }    if (place_cost_type == NONLINEAR_CONG) {    newcost = nonlinear_cong_cost(num_regions);    bb_delta_c = newcost - *bb_cost; } if (place_algorithm == NET_TIMING_DRIVEN_PLACE ||     place_algorithm == PATH_TIMING_DRIVEN_PLACE) {      /*in this case we redefine delta_c as a combination of timing and bb.  *    *additionally, we normalize all values, therefore delta_c is in       *    *relation to 1*/      comp_delta_td_cost(b_from, b_to, num_of_pins, &timing_delta_c,			      &delay_delta_c);   delta_c = (1-timing_tradeoff) * bb_delta_c * inverse_prev_bb_cost +      timing_tradeoff * timing_delta_c * inverse_prev_timing_cost; } else {   delta_c = bb_delta_c; }  keep_switch = assess_swap (delta_c, t);  /* 1 -> move accepted, 0 -> rejected. */  if (keep_switch) {    *cost = *cost + delta_c;        *bb_cost = *bb_cost + bb_delta_c;    if (place_algorithm == NET_TIMING_DRIVEN_PLACE ||	place_algorithm == PATH_TIMING_DRIVEN_PLACE) {            /*update the point_to_point_timing_cost and point_to_point_delay_cost 	values from the temporary values*/      *timing_cost = *timing_cost + timing_delta_c;      *delay_cost = *delay_cost + delay_delta_c;      update_td_cost(b_from, b_to, num_of_pins);    } /* update net cost functions and reset flags. */    bb_index = 0;    for (k=0;k<num_nets_affected;k++) {       inet = nets_to_update[k];/* If we swapped two blocks connected to the same net, its bounding box * * doesn't change.                                                      */       if (net_block_moved[k] == FROM_AND_TO) {          temp_net_cost[inet] = -1;            continue;       }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -