00001 #include <stdio.h>
00002 #include <math.h>
00003 #include <assert.h>
00004 #include <string.h>
00005 #include "util.h"
00006 #include "vpr_types.h"
00007 #include "globals.h"
00008 #include "rr_graph_util.h"
00009 #include "rr_graph.h"
00010 #include "rr_graph2.h"
00011 #include "rr_graph_sbox.h"
00012 #include "check_rr_graph.h"
00013 #include "rr_graph_timing_params.h"
00014 #include "rr_graph_indexed_data.h"
00015 #include "vpr_utils.h"
00016
00017
00018
00019
00020
00021
00022
00023 #define REVERSE_OPIN_ORDER
00024
00025
00026 #define MUX_SIZE_DIST_DISPLAY
00027
00028
00029
00030 typedef struct s_mux
00031 {
00032 int size;
00033 struct s_mux *next;
00034 }
00035 t_mux;
00036
00037 typedef struct s_mux_size_distribution
00038 {
00039 int mux_count;
00040 int max_index;
00041 int *distr;
00042 struct s_mux_size_distribution *next;
00043 }
00044 t_mux_size_distribution;
00045
00046
00047
00048
00049
00050
00051 static struct s_linked_vptr *rr_mem_chunk_list_head = NULL;
00052
00053
00054
00055 static int chunk_bytes_avail = 0;
00056 static char *chunk_next_avail_mem = NULL;
00057
00058
00059
00060
00061 static int ****alloc_and_load_pin_to_track_map(IN enum e_pin_type pin_type,
00062 IN int nodes_per_chan,
00063 IN int Fc,
00064 IN t_type_ptr Type,
00065 IN boolean
00066 perturb_switch_pattern,
00067 IN enum e_directionality
00068 directionality);
00069
00070 static struct s_ivec ***alloc_and_load_track_to_pin_lookup(IN int
00071 ****pin_to_track_map,
00072 IN int Fc,
00073 IN int height,
00074 IN int num_pins,
00075 IN int
00076 nodes_per_chan);
00077
00078 static void build_bidir_rr_opins(IN int i,
00079 IN int j,
00080 INOUT t_rr_node * rr_node,
00081 IN t_ivec *** rr_node_indices,
00082 IN int *****opin_to_track_map,
00083 IN int *Fc_out,
00084 IN boolean * rr_edge_done,
00085 IN t_seg_details * seg_details,
00086 IN struct s_grid_tile **grid);
00087
00088 static void build_unidir_rr_opins(IN int i,
00089 IN int j,
00090 IN struct s_grid_tile **grid,
00091 IN int *Fc_out,
00092 IN int nodes_per_chan,
00093 IN t_seg_details * seg_details,
00094 INOUT int **Fc_xofs,
00095 INOUT int **Fc_yofs,
00096 INOUT t_rr_node * rr_node,
00097 INOUT boolean * rr_edge_done,
00098 OUT boolean * Fc_clipped,
00099 IN t_ivec *** rr_node_indices);
00100
00101 static void alloc_and_load_rr_graph(IN int num_nodes,
00102 IN t_rr_node * rr_node,
00103 IN int num_seg_types,
00104 IN t_seg_details * seg_details,
00105 IN boolean * rr_edge_done,
00106 IN struct s_ivec ****track_to_ipin_lookup,
00107 IN int *****opin_to_track_map,
00108 IN struct s_ivec ***switch_block_conn,
00109 IN struct s_grid_tile **grid,
00110 IN int nx,
00111 IN int ny,
00112 IN int Fs,
00113 IN short *****sblock_pattern,
00114 IN int *Fc_out,
00115 IN int **Fc_xofs,
00116 IN int **Fc_yofs,
00117 IN t_ivec *** rr_node_indices,
00118 IN int nodes_per_chan,
00119 IN enum e_switch_block_type sb_type,
00120 IN int delayless_switch,
00121 IN enum e_directionality directionality,
00122 IN int wire_to_ipin_switch,
00123 OUT boolean * Fc_clipped);
00124
00125 static void load_uniform_switch_pattern(IN t_type_ptr type,
00126 INOUT int ****tracks_connected_to_pin,
00127 IN int num_phys_pins,
00128 IN int *pin_num_ordering,
00129 IN int *side_ordering,
00130 IN int *offset_ordering,
00131 IN int nodes_per_chan,
00132 IN int Fc,
00133 IN enum e_directionality
00134 directionality);
00135
00136 static void load_perturbed_switch_pattern(IN t_type_ptr type,
00137 INOUT int
00138 ****tracks_connected_to_pin,
00139 IN int num_phys_pins,
00140 IN int *pin_num_ordering,
00141 IN int *side_ordering,
00142 IN int *offset_ordering,
00143 IN int nodes_per_chan,
00144 IN int Fc,
00145 IN enum e_directionality
00146 directionality);
00147
00148 static void check_all_tracks_reach_pins(t_type_ptr type,
00149 int ****tracks_connected_to_pin,
00150 int nodes_per_chan,
00151 int Fc,
00152 enum e_pin_type ipin_or_opin);
00153
00154 static int track_side(int clb_side);
00155
00156 static boolean *alloc_and_load_perturb_ipins(IN int nodes_per_chan,
00157 IN int num_types,
00158 IN int *Fc_in,
00159 IN int *Fc_out,
00160 IN enum e_directionality
00161 directionality);
00162
00163
00164 static void print_rr_node(FILE * fp,
00165 t_rr_node * rr_node,
00166 int inode);
00167
00168 static void build_rr_sinks_sources(IN int i,
00169 IN int j,
00170 IN t_rr_node * rr_node,
00171 IN t_ivec *** rr_node_indices,
00172 IN int delayless_switch,
00173 IN struct s_grid_tile **grid);
00174
00175 static void build_rr_xchan(IN int i,
00176 IN int j,
00177 IN struct s_ivec ****track_to_ipin_lookup,
00178 IN struct s_ivec ***switch_block_conn,
00179 IN int cost_index_offset,
00180 IN int nodes_per_chan,
00181 IN int *opin_mux_size,
00182 IN short *****sblock_pattern,
00183 IN int Fs_per_side,
00184 IN t_seg_details * seg_details,
00185 IN t_ivec *** rr_node_indices,
00186 IN boolean * rr_edge_done,
00187 INOUT t_rr_node * rr_node,
00188 IN int wire_to_ipin_switch,
00189 IN enum e_directionality directionality);
00190
00191 static void build_rr_ychan(IN int i,
00192 IN int j,
00193 IN struct s_ivec ****track_to_ipin_lookup,
00194 IN struct s_ivec ***switch_block_conn,
00195 IN int cost_index_offset,
00196 IN int nodes_per_chan,
00197 IN int *opin_mux_size,
00198 IN short *****sblock_pattern,
00199 IN int Fs_per_side,
00200 IN t_seg_details * seg_details,
00201 IN t_ivec *** rr_node_indices,
00202 IN boolean * rr_edge_done,
00203 INOUT t_rr_node * rr_node,
00204 IN int wire_to_ipin_switch,
00205 IN enum e_directionality directionality);
00206
00207
00208 static void rr_graph_externals(
00209 t_timing_inf timing_inf,
00210 t_segment_inf * segment_inf,
00211 int num_seg_types,
00212 int nodes_per_chan,
00213 int wire_to_ipin_switch,
00214 enum e_base_cost_type base_cost_type);
00215
00216 void alloc_and_load_edges_and_switches(IN t_rr_node * rr_node,
00217 IN int inode,
00218 IN int num_edges,
00219 IN boolean * rr_edge_done,
00220 IN t_linked_edge * edge_list_head);
00221
00222 static void alloc_net_rr_terminals(void);
00223
00224 static void alloc_and_load_rr_clb_source(t_ivec *** rr_node_indices);
00225
00226
00227 static void load_uniform_opin_switch_pattern_paired(IN int *Fc_out,
00228 IN int num_pins,
00229 IN int *pins_in_chan_seg,
00230 IN int num_wire_inc_muxes,
00231 IN int num_wire_dec_muxes,
00232 IN int *wire_inc_muxes,
00233 IN int *wire_dec_muxes,
00234 INOUT t_rr_node * rr_node,
00235 INOUT boolean *
00236 rr_edge_done,
00237 IN t_seg_details *
00238 seg_details,
00239 OUT boolean * Fc_clipped);
00240
00241 static int *get_adj_opins(IN int i,
00242 IN int j,
00243 OUT int *num_pins,
00244 IN t_ivec *** rr_node_indices,
00245 IN enum e_rr_type chan_type);
00246
00247 void watch_edges(int inode,
00248 t_linked_edge * edge_list_head);
00249
00250 static void view_mux_size_distribution(t_ivec *** rr_node_indices,
00251 int nodes_per_chan,
00252 t_seg_details * seg_details_x,
00253 t_seg_details * seg_details_y);
00254
00255 static void print_distribution(FILE * fptr,
00256 t_mux_size_distribution * distr_struct);
00257
00258 static void free_type_pin_to_track_map(int***** ipin_to_track_map, t_type_ptr types, int* fc_in);
00259
00260 static void free_type_track_to_ipin_map(struct s_ivec**** track_to_pin_map, t_type_ptr types, int nodes_per_chan);
00261
00262 static t_seg_details *alloc_and_load_global_route_seg_details(IN int
00263 nodes_per_chan,
00264 IN int
00265 global_route_switch);
00266
00267
00268
00269 static int *alloc_and_load_actual_fc(IN int num_types,
00270 IN t_type_ptr types,
00271 IN int nodes_per_chan,
00272 IN boolean is_Fc_out,
00273 IN enum e_directionality directionality,
00274 OUT boolean * Fc_clipped);
00275
00276
00277
00278
00279 void
00280 build_rr_graph(IN t_graph_type graph_type,
00281 IN int num_types,
00282 IN t_type_ptr types,
00283 IN int nx,
00284 IN int ny,
00285 IN struct s_grid_tile **grid,
00286 IN int chan_width,
00287 IN struct s_chan_width_dist *chan_capacity_inf,
00288 IN enum e_switch_block_type sb_type,
00289 IN int Fs,
00290 IN int num_seg_types,
00291 IN int num_switches,
00292 IN t_segment_inf * segment_inf,
00293 IN int global_route_switch,
00294 IN int delayless_switch,
00295 IN t_timing_inf timing_inf,
00296 IN int wire_to_ipin_switch,
00297 IN enum e_base_cost_type base_cost_type,
00298 OUT int *Warnings)
00299 {
00300
00301 int nodes_per_chan, i, j;
00302 t_seg_details *seg_details = NULL;
00303 int *Fc_in = NULL;
00304 int *Fc_out = NULL;
00305
00306 int *****opin_to_track_map = NULL;
00307 int *****ipin_to_track_map = NULL;
00308 t_ivec ****track_to_ipin_lookup = NULL;
00309 t_ivec ***switch_block_conn = NULL;
00310 short *****unidir_sb_pattern = NULL;
00311 boolean *rr_edge_done = NULL;
00312 boolean is_global_graph;
00313 boolean Fc_clipped;
00314 boolean use_full_seg_groups;
00315 boolean *perturb_ipins = NULL;
00316 enum e_directionality directionality;
00317 int **Fc_xofs = NULL;
00318 int **Fc_yofs = NULL;
00319
00320 rr_node_indices = NULL;
00321 rr_node = NULL;
00322 num_rr_nodes = 0;
00323
00324
00325 *Warnings = RR_GRAPH_NO_WARN;
00326
00327
00328 is_global_graph = FALSE;
00329 if(GRAPH_GLOBAL == graph_type)
00330 {
00331 is_global_graph = TRUE;
00332 }
00333 use_full_seg_groups = FALSE;
00334 if(GRAPH_UNIDIR_TILEABLE == graph_type)
00335 {
00336 use_full_seg_groups = TRUE;
00337 }
00338 directionality = UNI_DIRECTIONAL;
00339 if(GRAPH_BIDIR == graph_type)
00340 {
00341 directionality = BI_DIRECTIONAL;
00342 }
00343 if(is_global_graph)
00344 {
00345 directionality = BI_DIRECTIONAL;
00346 }
00347
00348
00349
00350 nodes_per_chan = (is_global_graph ? 1 : chan_width);
00351 assert(nodes_per_chan > 0);
00352
00353
00354
00355
00356 if(is_global_graph)
00357 {
00358
00359 seg_details =
00360 alloc_and_load_global_route_seg_details(nodes_per_chan,
00361 global_route_switch);
00362 }
00363 else
00364 {
00365
00366
00367
00368 seg_details = alloc_and_load_seg_details(&nodes_per_chan,
00369 max(nx, ny),
00370 num_seg_types,
00371 segment_inf,
00372 use_full_seg_groups,
00373 is_global_graph,
00374 directionality);
00375 if((is_global_graph ? 1 : chan_width) != nodes_per_chan)
00376 {
00377 *Warnings |= RR_GRAPH_WARN_CHAN_WIDTH_CHANGED;
00378 }
00379 #ifdef CREATE_ECHO_FILES
00380 dump_seg_details(seg_details, nodes_per_chan, "seg_details.txt");
00381 #endif
00382 }
00383
00384
00385
00386
00387
00388
00389 if(is_global_graph)
00390 {
00391 Fc_in = (int *)my_malloc(sizeof(int) * num_types);
00392 Fc_out = (int *)my_malloc(sizeof(int) * num_types);
00393 for(i = 0; i < num_types; ++i)
00394 {
00395 Fc_in[i] = 1;
00396 Fc_out[i] = 1;
00397 }
00398 }
00399 else
00400 {
00401 Fc_clipped = FALSE;
00402 Fc_in =
00403 alloc_and_load_actual_fc(num_types, types, nodes_per_chan,
00404 FALSE, directionality, &Fc_clipped);
00405 if(Fc_clipped)
00406 {
00407 *Warnings |= RR_GRAPH_WARN_FC_CLIPPED;
00408 }
00409 Fc_clipped = FALSE;
00410 Fc_out =
00411 alloc_and_load_actual_fc(num_types, types, nodes_per_chan,
00412 TRUE, directionality, &Fc_clipped);
00413 if(Fc_clipped)
00414 {
00415 *Warnings |= RR_GRAPH_WARN_FC_CLIPPED;
00416 }
00417
00418
00419 #ifdef VERBOSE
00420 for(i = 1; i < num_types; ++i)
00421 {
00422 if(type_descriptors[i].is_Fc_out_full_flex)
00423 {
00424 printf
00425 ("Fc Actual Values: Type = %s, Fc_out = full, Fc_in = %d.\n",
00426 type_descriptors[i].name, Fc_input[i]);
00427 }
00428 else
00429 {
00430 printf
00431 ("Fc Actual Values: Type = %s, Fc_out = %d, Fc_in = %d.\n",
00432 type_descriptors[i].name, Fc_output[i],
00433 Fc_input[i]);
00434 }
00435 }
00436 #endif
00437 }
00438
00439 perturb_ipins =
00440 alloc_and_load_perturb_ipins(nodes_per_chan, num_types, Fc_in,
00441 Fc_out, directionality);
00442
00443
00444
00445
00446 num_rr_nodes = 0;
00447 rr_node_indices =
00448 alloc_and_load_rr_node_indices(nodes_per_chan, nx, ny, &num_rr_nodes,
00449 seg_details);
00450 rr_node = (t_rr_node *) my_malloc(sizeof(t_rr_node) * num_rr_nodes);
00451 memset(rr_node, 0, sizeof(t_rr_node) * num_rr_nodes);
00452 rr_edge_done = (boolean *) my_malloc(sizeof(boolean) * num_rr_nodes);
00453 memset(rr_edge_done, 0, sizeof(boolean) * num_rr_nodes);
00454
00455
00456 if(UNI_DIRECTIONAL == directionality)
00457 {
00458 Fc_xofs = (int **)alloc_matrix(0, ny, 0, nx, sizeof(int));
00459 Fc_yofs = (int **)alloc_matrix(0, nx, 0, ny, sizeof(int));
00460 for(i = 0; i <= nx; ++i)
00461 {
00462 for(j = 0; j <= ny; ++j)
00463 {
00464 Fc_xofs[j][i] = 0;
00465 Fc_yofs[i][j] = 0;
00466 }
00467 }
00468 }
00469
00470
00471
00472
00473
00474 if(is_global_graph)
00475 {
00476 assert(nodes_per_chan == 1);
00477 switch_block_conn =
00478 alloc_and_load_switch_block_conn(1, SUBSET, 3);
00479 }
00480 else if(BI_DIRECTIONAL == directionality)
00481 {
00482 switch_block_conn =
00483 alloc_and_load_switch_block_conn(nodes_per_chan, sb_type, Fs);
00484 }
00485 else
00486 {
00487 assert(UNI_DIRECTIONAL == directionality);
00488
00489 unidir_sb_pattern =
00490 alloc_sblock_pattern_lookup(nx, ny, nodes_per_chan);
00491 for(i = 0; i <= nx; i++)
00492 {
00493 for(j = 0; j <= ny; j++)
00494 {
00495 load_sblock_pattern_lookup(i, j, nodes_per_chan,
00496 seg_details, Fs,
00497 sb_type,
00498 unidir_sb_pattern);
00499 }
00500 }
00501 }
00502
00503
00504
00505
00506
00507
00508 ipin_to_track_map = (int *****)my_malloc(sizeof(int ****) * num_types);
00509 track_to_ipin_lookup =
00510 (struct s_ivec ****)my_malloc(sizeof(struct s_ivec ***) * num_types);
00511 for(i = 0; i < num_types; ++i)
00512 {
00513 ipin_to_track_map[i] = alloc_and_load_pin_to_track_map(RECEIVER,
00514 nodes_per_chan,
00515 Fc_in[i],
00516 &types[i],
00517 perturb_ipins
00518 [i],
00519 directionality);
00520 track_to_ipin_lookup[i] =
00521 alloc_and_load_track_to_pin_lookup(ipin_to_track_map[i],
00522 Fc_in[i], types[i].height,
00523 types[i].num_pins,
00524 nodes_per_chan);
00525 }
00526
00527
00528
00529
00530
00531
00532 if(BI_DIRECTIONAL == directionality)
00533 {
00534 opin_to_track_map =
00535 (int *****)my_malloc(sizeof(int ****) * num_types);
00536 for(i = 0; i < num_types; ++i)
00537 {
00538 opin_to_track_map[i] =
00539 alloc_and_load_pin_to_track_map(DRIVER,
00540 nodes_per_chan,
00541 Fc_out[i], &types[i],
00542 FALSE,
00543 directionality);
00544 }
00545 }
00546
00547
00548
00549
00550 for(i = 0; i < num_rr_nodes; i++)
00551 {
00552 rr_node[i].num_wire_drivers = 0;
00553 rr_node[i].num_opin_drivers = 0;
00554 }
00555
00556
00557 alloc_and_load_rr_graph(num_rr_nodes, rr_node, num_seg_types,
00558 seg_details, rr_edge_done,
00559 track_to_ipin_lookup, opin_to_track_map,
00560 switch_block_conn, grid, nx,
00561 ny, Fs, unidir_sb_pattern, Fc_out, Fc_xofs,
00562 Fc_yofs, rr_node_indices, nodes_per_chan,
00563 sb_type, delayless_switch, directionality,
00564 wire_to_ipin_switch, &Fc_clipped);
00565
00566
00567 #if 0
00568 #ifdef MUX_SIZE_DIST_DISPLAY
00569 if(UNI_DIRECTIONAL == directionality)
00570 {
00571 view_mux_size_distribution(rr_node_indices, nodes_per_chan,
00572 seg_details, seg_details);
00573 }
00574 #endif
00575 #endif
00576
00577
00578 if(graph_type == GLOBAL) {
00579 for(i = 0; i < num_rr_nodes; i++) {
00580 if(rr_node[i].type == CHANX || rr_node[i].type == CHANY) {
00581 rr_node[i].capacity = chan_width;
00582 }
00583 }
00584 }
00585
00586 rr_graph_externals(timing_inf, segment_inf, num_seg_types,
00587 nodes_per_chan, wire_to_ipin_switch, base_cost_type);
00588
00589 #ifdef CREATE_ECHO_FILES
00590 dump_rr_graph("rr_graph.echo");
00591 #endif
00592
00593 check_rr_graph(graph_type, num_types, types, nx, ny,
00594 grid, nodes_per_chan, Fs, num_seg_types, num_switches, segment_inf,
00595 global_route_switch, delayless_switch,
00596 wire_to_ipin_switch, seg_details, Fc_in, Fc_out,
00597 rr_node_indices, opin_to_track_map, ipin_to_track_map,
00598 track_to_ipin_lookup, switch_block_conn, perturb_ipins);
00599
00600
00601 if(seg_details)
00602 {
00603 free_seg_details(seg_details, nodes_per_chan);
00604 seg_details = NULL;
00605 }
00606 if(Fc_in)
00607 {
00608 free(Fc_in);
00609 Fc_in = NULL;
00610 }
00611 if(Fc_out)
00612 {
00613 free(Fc_out);
00614 Fc_out = NULL;
00615 }
00616 if(perturb_ipins)
00617 {
00618 free(perturb_ipins);
00619 perturb_ipins = NULL;
00620 }
00621 if(switch_block_conn)
00622 {
00623 free_switch_block_conn(switch_block_conn, nodes_per_chan);
00624 switch_block_conn = NULL;
00625 }
00626 if(rr_edge_done)
00627 {
00628 free(rr_edge_done);
00629 rr_edge_done = NULL;
00630 }
00631 if(Fc_xofs)
00632 {
00633 free_matrix(Fc_xofs, 0, ny, 0, sizeof(int));
00634 Fc_xofs = NULL;
00635 }
00636 if(Fc_yofs)
00637 {
00638 free_matrix(Fc_yofs, 0, nx, 0, sizeof(int));
00639 Fc_yofs = NULL;
00640 }
00641 if(unidir_sb_pattern)
00642 {
00643 free_sblock_pattern_lookup(unidir_sb_pattern);
00644 unidir_sb_pattern = NULL;
00645 }
00646 if(opin_to_track_map) {
00647 for(i = 0; i < num_types; ++i)
00648 {
00649 free_matrix4(opin_to_track_map[i], 0, types[i].num_pins - 1,
00650 0, types[i].height - 1, 0, 3, 0, sizeof(int));
00651 }
00652 free(opin_to_track_map);
00653 }
00654
00655 free_type_pin_to_track_map(ipin_to_track_map, types, Fc_in);
00656 free_type_track_to_ipin_map(track_to_ipin_lookup, types, nodes_per_chan);
00657 }
00658
00659
00660 static void
00661 rr_graph_externals( t_timing_inf timing_inf,
00662 t_segment_inf * segment_inf,
00663 int num_seg_types,
00664 int nodes_per_chan,
00665 int wire_to_ipin_switch,
00666 enum e_base_cost_type base_cost_type)
00667 {
00668 add_rr_graph_C_from_switches(timing_inf.C_ipin_cblock);
00669 alloc_and_load_rr_indexed_data(segment_inf, num_seg_types,
00670 rr_node_indices, nodes_per_chan,
00671 wire_to_ipin_switch, base_cost_type);
00672
00673 alloc_net_rr_terminals();
00674 load_net_rr_terminals(rr_node_indices);
00675 alloc_and_load_rr_clb_source(rr_node_indices);
00676 }
00677
00678
00679 static boolean *
00680 alloc_and_load_perturb_ipins(IN int nodes_per_chan,
00681 IN int num_types,
00682 IN int *Fc_in,
00683 IN int *Fc_out,
00684 IN enum e_directionality directionality)
00685 {
00686 int i;
00687 float Fc_ratio;
00688 boolean *result = NULL;
00689
00690 result = (boolean *) my_malloc(num_types * sizeof(boolean));
00691
00692 if(BI_DIRECTIONAL == directionality)
00693 {
00694 for(i = 0; i < num_types; ++i)
00695 {
00696 result[i] = FALSE;
00697
00698 if(Fc_in[i] > Fc_out[i])
00699 {
00700 Fc_ratio = (float)Fc_in[i] / (float)Fc_out[i];
00701 }
00702 else
00703 {
00704 Fc_ratio = (float)Fc_out[i] / (float)Fc_in[i];
00705 }
00706
00707 if((Fc_in[i] <= nodes_per_chan - 2) &&
00708 (fabs(Fc_ratio - nint(Fc_ratio)) <
00709 (0.5 / (float)nodes_per_chan)))
00710 {
00711 result[i] = TRUE;
00712 }
00713 }
00714 }
00715 else
00716 {
00717
00718
00719 assert(UNI_DIRECTIONAL == directionality);
00720 for(i = 0; i < num_types; ++i)
00721 {
00722 result[i] = FALSE;
00723 }
00724 }
00725
00726 return result;
00727 }
00728
00729
00730 static t_seg_details *
00731 alloc_and_load_global_route_seg_details(IN int nodes_per_chan,
00732 IN int global_route_switch)
00733 {
00734 t_seg_details *result = NULL;
00735
00736 assert(nodes_per_chan == 1);
00737 result = (t_seg_details *) my_malloc(sizeof(t_seg_details));
00738
00739 result->index = 0;
00740 result->length = 1;
00741 result->wire_switch = global_route_switch;
00742 result->opin_switch = global_route_switch;
00743 result->longline = FALSE;
00744 result->direction = BI_DIRECTION;
00745 result->Cmetal = 0.0;
00746 result->Rmetal = 0.0;
00747 result->start = 1;
00748 result->drivers = MULTI_BUFFERED;
00749 result->cb = (boolean *) my_malloc(sizeof(boolean) * 1);
00750 result->cb[0] = TRUE;
00751 result->sb = (boolean *) my_malloc(sizeof(boolean) * 2);
00752 result->sb[0] = TRUE;
00753 result->sb[1] = TRUE;
00754 result->group_size = 1;
00755 result->group_start = 0;
00756
00757 return result;
00758 }
00759
00760
00761
00762
00763
00764 static int *
00765 alloc_and_load_actual_fc(IN int num_types,
00766 IN t_type_ptr types,
00767 IN int nodes_per_chan,
00768 IN boolean is_Fc_out,
00769 IN enum e_directionality directionality,
00770 OUT boolean * Fc_clipped)
00771 {
00772
00773 int i;
00774 int *Result = NULL;
00775 int fac, num_sets;
00776 float Fc;
00777
00778 *Fc_clipped = FALSE;
00779
00780
00781 fac = 1;
00782 if(UNI_DIRECTIONAL == directionality)
00783 {
00784 fac = 2;
00785 }
00786
00787 assert((nodes_per_chan % fac) == 0);
00788 num_sets = nodes_per_chan / fac;
00789
00790 Result = (int *)my_malloc(sizeof(int) * num_types);
00791
00792 for(i = 0; i < num_types; ++i)
00793 {
00794 Fc = (is_Fc_out ? type_descriptors[i].
00795 Fc_out : type_descriptors[i].Fc_in);
00796
00797 if(type_descriptors[i].is_Fc_frac)
00798 {
00799 Result[i] = fac * nint(num_sets * Fc);
00800 }
00801 else
00802 {
00803 Result[i] = Fc;
00804 }
00805
00806 if(is_Fc_out && type_descriptors[i].is_Fc_out_full_flex)
00807 {
00808 Result[i] = nodes_per_chan;
00809 }
00810
00811 Result[i] = max(Result[i], fac);
00812 if(Result[i] > nodes_per_chan)
00813 {
00814 *Fc_clipped = TRUE;
00815 Result[i] = nodes_per_chan;
00816 }
00817
00818 assert(Result[i] % fac == 0);
00819 }
00820
00821 return Result;
00822 }
00823
00824
00825 static void
00826 free_type_track_to_ipin_map(struct s_ivec**** track_to_pin_map, t_type_ptr types, int nodes_per_chan)
00827 {
00828 int i, itrack, ioff, iside;
00829 for(i = 0; i < num_types; i++) {
00830 if(track_to_pin_map[i] != NULL) {
00831 for(itrack = 0; itrack < nodes_per_chan; itrack++)
00832 {
00833 for(ioff = 0; ioff < types[i].height; ioff++)
00834 {
00835 for(iside = 0; iside < 4; iside++)
00836 {
00837 if(track_to_pin_map[i][itrack][ioff][iside].list != NULL) {
00838 free(track_to_pin_map[i][itrack][ioff][iside].list);
00839 }
00840 }
00841 }
00842 }
00843 free_matrix3(track_to_pin_map[i], 0, nodes_per_chan - 1, 0,
00844 types[i].height - 1, 0,
00845 sizeof(struct s_ivec));
00846 }
00847 }
00848 free(track_to_pin_map);
00849 }
00850
00851
00852 static void
00853 free_type_pin_to_track_map(int***** ipin_to_track_map, t_type_ptr types, int* fc_in)
00854 {
00855 int i;
00856 for(i = 0; i < num_types; i++) {
00857 free_matrix4(ipin_to_track_map[i], 0, types[i].num_pins - 1,
00858 0, types[i].height - 1, 0, 3, 0, sizeof(int));
00859 }
00860 free(ipin_to_track_map);
00861 }
00862
00863
00864
00865 static void
00866 alloc_and_load_rr_graph(IN int num_nodes,
00867 IN t_rr_node * rr_node,
00868 IN int num_seg_types,
00869 IN t_seg_details * seg_details,
00870 IN boolean * rr_edge_done,
00871 IN struct s_ivec ****track_to_ipin_lookup,
00872 IN int *****opin_to_track_map,
00873 IN struct s_ivec ***switch_block_conn,
00874 IN struct s_grid_tile **grid,
00875 IN int nx,
00876 IN int ny,
00877 IN int Fs,
00878 IN short *****sblock_pattern,
00879 IN int *Fc_out,
00880 IN int **Fc_xofs,
00881 IN int **Fc_yofs,
00882 IN t_ivec *** rr_node_indices,
00883 IN int nodes_per_chan,
00884 IN enum e_switch_block_type sb_type,
00885 IN int delayless_switch,
00886 IN enum e_directionality directionality,
00887 IN int wire_to_ipin_switch,
00888 OUT boolean * Fc_clipped)
00889 {
00890
00891 int i, j;
00892 boolean clipped;
00893 int *opin_mux_size = NULL;
00894
00895
00896
00897 *Fc_clipped = FALSE;
00898
00899
00900 for(i = 0; i <= (nx + 1); i++)
00901 {
00902 for(j = 0; j <= (ny + 1); j++)
00903 {
00904 build_rr_sinks_sources(i, j, rr_node, rr_node_indices,
00905 delayless_switch, grid);
00906 }
00907 }
00908
00909
00910 for(i = 0; i <= (nx + 1); ++i)
00911 {
00912 for(j = 0; j <= (ny + 1); ++j)
00913 {
00914 if(BI_DIRECTIONAL == directionality)
00915 {
00916 build_bidir_rr_opins(i, j, rr_node,
00917 rr_node_indices,
00918 opin_to_track_map, Fc_out,
00919 rr_edge_done, seg_details,
00920 grid);
00921 }
00922 else
00923 {
00924 assert(UNI_DIRECTIONAL == directionality);
00925 build_unidir_rr_opins(i, j, grid, Fc_out,
00926 nodes_per_chan, seg_details,
00927 Fc_xofs, Fc_yofs, rr_node,
00928 rr_edge_done, &clipped,
00929 rr_node_indices);
00930 if(clipped)
00931 {
00932 *Fc_clipped = TRUE;
00933 }
00934 }
00935 }
00936 }
00937
00938
00939
00940 opin_mux_size = (int *)my_malloc(sizeof(int) * num_nodes);
00941 for(i = 0; i < num_nodes; ++i)
00942 {
00943 opin_mux_size[i] = rr_node[i].fan_in;
00944 }
00945
00946
00947 assert(Fs % 3 == 0);
00948 for(i = 0; i <= nx; i++)
00949 {
00950 for(j = 0; j <= ny; j++)
00951 {
00952 if(i > 0)
00953 {
00954 build_rr_xchan(i, j, track_to_ipin_lookup,
00955 switch_block_conn,
00956 CHANX_COST_INDEX_START,
00957 nodes_per_chan, opin_mux_size,
00958 sblock_pattern, Fs / 3,
00959 seg_details, rr_node_indices,
00960 rr_edge_done, rr_node,
00961 wire_to_ipin_switch,
00962 directionality);
00963 }
00964 if(j > 0)
00965 {
00966 build_rr_ychan(i, j, track_to_ipin_lookup,
00967 switch_block_conn,
00968 CHANX_COST_INDEX_START +
00969 num_seg_types, nodes_per_chan,
00970 opin_mux_size, sblock_pattern,
00971 Fs / 3, seg_details,
00972 rr_node_indices, rr_edge_done,
00973 rr_node, wire_to_ipin_switch,
00974 directionality);
00975 }
00976 }
00977 }
00978 free(opin_mux_size);
00979 }
00980
00981
00982
00983 static void
00984 build_bidir_rr_opins(IN int i,
00985 IN int j,
00986 INOUT t_rr_node * rr_node,
00987 IN t_ivec *** rr_node_indices,
00988 IN int *****opin_to_track_map,
00989 IN int *Fc_out,
00990 IN boolean * rr_edge_done,
00991 IN t_seg_details * seg_details,
00992 IN struct s_grid_tile **grid)
00993 {
00994
00995 int ipin, inode, num_edges, Fc, ofs;
00996 t_type_ptr type;
00997 struct s_linked_edge *edge_list, *next;
00998
00999
01000
01001 if(grid[i][j].offset > 0)
01002 {
01003 return;
01004 }
01005
01006 type = grid[i][j].type;
01007 Fc = Fc_out[type->index];
01008
01009 for(ipin = 0; ipin < type->num_pins; ++ipin)
01010 {
01011
01012 if(type->class_inf[type->pin_class[ipin]].type != DRIVER)
01013 {
01014 continue;
01015 }
01016
01017 num_edges = 0;
01018 edge_list = NULL;
01019
01020 for(ofs = 0; ofs < type->height; ++ofs)
01021 {
01022 num_edges +=
01023 get_bidir_opin_connections(i, j + ofs, ipin,
01024 &edge_list,
01025 opin_to_track_map, Fc,
01026 rr_edge_done,
01027 rr_node_indices,
01028 seg_details);
01029 }
01030
01031 inode = get_rr_node_index(i, j, OPIN, ipin, rr_node_indices);
01032 alloc_and_load_edges_and_switches(rr_node, inode, num_edges,
01033 rr_edge_done, edge_list);
01034 while(edge_list != NULL) {
01035 next = edge_list->next;
01036 free(edge_list);
01037 edge_list = next;
01038 }
01039 }
01040 }
01041
01042
01043
01044 void
01045 free_rr_graph(void)
01046 {
01047 int i;
01048
01049
01050
01051
01052
01053
01054
01055 if(rr_mem_chunk_list_head == NULL)
01056 return;
01057
01058 free_chunk_memory(rr_mem_chunk_list_head);
01059 rr_mem_chunk_list_head = NULL;
01060 chunk_bytes_avail = 0;
01061 chunk_next_avail_mem = NULL;
01062
01063
01064
01065
01066 free(net_rr_terminals);
01067
01068 for(i = 0; i < num_rr_nodes; i++) {
01069 if(rr_node[i].edges != NULL) {
01070 free(rr_node[i].edges);
01071 }
01072 if(rr_node[i].switches != NULL) {
01073 free(rr_node[i].switches);
01074 }
01075 }
01076
01077 assert(rr_node_indices);
01078 free_rr_node_indices(rr_node_indices);
01079 free(rr_node);
01080 free(rr_indexed_data);
01081 for(i = 0; i < num_blocks; i++)
01082 {
01083 free(rr_blk_source[i]);
01084 }
01085 free(rr_blk_source);
01086 rr_blk_source = NULL;
01087 net_rr_terminals = NULL;
01088 rr_node = NULL;
01089 rr_node_indices = NULL;
01090 rr_indexed_data = NULL;
01091 }
01092
01093
01094 static void
01095 alloc_net_rr_terminals(void)
01096 {
01097 int inet;
01098
01099 net_rr_terminals = (int **)my_malloc(num_nets * sizeof(int *));
01100
01101 for(inet = 0; inet < num_nets; inet++)
01102 {
01103 net_rr_terminals[inet] =
01104 (int *)my_chunk_malloc((net[inet].num_sinks + 1) *
01105 sizeof(int), &rr_mem_chunk_list_head,
01106 &chunk_bytes_avail,
01107 &chunk_next_avail_mem);
01108 }
01109 }
01110
01111
01112 void
01113 load_net_rr_terminals(t_ivec *** rr_node_indices)
01114 {
01115
01116
01117
01118
01119
01120
01121 int inet, ipin, inode, iblk, i, j, k, node_block_pin, iclass;
01122 t_type_ptr type;
01123
01124 for(inet = 0; inet < num_nets; inet++)
01125 {
01126 for(ipin = 0; ipin <= net[inet].num_sinks; ipin++)
01127 {
01128 iblk = net[inet].node_block[ipin];
01129 i = block[iblk].x;
01130 j = block[iblk].y;
01131 k = block[iblk].z;
01132 type = block[iblk].type;
01133
01134
01135
01136
01137 node_block_pin = net[inet].node_block_pin[ipin];
01138
01139 iclass = type->pin_class[node_block_pin];
01140
01141 inode = get_rr_node_index(i, j, (ipin == 0 ? SOURCE : SINK),
01142 iclass, rr_node_indices);
01143 net_rr_terminals[inet][ipin] = inode;
01144 }
01145 }
01146 }
01147
01148 static void
01149 alloc_and_load_rr_clb_source(t_ivec *** rr_node_indices)
01150 {
01151
01152
01153
01154
01155
01156
01157
01158 int iblk, i, j, iclass, inode;
01159 int class_low, class_high;
01160 t_rr_type rr_type;
01161 t_type_ptr type;
01162
01163 rr_blk_source = (int **)my_malloc(num_blocks * sizeof(int *));
01164
01165 for(iblk = 0; iblk < num_blocks; iblk++)
01166 {
01167 type = block[iblk].type;
01168 get_class_range_for_block(iblk, &class_low, &class_high);
01169 rr_blk_source[iblk] =
01170 (int *)my_malloc(type->num_class * sizeof(int));
01171 for(iclass = 0; iclass < type->num_class; iclass++)
01172 {
01173 if(iclass >= class_low && iclass <= class_high)
01174 {
01175 i = block[iblk].x;
01176 j = block[iblk].y;
01177
01178 if(type->class_inf[iclass].type == DRIVER)
01179 rr_type = SOURCE;
01180 else
01181 rr_type = SINK;
01182
01183 inode =
01184 get_rr_node_index(i, j, rr_type, iclass,
01185 rr_node_indices);
01186 rr_blk_source[iblk][iclass] = inode;
01187 }
01188 else
01189 {
01190 rr_blk_source[iblk][iclass] = OPEN;
01191 }
01192 }
01193 }
01194 }
01195
01196 static void
01197 build_rr_sinks_sources(IN int i,
01198 IN int j,
01199 IN t_rr_node * rr_node,
01200 IN t_ivec *** rr_node_indices,
01201 IN int delayless_switch,
01202 IN struct s_grid_tile **grid)
01203 {
01204
01205
01206
01207
01208 int ipin, iclass, inode, pin_num, to_node, num_edges;
01209 int num_class, num_pins;
01210 t_type_ptr type;
01211 struct s_class *class_inf;
01212 int *pin_class;
01213
01214
01215
01216 if(grid[i][j].offset > 0)
01217 return;
01218
01219 type = grid[i][j].type;
01220 num_class = type->num_class;
01221 class_inf = type->class_inf;
01222 num_pins = type->num_pins;
01223 pin_class = type->pin_class;
01224
01225
01226 for(iclass = 0; iclass < num_class; iclass++)
01227 {
01228 if(class_inf[iclass].type == DRIVER)
01229 {
01230 inode =
01231 get_rr_node_index(i, j, SOURCE, iclass,
01232 rr_node_indices);
01233
01234 num_edges = class_inf[iclass].num_pins;
01235 rr_node[inode].num_edges = num_edges;
01236 rr_node[inode].edges =
01237 (int *)my_malloc(num_edges * sizeof(int));
01238 rr_node[inode].switches =
01239 (short *)my_malloc(num_edges * sizeof(short));
01240
01241 for(ipin = 0; ipin < class_inf[iclass].num_pins; ipin++)
01242 {
01243 pin_num = class_inf[iclass].pinlist[ipin];
01244 to_node =
01245 get_rr_node_index(i, j, OPIN, pin_num,
01246 rr_node_indices);
01247 rr_node[inode].edges[ipin] = to_node;
01248 rr_node[inode].switches[ipin] = delayless_switch;
01249
01250 ++rr_node[to_node].fan_in;
01251 }
01252
01253 rr_node[inode].cost_index = SOURCE_COST_INDEX;
01254 rr_node[inode].type = SOURCE;
01255 }
01256 else
01257 {
01258 assert(class_inf[iclass].type == RECEIVER);
01259 inode =
01260 get_rr_node_index(i, j, SINK, iclass,
01261 rr_node_indices);
01262
01263
01264
01265
01266
01267
01268
01269
01270 rr_node[inode].num_edges = 0;
01271 rr_node[inode].edges = NULL;
01272 rr_node[inode].switches = NULL;
01273
01274 rr_node[inode].cost_index = SINK_COST_INDEX;
01275 rr_node[inode].type = SINK;
01276 }
01277
01278
01279 rr_node[inode].capacity = class_inf[iclass].num_pins;
01280 rr_node[inode].occ = 0;
01281 rr_node[inode].xlow = i;
01282 rr_node[inode].xhigh = i;
01283 rr_node[inode].ylow = j;
01284 rr_node[inode].yhigh = j + type->height - 1;
01285 rr_node[inode].R = 0;
01286 rr_node[inode].C = 0;
01287 rr_node[inode].ptc_num = iclass;
01288 rr_node[inode].direction = OPEN;
01289 rr_node[inode].drivers = OPEN;
01290 }
01291
01292
01293 for(ipin = 0; ipin < num_pins; ipin++)
01294 {
01295 iclass = pin_class[ipin];
01296
01297 if(class_inf[iclass].type == RECEIVER)
01298 {
01299 inode =
01300 get_rr_node_index(i, j, IPIN, ipin, rr_node_indices);
01301 to_node =
01302 get_rr_node_index(i, j, SINK, iclass,
01303 rr_node_indices);
01304
01305 rr_node[inode].num_edges = 1;
01306 rr_node[inode].edges = (int *)my_malloc(sizeof(int));
01307 rr_node[inode].switches =
01308 (short *)my_malloc(sizeof(short));
01309
01310 rr_node[inode].edges[0] = to_node;
01311 rr_node[inode].switches[0] = delayless_switch;
01312
01313 ++rr_node[to_node].fan_in;
01314
01315 rr_node[inode].cost_index = IPIN_COST_INDEX;
01316 rr_node[inode].type = IPIN;
01317 }
01318 else
01319 {
01320 assert(class_inf[iclass].type == DRIVER);
01321
01322 inode =
01323 get_rr_node_index(i, j, OPIN, ipin, rr_node_indices);
01324
01325 rr_node[inode].num_edges = 0;
01326 rr_node[inode].edges = NULL;
01327
01328 rr_node[inode].switches = NULL;
01329
01330 rr_node[inode].cost_index = OPIN_COST_INDEX;
01331 rr_node[inode].type = OPIN;
01332 }
01333
01334
01335 rr_node[inode].capacity = 1;
01336 rr_node[inode].occ = 0;
01337 rr_node[inode].xlow = i;
01338 rr_node[inode].xhigh = i;
01339 rr_node[inode].ylow = j;
01340 rr_node[inode].yhigh = j + type->height - 1;
01341 rr_node[inode].C = 0;
01342 rr_node[inode].R = 0;
01343 rr_node[inode].ptc_num = ipin;
01344 rr_node[inode].direction = OPEN;
01345 rr_node[inode].drivers = OPEN;
01346 }
01347 }
01348
01349
01350
01351 static void
01352 build_rr_xchan(IN int i,
01353 IN int j,
01354 IN struct s_ivec ****track_to_ipin_lookup,
01355 IN struct s_ivec ***switch_block_conn,
01356 IN int cost_index_offset,
01357 IN int nodes_per_chan,
01358 IN int *opin_mux_size,
01359 IN short *****sblock_pattern,
01360 IN int Fs_per_side,
01361 IN t_seg_details * seg_details,
01362 IN t_ivec *** rr_node_indices,
01363 INOUT boolean * rr_edge_done,
01364 INOUT t_rr_node * rr_node,
01365 IN int wire_to_ipin_switch,
01366 IN enum e_directionality directionality)
01367 {
01368
01369
01370
01371
01372 int itrack, istart, iend, num_edges, inode, length;
01373 struct s_linked_edge *edge_list, *next;
01374
01375
01376 for(itrack = 0; itrack < nodes_per_chan; itrack++)
01377 {
01378 istart = get_seg_start(seg_details, itrack, j, i);
01379 iend = get_seg_end(seg_details, itrack, istart, j, nx);
01380
01381 if(i > istart)
01382 continue;
01383
01384 edge_list = NULL;
01385
01386
01387 num_edges = 0;
01388
01389 num_edges += get_track_to_ipins(istart, j, itrack,
01390 &edge_list,
01391 rr_node_indices,
01392 track_to_ipin_lookup,
01393 seg_details,
01394 CHANX, nx,
01395 wire_to_ipin_switch,
01396 directionality);
01397
01398 if(j > 0)
01399 {
01400 num_edges += get_track_to_tracks(j, istart, itrack, CHANX,
01401 j, CHANY, nx,
01402 nodes_per_chan,
01403 opin_mux_size,
01404 Fs_per_side,
01405 sblock_pattern,
01406 &edge_list,
01407 seg_details,
01408 directionality,
01409 rr_node_indices,
01410 rr_edge_done,
01411 switch_block_conn);
01412 }
01413
01414 if(j < ny)
01415 {
01416 num_edges += get_track_to_tracks(j, istart, itrack, CHANX,
01417 j + 1, CHANY, nx,
01418 nodes_per_chan,
01419 opin_mux_size,
01420 Fs_per_side,
01421 sblock_pattern,
01422 &edge_list,
01423 seg_details,
01424 directionality,
01425 rr_node_indices,
01426 rr_edge_done,
01427 switch_block_conn);
01428 }
01429
01430 if(istart > 1)
01431 {
01432 num_edges += get_track_to_tracks(j, istart, itrack, CHANX,
01433 istart - 1, CHANX, nx,
01434 nodes_per_chan,
01435 opin_mux_size,
01436 Fs_per_side,
01437 sblock_pattern,
01438 &edge_list,
01439 seg_details,
01440 directionality,
01441 rr_node_indices,
01442 rr_edge_done,
01443 switch_block_conn);
01444 }
01445
01446 if(iend < nx)
01447 {
01448 num_edges += get_track_to_tracks(j, istart, itrack, CHANX,
01449 iend + 1, CHANX, nx,
01450 nodes_per_chan,
01451 opin_mux_size,
01452 Fs_per_side,
01453 sblock_pattern,
01454 &edge_list,
01455 seg_details,
01456 directionality,
01457 rr_node_indices,
01458 rr_edge_done,
01459 switch_block_conn);
01460 }
01461
01462
01463 inode = get_rr_node_index(i, j, CHANX, itrack, rr_node_indices);
01464 alloc_and_load_edges_and_switches(rr_node, inode, num_edges,
01465 rr_edge_done, edge_list);
01466
01467 while(edge_list != NULL) {
01468 next = edge_list->next;
01469 free(edge_list);
01470 edge_list = next;
01471 }
01472
01473
01474 rr_node[inode].cost_index =
01475 cost_index_offset + seg_details[itrack].index;
01476 rr_node[inode].occ = 0;
01477
01478 rr_node[inode].capacity = 1;
01479
01480 rr_node[inode].xlow = istart;
01481 rr_node[inode].xhigh = iend;
01482 rr_node[inode].ylow = j;
01483 rr_node[inode].yhigh = j;
01484
01485 length = iend - istart + 1;
01486 rr_node[inode].R = length * seg_details[itrack].Rmetal;
01487 rr_node[inode].C = length * seg_details[itrack].Cmetal;
01488
01489 rr_node[inode].ptc_num = itrack;
01490 rr_node[inode].type = CHANX;
01491 rr_node[inode].direction = seg_details[itrack].direction;
01492 rr_node[inode].drivers = seg_details[itrack].drivers;
01493 }
01494 }
01495
01496
01497
01498
01499 static void
01500 build_rr_ychan(IN int i,
01501 IN int j,
01502 IN struct s_ivec ****track_to_ipin_lookup,
01503 IN struct s_ivec ***switch_block_conn,
01504 IN int cost_index_offset,
01505 IN int nodes_per_chan,
01506 IN int *opin_mux_size,
01507 IN short *****sblock_pattern,
01508 IN int Fs_per_side,
01509 IN t_seg_details * seg_details,
01510 IN t_ivec *** rr_node_indices,
01511 IN boolean * rr_edge_done,
01512 INOUT t_rr_node * rr_node,
01513 IN int wire_to_ipin_switch,
01514 IN enum e_directionality directionality)
01515 {
01516
01517
01518
01519
01520 int itrack, istart, iend, num_edges, inode, length;
01521 struct s_linked_edge *edge_list, *next;
01522
01523
01524 for(itrack = 0; itrack < nodes_per_chan; itrack++)
01525 {
01526 istart = get_seg_start(seg_details, itrack, i, j);
01527 iend = get_seg_end(seg_details, itrack, istart, i, ny);
01528
01529 if(j > istart)
01530 continue;
01531
01532 edge_list = NULL;
01533
01534
01535 num_edges = 0;
01536
01537 num_edges += get_track_to_ipins(istart, i, itrack,
01538 &edge_list,
01539 rr_node_indices,
01540 track_to_ipin_lookup,
01541 seg_details,
01542 CHANY, ny,
01543 wire_to_ipin_switch,
01544 directionality);
01545
01546 if(i > 0)
01547 {
01548 num_edges += get_track_to_tracks(i, istart, itrack, CHANY,
01549 i, CHANX, ny,
01550 nodes_per_chan,
01551 opin_mux_size,
01552 Fs_per_side,
01553 sblock_pattern,
01554 &edge_list,
01555 seg_details,
01556 directionality,
01557 rr_node_indices,
01558 rr_edge_done,
01559 switch_block_conn);
01560 }
01561
01562 if(i < nx)
01563 {
01564 num_edges += get_track_to_tracks(i, istart, itrack, CHANY,
01565 i + 1, CHANX, ny,
01566 nodes_per_chan,
01567 opin_mux_size,
01568 Fs_per_side,
01569 sblock_pattern,
01570 &edge_list,
01571 seg_details,
01572 directionality,
01573 rr_node_indices,
01574 rr_edge_done,
01575 switch_block_conn);
01576 }
01577
01578 if(istart > 1)
01579 {
01580 num_edges += get_track_to_tracks(i, istart, itrack, CHANY,
01581 istart - 1, CHANY, ny,
01582 nodes_per_chan,
01583 opin_mux_size,
01584 Fs_per_side,
01585 sblock_pattern,
01586 &edge_list,
01587 seg_details,
01588 directionality,
01589 rr_node_indices,
01590 rr_edge_done,
01591 switch_block_conn);
01592 }
01593
01594 if(iend < ny)
01595 {
01596 num_edges += get_track_to_tracks(i, istart, itrack, CHANY,
01597 iend + 1, CHANY, ny,
01598 nodes_per_chan,
01599 opin_mux_size,
01600 Fs_per_side,
01601 sblock_pattern,
01602 &edge_list,
01603 seg_details,
01604 directionality,
01605 rr_node_indices,
01606 rr_edge_done,
01607 switch_block_conn);
01608 }
01609
01610
01611 inode = get_rr_node_index(i, j, CHANY, itrack, rr_node_indices);
01612 alloc_and_load_edges_and_switches(rr_node, inode, num_edges,
01613 rr_edge_done, edge_list);
01614
01615 while(edge_list != NULL) {
01616 next = edge_list->next;
01617 free(edge_list);
01618 edge_list = next;
01619 }
01620
01621
01622 rr_node[inode].cost_index =
01623 cost_index_offset + seg_details[itrack].index;
01624 rr_node[inode].occ = 0;
01625
01626 rr_node[inode].capacity = 1;
01627
01628 rr_node[inode].xlow = i;
01629 rr_node[inode].xhigh = i;
01630 rr_node[inode].ylow = istart;
01631 rr_node[inode].yhigh = iend;
01632
01633 length = iend - istart + 1;
01634 rr_node[inode].R = length * seg_details[itrack].Rmetal;
01635 rr_node[inode].C = length * seg_details[itrack].Cmetal;
01636
01637 rr_node[inode].ptc_num = itrack;
01638 rr_node[inode].type = CHANY;
01639 rr_node[inode].direction = seg_details[itrack].direction;
01640 rr_node[inode].drivers = seg_details[itrack].drivers;
01641 }
01642 }
01643
01644 void
01645 watch_edges(int inode,
01646 t_linked_edge * edge_list_head)
01647 {
01648 t_linked_edge *list_ptr;
01649 int i, to_node;
01650
01651 list_ptr = edge_list_head;
01652 i = 0;
01653
01654 printf("!!! Watching Node %d !!!!\n", inode);
01655 print_rr_node(stdout, rr_node, inode);
01656 printf("Currently connects to: \n");
01657 while(list_ptr != NULL)
01658 {
01659 to_node = list_ptr->edge;
01660 print_rr_node(stdout, rr_node, to_node);
01661 list_ptr = list_ptr->next;
01662 i++;
01663 }
01664 }
01665
01666 void
01667 alloc_and_load_edges_and_switches(IN t_rr_node * rr_node,
01668 IN int inode,
01669 IN int num_edges,
01670 INOUT boolean * rr_edge_done,
01671 IN t_linked_edge * edge_list_head)
01672 {
01673
01674
01675
01676
01677
01678
01679
01680
01681 t_linked_edge *list_ptr, *prev_ptr;
01682 int i;
01683
01684
01685 assert(rr_node[inode].num_edges < 1);
01686 assert(NULL == rr_node[inode].edges);
01687 assert(NULL == rr_node[inode].switches);
01688
01689 rr_node[inode].num_edges = num_edges;
01690 rr_node[inode].edges = (int *)my_malloc(num_edges * sizeof(int));
01691 rr_node[inode].switches = (short *)my_malloc(num_edges * sizeof(short));
01692
01693 i = 0;
01694 list_ptr = edge_list_head;
01695 while(list_ptr && (i < num_edges))
01696 {
01697 rr_node[inode].edges[i] = list_ptr->edge;
01698 rr_node[inode].switches[i] = list_ptr->iswitch;
01699
01700 ++rr_node[list_ptr->edge].fan_in;
01701
01702
01703 rr_edge_done[list_ptr->edge] = FALSE;
01704
01705 prev_ptr = list_ptr;
01706 list_ptr = list_ptr->next;
01707 ++i;
01708 }
01709 assert(list_ptr == NULL);
01710 assert(i == num_edges);
01711 }
01712
01713
01714
01715
01716
01717
01718
01719 static int ****
01720 alloc_and_load_pin_to_track_map(IN enum e_pin_type pin_type,
01721 IN int nodes_per_chan,
01722 IN int Fc,
01723 IN t_type_ptr Type,
01724 IN boolean perturb_switch_pattern,
01725 IN enum e_directionality directionality)
01726 {
01727
01728 int **num_dir;
01729 int ***dir_list;
01730
01731
01732 int i, j, k, iside, ipin, iclass, num_phys_pins, pindex, ioff;
01733 int *pin_num_ordering, *side_ordering, *offset_ordering;
01734 int **num_done_per_dir;
01735 int ****tracks_connected_to_pin;
01736
01737
01738
01739
01740
01741
01742
01743 if(Type->num_pins < 1)
01744 {
01745 return NULL;
01746 }
01747
01748 tracks_connected_to_pin = (int ****)
01749 alloc_matrix4(0, Type->num_pins - 1,
01750 0, Type->height - 1, 0, 3, 0, Fc - 1, sizeof(int));
01751
01752 for(ipin = 0; ipin < Type->num_pins; ipin++)
01753 {
01754 for(ioff = 0; ioff < Type->height; ioff++)
01755 {
01756 for(iside = 0; iside < 4; iside++)
01757 {
01758 for(i = 0; i < Fc; ++i)
01759 {
01760 tracks_connected_to_pin[ipin][ioff][iside][i] = OPEN;
01761 }
01762 }
01763 }
01764 }
01765
01766 num_dir = (int **)alloc_matrix(0, Type->height - 1, 0, 3, sizeof(int));
01767 dir_list =
01768 (int ***)alloc_matrix3(0, Type->height - 1, 0, 3, 0,
01769 Type->num_pins - 1, sizeof(int));
01770
01771
01772 for(i = 0; i < Type->height; i++)
01773 for(j = 0; j < 4; j++)
01774 for(k = 0; k < Type->num_pins; k++)
01775 dir_list[i][j][k] = (-1);
01776
01777 for(i = 0; i < Type->height; i++)
01778 for(j = 0; j < 4; j++)
01779 num_dir[i][j] = 0;
01780
01781 for(ipin = 0; ipin < Type->num_pins; ipin++)
01782 {
01783 iclass = Type->pin_class[ipin];
01784 if(Type->class_inf[iclass].type != pin_type)
01785 continue;
01786
01787
01788
01789
01790 if(Type->is_global_pin[ipin])
01791 continue;
01792 for(ioff = 0; ioff < Type->height; ioff++)
01793 {
01794 for(iside = 0; iside < 4; iside++)
01795 {
01796 if(Type->pinloc[ioff][iside][ipin] == 1)
01797 {
01798 dir_list[ioff][iside][num_dir[ioff]
01799 [iside]] = ipin;
01800 num_dir[ioff][iside]++;
01801 }
01802 }
01803 }
01804 }
01805
01806 num_phys_pins = 0;
01807 for(ioff = 0; ioff < Type->height; ioff++)
01808 {
01809 for(iside = 0; iside < 4; iside++)
01810 num_phys_pins += num_dir[ioff][iside];
01811 }
01812 num_done_per_dir =
01813 (int **)alloc_matrix(0, Type->height - 1, 0, 3, sizeof(int));
01814 for(ioff = 0; ioff < Type->height; ioff++)
01815 {
01816 for(iside = 0; iside < 4; iside++)
01817 {
01818 num_done_per_dir[ioff][iside] = 0;
01819 }
01820 }
01821 pin_num_ordering = (int *)my_malloc(num_phys_pins * sizeof(int));
01822 side_ordering = (int *)my_malloc(num_phys_pins * sizeof(int));
01823 offset_ordering = (int *)my_malloc(num_phys_pins * sizeof(int));
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833 iside = LEFT;
01834 ioff = Type->height - 1;
01835 ipin = 0;
01836 pindex = -1;
01837
01838 while(ipin < num_phys_pins)
01839 {
01840 if(iside == TOP)
01841 {
01842 iside = RIGHT;
01843 }
01844 else if(iside == RIGHT)
01845 {
01846 if(ioff <= 0)
01847 {
01848 iside = BOTTOM;
01849 }
01850 else
01851 {
01852 ioff--;
01853 }
01854 }
01855 else if(iside == BOTTOM)
01856 {
01857 iside = LEFT;
01858 }
01859 else
01860 {
01861 assert(iside == LEFT);
01862 if(ioff >= Type->height - 1)
01863 {
01864 pindex++;
01865 iside = TOP;
01866 }
01867 else
01868 {
01869 ioff++;
01870 }
01871 }
01872
01873 assert(pindex < num_phys_pins);
01874
01875 if(num_done_per_dir[ioff][iside] >= num_dir[ioff][iside])
01876 continue;
01877 pin_num_ordering[ipin] = dir_list[ioff][iside][pindex];
01878 side_ordering[ipin] = iside;
01879 offset_ordering[ipin] = ioff;
01880 assert(Type->pinloc[ioff][iside][dir_list[ioff][iside][pindex]]);
01881 num_done_per_dir[ioff][iside]++;
01882 ipin++;
01883 }
01884
01885 if(perturb_switch_pattern)
01886 {
01887 load_perturbed_switch_pattern(Type,
01888 tracks_connected_to_pin,
01889 num_phys_pins,
01890 pin_num_ordering,
01891 side_ordering,
01892 offset_ordering,
01893 nodes_per_chan, Fc, directionality);
01894 }
01895 else
01896 {
01897 load_uniform_switch_pattern(Type,
01898 tracks_connected_to_pin,
01899 num_phys_pins,
01900 pin_num_ordering,
01901 side_ordering,
01902 offset_ordering,
01903 nodes_per_chan, Fc, directionality);
01904 }
01905 check_all_tracks_reach_pins(Type, tracks_connected_to_pin,
01906 nodes_per_chan, Fc, pin_type);
01907
01908
01909 free_matrix(num_dir, 0, Type->height - 1, 0, sizeof(int));
01910 free_matrix3(dir_list, 0, Type->height - 1, 0, 3, 0, sizeof(int));
01911 free_matrix(num_done_per_dir, 0, Type->height - 1, 0, sizeof(int));
01912 free(pin_num_ordering);
01913 free(side_ordering);
01914 free(offset_ordering);
01915
01916 return tracks_connected_to_pin;
01917 }
01918
01919
01920
01921
01922 static void
01923 load_uniform_switch_pattern(IN t_type_ptr type,
01924 INOUT int ****tracks_connected_to_pin,
01925 IN int num_phys_pins,
01926 IN int *pin_num_ordering,
01927 IN int *side_ordering,
01928 IN int *offset_ordering,
01929 IN int nodes_per_chan,
01930 IN int Fc,
01931 enum e_directionality directionality)
01932 {
01933
01934
01935
01936
01937
01938
01939 int i, j, ipin, iside, ioff, itrack, k;
01940 float f_track, fc_step;
01941 int group_size;
01942 float step_size;
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959 step_size = (float)nodes_per_chan / (float)(Fc * num_phys_pins);
01960
01961 if(directionality == BI_DIRECTIONAL)
01962 {
01963 group_size = 1;
01964 }
01965 else
01966 {
01967 assert(directionality == UNI_DIRECTIONAL);
01968 group_size = 2;
01969 }
01970
01971 assert((nodes_per_chan % group_size == 0) && (Fc % group_size == 0));
01972
01973 fc_step = (float)nodes_per_chan / (float)Fc;
01974
01975 for(i = 0; i < num_phys_pins; i++)
01976 {
01977 ipin = pin_num_ordering[i];
01978 iside = side_ordering[i];
01979 ioff = offset_ordering[i];
01980
01981
01982 for(j = 0; j < (Fc / group_size); j++)
01983 {
01984 f_track = (i * step_size) + (j * fc_step);
01985 itrack = ((int)f_track) * group_size;
01986
01987
01988 itrack = min(itrack, nodes_per_chan - group_size);
01989
01990
01991 for(k = 0; k < group_size; ++k)
01992 {
01993 tracks_connected_to_pin[ipin][ioff][iside]
01994 [group_size * j + k] = itrack + k;
01995 }
01996 }
01997 }
01998 }
01999
02000 static void
02001 load_perturbed_switch_pattern(IN t_type_ptr type,
02002 INOUT int ****tracks_connected_to_pin,
02003 IN int num_phys_pins,
02004 IN int *pin_num_ordering,
02005 IN int *side_ordering,
02006 IN int *offset_ordering,
02007 IN int nodes_per_chan,
02008 IN int Fc,
02009 enum e_directionality directionality)
02010 {
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023 int i, j, ipin, iside, itrack, ihalf, iconn, ioff;
02024 int Fc_dense, Fc_sparse, Fc_half[2];
02025 float f_track, spacing_dense, spacing_sparse, spacing[2];
02026 float step_size;
02027
02028 assert(directionality == BI_DIRECTIONAL);
02029
02030 step_size = (float)nodes_per_chan / (float)(Fc * num_phys_pins);
02031
02032 Fc_dense = (Fc / 2) + 1;
02033 Fc_sparse = Fc - Fc_dense;
02034
02035 spacing_dense = (float)nodes_per_chan / (float)(2 * Fc_dense);
02036 spacing_sparse = (float)nodes_per_chan / (float)(2 * Fc_sparse);
02037
02038 for(i = 0; i < num_phys_pins; i++)
02039 {
02040 ipin = pin_num_ordering[i];
02041 iside = side_ordering[i];
02042 ioff = offset_ordering[i];
02043
02044
02045 spacing[i % 2] = spacing_dense;
02046 Fc_half[i % 2] = Fc_dense;
02047 spacing[(i + 1) % 2] = spacing_sparse;
02048 Fc_half[(i + 1) % 2] = Fc_sparse;
02049
02050 f_track = i * step_size;
02051 iconn = 0;
02052
02053 for(ihalf = 0; ihalf < 2; ihalf++)
02054 {
02055 for(j = 0; j < Fc_half[ihalf]; ++j)
02056 {
02057 itrack = (int)f_track;
02058
02059
02060
02061
02062 itrack = itrack % nodes_per_chan;
02063 tracks_connected_to_pin[ipin][ioff][iside][iconn]
02064 = itrack;
02065
02066 f_track += spacing[ihalf];
02067 iconn++;
02068 }
02069 }
02070 }
02071 }
02072
02073
02074 static void
02075 check_all_tracks_reach_pins(t_type_ptr type,
02076 int ****tracks_connected_to_pin,
02077 int nodes_per_chan,
02078 int Fc,
02079 enum e_pin_type ipin_or_opin)
02080 {
02081
02082
02083
02084 int iconn, iside, itrack, ipin, ioff;
02085 int *num_conns_to_track;
02086
02087 assert(nodes_per_chan > 0);
02088
02089 num_conns_to_track = (int *)my_calloc(nodes_per_chan, sizeof(int));
02090
02091 for(ipin = 0; ipin < type->num_pins; ipin++)
02092 {
02093 for(ioff = 0; ioff < type->height; ioff++)
02094 {
02095 for(iside = 0; iside < 4; iside++)
02096 {
02097 if(tracks_connected_to_pin[ipin][ioff][iside][0]
02098 != OPEN)
02099 {
02100 for(iconn = 0; iconn < Fc; iconn++)
02101 {
02102 itrack =
02103 tracks_connected_to_pin[ipin]
02104 [ioff][iside][iconn];
02105 num_conns_to_track[itrack]++;
02106 }
02107 }
02108 }
02109 }
02110 }
02111
02112 for(itrack = 0; itrack < nodes_per_chan; itrack++)
02113 {
02114 if(num_conns_to_track[itrack] <= 0)
02115 {
02116 printf
02117 ("Warning (check_all_tracks_reach_pins): track %d does not \n"
02118 "\tconnect to any FB ", itrack);
02119
02120 if(ipin_or_opin == DRIVER)
02121 printf("OPINs.\n");
02122 else
02123 printf("IPINs.\n");
02124 }
02125 }
02126
02127 free(num_conns_to_track);
02128 }
02129
02130
02131
02132
02133 static struct s_ivec ***
02134 alloc_and_load_track_to_pin_lookup(IN int ****pin_to_track_map,
02135 IN int Fc,
02136 IN int height,
02137 IN int num_pins,
02138 IN int nodes_per_chan)
02139 {
02140 int ipin, iside, itrack, iconn, ioff, pin_counter;
02141 struct s_ivec ***track_to_pin_lookup;
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155 if(num_pins < 1)
02156 {
02157 return NULL;
02158 }
02159
02160
02161 track_to_pin_lookup =
02162 (struct s_ivec ***)alloc_matrix3(0, nodes_per_chan - 1, 0,
02163 height - 1, 0, 3,
02164 sizeof(struct s_ivec));
02165 for(itrack = 0; itrack < nodes_per_chan; itrack++)
02166 {
02167 for(ioff = 0; ioff < height; ioff++)
02168 {
02169 for(iside = 0; iside < 4; iside++)
02170 {
02171 track_to_pin_lookup[itrack][ioff][iside].nelem =
02172 0;
02173 track_to_pin_lookup[itrack][ioff][iside].list =
02174 NULL;
02175 }
02176 }
02177 }
02178
02179
02180 for(ipin = 0; ipin < num_pins; ipin++)
02181 {
02182 for(ioff = 0; ioff < height; ioff++)
02183 {
02184 for(iside = 0; iside < 4; iside++)
02185 {
02186 if(pin_to_track_map[ipin][ioff][iside][0] == OPEN)
02187 continue;
02188
02189 for(iconn = 0; iconn < Fc; iconn++)
02190 {
02191 itrack =
02192 pin_to_track_map[ipin][ioff][iside]
02193 [iconn];
02194 track_to_pin_lookup[itrack][ioff][iside].
02195 nelem++;
02196 }
02197 }
02198 }
02199 }
02200
02201
02202 for(itrack = 0; itrack < nodes_per_chan; itrack++)
02203 {
02204 for(ioff = 0; ioff < height; ioff++)
02205 {
02206 for(iside = 0; iside < 4; iside++)
02207 {
02208 track_to_pin_lookup[itrack][ioff][iside].list = NULL;
02209 if(track_to_pin_lookup[itrack][ioff][iside].
02210 nelem != 0)
02211 {
02212 track_to_pin_lookup[itrack][ioff][iside].
02213 list =
02214 (int *)
02215 my_malloc(track_to_pin_lookup[itrack]
02216 [ioff][iside].nelem *
02217 sizeof(int));
02218 track_to_pin_lookup[itrack][ioff][iside].
02219 nelem = 0;
02220 }
02221 }
02222 }
02223 }
02224
02225
02226 for(ipin = 0; ipin < num_pins; ipin++)
02227 {
02228 for(ioff = 0; ioff < height; ioff++)
02229 {
02230 for(iside = 0; iside < 4; iside++)
02231 {
02232 if(pin_to_track_map[ipin][ioff][iside][0] == OPEN)
02233 continue;
02234
02235 for(iconn = 0; iconn < Fc; iconn++)
02236 {
02237 itrack =
02238 pin_to_track_map[ipin][ioff][iside]
02239 [iconn];
02240 pin_counter =
02241 track_to_pin_lookup[itrack][ioff]
02242 [iside].nelem;
02243 track_to_pin_lookup[itrack][ioff][iside].
02244 list[pin_counter] = ipin;
02245 track_to_pin_lookup[itrack][ioff][iside].
02246 nelem++;
02247 }
02248 }
02249 }
02250 }
02251
02252 return track_to_pin_lookup;
02253 }
02254
02255
02256
02257
02258 void
02259 dump_rr_graph(IN const char *file_name)
02260 {
02261
02262 int inode;
02263 FILE *fp;
02264
02265 fp = my_fopen(file_name, "w");
02266
02267 for(inode = 0; inode < num_rr_nodes; inode++)
02268 {
02269 print_rr_node(fp, rr_node, inode);
02270 fprintf(fp, "\n");
02271 }
02272
02273 #if 0
02274 fprintf(fp, "\n\n%d rr_indexed_data entries.\n\n", num_rr_indexed_data);
02275
02276 for(index = 0; index < num_rr_indexed_data; index++)
02277 {
02278 print_rr_indexed_data(fp, index);
02279 fprintf(fp, "\n");
02280 }
02281 #endif
02282
02283 fclose(fp);
02284 }
02285
02286
02287
02288 static void
02289 print_rr_node(FILE * fp,
02290 t_rr_node * rr_node,
02291 int inode)
02292 {
02293
02294 static const char *name_type[] = {
02295 "SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY"
02296 };
02297 static const char *direction_name[] = {
02298 "OPEN", "INC_DIRECTION", "DEC_DIRECTION", "BI_DIRECTION"
02299 };
02300 static const char *drivers_name[] = {
02301 "OPEN", "MULTI_BUFFER", "MULTI_MUXED", "MULTI_MERGED", "SINGLE"
02302 };
02303
02304 t_rr_type rr_type;
02305 int iconn;
02306
02307 rr_type = rr_node[inode].type;
02308
02309
02310 assert(rr_type < (sizeof(name_type) / sizeof(char *)));
02311 assert((rr_node[inode].direction + 1) <
02312 (sizeof(direction_name) / sizeof(char *)));
02313 assert((rr_node[inode].drivers + 1) <
02314 (sizeof(drivers_name) / sizeof(char *)));
02315
02316 fprintf(fp, "Node: %d %s ", inode, name_type[rr_type]);
02317 if((rr_node[inode].xlow == rr_node[inode].xhigh) &&
02318 (rr_node[inode].ylow == rr_node[inode].yhigh))
02319 {
02320 fprintf(fp, "(%d, %d) ", rr_node[inode].xlow,
02321 rr_node[inode].ylow);
02322 }
02323 else
02324 {
02325 fprintf(fp, "(%d, %d) to (%d, %d) ", rr_node[inode].xlow,
02326 rr_node[inode].ylow, rr_node[inode].xhigh,
02327 rr_node[inode].yhigh);
02328 }
02329 fprintf(fp, "Ptc_num: %d ", rr_node[inode].ptc_num);
02330 fprintf(fp, "Direction: %s ",
02331 direction_name[rr_node[inode].direction + 1]);
02332 fprintf(fp, "Drivers: %s ", drivers_name[rr_node[inode].drivers + 1]);
02333 fprintf(fp, "\n");
02334
02335 fprintf(fp, "%d edge(s):", rr_node[inode].num_edges);
02336 for(iconn = 0; iconn < rr_node[inode].num_edges; iconn++)
02337 fprintf(fp, " %d", rr_node[inode].edges[iconn]);
02338 fprintf(fp, "\n");
02339
02340 fprintf(fp, "Switch types:");
02341 for(iconn = 0; iconn < rr_node[inode].num_edges; iconn++)
02342 fprintf(fp, " %d", rr_node[inode].switches[iconn]);
02343 fprintf(fp, "\n");
02344
02345 fprintf(fp, "Occ: %d Capacity: %d\n", rr_node[inode].occ,
02346 rr_node[inode].capacity);
02347 fprintf(fp, "R: %g C: %g\n", rr_node[inode].R, rr_node[inode].C);
02348 fprintf(fp, "Cost_index: %d\n", rr_node[inode].cost_index);
02349 }
02350
02351
02352
02353 void
02354 print_rr_indexed_data(FILE * fp,
02355 int index)
02356 {
02357
02358 fprintf(fp, "Index: %d\n", index);
02359
02360 fprintf(fp, "ortho_cost_index: %d ",
02361 rr_indexed_data[index].ortho_cost_index);
02362 fprintf(fp, "base_cost: %g ", rr_indexed_data[index].saved_base_cost);
02363 fprintf(fp, "saved_base_cost: %g\n",
02364 rr_indexed_data[index].saved_base_cost);
02365
02366 fprintf(fp, "Seg_index: %d ", rr_indexed_data[index].seg_index);
02367 fprintf(fp, "inv_length: %g\n", rr_indexed_data[index].inv_length);
02368
02369 fprintf(fp, "T_linear: %g ", rr_indexed_data[index].T_linear);
02370 fprintf(fp, "T_quadratic: %g ", rr_indexed_data[index].T_quadratic);
02371 fprintf(fp, "C_load: %g\n", rr_indexed_data[index].C_load);
02372 }
02373
02374
02375
02376 static void
02377 build_unidir_rr_opins(IN int i,
02378 IN int j,
02379 IN struct s_grid_tile **grid,
02380 IN int *Fc_out,
02381 IN int nodes_per_chan,
02382 IN t_seg_details * seg_details,
02383 INOUT int **Fc_xofs,
02384 INOUT int **Fc_yofs,
02385 INOUT t_rr_node * rr_node,
02386 INOUT boolean * rr_edge_done,
02387 OUT boolean * Fc_clipped,
02388 IN t_ivec *** rr_node_indices)
02389 {
02390
02391
02392
02393
02394 t_type_ptr type;
02395 int ipin, iclass, ofs, chan, seg, max_len, inode;
02396 enum e_side side;
02397 t_rr_type chan_type;
02398 t_linked_edge *edge_list = NULL, *next;
02399 boolean clipped, vert, pos_dir;
02400 int num_edges;
02401 int **Fc_ofs;
02402
02403 *Fc_clipped = FALSE;
02404
02405
02406 if(grid[i][j].offset > 0)
02407 {
02408 return;
02409 }
02410
02411 type = grid[i][j].type;
02412
02413
02414 for(ipin = 0; ipin < type->num_pins; ++ipin)
02415 {
02416
02417 iclass = type->pin_class[ipin];
02418 if(type->class_inf[iclass].type != DRIVER)
02419 {
02420 continue;
02421 }
02422 if(type->is_global_pin[ipin])
02423 {
02424 continue;
02425 }
02426
02427 num_edges = 0;
02428 edge_list = NULL;
02429 for(ofs = 0; ofs < type->height; ++ofs)
02430 {
02431 for(side = 0; side < 4; ++side)
02432 {
02433
02434 if(0 == type->pinloc[ofs][side][ipin])
02435 {
02436 continue;
02437 }
02438
02439
02440
02441 vert = ((side == TOP) || (side == BOTTOM));
02442 pos_dir = ((side == TOP) || (side == RIGHT));
02443 chan_type = (vert ? CHANX : CHANY);
02444 chan = (vert ? (j + ofs) : i);
02445 seg = (vert ? i : (j + ofs));
02446 max_len = (vert ? ny : nx);
02447 Fc_ofs = (vert ? Fc_xofs : Fc_yofs);
02448 if(FALSE == pos_dir)
02449 {
02450 --chan;
02451 }
02452
02453
02454 if(chan < 0)
02455 {
02456 continue;
02457 }
02458 if(seg < 1)
02459 {
02460 continue;
02461 }
02462 if(seg > (vert ? ny : nx))
02463 {
02464 continue;
02465 }
02466 if(chan > (vert ? nx : ny))
02467 {
02468 continue;
02469 }
02470
02471
02472 num_edges +=
02473 get_unidir_opin_connections(chan, seg,
02474 Fc_out[type->
02475 index],
02476 chan_type,
02477 seg_details,
02478 &edge_list,
02479 Fc_ofs,
02480 rr_edge_done,
02481 max_len,
02482 nodes_per_chan,
02483 rr_node_indices,
02484 &clipped);
02485 if(clipped)
02486 {
02487 *Fc_clipped = TRUE;
02488 }
02489 }
02490 }
02491
02492
02493 inode = get_rr_node_index(i, j, OPIN, ipin, rr_node_indices);
02494 alloc_and_load_edges_and_switches(rr_node, inode, num_edges,
02495 rr_edge_done, edge_list);
02496 while(edge_list != NULL) {
02497 next = edge_list->next;
02498 free(edge_list);
02499 edge_list = next;
02500 }
02501 }
02502 }
02503
02504 static void
02505 load_uniform_opin_switch_pattern_paired(IN int *Fc_out,
02506 IN int num_pins,
02507 IN int *pins_in_chan_seg,
02508 IN int num_wire_inc_muxes,
02509 IN int num_wire_dec_muxes,
02510 IN int *wire_inc_muxes,
02511 IN int *wire_dec_muxes,
02512 INOUT t_rr_node * rr_node,
02513 INOUT boolean * rr_edge_done,
02514 IN t_seg_details * seg_details,
02515 OUT boolean * Fc_clipped)
02516 {
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548 int ipin, iconn, num_edges, init_mux;
02549 int from_node, to_node, to_track;
02550 int xlow, ylow;
02551 t_linked_edge *edge_list;
02552 int *wire_muxes;
02553 int k, num_wire_muxes, Fc_output_per_side, CurFc;
02554 int count_inc, count_dec;
02555 t_type_ptr type;
02556
02557 *Fc_clipped = FALSE;
02558
02559 count_inc = count_dec = 0;
02560
02561 for(ipin = 0; ipin < num_pins; ipin++)
02562 {
02563 from_node = pins_in_chan_seg[ipin];
02564 xlow = rr_node[from_node].xlow;
02565 ylow = rr_node[from_node].ylow;
02566 type = grid[xlow][ylow].type;
02567 edge_list = NULL;
02568 num_edges = 0;
02569
02570
02571 for(k = 0; k < 2; ++k)
02572 {
02573 if(k == 0)
02574 {
02575 num_wire_muxes = num_wire_inc_muxes;
02576 wire_muxes = wire_inc_muxes;
02577 }
02578 else
02579 {
02580 num_wire_muxes = num_wire_dec_muxes;
02581 wire_muxes = wire_dec_muxes;
02582 }
02583
02584
02585 assert(Fc_out[type->index] % 2 == 0);
02586 Fc_output_per_side = Fc_out[type->index] / 2;
02587
02588
02589
02590 CurFc = Fc_output_per_side;
02591 if(Fc_output_per_side > num_wire_muxes)
02592 {
02593 *Fc_clipped = TRUE;
02594 CurFc = num_wire_muxes;
02595 }
02596
02597 if(k == 0)
02598 {
02599 init_mux = (count_inc) % num_wire_muxes;
02600 count_inc += CurFc;
02601 }
02602 else
02603 {
02604 init_mux = (count_dec) % num_wire_muxes;
02605 count_dec += CurFc;
02606 }
02607
02608 for(iconn = 0; iconn < CurFc; iconn++)
02609 {
02610
02611
02612 to_node =
02613 wire_muxes[(init_mux +
02614 iconn) % num_wire_muxes];
02615
02616 rr_node[to_node].num_opin_drivers++;
02617 to_track = rr_node[to_node].ptc_num;
02618
02619 if(FALSE == rr_edge_done[to_node])
02620 {
02621
02622
02623 rr_edge_done[to_node] = TRUE;
02624 edge_list =
02625 insert_in_edge_list(edge_list,
02626 to_node,
02627 seg_details
02628 [to_track].
02629 wire_switch);
02630 num_edges++;
02631 }
02632 }
02633 }
02634
02635 if(num_edges < 1)
02636 {
02637 printf
02638 ("Error: opin %d at (%d,%d) does not connect to any "
02639 "tracks.\n", rr_node[from_node].ptc_num,
02640 rr_node[from_node].xlow, rr_node[from_node].ylow);
02641 exit(1);
02642 }
02643
02644 alloc_and_load_edges_and_switches(rr_node, from_node, num_edges,
02645 rr_edge_done, edge_list);
02646 }
02647 }
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659 static void
02660 view_mux_size_distribution(t_ivec *** rr_node_indices,
02661 int nodes_per_chan,
02662 t_seg_details * seg_details_x,
02663 t_seg_details * seg_details_y)
02664 {
02665
02666 int i, j, itrack, seg_num, chan_num, max_len;
02667 int start, end, inode, max_value, min_value;
02668 int array_count, k, num_muxes;
02669 short direction, side;
02670 float *percent_range_array;
02671 float percent_range, percent_range_sum, avg_percent_range;
02672 float std_dev_percent_range, deviation_f;
02673 int range, *range_array, global_max_range;
02674 float avg_range, range_sum, std_dev_range;
02675 t_seg_details *seg_details;
02676 t_mux *new_mux, *sblock_mux_list_head, *current, *next;
02677
02678 #ifdef ENABLE_DUMP
02679 FILE *dump_file_per_sblock, *dump_file;
02680 #endif
02681 t_mux_size_distribution *distr_list, *distr_current, *new_distribution,
02682 *distr_next;
02683
02684 #ifdef ENABLE_DUMP
02685 dump_file = my_fopen("mux_size_dump.txt", "w");
02686 dump_file_per_sblock = my_fopen("mux_size_per_sblock_dump.txt", "w");
02687 #endif
02688
02689 sblock_mux_list_head = NULL;
02690 percent_range_array =
02691 (float *)my_malloc((nx - 1) * (ny - 1) * sizeof(float));
02692 range_array = (int *)my_malloc((nx - 1) * (ny - 1) * sizeof(int));
02693 array_count = 0;
02694 percent_range_sum = 0.0;
02695 range_sum = 0.0;
02696 global_max_range = 0;
02697 min_value = 0;
02698 max_value = 0;
02699 seg_num = 0;
02700 chan_num = 0;
02701 direction = 0;
02702 seg_details = 0;
02703 max_len = 0;
02704 distr_list = NULL;
02705
02706
02707 for(j = (ny - 1); j > 0; j--)
02708 {
02709 for(i = 1; i < nx; i++)
02710 {
02711 num_muxes = 0;
02712 for(side = 0; side < 4; side++)
02713 {
02714 switch (side)
02715 {
02716 case LEFT:
02717 seg_num = i;
02718 chan_num = j;
02719 direction = DEC_DIRECTION;
02720 seg_details = seg_details_x;
02721 max_len = nx;
02722 break;
02723
02724 case RIGHT:
02725 seg_num = i + 1;
02726 chan_num = j;
02727 direction = INC_DIRECTION;
02728 seg_details = seg_details_x;
02729 max_len = nx;
02730 break;
02731
02732 case TOP:
02733 seg_num = j + 1;
02734 chan_num = i;
02735 direction = INC_DIRECTION;
02736 seg_details = seg_details_y;
02737 max_len = ny;
02738 break;
02739
02740 case BOTTOM:
02741 seg_num = j;
02742 chan_num = i;
02743 direction = DEC_DIRECTION;
02744 seg_details = seg_details_y;
02745 max_len = ny;
02746 break;
02747
02748 default:
02749 assert(FALSE);
02750 }
02751
02752 assert(nodes_per_chan > 0);
02753 for(itrack = 0; itrack < nodes_per_chan; itrack++)
02754 {
02755 start =
02756 get_seg_start(seg_details, itrack,
02757 seg_num, chan_num);
02758 end =
02759 get_seg_end(seg_details, itrack,
02760 start, chan_num, max_len);
02761
02762 if((seg_details[itrack].direction ==
02763 direction) && (((start == seg_num)
02764 && (direction ==
02765 INC_DIRECTION))
02766 || ((end == seg_num)
02767 && (direction ==
02768 DEC_DIRECTION))))
02769 {
02770 num_muxes++;
02771 if(side == LEFT || side == RIGHT)
02772 {
02773 inode =
02774 get_rr_node_index
02775 (seg_num, chan_num,
02776 CHANX, itrack,
02777 rr_node_indices);
02778 }
02779 else
02780 {
02781 assert((side == TOP) || (side == BOTTOM));
02782 inode =
02783 get_rr_node_index
02784 (chan_num, seg_num,
02785 CHANY, itrack,
02786 rr_node_indices);
02787 }
02788
02789 new_mux = (t_mux *)
02790 my_malloc(sizeof(t_mux));
02791 new_mux->size =
02792 rr_node[inode].
02793 num_wire_drivers +
02794 rr_node[inode].
02795 num_opin_drivers;
02796 new_mux->next = NULL;
02797
02798
02799 if(sblock_mux_list_head == NULL)
02800 {
02801
02802 sblock_mux_list_head =
02803 new_mux;
02804 }
02805 else if(sblock_mux_list_head->
02806 size < new_mux->size)
02807 {
02808
02809 new_mux->next =
02810 sblock_mux_list_head;
02811 sblock_mux_list_head =
02812 new_mux;
02813 }
02814 else
02815 {
02816
02817 current =
02818 sblock_mux_list_head;
02819 next = current->next;
02820
02821 while((next != NULL)
02822 && (next->size >
02823 new_mux->size))
02824 {
02825 current = next;
02826 next =
02827 current->next;
02828 }
02829
02830 if(next == NULL)
02831 {
02832 current->next =
02833 new_mux;
02834 }
02835 else
02836 {
02837 new_mux->next =
02838 current->next;
02839 current->next =
02840 new_mux;
02841 }
02842 }
02843
02844 }
02845 }
02846 }
02847
02848
02849 current = sblock_mux_list_head;
02850
02851 #ifdef ENABLE_DUMP
02852 fprintf(dump_file_per_sblock,
02853 "sblock at (%d, %d) has mux sizes: {", i, j);
02854 #endif
02855
02856 if(current != NULL)
02857 {
02858 max_value = min_value = current->size;
02859 }
02860 while(current != NULL)
02861 {
02862 if(max_value < current->size)
02863 max_value = current->size;
02864 if(min_value > current->size)
02865 min_value = current->size;
02866
02867 #ifdef ENABLE_DUMP
02868 fprintf(dump_file_per_sblock, "%d ",
02869 current->size);
02870 fprintf(dump_file, "%d\n", current->size);
02871 #endif
02872
02873 current = current->next;
02874 }
02875
02876 #ifdef ENABLE_DUMP
02877 fprintf(dump_file_per_sblock, "}\n\tmax: %d\tmin:%d",
02878 max_value, min_value);
02879 #endif
02880
02881 range = max_value - min_value;
02882 percent_range = ((float)range) / ((float)min_value);
02883
02884 if(global_max_range < range)
02885 global_max_range = range;
02886
02887 #ifdef ENABLE_DUMP
02888 fprintf(dump_file_per_sblock,
02889 "\t\trange: %d\t\tpercent range:%.2f\n",
02890 range, percent_range);
02891 #endif
02892
02893 percent_range_array[array_count] = percent_range;
02894 range_array[array_count] = range;
02895
02896 percent_range_sum += percent_range;
02897 range_sum += range;
02898
02899 array_count++;
02900
02901
02902
02903
02904
02905
02906
02907 distr_current = distr_list;
02908 while(distr_current != NULL
02909 && distr_current->mux_count != num_muxes)
02910 {
02911 distr_current = distr_current->next;
02912 }
02913
02914 if(distr_current == NULL)
02915 {
02916
02917
02918
02919 new_distribution = (t_mux_size_distribution *)
02920 my_malloc(sizeof(t_mux_size_distribution));
02921 new_distribution->mux_count = num_muxes;
02922 new_distribution->max_index = max_value;
02923 new_distribution->distr =
02924 (int *)my_calloc(max_value + 1, sizeof(int));
02925
02926
02927 current = sblock_mux_list_head;
02928 while(current != NULL)
02929 {
02930 assert(current->size <=
02931 new_distribution->max_index);
02932 new_distribution->distr[current->size]++;
02933 current = current->next;
02934 }
02935
02936
02937 new_distribution->next = distr_list;
02938 distr_list = new_distribution;
02939 }
02940 else
02941 {
02942
02943 current = sblock_mux_list_head;
02944
02945 while(current != NULL)
02946 {
02947 if(current->size >
02948 distr_current->max_index)
02949 {
02950
02951 distr_current->distr =
02952 my_realloc(distr_current->
02953 distr,
02954 (current->size +
02955 1) * sizeof(int));
02956
02957
02958 for(k =
02959 (distr_current->max_index +
02960 1); k <= current->size; k++)
02961 distr_current->distr[k] = 0;
02962
02963 distr_current->max_index =
02964 current->size;
02965 distr_current->distr[current->
02966 size]++;
02967 }
02968 else
02969 {
02970 distr_current->distr[current->
02971 size]++;
02972 }
02973 current = current->next;
02974 }
02975 }
02976
02977
02978 current = sblock_mux_list_head;
02979 while(current != NULL)
02980 {
02981 next = current->next;
02982 free(current);
02983 current = next;
02984 }
02985 sblock_mux_list_head = NULL;
02986 }
02987 }
02988
02989 avg_percent_range = (float)percent_range_sum / array_count;
02990 avg_range = (float)range_sum / array_count;
02991
02992 percent_range_sum = 0.0;
02993 range_sum = 0.0;
02994 for(k = 0; k < array_count; k++)
02995 {
02996 deviation_f = (percent_range_array[k] - avg_percent_range);
02997 percent_range_sum += deviation_f * deviation_f;
02998
02999 deviation_f = ((float)range_array[k] - avg_range);
03000 range_sum += deviation_f * deviation_f;
03001 }
03002 std_dev_percent_range =
03003 sqrt(percent_range_sum / ((float)array_count - 1.0));
03004 std_dev_range = sqrt(range_sum / ((float)array_count - 1.0));
03005 printf("==== MUX size statistics ====\n");
03006 printf("max range of mux size within a sblock is; %d\n",
03007 global_max_range);
03008 printf("average range of mux size within a sblock is; %.2f\n", avg_range);
03009 printf("std dev of range of mux size within a sblock is; %.2f\n",
03010 std_dev_range);
03011 printf
03012 ("average percent range of mux size within a sblock is; %.2f%%\n",
03013 avg_percent_range * 100.0);
03014 printf
03015 ("std dev of percent range of mux size within a sblock is; %.2f%%\n",
03016 std_dev_percent_range * 100.0);
03017
03018 printf(" -- Detailed MUX size distribution by sblock type -- \n");
03019 distr_current = distr_list;
03020 while(distr_current != NULL)
03021 {
03022 print_distribution(stdout, distr_current);
03023
03024
03025 distr_next = distr_current->next;
03026
03027 free(distr_current->distr);
03028 free(distr_current);
03029
03030 distr_current = distr_next;
03031 }
03032
03033 free(percent_range_array);
03034 free(range_array);
03035 #ifdef ENABLE_DUMP
03036 fclose(dump_file_per_sblock);
03037 fclose(dump_file);
03038 #endif
03039 }
03040
03041
03042 static void
03043 print_distribution(FILE * fptr,
03044 t_mux_size_distribution * distr_struct)
03045 {
03046 int *distr;
03047 int k;
03048 float sum;
03049 boolean zeros;
03050
03051 distr = distr_struct->distr;
03052 fprintf(fptr,
03053 "For Sblocks containing %d MUXes, the MUX size distribution is:\n",
03054 distr_struct->mux_count);
03055 fprintf(fptr, "\t\t\tSize\t\t\tFrequency (percent)\n");
03056
03057 sum = 0.0;
03058 for(k = 0; k <= distr_struct->max_index; k++)
03059 sum += distr[k];
03060
03061 zeros = TRUE;
03062 for(k = 0; k <= distr_struct->max_index; k++)
03063 {
03064 if(zeros && (distr[k] == 0))
03065 {
03066
03067 }
03068 else
03069 {
03070 zeros = FALSE;
03071 fprintf(fptr, "\t\t\t%d\t\t\t%d (%.2f%%)\n", k, distr[k],
03072 (float)distr[k] / sum * 100.0);
03073 }
03074 }
03075 fprintf(fptr, "\nEnd of this Sblock MUX size distribution.\n");
03076
03077 }