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