|
| 1 | +#ifndef _CONNECTION_ROUTER_H |
| 2 | +#define _CONNECTION_ROUTER_H |
| 3 | + |
| 4 | +#include "connection_router_interface.h" |
| 5 | +#include "rr_graph_storage.h" |
| 6 | +#include "route_common.h" |
| 7 | +#include "router_lookahead.h" |
| 8 | +#include "route_tree.h" |
| 9 | +#include "rr_rc_data.h" |
| 10 | +#include "router_stats.h" |
| 11 | +#include "spatial_route_tree_lookup.h" |
| 12 | + |
| 13 | +// This class encapsulates the timing driven connection router. This class |
| 14 | +// routes from some initial set of sources (via the input rt tree) to a |
| 15 | +// particular sink. |
| 16 | +// |
| 17 | +// When the ConnectionRouter is used, it mutates the provided |
| 18 | +// rr_node_route_inf. The routed path can be found by tracing from the sink |
| 19 | +// node (which is returned) through the rr_node_route_inf. See |
| 20 | +// update_traceback as an example of this tracing. |
| 21 | +template<typename HeapImplementation> |
| 22 | +class ConnectionRouter : public ConnectionRouterInterface { |
| 23 | + public: |
| 24 | + ConnectionRouter( |
| 25 | + const DeviceGrid& grid, |
| 26 | + const RouterLookahead& router_lookahead, |
| 27 | + const t_rr_graph_storage& rr_nodes, |
| 28 | + const RRGraphView* rr_graph, |
| 29 | + const std::vector<t_rr_rc_data>& rr_rc_data, |
| 30 | + const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switch_inf, |
| 31 | + vtr::vector<RRNodeId, t_rr_node_route_inf>& rr_node_route_inf, |
| 32 | + bool is_flat) |
| 33 | + : grid_(grid) |
| 34 | + , router_lookahead_(router_lookahead) |
| 35 | + , rr_nodes_(rr_nodes.view()) |
| 36 | + , rr_graph_(rr_graph) |
| 37 | + , rr_rc_data_(rr_rc_data.data(), rr_rc_data.size()) |
| 38 | + , rr_switch_inf_(rr_switch_inf.data(), rr_switch_inf.size()) |
| 39 | + , net_terminal_groups(g_vpr_ctx.routing().net_terminal_groups) |
| 40 | + , net_terminal_group_num(g_vpr_ctx.routing().net_terminal_group_num) |
| 41 | + , rr_node_route_inf_(rr_node_route_inf) |
| 42 | + , is_flat_(is_flat) |
| 43 | + , router_stats_(nullptr) |
| 44 | + , router_debug_(false) |
| 45 | + , path_search_cumulative_time(0) { |
| 46 | + heap_.init_heap(grid); |
| 47 | + only_opin_inter_layer = (grid.get_num_layers() > 1) && inter_layer_connections_limited_to_opin(*rr_graph); |
| 48 | + } |
| 49 | + |
| 50 | + virtual ~ConnectionRouter() {} |
| 51 | + |
| 52 | + // Clear's the modified list. Should be called after reset_path_costs |
| 53 | + // have been called. |
| 54 | + virtual void clear_modified_rr_node_info() = 0; |
| 55 | + |
| 56 | + // Reset modified data in rr_node_route_inf based on modified_rr_node_inf. |
| 57 | + virtual void reset_path_costs() = 0; |
| 58 | + |
| 59 | + /** Finds a path from the route tree rooted at rt_root to sink_node. |
| 60 | + * This is used when you want to allow previous routing of the same net to |
| 61 | + * serve as valid start locations for the current connection. |
| 62 | + * |
| 63 | + * Returns a tuple of: |
| 64 | + * bool: path exists? (hard failure, rr graph disconnected) |
| 65 | + * bool: should retry with full bounding box? (only used in parallel routing) |
| 66 | + * RTExploredNode: the explored sink node, from which the cheapest path can be found via back-tracing */ |
| 67 | + std::tuple<bool, bool, RTExploredNode> timing_driven_route_connection_from_route_tree( |
| 68 | + const RouteTreeNode& rt_root, |
| 69 | + RRNodeId sink_node, |
| 70 | + const t_conn_cost_params& cost_params, |
| 71 | + const t_bb& bounding_box, |
| 72 | + RouterStats& router_stats, |
| 73 | + const ConnectionParameters& conn_params) final; |
| 74 | + |
| 75 | + /** Finds a path from the route tree rooted at rt_root to sink_node for a |
| 76 | + * high fanout net. |
| 77 | + * |
| 78 | + * Unlike timing_driven_route_connection_from_route_tree(), only part of |
| 79 | + * the route tree which is spatially close to the sink is added to the heap. |
| 80 | + * |
| 81 | + * Returns a tuple of: |
| 82 | + * bool: path exists? (hard failure, rr graph disconnected) |
| 83 | + * bool: should retry with full bounding box? (only used in parallel routing) |
| 84 | + * RTExploredNode: the explored sink node, from which the cheapest path can be found via back-tracing */ |
| 85 | + std::tuple<bool, bool, RTExploredNode> timing_driven_route_connection_from_route_tree_high_fanout( |
| 86 | + const RouteTreeNode& rt_root, |
| 87 | + RRNodeId sink_node, |
| 88 | + const t_conn_cost_params& cost_params, |
| 89 | + const t_bb& net_bounding_box, |
| 90 | + const SpatialRouteTreeLookup& spatial_rt_lookup, |
| 91 | + RouterStats& router_stats, |
| 92 | + const ConnectionParameters& conn_params) final; |
| 93 | + |
| 94 | + // Finds a path from the route tree rooted at rt_root to all sinks |
| 95 | + // available. |
| 96 | + // |
| 97 | + // Each element of the returned vector is a reachable sink. |
| 98 | + // |
| 99 | + // If cost_params.astar_fac is set to 0, this effectively becomes |
| 100 | + // Dijkstra's algorithm with a modified exit condition (runs until heap is |
| 101 | + // empty). When using cost_params.astar_fac = 0, for efficiency the |
| 102 | + // RouterLookahead used should be the NoOpLookahead. |
| 103 | + // |
| 104 | + // Note: This routine is currently used only to generate information that |
| 105 | + // may be helpful in debugging an architecture. |
| 106 | + virtual vtr::vector<RRNodeId, RTExploredNode> timing_driven_find_all_shortest_paths_from_route_tree( |
| 107 | + const RouteTreeNode& rt_root, |
| 108 | + const t_conn_cost_params& cost_params, |
| 109 | + const t_bb& bounding_box, |
| 110 | + RouterStats& router_stats, |
| 111 | + const ConnectionParameters& conn_params) = 0; |
| 112 | + |
| 113 | + void set_router_debug(bool router_debug) final { |
| 114 | + router_debug_ = router_debug; |
| 115 | + } |
| 116 | + |
| 117 | + // Empty the route tree set used for RCV node detection |
| 118 | + // Will return if RCV is disabled |
| 119 | + // Called after each net is finished routing to flush the set |
| 120 | + void empty_rcv_route_tree_set() final; |
| 121 | + |
| 122 | + // Enable or disable RCV in connection router |
| 123 | + // Enabling this will utilize extra path structures, as well as the RCV cost function |
| 124 | + // |
| 125 | + // Ensure route budgets have been calculated before enabling this |
| 126 | + virtual void set_rcv_enabled(bool enable) = 0; |
| 127 | + |
| 128 | + protected: |
| 129 | + /** Common logic from timing_driven_route_connection_from_route_tree and |
| 130 | + * timing_driven_route_connection_from_route_tree_high_fanout for running |
| 131 | + * the connection router. |
| 132 | + * @param[in] rt_root RouteTreeNode describing the current routing state |
| 133 | + * @param[in] sink_node Sink node ID to route to |
| 134 | + * @param[in] cost_params |
| 135 | + * @param[in] bounding_box Keep search confined to this bounding box |
| 136 | + * @return bool Signal to retry this connection with a full-device bounding box */ |
| 137 | + bool timing_driven_route_connection_common_setup( |
| 138 | + const RouteTreeNode& rt_root, |
| 139 | + RRNodeId sink_node, |
| 140 | + const t_conn_cost_params& cost_params, |
| 141 | + const t_bb& bounding_box); |
| 142 | + |
| 143 | + // Finds a path to sink_node, starting from the elements currently in the |
| 144 | + // heap. |
| 145 | + // |
| 146 | + // If the path is not found, which means that the path_cost of sink_node in |
| 147 | + // RR node route info has never been updated, `rr_node_route_inf_[sink_node] |
| 148 | + // .path_cost` will be the initial value (i.e., float infinity). This case |
| 149 | + // can be detected by `std::isinf(rr_node_route_inf_[sink_node].path_cost)`. |
| 150 | + // |
| 151 | + // This is the core maze routing routine. |
| 152 | + // |
| 153 | + // Note: For understanding the connection router, start here. |
| 154 | + void timing_driven_route_connection_from_heap( |
| 155 | + RRNodeId sink_node, |
| 156 | + const t_conn_cost_params& cost_params, |
| 157 | + const t_bb& bounding_box); |
| 158 | + |
| 159 | + // Find the shortest path from current heap to the sink node in the RR graph |
| 160 | + virtual void timing_driven_find_single_shortest_path_from_heap(RRNodeId sink_node, |
| 161 | + const t_conn_cost_params& cost_params, |
| 162 | + const t_bb& bounding_box, |
| 163 | + const t_bb& target_bb) = 0; |
| 164 | + |
| 165 | + // Find paths from current heap to all nodes in the RR graph |
| 166 | + virtual vtr::vector<RRNodeId, RTExploredNode> timing_driven_find_all_shortest_paths_from_heap( |
| 167 | + const t_conn_cost_params& cost_params, |
| 168 | + const t_bb& bounding_box) = 0; |
| 169 | + |
| 170 | + //Unconditionally adds rt_node to the heap |
| 171 | + // |
| 172 | + //Note that if you want to respect rt_node->re_expand that is the caller's |
| 173 | + //responsibility. |
| 174 | + virtual void add_route_tree_node_to_heap( |
| 175 | + const RouteTreeNode& rt_node, |
| 176 | + RRNodeId target_node, |
| 177 | + const t_conn_cost_params& cost_params, |
| 178 | + const t_bb& net_bb) = 0; |
| 179 | + |
| 180 | + // Calculates the cost of reaching to_node |
| 181 | + void evaluate_timing_driven_node_costs( |
| 182 | + RTExploredNode* to, |
| 183 | + const t_conn_cost_params& cost_params, |
| 184 | + RRNodeId from_node, |
| 185 | + RRNodeId target_node); |
| 186 | + |
| 187 | + // Evaluate node costs using the RCV algorith |
| 188 | + float compute_node_cost_using_rcv(const t_conn_cost_params cost_params, |
| 189 | + RRNodeId to_node, |
| 190 | + RRNodeId target_node, |
| 191 | + float backwards_delay, |
| 192 | + float backwards_cong, |
| 193 | + float R_upstream); |
| 194 | + |
| 195 | + //Adds the route tree rooted at rt_node to the heap, preparing it to be |
| 196 | + //used as branch-points for further routing. |
| 197 | + void add_route_tree_to_heap(const RouteTreeNode& rt_node, |
| 198 | + RRNodeId target_node, |
| 199 | + const t_conn_cost_params& cost_params, |
| 200 | + const t_bb& net_bb); |
| 201 | + |
| 202 | + t_bb add_high_fanout_route_tree_to_heap( |
| 203 | + const RouteTreeNode& rt_root, |
| 204 | + RRNodeId target_node, |
| 205 | + const t_conn_cost_params& cost_params, |
| 206 | + const SpatialRouteTreeLookup& spatial_route_tree_lookup, |
| 207 | + const t_bb& net_bounding_box); |
| 208 | + |
| 209 | + const DeviceGrid& grid_; |
| 210 | + const RouterLookahead& router_lookahead_; |
| 211 | + const t_rr_graph_view rr_nodes_; |
| 212 | + const RRGraphView* rr_graph_; |
| 213 | + vtr::array_view<const t_rr_rc_data> rr_rc_data_; |
| 214 | + vtr::array_view<const t_rr_switch_inf> rr_switch_inf_; |
| 215 | + const vtr::vector<ParentNetId, std::vector<std::vector<int>>>& net_terminal_groups; |
| 216 | + const vtr::vector<ParentNetId, std::vector<int>>& net_terminal_group_num; |
| 217 | + vtr::vector<RRNodeId, t_rr_node_route_inf>& rr_node_route_inf_; |
| 218 | + bool is_flat_; |
| 219 | + std::vector<RRNodeId> modified_rr_node_inf_; |
| 220 | + RouterStats* router_stats_; |
| 221 | + const ConnectionParameters* conn_params_; |
| 222 | + HeapImplementation heap_; |
| 223 | + bool router_debug_; |
| 224 | + |
| 225 | + bool only_opin_inter_layer; |
| 226 | + |
| 227 | + // Cumulative time spent in the path search part of the connection router. |
| 228 | + std::chrono::microseconds path_search_cumulative_time; |
| 229 | + |
| 230 | + // The path manager for RCV, keeps track of the route tree as a set, also |
| 231 | + // manages the allocation of `rcv_path_data`. |
| 232 | + PathManager rcv_path_manager; |
| 233 | + vtr::vector<RRNodeId, t_heap_path*> rcv_path_data; |
| 234 | +}; |
| 235 | + |
| 236 | +#include "connection_router.tpp" |
| 237 | + |
| 238 | +#endif /* _CONNECTION_ROUTER_H */ |
0 commit comments