VPR-6.0
|
00001 #include <assert.h> 00002 #include <stdio.h> 00003 #include <sys/types.h> 00004 #include <time.h> 00005 #include "util.h" 00006 #include "vpr_types.h" 00007 #include "vpr_utils.h" 00008 #include "globals.h" 00009 #include "place_and_route.h" 00010 #include "mst.h" 00011 #include "place.h" 00012 #include "read_place.h" 00013 #include "route_export.h" 00014 #include "draw.h" 00015 #include "stats.h" 00016 #include "check_route.h" 00017 #include "rr_graph.h" 00018 #include "path_delay.h" 00019 #include "net_delay.h" 00020 #include "timing_place.h" 00021 #include "read_xml_arch_file.h" 00022 00023 /******************* Subroutines local to this module ************************/ 00024 00025 static int binary_search_place_and_route(struct s_placer_opts placer_opts, 00026 char *place_file, 00027 char *net_file, 00028 char *arch_file, 00029 char *route_file, 00030 boolean full_stats, 00031 boolean verify_binary_search, 00032 struct s_annealing_sched 00033 annealing_sched, 00034 struct s_router_opts router_opts, 00035 struct s_det_routing_arch 00036 det_routing_arch, 00037 t_segment_inf * segment_inf, 00038 t_timing_inf timing_inf, 00039 t_chan_width_dist chan_width_dist, 00040 t_mst_edge ** mst, 00041 t_model *models); 00042 00043 static float comp_width(t_chan * chan, 00044 float x, 00045 float separation); 00046 00047 00048 void post_place_sync(INP int num_blocks, 00049 INOUTP const struct s_block block_list[]); 00050 00051 void free_pb_data(t_pb *pb); 00052 00053 00054 /************************* Subroutine Definitions ****************************/ 00055 00056 /** This routine controls the overall placement and routing of a circuit. */ 00057 void 00058 place_and_route(enum e_operation operation, 00059 struct s_placer_opts placer_opts, 00060 char *place_file, 00061 char *net_file, 00062 char *arch_file, 00063 char *route_file, 00064 struct s_annealing_sched annealing_sched, 00065 struct s_router_opts router_opts, 00066 struct s_det_routing_arch det_routing_arch, 00067 t_segment_inf * segment_inf, 00068 t_timing_inf timing_inf, 00069 t_chan_width_dist chan_width_dist, 00070 struct s_model *models) 00071 { 00072 char msg[BUFSIZE]; 00073 int width_fac, inet, i; 00074 boolean success, Fc_clipped; 00075 float **net_delay, **net_slack; 00076 struct s_linked_vptr *net_delay_chunk_list_head; 00077 t_ivec **clb_opins_used_locally; /* [0..num_blocks-1][0..num_class-1] */ 00078 t_mst_edge **mst = NULL; /* Make sure mst is never undefined */ 00079 int max_pins_per_clb; 00080 clock_t begin, end; 00081 00082 Fc_clipped = FALSE; 00083 00084 max_pins_per_clb = 0; 00085 for(i = 0; i < num_types; i++) 00086 { 00087 if(type_descriptors[i].num_pins > max_pins_per_clb) 00088 { 00089 max_pins_per_clb = type_descriptors[i].num_pins; 00090 } 00091 } 00092 00093 if(placer_opts.place_freq == PLACE_NEVER) 00094 { 00095 /* Read the placement from a file */ 00096 read_place(place_file, net_file, arch_file, nx, ny, num_blocks, 00097 block); 00098 sync_grid_to_blocks(num_blocks, block, nx, ny, grid); 00099 } 00100 else 00101 { 00102 assert((PLACE_ONCE == placer_opts.place_freq) || 00103 (PLACE_ALWAYS == placer_opts.place_freq)); 00104 begin = clock(); 00105 try_place(placer_opts, annealing_sched, chan_width_dist, 00106 router_opts, det_routing_arch, segment_inf, 00107 timing_inf, &mst); 00108 print_place(place_file, net_file, arch_file); 00109 end = clock(); 00110 #ifdef CLOCKS_PER_SEC 00111 printf("Placement took %g seconds\n", (float)(end - begin) / CLOCKS_PER_SEC); 00112 #else 00113 printf("Placement took %g seconds\n", (float)(end - begin) / CLK_PER_SEC); 00114 #endif 00115 } 00116 begin = clock(); 00117 post_place_sync(num_blocks, block); 00118 00119 00120 fflush(stdout); 00121 00122 /* reset mst */ 00123 if(mst) 00124 { 00125 for(inet = 0; inet < num_nets; inet++) 00126 { 00127 if(mst[inet]) { 00128 free(mst[inet]); 00129 } 00130 } 00131 free(mst); 00132 } 00133 mst = NULL; 00134 00135 if(!router_opts.doRouting) 00136 return; 00137 00138 mst = (t_mst_edge **) my_malloc(sizeof(t_mst_edge *) * num_nets); 00139 for(inet = 0; inet < num_nets; inet++) 00140 { 00141 mst[inet] = get_mst_of_net(inet); 00142 } 00143 00144 width_fac = router_opts.fixed_channel_width; 00145 00146 /* If channel width not fixed, use binary search to find min W */ 00147 if(NO_FIXED_CHANNEL_WIDTH == width_fac) 00148 { 00149 binary_search_place_and_route(placer_opts, place_file, 00150 net_file, arch_file, route_file, 00151 router_opts.full_stats, router_opts.verify_binary_search, 00152 annealing_sched, router_opts, 00153 det_routing_arch, segment_inf, 00154 timing_inf, 00155 chan_width_dist, mst, models); 00156 } 00157 else 00158 { 00159 if(det_routing_arch.directionality == UNI_DIRECTIONAL) 00160 { 00161 if(width_fac % 2 != 0) 00162 { 00163 printf 00164 ("Error: pack_place_and_route.c: given odd chan width (%d) for udsd architecture\n", 00165 width_fac); 00166 exit(1); 00167 } 00168 } 00169 /* Other constraints can be left to rr_graph to check since this is one pass routing */ 00170 00171 00172 /* Allocate the major routing structures. */ 00173 00174 clb_opins_used_locally = alloc_route_structs(); 00175 00176 if(timing_inf.timing_analysis_enabled) 00177 { 00178 net_slack = 00179 alloc_and_load_timing_graph(timing_inf); 00180 net_delay = alloc_net_delay(&net_delay_chunk_list_head, clb_net, num_nets); 00181 } 00182 else 00183 { 00184 net_delay = NULL; /* Defensive coding. */ 00185 net_slack = NULL; 00186 } 00187 00188 success = 00189 try_route(width_fac, router_opts, det_routing_arch, 00190 segment_inf, timing_inf, net_slack, net_delay, 00191 chan_width_dist, clb_opins_used_locally, mst, 00192 &Fc_clipped); 00193 00194 if(Fc_clipped) 00195 { 00196 printf 00197 ("Warning: Fc_output was too high and was clipped to full (maximum) connectivity.\n"); 00198 } 00199 00200 if(success == FALSE) 00201 { 00202 printf 00203 ("Circuit is unrouteable with a channel width factor of %d\n\n", 00204 width_fac); 00205 sprintf(msg, 00206 "Routing failed with a channel width factor of %d. ILLEGAL routing shown.", 00207 width_fac); 00208 } 00209 00210 else 00211 { 00212 check_route(router_opts.route_type, 00213 det_routing_arch.num_switch, 00214 clb_opins_used_locally); 00215 get_serial_num(); 00216 00217 printf 00218 ("Circuit successfully routed with a channel width factor of %d.\n\n", 00219 width_fac); 00220 00221 routing_stats(router_opts.full_stats, router_opts.route_type, 00222 det_routing_arch.num_switch, segment_inf, 00223 det_routing_arch.num_segment, 00224 det_routing_arch.R_minW_nmos, 00225 det_routing_arch.R_minW_pmos, 00226 det_routing_arch.directionality, 00227 timing_inf.timing_analysis_enabled, 00228 net_slack, net_delay); 00229 00230 print_route(route_file); 00231 00232 #ifdef CREATE_ECHO_FILES 00233 /*print_sink_delays("routing_sink_delays.echo"); */ 00234 #endif /* CREATE_ECHO_FILES */ 00235 00236 sprintf(msg, 00237 "Routing succeeded with a channel width factor of %d.\n\n", 00238 width_fac); 00239 } 00240 00241 init_draw_coords(max_pins_per_clb); 00242 update_screen(MAJOR, msg, ROUTING, 00243 timing_inf.timing_analysis_enabled); 00244 00245 if(timing_inf.timing_analysis_enabled) 00246 { 00247 assert(net_slack); 00248 #ifdef CREATE_ECHO_FILES 00249 print_timing_graph_as_blif("post_flow_timing_graph.blif", models); 00250 #endif 00251 00252 free_timing_graph(net_slack); 00253 00254 assert(net_delay); 00255 free_net_delay(net_delay, &net_delay_chunk_list_head); 00256 } 00257 00258 free_route_structs(clb_opins_used_locally); 00259 fflush(stdout); 00260 } 00261 end = clock(); 00262 #ifdef CLOCKS_PER_SEC 00263 printf("Routing took %g seconds\n", (float)(end - begin) / CLOCKS_PER_SEC); 00264 #else 00265 printf("Routing took %g seconds\n", (float)(end - begin) / CLK_PER_SEC); 00266 #endif 00267 00268 /*WMF: cleaning up memory usage */ 00269 if(mst) 00270 { 00271 for(inet = 0; inet < num_nets; inet++) 00272 { 00273 if(!mst[inet]) { 00274 printf("no mst for net %s #%d\n", clb_net[inet].name, inet); 00275 } 00276 assert(mst[inet]); 00277 free(mst[inet]); 00278 } 00279 free(mst); 00280 mst = NULL; 00281 } 00282 } 00283 00284 00285 00286 /** This routine performs a binary search to find the minimum number of 00287 * tracks per channel required to successfully route a circuit, and returns 00288 * that minimum width_fac. 00289 */ 00290 static int 00291 binary_search_place_and_route(struct s_placer_opts placer_opts, 00292 char *place_file, 00293 char *net_file, 00294 char *arch_file, 00295 char *route_file, 00296 boolean full_stats, 00297 boolean verify_binary_search, 00298 struct s_annealing_sched annealing_sched, 00299 struct s_router_opts router_opts, 00300 struct s_det_routing_arch det_routing_arch, 00301 t_segment_inf * segment_inf, 00302 t_timing_inf timing_inf, 00303 t_chan_width_dist chan_width_dist, 00304 t_mst_edge ** mst, 00305 t_model *models) 00306 { 00307 00308 00309 struct s_trace **best_routing; /* Saves the best routing found so far. */ 00310 int current, low, high, final; 00311 int max_pins_per_clb, i; 00312 boolean success, prev_success, prev2_success, Fc_clipped = FALSE; 00313 char msg[BUFSIZE]; 00314 float **net_delay, **net_slack; 00315 struct s_linked_vptr *net_delay_chunk_list_head; 00316 int try_w_limit; 00317 t_ivec **clb_opins_used_locally, **saved_clb_opins_used_locally; 00318 00319 /* [0..num_blocks-1][0..num_class-1] */ 00320 int attempt_count; 00321 int udsd_multiplier; 00322 int warnings; 00323 00324 t_graph_type graph_type; 00325 00326 /* Allocate the major routing structures. */ 00327 00328 if(router_opts.route_type == GLOBAL) { 00329 graph_type = GRAPH_GLOBAL; 00330 } else { 00331 graph_type = (det_routing_arch.directionality == 00332 BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); 00333 } 00334 00335 max_pins_per_clb = 0; 00336 for(i = 0; i < num_types; i++) 00337 { 00338 max_pins_per_clb = 00339 max(max_pins_per_clb, type_descriptors[i].num_pins); 00340 } 00341 00342 clb_opins_used_locally = alloc_route_structs(); 00343 best_routing = alloc_saved_routing(clb_opins_used_locally, 00344 &saved_clb_opins_used_locally); 00345 00346 if(timing_inf.timing_analysis_enabled) 00347 { 00348 net_slack = 00349 alloc_and_load_timing_graph(timing_inf); 00350 net_delay = alloc_net_delay(&net_delay_chunk_list_head, clb_net, num_nets); 00351 } 00352 else 00353 { 00354 net_delay = NULL; /* Defensive coding. */ 00355 net_slack = NULL; 00356 } 00357 00358 /* UDSD by AY Start */ 00359 if(det_routing_arch.directionality == BI_DIRECTIONAL) 00360 udsd_multiplier = 1; 00361 else 00362 udsd_multiplier = 2; 00363 /* UDSD by AY End */ 00364 00365 if(router_opts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH) 00366 { 00367 current = router_opts.fixed_channel_width + 5 * udsd_multiplier; 00368 low = router_opts.fixed_channel_width - 1 * udsd_multiplier; 00369 } 00370 else 00371 { 00372 current = max_pins_per_clb + max_pins_per_clb % 2; /* Binary search part */ 00373 low = -1; 00374 } 00375 00376 /* Constraints must be checked to not break rr_graph generator */ 00377 if(det_routing_arch.directionality == UNI_DIRECTIONAL) 00378 { 00379 if(current % 2 != 0) 00380 { 00381 printf 00382 ("Error: pack_place_and_route.c: tried odd chan width (%d) for udsd architecture\n", 00383 current); 00384 exit(1); 00385 } 00386 } 00387 00388 else 00389 { 00390 if(det_routing_arch.Fs % 3) 00391 { 00392 printf("Fs must be three in bidirectional mode\n"); 00393 exit(1); 00394 } 00395 } 00396 00397 high = -1; 00398 final = -1; 00399 try_w_limit = 0; 00400 00401 attempt_count = 0; 00402 00403 while(final == -1) 00404 { 00405 00406 printf("low, high, current %d %d %d\n", low, high, current); 00407 fflush(stdout); 00408 00409 /* Check if the channel width is huge to avoid overflow. Assume the * 00410 * circuit is unroutable with the current router options if we're * 00411 * going to overflow. */ 00412 if(router_opts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH) 00413 { 00414 if(current > router_opts.fixed_channel_width * 4) 00415 { 00416 printf 00417 ("This circuit appears to be unroutable with the current " 00418 "router options. Last failed at %d\n", low); 00419 printf("Aborting routing procedure.\n"); 00420 exit(1); 00421 } 00422 } 00423 else 00424 { 00425 if(current > 1000) 00426 { 00427 printf 00428 ("This circuit requires a channel width above 1000, probably isn't going to route.\n"); 00429 printf("Aborting routing procedure.\n"); 00430 exit(1); 00431 } 00432 } 00433 00434 if((current * 3) < det_routing_arch.Fs) 00435 { 00436 printf 00437 ("width factor is now below specified Fs. Stop search.\n"); 00438 final = high; 00439 break; 00440 } 00441 00442 if(placer_opts.place_freq == PLACE_ALWAYS) 00443 { 00444 placer_opts.place_chan_width = current; 00445 try_place(placer_opts, annealing_sched, chan_width_dist, 00446 router_opts, det_routing_arch, segment_inf, 00447 timing_inf, &mst); 00448 } 00449 success = 00450 try_route(current, router_opts, det_routing_arch, segment_inf, 00451 timing_inf, net_slack, net_delay, chan_width_dist, 00452 clb_opins_used_locally, mst, &Fc_clipped); 00453 attempt_count++; 00454 fflush(stdout); 00455 #if 1 00456 if(success && (Fc_clipped == FALSE)) 00457 { 00458 #else 00459 if(success 00460 && (Fc_clipped == FALSE 00461 || det_routing_arch.Fc_type == FRACTIONAL)) 00462 { 00463 #endif 00464 if(current == high) { 00465 /* Can't go any lower */ 00466 final = current; 00467 } 00468 high = current; 00469 00470 /* If Fc_output is too high, set to full connectivity but warn the user */ 00471 if(Fc_clipped) 00472 { 00473 printf 00474 ("Warning: Fc_output was too high and was clipped to full (maximum) connectivity.\n"); 00475 } 00476 00477 /* If we're re-placing constantly, save placement in case it is best. */ 00478 #if 0 00479 if(placer_opts.place_freq == PLACE_ALWAYS) 00480 { 00481 print_place(place_file, net_file, arch_file); 00482 } 00483 #endif 00484 00485 /* Save routing in case it is best. */ 00486 save_routing(best_routing, clb_opins_used_locally, 00487 saved_clb_opins_used_locally); 00488 00489 if((high - low) <= 1 * udsd_multiplier) 00490 final = high; 00491 00492 if(low != -1) 00493 { 00494 current = (high + low) / 2; 00495 } 00496 else 00497 { 00498 current = high / 2; /* haven't found lower bound yet */ 00499 } 00500 } 00501 else 00502 { /* last route not successful */ 00503 if(success && Fc_clipped) 00504 { 00505 printf 00506 ("Routing rejected, Fc_output was too high.\n"); 00507 success = FALSE; 00508 } 00509 low = current; 00510 if(high != -1) 00511 { 00512 00513 if((high - low) <= 1 * udsd_multiplier) 00514 final = high; 00515 00516 current = (high + low) / 2; 00517 } 00518 else 00519 { 00520 if(router_opts.fixed_channel_width != 00521 NO_FIXED_CHANNEL_WIDTH) 00522 { 00523 /* FOR Wneed = f(Fs) search */ 00524 if(low < 00525 router_opts.fixed_channel_width + 30) 00526 { 00527 current = 00528 low + 5 * udsd_multiplier; 00529 } 00530 else 00531 { 00532 printf 00533 ("Aborting: Wneed = f(Fs) search found exceedingly large Wneed (at least %d)\n", 00534 low); 00535 exit(1); 00536 } 00537 } 00538 else 00539 { 00540 current = low * 2; /* Haven't found upper bound yet */ 00541 } 00542 } 00543 } 00544 current = current + current % udsd_multiplier; 00545 } 00546 00547 /* The binary search above occassionally does not find the minimum * 00548 * routeable channel width. Sometimes a circuit that will not route * 00549 * in 19 channels will route in 18, due to router flukiness. If * 00550 * verify_binary_search is set, the code below will ensure that FPGAs * 00551 * with channel widths of final-2 and final-3 wil not route * 00552 * successfully. If one does route successfully, the router keeps * 00553 * trying smaller channel widths until two in a row (e.g. 8 and 9) * 00554 * fail. */ 00555 00556 if(verify_binary_search) 00557 { 00558 00559 printf 00560 ("\nVerifying that binary search found min. channel width ...\n"); 00561 00562 prev_success = TRUE; /* Actually final - 1 failed, but this makes router */ 00563 /* try final-2 and final-3 even if both fail: safer */ 00564 prev2_success = TRUE; 00565 00566 current = final - 2; 00567 00568 while(prev2_success || prev_success) 00569 { 00570 if((router_opts.fixed_channel_width != 00571 NO_FIXED_CHANNEL_WIDTH) 00572 && (current < router_opts.fixed_channel_width)) 00573 { 00574 break; 00575 } 00576 fflush(stdout); 00577 if(current < 1) 00578 break; 00579 if(placer_opts.place_freq == PLACE_ALWAYS) 00580 { 00581 placer_opts.place_chan_width = current; 00582 try_place(placer_opts, annealing_sched, 00583 chan_width_dist, router_opts, 00584 det_routing_arch, segment_inf, 00585 timing_inf, &mst); 00586 } 00587 00588 success = 00589 try_route(current, router_opts, det_routing_arch, 00590 segment_inf, timing_inf, net_slack, 00591 net_delay, chan_width_dist, 00592 clb_opins_used_locally, mst, &Fc_clipped); 00593 00594 if(success && Fc_clipped == FALSE) 00595 { 00596 final = current; 00597 save_routing(best_routing, clb_opins_used_locally, 00598 saved_clb_opins_used_locally); 00599 00600 if(placer_opts.place_freq == PLACE_ALWAYS) 00601 { 00602 print_place(place_file, net_file, 00603 arch_file); 00604 } 00605 } 00606 00607 00608 prev2_success = prev_success; 00609 prev_success = success; 00610 current--; 00611 if(det_routing_arch.directionality == UNI_DIRECTIONAL) { 00612 current--; /* width must be even */ 00613 } 00614 } 00615 } 00616 00617 00618 00619 /* End binary search verification. */ 00620 /* Restore the best placement (if necessary), the best routing, and * 00621 * * the best channel widths for final drawing and statistics output. */ 00622 init_chan(final, chan_width_dist); 00623 #if 0 00624 if(placer_opts.place_freq == PLACE_ALWAYS) 00625 { 00626 printf("Reading best placement back in.\n"); 00627 placer_opts.place_chan_width = final; 00628 read_place(place_file, net_file, arch_file, placer_opts, 00629 router_opts, chan_width_dist, det_routing_arch, 00630 segment_inf, timing_inf, &mst); 00631 } 00632 #endif 00633 free_rr_graph(); 00634 00635 build_rr_graph(graph_type, 00636 num_types, type_descriptors, nx, ny, grid, 00637 chan_width_x[0], NULL, 00638 det_routing_arch.switch_block_type, det_routing_arch.Fs, 00639 det_routing_arch.num_segment, det_routing_arch.num_switch, segment_inf, 00640 det_routing_arch.global_route_switch, 00641 det_routing_arch.delayless_switch, timing_inf, 00642 det_routing_arch.wire_to_ipin_switch, 00643 router_opts.base_cost_type, &warnings); 00644 00645 restore_routing(best_routing, clb_opins_used_locally, 00646 saved_clb_opins_used_locally); 00647 check_route(router_opts.route_type, det_routing_arch.num_switch, 00648 clb_opins_used_locally); 00649 get_serial_num(); 00650 if(Fc_clipped) 00651 { 00652 printf 00653 ("Warning: Best routing Fc_output too high, clipped to full (maximum) connectivity.\n"); 00654 } 00655 printf("Best routing used a channel width factor of %d.\n\n", final); 00656 00657 routing_stats(full_stats, router_opts.route_type, 00658 det_routing_arch.num_switch, segment_inf, 00659 det_routing_arch.num_segment, 00660 det_routing_arch.R_minW_nmos, 00661 det_routing_arch.R_minW_pmos, 00662 det_routing_arch.directionality, 00663 timing_inf.timing_analysis_enabled, net_slack, net_delay); 00664 00665 print_route(route_file); 00666 00667 #ifdef CREATE_ECHO_FILES 00668 /* print_sink_delays("routing_sink_delays.echo"); */ 00669 #endif /* CREATE_ECHO_FILES */ 00670 00671 init_draw_coords(max_pins_per_clb); 00672 sprintf(msg, "Routing succeeded with a channel width factor of %d.", 00673 final); 00674 update_screen(MAJOR, msg, ROUTING, timing_inf.timing_analysis_enabled); 00675 00676 if(timing_inf.timing_analysis_enabled) 00677 { 00678 #ifdef CREATE_ECHO_FILES 00679 print_timing_graph_as_blif("post_flow_timing_graph.blif", models); 00680 #endif 00681 free_timing_graph(net_slack); 00682 free_net_delay(net_delay, &net_delay_chunk_list_head); 00683 } 00684 00685 free_route_structs(clb_opins_used_locally); 00686 free_saved_routing(best_routing, saved_clb_opins_used_locally); 00687 fflush(stdout); 00688 00689 return (final); 00690 } 00691 00692 00693 /** Assigns widths to channels (in tracks). Minimum one track 00694 * per channel. io channels are io_rat * maximum in interior 00695 * tracks wide. The channel distributions read from the architecture 00696 * file are scaled by cfactor. 00697 */ 00698 void 00699 init_chan(int cfactor, 00700 t_chan_width_dist chan_width_dist) 00701 { 00702 00703 float x, separation, chan_width_io; 00704 int nio, i; 00705 t_chan chan_x_dist, chan_y_dist; 00706 00707 chan_width_io = chan_width_dist.chan_width_io; 00708 chan_x_dist = chan_width_dist.chan_x_dist; 00709 chan_y_dist = chan_width_dist.chan_y_dist; 00710 00711 /* io channel widths */ 00712 00713 nio = (int)floor(cfactor * chan_width_io + 0.5); 00714 if(nio == 0) 00715 nio = 1; /* No zero width channels */ 00716 00717 chan_width_x[0] = chan_width_x[ny] = nio; 00718 chan_width_y[0] = chan_width_y[nx] = nio; 00719 00720 if(ny > 1) 00721 { 00722 separation = 1. / (ny - 2.); /* Norm. distance between two channels. */ 00723 x = 0.; /* This avoids div by zero if ny = 2. */ 00724 chan_width_x[1] = (int)floor(cfactor * comp_width(&chan_x_dist, x, 00725 separation) + 00726 0.5); 00727 00728 /* No zero width channels */ 00729 chan_width_x[1] = max(chan_width_x[1], 1); 00730 00731 for(i = 1; i < ny - 1; i++) 00732 { 00733 x = (float)i / ((float)(ny - 2.)); 00734 chan_width_x[i + 1] = 00735 (int)floor(cfactor * 00736 comp_width(&chan_x_dist, x, 00737 separation) + 0.5); 00738 chan_width_x[i + 1] = max(chan_width_x[i + 1], 1); 00739 } 00740 } 00741 00742 if(nx > 1) 00743 { 00744 separation = 1. / (nx - 2.); /* Norm. distance between two channels. */ 00745 x = 0.; /* Avoids div by zero if nx = 2. */ 00746 chan_width_y[1] = (int)floor(cfactor * comp_width(&chan_y_dist, x, 00747 separation) + 00748 0.5); 00749 00750 chan_width_y[1] = max(chan_width_y[1], 1); 00751 00752 for(i = 1; i < nx - 1; i++) 00753 { 00754 x = (float)i / ((float)(nx - 2.)); 00755 chan_width_y[i + 1] = 00756 (int)floor(cfactor * 00757 comp_width(&chan_y_dist, x, 00758 separation) + 0.5); 00759 chan_width_y[i + 1] = max(chan_width_y[i + 1], 1); 00760 } 00761 } 00762 #ifdef VERBOSE 00763 printf("\nchan_width_x:\n"); 00764 for(i = 0; i <= ny; i++) 00765 printf("%d ", chan_width_x[i]); 00766 printf("\n\nchan_width_y:\n"); 00767 for(i = 0; i <= nx; i++) 00768 printf("%d ", chan_width_y[i]); 00769 printf("\n\n"); 00770 #endif 00771 00772 } 00773 00774 00775 /** Return the relative channel density. *chan points to a channel 00776 * functional description data structure, and x is the distance 00777 * (between 0 and 1) we are across the chip. separation is the 00778 * distance between two channels, in the 0 to 1 coordinate system. 00779 */ 00780 static float 00781 comp_width(t_chan * chan, 00782 float x, 00783 float separation) 00784 { 00785 float val; 00786 00787 switch (chan->type) 00788 { 00789 00790 case UNIFORM: 00791 val = chan->peak; 00792 break; 00793 00794 case GAUSSIAN: 00795 val = (x - chan->xpeak) * (x - chan->xpeak) / (2 * chan->width * 00796 chan->width); 00797 val = chan->peak * exp(-val); 00798 val += chan->dc; 00799 break; 00800 00801 case PULSE: 00802 val = (float)fabs((double)(x - chan->xpeak)); 00803 if(val > chan->width / 2.) 00804 { 00805 val = 0; 00806 } 00807 else 00808 { 00809 val = chan->peak; 00810 } 00811 val += chan->dc; 00812 break; 00813 00814 case DELTA: 00815 val = x - chan->xpeak; 00816 if(val > -separation / 2. && val <= separation / 2.) 00817 val = chan->peak; 00818 else 00819 val = 0.; 00820 val += chan->dc; 00821 break; 00822 00823 default: 00824 printf("Error in comp_width: Unknown channel type %d.\n", 00825 chan->type); 00826 exit(1); 00827 break; 00828 } 00829 00830 return (val); 00831 } 00832 00833 /** After placement, logical pins for blocks, and nets must be updated to correspond with physical pins of type. 00834 * This function should only be called once 00835 */ 00836 void 00837 post_place_sync(INP int num_blocks, 00838 INOUTP const struct s_block block_list[]) 00839 { 00840 int iblk, j, k, inet; 00841 t_type_ptr type; 00842 int max_num_block_pins; 00843 00844 /* Go through each block */ 00845 for(iblk = 0; iblk < num_blocks; ++iblk) 00846 { 00847 type = block[iblk].type; 00848 assert(type->num_pins % type->capacity == 0); 00849 max_num_block_pins = type->num_pins / type->capacity; 00850 /* Logical location and physical location is offset by z * max_num_block_pins */ 00851 /* Sync blocks and nets */ 00852 for(j = 0; j < max_num_block_pins; j++) 00853 { 00854 inet = block[iblk].nets[j]; 00855 if(inet != OPEN && block[iblk].z > 0) 00856 { 00857 assert(block[iblk]. 00858 nets[j + 00859 block[iblk].z * max_num_block_pins] == 00860 OPEN); 00861 block[iblk].nets[j + 00862 block[iblk].z * 00863 max_num_block_pins] = 00864 block[iblk].nets[j]; 00865 block[iblk].nets[j] = OPEN; 00866 for(k = 0; k <= clb_net[inet].num_sinks; k++) 00867 { 00868 if(clb_net[inet].node_block[k] == iblk) 00869 { 00870 assert(clb_net[inet]. 00871 node_block_pin[k] == j); 00872 clb_net[inet].node_block_pin[k] = 00873 j + 00874 block[iblk].z * 00875 max_num_block_pins; 00876 break; 00877 } 00878 } 00879 assert(k <= clb_net[inet].num_sinks); 00880 } 00881 } 00882 } 00883 } 00884 00885 void 00886 free_pb_data(t_pb *pb) 00887 { 00888 int i, j; 00889 const t_pb_type *pb_type; 00890 t_rr_node *temp; 00891 00892 if(pb == NULL || pb->name == NULL) { 00893 return; 00894 } 00895 00896 pb_type = pb->pb_graph_node->pb_type; 00897 00898 /* free existing rr graph for pb */ 00899 if(pb->rr_graph) { 00900 temp = rr_node; 00901 rr_node = pb->rr_graph; 00902 num_rr_nodes = pb->pb_graph_node->total_pb_pins; 00903 free_rr_graph(); 00904 rr_node = temp; 00905 } 00906 00907 if(pb_type->num_modes > 0) { 00908 /* Free children of pb */ 00909 for(i = 0; i < pb_type->modes[pb->mode].num_pb_type_children; i++) { 00910 for(j = 0; j < pb_type->modes[pb->mode].pb_type_children[i].num_pb; j++) { 00911 if(pb->child_pbs[i]) { 00912 free_pb_data(&pb->child_pbs[i][j]); 00913 } 00914 } 00915 } 00916 } 00917 00918 /* Frees all the pb data structures. */ 00919 if(pb->name) { 00920 free(pb->name); 00921 if(pb->child_pbs) { 00922 free(pb->child_pbs); 00923 } 00924 } 00925 }