VPR-6.0
|
00001 #include <stdio.h> 00002 #include <math.h> 00003 #include <string.h> 00004 #include "util.h" 00005 #include "vpr_types.h" 00006 #include "globals.h" 00007 #include "route_common.h" 00008 #include "place_and_route.h" 00009 #include "route_tree_timing.h" 00010 #include "route_timing.h" 00011 #include "timing_place_lookup.h" 00012 #include "rr_graph.h" 00013 #include "mst.h" 00014 #include "route_export.h" 00015 #include <assert.h> 00016 #include "read_xml_arch_file.h" 00017 00018 /* 00019 * @file 00020 * 00021 * this file contains routines that generate the array containing 00022 * the delays between blocks, this is used in the timing driven 00023 * placement routines. 00024 * 00025 * To compute delay between blocks we place temporary blocks at 00026 * different locations in the FPGA and route nets between 00027 * the blocks. From this procedure we generate a lookup table 00028 * which tells us the delay between different locations in 00029 * the FPGA 00030 * 00031 * Note: these routines assume that there is a uniform and even 00032 * distribution of the different wire segments. If this is not 00033 * the case, then this lookup table will be off 00034 * 00035 * Note: This code removes all heterogeneous types and creates an 00036 * artificial 1x1 tile. A good lookup for heterogeniety requires 00037 * more research 00038 */ 00039 00040 #define NET_COUNT 1 /**< we only use one net in these routines, 00041 it is repeatedly routed and ripped up 00042 to compute delays between different 00043 locations, this value should not change */ 00044 #define NET_USED 0 /**< we use net at location zero of the net structure */ 00045 #define NET_USED_SOURCE_BLOCK 0 /**< net.block[0] is source block */ 00046 #define NET_USED_SINK_BLOCK 1 /**< net.block[1] is sink block */ 00047 #define SOURCE_BLOCK 0 /**< block[0] is source */ 00048 #define SINK_BLOCK 1 /**< block[1] is sink */ 00049 00050 #define BLOCK_COUNT 2 /**< use 2 blocks to compute delay between 00051 * the various FPGA locations 00052 * do not change this number unless you 00053 * really know what you are doing, it is 00054 * assumed that the net only connects to 00055 * two blocks */ 00056 00057 #define NUM_TYPES_USED 3 /**< number of types used in look up */ 00058 00059 #define DEBUG_TIMING_PLACE_LOOKUP /**< initialize arrays to known state */ 00060 00061 #define DUMPFILE "lookup_dump.echo" 00062 /* #define PRINT_ARRAYS *//**<only used during debugging, calls routine to 00063 * print out the various lookup arrays */ 00064 00065 /***variables that are exported to other modules***/ 00066 00067 /**@{*/ 00068 /** the delta arrays are used to contain the best case routing delay 00069 * between different locations on the FPGA. 00070 */ 00071 float **delta_io_to_clb; 00072 float **delta_clb_to_clb; 00073 float **delta_clb_to_io; 00074 float **delta_io_to_io; 00075 /**@}*/ 00076 00077 /*** Other Global Arrays ******/ 00078 /* I could have allocated these as local variables, and passed them all */ 00079 /* around, but was too lazy, since this is a small file, it should not */ 00080 /* be a big problem */ 00081 00082 static float **net_delay; 00083 static float **net_slack; 00084 static float *pin_criticality; 00085 static int *sink_order; 00086 static t_rt_node **rt_node_of_sink; 00087 static t_type_ptr IO_TYPE_BACKUP; 00088 static t_type_ptr EMPTY_TYPE_BACKUP; 00089 static t_type_ptr FILL_TYPE_BACKUP; 00090 static t_type_descriptor dummy_type_descriptors[NUM_TYPES_USED]; 00091 static t_type_descriptor *type_descriptors_backup; 00092 static struct s_grid_tile **grid_backup; 00093 static int num_types_backup; 00094 00095 static t_ivec **clb_opins_used_locally; 00096 00097 #ifdef PRINT_ARRAYS 00098 static FILE *lookup_dump; /**< If debugging mode is on, print out to 00099 * the file defined in DUMPFILE */ 00100 #endif /* PRINT_ARRAYS */ 00101 00102 /*** Function Prototypes *****/ 00103 00104 static void alloc_net(void); 00105 00106 static void alloc_block(void); 00107 00108 static void load_simplified_device(void); 00109 static void restore_original_device(void); 00110 00111 static void alloc_and_assign_internal_structures(struct s_net **original_net, 00112 struct s_block 00113 **original_block, 00114 int *original_num_nets, 00115 int *original_num_blocks); 00116 00117 static void free_and_reset_internal_structures(struct s_net *original_net, 00118 struct s_block *original_block, 00119 int original_num_nets, 00120 int original_num_blocks); 00121 00122 static void setup_chan_width(struct s_router_opts router_opts, 00123 t_chan_width_dist chan_width_dist); 00124 00125 static void alloc_routing_structs(struct s_router_opts router_opts, 00126 struct s_det_routing_arch det_routing_arch, 00127 t_segment_inf * segment_inf, 00128 t_timing_inf timing_inf); 00129 00130 static void free_routing_structs(struct s_router_opts router_opts, 00131 struct s_det_routing_arch det_routing_arch, 00132 t_segment_inf * segment_inf, 00133 t_timing_inf timing_inf); 00134 00135 static void assign_locations(t_type_ptr source_type, 00136 int source_x_loc, 00137 int source_y_loc, 00138 int source_z_loc, 00139 t_type_ptr sink_type, 00140 int sink_x_loc, 00141 int sink_y_loc, 00142 int sink_z_loc); 00143 00144 static float assign_blocks_and_route_net(t_type_ptr source_type, 00145 int source_x_loc, 00146 int source_y_loc, 00147 t_type_ptr sink_type, 00148 int sink_x_loc, 00149 int sink_y_loc, 00150 struct s_router_opts router_opts, 00151 struct s_det_routing_arch 00152 det_routing_arch, 00153 t_segment_inf * segment_inf, 00154 t_timing_inf timing_inf); 00155 00156 static void alloc_delta_arrays(void); 00157 00158 static void free_delta_arrays(void); 00159 00160 static void generic_compute_matrix(float ***matrix_ptr, 00161 t_type_ptr source_type, 00162 t_type_ptr sink_type, 00163 int source_x, 00164 int source_y, 00165 int start_x, 00166 int end_x, 00167 int start_y, 00168 int end_y, 00169 struct s_router_opts router_opts, 00170 struct s_det_routing_arch det_routing_arch, 00171 t_segment_inf * segment_inf, 00172 t_timing_inf timing_inf); 00173 00174 static void compute_delta_clb_to_clb(struct s_router_opts router_opts, 00175 struct s_det_routing_arch det_routing_arch, 00176 t_segment_inf * segment_inf, 00177 t_timing_inf timing_inf, 00178 int longest_length); 00179 00180 static void compute_delta_io_to_clb(struct s_router_opts router_opts, 00181 struct s_det_routing_arch det_routing_arch, 00182 t_segment_inf * segment_inf, 00183 t_timing_inf timing_inf); 00184 00185 static void compute_delta_clb_to_io(struct s_router_opts router_opts, 00186 struct s_det_routing_arch det_routing_arch, 00187 t_segment_inf * segment_inf, 00188 t_timing_inf timing_inf); 00189 00190 static void compute_delta_io_to_io(struct s_router_opts router_opts, 00191 struct s_det_routing_arch det_routing_arch, 00192 t_segment_inf * segment_inf, 00193 t_timing_inf timing_inf); 00194 00195 static void compute_delta_arrays(struct s_router_opts router_opts, 00196 struct s_det_routing_arch det_routing_arch, 00197 t_segment_inf * segment_inf, 00198 t_timing_inf timing_inf, 00199 int longest_length); 00200 00201 static int get_first_pin(enum e_pin_type pintype, 00202 t_type_ptr type); 00203 00204 static int get_longest_segment_length(struct s_det_routing_arch 00205 det_routing_arch, 00206 t_segment_inf * segment_inf); 00207 static void reset_placement(void); 00208 00209 #ifdef PRINT_ARRAYS 00210 static void print_array(float **array_to_print, 00211 int x1, 00212 int x2, 00213 int y1, 00214 int y2); 00215 #endif 00216 /**************************************/ 00217 /** this code assumes logical equivilance between all driving pins 00218 * global pins are not hooked up to the temporary net 00219 */ 00220 static int 00221 get_first_pin(enum e_pin_type pintype, 00222 t_type_ptr type) 00223 { 00224 00225 int i, currpin; 00226 00227 currpin = 0; 00228 for(i = 0; i < type->num_class; i++) 00229 { 00230 if(type->class_inf[i].type == pintype 00231 && !type->is_global_pin[currpin]) 00232 return (type->class_inf[i].pinlist[0]); 00233 else 00234 currpin += type->class_inf[i].num_pins; 00235 } 00236 assert(0); 00237 exit(0); /*should never hit this line */ 00238 } 00239 00240 /**************************************/ 00241 static int 00242 get_longest_segment_length(struct s_det_routing_arch det_routing_arch, 00243 t_segment_inf * segment_inf) 00244 { 00245 00246 int i, length; 00247 00248 length = 0; 00249 for(i = 0; i < det_routing_arch.num_segment; i++) 00250 { 00251 if(segment_inf[i].length > length) 00252 length = segment_inf[i].length; 00253 } 00254 return (length); 00255 } 00256 00257 /**************************************/ 00258 static void 00259 alloc_net(void) 00260 { 00261 00262 int i, len; 00263 00264 clb_net = (struct s_net *)my_malloc(num_nets * sizeof(struct s_net)); 00265 for(i = 0; i < NET_COUNT; i++) 00266 { 00267 /* FIXME: We *really* shouldn't be allocating write-once copies */ 00268 len = strlen("TEMP_NET"); 00269 clb_net[i].name = (char *)my_malloc((len + 1) * sizeof(char)); 00270 clb_net[i].is_global = FALSE; 00271 strcpy(clb_net[NET_USED].name, "TEMP_NET"); 00272 00273 clb_net[i].num_sinks = (BLOCK_COUNT - 1); 00274 clb_net[i].node_block = (int *)my_malloc(BLOCK_COUNT * sizeof(int)); 00275 clb_net[i].node_block[NET_USED_SOURCE_BLOCK] = NET_USED_SOURCE_BLOCK; /*driving block */ 00276 clb_net[i].node_block[NET_USED_SINK_BLOCK] = NET_USED_SINK_BLOCK; /*target block */ 00277 00278 clb_net[i].node_block_pin = 00279 (int *)my_malloc(BLOCK_COUNT * sizeof(int)); 00280 /*the values for this are allocated in assign_blocks_and_route_net */ 00281 00282 } 00283 } 00284 00285 /**************************************/ 00286 /** allocates block structure, and assigns values to known parameters 00287 * type and x,y fields are left undefined at this stage since they 00288 * are not known until we start moving blocks through the clb array 00289 */ 00290 static void 00291 alloc_block(void) 00292 { 00293 00294 int ix_b, ix_p, len, i; 00295 int max_pins; 00296 00297 max_pins = 0; 00298 for(i = 0; i < NUM_TYPES_USED; i++) 00299 { 00300 max_pins = max(max_pins, type_descriptors[i].num_pins); 00301 } 00302 00303 block = (struct s_block *)my_malloc(num_blocks * sizeof(struct s_block)); 00304 00305 for(ix_b = 0; ix_b < BLOCK_COUNT; ix_b++) 00306 { 00307 len = strlen("TEMP_BLOCK"); 00308 block[ix_b].name = (char *)my_malloc((len + 1) * sizeof(char)); 00309 strcpy(block[ix_b].name, "TEMP_BLOCK"); 00310 00311 block[ix_b].nets = (int *)my_malloc(max_pins * sizeof(int)); 00312 block[ix_b].nets[0] = 0; 00313 for(ix_p = 1; ix_p < max_pins; ix_p++) 00314 block[ix_b].nets[ix_p] = OPEN; 00315 } 00316 } 00317 00318 /**************************************/ 00319 static void 00320 load_simplified_device(void) 00321 { 00322 int i, j; 00323 00324 /* Backup original globals */ 00325 EMPTY_TYPE_BACKUP = EMPTY_TYPE; 00326 IO_TYPE_BACKUP = IO_TYPE; 00327 FILL_TYPE_BACKUP = FILL_TYPE; 00328 type_descriptors_backup = type_descriptors; 00329 num_types_backup = num_types; 00330 num_types = NUM_TYPES_USED; 00331 00332 /* Fill in homogeneous core type info */ 00333 dummy_type_descriptors[0] = *EMPTY_TYPE; 00334 dummy_type_descriptors[0].index = 0; 00335 dummy_type_descriptors[1] = *IO_TYPE; 00336 dummy_type_descriptors[1].index = 1; 00337 dummy_type_descriptors[2] = *FILL_TYPE; 00338 dummy_type_descriptors[2].index = 2; 00339 type_descriptors = dummy_type_descriptors; 00340 EMPTY_TYPE = &dummy_type_descriptors[0]; 00341 IO_TYPE = &dummy_type_descriptors[1]; 00342 FILL_TYPE = &dummy_type_descriptors[2]; 00343 00344 /* Fill in homogeneous core grid info */ 00345 grid_backup = grid; 00346 grid = 00347 (struct s_grid_tile **)alloc_matrix(0, nx + 1, 0, ny + 1, 00348 sizeof(struct s_grid_tile)); 00349 for(i = 0; i < nx + 2; i++) 00350 { 00351 for(j = 0; j < ny + 2; j++) 00352 { 00353 if((i == 0 && j == 0) || 00354 (i == nx + 1 && j == 0) || 00355 (i == 0 && j == ny + 1) || (i == nx + 1 00356 && j == ny + 1)) 00357 { 00358 grid[i][j].type = EMPTY_TYPE; 00359 } 00360 else if(i == 0 || i == nx + 1 || j == 0 || j == ny + 1) 00361 { 00362 grid[i][j].type = IO_TYPE; 00363 } 00364 else 00365 { 00366 grid[i][j].type = FILL_TYPE; 00367 } 00368 grid[i][j].blocks = 00369 my_malloc(grid[i][j].type->capacity * sizeof(int)); 00370 grid[i][j].offset = 0; 00371 } 00372 } 00373 } 00374 static void 00375 restore_original_device(void) 00376 { 00377 int i, j; 00378 00379 /* restore previous globals */ 00380 IO_TYPE = IO_TYPE_BACKUP; 00381 EMPTY_TYPE = EMPTY_TYPE_BACKUP; 00382 FILL_TYPE = FILL_TYPE_BACKUP; 00383 type_descriptors = type_descriptors_backup; 00384 num_types = num_types_backup; 00385 00386 /* free allocatd data */ 00387 for(i = 0; i < nx + 2; i++) 00388 { 00389 for(j = 0; j < ny + 2; j++) 00390 { 00391 free(grid[i][j].blocks); 00392 } 00393 } 00394 free_matrix(grid, 0, nx + 1, 0, sizeof(struct s_grid_tile)); 00395 grid = grid_backup; 00396 } 00397 00398 /**************************************/ 00399 static void 00400 reset_placement(void) 00401 { 00402 int i, j, k; 00403 00404 for(i = 0; i <= nx + 1; i++) 00405 { 00406 for(j = 0; j <= ny + 1; j++) 00407 { 00408 grid[i][j].usage = 0; 00409 for(k = 0; k < grid[i][j].type->capacity; k++) 00410 { 00411 grid[i][j].blocks[k] = EMPTY; 00412 } 00413 } 00414 } 00415 } 00416 00417 /**************************************/ 00418 /** allocate new data structures to hold net, and block info */ 00419 static void 00420 alloc_and_assign_internal_structures(struct s_net **original_net, 00421 struct s_block **original_block, 00422 int *original_num_nets, 00423 int *original_num_blocks) 00424 { 00425 00426 *original_net = clb_net; 00427 *original_num_nets = num_nets; 00428 num_nets = NET_COUNT; 00429 alloc_net(); 00430 00431 *original_block = block; 00432 *original_num_blocks = num_blocks; 00433 num_blocks = BLOCK_COUNT; 00434 alloc_block(); 00435 00436 00437 /* [0..num_nets-1][1..num_pins-1] */ 00438 net_delay = 00439 (float **)alloc_matrix(0, NET_COUNT - 1, 1, BLOCK_COUNT - 1, 00440 sizeof(float)); 00441 net_slack = 00442 (float **)alloc_matrix(0, NET_COUNT - 1, 1, BLOCK_COUNT - 1, 00443 sizeof(float)); 00444 00445 reset_placement(); 00446 } 00447 00448 /**************************************/ 00449 /** reset gloabal data structures to the state that they were in before these 00450 * lookup computation routines were called 00451 */ 00452 static void 00453 free_and_reset_internal_structures(struct s_net *original_net, 00454 struct s_block *original_block, 00455 int original_num_nets, 00456 int original_num_blocks) 00457 { 00458 int i; 00459 00460 00461 /*there should be only one net to free, but this is safer */ 00462 for(i = 0; i < NET_COUNT; i++) 00463 { 00464 free(clb_net[i].name); 00465 free(clb_net[i].node_block); 00466 free(clb_net[i].node_block_pin); 00467 } 00468 free(clb_net); 00469 clb_net = original_net; 00470 00471 for(i = 0; i < BLOCK_COUNT; i++) 00472 { 00473 free(block[i].name); 00474 free(block[i].nets); 00475 } 00476 free(block); 00477 block = original_block; 00478 00479 num_nets = original_num_nets; 00480 num_blocks = original_num_blocks; 00481 00482 free_matrix(net_delay, 0, NET_COUNT - 1, 1, sizeof(float)); 00483 free_matrix(net_slack, 0, NET_COUNT - 1, 1, sizeof(float)); 00484 00485 } 00486 00487 /**************************************/ 00488 /** we give plenty of tracks, this increases routability for the 00489 * lookup table generation */ 00490 static void 00491 setup_chan_width(struct s_router_opts router_opts, 00492 t_chan_width_dist chan_width_dist) 00493 { 00494 int width_fac, i, max_pins_per_clb; 00495 00496 max_pins_per_clb = 0; 00497 for(i = 0; i < num_types; i++) 00498 { 00499 max_pins_per_clb = 00500 max(max_pins_per_clb, type_descriptors[i].num_pins); 00501 } 00502 00503 if(router_opts.fixed_channel_width == NO_FIXED_CHANNEL_WIDTH) 00504 width_fac = 4 * max_pins_per_clb; /*this is 2x the value that binary search starts */ 00505 /*this should be enough to allow most pins to */ 00506 /*connect to tracks in the architecture */ 00507 else 00508 width_fac = router_opts.fixed_channel_width; 00509 00510 init_chan(width_fac, chan_width_dist); 00511 } 00512 00513 /**************************************/ 00514 /** calls routines that set up routing resource graph and associated structures */ 00515 static void 00516 alloc_routing_structs(struct s_router_opts router_opts, 00517 struct s_det_routing_arch det_routing_arch, 00518 t_segment_inf * segment_inf, 00519 t_timing_inf timing_inf) 00520 { 00521 00522 int bb_factor; 00523 int warnings; 00524 t_graph_type graph_type; 00525 00526 /*must set up dummy blocks for the first pass through to setup locally used opins */ 00527 /* Only one block per tile */ 00528 assign_locations(FILL_TYPE, 1, 1, 0, FILL_TYPE, nx, ny, 0); 00529 00530 clb_opins_used_locally = alloc_route_structs(); 00531 00532 free_rr_graph(); 00533 00534 if(router_opts.route_type == GLOBAL) { 00535 graph_type = GRAPH_GLOBAL; 00536 } else { 00537 graph_type = (det_routing_arch.directionality == 00538 BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); 00539 } 00540 00541 build_rr_graph(graph_type, num_types, dummy_type_descriptors, nx, 00542 ny, grid, chan_width_x[0], NULL, 00543 det_routing_arch.switch_block_type, 00544 det_routing_arch.Fs, det_routing_arch.num_segment, det_routing_arch.num_switch, 00545 segment_inf, det_routing_arch.global_route_switch, 00546 det_routing_arch.delayless_switch, timing_inf, 00547 det_routing_arch.wire_to_ipin_switch, 00548 router_opts.base_cost_type, &warnings); 00549 00550 alloc_and_load_rr_node_route_structs(); 00551 00552 alloc_timing_driven_route_structs(&pin_criticality, &sink_order, 00553 &rt_node_of_sink); 00554 00555 00556 bb_factor = nx + ny; /*set it to a huge value */ 00557 init_route_structs(bb_factor); 00558 } 00559 00560 /**************************************/ 00561 static void 00562 free_routing_structs(struct s_router_opts router_opts, 00563 struct s_det_routing_arch det_routing_arch, 00564 t_segment_inf * segment_inf, 00565 t_timing_inf timing_inf) 00566 { 00567 free_rr_graph(); 00568 00569 free_rr_node_route_structs(); 00570 free_route_structs(clb_opins_used_locally); 00571 free_trace_structs(); 00572 00573 free_timing_driven_route_structs(pin_criticality, sink_order, 00574 rt_node_of_sink); 00575 } 00576 00577 /**************************************/ 00578 static void 00579 assign_locations(t_type_ptr source_type, 00580 int source_x_loc, 00581 int source_y_loc, 00582 int source_z_loc, 00583 t_type_ptr sink_type, 00584 int sink_x_loc, 00585 int sink_y_loc, 00586 int sink_z_loc) 00587 { 00588 /*all routing occurs between block 0 (source) and block 1 (sink) */ 00589 block[SOURCE_BLOCK].type = source_type; 00590 block[SOURCE_BLOCK].x = source_x_loc; 00591 block[SOURCE_BLOCK].y = source_y_loc; 00592 block[SOURCE_BLOCK].z = source_z_loc; 00593 00594 block[SINK_BLOCK].type = sink_type; 00595 block[SINK_BLOCK].x = sink_x_loc; 00596 block[SINK_BLOCK].y = sink_y_loc; 00597 block[SINK_BLOCK].z = sink_z_loc; 00598 00599 grid[source_x_loc][source_y_loc].blocks[source_z_loc] = SOURCE_BLOCK; 00600 grid[sink_x_loc][sink_y_loc].blocks[sink_z_loc] = SINK_BLOCK; 00601 00602 clb_net[NET_USED].node_block_pin[NET_USED_SOURCE_BLOCK] = 00603 get_first_pin(DRIVER, block[SOURCE_BLOCK].type); 00604 clb_net[NET_USED].node_block_pin[NET_USED_SINK_BLOCK] = 00605 get_first_pin(RECEIVER, block[SINK_BLOCK].type); 00606 00607 grid[source_x_loc][source_y_loc].usage += 1; 00608 grid[sink_x_loc][sink_y_loc].usage += 1; 00609 00610 } 00611 00612 /**************************************/ 00613 /** places blocks at the specified locations, and routes a net between them 00614 * @returns the delay of this net 00615 */ 00616 static float 00617 assign_blocks_and_route_net(t_type_ptr source_type, 00618 int source_x_loc, 00619 int source_y_loc, 00620 t_type_ptr sink_type, 00621 int sink_x_loc, 00622 int sink_y_loc, 00623 struct s_router_opts router_opts, 00624 struct s_det_routing_arch det_routing_arch, 00625 t_segment_inf * segment_inf, 00626 t_timing_inf timing_inf) 00627 { 00628 boolean is_routeable; 00629 int ipin; 00630 float pres_fac, T_crit; 00631 float net_delay_value; 00632 00633 int source_z_loc, sink_z_loc; 00634 00635 /* Only one block per tile */ 00636 source_z_loc = 0; 00637 sink_z_loc = 0; 00638 00639 net_delay_value = IMPOSSIBLE; /*set to known value for debug purposes */ 00640 00641 assign_locations(source_type, source_x_loc, source_y_loc, source_z_loc, 00642 sink_type, sink_x_loc, sink_y_loc, sink_z_loc); 00643 00644 load_net_rr_terminals(rr_node_indices); 00645 00646 T_crit = 1; 00647 pres_fac = 0; /* ignore congestion */ 00648 00649 for(ipin = 1; ipin <= clb_net[NET_USED].num_sinks; ipin++) 00650 net_slack[NET_USED][ipin] = 0; 00651 00652 is_routeable = timing_driven_route_net(NET_USED, pres_fac, 00653 router_opts.max_criticality, 00654 router_opts.criticality_exp, 00655 router_opts.astar_fac, 00656 router_opts.bend_cost, 00657 net_slack[NET_USED], 00658 pin_criticality, sink_order, 00659 rt_node_of_sink, T_crit, 00660 net_delay[NET_USED]); 00661 00662 net_delay_value = net_delay[NET_USED][NET_USED_SINK_BLOCK]; 00663 00664 grid[source_x_loc][source_y_loc].usage = 0; 00665 grid[source_x_loc][source_y_loc].blocks[source_z_loc] = EMPTY; 00666 grid[sink_x_loc][sink_y_loc].usage = 0; 00667 grid[sink_x_loc][sink_y_loc].blocks[sink_z_loc] = EMPTY; 00668 00669 return (net_delay_value); 00670 } 00671 00672 /**************************************/ 00673 static void 00674 alloc_delta_arrays(void) 00675 { 00676 int id_x, id_y; 00677 00678 delta_clb_to_clb = 00679 (float **)alloc_matrix(0, nx - 1, 0, ny - 1, sizeof(float)); 00680 delta_io_to_clb = (float **)alloc_matrix(0, nx, 0, ny, sizeof(float)); 00681 delta_clb_to_io = (float **)alloc_matrix(0, nx, 0, ny, sizeof(float)); 00682 delta_io_to_io = 00683 (float **)alloc_matrix(0, nx + 1, 0, ny + 1, sizeof(float)); 00684 00685 00686 /*initialize all of the array locations to -1 */ 00687 00688 for(id_x = 0; id_x <= nx; id_x++) 00689 { 00690 for(id_y = 0; id_y <= ny; id_y++) 00691 { 00692 delta_io_to_clb[id_x][id_y] = IMPOSSIBLE; 00693 } 00694 } 00695 for(id_x = 0; id_x <= nx - 1; id_x++) 00696 { 00697 for(id_y = 0; id_y <= ny - 1; id_y++) 00698 { 00699 delta_clb_to_clb[id_x][id_y] = IMPOSSIBLE; 00700 } 00701 } 00702 for(id_x = 0; id_x <= nx; id_x++) 00703 { 00704 for(id_y = 0; id_y <= ny; id_y++) 00705 { 00706 delta_clb_to_io[id_x][id_y] = IMPOSSIBLE; 00707 } 00708 } 00709 for(id_x = 0; id_x <= nx + 1; id_x++) 00710 { 00711 for(id_y = 0; id_y <= ny + 1; id_y++) 00712 { 00713 delta_io_to_io[id_x][id_y] = IMPOSSIBLE; 00714 } 00715 } 00716 } 00717 00718 /**************************************/ 00719 static void 00720 free_delta_arrays(void) 00721 { 00722 00723 free_matrix(delta_io_to_clb, 0, nx, 0, sizeof(float)); 00724 free_matrix(delta_clb_to_clb, 0, nx - 1, 0, sizeof(float)); 00725 free_matrix(delta_clb_to_io, 0, nx, 0, sizeof(float)); 00726 free_matrix(delta_io_to_io, 0, nx + 1, 0, sizeof(float)); 00727 00728 } 00729 00730 /**************************************/ 00731 static void 00732 generic_compute_matrix(float ***matrix_ptr, 00733 t_type_ptr source_type, 00734 t_type_ptr sink_type, 00735 int source_x, 00736 int source_y, 00737 int start_x, 00738 int end_x, 00739 int start_y, 00740 int end_y, 00741 struct s_router_opts router_opts, 00742 struct s_det_routing_arch det_routing_arch, 00743 t_segment_inf * segment_inf, 00744 t_timing_inf timing_inf) 00745 { 00746 00747 int delta_x, delta_y; 00748 int sink_x, sink_y; 00749 00750 for(sink_x = start_x; sink_x <= end_x; sink_x++) 00751 { 00752 for(sink_y = start_y; sink_y <= end_y; sink_y++) 00753 { 00754 delta_x = abs(sink_x - source_x); 00755 delta_y = abs(sink_y - source_y); 00756 00757 if(delta_x == 0 && delta_y == 0) 00758 continue; /*do not compute distance from a block to itself */ 00759 /*if a value is desired, pre-assign it somewhere else */ 00760 00761 (*matrix_ptr)[delta_x][delta_y] = 00762 assign_blocks_and_route_net(source_type, source_x, 00763 source_y, sink_type, 00764 sink_x, sink_y, 00765 router_opts, 00766 det_routing_arch, 00767 segment_inf, timing_inf); 00768 } 00769 } 00770 } 00771 00772 /**************************************/ 00773 /** this routine must compute delay values in a slightly different way than the 00774 * other compute routines. We cannot use a location close to the edge as the 00775 * source location for the majority of the delay computations because this 00776 * would give gradually increasing delay values. To avoid this from happening 00777 * a clb that is at least longest_length away from an edge should be chosen 00778 * as a source , if longest_length is more than 0.5 of the total size then 00779 * choose a CLB at the center as the source CLB 00780 */ 00781 static void 00782 compute_delta_clb_to_clb(struct s_router_opts router_opts, 00783 struct s_det_routing_arch det_routing_arch, 00784 t_segment_inf * segment_inf, 00785 t_timing_inf timing_inf, 00786 int longest_length) 00787 { 00788 00789 int source_x, source_y, sink_x, sink_y; 00790 int start_x, start_y, end_x, end_y; 00791 int delta_x, delta_y; 00792 t_type_ptr source_type, sink_type; 00793 00794 source_type = FILL_TYPE; 00795 sink_type = FILL_TYPE; 00796 00797 if(longest_length < 0.5 * (nx)) 00798 { 00799 start_x = longest_length; 00800 } 00801 else 00802 { 00803 start_x = (int)(0.5 * nx); 00804 } 00805 end_x = nx; 00806 source_x = start_x; 00807 00808 if(longest_length < 0.5 * (ny)) 00809 { 00810 start_y = longest_length; 00811 } 00812 else 00813 { 00814 start_y = (int)(0.5 * ny); 00815 } 00816 end_y = ny; 00817 source_y = start_y; 00818 00819 00820 /*don't put the sink all the way to the corner, until it is necessary */ 00821 for(sink_x = start_x; sink_x <= end_x - 1; sink_x++) 00822 { 00823 for(sink_y = start_y; sink_y <= end_y - 1; sink_y++) 00824 { 00825 delta_x = abs(sink_x - source_x); 00826 delta_y = abs(sink_y - source_y); 00827 00828 if(delta_x == 0 && delta_y == 0) 00829 { 00830 delta_clb_to_clb[delta_x][delta_y] = 0.0; 00831 continue; 00832 } 00833 delta_clb_to_clb[delta_x][delta_y] = 00834 assign_blocks_and_route_net(source_type, source_x, 00835 source_y, sink_type, 00836 sink_x, sink_y, 00837 router_opts, 00838 det_routing_arch, 00839 segment_inf, timing_inf); 00840 } 00841 00842 } 00843 00844 00845 sink_x = end_x - 1; 00846 sink_y = end_y - 1; 00847 00848 for(source_x = start_x - 1; source_x >= 1; source_x--) 00849 { 00850 for(source_y = start_y; source_y <= end_y - 1; source_y++) 00851 { 00852 delta_x = abs(sink_x - source_x); 00853 delta_y = abs(sink_y - source_y); 00854 00855 delta_clb_to_clb[delta_x][delta_y] = 00856 assign_blocks_and_route_net(source_type, source_x, 00857 source_y, sink_type, 00858 sink_x, sink_y, 00859 router_opts, 00860 det_routing_arch, 00861 segment_inf, timing_inf); 00862 } 00863 } 00864 00865 for(source_x = 1; source_x <= end_x - 1; source_x++) 00866 { 00867 for(source_y = 1; source_y < start_y; source_y++) 00868 { 00869 delta_x = abs(sink_x - source_x); 00870 delta_y = abs(sink_y - source_y); 00871 00872 delta_clb_to_clb[delta_x][delta_y] = 00873 assign_blocks_and_route_net(source_type, source_x, 00874 source_y, sink_type, 00875 sink_x, sink_y, 00876 router_opts, 00877 det_routing_arch, 00878 segment_inf, timing_inf); 00879 } 00880 } 00881 00882 00883 /*now move sink into the top right corner */ 00884 sink_x = end_x; 00885 sink_y = end_y; 00886 source_x = 1; 00887 for(source_y = 1; source_y <= end_y; source_y++) 00888 { 00889 delta_x = abs(sink_x - source_x); 00890 delta_y = abs(sink_y - source_y); 00891 00892 delta_clb_to_clb[delta_x][delta_y] = 00893 assign_blocks_and_route_net(source_type, source_x, source_y, 00894 sink_type, sink_x, sink_y, 00895 router_opts, det_routing_arch, 00896 segment_inf, timing_inf); 00897 00898 } 00899 00900 sink_x = end_x; 00901 sink_y = end_y; 00902 source_y = 1; 00903 for(source_x = 1; source_x <= end_x; source_x++) 00904 { 00905 delta_x = abs(sink_x - source_x); 00906 delta_y = abs(sink_y - source_y); 00907 00908 delta_clb_to_clb[delta_x][delta_y] = 00909 assign_blocks_and_route_net(source_type, source_x, source_y, 00910 sink_type, sink_x, sink_y, 00911 router_opts, det_routing_arch, 00912 segment_inf, timing_inf); 00913 } 00914 } 00915 00916 /**************************************/ 00917 static void 00918 compute_delta_io_to_clb(struct s_router_opts router_opts, 00919 struct s_det_routing_arch det_routing_arch, 00920 t_segment_inf * segment_inf, 00921 t_timing_inf timing_inf) 00922 { 00923 int source_x, source_y; 00924 int start_x, start_y, end_x, end_y; 00925 t_type_ptr source_type, sink_type; 00926 00927 source_type = IO_TYPE; 00928 sink_type = FILL_TYPE; 00929 00930 delta_io_to_clb[0][0] = IMPOSSIBLE; 00931 delta_io_to_clb[nx][ny] = IMPOSSIBLE; 00932 00933 source_x = 0; 00934 source_y = 1; 00935 00936 start_x = 1; 00937 end_x = nx; 00938 start_y = 1; 00939 end_y = ny; 00940 generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, 00941 source_x, source_y, start_x, end_x, start_y, 00942 end_y, router_opts, det_routing_arch, 00943 segment_inf, timing_inf); 00944 00945 source_x = 1; 00946 source_y = 0; 00947 00948 start_x = 1; 00949 end_x = 1; 00950 start_y = 1; 00951 end_y = ny; 00952 generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, 00953 source_x, source_y, start_x, end_x, start_y, 00954 end_y, router_opts, det_routing_arch, 00955 segment_inf, timing_inf); 00956 00957 start_x = 1; 00958 end_x = nx; 00959 start_y = ny; 00960 end_y = ny; 00961 generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, 00962 source_x, source_y, start_x, end_x, start_y, 00963 end_y, router_opts, det_routing_arch, 00964 segment_inf, timing_inf); 00965 } 00966 00967 /**************************************/ 00968 static void 00969 compute_delta_clb_to_io(struct s_router_opts router_opts, 00970 struct s_det_routing_arch det_routing_arch, 00971 t_segment_inf * segment_inf, 00972 t_timing_inf timing_inf) 00973 { 00974 int source_x, source_y, sink_x, sink_y; 00975 int delta_x, delta_y; 00976 t_type_ptr source_type, sink_type; 00977 00978 source_type = FILL_TYPE; 00979 sink_type = IO_TYPE; 00980 00981 delta_clb_to_io[0][0] = IMPOSSIBLE; 00982 delta_clb_to_io[nx][ny] = IMPOSSIBLE; 00983 00984 sink_x = 0; 00985 sink_y = 1; 00986 for(source_x = 1; source_x <= nx; source_x++) 00987 { 00988 for(source_y = 1; source_y <= ny; source_y++) 00989 { 00990 delta_x = abs(source_x - sink_x); 00991 delta_y = abs(source_y - sink_y); 00992 00993 delta_clb_to_io[delta_x][delta_y] = 00994 assign_blocks_and_route_net(source_type, source_x, 00995 source_y, sink_type, 00996 sink_x, sink_y, 00997 router_opts, 00998 det_routing_arch, 00999 segment_inf, timing_inf); 01000 } 01001 } 01002 01003 sink_x = 1; 01004 sink_y = 0; 01005 source_x = 1; 01006 delta_x = abs(source_x - sink_x); 01007 for(source_y = 1; source_y <= ny; source_y++) 01008 { 01009 delta_y = abs(source_y - sink_y); 01010 delta_clb_to_io[delta_x][delta_y] = 01011 assign_blocks_and_route_net(source_type, source_x, source_y, 01012 sink_type, sink_x, sink_y, 01013 router_opts, det_routing_arch, 01014 segment_inf, timing_inf); 01015 } 01016 01017 sink_x = 1; 01018 sink_y = 0; 01019 source_y = ny; 01020 delta_y = abs(source_y - sink_y); 01021 for(source_x = 2; source_x <= nx; source_x++) 01022 { 01023 delta_x = abs(source_x - sink_x); 01024 delta_clb_to_io[delta_x][delta_y] = 01025 assign_blocks_and_route_net(source_type, source_x, source_y, 01026 sink_type, sink_x, sink_y, 01027 router_opts, det_routing_arch, 01028 segment_inf, timing_inf); 01029 } 01030 } 01031 01032 /**************************************/ 01033 static void 01034 compute_delta_io_to_io(struct s_router_opts router_opts, 01035 struct s_det_routing_arch det_routing_arch, 01036 t_segment_inf * segment_inf, 01037 t_timing_inf timing_inf) 01038 { 01039 int source_x, source_y, sink_x, sink_y; 01040 int delta_x, delta_y; 01041 t_type_ptr source_type, sink_type; 01042 01043 source_type = IO_TYPE; 01044 sink_type = IO_TYPE; 01045 01046 delta_io_to_io[0][0] = 0; /*delay to itself is 0 (this can happen) */ 01047 delta_io_to_io[nx + 1][ny + 1] = IMPOSSIBLE; 01048 delta_io_to_io[0][ny] = IMPOSSIBLE; 01049 delta_io_to_io[nx][0] = IMPOSSIBLE; 01050 delta_io_to_io[nx][ny + 1] = IMPOSSIBLE; 01051 delta_io_to_io[nx + 1][ny] = IMPOSSIBLE; 01052 01053 01054 source_x = 0; 01055 source_y = 1; 01056 sink_x = 0; 01057 delta_x = abs(sink_x - source_x); 01058 01059 01060 for(sink_y = 2; sink_y <= ny; sink_y++) 01061 { 01062 delta_y = abs(sink_y - source_y); 01063 delta_io_to_io[delta_x][delta_y] = 01064 assign_blocks_and_route_net(source_type, source_x, source_y, 01065 sink_type, sink_x, sink_y, 01066 router_opts, det_routing_arch, 01067 segment_inf, timing_inf); 01068 01069 } 01070 01071 source_x = 0; 01072 source_y = 1; 01073 sink_x = nx + 1; 01074 delta_x = abs(sink_x - source_x); 01075 01076 for(sink_y = 1; sink_y <= ny; sink_y++) 01077 { 01078 delta_y = abs(sink_y - source_y); 01079 delta_io_to_io[delta_x][delta_y] = 01080 assign_blocks_and_route_net(source_type, source_x, source_y, 01081 sink_type, sink_x, sink_y, 01082 router_opts, det_routing_arch, 01083 segment_inf, timing_inf); 01084 01085 } 01086 01087 01088 source_x = 1; 01089 source_y = 0; 01090 sink_y = 0; 01091 delta_y = abs(sink_y - source_y); 01092 01093 for(sink_x = 2; sink_x <= nx; sink_x++) 01094 { 01095 delta_x = abs(sink_x - source_x); 01096 delta_io_to_io[delta_x][delta_y] = 01097 assign_blocks_and_route_net(source_type, source_x, source_y, 01098 sink_type, sink_x, sink_y, 01099 router_opts, det_routing_arch, 01100 segment_inf, timing_inf); 01101 01102 } 01103 01104 source_x = 1; 01105 source_y = 0; 01106 sink_y = ny + 1; 01107 delta_y = abs(sink_y - source_y); 01108 01109 for(sink_x = 1; sink_x <= nx; sink_x++) 01110 { 01111 delta_x = abs(sink_x - source_x); 01112 delta_io_to_io[delta_x][delta_y] = 01113 assign_blocks_and_route_net(source_type, source_x, source_y, 01114 sink_type, sink_x, sink_y, 01115 router_opts, det_routing_arch, 01116 segment_inf, timing_inf); 01117 01118 } 01119 01120 source_x = 0; 01121 sink_y = ny + 1; 01122 for(source_y = 1; source_y <= ny; source_y++) 01123 { 01124 for(sink_x = 1; sink_x <= nx; sink_x++) 01125 { 01126 delta_y = abs(source_y - sink_y); 01127 delta_x = abs(source_x - sink_x); 01128 delta_io_to_io[delta_x][delta_y] = 01129 assign_blocks_and_route_net(source_type, source_x, 01130 source_y, sink_type, 01131 sink_x, sink_y, 01132 router_opts, 01133 det_routing_arch, 01134 segment_inf, timing_inf); 01135 01136 } 01137 } 01138 } 01139 01140 /**************************************/ 01141 #ifdef PRINT_ARRAYS 01142 static void 01143 print_array(float **array_to_print, 01144 int x1, 01145 int x2, 01146 int y1, 01147 int y2) 01148 { 01149 01150 01151 int idx_x, idx_y; 01152 01153 fprintf(lookup_dump, "\nPrinting Array \n\n"); 01154 01155 for(idx_y = y2; idx_y >= y1; idx_y--) 01156 { 01157 for(idx_x = x1; idx_x <= x2; idx_x++) 01158 { 01159 fprintf(lookup_dump, " %9.2e", 01160 array_to_print[idx_x][idx_y]); 01161 } 01162 fprintf(lookup_dump, "\n"); 01163 } 01164 fprintf(lookup_dump, "\n\n"); 01165 } 01166 #endif 01167 /**************************************/ 01168 static void 01169 compute_delta_arrays(struct s_router_opts router_opts, 01170 struct s_det_routing_arch det_routing_arch, 01171 t_segment_inf * segment_inf, 01172 t_timing_inf timing_inf, 01173 int longest_length) 01174 { 01175 01176 printf 01177 ("Computing delta_io_to_io lookup matrix, may take a few seconds, please wait...\n"); 01178 compute_delta_io_to_io(router_opts, det_routing_arch, segment_inf, 01179 timing_inf); 01180 printf 01181 ("Computing delta_io_to_clb lookup matrix, may take a few seconds, please wait...\n"); 01182 compute_delta_io_to_clb(router_opts, det_routing_arch, segment_inf, 01183 timing_inf); 01184 printf 01185 ("Computing delta_clb_to_io lookup matrix, may take a few seconds, please wait...\n"); 01186 compute_delta_clb_to_io(router_opts, det_routing_arch, segment_inf, 01187 timing_inf); 01188 printf 01189 ("Computing delta_clb_to_clb lookup matrix, may take a few seconds, please wait...\n"); 01190 compute_delta_clb_to_clb(router_opts, det_routing_arch, segment_inf, 01191 timing_inf, longest_length); 01192 01193 #ifdef PRINT_ARRAYS 01194 lookup_dump = my_fopen(DUMPFILE, "w", 0); 01195 fprintf(lookup_dump, "\n\nprinting delta_clb_to_clb\n"); 01196 print_array(delta_clb_to_clb, 0, nx - 1, 0, ny - 1); 01197 fprintf(lookup_dump, "\n\nprinting delta_io_to_clb\n"); 01198 print_array(delta_io_to_clb, 0, nx, 0, ny); 01199 fprintf(lookup_dump, "\n\nprinting delta_clb_to_io\n"); 01200 print_array(delta_clb_to_io, 0, nx, 0, ny); 01201 fprintf(lookup_dump, "\n\nprinting delta_io_to_io\n"); 01202 print_array(delta_io_to_io, 0, nx + 1, 0, ny + 1); 01203 fclose(lookup_dump); 01204 #endif 01205 01206 } 01207 01208 /******* Globally Accessable Functions **********/ 01209 01210 /**************************************/ 01211 void 01212 compute_delay_lookup_tables(struct s_router_opts router_opts, 01213 struct s_det_routing_arch det_routing_arch, 01214 t_segment_inf * segment_inf, 01215 t_timing_inf timing_inf, 01216 t_chan_width_dist chan_width_dist) 01217 { 01218 01219 static struct s_net *original_net; /*this will be used as a pointer to remember what */ 01220 01221 /*the "real" nets in the circuit are. This is */ 01222 /*required because we are using the net structure */ 01223 /*in these routines to find delays between blocks */ 01224 static struct s_block *original_block; /*same def as original_nets, but for block */ 01225 01226 static int original_num_nets; 01227 static int original_num_blocks; 01228 static int longest_length; 01229 01230 load_simplified_device(); 01231 01232 alloc_and_assign_internal_structures(&original_net, 01233 &original_block, 01234 &original_num_nets, 01235 &original_num_blocks); 01236 setup_chan_width(router_opts, chan_width_dist); 01237 01238 alloc_routing_structs(router_opts, det_routing_arch, segment_inf, 01239 timing_inf); 01240 01241 longest_length = 01242 get_longest_segment_length(det_routing_arch, segment_inf); 01243 01244 01245 /*now setup and compute the actual arrays */ 01246 alloc_delta_arrays(); 01247 compute_delta_arrays(router_opts, det_routing_arch, segment_inf, 01248 timing_inf, longest_length); 01249 01250 /*free all data structures that are no longer needed */ 01251 free_routing_structs(router_opts, det_routing_arch, segment_inf, 01252 timing_inf); 01253 01254 restore_original_device(); 01255 01256 free_and_reset_internal_structures(original_net, original_block, 01257 original_num_nets, 01258 original_num_blocks); 01259 } 01260 01261 /**************************************/ 01262 void 01263 free_place_lookup_structs(void) 01264 { 01265 01266 free_delta_arrays(); 01267 01268 }