📄 route_timing.c
字号:
#include <stdio.h>#include <math.h>#include "util.h"#include "vpr_types.h"#include "globals.h"#include "route_export.h"#include "route_common.h"#include "route_tree_timing.h"#include "route_timing.h"#include "heapsort.h"#include "path_delay.h"#include "net_delay.h"/******************** Subroutines local to route_timing.c ********************/static int get_max_pins_per_net (void);static void add_route_tree_to_heap (t_rt_node *rt_node, int target_node, float target_criticality, float astar_fac); static void timing_driven_expand_neighbours (struct s_heap *current, int inet, float bend_cost, float criticality_fac, int target_node, float astar_fac); static float get_timing_driven_expected_cost (int inode, int target_node, float criticality_fac, float R_upstream); static int get_expected_segs_to_target (int inode, int target_node, int * num_segs_ortho_dir_ptr);static void update_rr_base_costs (int inet, float largest_criticality); static void timing_driven_check_net_delays (float **net_delay); /************************ Subroutine definitions *****************************/boolean try_timing_driven_route (struct s_router_opts router_opts, float **net_slack, float **net_delay, t_ivec **clb_opins_used_locally) {/* Timing-driven routing algorithm. The timing graph (includes net_slack) * * must have already been allocated, and net_delay must have been allocated. * * Returns TRUE if the routing succeeds, FALSE otherwise. */ int itry, inet, ipin; boolean success, is_routable, rip_up_local_opins; float *pin_criticality; /* [1..max_pins_per_net-1]. */ int *sink_order; /* [1..max_pins_per_net-1]. */ t_rt_node **rt_node_of_sink; /* [1..max_pins_per_net-1]. */ float T_crit, pres_fac; alloc_timing_driven_route_structs (&pin_criticality, &sink_order, &rt_node_of_sink);/* First do one routing iteration ignoring congestion and marking all sinks * * on each net as critical to get reasonable net delay estimates. */ for (inet=0;inet<num_nets;inet++) { if (is_global[inet] == FALSE) { for (ipin=1;ipin<net[inet].num_pins;ipin++) net_slack[inet][ipin] = 0.; } else { /* Set delay of global signals to zero. */ for (ipin=1;ipin<net[inet].num_pins;ipin++) net_delay[inet][ipin] = 0.; } } T_crit = 1.; pres_fac = router_opts.first_iter_pres_fac; /* Typically 0 -> ignore cong. */ for (itry=1;itry<=router_opts.max_router_iterations;itry++) { for (inet=0;inet<num_nets;inet++) { if (is_global[inet] == FALSE) { /* Skip global nets. */ is_routable = timing_driven_route_net (inet, pres_fac, router_opts.max_criticality, router_opts.criticality_exp, router_opts.astar_fac, router_opts.bend_cost, net_slack[inet], pin_criticality, sink_order, rt_node_of_sink, T_crit, net_delay[inet]); /* Impossible to route? (disconnected rr_graph) */ if (!is_routable) { printf ("Routing failed.\n"); free_timing_driven_route_structs (pin_criticality, sink_order, rt_node_of_sink); return (FALSE); } } } /* Make sure any CLB OPINs used up by subblocks being hooked directly * * to them are reserved for that purpose. */ if (itry == 1) rip_up_local_opins = FALSE; else rip_up_local_opins = TRUE; reserve_locally_used_opins (pres_fac, rip_up_local_opins, clb_opins_used_locally); /* Pathfinder guys quit after finding a feasible route. I may want to keep * * going longer, trying to improve timing. Think about this some. */ success = feasible_routing (); if (success) { printf("Successfully routed after %d routing iterations.\n", itry); free_timing_driven_route_structs (pin_criticality, sink_order, rt_node_of_sink);#ifdef DEBUG timing_driven_check_net_delays (net_delay);#endif return (TRUE); } if (itry == 1) { pres_fac = router_opts.initial_pres_fac; pathfinder_update_cost (pres_fac, 0.); /* Acc_fac=0 for first iter. */ } else { pres_fac *= router_opts.pres_fac_mult; pathfinder_update_cost (pres_fac, router_opts.acc_fac); } /* Update slack values by doing another timing analysis. * * Timing_driven_route_net updated the net delay values. */ load_timing_graph_net_delays (net_delay); T_crit = load_net_slack (net_slack, 0); printf ("T_crit: %g.\n", T_crit); } printf ("Routing failed.\n"); free_timing_driven_route_structs (pin_criticality, sink_order, rt_node_of_sink); return (FALSE);}void alloc_timing_driven_route_structs (float **pin_criticality_ptr, int **sink_order_ptr, t_rt_node ***rt_node_of_sink_ptr) {/* Allocates all the structures needed only by the timing-driven router. */ int max_pins_per_net; float *pin_criticality; int *sink_order; t_rt_node **rt_node_of_sink; max_pins_per_net = get_max_pins_per_net (); pin_criticality = (float *) my_malloc ((max_pins_per_net-1) * sizeof (float)); *pin_criticality_ptr = pin_criticality - 1; /* First sink is pin #1. */ sink_order = (int *) my_malloc ((max_pins_per_net - 1) * sizeof (int)); *sink_order_ptr = sink_order - 1; rt_node_of_sink = (t_rt_node **) my_malloc ((max_pins_per_net - 1) * sizeof (t_rt_node *)); *rt_node_of_sink_ptr = rt_node_of_sink - 1; alloc_route_tree_timing_structs ();}void free_timing_driven_route_structs (float *pin_criticality, int *sink_order, t_rt_node **rt_node_of_sink) {/* Frees all the stuctures needed only by the timing-driven router. */ free (pin_criticality + 1); /* Starts at index 1. */ free (sink_order + 1); free (rt_node_of_sink + 1); free_route_tree_timing_structs ();}static int get_max_pins_per_net (void) {/* Returns the largest number of pins on any non-global net. */ int inet, max_pins_per_net; max_pins_per_net = 0; for (inet=0;inet<num_nets;inet++) { if (is_global[inet] == FALSE) { max_pins_per_net = max (max_pins_per_net, net[inet].num_pins); } } return (max_pins_per_net);}boolean timing_driven_route_net (int inet, float pres_fac, float max_criticality, float criticality_exp, float astar_fac, float bend_cost, float *net_slack, float *pin_criticality, int *sink_order, t_rt_node **rt_node_of_sink, float T_crit, float *net_delay) {/* Returns TRUE as long is found some way to hook up this net, even if that * * way resulted in overuse of resources (congestion). If there is no way * * to route this net, even ignoring congestion, it returns FALSE. In this * * case the rr_graph is disconnected and you can give up. */ int ipin, num_sinks, itarget, target_pin, target_node, inode; float target_criticality, old_tcost, new_tcost, largest_criticality, pin_crit; float old_back_cost, new_back_cost; t_rt_node *rt_root; struct s_heap *current; struct s_trace *new_route_start_tptr;/* Rip-up any old routing. *//* printf ("\nRouting inet: %d\n", inet); */ pathfinder_update_one_cost (trace_head[inet], -1, pres_fac); free_traceback (inet); for (ipin=1;ipin<net[inet].num_pins;ipin++) { /* For all sinks */ pin_crit = max (max_criticality - net_slack[ipin] / T_crit, 0.); pin_crit = pow (pin_crit, criticality_exp); pin_crit = min (pin_crit, max_criticality); pin_criticality[ipin] = pin_crit; } num_sinks = net[inet].num_pins - 1; heapsort (sink_order, pin_criticality, num_sinks);/* Update base costs according to fanout and criticality rules */ largest_criticality = pin_criticality[sink_order[1]]; update_rr_base_costs (inet, largest_criticality); mark_ends (inet); /* Only needed to check for multiply-connected SINKs */ rt_root = init_route_tree_to_source (inet); for (itarget=1;itarget<=num_sinks;itarget++) { target_pin = sink_order[itarget]; target_node = net_rr_terminals[inet][target_pin];/* printf ("Target #%d, pin number %d, target_node: %d.\n", itarget, target_pin, target_node); */ target_criticality = pin_criticality[target_pin]; add_route_tree_to_heap (rt_root, target_node, target_criticality, astar_fac); current = get_heap_head (); if (current == NULL) { /* Infeasible routing. No possible path for net. */ reset_path_costs (); free_route_tree (rt_root); return (FALSE); } inode = current->index; while (inode != target_node) { old_tcost = rr_node_route_inf[inode].path_cost; new_tcost = current->cost; if (old_tcost > 0.99 * HUGE_FLOAT) /* First time touched. */ old_back_cost = HUGE_FLOAT; else old_back_cost = rr_node_route_inf[inode].backward_path_cost; new_back_cost = current->backward_path_cost; /* I only re-expand a node if both the "known" backward cost is lower * * in the new expansion (this is necessary to prevent loops from * * forming in the routing and causing havoc) *and* the expected total * * cost to the sink is lower than the old value. Different R_upstream * * values could make a path with lower back_path_cost less desirable * * than one with higher cost. Test whether or not I should disallow * * re-expansion based on a higher total cost. */ if (old_tcost > new_tcost && old_back_cost > new_back_cost) { /* if (old_tcost > new_tcost) { */ rr_node_route_inf[inode].prev_node = current->u.prev_node; rr_node_route_inf[inode].prev_edge = current->prev_edge; rr_node_route_inf[inode].path_cost = new_tcost; rr_node_route_inf[inode].backward_path_cost = new_back_cost; if (old_tcost > 0.99 * HUGE_FLOAT) /* First time touched. */ add_to_mod_list (&rr_node_route_inf[inode].path_cost); timing_driven_expand_neighbours (current, inet, bend_cost, target_criticality, target_node, astar_fac); } free_heap_data (current); current = get_heap_head (); if (current == NULL) { /* Impossible routing. No path for net. */ reset_path_costs (); free_route_tree (rt_root); return (FALSE); } inode = current->index; }/* NB: In the code below I keep two records of the partial routing: the * * traceback and the route_tree. The route_tree enables fast recomputation * * of the Elmore delay to each node in the partial routing. The traceback * * lets me reuse all the routines written for breadth-first routing, which * * all take a traceback structure as input. Before this routine exits the * * route_tree structure is destroyed; only the traceback is needed at that * * point. */ rr_node_route_inf[inode].target_flag--; /* Connected to this SINK. */ new_route_start_tptr = update_traceback (current, inet); rt_node_of_sink[target_pin] = update_route_tree (current); free_heap_data (current); pathfinder_update_one_cost (new_route_start_tptr, 1, pres_fac); empty_heap (); reset_path_costs (); }/* For later timing analysis. */ update_net_delays_from_route_tree (net_delay, rt_node_of_sink, inet); free_route_tree (rt_root); return (TRUE);}static void add_route_tree_to_heap (t_rt_node *rt_node, int target_node, float target_criticality, float astar_fac) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -