static void build_rr_clb (int **rr_node_indices, int Fc_output, int ***
       clb_opin_to_tracks, int nodes_per_chan, int i, int j, int 
       delayless_switch, t_seg_details *seg_details_x, t_seg_details 
       *seg_details_y) {

/* Load up the rr_node structures for the clb at location (i,j).  I both  *
 * fill in fields that shouldn't change during the entire routing and     *
 * initialize fields that will change to the proper starting value.       */

 int ipin, iclass, inode, pin_num, to_node, num_edges;
 t_linked_edge *edge_list_head;

/* SOURCES and SINKS first.   */

 for (iclass=0;iclass<num_class;iclass++) {
    if (class_inf[iclass].type == DRIVER) {    /* SOURCE */
       inode = get_rr_node_index (i, j, SOURCE, iclass, nodes_per_chan,
                 rr_node_indices);

       num_edges = class_inf[iclass].num_pins;
       rr_node[inode].num_edges = num_edges;
       rr_node[inode].edges = (int *) my_chunk_malloc (num_edges * 
              sizeof (int), &rr_mem_chunk_list_head, &chunk_bytes_avail, 
              &chunk_next_avail_mem);

       rr_node[inode].switches = (short *) my_chunk_malloc (num_edges *
              sizeof (short), &rr_mem_chunk_list_head, &chunk_bytes_avail,
              &chunk_next_avail_mem);

       for (ipin=0;ipin<class_inf[iclass].num_pins;ipin++) {
          pin_num = class_inf[iclass].pinlist[ipin];
          to_node = get_rr_node_index (i, j, OPIN, pin_num, nodes_per_chan,
                  rr_node_indices);
          rr_node[inode].edges[ipin] = to_node;
          rr_node[inode].switches[ipin] = delayless_switch;
       }

       rr_node_cost_inf[inode].capacity = class_inf[iclass].num_pins;
       rr_node_cost_inf[inode].base_cost = 1.;
       rr_node[inode].type = SOURCE;
    }

    else {    /* SINK */
       inode = get_rr_node_index (i, j, SINK, iclass, nodes_per_chan,
                 rr_node_indices);

/* Note:  To allow route throughs through clbs, change the lines below to  *
 * make an edge from the input SINK to the output SOURCE.  Do for just the *
 * special case of INPUTS = class 0 and OUTPUTS = class 1 and see what it  *
 * leads to.  If route throughs are allowed, you may want to increase the  *
 * base cost of OPINs and/or SOURCES so they aren't used excessively.      */

       rr_node[inode].num_edges = 0; 
       rr_node[inode].edges = NULL;
       rr_node[inode].switches = NULL;
       rr_node_cost_inf[inode].capacity = class_inf[iclass].num_pins;
       rr_node_cost_inf[inode].base_cost = 0.;
       rr_node[inode].type = SINK;
    }

/* Things common to both SOURCEs and SINKs.   */

    rr_node_cost_inf[inode].acc_cost = 0.;
    rr_node_cost_inf[inode].occ = 0;

    rr_node[inode].xlow = i;
    rr_node[inode].xhigh = i;
    rr_node[inode].ylow = j;
    rr_node[inode].yhigh = j;
    rr_node[inode].R = 0;
    rr_node[inode].C = 0;

    rr_node[inode].ptc_num = iclass;
 }

/* Now do the pins.  */

 for (ipin=0;ipin<pins_per_clb;ipin++) {
    iclass = clb_pin_class[ipin];
    if (class_inf[iclass].type == DRIVER) {  /* OPIN */
       inode = get_rr_node_index (i, j, OPIN, ipin, nodes_per_chan,
                 rr_node_indices);

       edge_list_head = NULL;
       num_edges = get_clb_opin_connections (clb_opin_to_tracks, ipin, i, j,
                   Fc_output, seg_details_x, seg_details_y, &edge_list_head, 
                   nodes_per_chan, rr_node_indices);

       alloc_and_load_edges_and_switches (inode, num_edges, edge_list_head);

       rr_node_cost_inf[inode].base_cost = 1.;
       rr_node[inode].type = OPIN;
    }
    else {                                   /* IPIN */
       inode = get_rr_node_index (i, j, IPIN, ipin, nodes_per_chan,
                 rr_node_indices);

       rr_node[inode].num_edges = 1;
       rr_node[inode].edges = (int *) my_chunk_malloc (sizeof(int), 
          &rr_mem_chunk_list_head, &chunk_bytes_avail, &chunk_next_avail_mem);

       rr_node[inode].switches = (short *) my_chunk_malloc (sizeof(short), 
          &rr_mem_chunk_list_head, &chunk_bytes_avail, &chunk_next_avail_mem);

       to_node = get_rr_node_index (i, j, SINK, iclass, nodes_per_chan,
                  rr_node_indices);
       rr_node[inode].edges[0] = to_node;
       rr_node[inode].switches[0] = delayless_switch;

#ifndef SPEC_CPU2000
       rr_node_cost_inf[inode].base_cost = 0.95;
#else
       rr_node_cost_inf[inode].base_cost = 1.;  /* Avoid roundoff for SPEC */
#endif

       rr_node[inode].type = IPIN;
    }

/* Things that are common to both OPINs and IPINs.  */

    rr_node_cost_inf[inode].capacity = 1;
    rr_node_cost_inf[inode].acc_cost = 0.;
    rr_node_cost_inf[inode].occ = 0;
 
    rr_node[inode].xlow = i;
    rr_node[inode].xhigh = i;
    rr_node[inode].ylow = j;
    rr_node[inode].yhigh = j;
    rr_node[inode].C = 0;
    rr_node[inode].R = 0;
 
    rr_node[inode].ptc_num = ipin;
 }
}
Beispiel #2
0
static void load_rr_indexed_data_T_values (int index_start, int
             num_indices_to_load, t_rr_type rr_type, int nodes_per_chan,
             int **rr_node_indices, t_segment_inf *segment_inf) {

/* Loads the average propagation times through segments of each index type  *
 * for either all CHANX segment types or all CHANY segment types.  It does  *
 * this by looking at all the segments in one channel in the middle of the  *
 * array and averaging the R and C values of all segments of the same type  *
 * and using them to compute average delay values for this type of segment. */

 int itrack, iseg, inode, cost_index, iswitch;
 float *C_total, *R_total;    /* [0..num_rr_indexed_data - 1] */
 int *num_nodes_of_index;     /* [0..num_rr_indexed_data - 1] */
 float Rnode, Cnode, Rsw, Tsw;

 num_nodes_of_index = (int *) my_calloc (num_rr_indexed_data, sizeof (int));
 C_total = (float *) my_calloc (num_rr_indexed_data, sizeof (float));
 R_total = (float *) my_calloc (num_rr_indexed_data, sizeof (float));

/* Get average C and R values for all the segments of this type in one      *
 * channel segment, near the middle of the array.                           */

 for (itrack=0;itrack<nodes_per_chan;itrack++) {
    inode = get_rr_node_index ((nx+1) / 2, (ny+1) / 2, rr_type, itrack,
                  nodes_per_chan, rr_node_indices);
    cost_index = rr_node[inode].cost_index;
    num_nodes_of_index[cost_index]++;
    C_total[cost_index] += rr_node[inode].C;
    R_total[cost_index] += rr_node[inode].R;
 }


 for (cost_index=index_start;cost_index<index_start + num_indices_to_load;
                                         cost_index++) {

    if (num_nodes_of_index[cost_index] == 0) {     /* Segments don't exist. */
       rr_indexed_data[cost_index].T_linear = OPEN;
       rr_indexed_data[cost_index].T_quadratic = OPEN;
       rr_indexed_data[cost_index].C_load = OPEN;
    }
    else {
       Rnode = R_total[cost_index] / num_nodes_of_index[cost_index];
       Cnode = C_total[cost_index] / num_nodes_of_index[cost_index];
       iseg = rr_indexed_data[cost_index].seg_index;
       iswitch = segment_inf[iseg].wire_switch;
       Rsw = switch_inf[iswitch].R;
       Tsw = switch_inf[iswitch].Tdel;

       if (switch_inf[iswitch].buffered) {
          rr_indexed_data[cost_index].T_linear = Tsw + Rsw * Cnode + 0.5 *
                                                 Rnode * Cnode;
          rr_indexed_data[cost_index].T_quadratic = 0.;
          rr_indexed_data[cost_index].C_load = 0.;
       }
       else {    /* Pass transistor */
          rr_indexed_data[cost_index].C_load = Cnode;

         /* See Dec. 23, 1997 notes for deriviation of formulae. */

          rr_indexed_data[cost_index].T_linear = Tsw + 0.5 * Rsw * Cnode;
          rr_indexed_data[cost_index].T_quadratic = (Rsw + Rnode) * 0.5 * Cnode;       }
    }
 }

 free (num_nodes_of_index);
 free (C_total);
 free (R_total);
}