diff --git a/vpr/src/route/lookahead_profiler.cpp b/vpr/src/route/lookahead_profiler.cpp index e9a302e303f..a5d1c873e6a 100644 --- a/vpr/src/route/lookahead_profiler.cpp +++ b/vpr/src/route/lookahead_profiler.cpp @@ -3,23 +3,14 @@ // #include -#include "lookahead_profiler.h" -#include "vtr_error.h" -#include "vtr_log.h" + #include "globals.h" +#include "lookahead_profiler.h" +#include "re_cluster_util.h" #include "router_lookahead_map_utils.h" #include "vpr_utils.h" -#include "re_cluster_util.h" - -LookaheadProfiler::LookaheadProfiler() - : is_empty(true) { - lookahead_verifier_csv.open("lookahead_verifier_info.csv", std::ios::out); - - if (!lookahead_verifier_csv.is_open()) { - VTR_LOG_WARN("Could not open lookahead_verifier_info.csv"); - return; - } -} +#include "vtr_error.h" +#include "vtr_log.h" void LookaheadProfiler::record(int iteration, int target_net_pin_index, @@ -32,10 +23,14 @@ void LookaheadProfiler::record(int iteration, const auto& rr_graph = device_ctx.rr_graph; auto& route_ctx = g_vpr_ctx.routing(); - if (!lookahead_verifier_csv.is_open()) - return; - + // If csv file hasn't been opened, open it and write out column headers if (is_empty) { + lookahead_verifier_csv.open("lookahead_verifier_info.csv", std::ios::out); + + if (!lookahead_verifier_csv.is_open()) { + VTR_LOG_ERROR("Could not open lookahead_verifier_info.csv", "error"); + } + lookahead_verifier_csv << "iteration no." << ",source node" @@ -63,72 +58,96 @@ void LookaheadProfiler::record(int iteration, is_empty = false; } + if (!lookahead_verifier_csv.is_open()) + return; + + // The default value in RouteTree::update_from_heap() is -1; only calls which descend from route_net() + // pass in an iteration value, which is the only context in which we want to profile. if (iteration < 1) return; - 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]; + RRNodeId source_inode = branch_inodes.back(); + RRNodeId sink_inode = branch_inodes.front(); - 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; + VTR_ASSERT(rr_graph.node_type(source_inode) == SOURCE); + VTR_ASSERT(rr_graph.node_type(sink_inode) == SINK); - 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; + /* Get sink node attributes (atom block name, atom block model, cluster type, tile dimensions) */ - auto [from_x, from_y] = util::get_adjusted_rr_position(curr_inode); - auto [to_x, to_y] = util::get_adjusted_rr_position(sink_inode); + 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)); - int delta_x = to_x - from_x; - int delta_y = to_y - from_y; + 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; - 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; + ClusterBlockId cluster_block_id = atom_to_cluster(atom_block_id); - 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); + 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_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] = {"--", "--"}; + } + } - 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)); + 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()); - 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; + 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]; - ClusterBlockId cluster_block_id = atom_to_cluster(atom_block_id); + /* Iterate through the given path and record information for each node */ + for (size_t i = 2; i < branch_inodes.size(); ++i) { // Distance one node away is always 0. (IPIN->SINK) + RRNodeId curr_inode = branch_inodes[i]; - cluster_block_types[sink_inode] = g_vpr_ctx.clustering().clb_nlist.block_type(cluster_block_id)->name; + // Get backwards path cost, delay, and congestion from sink node + t_rr_node_route_inf sink_node_info = route_ctx.rr_node_route_inf[sink_inode]; + float total_backward_cost = sink_node_info.backward_path_cost; + float total_backward_delay = sink_node_info.backward_path_delay; + float total_backward_congestion = sink_node_info.backward_path_congestion; + + // Get backwards path cost, delay, and congestion from current node + t_rr_node_route_inf curr_node_info = route_ctx.rr_node_route_inf[curr_inode]; + float current_backward_cost = curr_node_info.backward_path_cost; + float current_backward_delay = curr_node_info.backward_path_delay; + float current_backward_congestion = curr_node_info.backward_path_congestion; + + // Get the difference in the coordinates in the current and sink nodes. + // Note: we are not using util::get_xy_deltas() because this always gives positive values + // unless the current node is the source node. Using util::get_adjusted_rr_position therefore + // gives us more information. + auto [from_x, from_y] = util::get_adjusted_rr_position(curr_inode); + auto [to_x, to_y] = util::get_adjusted_rr_position(sink_inode); - 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] = {"--", "--"}; - } - } + int delta_x = to_x - from_x; + int delta_y = to_y - from_y; - 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()); + // Calculate the actual cost, delay, and congestion from the current node to the sink. + float actual_cost = total_backward_cost - current_backward_cost; + float actual_delay = total_backward_delay - current_backward_delay; + float actual_congestion = total_backward_congestion - current_backward_congestion; - 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]; + // Get the cost, delay, and congestion estimates made by the lookahead. + // Note: lookahead_cost = lookahead_delay * criticality + lookahead_congestion * (1. - criticality) + 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); + // Get the current node's type and length 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)) : "--"; + /* Write out all info */ + lookahead_verifier_csv << iteration << ","; // iteration no. lookahead_verifier_csv << source_inode << ","; // source node lookahead_verifier_csv << sink_inode << ","; // sink node @@ -143,9 +162,9 @@ void LookaheadProfiler::record(int iteration, 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 << actual_cost << ","; // actual cost + lookahead_verifier_csv << actual_delay << ","; // actual delay + lookahead_verifier_csv << actual_congestion << ","; // actual congestion lookahead_verifier_csv << lookahead_cost << ","; // predicted cost lookahead_verifier_csv << lookahead_delay << ","; // predicted delay lookahead_verifier_csv << lookahead_congestion << ","; // predicted congestion diff --git a/vpr/src/route/lookahead_profiler.h b/vpr/src/route/lookahead_profiler.h index 8d1c6c0e3f9..82467996db1 100644 --- a/vpr/src/route/lookahead_profiler.h +++ b/vpr/src/route/lookahead_profiler.h @@ -3,14 +3,35 @@ #include #include -#include "rr_graph_fwd.h" + #include "connection_router_interface.h" #include "router_lookahead.h" +#include "rr_graph_fwd.h" +/** + * @brief A class which records information used to profile the router lookahead: most importantly, + * the actual cost (delay and congestion) from nodes to the sink to which they have been routed, as + * well as the lookahead's estimation of this cost. + */ class LookaheadProfiler { public: - LookaheadProfiler(); + LookaheadProfiler() + : is_empty(true) {} + /** + * @brief Record information on nodes on a path from a source to a sink. + * + * @param iteration The router iteration. + * @param target_net_pin_index Target pin of this sink in the net. + * @param cost_params + * @param router_lookahead + * @param net_id + * @param net_list + * @param branch_inodes A path from a sink to its source, as a vector of nodes. + * + * @warning + * branch_inodes must be a backwards path, from a sink node to a source node. + */ void record(int iteration, int target_net_pin_index, const t_conn_cost_params& cost_params, @@ -20,11 +41,17 @@ class LookaheadProfiler { std::vector branch_inodes); private: + ///@breif The output filestream. std::ofstream lookahead_verifier_csv; + ///@brief Whether the output file is empty/not yet opened. bool is_empty; + ///@brief A map from sink node IDs to the names of their atom blocks. std::unordered_map atom_block_names; + ///@brief A map from sink node IDs to the names of the models of their atom blocks. std::unordered_map atom_block_models; + ///@brief A map from sink node IDs to the names of the types of their clusters. std::unordered_map cluster_block_types; + ///@brief A map from sink node IDs to the dimensions of their tiles (width, height). std::unordered_map> tile_dimensions; };