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; } }
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); }