23 float target_criticality,
float astar_fac);
26 float bend_cost,
float criticality_fac,
int target_node,
27 float astar_fac,
int highfanout_rlim);
30 float criticality_fac,
float R_upstream);
33 int *num_segs_ortho_dir_ptr);
51 int itry, inet, ipin, i, bends, wirelength, total_wirelength, available_wirelength,
53 boolean success, is_routable, rip_up_local_opins;
55 critical_path_delay, init_timing_criticality_val;
65 heapsort(net_index, sinks, num_nets, 1);
75 if (timing_analysis_enabled) {
76 init_timing_criticality_val = 1.;
78 init_timing_criticality_val = 0.;
81 for (inet = 0; inet <
num_nets; inet++) {
86 slacks->path_criticality[inet][ipin] = init_timing_criticality_val;
94 net_delay[inet][ipin] = 0.;
104 vpr_printf(TIO_MESSAGE_INFO,
"Routing iteration: %d\n", itry);
114 sink_order, rt_node_of_sink, net_delay[inet], slacks);
119 vpr_printf(TIO_MESSAGE_INFO,
"Routing failed.\n");
121 sink_order, rt_node_of_sink);
133 total_wirelength = 0;
134 available_wirelength = 0;
144 for (inet = 0; inet <
num_nets; inet++) {
146 &&
clb_net[inet].num_sinks != 0) {
150 total_wirelength += wirelength;
153 vpr_printf(TIO_MESSAGE_INFO,
"Wire length after first iteration %d, total available wire length %d, ratio %g\n",
154 total_wirelength, available_wirelength,
155 (
float) (total_wirelength) / (
float) (available_wirelength));
157 vpr_printf(TIO_MESSAGE_INFO,
"Wire length usage ratio exceeds limit of %g, fail routing.\n",
171 rip_up_local_opins =
FALSE;
173 rip_up_local_opins =
TRUE;
176 clb_opins_used_locally);
183 vpr_printf(TIO_MESSAGE_INFO,
"Successfully routed after %d routing iterations.\n", itry);
205 if (timing_analysis_enabled) {
211 #ifdef HACK_LUT_PIN_SWAPPING
219 vpr_printf(TIO_MESSAGE_INFO,
"Critical path: %g ns\n", critical_path_delay);
224 for (inet = 0; inet <
num_nets; inet++) {
228 slacks->path_criticality[inet][ipin] = 0.;
230 net_delay[inet][ipin] = 0.;
236 #ifdef CLOCKS_PER_SEC
237 vpr_printf(TIO_MESSAGE_INFO,
"Routing iteration took %g seconds.\n", (
float)(end - begin) / CLOCKS_PER_SEC);
239 vpr_printf(TIO_MESSAGE_INFO,
"Routing iteration took %g seconds.\n", (
float)(end - begin) / CLK_PER_SEC);
245 vpr_printf(TIO_MESSAGE_INFO,
"Routing failed.\n");
254 int **sink_order_ptr,
t_rt_node *** rt_node_of_sink_ptr) {
258 int max_pins_per_net;
266 (max_pins_per_net - 1) *
sizeof(float));
267 *pin_criticality_ptr = pin_criticality - 1;
269 sink_order = (
int *)
my_malloc((max_pins_per_net - 1) *
sizeof(int));
270 *sink_order_ptr = sink_order - 1;
273 (max_pins_per_net - 1) *
sizeof(
t_rt_node *));
274 *rt_node_of_sink_ptr = rt_node_of_sink - 1;
284 free(pin_criticality + 1);
285 free(sink_order + 1);
286 free(rt_node_of_sink + 1);
294 int inet, max_pins_per_net;
296 max_pins_per_net = 0;
297 for (inet = 0; inet <
num_nets; inet++) {
299 max_pins_per_net =
std::max(max_pins_per_net,
300 (
clb_net[inet].num_sinks + 1));
304 return (max_pins_per_net);
308 float criticality_exp,
float astar_fac,
float bend_cost,
318 int ipin, num_sinks, itarget, target_pin, target_node, inode;
319 float target_criticality, old_tcost, new_tcost, largest_criticality,
320 old_back_cost, new_back_cost;
323 struct s_trace *new_route_start_tptr;
336 pin_criticality[ipin] = 1.0;
340 pin_criticality[ipin] = ROUTE_PATH_WEIGHT * slacks->path_criticality[inet][ipin]
352 assert(pin_criticality[ipin] > -0.01 && pin_criticality[ipin] < 1.01);
353 pin_criticality[ipin] =
std::max(pin_criticality[ipin] - (1.0 - max_criticality), 0.0);
356 pin_criticality[ipin] = pow(pin_criticality[ipin], criticality_exp);
359 pin_criticality[ipin] =
std::min(pin_criticality[ipin], max_criticality);
364 heapsort(sink_order, pin_criticality, num_sinks, 0);
368 largest_criticality = pin_criticality[sink_order[1]];
375 for (itarget = 1; itarget <= num_sinks; itarget++) {
376 target_pin = sink_order[itarget];
379 target_criticality = pin_criticality[target_pin];
389 if (current == NULL) {
390 vpr_printf(TIO_MESSAGE_INFO,
"Cannot route net #%d (%s) to sink #%d -- no possible path.\n",
391 inet,
clb_net[inet].name, itarget);
397 inode = current->
index;
399 while (inode != target_node) {
401 new_tcost = current->
cost;
418 if (old_tcost > new_tcost && old_back_cost > new_back_cost) {
428 target_criticality, target_node, astar_fac,
435 if (current == NULL) {
436 vpr_printf(TIO_MESSAGE_INFO,
"Cannot route net #%d (%s) to sink #%d -- no possible path.\n",
437 inet,
clb_net[inet].name, itarget);
443 inode = current->
index;
472 float target_criticality,
float astar_fac) {
481 float tot_cost, backward_path_cost, R_upstream;
486 inode = rt_node->
inode;
487 backward_path_cost = target_criticality * rt_node->
Tdel;
489 tot_cost = backward_path_cost
492 target_criticality, R_upstream);
494 backward_path_cost, R_upstream);
499 while (linked_rt_edge != NULL) {
500 child_node = linked_rt_edge->
child;
503 linked_rt_edge = linked_rt_edge->
next;
508 float bend_cost,
float criticality_fac,
int target_node,
509 float astar_fac,
int highfanout_rlim) {
515 int iconn, to_node, num_edges, inode,
iswitch, target_x, target_y;
517 float new_tot_cost, old_back_pcost, new_back_pcost, R_upstream;
518 float new_R_upstream, Tdel;
520 inode = current->
index;
528 for (iconn = 0; iconn < num_edges; iconn++) {
538 if (
rr_node[to_node].xhigh < target_x - highfanout_rlim
539 ||
rr_node[to_node].xlow > target_x + highfanout_rlim
540 ||
rr_node[to_node].yhigh < target_y - highfanout_rlim
541 ||
rr_node[to_node].ylow > target_y + highfanout_rlim)
552 && (
rr_node[to_node].xhigh != target_x
553 ||
rr_node[to_node].yhigh != target_y))
561 new_back_pcost = old_back_pcost
573 new_R_upstream +=
rr_node[to_node].
R;
574 new_back_pcost += criticality_fac * Tdel;
576 if (bend_cost != 0.) {
581 new_back_pcost += bend_cost;
584 new_tot_cost = new_back_pcost
587 criticality_fac, new_R_upstream);
589 node_to_heap(to_node, new_tot_cost, inode, iconn, new_back_pcost,
596 float criticality_fac,
float R_upstream) {
603 int cost_index, ortho_cost_index, num_segs_same_dir, num_segs_ortho_dir;
604 float expected_cost, cong_cost, Tdel;
610 &num_segs_ortho_dir);
624 + num_segs_same_dir * num_segs_same_dir
626 + num_segs_ortho_dir * num_segs_ortho_dir
636 expected_cost = criticality_fac * Tdel
637 + (1. - criticality_fac) * cong_cost;
638 return (expected_cost);
641 else if (rr_type ==
IPIN) {
653 #define ROUND_UP(x) (ceil (x - 0.001))
656 int *num_segs_ortho_dir_ptr) {
663 int target_x, target_y, num_segs_same_dir, cost_index, ortho_cost_index;
664 int no_need_to_pass_by_clb;
665 float inv_length, ortho_inv_length, ylow, yhigh, xlow, xhigh;
675 if (rr_type ==
CHANX) {
682 if (ylow > target_y) {
683 *num_segs_ortho_dir_ptr =
684 (int)(
ROUND_UP((ylow - target_y + 1.) * ortho_inv_length));
685 no_need_to_pass_by_clb = 1;
686 }
else if (ylow < target_y - 1) {
687 *num_segs_ortho_dir_ptr = (int)(
ROUND_UP((target_y - ylow) *
689 no_need_to_pass_by_clb = 1;
691 *num_segs_ortho_dir_ptr = 0;
692 no_need_to_pass_by_clb = 0;
697 if (xlow > target_x + no_need_to_pass_by_clb) {
698 num_segs_same_dir = (int)(
ROUND_UP((xlow - no_need_to_pass_by_clb -
699 target_x) * inv_length));
700 }
else if (xhigh < target_x - no_need_to_pass_by_clb) {
701 num_segs_same_dir = (int)(
ROUND_UP((target_x - no_need_to_pass_by_clb -
702 xhigh) * inv_length));
704 num_segs_same_dir = 0;
715 if (xlow > target_x) {
716 *num_segs_ortho_dir_ptr = (int)(
717 ROUND_UP((xlow - target_x + 1.) * ortho_inv_length));
718 no_need_to_pass_by_clb = 1;
719 }
else if (xlow < target_x - 1) {
720 *num_segs_ortho_dir_ptr = (int)(
ROUND_UP((target_x - xlow) *
722 no_need_to_pass_by_clb = 1;
724 *num_segs_ortho_dir_ptr = 0;
725 no_need_to_pass_by_clb = 0;
730 if (ylow > target_y + no_need_to_pass_by_clb) {
731 num_segs_same_dir = (int)(
ROUND_UP((ylow - no_need_to_pass_by_clb -
732 target_y) * inv_length));
733 }
else if (yhigh < target_y - no_need_to_pass_by_clb) {
734 num_segs_same_dir = (int)(
ROUND_UP((target_y - no_need_to_pass_by_clb -
735 yhigh) * inv_length));
737 num_segs_same_dir = 0;
741 return (num_segs_same_dir);
749 float fanout, factor;
755 factor = sqrt(fanout);
771 int target_x, target_y;
793 rlim = (int)(ceil(sqrt((
float) area / (
float)
clb_net[inet].num_sinks)));
794 if (rt_node == NULL || rt_node->
u.
child_list == NULL) {
805 while (success ==
FALSE && linked_rt_edge != NULL) {
806 while (linked_rt_edge != NULL && success ==
FALSE) {
807 child_node = linked_rt_edge->
child;
808 inode = child_node->
inode;
810 if (
rr_node[inode].xlow <= target_x + rlim
811 &&
rr_node[inode].xhigh >= target_x - rlim
812 &&
rr_node[inode].ylow <= target_y + rlim
813 &&
rr_node[inode].yhigh >= target_y - rlim) {
817 linked_rt_edge = linked_rt_edge->
next;
820 if (success ==
FALSE) {
822 vpr_printf(TIO_MESSAGE_ERROR,
"VPR internal error, net %s has paths that are not found in traceback.\n",
837 while (linked_rt_edge != NULL) {
838 child_node = linked_rt_edge->
child;
839 inode = child_node->
inode;
841 if (
rr_node[inode].xlow <= target_x + rlim
842 &&
rr_node[inode].xhigh >= target_x - rlim
843 &&
rr_node[inode].ylow <= target_y + rlim
844 &&
rr_node[inode].yhigh >= target_y - rlim) {
850 linked_rt_edge = linked_rt_edge->
next;
855 #define ERROR_TOL 0.0001
863 float **net_delay_check;
865 t_chunk list_head_net_delay_check_ch = {NULL, 0, NULL};
873 for (inet = 0; inet <
num_nets; inet++) {
875 if (net_delay_check[inet][ipin] == 0.) {
876 if (fabs(net_delay[inet][ipin]) >
ERROR_TOL) {
877 vpr_printf(TIO_MESSAGE_ERROR,
"in timing_driven_check_net_delays: net %d pin %d.\n",
879 vpr_printf(TIO_MESSAGE_ERROR,
"\tIncremental calc. net_delay is %g, but from scratch net delay is %g.\n",
880 net_delay[inet][ipin], net_delay_check[inet][ipin]);
884 if (fabs(1.0 - net_delay[inet][ipin] / net_delay_check[inet][ipin]) >
ERROR_TOL) {
885 vpr_printf(TIO_MESSAGE_ERROR,
"in timing_driven_check_net_delays: net %d pin %d.\n",
887 vpr_printf(TIO_MESSAGE_ERROR,
"\tIncremental calc. net_delay is %g, but from scratch net delay is %g.\n",
888 net_delay[inet][ipin], net_delay_check[inet][ipin]);
896 vpr_printf(TIO_MESSAGE_INFO,
"Completed net delay value cross check successfully.\n");
boolean feasible_routing(void)
void load_net_delay_from_routing(float **net_delay, struct s_net *nets, int n_nets)
float get_rr_cong_cost(int inode)
void free_timing_driven_route_structs(float *pin_criticality, int *sink_order, t_rt_node **rt_node_of_sink)
t_rt_node * init_route_tree_to_source(int inet)
struct s_heap * get_heap_head(void)
void heapsort(int *sort_index, float *sort_values, int nelem, int start_index)
void free_traceback(int inet)
t_rr_node_route_inf * rr_node_route_inf
t_rr_indexed_data * rr_indexed_data
float get_critical_path_delay(void)
void free_heap_data(struct s_heap *hptr)
static float ** net_delay
int max_router_iterations
float first_iter_pres_fac
void alloc_route_tree_timing_structs(void)
struct s_linked_rt_edge * next
void pathfinder_update_cost(float pres_fac, float acc_fac)
#define FIRST_ITER_WIRELENTH_LIMIT
static int get_max_pins_per_net(void)
void do_timing_analysis(t_slack *slacks, boolean is_prepacked, boolean do_lut_input_balancing, boolean is_final_analysis)
void update_net_delays_from_route_tree(float *net_delay, t_rt_node **rt_node_of_sink, int inet)
void reset_path_costs(void)
void get_num_bends_and_length(int inet, int *bends_ptr, int *len_ptr, int *segments_ptr)
static t_ivec ** clb_opins_used_locally
static float get_timing_driven_expected_cost(int inode, int target_node, float criticality_fac, float R_upstream)
#define HUGE_POSITIVE_FLOAT
static void * my_malloc(int ibytes)
static float * pin_criticality
static void add_route_tree_to_heap(t_rt_node *rt_node, int target_node, float target_criticality, float astar_fac)
void free_route_tree(t_rt_node *rt_node)
void free_route_tree_timing_structs(void)
struct s_trace ** trace_head
struct s_switch_inf * switch_inf
void alloc_timing_driven_route_structs(float **pin_criticality_ptr, int **sink_order_ptr, t_rt_node ***rt_node_of_sink_ptr)
static void timing_driven_expand_neighbours(struct s_heap *current, int inet, float bend_cost, float criticality_fac, int target_node, float astar_fac, int highfanout_rlim)
void node_to_heap(int inode, float cost, int prev_node, int prev_edge, float backward_path_cost, float R_upstream)
void free_net_delay(float **net_delay, t_chunk *chunk_list_ptr)
static void timing_driven_check_net_delays(float **net_delay)
float ** alloc_net_delay(t_chunk *chunk_list_ptr, struct s_net *nets, int n_nets)
t_linked_rt_edge * child_list
void pathfinder_update_one_cost(struct s_trace *route_segment_start, int add_or_sub, float pres_fac)
boolean timing_driven_route_net(int inet, float pres_fac, float max_criticality, float criticality_exp, float astar_fac, float bend_cost, float *pin_criticality, int *sink_order, t_rt_node **rt_node_of_sink, float *net_delay, t_slack *slacks)
struct s_trace * update_traceback(struct s_heap *hptr, int inet)
static void update_rr_base_costs(int inet, float largest_criticality)
float ** timing_criticality
static int get_expected_segs_to_target(int inode, int target_node, int *num_segs_ortho_dir_ptr)
t_rt_node * update_route_tree(struct s_heap *hptr)
#define HIGH_FANOUT_NET_LIM
static int mark_node_expansion_by_bin(int inet, int target_node, t_rt_node *rt_node)
void add_to_mod_list(float *fptr)
void reserve_locally_used_opins(float pres_fac, boolean rip_up_local_opins, t_ivec **clb_opins_used_locally)
static t_rt_node ** rt_node_of_sink
boolean try_timing_driven_route(struct s_router_opts router_opts, float **net_delay, t_slack *slacks, t_ivec **clb_opins_used_locally, boolean timing_analysis_enabled)
void load_timing_graph_net_delays(float **net_delay)