diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 376a5c6e01e..62d566f3837 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -37,6 +37,7 @@ #ifndef NO_SERVER #include "gateio.h" +# include "lookahead_profiler.h" #include "taskresolver.h" class SetupHoldTimingInfo; @@ -496,6 +497,8 @@ struct RoutingContext : public Context { * @brief User specified routing constraints */ UserRouteConstraints constraints; + + LookaheadProfiler lookahead_profiler; }; /** diff --git a/vpr/src/route/connection_router.cpp b/vpr/src/route/connection_router.cpp index 7978bb0106b..07e6539557e 100644 --- a/vpr/src/route/connection_router.cpp +++ b/vpr/src/route/connection_router.cpp @@ -660,7 +660,8 @@ float ConnectionRouter::compute_node_cost_using_rcv(const t_conn_cost_para const t_conn_delay_budget* delay_budget = cost_params.delay_budget; // TODO: This function is not tested for is_flat == true VTR_ASSERT(is_flat_ != true); - std::tie(expected_delay, expected_cong) = router_lookahead_.get_expected_delay_and_cong(to_node, target_node, cost_params, R_upstream, false); + std::tie(expected_delay, expected_cong) = router_lookahead_.get_expected_delay_and_cong(to_node, target_node, cost_params, R_upstream); + router_lookahead_.scale_delay_and_cong_by_criticality(expected_delay, expected_cong, cost_params); float expected_total_delay_cost; float expected_total_cong_cost; diff --git a/vpr/src/route/lookahead_profiler.cpp b/vpr/src/route/lookahead_profiler.cpp index d7cb90a6dd2..a172ed10438 100644 --- a/vpr/src/route/lookahead_profiler.cpp +++ b/vpr/src/route/lookahead_profiler.cpp @@ -11,8 +11,6 @@ #include "vpr_utils.h" #include "re_cluster_util.h" -LookaheadProfiler lookahead_profiler = LookaheadProfiler(); - LookaheadProfiler::LookaheadProfiler() { lookahead_verifier_csv.open("lookahead_verifier_info.csv", std::ios::out); @@ -45,136 +43,104 @@ LookaheadProfiler::LookaheadProfiler() { << std::endl; } -void LookaheadProfiler::record(const int iteration, - const int target_net_pin_index, - const RRNodeId source_inode, - const RRNodeId sink_inode, - const RRNodeId curr_inode, - const size_t nodes_from_sink, +void LookaheadProfiler::record(int iteration, + int target_net_pin_index, const t_conn_cost_params& cost_params, const RouterLookahead& router_lookahead, const ParentNetId& net_id, - const Netlist<>& net_list) { + const Netlist<>& net_list, + std::vector branch_inodes) { auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; auto& route_ctx = g_vpr_ctx.routing(); - float total_backward_cost = route_ctx.rr_node_route_inf[sink_inode].backward_path_cost; - float total_backward_delay = route_ctx.rr_node_route_inf[sink_inode].backward_path_delay; - float total_backward_congestion = route_ctx.rr_node_route_inf[sink_inode].backward_path_congestion; + if (iteration < 1) + return; - auto current_node = route_ctx.rr_node_route_inf[curr_inode]; - float current_backward_cost = current_node.backward_path_cost; - float current_backward_delay = current_node.backward_path_delay; - float current_backward_congestion = current_node.backward_path_congestion; + for (size_t i = 2; i < branch_inodes.size(); ++i) { /* Distance one node away is always 0.0 (IPIN->SINK) */ + RRNodeId source_inode = branch_inodes.back(); + RRNodeId sink_inode = branch_inodes.front(); + RRNodeId curr_inode = branch_inodes[i]; - auto [from_x, from_y] = util::get_adjusted_rr_position(curr_inode); - auto [to_x, to_y] = util::get_adjusted_rr_position(sink_inode); + float total_backward_cost = route_ctx.rr_node_route_inf[sink_inode].backward_path_cost; + float total_backward_delay = route_ctx.rr_node_route_inf[sink_inode].backward_path_delay; + float total_backward_congestion = route_ctx.rr_node_route_inf[sink_inode].backward_path_congestion; - int delta_x = to_x - from_x; - int delta_y = to_y - from_y; + auto current_node = route_ctx.rr_node_route_inf[curr_inode]; + float current_backward_cost = current_node.backward_path_cost; + float current_backward_delay = current_node.backward_path_delay; + float current_backward_congestion = current_node.backward_path_congestion; - float djikstra_cost = total_backward_cost - current_backward_cost; - float djikstra_delay = total_backward_delay - current_backward_delay; - float djikstra_congestion = total_backward_congestion - current_backward_congestion; + auto [from_x, from_y] = util::get_adjusted_rr_position(curr_inode); + auto [to_x, to_y] = util::get_adjusted_rr_position(sink_inode); - float lookahead_cost = router_lookahead.get_expected_cost(curr_inode, sink_inode, cost_params, - 0.0); - float lookahead_delay, lookahead_congestion; - std::tie(lookahead_delay, lookahead_congestion) = router_lookahead.get_expected_delay_and_cong(curr_inode, sink_inode, cost_params, 0.0, true); + int delta_x = to_x - from_x; + int delta_y = to_y - from_y; - std::string block_name = "--"; - std::string atom_block_model = "--"; - std::string cluster_block_type = "--"; - std::string tile_height = "--"; - std::string tile_width = "--"; + float djikstra_cost = total_backward_cost - current_backward_cost; + float djikstra_delay = total_backward_delay - current_backward_delay; + float djikstra_congestion = total_backward_congestion - current_backward_congestion; - if (atom_block_names.find(sink_inode) != atom_block_names.end()) { - VTR_ASSERT_SAFE(atom_block_models.find(sink_inode) != atom_block_models.end()); - VTR_ASSERT_SAFE(cluster_block_types.find(sink_inode) != cluster_block_types.end()); - VTR_ASSERT_SAFE(tile_dimensions.find(sink_inode) != tile_dimensions.end()); + float lookahead_cost = router_lookahead.get_expected_cost(curr_inode, sink_inode, cost_params, 0.0); + auto [lookahead_delay, lookahead_congestion] = router_lookahead.get_expected_delay_and_cong(curr_inode, sink_inode, cost_params, 0.0); - block_name = atom_block_names[sink_inode]; - atom_block_model = atom_block_models[sink_inode]; - cluster_block_type = cluster_block_types[sink_inode]; - std::tie(tile_width, tile_height) = tile_dimensions[sink_inode]; - } else { - if (net_id != ParentNetId::INVALID() && target_net_pin_index != OPEN) { - block_name = net_list.block_name(net_list.net_pin_block(net_id, target_net_pin_index)); + if (atom_block_names.find(sink_inode) == atom_block_names.end()) { + if (net_id != ParentNetId::INVALID() && target_net_pin_index != OPEN) { + atom_block_names[sink_inode] = net_list.block_name(net_list.net_pin_block(net_id, target_net_pin_index)); - AtomBlockId atom_block_id = g_vpr_ctx.atom().nlist.find_block(block_name); - atom_block_model = g_vpr_ctx.atom().nlist.block_model(atom_block_id)->name; + AtomBlockId atom_block_id = g_vpr_ctx.atom().nlist.find_block(atom_block_names[sink_inode]); + atom_block_models[sink_inode] = g_vpr_ctx.atom().nlist.block_model(atom_block_id)->name; - ClusterBlockId cluster_block_id = atom_to_cluster(atom_block_id); + ClusterBlockId cluster_block_id = atom_to_cluster(atom_block_id); - cluster_block_type = g_vpr_ctx.clustering().clb_nlist.block_type(cluster_block_id)->name; + cluster_block_types[sink_inode] = g_vpr_ctx.clustering().clb_nlist.block_type(cluster_block_id)->name; - auto tile_type = physical_tile_type(cluster_block_id); - tile_height = std::to_string(tile_type->height); - tile_width = std::to_string(tile_type->width); + auto tile_type = physical_tile_type(cluster_block_id); + tile_dimensions[sink_inode] = std::pair(std::to_string(tile_type->width), std::to_string(tile_type->height)); + } else { + atom_block_names[sink_inode] = "--"; + atom_block_models[sink_inode] = "--"; + cluster_block_types[sink_inode] = "--"; + tile_dimensions[sink_inode] = {"--", "--"}; + } } - atom_block_names[sink_inode] = block_name; - atom_block_models[sink_inode] = atom_block_model; - cluster_block_types[sink_inode] = cluster_block_type; - tile_dimensions[sink_inode] = {tile_width, tile_height}; - } + VTR_ASSERT_SAFE(atom_block_names.find(sink_inode) != atom_block_names.end()); + VTR_ASSERT_SAFE(atom_block_models.find(sink_inode) != atom_block_models.end()); + VTR_ASSERT_SAFE(cluster_block_types.find(sink_inode) != cluster_block_types.end()); + VTR_ASSERT_SAFE(tile_dimensions.find(sink_inode) != tile_dimensions.end()); - auto node_type = rr_graph.node_type(curr_inode); - std::string node_type_str; - std::string node_length; - - switch (node_type) { - case SOURCE: - node_type_str = "SOURCE"; - node_length = "--"; - break; - case SINK: - node_type_str = "SINK"; - node_length = "--"; - break; - case IPIN: - node_type_str = "IPIN"; - node_length = "--"; - break; - case OPIN: - node_type_str = "OPIN"; - node_length = "--"; - break; - case CHANX: - node_type_str = "CHANX"; - node_length = std::to_string(rr_graph.node_length(curr_inode)); - break; - case CHANY: - node_type_str = "CHANY"; - node_length = std::to_string(rr_graph.node_length(curr_inode)); - break; - default: - node_type_str = "--"; - node_length = "--"; - break; + std::string block_name = atom_block_names[sink_inode]; + std::string atom_block_model = atom_block_models[sink_inode]; + std::string cluster_block_type = cluster_block_types[sink_inode]; + auto [tile_width, tile_height] = tile_dimensions[sink_inode]; + + std::string node_type_str = rr_graph.node_type_string(curr_inode); + std::string node_length = (node_type_str == "CHANX" || node_type_str == "CHANX") + ? std::to_string(rr_graph.node_length(curr_inode)) + : "--"; + + lookahead_verifier_csv << iteration << ","; // iteration no. + lookahead_verifier_csv << source_inode << ","; // source node + lookahead_verifier_csv << sink_inode << ","; // sink node + lookahead_verifier_csv << block_name << ","; // sink block name + lookahead_verifier_csv << atom_block_model << ","; // sink atom block model + lookahead_verifier_csv << cluster_block_type << ","; // sink cluster block type + lookahead_verifier_csv << tile_height << ","; // sink cluster tile height + lookahead_verifier_csv << tile_width << ","; // sink cluster tile width + lookahead_verifier_csv << curr_inode << ","; // current node + lookahead_verifier_csv << node_type_str << ","; // node type + lookahead_verifier_csv << node_length << ","; // node length + lookahead_verifier_csv << i << ","; // num. nodes from sink + lookahead_verifier_csv << delta_x << ","; // delta x + lookahead_verifier_csv << delta_y << ","; // delta y + lookahead_verifier_csv << djikstra_cost << ","; // actual cost + lookahead_verifier_csv << djikstra_delay << ","; // actual delay + lookahead_verifier_csv << djikstra_congestion << ","; // actual congestion + lookahead_verifier_csv << lookahead_cost << ","; // predicted cost + lookahead_verifier_csv << lookahead_delay << ","; // predicted delay + lookahead_verifier_csv << lookahead_congestion << ","; // predicted congestion + lookahead_verifier_csv << cost_params.criticality; // criticality + lookahead_verifier_csv << std::endl; } - - lookahead_verifier_csv << iteration << ","; // iteration no. - lookahead_verifier_csv << source_inode << ","; // source node - lookahead_verifier_csv << sink_inode << ","; // sink node - lookahead_verifier_csv << block_name << ","; // sink block name - lookahead_verifier_csv << atom_block_model << ","; // sink atom block model - lookahead_verifier_csv << cluster_block_type << ","; // sink cluster block type - lookahead_verifier_csv << tile_height << ","; // sink cluster tile height - lookahead_verifier_csv << tile_width << ","; // sink cluster tile width - lookahead_verifier_csv << curr_inode << ","; // current node - lookahead_verifier_csv << node_type_str << ","; // node type - lookahead_verifier_csv << node_length << ","; // node length - lookahead_verifier_csv << nodes_from_sink << ","; // num. nodes from sink - lookahead_verifier_csv << delta_x << ","; // delta x - lookahead_verifier_csv << delta_y << ","; // delta y - lookahead_verifier_csv << djikstra_cost << ","; // actual cost - lookahead_verifier_csv << djikstra_delay << ","; // actual delay - lookahead_verifier_csv << djikstra_congestion << ","; // actual congestion - lookahead_verifier_csv << lookahead_cost << ","; // predicted cost - lookahead_verifier_csv << lookahead_delay << ","; // predicted delay - lookahead_verifier_csv << lookahead_congestion << ","; // predicted congestion - lookahead_verifier_csv << cost_params.criticality; // criticality - lookahead_verifier_csv << std::endl; } \ No newline at end of file diff --git a/vpr/src/route/lookahead_profiler.h b/vpr/src/route/lookahead_profiler.h index 2e079db8eb0..6a75632ced0 100644 --- a/vpr/src/route/lookahead_profiler.h +++ b/vpr/src/route/lookahead_profiler.h @@ -15,16 +15,7 @@ class LookaheadProfiler { public: LookaheadProfiler(); - void record(int iteration, - int target_net_pin_index, - RRNodeId source_inode, - RRNodeId sink_inode, - RRNodeId curr_inode, - size_t nodes_from_sink, - const t_conn_cost_params& cost_params, - const RouterLookahead& router_lookahead, - const ParentNetId& net_id, - const Netlist<>& net_list); + void record(int iteration, int target_net_pin_index, const t_conn_cost_params& cost_params, const RouterLookahead& router_lookahead, const ParentNetId& net_id, const Netlist<>& net_list, std::vector branch_inodes); private: std::ofstream lookahead_verifier_csv; @@ -34,6 +25,4 @@ class LookaheadProfiler { std::unordered_map> tile_dimensions; }; -extern LookaheadProfiler lookahead_profiler; - #endif //VTR_LOOKAHEAD_PROFILER_H \ No newline at end of file diff --git a/vpr/src/route/route_tree.cpp b/vpr/src/route/route_tree.cpp index 24caf098034..c56d52184a6 100644 --- a/vpr/src/route/route_tree.cpp +++ b/vpr/src/route/route_tree.cpp @@ -549,23 +549,12 @@ RouteTree::add_subtree_from_heap(t_heap* hptr, int target_net_pin_index, bool is } new_branch_iswitches.push_back(new_iswitch); - /* - * ROUTER LOOKAHEAD VERIFIER - */ - if (itry >= 1) { - for (size_t i = 2; i < new_branch_inodes.size(); ++i) { /* Distance one node away is always 0.0 */ - lookahead_profiler.record(itry, - target_net_pin_index, - new_branch_inodes.back(), - new_branch_inodes.front(), - new_branch_inodes[i], - i, - cost_params, - router_lookahead, - net_id, - net_list); - } - } + g_vpr_ctx.mutable_routing().lookahead_profiler.record(itry, + target_net_pin_index, + cost_params, + router_lookahead, + net_id, + net_list, std::vector()); /* Build the new tree branch starting from the existing node we found */ RouteTreeNode* last_node = _rr_node_to_rt_node[new_inode]; diff --git a/vpr/src/route/router_lookahead.cpp b/vpr/src/route/router_lookahead.cpp index bf5b9a7e7f4..2bf4000361c 100644 --- a/vpr/src/route/router_lookahead.cpp +++ b/vpr/src/route/router_lookahead.cpp @@ -61,13 +61,19 @@ std::unique_ptr make_router_lookahead(const t_det_routing_arch& return router_lookahead; } +void RouterLookahead::scale_delay_and_cong_by_criticality(float& delay, float& cong, const t_conn_cost_params& params) const { + delay *= params.criticality; + cong *= 1. - params.criticality; +} + float ClassicLookahead::get_expected_cost(RRNodeId current_node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const { - auto [delay_cost, cong_cost] = get_expected_delay_and_cong(current_node, target_node, params, R_upstream, false); + auto [delay_cost, cong_cost] = get_expected_delay_and_cong(current_node, target_node, params, R_upstream); + scale_delay_and_cong_by_criticality(delay_cost, cong_cost, params); return delay_cost + cong_cost; } -std::pair ClassicLookahead::get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const { +std::pair ClassicLookahead::get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& /*params*/, float R_upstream) const { auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; @@ -96,11 +102,7 @@ std::pair ClassicLookahead::get_expected_delay_and_cong(RRNodeId n + R_upstream * (num_segs_same_dir * same_data.C_load + num_segs_ortho_dir * ortho_data.C_load) + ipin_data.T_linear; - if (ignore_criticality) { - return std::make_pair(Tdel, cong_cost); - } else { - return std::make_pair(params.criticality * Tdel, (1 - params.criticality) * cong_cost); - } + return std::make_pair(Tdel, cong_cost); } else if (rr_type == IPIN) { /* Change if you're allowing route-throughs */ return std::make_pair(0., device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); @@ -113,7 +115,7 @@ float NoOpLookahead::get_expected_cost(RRNodeId /*current_node*/, RRNodeId /*tar return 0.; } -std::pair NoOpLookahead::get_expected_delay_and_cong(RRNodeId, RRNodeId, const t_conn_cost_params&, float, bool /*ignore_criticality*/) const { +std::pair NoOpLookahead::get_expected_delay_and_cong(RRNodeId, RRNodeId, const t_conn_cost_params&, float) const { return std::make_pair(0., 0.); } diff --git a/vpr/src/route/router_lookahead.h b/vpr/src/route/router_lookahead.h index e37885ebb91..3deff54a312 100644 --- a/vpr/src/route/router_lookahead.h +++ b/vpr/src/route/router_lookahead.h @@ -23,7 +23,8 @@ class RouterLookahead { * @return */ virtual float get_expected_cost(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const = 0; - virtual std::pair get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const = 0; + virtual std::pair get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const = 0; + void scale_delay_and_cong_by_criticality(float& delay, float& cong, const t_conn_cost_params& params) const; /** * @brief Compute router lookahead (if needed) @@ -123,7 +124,7 @@ const RouterLookahead* get_cached_router_lookahead(const t_det_routing_arch& det class ClassicLookahead : public RouterLookahead { public: float get_expected_cost(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const override; - std::pair get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const override; + std::pair get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const override; void compute(const std::vector& /*segment_inf*/) override { } @@ -159,7 +160,7 @@ class ClassicLookahead : public RouterLookahead { class NoOpLookahead : public RouterLookahead { protected: float get_expected_cost(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const override; - std::pair get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const override; + std::pair get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const override; void compute(const std::vector& /*segment_inf*/) override { } diff --git a/vpr/src/route/router_lookahead_compressed_map.cpp b/vpr/src/route/router_lookahead_compressed_map.cpp index 4ac912b4043..e9060cd0425 100644 --- a/vpr/src/route/router_lookahead_compressed_map.cpp +++ b/vpr/src/route/router_lookahead_compressed_map.cpp @@ -412,7 +412,8 @@ float CompressedMapLookahead::get_expected_cost(RRNodeId current_node, RRNodeId if (from_rr_type == CHANX || from_rr_type == CHANY || from_rr_type == SOURCE || from_rr_type == OPIN) { // Get the total cost using the combined delay and congestion costs - std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong(current_node, target_node, params, R_upstream, false); + std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong(current_node, target_node, params, R_upstream); + scale_delay_and_cong_by_criticality(delay_cost, cong_cost, params); return delay_cost + cong_cost; } else if (from_rr_type == IPIN) { /* Change if you're allowing route-throughs */ return (device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); @@ -421,7 +422,7 @@ float CompressedMapLookahead::get_expected_cost(RRNodeId current_node, RRNodeId } } -std::pair CompressedMapLookahead::get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float, bool ignore_criticality) const { +std::pair CompressedMapLookahead::get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float) const { auto& device_ctx = g_vpr_ctx.device(); auto& rr_graph = device_ctx.rr_graph; @@ -455,11 +456,6 @@ std::pair CompressedMapLookahead::get_expected_delay_and_cong(RRNo to_layer_num, get_wire_cost_entry_compressed_lookahead); - if (!ignore_criticality) { - expected_delay_cost *= params.criticality; - expected_cong_cost *= (1 - params.criticality); - } - VTR_ASSERT_SAFE_MSG(std::isfinite(expected_delay_cost), vtr::string_fmt("Lookahead failed to estimate cost from %s: %s", rr_node_arch_name(from_node, is_flat_).c_str(), @@ -470,7 +466,6 @@ std::pair CompressedMapLookahead::get_expected_delay_and_cong(RRNo is_flat_) .c_str()) .c_str()); - } else if (from_type == CHANX || from_type == CHANY) { //When estimating costs from a wire, we directly look-up the result in the wire lookahead (f_wire_cost_map) @@ -499,11 +494,6 @@ std::pair CompressedMapLookahead::get_expected_delay_and_cong(RRNo is_flat_) .c_str()) .c_str()); - - if (!ignore_criticality) { - expected_delay_cost = cost_entry.delay * params.criticality; - expected_cong_cost = cost_entry.congestion * (1 - params.criticality); - } } else if (from_type == IPIN) { /* Change if you're allowing route-throughs */ return std::make_pair(0., device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); } else { /* Change this if you want to investigate route-throughs */ diff --git a/vpr/src/route/router_lookahead_compressed_map.h b/vpr/src/route/router_lookahead_compressed_map.h index 02c45be6e7c..e57e9a27f14 100644 --- a/vpr/src/route/router_lookahead_compressed_map.h +++ b/vpr/src/route/router_lookahead_compressed_map.h @@ -27,7 +27,7 @@ class CompressedMapLookahead : public RouterLookahead { protected: float get_expected_cost(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const override; - std::pair get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const override; + std::pair get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float R_upstream) const override; void compute(const std::vector& segment_inf) override; diff --git a/vpr/src/route/router_lookahead_extended_map.cpp b/vpr/src/route/router_lookahead_extended_map.cpp index 12771de32b5..b0d9fdcaf2a 100644 --- a/vpr/src/route/router_lookahead_extended_map.cpp +++ b/vpr/src/route/router_lookahead_extended_map.cpp @@ -181,7 +181,7 @@ float ExtendedMapLookahead::get_chan_ipin_delays(RRNodeId to_node) const { // // The from_node can be of one of the following types: CHANX, CHANY, SOURCE, OPIN // The to_node is always a SINK -std::pair ExtendedMapLookahead::get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float, bool ignore_criticality) const { +std::pair ExtendedMapLookahead::get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float) const { if (from_node == to_node) { return std::make_pair(0., 0.); } @@ -237,13 +237,8 @@ std::pair ExtendedMapLookahead::get_expected_delay_and_cong(RRNode float site_pin_delay = this->get_chan_ipin_delays(to_node); expected_delay += site_pin_delay; - float expected_delay_cost = expected_delay; - float expected_cong_cost = expected_congestion; - - if (!ignore_criticality) { - expected_delay_cost *= params.criticality; - expected_cong_cost *= 1.0 - params.criticality; - } + float expected_delay_cost = expected_delay * params.criticality; + float expected_cong_cost = expected_congestion * (1. - params.criticality); float expected_cost = expected_delay_cost + expected_cong_cost; @@ -268,7 +263,7 @@ std::pair ExtendedMapLookahead::get_expected_delay_and_cong(RRNode VTR_ASSERT(0); } - return std::make_pair(expected_delay_cost, expected_cong_cost); + return std::make_pair(expected_delay, expected_congestion); } // Adds a best cost routing path from start_node_ind to node_ind to routing costs @@ -598,7 +593,8 @@ float ExtendedMapLookahead::get_expected_cost( float delay_cost, cong_cost; // Get the total cost using the combined delay and congestion costs - std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong(current_node, target_node, params, R_upstream, false); + std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong(current_node, target_node, params, R_upstream); + scale_delay_and_cong_by_criticality(delay_cost, cong_cost, params); return delay_cost + cong_cost; } else if (rr_type == IPIN) { /* Change if you're allowing route-throughs */ // This is to return only the cost between the IPIN and SINK. No need to diff --git a/vpr/src/route/router_lookahead_extended_map.h b/vpr/src/route/router_lookahead_extended_map.h index bd901b874b8..589ea06e6a4 100644 --- a/vpr/src/route/router_lookahead_extended_map.h +++ b/vpr/src/route/router_lookahead_extended_map.h @@ -69,7 +69,7 @@ class ExtendedMapLookahead : public RouterLookahead { /** * @brief Returns a pair of expected delay and congestion */ - std::pair get_expected_delay_and_cong(RRNodeId inode, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const override; + std::pair get_expected_delay_and_cong(RRNodeId inode, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const override; /** * @brief Computes the extended lookahead map diff --git a/vpr/src/route/router_lookahead_map.cpp b/vpr/src/route/router_lookahead_map.cpp index fadb2ad2498..7a71cb09ec9 100644 --- a/vpr/src/route/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead_map.cpp @@ -1,25 +1,25 @@ /* - * The router lookahead provides an estimate of the cost from an intermediate node to the target node - * during directed (A*-like) routing. - * - * The VPR 7.0 lookahead (route/route_timing.c ==> get_timing_driven_expected_cost) lower-bounds the remaining delay and - * congestion by assuming that a minimum number of wires, of the same type as the current node being expanded, can be used - * to complete the route. While this method is efficient, it can run into trouble with architectures that use - * multiple interconnected wire types. - * - * The lookahead in this file performs undirected Dijkstra searches to evaluate many paths through the routing network, - * starting from all the different wire types in the routing architecture. This ensures the lookahead captures the - * effect of inter-wire connectivity. This information is then reduced into a delta_x delta_y based lookup table for - * reach source wire type (f_cost_map). This is used for estimates from CHANX/CHANY -> SINK nodes. See Section 3.2.4 - * in Oleg Petelin's MASc thesis (2016) for more discussion. - * - * To handle estimates starting from SOURCE/OPIN's the lookahead also creates a small side look-up table of the wire types - * which are reachable from each physical tile type's SOURCEs/OPINs (f_src_opin_delays). This is used for - * SRC/OPIN -> CHANX/CHANY estimates. - * - * In the case of SRC/OPIN -> SINK estimates the results from the two look-ups are added together (and the minimum taken - * if there are multiple possibilities). - */ +* The router lookahead provides an estimate of the cost from an intermediate node to the target node +* during directed (A*-like) routing. +* +* The VPR 7.0 lookahead (route/route_timing.c ==> get_timing_driven_expected_cost) lower-bounds the remaining delay and +* congestion by assuming that a minimum number of wires, of the same type as the current node being expanded, can be used +* to complete the route. While this method is efficient, it can run into trouble with architectures that use +* multiple interconnected wire types. +* +* The lookahead in this file performs undirected Dijkstra searches to evaluate many paths through the routing network, +* starting from all the different wire types in the routing architecture. This ensures the lookahead captures the +* effect of inter-wire connectivity. This information is then reduced into a delta_x delta_y based lookup table for +* reach source wire type (f_cost_map). This is used for estimates from CHANX/CHANY -> SINK nodes. See Section 3.2.4 +* in Oleg Petelin's MASc thesis (2016) for more discussion. +* +* To handle estimates starting from SOURCE/OPIN's the lookahead also creates a small side look-up table of the wire types +* which are reachable from each physical tile type's SOURCEs/OPINs (f_src_opin_delays). This is used for +* SRC/OPIN -> CHANX/CHANY estimates. +* +* In the case of SRC/OPIN -> SINK estimates the results from the two look-ups are added together (and the minimum taken +* if there are multiple possibilities). +*/ #include #include @@ -51,8 +51,8 @@ static constexpr int VALID_NEIGHBOR_NUMBER = 3; /* when a list of delay/congestion entries at a coordinate in Cost_Entry is boiled down to a single - * representative entry, this enum is passed-in to specify how that representative entry should be - * calculated */ +* representative entry, this enum is passed-in to specify how that representative entry should be +* calculated */ enum e_representative_entry_method { FIRST = 0, //the first cost that was recorded SMALLEST, //the smallest-delay cost recorded @@ -69,9 +69,9 @@ t_wire_cost_map f_wire_cost_map; /******** File-Scope Functions ********/ /*** - * @brief Fill f_wire_cost_map. It is a look-up table from CHANX/CHANY (to SINKs) for various distances - * @param segment_inf - */ +* @brief Fill f_wire_cost_map. It is a look-up table from CHANX/CHANY (to SINKs) for various distances +* @param segment_inf +*/ static util::Cost_Entry get_wire_cost_entry(e_rr_type rr_type, int seg_index, int from_layer_num, @@ -82,50 +82,50 @@ static util::Cost_Entry get_wire_cost_entry(e_rr_type rr_type, static void compute_router_wire_lookahead(const std::vector& segment_inf); /*** - * @brief Compute the cost from pin to sinks of tiles - Compute the minimum cost to get to each tile sink from pins on the cluster - * @param intra_tile_pin_primitive_pin_delay - * @param tile_min_cost - * @param det_routing_arch - * @param device_ctx - */ +* @brief Compute the cost from pin to sinks of tiles - Compute the minimum cost to get to each tile sink from pins on the cluster +* @param intra_tile_pin_primitive_pin_delay +* @param tile_min_cost +* @param det_routing_arch +* @param device_ctx +*/ static void compute_tiles_lookahead(std::unordered_map& intra_tile_pin_primitive_pin_delay, std::unordered_map>& tile_min_cost, const t_det_routing_arch& det_routing_arch, const DeviceContext& device_ctx); /*** - * @brief Compute the cose from tile pins to tile sinks - * @param intra_tile_pin_primitive_pin_delay [physical_tile_type_idx][from_pin_ptc_num][sink_ptc_num] -> cost - * @param physical_tile - * @param det_routing_arch - * @param delayless_switch - */ +* @brief Compute the cose from tile pins to tile sinks +* @param intra_tile_pin_primitive_pin_delay [physical_tile_type_idx][from_pin_ptc_num][sink_ptc_num] -> cost +* @param physical_tile +* @param det_routing_arch +* @param delayless_switch +*/ static void compute_tile_lookahead(std::unordered_map& intra_tile_pin_primitive_pin_delay, t_physical_tile_type_ptr physical_tile, const t_det_routing_arch& det_routing_arch, const int delayless_switch); /*** - * @brief Compute the minimum cost to get to the sinks from pins on the cluster - * @param tile_min_cost [physical_tile_idx][sink_ptc_num] -> min_cost - * @param physical_tile - * @param intra_tile_pin_primitive_pin_delay [physical_tile_type_idx][from_pin_ptc_num][sink_ptc_num] -> cost - */ +* @brief Compute the minimum cost to get to the sinks from pins on the cluster +* @param tile_min_cost [physical_tile_idx][sink_ptc_num] -> min_cost +* @param physical_tile +* @param intra_tile_pin_primitive_pin_delay [physical_tile_type_idx][from_pin_ptc_num][sink_ptc_num] -> cost +*/ static void store_min_cost_to_sinks(std::unordered_map>& tile_min_cost, t_physical_tile_type_ptr physical_tile, const std::unordered_map& intra_tile_pin_primitive_pin_delay); /** - * @brief Iterate over the first (channel type) and second (segment type) dimensions of f_wire_cost_map to get the minimum cost for each dx and dy_ - * @param internal_opin_global_cost_map This map is populated in this function. [dx][dy] -> cost - */ +* @brief Iterate over the first (channel type) and second (segment type) dimensions of f_wire_cost_map to get the minimum cost for each dx and dy_ +* @param internal_opin_global_cost_map This map is populated in this function. [dx][dy] -> cost +*/ static void min_chann_global_cost_map(vtr::NdMatrix& distance_min_cost); /** - * @brief // Given the src/opin map of each physical tile type, iterate over all OPINs/sources of a type and create - * the minimum cost map across all of them for each tile type. - * @param src_opin_delays - * @param distance_min_cost - */ +* @brief // Given the src/opin map of each physical tile type, iterate over all OPINs/sources of a type and create +* the minimum cost map across all of them for each tile type. +* @param src_opin_delays +* @param distance_min_cost +*/ static void min_opin_distance_cost_map(const util::t_src_opin_delays& src_opin_delays, vtr::NdMatrix& distance_min_cost); // Read the file and fill intra_tile_pin_primitive_pin_delay and tile_min_cost @@ -144,17 +144,17 @@ static void fill_in_missing_lookahead_entries(int segment_index, e_rr_type chan_ static util::Cost_Entry get_nearby_cost_entry(int from_layer_num, int x, int y, int to_layer_num, int segment_index, int chan_index); /** - * @brief Fill in the missing entry in router lookahead map - * If there is a missing entry in the router lookahead, search among its neighbors in a 3x3 window. If there are `VALID_NEIGHBOR_NUMBER` valid entries, - * take the average of them and fill in the missing entry. - * @param from_layer_num The layer num of the source node - * @param missing_dx Dx of the missing input - * @param missing_dy Dy of the missing input - * @param to_layer_num The layer num of the destination point - * @param segment_index The segment index of the source node - * @param chan_index The channel index of the source node - * @return The cost for the missing entry - */ +* @brief Fill in the missing entry in router lookahead map +* If there is a missing entry in the router lookahead, search among its neighbors in a 3x3 window. If there are `VALID_NEIGHBOR_NUMBER` valid entries, +* take the average of them and fill in the missing entry. +* @param from_layer_num The layer num of the source node +* @param missing_dx Dx of the missing input +* @param missing_dy Dy of the missing input +* @param to_layer_num The layer num of the destination point +* @param segment_index The segment index of the source node +* @param chan_index The channel index of the source node +* @return The cost for the missing entry +*/ static util::Cost_Entry get_nearby_cost_entry_average_neighbour(int from_layer_num, int missing_dx, int missing_dy, @@ -175,116 +175,19 @@ float MapLookahead::get_expected_cost(RRNodeId current_node, RRNodeId target_nod VTR_ASSERT_SAFE(rr_graph.node_type(target_node) == t_rr_type::SINK); - if (is_flat_) { - auto [delay_cost, cong_cost] = get_expected_delay_and_cong(current_node, target_node, params, R_upstream, false); + if (is_flat_ || from_rr_type == CHANX || from_rr_type == CHANY || from_rr_type == SOURCE || from_rr_type == OPIN) { + // Get the total cost using the combined delay and congestion costs + auto [delay_cost, cong_cost] = get_expected_delay_and_cong(current_node, target_node, params, R_upstream); + scale_delay_and_cong_by_criticality(delay_cost, cong_cost, params); return delay_cost + cong_cost; - } else { - if (from_rr_type == CHANX || from_rr_type == CHANY || from_rr_type == SOURCE || from_rr_type == OPIN) { - // Get the total cost using the combined delay and congestion costs - auto [delay_cost, cong_cost] = get_expected_delay_and_cong(current_node, target_node, params, R_upstream, false); - return delay_cost + cong_cost; - } else if (from_rr_type == IPIN) { /* Change if you're allowing route-throughs */ - return (device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); - } else { /* Change this if you want to investigate route-throughs */ - return (0.); - } - } -} - -std::pair MapLookahead::get_expected_delay_and_cong_default(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float, bool ignore_criticality) const { - auto& device_ctx = g_vpr_ctx.device(); - auto& rr_graph = device_ctx.rr_graph; - - int from_layer_num = rr_graph.node_layer(from_node); - int to_layer_num = rr_graph.node_layer(to_node); - auto [delta_x, delta_y] = util::get_xy_deltas(from_node, to_node); - delta_x = abs(delta_x); - delta_y = abs(delta_y); - - float expected_delay_cost = std::numeric_limits::infinity(); - float expected_cong_cost = std::numeric_limits::infinity(); - - e_rr_type from_type = rr_graph.node_type(from_node); - if (from_type == SOURCE || from_type == OPIN) { - //When estimating costs from a SOURCE/OPIN we look-up to find which wire types (and the - //cost to reach them) in src_opin_delays. Once we know what wire types are - //reachable, we query the f_wire_cost_map (i.e. the wire lookahead) to get the final - //delay to reach the sink. - - t_physical_tile_type_ptr from_tile_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(from_node), - rr_graph.node_ylow(from_node), - from_layer_num}); - - auto from_tile_index = std::distance(&device_ctx.physical_tile_types[0], from_tile_type); - - auto from_ptc = rr_graph.node_ptc_num(from_node); - - std::tie(expected_delay_cost, expected_cong_cost) = util::get_cost_from_src_opin(src_opin_delays[from_layer_num][from_tile_index][from_ptc][to_layer_num], - delta_x, - delta_y, - to_layer_num, - get_wire_cost_entry); - - if (!ignore_criticality) { - expected_delay_cost *= params.criticality; - expected_cong_cost *= (1 - params.criticality); - } - - VTR_ASSERT_SAFE_MSG(std::isfinite(expected_delay_cost), - vtr::string_fmt("Lookahead failed to estimate cost from %s: %s", - rr_node_arch_name(from_node, is_flat_).c_str(), - describe_rr_node(rr_graph, - device_ctx.grid, - device_ctx.rr_indexed_data, - from_node, - is_flat_) - .c_str()) - .c_str()); - - } else if (from_type == CHANX || from_type == CHANY) { - //When estimating costs from a wire, we directly look-up the result in the wire lookahead (f_wire_cost_map) - - auto from_cost_index = rr_graph.node_cost_index(from_node); - int from_seg_index = device_ctx.rr_indexed_data[from_cost_index].seg_index; - - VTR_ASSERT(from_seg_index >= 0); - - /* now get the expected cost from our lookahead map */ - util::Cost_Entry cost_entry = get_wire_cost_entry(from_type, - from_seg_index, - from_layer_num, - delta_x, - delta_y, - to_layer_num); - - expected_delay_cost = cost_entry.delay; - expected_cong_cost = cost_entry.congestion; - - VTR_ASSERT_SAFE_MSG(std::isfinite(expected_delay_cost), - vtr::string_fmt("Lookahead failed to estimate cost from %s: %s", - rr_node_arch_name(from_node, is_flat_).c_str(), - describe_rr_node(rr_graph, - device_ctx.grid, - device_ctx.rr_indexed_data, - from_node, - is_flat_) - .c_str()) - .c_str()); - - if (!ignore_criticality) { - expected_delay_cost = cost_entry.delay * params.criticality; - expected_cong_cost = cost_entry.congestion * (1 - params.criticality); - } - } else if (from_type == IPIN) { /* Change if you're allowing route-throughs */ - return std::make_pair(0., device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); + } else if (from_rr_type == IPIN) { /* Change if you're allowing route-throughs */ + return (device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); } else { /* Change this if you want to investigate route-throughs */ - return std::make_pair(0., 0.); + return (0.); } - - return std::make_pair(expected_delay_cost, expected_cong_cost); } -std::pair MapLookahead::get_expected_delay_and_cong_flat_router(RRNodeId current_node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const { +std::pair MapLookahead::get_expected_delay_and_cong_flat_router(RRNodeId current_node, RRNodeId target_node) const { auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; @@ -309,34 +212,22 @@ std::pair MapLookahead::get_expected_delay_and_cong_flat_router(RR // We have not checked the multi-layer FPGA for flat routing VTR_ASSERT(rr_graph.node_layer(current_node) == rr_graph.node_layer(target_node)); if (from_rr_type == CHANX || from_rr_type == CHANY) { - std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong_default(current_node, target_node, params, R_upstream, ignore_criticality); + std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong_default(current_node, target_node); // delay_cost and cong_cost only represent the cost to get to the root-level pins. The below offsets are used to represent the intra-cluster cost // of getting to a sink delay_offset_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).delay; cong_offset_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).congestion; - if (!ignore_criticality) { - delay_offset_cost *= params.criticality; - cong_offset_cost *= (1. - params.criticality); - } - return {delay_cost + delay_offset_cost, cong_cost + cong_offset_cost}; } else if (from_rr_type == OPIN) { if (is_inter_cluster_node(rr_graph, current_node)) { // Similar to CHANX and CHANY - std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong_default(current_node, target_node, params, R_upstream, ignore_criticality); + std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong_default(current_node, target_node); delay_offset_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).delay; cong_offset_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).congestion; - - if (!ignore_criticality) { - delay_offset_cost *= params.criticality; - cong_offset_cost *= (1. - params.criticality); - } - return {delay_cost + delay_offset_cost, cong_cost + cong_offset_cost}; - ; } else { if (node_in_same_physical_tile(current_node, target_node)) { delay_offset_cost = 0.; @@ -349,21 +240,10 @@ std::pair MapLookahead::get_expected_delay_and_cong_flat_router(RR // since it does not consider the cost of going outside of the cluster and, then, returning to it. delay_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).delay; cong_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).congestion; - - if (!ignore_criticality) { - delay_cost *= params.criticality; - cong_cost *= (1. - params.criticality); - } - return {delay_cost, cong_cost}; } else { delay_cost = pin_delay_itr->second.delay; cong_cost = pin_delay_itr->second.congestion; - - if (!ignore_criticality) { - delay_cost *= params.criticality; - cong_cost *= (1. - params.criticality); - } } } else { // Since we don't know which type of wires are accessible from an OPIN inside the cluster, we use @@ -377,14 +257,6 @@ std::pair MapLookahead::get_expected_delay_and_cong_flat_router(RR delay_offset_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).delay; cong_offset_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).congestion; - - if (!ignore_criticality) { - delay_cost *= params.criticality; - cong_cost *= (1. - params.criticality); - - delay_offset_cost *= params.criticality; - cong_offset_cost *= (1. - params.criticality); - } } return {delay_cost + delay_offset_cost, cong_cost + cong_offset_cost}; } @@ -399,11 +271,6 @@ std::pair MapLookahead::get_expected_delay_and_cong_flat_router(RR } else { delay_cost = pin_delay_itr->second.delay; cong_cost = pin_delay_itr->second.congestion; - - if (!ignore_criticality) { - delay_cost *= params.criticality; - cong_cost *= (1. - params.criticality); - } } return {delay_cost, cong_cost}; } else if (from_rr_type == SOURCE) { @@ -421,14 +288,6 @@ std::pair MapLookahead::get_expected_delay_and_cong_flat_router(RR delay_offset_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).delay; cong_offset_cost = tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).congestion; - - if (!ignore_criticality) { - delay_cost *= params.criticality; - cong_cost *= (1. - params.criticality); - - delay_offset_cost *= params.criticality; - cong_offset_cost *= (1. - params.criticality); - } } return {delay_cost + delay_offset_cost, cong_cost + cong_offset_cost}; } else { @@ -437,14 +296,95 @@ std::pair MapLookahead::get_expected_delay_and_cong_flat_router(RR } } +std::pair MapLookahead::get_expected_delay_and_cong_default(RRNodeId current_node, RRNodeId target_node) const { + auto& device_ctx = g_vpr_ctx.device(); + auto& rr_graph = device_ctx.rr_graph; + + int from_layer_num = rr_graph.node_layer(current_node); + int to_layer_num = rr_graph.node_layer(current_node); + auto [delta_x, delta_y] = util::get_xy_deltas(current_node, target_node); + delta_x = abs(delta_x); + delta_y = abs(delta_y); + + float expected_delay_cost = std::numeric_limits::infinity(); + float expected_cong_cost = std::numeric_limits::infinity(); + + e_rr_type from_type = rr_graph.node_type(current_node); + if (from_type == SOURCE || from_type == OPIN) { + //When estimating costs from a SOURCE/OPIN we look-up to find which wire types (and the + //cost to reach them) in src_opin_delays. Once we know what wire types are + //reachable, we query the f_wire_cost_map (i.e. the wire lookahead) to get the final + //delay to reach the sink. + + t_physical_tile_type_ptr from_tile_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(current_node), + rr_graph.node_ylow(current_node), + from_layer_num}); + + auto from_tile_index = std::distance(&device_ctx.physical_tile_types[0], from_tile_type); + + auto from_ptc = rr_graph.node_ptc_num(current_node); + + std::tie(expected_delay_cost, expected_cong_cost) = util::get_cost_from_src_opin(src_opin_delays[from_layer_num][from_tile_index][from_ptc][to_layer_num], + delta_x, + delta_y, + to_layer_num, + get_wire_cost_entry); + + VTR_ASSERT_SAFE_MSG(std::isfinite(expected_delay_cost), + vtr::string_fmt("Lookahead failed to estimate cost from %s: %s", + rr_node_arch_name(current_node, is_flat_).c_str(), + describe_rr_node(rr_graph, + device_ctx.grid, + device_ctx.rr_indexed_data, + current_node, + is_flat_) + .c_str()) + .c_str()); + + } else if (from_type == CHANX || from_type == CHANY) { + //When estimating costs from a wire, we directly look-up the result in the wire lookahead (f_wire_cost_map) + + auto from_cost_index = rr_graph.node_cost_index(current_node); + int from_seg_index = device_ctx.rr_indexed_data[from_cost_index].seg_index; + + VTR_ASSERT(from_seg_index >= 0); + + /* now get the expected cost from our lookahead map */ + util::Cost_Entry cost_entry = get_wire_cost_entry(from_type, + from_seg_index, + from_layer_num, + delta_x, + delta_y, + to_layer_num); + + expected_delay_cost = cost_entry.delay; + expected_cong_cost = cost_entry.congestion; + + VTR_ASSERT_SAFE_MSG(std::isfinite(expected_delay_cost), + vtr::string_fmt("Lookahead failed to estimate cost from %s: %s", + rr_node_arch_name(current_node, is_flat_).c_str(), + describe_rr_node(rr_graph, + device_ctx.grid, + device_ctx.rr_indexed_data, + current_node, + is_flat_) + .c_str()) + .c_str()); + } else if (from_type == IPIN) { /* Change if you're allowing route-throughs */ + return std::make_pair(0., device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); + } else { /* Change this if you want to investigate route-throughs */ + return std::make_pair(0., 0.); + } + + return std::make_pair(expected_delay_cost, expected_cong_cost); +} + /******** Function Definitions ********/ /* queries the lookahead_map (should have been computed prior to routing) to get the expected cost - * from the specified source to the specified target */ -std::pair MapLookahead::get_expected_delay_and_cong(RRNodeId current_node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const { - if (is_flat_) - return get_expected_delay_and_cong_flat_router(current_node, target_node, params, R_upstream, ignore_criticality); - else - return get_expected_delay_and_cong_default(current_node, target_node, params, R_upstream, ignore_criticality); +* from the specified source to the specified target */ +std::pair MapLookahead::get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& /*params*/, float /*R_upstream*/) const { + return (is_flat_) ? get_expected_delay_and_cong_flat_router(from_node, to_node) + : get_expected_delay_and_cong_default(from_node, to_node); } void MapLookahead::compute(const std::vector& segment_inf) { @@ -587,11 +527,11 @@ static void compute_router_wire_lookahead(const std::vector& segm } /* boil down the cost list in routing_cost_map at each coordinate to a representative cost entry and store it in the lookahead - * cost map */ + * cost map */ set_lookahead_map_costs(from_layer_num, segment_inf.seg_index, chan_type, routing_cost_map); /* fill in missing entries in the lookahead cost map by copying the closest cost entries (cost map was computed based on - * a reference coordinate > (0,0) so some entries that represent a cross-chip distance have not been computed) */ + * a reference coordinate > (0,0) so some entries that represent a cross-chip distance have not been computed) */ fill_in_missing_lookahead_entries(segment_inf.seg_index, chan_type); } } @@ -645,7 +585,7 @@ static void fill_in_missing_lookahead_entries(int segment_index, e_rr_type chan_ /* returns a cost entry in the f_wire_cost_map that is near the specified coordinates (and preferably towards (0,0)) */ static util::Cost_Entry get_nearby_cost_entry(int from_layer_num, int x, int y, int to_layer_num, int segment_index, int chan_index) { /* compute the slope from x,y to 0,0 and then move towards 0,0 by one unit to get the coordinates - * of the cost entry to be copied */ + * of the cost entry to be copied */ //VTR_ASSERT(x > 0 || y > 0); //Asertion fails in practise. TODO: debug @@ -856,12 +796,12 @@ static void min_chann_global_cost_map(vtr::NdMatrix& distan static void min_opin_distance_cost_map(const util::t_src_opin_delays& src_opin_delays, vtr::NdMatrix& distance_min_cost) { /** - * This function calculates and stores the minimum cost to reach a point on layer `n_sink`, which is `dx` and `dy` further from the current point - * on layer `n_source` and is located on physical tile type `t`. To compute this cost, the function iterates over all output pins of tile `t`, - * and for each pin, iterates over all segment types accessible by it. It then determines and stores the minimum cost to the destination point. - * "src_opin_delays" stores the routing segments accessible by each OPIN of each physical type on each layer. After getting the accessible segment types, - * "get_wire_cost_entry" is called to get the cost from that segment type to the destination point. - */ + * This function calculates and stores the minimum cost to reach a point on layer `n_sink`, which is `dx` and `dy` further from the current point + * on layer `n_source` and is located on physical tile type `t`. To compute this cost, the function iterates over all output pins of tile `t`, + * and for each pin, iterates over all segment types accessible by it. It then determines and stores the minimum cost to the destination point. + * "src_opin_delays" stores the routing segments accessible by each OPIN of each physical type on each layer. After getting the accessible segment types, + * "get_wire_cost_entry" is called to get the cost from that segment type to the destination point. + */ int num_tile_types = g_vpr_ctx.device().physical_tile_types.size(); int num_layers = g_vpr_ctx.device().grid.get_num_layers(); int width = (int)g_vpr_ctx.device().grid.width(); @@ -1150,4 +1090,4 @@ void write_router_lookahead(const std::string& file) { writeMessageToFile(file, &builder); } -#endif +#endif \ No newline at end of file diff --git a/vpr/src/route/router_lookahead_map.h b/vpr/src/route/router_lookahead_map.h index 66e66748639..dc6c224853e 100644 --- a/vpr/src/route/router_lookahead_map.h +++ b/vpr/src/route/router_lookahead_map.h @@ -14,8 +14,8 @@ class MapLookahead : public RouterLookahead { explicit MapLookahead(const t_det_routing_arch& det_routing_arch, bool is_flat); private: - std::pair get_expected_delay_and_cong_default(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const; - std::pair get_expected_delay_and_cong_flat_router(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const; + std::pair get_expected_delay_and_cong_flat_router(RRNodeId current_node, RRNodeId target_node) const; + std::pair get_expected_delay_and_cong_default(RRNodeId current_node, RRNodeId target_node) const; //Look-up table from SOURCE/OPIN to CHANX/CHANY of various types util::t_src_opin_delays src_opin_delays; // Lookup table from a tile pins to the primitive classes inside that tile @@ -31,7 +31,7 @@ class MapLookahead : public RouterLookahead { protected: float get_expected_cost(RRNodeId current_node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const override; - std::pair get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float R_upstream, bool ignore_criticality) const override; + std::pair get_expected_delay_and_cong(RRNodeId from_node, RRNodeId to_node, const t_conn_cost_params& params, float R_upstream) const override; void compute(const std::vector& segment_inf) override; void compute_intra_tile() override; @@ -54,4 +54,4 @@ typedef vtr::NdMatrix t_wire_cost_map; //[0..num_layers][0. // is the layer number that the target node is on. void read_router_lookahead(const std::string& file); -void write_router_lookahead(const std::string& file); +void write_router_lookahead(const std::string& file); \ No newline at end of file