Go to the source code of this file.
Typedefs | |
typedef enum e_graph_type | t_graph_type |
Enumerations | |
enum | e_graph_type { GRAPH_GLOBAL, GRAPH_BIDIR, GRAPH_UNIDIR, GRAPH_UNIDIR_TILEABLE } |
enum | { RR_GRAPH_NO_WARN = 0x00, RR_GRAPH_WARN_FC_CLIPPED = 0x01, RR_GRAPH_WARN_CHAN_WIDTH_CHANGED = 0x02 } |
Functions | |
void | build_rr_graph (IN t_graph_type graph_type, IN int num_types, IN t_type_ptr types, IN int nx, IN int ny, IN struct s_grid_tile **grid, IN int chan_width, IN struct s_chan_width_dist *chan_capacity_inf, IN enum e_switch_block_type sb_type, IN int Fs, IN int num_seg_types, IN int num_switches, IN t_segment_inf *segment_inf, IN int global_route_switch, IN int delayless_switch, IN t_timing_inf timing_inf, IN int wire_to_ipin_switch, IN enum e_base_cost_type base_cost_type, OUT int *Warnings) |
void | free_rr_graph (void) |
void | dump_rr_graph (IN const char *file_name) |
void | print_rr_indexed_data (FILE *fp, int index) |
void | load_net_rr_terminals (t_ivec ***rr_node_indices) |
typedef enum e_graph_type t_graph_type |
Definition at line 9 of file rr_graph.h.
anonymous enum |
Definition at line 13 of file rr_graph.h.
00014 { 00015 RR_GRAPH_NO_WARN = 0x00, 00016 RR_GRAPH_WARN_FC_CLIPPED = 0x01, 00017 RR_GRAPH_WARN_CHAN_WIDTH_CHANGED = 0x02 00018 };
enum e_graph_type |
Definition at line 1 of file rr_graph.h.
00002 { 00003 GRAPH_GLOBAL, /* One node per channel with wire capacity > 1 and full connectivity */ 00004 GRAPH_BIDIR, /* Detailed bidirectional graph */ 00005 GRAPH_UNIDIR, /* Detailed unidir graph, untilable */ 00006 /* RESEARCH TODO: Get this option debugged */ 00007 GRAPH_UNIDIR_TILEABLE /* Detail unidir graph with wire groups multiples of 2*L */ 00008 };
void build_rr_graph | ( | IN t_graph_type | graph_type, | |
IN int | num_types, | |||
IN t_type_ptr | types, | |||
IN int | nx, | |||
IN int | ny, | |||
IN struct s_grid_tile ** | grid, | |||
IN int | chan_width, | |||
IN struct s_chan_width_dist * | chan_capacity_inf, | |||
IN enum e_switch_block_type | sb_type, | |||
IN int | Fs, | |||
IN int | num_seg_types, | |||
IN int | num_switches, | |||
IN t_segment_inf * | segment_inf, | |||
IN int | global_route_switch, | |||
IN int | delayless_switch, | |||
IN t_timing_inf | timing_inf, | |||
IN int | wire_to_ipin_switch, | |||
IN enum e_base_cost_type | base_cost_type, | |||
OUT int * | Warnings | |||
) |
Definition at line 280 of file rr_graph.c.
00299 { 00300 /* Temp structures used to build graph */ 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; /* [0..num_types-1][0..num_pins-1][0..height][0..3][0..Fc-1] */ 00307 int *****ipin_to_track_map = NULL; /* [0..num_types-1][0..num_pins-1][0..height][0..3][0..Fc-1] */ 00308 t_ivec ****track_to_ipin_lookup = NULL; /* [0..num_types-1][0..nodes_per_chan-1][0..height][0..3] */ 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; /* [0..ny-1][0..nx-1] */ 00318 int **Fc_yofs = NULL; /* [0..nx-1][0..ny-1] */ 00319 00320 rr_node_indices = NULL; 00321 rr_node = NULL; 00322 num_rr_nodes = 0; 00323 00324 /* Reset warning flag */ 00325 *Warnings = RR_GRAPH_NO_WARN; 00326 00327 /* Decode the graph_type */ 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 /* Global routing uses a single longwire track */ 00350 nodes_per_chan = (is_global_graph ? 1 : chan_width); 00351 assert(nodes_per_chan > 0); 00352 00353 00354 00355 /* START SEG_DETAILS */ 00356 if(is_global_graph) 00357 { 00358 /* Sets up a single unit length segment type for global routing. */ 00359 seg_details = 00360 alloc_and_load_global_route_seg_details(nodes_per_chan, 00361 global_route_switch); 00362 } 00363 else 00364 { 00365 /* Setup segments including distrubuting tracks and staggering. 00366 * If use_full_seg_groups is specified, nodes_per_chan may be 00367 * changed. Warning should be singled to caller if this happens. */ 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 /* CREATE_ECHO_FILES */ 00382 } 00383 /* END SEG_DETAILS */ 00384 00385 00386 00387 /* START FC */ 00388 /* Determine the actual value of Fc */ 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 { /* Skip "<EMPTY>" */ 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 /* VERBOSE */ 00437 } 00438 00439 perturb_ipins = 00440 alloc_and_load_perturb_ipins(nodes_per_chan, num_types, Fc_in, 00441 Fc_out, directionality); 00442 /* END FC */ 00443 00444 00445 /* Alloc node lookups, count nodes, alloc rr nodes */ 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 /* These are data structures used by the the unidir opin mapping. */ 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 /* START SB LOOKUP */ 00473 /* Alloc and load the switch block lookup */ 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 /* END SB LOOKUP */ 00503 00504 00505 00506 /* START IPIN MAP */ 00507 /* Create ipin map lookups */ 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 /* END IPIN MAP */ 00527 00528 00529 00530 /* START OPIN MAP */ 00531 /* Create opin map lookups */ 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 /* END OPIN MAP */ 00547 00548 /* UDSD Modifications by WMF begin */ 00549 /* I'm adding 2 new fields to t_rr_node, and I want them initialized to 0. */ 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 /* Update rr_nodes capacities if global routing */ 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 /* CREATE_ECHO_FILES */ 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 /* Free all temp structs */ 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 }
void dump_rr_graph | ( | IN const char * | file_name | ) |
Definition at line 2259 of file rr_graph.c.
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 }
void free_rr_graph | ( | void | ) |
Definition at line 1045 of file rr_graph.c.
01046 { 01047 int i; 01048 01049 /* Frees all the routing graph data structures, if they have been * 01050 * allocated. I use rr_mem_chunk_list_head as a flag to indicate * 01051 * whether or not the graph has been allocated -- if it is not NULL, * 01052 * a routing graph exists and can be freed. Hence, you can call this * 01053 * routine even if you're not sure of whether a rr_graph exists or not. */ 01054 01055 if(rr_mem_chunk_list_head == NULL) /* Nothing to free. */ 01056 return; 01057 01058 free_chunk_memory(rr_mem_chunk_list_head); /* Frees ALL "chunked" data */ 01059 rr_mem_chunk_list_head = NULL; /* No chunks allocated now. */ 01060 chunk_bytes_avail = 0; /* 0 bytes left in current "chunk". */ 01061 chunk_next_avail_mem = NULL; /* No current chunk. */ 01062 01063 /* Before adding any more free calls here, be sure the data is NOT chunk * 01064 * allocated, as ALL the chunk allocated data is already free! */ 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 }
void load_net_rr_terminals | ( | t_ivec *** | rr_node_indices | ) |
Definition at line 1113 of file rr_graph.c.
01114 { 01115 01116 /* Allocates and loads the net_rr_terminals data structure. For each net * 01117 * it stores the rr_node index of the SOURCE of the net and all the SINKs * 01118 * of the net. [0..num_nets-1][0..num_pins-1]. Entry [inet][pnum] stores * 01119 * the rr index corresponding to the SOURCE (opin) or SINK (ipin) of pnum. */ 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 /* In the routing graph, each (x, y) location has unique pins on it 01135 * so when there is capacity, blocks are packed and their pin numbers 01136 * are offset to get their actual rr_node */ 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), /* First pin is driver */ 01142 iclass, rr_node_indices); 01143 net_rr_terminals[inet][ipin] = inode; 01144 } 01145 } 01146 }
void print_rr_indexed_data | ( | FILE * | fp, | |
int | index | |||
) |
Definition at line 2354 of file rr_graph.c.
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 }