diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index 0ccb375113..62cbb3f590 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -53,9 +53,9 @@ void check_rr_graph(const RRGraphView& rr_graph, const t_chan_width& chan_width, const e_graph_type graph_type, bool is_flat) { - e_route_type route_type = DETAILED; + e_route_type route_type = e_route_type::DETAILED; if (graph_type == e_graph_type::GLOBAL) { - route_type = GLOBAL; + route_type = e_route_type::GLOBAL; } auto total_edges_to_node = std::vector(rr_graph.num_nodes()); @@ -420,7 +420,7 @@ void check_rr_node(const RRGraphView& rr_graph, VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "in check_rr_node: CHANX out of range for endpoints (%d,%d) and (%d,%d)\n", xlow, ylow, xhigh, yhigh); } - if (route_type == GLOBAL && xlow != xhigh) { + if (route_type == e_route_type::GLOBAL && xlow != xhigh) { VPR_ERROR(VPR_ERROR_ROUTE, "in check_rr_node: node %d spans multiple channel segments (not allowed for global routing).\n", inode); } @@ -431,7 +431,7 @@ void check_rr_node(const RRGraphView& rr_graph, VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Error in check_rr_node: CHANY out of range for endpoints (%d,%d) and (%d,%d)\n", xlow, ylow, xhigh, yhigh); } - if (route_type == GLOBAL && ylow != yhigh) { + if (route_type == e_route_type::GLOBAL && ylow != yhigh) { VPR_ERROR(VPR_ERROR_ROUTE, "in check_rr_node: node %d spans multiple channel segments (not allowed for global routing).\n", inode); } @@ -480,7 +480,7 @@ void check_rr_node(const RRGraphView& rr_graph, case e_rr_type::CHANX: case e_rr_type::CHANY: - if (route_type == DETAILED) { + if (route_type == e_route_type::DETAILED) { nodes_per_chan = chan_width.max; tracks_per_node = 1; } else { diff --git a/libs/librrgraph/src/base/rr_graph_type.h b/libs/librrgraph/src/base/rr_graph_type.h index cb4caff72d..da5f83d3c6 100644 --- a/libs/librrgraph/src/base/rr_graph_type.h +++ b/libs/librrgraph/src/base/rr_graph_type.h @@ -13,7 +13,8 @@ struct t_chan_width { std::vector y_list; }; -enum e_route_type { +/// @brief Specifies whether global routing or combined global and detailed routing is performed. +enum class e_route_type { GLOBAL, DETAILED }; diff --git a/libs/librrgraph/src/base/rr_node_types.h b/libs/librrgraph/src/base/rr_node_types.h index a30cb16e48..4df21fdb3d 100644 --- a/libs/librrgraph/src/base/rr_node_types.h +++ b/libs/librrgraph/src/base/rr_node_types.h @@ -103,8 +103,8 @@ typedef vtr::Range edge_idx_range; typedef std::vector> t_arch_switch_fanin; -/* - * Resistance/Capacitance data for an RR Nodes +/** + * @brief Resistance/Capacitance data for an RR Node. * * In practice many RR nodes have the same values, so they are fly-weighted * to keep t_rr_node small. Each RR node holds an rc_index which allows @@ -121,8 +121,8 @@ typedef std::vector> t_arch_switch_fanin; struct t_rr_rc_data { t_rr_rc_data(float Rval, float Cval) noexcept; - float R; - float C; + float R; ///< Resistance to go through an RR node + float C; ///< Total capacitance of an RR node. }; // This is the data type of fast lookups of an rr-node given an (rr_type, layer, x, y, and the side) diff --git a/libs/librrgraph/src/base/rr_rc_data.h b/libs/librrgraph/src/base/rr_rc_data.h index 60a52a98f5..b545deb1c1 100644 --- a/libs/librrgraph/src/base/rr_rc_data.h +++ b/libs/librrgraph/src/base/rr_rc_data.h @@ -2,8 +2,8 @@ #include "rr_node_types.h" -/* - * Returns the index to a t_rr_rc_data matching the specified values. +/** + * @brief Returns the index to a t_rr_rc_data matching the specified values. * * If an existing t_rr_rc_data matches the specified R/C it's index * is returned, otherwise the t_rr_rc_data is created. diff --git a/libs/libvtrutil/src/vtr_assert.h b/libs/libvtrutil/src/vtr_assert.h index f159bc2969..3277cdb8ea 100644 --- a/libs/libvtrutil/src/vtr_assert.h +++ b/libs/libvtrutil/src/vtr_assert.h @@ -101,7 +101,7 @@ * * Note that to avoid 'unused' variable warnings when assertions are * disabled, we pass the expr and msg to sizeof(). We use sizeof specifically - * since it accepts expressions, and the C++ standard gaurentees sizeof's arguments + * since it accepts expressions, and the C++ standard guarantees sizeof's arguments * are never evaluated (ensuring any expensive expressions are not evaluated when * assertions are disabled). To avoid warnings about the unused result of sizeof() * we cast it to void. @@ -140,7 +140,7 @@ namespace assert { * function will never return. This should ensure the * compiler won't warn about detected conditions such as * dead-code or potential null pointer dereferences - * which are gaurded against by assertions. + * which are guarded against by assertions. */ [[noreturn]] void handle_assert(const char* expr, const char* file, unsigned int line, const char* function, const char* msg); } // namespace assert diff --git a/libs/libvtrutil/src/vtr_prefix_sum.h b/libs/libvtrutil/src/vtr_prefix_sum.h index a5817f848f..a9472fcd07 100644 --- a/libs/libvtrutil/src/vtr_prefix_sum.h +++ b/libs/libvtrutil/src/vtr_prefix_sum.h @@ -123,6 +123,11 @@ class PrefixSum1D { return prefix_sum_[upper_x + 1] - prefix_sum_[lower_x]; } + /// @brief Checks if the prefix sum is initialized or it is empty. + bool empty() const { + return prefix_sum_.empty(); + } + private: /** * @brief The 1D prefix sum of the original array of values. @@ -268,6 +273,11 @@ class PrefixSum2D { + prefix_sum_[lower_x][lower_y]; } + /// @brief Checks if the prefix sum is initialized or it is empty. + bool empty() const { + return prefix_sum_.empty(); + } + private: /** * @brief The 2D prefix sum of the original grid of values. diff --git a/vpr/src/analytical_place/detailed_placer.cpp b/vpr/src/analytical_place/detailed_placer.cpp index 9b84e1cf6f..58f7b0424a 100644 --- a/vpr/src/analytical_place/detailed_placer.cpp +++ b/vpr/src/analytical_place/detailed_placer.cpp @@ -101,7 +101,7 @@ void AnnealerDetailedPlacer::optimize_placement() { placer_->place(); // Copy the placement solution into the global placement solution. - placer_->copy_locs_to_global_state(g_vpr_ctx.mutable_placement()); + placer_->update_global_state(); // Since the placement was modified, need to resynchronize the pins in the // clusters. diff --git a/vpr/src/base/CheckSetup.cpp b/vpr/src/base/CheckSetup.cpp index 4d6a308016..ae5d43eba4 100644 --- a/vpr/src/base/CheckSetup.cpp +++ b/vpr/src/base/CheckSetup.cpp @@ -34,8 +34,8 @@ void CheckSetup(const t_packer_opts& packer_opts, } } - if ((GLOBAL == router_opts.route_type) - && (placer_opts.place_algorithm.is_timing_driven())) { + if (e_route_type::GLOBAL == router_opts.route_type + && placer_opts.place_algorithm.is_timing_driven()) { /* Works, but very weird. Can't optimize timing well, since you're * not doing proper architecture delay modelling. */ VTR_LOG_WARN( @@ -106,7 +106,7 @@ void CheckSetup(const t_packer_opts& packer_opts, } } - if (DETAILED == router_opts.route_type) { + if (e_route_type::DETAILED == router_opts.route_type) { if ((chans.chan_x_dist.type != UNIFORM) || (chans.chan_y_dist.type != UNIFORM)) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index a6c5232752..22dbec78cc 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -488,6 +488,9 @@ static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts) RouterOpts->router_debug_sink_rr = Options.router_debug_sink_rr; RouterOpts->router_debug_iteration = Options.router_debug_iteration; RouterOpts->lookahead_type = Options.router_lookahead_type; + RouterOpts->initial_acc_cost_chan_congestion_threshold = Options.router_initial_acc_cost_chan_congestion_threshold; + RouterOpts->initial_acc_cost_chan_congestion_weight = Options.router_initial_acc_cost_chan_congestion_weight; + RouterOpts->max_convergence_count = Options.router_max_convergence_count; RouterOpts->reconvergence_cpd_threshold = Options.router_reconvergence_cpd_threshold; RouterOpts->initial_timing = Options.router_initial_timing; diff --git a/vpr/src/base/ShowSetup.cpp b/vpr/src/base/ShowSetup.cpp index f841e7c390..846cb2d697 100644 --- a/vpr/src/base/ShowSetup.cpp +++ b/vpr/src/base/ShowSetup.cpp @@ -224,10 +224,10 @@ static void ShowAnnealSched(const t_annealing_sched& AnnealSched) { static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("RouterOpts.route_type: "); switch (RouterOpts.route_type) { - case GLOBAL: + case e_route_type::GLOBAL: VTR_LOG("GLOBAL\n"); break; - case DETAILED: + case e_route_type::DETAILED: VTR_LOG("DETAILED\n"); break; default: @@ -248,7 +248,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("off\n"); } - VTR_ASSERT(GLOBAL == RouterOpts.route_type || DETAILED == RouterOpts.route_type); + VTR_ASSERT(e_route_type::GLOBAL == RouterOpts.route_type || e_route_type::DETAILED == RouterOpts.route_type); VTR_LOG("RouterOpts.router_algorithm: "); switch (RouterOpts.router_algorithm) { @@ -266,9 +266,9 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { break; default: switch (RouterOpts.route_type) { - case DETAILED: + case e_route_type::DETAILED: VPR_FATAL_ERROR(VPR_ERROR_UNKNOWN, "\n"); - case GLOBAL: + case e_route_type::GLOBAL: VTR_LOG_ERROR("Unknown router algorithm\n"); break; default: @@ -282,7 +282,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("DELAY_NORMALIZED\n"); break; case DELAY_NORMALIZED_LENGTH: - if (GLOBAL == RouterOpts.route_type) { + if (e_route_type::GLOBAL == RouterOpts.route_type) { VTR_LOG_ERROR("Unknown router base cost type\n"); break; } @@ -290,7 +290,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("DELAY_NORMALIZED_LENGTH\n"); break; case DELAY_NORMALIZED_LENGTH_BOUNDED: - if (GLOBAL == RouterOpts.route_type) { + if (e_route_type::GLOBAL == RouterOpts.route_type) { VTR_LOG_ERROR("Unknown router base cost type\n"); break; } @@ -298,7 +298,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("DELAY_NORMALIZED_LENGTH_BOUNDED\n"); break; case DELAY_NORMALIZED_FREQUENCY: - if (GLOBAL == RouterOpts.route_type) { + if (e_route_type::GLOBAL == RouterOpts.route_type) { VTR_LOG_ERROR("Unknown router base cost type\n"); break; } @@ -306,7 +306,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("DELAY_NORMALIZED_FREQUENCY\n"); break; case DELAY_NORMALIZED_LENGTH_FREQUENCY: - if (GLOBAL == RouterOpts.route_type) { + if (e_route_type::GLOBAL == RouterOpts.route_type) { VTR_LOG_ERROR("Unknown router base cost type\n"); break; } @@ -317,7 +317,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("DEMAND_ONLY\n"); break; case DEMAND_ONLY_NORMALIZED_LENGTH: - if (GLOBAL == RouterOpts.route_type) { + if (e_route_type::GLOBAL == RouterOpts.route_type) { VTR_LOG_ERROR("Unknown router base cost type\n"); break; } @@ -326,9 +326,9 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { break; default: switch (RouterOpts.route_type) { - case DETAILED: + case e_route_type::DETAILED: VPR_FATAL_ERROR(VPR_ERROR_UNKNOWN, "Unknown base_cost_type\n"); - case GLOBAL: + case e_route_type::GLOBAL: VTR_LOG_ERROR("Unknown router base cost type\n"); break; default: @@ -343,7 +343,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("%d\n", RouterOpts.fixed_channel_width); } - if (DETAILED == RouterOpts.route_type) { + if (e_route_type::DETAILED == RouterOpts.route_type) { VTR_LOG("RouterOpts.check_route: "); switch (RouterOpts.check_route) { case e_check_route_option::OFF: @@ -389,7 +389,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VTR_LOG("RouterOpts.max_criticality: %f\n", RouterOpts.max_criticality); VTR_LOG("RouterOpts.init_wirelength_abort_threshold: %f\n", RouterOpts.init_wirelength_abort_threshold); - if (GLOBAL == RouterOpts.route_type) + if (e_route_type::GLOBAL == RouterOpts.route_type) VTR_LOG("RouterOpts.incr_reroute_delay_ripup: %f\n", RouterOpts.incr_reroute_delay_ripup); else { std::string incr_delay_ripup_opts[3] = {"ON", "OFF", "AUTO"}; @@ -468,7 +468,7 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { } } - if (DETAILED == RouterOpts.route_type) { + if (e_route_type::DETAILED == RouterOpts.route_type) { if (RouterOpts.routing_failure_predictor == SAFE) VTR_LOG("RouterOpts.routing_failure_predictor = SAFE\n"); else if (RouterOpts.routing_failure_predictor == AGGRESSIVE) diff --git a/vpr/src/base/globals.cpp b/vpr/src/base/globals.cpp index 5faafe9dc1..84ed4a4c43 100644 --- a/vpr/src/base/globals.cpp +++ b/vpr/src/base/globals.cpp @@ -1,3 +1,4 @@ #include "globals.h" +#include "route_common.h" VprContext g_vpr_ctx; diff --git a/vpr/src/base/old_traceback.cpp b/vpr/src/base/old_traceback.cpp index 29531cb29d..41bb857f59 100644 --- a/vpr/src/base/old_traceback.cpp +++ b/vpr/src/base/old_traceback.cpp @@ -3,6 +3,7 @@ #include "clustered_netlist_fwd.h" #include "globals.h" #include "vtr_assert.h" +#include "route_common.h" #include diff --git a/vpr/src/base/place_and_route.cpp b/vpr/src/base/place_and_route.cpp index 6fd8dc87f2..ac61f64478 100644 --- a/vpr/src/base/place_and_route.cpp +++ b/vpr/src/base/place_and_route.cpp @@ -79,7 +79,7 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list, /* Allocate the major routing structures. */ - if (router_opts.route_type == GLOBAL) { + if (router_opts.route_type == e_route_type::GLOBAL) { graph_type = e_graph_type::GLOBAL; graph_directionality = e_graph_type::BIDIR; } else { @@ -376,8 +376,8 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list, init_draw_coords(final, g_vpr_ctx.placement().blk_loc_registry()); - /* Allocate and load additional rr_graph information needed only by the router. */ - alloc_and_load_rr_node_route_structs(); + // Allocate and load additional rr_graph information needed only by the router. + alloc_and_load_rr_node_route_structs(router_opts); init_route_structs(router_net_list, router_opts.bb_factor, @@ -424,7 +424,7 @@ t_chan_width setup_chan_width(const t_router_opts& router_opts, width_fac = router_opts.fixed_channel_width; } - if (router_opts.route_type == GLOBAL) { + if (router_opts.route_type == e_route_type::GLOBAL) { graph_directionality = e_graph_type::BIDIR; } else { graph_directionality = e_graph_type::UNIDIR; diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index d2f452af6a..056f7b798f 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -432,9 +432,9 @@ struct ParseRouteType { ConvertedValue from_str(const std::string& str) { ConvertedValue conv_value; if (str == "global") - conv_value.set_value(GLOBAL); + conv_value.set_value(e_route_type::GLOBAL); else if (str == "detailed") - conv_value.set_value(DETAILED); + conv_value.set_value(e_route_type::DETAILED); else { std::stringstream msg; msg << "Invalid conversion from '" << str << "' to e_router_algorithm (expected one of: " << argparse::join(default_choices(), ", ") << ")"; @@ -445,10 +445,10 @@ struct ParseRouteType { ConvertedValue to_str(e_route_type val) { ConvertedValue conv_value; - if (val == GLOBAL) + if (val == e_route_type::GLOBAL) conv_value.set_value("global"); else { - VTR_ASSERT(val == DETAILED); + VTR_ASSERT(val == e_route_type::DETAILED); conv_value.set_value("detailed"); } return conv_value; @@ -2902,6 +2902,20 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio .default_value("map") .show_in(argparse::ShowIn::HELP_ONLY); + route_timing_grp.add_argument(args.router_initial_acc_cost_chan_congestion_threshold, "--router_initial_acc_cost_chan_congestion_threshold") + .help("Utilization threshold above which initial accumulated routing cost (acc_cost) " + "is increased to penalize congested channels. Used to bias routing away from " + "highly utilized regions during early routing iterations.") + .default_value("0.5") + .show_in(argparse::ShowIn::HELP_ONLY); + + route_timing_grp.add_argument(args.router_initial_acc_cost_chan_congestion_weight, "--router_initial_acc_cost_chan_congestion_weight") + .help("Weight applied to the excess channel utilization (above threshold) " + "when computing the initial accumulated cost (acc_cost)of routing resources. " + "Higher values make the router more sensitive to early congestion.") + .default_value("0.5") + .show_in(argparse::ShowIn::HELP_ONLY); + route_timing_grp.add_argument(args.router_max_convergence_count, "--router_max_convergence_count") .help( "Controls how many times the router is allowed to converge to a legal routing before halting." @@ -3443,14 +3457,14 @@ void set_conditional_defaults(t_options& args) { */ //Base cost type if (args.base_cost_type.provenance() != Provenance::SPECIFIED) { - if (args.RouteType == DETAILED) { + if (args.RouteType == e_route_type::DETAILED) { if (args.timing_analysis) { args.base_cost_type.set(DELAY_NORMALIZED_LENGTH, Provenance::INFERRED); } else { args.base_cost_type.set(DEMAND_ONLY_NORMALIZED_LENGTH, Provenance::INFERRED); } } else { - VTR_ASSERT(args.RouteType == GLOBAL); + VTR_ASSERT(args.RouteType == e_route_type::GLOBAL); //Global RR graphs don't have valid timing, so use demand base cost args.base_cost_type.set(DEMAND_ONLY_NORMALIZED_LENGTH, Provenance::INFERRED); } @@ -3458,10 +3472,10 @@ void set_conditional_defaults(t_options& args) { //Bend cost if (args.bend_cost.provenance() != Provenance::SPECIFIED) { - if (args.RouteType == GLOBAL) { + if (args.RouteType == e_route_type::GLOBAL) { args.bend_cost.set(1., Provenance::INFERRED); } else { - VTR_ASSERT(args.RouteType == DETAILED); + VTR_ASSERT(args.RouteType == e_route_type::DETAILED); args.bend_cost.set(0., Provenance::INFERRED); } } diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index 854f283a26..480de2bf75 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -254,6 +254,8 @@ struct t_options { argparse::ArgValue router_debug_sink_rr; argparse::ArgValue router_debug_iteration; argparse::ArgValue router_lookahead_type; + argparse::ArgValue router_initial_acc_cost_chan_congestion_threshold; + argparse::ArgValue router_initial_acc_cost_chan_congestion_weight; argparse::ArgValue router_max_convergence_count; argparse::ArgValue router_reconvergence_cpd_threshold; argparse::ArgValue router_update_lower_bound_delays; diff --git a/vpr/src/base/read_route.cpp b/vpr/src/base/read_route.cpp index 3ede11a9f9..28c15debac 100644 --- a/vpr/src/base/read_route.cpp +++ b/vpr/src/base/read_route.cpp @@ -93,7 +93,7 @@ bool read_route(const char* route_file, const t_router_opts& router_opts, bool v } /*Allocate necessary routing structures*/ - alloc_and_load_rr_node_route_structs(); + alloc_and_load_rr_node_route_structs(router_opts); const Netlist<>& router_net_list = (flat_router) ? (const Netlist<>&)g_vpr_ctx.atom().netlist() : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; init_route_structs(router_net_list, router_opts.bb_factor, diff --git a/vpr/src/base/stats.cpp b/vpr/src/base/stats.cpp index 08927b500e..6718d67678 100644 --- a/vpr/src/base/stats.cpp +++ b/vpr/src/base/stats.cpp @@ -118,7 +118,7 @@ void routing_stats(const Netlist<>& net_list, } VTR_LOG("\tTotal used logic block area: %g\n", used_area); - if (route_type == DETAILED) { + if (route_type == e_route_type::DETAILED) { count_routing_transistors(directionality, num_rr_switch, wire_to_ipin_switch, segment_inf, R_minW_nmos, R_minW_pmos, is_flat); get_segment_usage_stats(segment_inf); @@ -129,6 +129,41 @@ void routing_stats(const Netlist<>& net_list, } } +std::pair, vtr::NdMatrix> calculate_channel_width() { + const auto& device_ctx = g_vpr_ctx.device(); + const auto& rr_graph = device_ctx.rr_graph; + + auto chanx_width = vtr::NdMatrix({{(size_t)device_ctx.grid.get_num_layers(), + device_ctx.grid.width(), + device_ctx.grid.height()}}, + 0); + + auto chany_width = vtr::NdMatrix({{(size_t)device_ctx.grid.get_num_layers(), + device_ctx.grid.width(), + device_ctx.grid.height()}}, + 0); + + for (RRNodeId node_id : rr_graph.nodes()) { + e_rr_type rr_type = rr_graph.node_type(node_id); + + if (rr_type == e_rr_type::CHANX) { + int y = rr_graph.node_ylow(node_id); + int layer = rr_graph.node_layer(node_id); + for (int x = rr_graph.node_xlow(node_id); x <= rr_graph.node_xhigh(node_id); x++) { + chanx_width[layer][x][y] += rr_graph.node_capacity(node_id); + } + } else if (rr_type == e_rr_type::CHANY) { + int x = rr_graph.node_xlow(node_id); + int layer = rr_graph.node_layer(node_id); + for (int y = rr_graph.node_ylow(node_id); y <= rr_graph.node_yhigh(node_id); y++) { + chany_width[layer][x][y] += rr_graph.node_capacity(node_id); + } + } + } + + return {chanx_width, chany_width}; +} + void length_and_bends_stats(const Netlist<>& net_list, bool is_flat) { int max_bends = 0; int total_bends = 0; diff --git a/vpr/src/base/stats.h b/vpr/src/base/stats.h index eb79a2c394..08b9e4d1d1 100644 --- a/vpr/src/base/stats.h +++ b/vpr/src/base/stats.h @@ -23,6 +23,18 @@ void routing_stats(const Netlist<>& net_list, int wire_to_ipin_switch, bool is_flat); +/** + * @brief Calculates the routing channel width at each grid location. + * + * Iterates through all RR nodes and counts how many wires pass through each (x, y) location + * for both horizontal (CHANX) and vertical (CHANY) channels. + * + * @return A pair of 3D matrices: + * - First: CHANX width per [layer][x][y] + * - Second: CHANY width per [layer][x][y] + */ +std::pair, vtr::NdMatrix> calculate_channel_width(); + void print_wirelen_prob_dist(bool is_flat); void print_lambda(); diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index e20c046294..1c8655702f 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -55,6 +55,7 @@ #include "pb_type_graph.h" #include "route.h" #include "route_export.h" +#include "route_common.h" #include "vpr_api.h" #include "read_sdc.h" #include "power.h" @@ -1172,7 +1173,7 @@ void vpr_create_rr_graph(t_vpr_setup& vpr_setup, const t_arch& arch, int chan_wi e_graph_type graph_type; e_graph_type graph_directionality; - if (router_opts.route_type == GLOBAL) { + if (router_opts.route_type == e_route_type::GLOBAL) { graph_type = e_graph_type::GLOBAL; graph_directionality = e_graph_type::BIDIR; } else { diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index b975ae4768..a07beefd47 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -46,6 +46,8 @@ class PostClusterDelayCalculator; #endif /* NO_SERVER */ +struct t_rr_node_route_inf; + /** * @brief A Context is collection of state relating to a particular part of VPR * @@ -559,6 +561,11 @@ struct RoutingContext : public Context { /** Is flat routing enabled? */ bool is_flat; + + /// @brief Post-placement estimate of CHANX routing utilization per (layer, x, y) location. + vtr::NdMatrix chanx_util; + /// @brief Post-placement estimate of CHANY routing utilization per (layer, x, y) location. + vtr::NdMatrix chany_util; }; /** diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 34d4791430..4e8e7202a2 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1302,6 +1302,8 @@ struct t_router_opts { int router_debug_sink_rr; int router_debug_iteration; e_router_lookahead lookahead_type; + double initial_acc_cost_chan_congestion_threshold; + double initial_acc_cost_chan_congestion_weight; int max_convergence_count; int route_verbosity; float reconvergence_cpd_threshold; @@ -1436,42 +1438,6 @@ constexpr bool is_pin(e_rr_type type) { return (type == e_rr_type::IPIN || type constexpr bool is_chan(e_rr_type type) { return (type == e_rr_type::CHANX || type == e_rr_type::CHANY); } constexpr bool is_src_sink(e_rr_type type) { return (type == e_rr_type::SOURCE || type == e_rr_type::SINK); } -/** - * @brief Extra information about each rr_node needed only during routing - * (i.e. during the maze expansion). - * - * @param prev_edge ID of the edge (globally unique edge ID in the RR Graph) - * that was used to reach this node from the previous node. - * If there is no predecessor, prev_edge = NO_PREVIOUS. - * @param acc_cost Accumulated cost term from previous Pathfinder iterations. - * @param path_cost Total cost of the path up to and including this node + - * the expected cost to the target if the timing_driven router - * is being used. - * @param backward_path_cost Total cost of the path up to and including this - * node. - * @param R_upstream Upstream resistance to ground from this node in the current - * path search (connection routing), including the resistance - * of the node itself (device_ctx.rr_nodes[index].R). - * @param occ The current occupancy of the associated rr node. - */ -struct t_rr_node_route_inf { - RREdgeId prev_edge; - - float acc_cost; - float path_cost; - float backward_path_cost; - float R_upstream; - - public: //Accessors - short occ() const { return occ_; } - - public: //Mutators - void set_occ(int new_occ) { occ_ = new_occ; } - - private: //Data - short occ_ = 0; -}; - /** * @brief Information about the current status of a particular * net as pertains to routing diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index 42d6123370..0061fad803 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp @@ -73,7 +73,7 @@ void act_on_mouse_move(ezgl::application* app, GdkEventButton* event, double x, static void highlight_blocks(double x, double y); -static float get_router_expansion_cost(const t_rr_node_route_inf node_inf, +static float get_router_expansion_cost(const t_rr_node_route_inf& node_inf, e_draw_router_expansion_cost draw_router_expansion_cost); static void draw_router_expansion_costs(ezgl::renderer* g); @@ -278,7 +278,7 @@ static void default_setup(ezgl::application* app) { // Initial Setup functions run default setup if they are a new window. Then, they will run // the specific hiding/showing functions that separate them from the other init. setup functions -/* function below intializes the interface window with a set of buttons and links +/* function below initializes the interface window with a set of buttons and links * signals to corresponding functions for situation where the window is opened from * NO_PICTURE_to_PLACEMENT */ static void initial_setup_NO_PICTURE_to_PLACEMENT(ezgl::application* app, @@ -290,7 +290,7 @@ static void initial_setup_NO_PICTURE_to_PLACEMENT(ezgl::application* app, hide_widget("RoutingMenuButton", app); } -/* function below intializes the interface window with a set of buttons and links +/* function below initializes the interface window with a set of buttons and links * signals to corresponding functions for situation where the window is opened from * NO_PICTURE_to_PLACEMENT_with_crit_path */ static void initial_setup_NO_PICTURE_to_PLACEMENT_with_crit_path( @@ -308,7 +308,7 @@ static void initial_setup_NO_PICTURE_to_PLACEMENT_with_crit_path( hide_widget("RoutingMenuButton", app); } -/* function below intializes the interface window with a set of buttons and links +/* function below initializes the interface window with a set of buttons and links * signals to corresponding functions for situation where the window is opened from * PLACEMENT_to_ROUTING */ static void initial_setup_PLACEMENT_to_ROUTING(ezgl::application* app, @@ -321,7 +321,7 @@ static void initial_setup_PLACEMENT_to_ROUTING(ezgl::application* app, hide_crit_path_routing(app, false); } -/* function below intializes the interface window with a set of buttons and links +/* function below initializes the interface window with a set of buttons and links * signals to corresponding functions for situation where the window is opened from * ROUTING_to_PLACEMENT */ static void initial_setup_ROUTING_to_PLACEMENT(ezgl::application* app, @@ -335,7 +335,7 @@ static void initial_setup_ROUTING_to_PLACEMENT(ezgl::application* app, hide_crit_path_routing(app, false); } -/* function below intializes the interface window with a set of buttons and links +/* function below initializes the interface window with a set of buttons and links * signals to corresponding functions for situation where the window is opened from * NO_PICTURE_to_ROUTING */ static void initial_setup_NO_PICTURE_to_ROUTING(ezgl::application* app, @@ -348,7 +348,7 @@ static void initial_setup_NO_PICTURE_to_ROUTING(ezgl::application* app, hide_crit_path_routing(app, false); } -/* function below intializes the interface window with a set of buttons and links +/* function below initializes the interface window with a set of buttons and links * signals to corresponding functions for situation where the window is opened from * NO_PICTURE_to_ROUTING_with_crit_path */ static void initial_setup_NO_PICTURE_to_ROUTING_with_crit_path( @@ -630,7 +630,7 @@ int get_track_num(int inode, const vtr::OffsetMatrix& chanx_track, const vt const auto& rr_graph = device_ctx.rr_graph; RRNodeId rr_node = RRNodeId(inode); - if (get_draw_state_vars()->draw_route_type == DETAILED) + if (get_draw_state_vars()->draw_route_type == e_route_type::DETAILED) return (rr_graph.node_track_num(rr_node)); /* GLOBAL route stuff below. */ @@ -891,19 +891,16 @@ ezgl::color to_ezgl_color(vtr::Color color) { return ezgl::color(color.r * 255, color.g * 255, color.b * 255); } -static float get_router_expansion_cost(const t_rr_node_route_inf node_inf, +static float get_router_expansion_cost(const t_rr_node_route_inf& node_inf, e_draw_router_expansion_cost draw_router_expansion_cost) { if (draw_router_expansion_cost == DRAW_ROUTER_EXPANSION_COST_TOTAL - || draw_router_expansion_cost - == DRAW_ROUTER_EXPANSION_COST_TOTAL_WITH_EDGES) { + || draw_router_expansion_cost == DRAW_ROUTER_EXPANSION_COST_TOTAL_WITH_EDGES) { return node_inf.path_cost; } else if (draw_router_expansion_cost == DRAW_ROUTER_EXPANSION_COST_KNOWN - || draw_router_expansion_cost - == DRAW_ROUTER_EXPANSION_COST_KNOWN_WITH_EDGES) { + || draw_router_expansion_cost == DRAW_ROUTER_EXPANSION_COST_KNOWN_WITH_EDGES) { return node_inf.backward_path_cost; } else if (draw_router_expansion_cost == DRAW_ROUTER_EXPANSION_COST_EXPECTED - || draw_router_expansion_cost - == DRAW_ROUTER_EXPANSION_COST_EXPECTED_WITH_EDGES) { + || draw_router_expansion_cost == DRAW_ROUTER_EXPANSION_COST_EXPECTED_WITH_EDGES) { return node_inf.path_cost - node_inf.backward_path_cost; } @@ -912,8 +909,7 @@ static float get_router_expansion_cost(const t_rr_node_route_inf node_inf, static void draw_router_expansion_costs(ezgl::renderer* g) { t_draw_state* draw_state = get_draw_state_vars(); - if (draw_state->show_router_expansion_cost - == DRAW_NO_ROUTER_EXPANSION_COST) { + if (draw_state->show_router_expansion_cost == DRAW_NO_ROUTER_EXPANSION_COST) { return; } @@ -923,9 +919,8 @@ static void draw_router_expansion_costs(ezgl::renderer* g) { vtr::vector rr_costs(device_ctx.rr_graph.num_nodes()); for (RRNodeId inode : device_ctx.rr_graph.nodes()) { - float cost = get_router_expansion_cost( - routing_ctx.rr_node_route_inf[inode], - draw_state->show_router_expansion_cost); + float cost = get_router_expansion_cost(routing_ctx.rr_node_route_inf[inode], + draw_state->show_router_expansion_cost); rr_costs[inode] = cost; } diff --git a/vpr/src/draw/draw_basic.cpp b/vpr/src/draw/draw_basic.cpp index 9fc27bbdc9..4a4243af46 100644 --- a/vpr/src/draw/draw_basic.cpp +++ b/vpr/src/draw/draw_basic.cpp @@ -613,7 +613,7 @@ void draw_partial_route(const std::vector& rr_nodes_to_draw, ezgl::ren static vtr::OffsetMatrix chanx_track; /* [1..device_ctx.grid.width() - 2][0..device_ctx.grid.height() - 2] */ static vtr::OffsetMatrix chany_track; /* [0..device_ctx.grid.width() - 2][1..device_ctx.grid.height() - 2] */ - if (draw_state->draw_route_type == GLOBAL) { + if (draw_state->draw_route_type == e_route_type::GLOBAL) { /* Allocate some temporary storage if it's not already available. */ int width = (int)device_ctx.grid.width(); int height = (int)device_ctx.grid.height(); @@ -677,7 +677,7 @@ void draw_partial_route(const std::vector& rr_nodes_to_draw, ezgl::ren break; } case e_rr_type::CHANX: { - if (draw_state->draw_route_type == GLOBAL) + if (draw_state->draw_route_type == e_route_type::GLOBAL) chanx_track[rr_graph.node_xlow(inode)][rr_graph.node_ylow(inode)]++; draw_rr_chan(inode, color, g); @@ -707,7 +707,7 @@ void draw_partial_route(const std::vector& rr_nodes_to_draw, ezgl::ren break; } case e_rr_type::CHANY: { - if (draw_state->draw_route_type == GLOBAL) + if (draw_state->draw_route_type == e_route_type::GLOBAL) chany_track[rr_graph.node_xlow(inode)][rr_graph.node_ylow(inode)]++; draw_rr_chan(inode, color, g); diff --git a/vpr/src/draw/draw_types.h b/vpr/src/draw/draw_types.h index 92cdae4601..56d6d96985 100644 --- a/vpr/src/draw/draw_types.h +++ b/vpr/src/draw/draw_types.h @@ -228,7 +228,7 @@ struct t_draw_state { bool auto_proceed = false; ///@brief GLOBAL or DETAILED - e_route_type draw_route_type = GLOBAL; + e_route_type draw_route_type = e_route_type::GLOBAL; ///@brief default screen message on screen char default_message[vtr::bufsize]; diff --git a/vpr/src/place/delay_model/PlacementDelayModelCreator.cpp b/vpr/src/place/delay_model/PlacementDelayModelCreator.cpp index 1ec59f4ed1..a4c2110dcd 100644 --- a/vpr/src/place/delay_model/PlacementDelayModelCreator.cpp +++ b/vpr/src/place/delay_model/PlacementDelayModelCreator.cpp @@ -11,7 +11,7 @@ #include "physical_types.h" #include "place_and_route.h" -static int get_longest_segment_length(std::vector& segment_inf) { +static int get_longest_segment_length(const std::vector& segment_inf) { int length = 0; for (const t_segment_inf& seg_info : segment_inf) { @@ -28,7 +28,7 @@ PlacementDelayModelCreator::create_delay_model(const t_placer_opts& placer_opts, const t_router_opts& router_opts, const Netlist<>& net_list, t_det_routing_arch& det_routing_arch, - std::vector& segment_inf, + const std::vector& segment_inf, const t_chan_width_dist& chan_width_dist, const std::vector& directs, bool is_flat) { diff --git a/vpr/src/place/delay_model/PlacementDelayModelCreator.h b/vpr/src/place/delay_model/PlacementDelayModelCreator.h index 2cfd4e5b12..6da4ac56f1 100644 --- a/vpr/src/place/delay_model/PlacementDelayModelCreator.h +++ b/vpr/src/place/delay_model/PlacementDelayModelCreator.h @@ -22,7 +22,7 @@ class PlacementDelayModelCreator { const t_router_opts& router_opts, const Netlist<>& net_list, t_det_routing_arch& det_routing_arch, - std::vector& segment_inf, + const std::vector& segment_inf, const t_chan_width_dist& chan_width_dist, const std::vector& directs, bool is_flat); diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index 0a48466c64..4784c5d922 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -35,6 +35,7 @@ #include "vtr_ndmatrix.h" #include "PlacerCriticalities.h" #include "vtr_prefix_sum.h" +#include "stats.h" #include @@ -1426,14 +1427,11 @@ double NetCostHandler::get_net_wirelength_estimate_(ClusterNetId net_id) const { } double NetCostHandler::get_net_wirelength_from_layer_bb_(ClusterNetId net_id) const { - /* WMF: Finds the estimate of wirelength due to one net by looking at * - * its coordinate bounding box. */ - const std::vector& bb = layer_bb_coords_[net_id]; const vtr::NdMatrixProxy net_layer_pin_sink_count = num_sink_pin_layer_[size_t(net_id)]; double ncost = 0.; - VTR_ASSERT_SAFE(static_cast(bb.size()) == g_vpr_ctx.device().grid.get_num_layers()); + VTR_ASSERT_SAFE((int)bb.size() == g_vpr_ctx.device().grid.get_num_layers()); for (size_t layer_num = 0; layer_num < bb.size(); layer_num++) { VTR_ASSERT_SAFE(net_layer_pin_sink_count[layer_num] != OPEN); @@ -1757,3 +1755,115 @@ std::pair NetCostHandler::union_2d_bb_incr(ClusterNetId net_id) cons return std::make_pair(merged_num_edge, merged_bb); } + +std::pair, vtr::NdMatrix> NetCostHandler::estimate_routing_chan_util() const { + const auto& cluster_ctx = g_vpr_ctx.clustering(); + const auto& device_ctx = g_vpr_ctx.device(); + + auto chanx_util = vtr::NdMatrix({{(size_t)device_ctx.grid.get_num_layers(), + device_ctx.grid.width(), + device_ctx.grid.height()}}, + 0); + + auto chany_util = vtr::NdMatrix({{(size_t)device_ctx.grid.get_num_layers(), + device_ctx.grid.width(), + device_ctx.grid.height()}}, + 0); + + // For each net, this function estimates routing channel utilization by distributing + // the net's expected wirelength across its bounding box. The expected wirelength + // for each dimension (x, y) is computed proportionally based on the bounding box size + // in each direction. The wirelength in each dimension is then **evenly spread** across + // all grid locations within the bounding box, and the demand is accumulated in + // the channel utilization matrices. + + for (ClusterNetId net_id : cluster_ctx.clb_nlist.nets()) { + if (!cluster_ctx.clb_nlist.net_is_ignored(net_id)) { + + if (cube_bb_) { + const t_bb& bb = bb_coords_[net_id]; + double expected_wirelength = get_net_wirelength_estimate_(net_id); + + int distance_x = bb.xmax - bb.xmin + 1; + int distance_y = bb.ymax - bb.ymin + 1; + int distance_z = bb.layer_max - bb.layer_min + 1; + + double expected_x_wl = (double)distance_x / (distance_x + distance_y) * expected_wirelength; + double expected_y_wl = expected_wirelength - expected_x_wl; + + int total_channel_segments = distance_x * distance_y * distance_z; + double expected_per_x_segment_wl = expected_x_wl / total_channel_segments; + double expected_per_y_segment_wl = expected_y_wl / total_channel_segments; + + for (int layer = bb.layer_min; layer <= bb.layer_max; layer++) { + for (int x = bb.xmin; x <= bb.xmax; x++) { + for (int y = bb.ymin; y <= bb.ymax; y++) { + chanx_util[layer][x][y] += expected_per_x_segment_wl; + chany_util[layer][x][y] += expected_per_y_segment_wl; + } + } + } + } else { + const std::vector& bb = layer_bb_coords_[net_id]; + const vtr::NdMatrixProxy net_layer_pin_sink_count = num_sink_pin_layer_[size_t(net_id)]; + + for (size_t layer = 0; layer < bb.size(); layer++) { + if (net_layer_pin_sink_count[layer] == 0) { + continue; + } + + double crossing = wirelength_crossing_count(net_layer_pin_sink_count[layer] + 1); + double expected_wirelength = ((bb[layer].xmax - bb[layer].xmin + 1) + (bb[layer].ymax - bb[layer].ymin + 1)) * crossing; + + int distance_x = bb[layer].xmax - bb[layer].xmin + 1; + int distance_y = bb[layer].ymax - bb[layer].ymin + 1; + + double expected_x_wl = (double)distance_x / (distance_x + distance_y) * expected_wirelength; + double expected_y_wl = expected_wirelength - expected_x_wl; + + int total_channel_segments = distance_x * distance_y; + double expected_per_x_segment_wl = expected_x_wl / total_channel_segments; + double expected_per_y_segment_wl = expected_y_wl / total_channel_segments; + + for (int x = bb[layer].xmin; x <= bb[layer].xmax; x++) { + for (int y = bb[layer].ymin; y <= bb[layer].ymax; y++) { + chanx_util[layer][x][y] += expected_per_x_segment_wl; + chany_util[layer][x][y] += expected_per_y_segment_wl; + } + } + } + } + } + } + + const auto [chanx_width, chany_width] = calculate_channel_width(); + + VTR_ASSERT(chanx_util.size() == chany_util.size()); + VTR_ASSERT(chanx_util.ndims() == chany_util.ndims()); + VTR_ASSERT(chanx_util.size() == chanx_width.size()); + VTR_ASSERT(chanx_util.ndims() == chanx_width.ndims()); + VTR_ASSERT(chany_util.size() == chany_width.size()); + VTR_ASSERT(chany_util.ndims() == chany_width.ndims()); + + for (size_t layer = 0; layer < chanx_util.dim_size(0); ++layer) { + for (size_t x = 0; x < chanx_util.dim_size(1); ++x) { + for (size_t y = 0; y < chanx_util.dim_size(2); ++y) { + if (chanx_width[layer][x][y] > 0) { + chanx_util[layer][x][y] /= chanx_width[layer][x][y]; + } else { + VTR_ASSERT_SAFE(chanx_width[layer][x][y] == 0); + chanx_util[layer][x][y] = 1.; + } + + if (chany_width[layer][x][y] > 0) { + chany_util[layer][x][y] /= chany_width[layer][x][y]; + } else { + VTR_ASSERT_SAFE(chany_width[layer][x][y] == 0); + chany_util[layer][x][y] = 1.; + } + } + } + } + + return {chanx_util, chany_util}; +} diff --git a/vpr/src/place/net_cost_handler.h b/vpr/src/place/net_cost_handler.h index 7681b93f6a..ca95e4be56 100644 --- a/vpr/src/place/net_cost_handler.h +++ b/vpr/src/place/net_cost_handler.h @@ -125,6 +125,18 @@ class NetCostHandler { */ double get_total_wirelength_estimate() const; + /** + * @brief Estimates routing channel utilization. + * + * For each net, distributes estimated wirelength across its bounding box + * and accumulates demand for different routing channels. Normalizes by channel widths + * (e.g. a value of 0.5 means 50% of the wiring in a channel is expected to be used). + * + * @return Pair of matrices with relative CHANX and CHANY utilization. + * The dimension order for each matrix is [layer][x][y]. + */ + std::pair, vtr::NdMatrix> estimate_routing_chan_util() const; + private: ///@brief Specifies whether the bounding box is computed using cube method or per-layer method. bool cube_bb_; diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index 39d6cd24f8..f4a370e1df 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -1,10 +1,8 @@ #include -#include #include "flat_placement_types.h" #include "initial_placement.h" -#include "load_flat_place.h" #include "noc_place_utils.h" #include "pack.h" #include "vpr_context.h" @@ -35,7 +33,7 @@ void try_place(const Netlist<>& net_list, const t_noc_opts& noc_opts, const t_chan_width_dist& chan_width_dist, t_det_routing_arch& det_routing_arch, - std::vector& segment_inf, + const std::vector& segment_inf, const std::vector& directs, const FlatPlacementInfo& flat_placement_info, bool is_flat) { @@ -48,18 +46,18 @@ void try_place(const Netlist<>& net_list, const auto& device_ctx = g_vpr_ctx.device(); const auto& cluster_ctx = g_vpr_ctx.clustering(); const auto& atom_ctx = g_vpr_ctx.atom(); + auto& mutable_placement = g_vpr_ctx.mutable_placement(); + auto& mutable_floorplanning = g_vpr_ctx.mutable_floorplanning(); // Initialize the variables in the placement context. - g_vpr_ctx.mutable_placement().init_placement_context(placer_opts, directs); + mutable_placement.init_placement_context(placer_opts, directs); // Update the floorplanning constraints with the macro information from the // placement context. - g_vpr_ctx.mutable_floorplanning().update_floorplanning_context_pre_place(*g_vpr_ctx.placement().place_macros); - - const bool cube_bb = g_vpr_ctx.placement().cube_bb; + mutable_floorplanning.update_floorplanning_context_pre_place(*mutable_placement.place_macros); VTR_LOG("\n"); - VTR_LOG("Bounding box mode is %s\n", (cube_bb ? "Cube" : "Per-layer")); + VTR_LOG("Bounding box mode is %s\n", (mutable_placement.cube_bb ? "Cube" : "Per-layer")); VTR_LOG("\n"); /* To make sure the importance of NoC-related cost terms compared to @@ -101,7 +99,7 @@ void try_place(const Netlist<>& net_list, * placement context. This is done to make sure that the placement stage only accesses its * own local instances of BlkLocRegistry. */ - g_vpr_ctx.mutable_placement().lock_loc_vars(); + mutable_placement.lock_loc_vars(); /* Start measuring placement time. The measured execution time will be printed * when this object goes out of scope at the end of this function. @@ -114,7 +112,7 @@ void try_place(const Netlist<>& net_list, ClusteredPinAtomPinsLookup netlist_pin_lookup(cluster_ctx.clb_nlist, atom_ctx.netlist(), pb_gpin_lookup); Placer placer(net_list, {}, placer_opts, analysis_opts, noc_opts, pb_gpin_lookup, netlist_pin_lookup, - flat_placement_info, place_delay_model, cube_bb, is_flat, /*quiet=*/false); + flat_placement_info, place_delay_model, mutable_placement.cube_bb, is_flat, /*quiet=*/false); placer.place(); @@ -122,13 +120,13 @@ void try_place(const Netlist<>& net_list, * the global context directly. We need to copy its internal data structures * to the global placement context before it goes out of scope. */ - placer.copy_locs_to_global_state(g_vpr_ctx.mutable_placement()); + placer.update_global_state(); // Clean the variables in the placement context. This will deallocate memory // used by variables which were allocated in the placement context and are // never used outside of placement. - g_vpr_ctx.mutable_placement().clean_placement_context_post_place(); - g_vpr_ctx.mutable_floorplanning().clean_floorplanning_context_post_place(); + mutable_placement.clean_placement_context_post_place(); + mutable_floorplanning.clean_floorplanning_context_post_place(); } #ifdef VERBOSE diff --git a/vpr/src/place/place.h b/vpr/src/place/place.h index ae5384af49..37246502bc 100644 --- a/vpr/src/place/place.h +++ b/vpr/src/place/place.h @@ -12,7 +12,7 @@ void try_place(const Netlist<>& net_list, const t_noc_opts& noc_opts, const t_chan_width_dist& chan_width_dist, t_det_routing_arch& det_routing_arch, - std::vector& segment_inf, + const std::vector& segment_inf, const std::vector& directs, const FlatPlacementInfo& flat_placement_info, bool is_flat); diff --git a/vpr/src/place/placer.cpp b/vpr/src/place/placer.cpp index 43018b7c90..956171998c 100644 --- a/vpr/src/place/placer.cpp +++ b/vpr/src/place/placer.cpp @@ -376,14 +376,22 @@ void Placer::place() { log_printer_.print_post_placement_stats(); } -void Placer::copy_locs_to_global_state(PlacementContext& place_ctx) { +void Placer::update_global_state() { + auto& mutable_palce_ctx = g_vpr_ctx.mutable_placement(); + auto& mutable_routing_ctx = g_vpr_ctx.mutable_routing(); + // the placement location variables should be unlocked before being accessed - place_ctx.unlock_loc_vars(); + mutable_palce_ctx.unlock_loc_vars(); // copy the local location variables into the global state - auto& global_blk_loc_registry = place_ctx.mutable_blk_loc_registry(); + auto& global_blk_loc_registry = mutable_palce_ctx.mutable_blk_loc_registry(); global_blk_loc_registry = placer_state_.blk_loc_registry(); + auto [chanx_util, chany_util] = net_cost_handler_.estimate_routing_chan_util(); + + mutable_routing_ctx.chanx_util = std::move(chanx_util); + mutable_routing_ctx.chany_util = std::move(chany_util); + #ifndef NO_GRAPHICS // update the graphics' reference to placement location variables get_draw_state_vars()->set_graphics_blk_loc_registry_ref(global_blk_loc_registry); diff --git a/vpr/src/place/placer.h b/vpr/src/place/placer.h index 02ffd5478a..6fb32cafad 100644 --- a/vpr/src/place/placer.h +++ b/vpr/src/place/placer.h @@ -67,10 +67,10 @@ class Placer { void place(); /** - * @brief Copies the placement location variables into the given global placement context. - * @param place_ctx The placement context to which location information will be copied. + * @brief Copies the placement location variables into the global placement context. + * This method also updates the global routing context with the estimated routing channel utilization. */ - void copy_locs_to_global_state(PlacementContext& place_ctx); + void update_global_state(); private: /// Holds placement algorithm parameters diff --git a/vpr/src/route/connection_router.h b/vpr/src/route/connection_router.h index db2fe0894a..7ba6b35fa7 100644 --- a/vpr/src/route/connection_router.h +++ b/vpr/src/route/connection_router.h @@ -1,4 +1,5 @@ #pragma once + /** * @file * @brief This file defines the ConnectionRouter class. diff --git a/vpr/src/route/connection_router.tpp b/vpr/src/route/connection_router.tpp index 34774ccf9d..2e9a12276c 100644 --- a/vpr/src/route/connection_router.tpp +++ b/vpr/src/route/connection_router.tpp @@ -25,8 +25,7 @@ std::tuple ConnectionRouter::timing_driven_rou router_stats_ = &router_stats; conn_params_ = &conn_params; - bool retry = false; - retry = timing_driven_route_connection_common_setup(rt_root, sink_node, cost_params, bounding_box); + bool retry = timing_driven_route_connection_common_setup(rt_root, sink_node, cost_params, bounding_box); if (!std::isinf(rr_node_route_inf_[sink_node].path_cost)) { // Only the `index`, `prev_edge`, and `rcv_path_backward_delay` fields of `out` @@ -231,16 +230,10 @@ float ConnectionRouter::compute_node_cost_using_rcv(const t_conn_cost_para float backwards_delay, float backwards_cong, float R_upstream) { - float expected_delay; - float expected_cong; - 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); - - float expected_total_delay_cost; - float expected_total_cong_cost; + const auto [expected_delay, expected_cong] = router_lookahead_.get_expected_delay_and_cong(to_node, target_node, cost_params, R_upstream); float expected_total_cong = expected_cong + backwards_cong; float expected_total_delay = expected_delay + backwards_delay; @@ -253,11 +246,11 @@ float ConnectionRouter::compute_node_cost_using_rcv(const t_conn_cost_para // Normalization constant defined in RCV paper cited above constexpr float NORMALIZATION_CONSTANT = 100e-12; - expected_total_delay_cost = expected_total_delay; + float expected_total_delay_cost = expected_total_delay; expected_total_delay_cost += (delay_budget->short_path_criticality + cost_params.criticality) * std::max(0.f, delay_budget->target_delay - expected_total_delay); // expected_total_delay_cost += std::pow(std::max(0.f, expected_total_delay - delay_budget->max_delay), 2) / NORMALIZATION_CONSTANT; expected_total_delay_cost += std::pow(std::max(0.f, delay_budget->min_delay - expected_total_delay), 2) / NORMALIZATION_CONSTANT; - expected_total_cong_cost = expected_total_cong; + float expected_total_cong_cost = expected_total_cong; float total_cost = expected_total_delay_cost + expected_total_cong_cost; diff --git a/vpr/src/route/overuse_report.cpp b/vpr/src/route/overuse_report.cpp index 25348e0f5f..8d4e36be69 100644 --- a/vpr/src/route/overuse_report.cpp +++ b/vpr/src/route/overuse_report.cpp @@ -5,6 +5,7 @@ #include "physical_types_util.h" #include "vpr_utils.h" #include "vtr_log.h" +#include "route_common.h" /** * @brief Definitions of global and helper routines related to printing RR node overuse info. diff --git a/vpr/src/route/route.cpp b/vpr/src/route/route.cpp index 8bc82be005..53952af47f 100644 --- a/vpr/src/route/route.cpp +++ b/vpr/src/route/route.cpp @@ -26,8 +26,8 @@ bool route(const Netlist<>& net_list, ScreenUpdatePriority first_iteration_priority, bool is_flat) { auto& device_ctx = g_vpr_ctx.mutable_device(); - auto& cluster_ctx = g_vpr_ctx.clustering(); - auto& atom_ctx = g_vpr_ctx.atom(); + const auto& cluster_ctx = g_vpr_ctx.clustering(); + const auto& atom_ctx = g_vpr_ctx.atom(); auto& route_ctx = g_vpr_ctx.mutable_routing(); if (net_list.nets().empty()) { @@ -36,7 +36,7 @@ bool route(const Netlist<>& net_list, e_graph_type graph_type; e_graph_type graph_directionality; - if (router_opts.route_type == GLOBAL) { + if (router_opts.route_type == e_route_type::GLOBAL) { graph_type = e_graph_type::GLOBAL; graph_directionality = e_graph_type::BIDIR; } else { @@ -65,7 +65,7 @@ bool route(const Netlist<>& net_list, init_draw_coords(width_fac, g_vpr_ctx.placement().blk_loc_registry()); /* Allocate and load additional rr_graph information needed only by the router. */ - alloc_and_load_rr_node_route_structs(); + alloc_and_load_rr_node_route_structs(router_opts); init_route_structs(net_list, router_opts.bb_factor, diff --git a/vpr/src/route/route_common.cpp b/vpr/src/route/route_common.cpp index 7ead8f73cd..95d9a93e4c 100644 --- a/vpr/src/route/route_common.cpp +++ b/vpr/src/route/route_common.cpp @@ -1,9 +1,10 @@ /** @file Impls for more router utils */ +#include "route_common.h" + #include "atom_netlist_utils.h" #include "connection_router_interface.h" #include "describe_rr_node.h" -#include "route_common.h" #include "logic_types.h" #include "physical_types_util.h" #include "route_export.h" @@ -70,6 +71,19 @@ static vtr::vector load_is_clock_net(const Netlist<>& net_ static bool classes_in_same_block(ParentBlockId blk_id, int first_class_ptc_num, int second_class_ptc_num, bool is_flat); +/** + * @brief Computes the initial `acc_cost` for the given RR node by checking + * if the node is of type CHANX/CHANY and goes through a possibly congested + * routing channel. + * @param node_id The RR node whose initial acc_cost is to be computed. + * @param route_opts Contains channel utilization threshold and weighting factor + * used to increase initial 'acc_cost' for nodes going through + * congested channels. + * @return Initial `acc_cost` for the given RR node. + */ +static float comp_initial_acc_cost(RRNodeId node_id, + const t_router_opts& route_opts); + /************************** Subroutine definitions ***************************/ void save_routing(vtr::vector>& best_routing, @@ -342,13 +356,10 @@ static t_clb_opins_used alloc_and_load_clb_opins_used_locally() { * output pins for connections made locally within a CLB (if the netlist * * specifies that this is necessary). */ - t_clb_opins_used clb_opins_used_locally; - int clb_pin, iclass; + const auto& cluster_ctx = g_vpr_ctx.clustering(); + const auto& block_locs = g_vpr_ctx.placement().block_locs(); - auto& cluster_ctx = g_vpr_ctx.clustering(); - auto& block_locs = g_vpr_ctx.placement().block_locs(); - - clb_opins_used_locally.resize(cluster_ctx.clb_nlist.blocks().size()); + t_clb_opins_used clb_opins_used_locally(cluster_ctx.clb_nlist.blocks().size()); for (ClusterBlockId blk_id : cluster_ctx.clb_nlist.blocks()) { t_pl_loc block_loc = block_locs[blk_id].loc; @@ -363,13 +374,13 @@ static t_clb_opins_used alloc_and_load_clb_opins_used_locally() { const auto [pin_low, pin_high] = get_pin_range_for_block(blk_id); - for (clb_pin = pin_low; clb_pin <= pin_high; clb_pin++) { + for (int clb_pin = pin_low; clb_pin <= pin_high; clb_pin++) { ClusterNetId net = cluster_ctx.clb_nlist.block_net(blk_id, clb_pin); if (!net || (net && cluster_ctx.clb_nlist.net_sinks(net).size() == 0)) { //There is no external net connected to this pin - auto port_eq = get_port_equivalency_from_pin_physical_num(type, clb_pin); - iclass = get_class_num_from_pin_physical_num(type, clb_pin); + PortEquivalence port_eq = get_port_equivalency_from_pin_physical_num(type, clb_pin); + int iclass = get_class_num_from_pin_physical_num(type, clb_pin); if (port_eq == PortEquivalence::INSTANCE) { //The pin is part of an instance equivalent class, hence we need to reserve a pin @@ -401,38 +412,77 @@ void free_route_structs() { } } -void alloc_and_load_rr_node_route_structs() { - /* Allocates some extra information about each rr_node that is used only * - * during routing. */ +void alloc_and_load_rr_node_route_structs(const t_router_opts& router_opts) { + // Allocates some extra information about each rr_node that is used only during routing. auto& route_ctx = g_vpr_ctx.mutable_routing(); - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); route_ctx.rr_node_route_inf.resize(device_ctx.rr_graph.num_nodes()); route_ctx.non_configurable_bitset.resize(device_ctx.rr_graph.num_nodes()); route_ctx.non_configurable_bitset.fill(false); - reset_rr_node_route_structs(); + reset_rr_node_route_structs(router_opts); for (auto i : device_ctx.rr_node_to_non_config_node_set) { route_ctx.non_configurable_bitset.set(i.first, true); } } -void reset_rr_node_route_structs() { - /* Resets some extra information about each rr_node that is used only * - * during routing. */ +static float comp_initial_acc_cost(RRNodeId node_id, + const t_router_opts& route_opts) { + const auto& route_ctx = g_vpr_ctx.routing(); + const auto& rr_graph = g_vpr_ctx.device().rr_graph; + + // The default acc_cost is 1 for all rr_nodes. For routing wires, if they pass through a channel + // with expected utilization above the threshold, we assign a higher initial cost. + // This helps the router avoid channels that are likely to be congested. + float cost = 1.f; + + const e_rr_type rr_type = rr_graph.node_type(node_id); + const double threshold = route_opts.initial_acc_cost_chan_congestion_threshold; + const double weight = route_opts.initial_acc_cost_chan_congestion_weight; + + // TODO: We don't have an explicit CHANZ type. These wires are marked as CHANX. This should be fixed. + if (is_chan(rr_type) && !route_ctx.chanx_util.empty()) { + VTR_ASSERT_SAFE(!route_ctx.chany_util.empty()); + double max_util = 0.; + + if (rr_type == e_rr_type::CHANX) { + int y = rr_graph.node_ylow(node_id); + int layer = rr_graph.node_layer(node_id); + for (int x = rr_graph.node_xlow(node_id); x <= rr_graph.node_xhigh(node_id); x++) { + max_util = std::max(max_util, route_ctx.chanx_util[layer][x][y]); + } + + } else { + VTR_ASSERT_SAFE(rr_type == e_rr_type::CHANY); + int x = rr_graph.node_xlow(node_id); + int layer = rr_graph.node_layer(node_id); + for (int y = rr_graph.node_ylow(node_id); y <= rr_graph.node_yhigh(node_id); y++) { + max_util = std::max(max_util, route_ctx.chany_util[layer][x][y]); + } + } + + cost += std::max(max_util - threshold, 0.) * weight; + } + + return cost; +} + +void reset_rr_node_route_structs(const t_router_opts& route_opts) { + // Resets some extra information about each rr_node that is used only during routing. auto& route_ctx = g_vpr_ctx.mutable_routing(); - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); VTR_ASSERT(route_ctx.rr_node_route_inf.size() == size_t(device_ctx.rr_graph.num_nodes())); - for (const RRNodeId& rr_id : device_ctx.rr_graph.nodes()) { - auto& node_inf = route_ctx.rr_node_route_inf[rr_id]; + for (const RRNodeId rr_id : device_ctx.rr_graph.nodes()) { + t_rr_node_route_inf& node_inf = route_ctx.rr_node_route_inf[rr_id]; node_inf.prev_edge = RREdgeId::INVALID(); - node_inf.acc_cost = 1.0; + node_inf.acc_cost = comp_initial_acc_cost(rr_id, route_opts); node_inf.path_cost = std::numeric_limits::infinity(); node_inf.backward_path_cost = std::numeric_limits::infinity(); node_inf.set_occ(0); @@ -1015,7 +1065,7 @@ float get_cost_from_lookahead(const RouterLookahead& router_lookahead, RRNodeId from_node, RRNodeId to_node, float R_upstream, - const t_conn_cost_params cost_params, + const t_conn_cost_params& cost_params, bool /*is_flat*/) { return router_lookahead.get_expected_cost(from_node, to_node, cost_params, R_upstream); } diff --git a/vpr/src/route/route_common.h b/vpr/src/route/route_common.h index 49ac82a690..9c67467cc5 100644 --- a/vpr/src/route/route_common.h +++ b/vpr/src/route/route_common.h @@ -7,6 +7,48 @@ #include "router_stats.h" #include "globals.h" +/** + * @brief Extra information about each rr_node needed only during routing + * (i.e. during the maze expansion). + */ +struct t_rr_node_route_inf { + /** ID of the edge (globally unique edge ID in the RR Graph) + * that was used to reach this node from the previous node. + * If there is no predecessor, prev_edge = NO_PREVIOUS. + */ + RREdgeId prev_edge; + + /** Accumulated cost term from previous Pathfinder iterations. */ + float acc_cost; + + /** Total cost of the path up to and including this node + + * the expected cost to the target if the timing_driven router + * is being used. + */ + float path_cost; + + /** Total cost of the path up to and including this node. */ + float backward_path_cost; + + /** Upstream resistance to ground from this node in the current + * path search (connection routing), including the resistance + * of the node itself (device_ctx.rr_nodes[index].R). + */ + float R_upstream; + + public: // Accessors + /** @return The current occupancy of the associated rr node. */ + short occ() const { return occ_; } + + public: // Mutators + /** @param new_occ The new occupancy to set. */ + void set_occ(int new_occ) { occ_ = new_occ; } + + private: // Data + /** The current occupancy of the associated rr node. */ + short occ_ = 0; +}; + /** This routine checks to see if this is a resource-feasible routing. * That is, are all rr_node capacity limitations respected? It assumes * that the occupancy arrays are up to date when it is called. */ @@ -118,9 +160,9 @@ void init_route_structs(const Netlist<>& net_list, bool has_choking_point, bool is_flat); -void alloc_and_load_rr_node_route_structs(); +void alloc_and_load_rr_node_route_structs(const t_router_opts& router_opts); -void reset_rr_node_route_structs(); +void reset_rr_node_route_structs(const t_router_opts& route_opts); void reserve_locally_used_opins(HeapInterface* heap, float pres_fac, float acc_fac, bool rip_up_local_opins, bool is_flat); @@ -140,5 +182,5 @@ float get_cost_from_lookahead(const RouterLookahead& router_lookahead, RRNodeId from_node, RRNodeId to_node, float R_upstream, - const t_conn_cost_params cost_params, + const t_conn_cost_params& cost_params, bool is_flat); diff --git a/vpr/src/route/route_path_manager.cpp b/vpr/src/route/route_path_manager.cpp index 58aa565aee..3e920a592a 100644 --- a/vpr/src/route/route_path_manager.cpp +++ b/vpr/src/route/route_path_manager.cpp @@ -1,5 +1,6 @@ #include "route_path_manager.h" #include "vpr_context.h" +#include "route_common.h" PathManager::PathManager() { // Only init data structure if required by RCV @@ -23,7 +24,7 @@ bool PathManager::node_exists_in_tree(t_heap_path* path_data, } } - // Search through route tree set for nodes existance + // Search through route tree set for nodes existence auto node_exists_in_route_tree = route_tree_nodes_.find(to_node); if (node_exists_in_route_tree != route_tree_nodes_.end()) { @@ -70,7 +71,7 @@ void PathManager::alloc_path_struct(t_heap_path*& tptr) { // if (tptr == nullptr) { // Use a free node list to avoid unnecessary data allocation // If there are unused data structures in memory use these - if (freed_nodes_.size() > 0) { + if (!freed_nodes_.empty()) { tptr = freed_nodes_.back(); freed_nodes_.pop_back(); } else { diff --git a/vpr/src/route/route_tree.cpp b/vpr/src/route/route_tree.cpp index cc8f5a8fee..542116cdce 100644 --- a/vpr/src/route/route_tree.cpp +++ b/vpr/src/route/route_tree.cpp @@ -4,6 +4,7 @@ #include "globals.h" #include "netlist_fwd.h" #include "route_debug.h" +#include "route_common.h" #include "rr_graph_fwd.h" #include "vtr_math.h" @@ -13,7 +14,7 @@ RouteTreeNode::RouteTreeNode(RRNodeId _inode, RRSwitchId _parent_switch, RouteTr : inode(_inode) , parent_switch(_parent_switch) , _parent(parent) { - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; re_expand = true; diff --git a/vpr/src/route/route_utilization.cpp b/vpr/src/route/route_utilization.cpp index e4bb2df36a..4885a7f898 100644 --- a/vpr/src/route/route_utilization.cpp +++ b/vpr/src/route/route_utilization.cpp @@ -3,6 +3,7 @@ #include "draw_types.h" #include "globals.h" #include "vpr_utils.h" +#include "route_common.h" vtr::Matrix calculate_routing_usage(e_rr_type rr_type, bool is_flat, bool is_print) { VTR_ASSERT(rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY); diff --git a/vpr/src/route/route_utils.cpp b/vpr/src/route/route_utils.cpp index 2df800adfe..24133023ee 100644 --- a/vpr/src/route/route_utils.cpp +++ b/vpr/src/route/route_utils.cpp @@ -10,6 +10,7 @@ #include "place_and_route.h" #include "route_common.h" #include "route_debug.h" +#include "stats.h" #include "VprTimingGraphResolver.h" #include "route_tree.h" @@ -38,7 +39,7 @@ bool check_net_delays(const Netlist<>& net_list, NetPinsMatrix& net_delay load_net_delay_from_routing(net_list, net_delay_check); - for (auto net_id : net_list.nets()) { + for (ParentNetId net_id : net_list.nets()) { for (size_t ipin = 1; ipin < net_list.net_pins(net_id).size(); ipin++) { if (net_delay_check[net_id][ipin] == 0.) { /* Should be only GLOBAL nets */ if (fabs(net_delay[net_id][ipin]) > ERROR_TOL) { @@ -84,7 +85,8 @@ bool check_net_delays(const Netlist<>& net_list, NetPinsMatrix& net_delay // // Typically, only a small minority of nets (typically > 10%) have their BBs updated // each routing iteration. -void dynamic_update_bounding_boxes(const std::vector& rerouted_nets, std::vector out_bb_updated_nets) { +void dynamic_update_bounding_boxes(const std::vector& rerouted_nets, + std::vector out_bb_updated_nets) { auto& device_ctx = g_vpr_ctx.device(); auto& route_ctx = g_vpr_ctx.mutable_routing(); @@ -270,7 +272,15 @@ void print_overused_nodes_status(const t_router_opts& router_opts, const Overuse VTR_LOG("\n"); } -void print_route_status(int itry, double elapsed_sec, float pres_fac, int num_bb_updated, const RouterStats& router_stats, const OveruseInfo& overuse_info, const WirelengthInfo& wirelength_info, std::shared_ptr timing_info, float est_success_iteration) { +void print_route_status(int itry, + double elapsed_sec, + float pres_fac, + int num_bb_updated, + const RouterStats& router_stats, + const OveruseInfo& overuse_info, + const WirelengthInfo& wirelength_info, + std::shared_ptr timing_info, + float est_success_iteration) { //Iteration VTR_LOG("%4d", itry); @@ -489,7 +499,7 @@ void try_graph(int width_fac, e_graph_type graph_type; e_graph_type graph_directionality; - if (router_opts.route_type == GLOBAL) { + if (router_opts.route_type == e_route_type::GLOBAL) { graph_type = e_graph_type::GLOBAL; graph_directionality = e_graph_type::BIDIR; } else { diff --git a/vpr/src/route/route_utils.h b/vpr/src/route/route_utils.h index 392f764704..6aa2e2d6c7 100644 --- a/vpr/src/route/route_utils.h +++ b/vpr/src/route/route_utils.h @@ -10,8 +10,6 @@ #include "RoutingDelayCalculator.h" -constexpr float CONGESTED_SLOPE_VAL = -0.04; - /** Identifies the two breakpoint types in routing */ typedef enum router_breakpoint_type { BP_ROUTE_ITER, @@ -105,7 +103,15 @@ bool is_iteration_complete(bool routing_is_feasible, const t_router_opts& router void print_overused_nodes_status(const t_router_opts& router_opts, const OveruseInfo& overuse_info); -void print_route_status(int itry, double elapsed_sec, float pres_fac, int num_bb_updated, const RouterStats& router_stats, const OveruseInfo& overuse_info, const WirelengthInfo& wirelength_info, std::shared_ptr timing_info, float est_success_iteration); +void print_route_status(int itry, + double elapsed_sec, + float pres_fac, + int num_bb_updated, + const RouterStats& router_stats, + const OveruseInfo& overuse_info, + const WirelengthInfo& wirelength_info, + std::shared_ptr timing_info, + float est_success_iteration); void print_route_status_header(); diff --git a/vpr/src/route/router_delay_profiling.cpp b/vpr/src/route/router_delay_profiling.cpp index c85c97ff4a..66a8e8e13f 100644 --- a/vpr/src/route/router_delay_profiling.cpp +++ b/vpr/src/route/router_delay_profiling.cpp @@ -54,20 +54,10 @@ bool RouterDelayProfiler::calculate_delay(RRNodeId source_node, * 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. */ - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; auto& route_ctx = g_vpr_ctx.mutable_routing(); - //vtr::ScopedStartFinishTimer t(vtr::string_fmt("Profiling Delay from %s at %d,%d (%s) to %s at %d,%d (%s)", - //rr_graph.node_type_string(RRNodeId(source_node)), - //rr_graph.node_xlow(RRNodeId(source_node)), - //rr_graph.node_ylow(RRNodeId(source_node)), - //rr_node_arch_name(source_node).c_str(), - //rr_graph.node_type_string(RRNodeId(sink_node)), - //rr_graph.node_xlow(RRNodeId(sink_node)), - //rr_graph.node_ylow(RRNodeId(sink_node)), - //rr_node_arch_name(sink_node).c_str())); - RouteTree tree((RRNodeId(source_node))); enable_router_debug(router_opts, ParentNetId(), sink_node, 0, &router_); @@ -102,6 +92,7 @@ bool RouterDelayProfiler::calculate_delay(RRNodeId source_node, -1, false, std::unordered_map()); + std::tie(found_path, std::ignore, cheapest) = router_.timing_driven_route_connection_from_route_tree( tree.root(), sink_node, @@ -245,7 +236,7 @@ vtr::vector calculate_all_path_delays_from_rr_node(RRNodeId src void alloc_routing_structs(const t_chan_width& chan_width, const t_router_opts& router_opts, t_det_routing_arch& det_routing_arch, - std::vector& segment_inf, + const std::vector& segment_inf, const std::vector& directs, bool is_flat) { int warnings; @@ -253,7 +244,7 @@ void alloc_routing_structs(const t_chan_width& chan_width, auto& device_ctx = g_vpr_ctx.mutable_device(); - if (router_opts.route_type == GLOBAL) { + if (router_opts.route_type == e_route_type::GLOBAL) { graph_type = e_graph_type::GLOBAL; } else { graph_type = (det_routing_arch.directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); @@ -270,7 +261,7 @@ void alloc_routing_structs(const t_chan_width& chan_width, &warnings, is_flat); - alloc_and_load_rr_node_route_structs(); + alloc_and_load_rr_node_route_structs(router_opts); } void free_routing_structs() { diff --git a/vpr/src/route/router_delay_profiling.h b/vpr/src/route/router_delay_profiling.h index e03d62abbd..2769a34c45 100644 --- a/vpr/src/route/router_delay_profiling.h +++ b/vpr/src/route/router_delay_profiling.h @@ -19,11 +19,6 @@ class RouterDelayProfiler { * 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. - * @param source_node - * @param sink_node - * @param router_opts - * @param net_delay - * @param layer_num * @return */ bool calculate_delay(RRNodeId source_node, @@ -32,11 +27,6 @@ class RouterDelayProfiler { float* net_delay); /** - * @param physical_tile_type_idx - * @param from_layer - * @param to_layer - * @param dx - * @param dy * @return Return the minimum delay across all output pins (OPINs) on the physical tile identified by "physical_tile_idx" from an * instance of the physical type on the "from_layer" to an input pin (IPIN) that is dx and dy away at its location on "to_layer". */ @@ -57,7 +47,7 @@ vtr::vector calculate_all_path_delays_from_rr_node(RRNodeId src void alloc_routing_structs(const t_chan_width& chan_width, const t_router_opts& router_opts, t_det_routing_arch& det_routing_arch, - std::vector& segment_inf, + const std::vector& segment_inf, const std::vector& directs, bool is_flat); diff --git a/vpr/src/route/router_lookahead/router_lookahead.h b/vpr/src/route/router_lookahead/router_lookahead.h index ff50ff9e9d..1a53ba541d 100644 --- a/vpr/src/route/router_lookahead/router_lookahead.h +++ b/vpr/src/route/router_lookahead/router_lookahead.h @@ -82,12 +82,6 @@ class RouterLookahead { /** * @brief Force creation of lookahead object. * @attention This may involve recomputing the lookahead, so only use if lookahead cache cannot be used. - * @param det_routing_arch - * @param router_lookahead_type - * @param write_lookahead - * @param read_lookahead - * @param segment_inf - * @param is_flat * @return Return a unique pointer that points to the router lookahead object */ std::unique_ptr make_router_lookahead(const t_det_routing_arch& det_routing_arch, @@ -105,12 +99,6 @@ void invalidate_router_lookahead_cache(); /** * @brief Returns lookahead for given rr graph. * @attention Object is cached in RouterContext, but access to cached object should performed via this function. - * @param det_routing_arch - * @param router_lookahead_type - * @param write_lookahead - * @param read_lookahead - * @param segment_inf - * @param is_flat * @return */ const RouterLookahead* get_cached_router_lookahead(const t_det_routing_arch& det_routing_arch, diff --git a/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp index 337fc17161..6d6bbb42ec 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp @@ -1,9 +1,4 @@ -// -// Created by amin on 11/27/23. -// -#include -#include #include #include "router_lookahead_compressed_map.h" #include "connection_router_interface.h" diff --git a/vpr/src/route/router_lookahead/router_lookahead_compressed_map.h b/vpr/src/route/router_lookahead/router_lookahead_compressed_map.h index 4e3e4e4ad8..51d4822784 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_compressed_map.h +++ b/vpr/src/route/router_lookahead/router_lookahead_compressed_map.h @@ -1,7 +1,4 @@ #pragma once -// -// Created by amin on 11/27/23. -// #include #include "vtr_ndmatrix.h" diff --git a/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp index 0dabadb438..010e6b2b85 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp @@ -425,9 +425,6 @@ void ExtendedMapLookahead::compute(const std::vector& segment_inf vtr::ScopedStartFinishTimer timer("Computing connection box lookahead map"); - // Initialize rr_node_route_inf if not already - alloc_and_load_rr_node_route_structs(); - size_t num_segments = segment_inf.size(); std::vector sample_regions = find_sample_regions(num_segments); diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_map.cpp index 224951d77b..2f49b43961 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map.cpp @@ -165,7 +165,7 @@ MapLookahead::MapLookahead(const t_det_routing_arch& det_routing_arch, bool is_f , is_flat_(is_flat) {} float MapLookahead::get_expected_cost(RRNodeId current_node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const { - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; e_rr_type from_rr_type = rr_graph.node_type(current_node); @@ -300,8 +300,8 @@ float MapLookahead::get_expected_cost_flat_router(RRNodeId current_node, RRNodeI /* 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 from_node, RRNodeId to_node, const t_conn_cost_params& params, float /*R_upstream*/) const { - auto& device_ctx = g_vpr_ctx.device(); - auto& rr_graph = device_ctx.rr_graph; + const auto& device_ctx = g_vpr_ctx.device(); + const 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); @@ -334,13 +334,11 @@ std::pair MapLookahead::get_expected_delay_and_cong(RRNodeId from_ * the minimum cost from the given OPIN/SOURCE to the specified SINK considering routing options across all layers. */ for (int layer_num = 0; layer_num < device_ctx.grid.get_num_layers(); layer_num++) { - float this_delay_cost; - float this_cong_cost; - std::tie(this_delay_cost, this_cong_cost) = util::get_cost_from_src_opin(src_opin_delays[from_layer_num][from_tile_index][from_ptc][layer_num], - delta_x, - delta_y, - to_layer_num, - get_wire_cost_entry); + const auto [this_delay_cost, this_cong_cost] = util::get_cost_from_src_opin(src_opin_delays[from_layer_num][from_tile_index][from_ptc][layer_num], + delta_x, + delta_y, + to_layer_num, + get_wire_cost_entry); expected_delay_cost = std::min(expected_delay_cost, this_delay_cost); expected_cong_cost = std::min(expected_cong_cost, this_cong_cost); } @@ -481,27 +479,25 @@ float MapLookahead::get_opin_distance_min_delay(int physical_tile_idx, int from_ static util::Cost_Entry get_wire_cost_entry(e_rr_type rr_type, int seg_index, int from_layer_num, int delta_x, int delta_y, int to_layer_num) { VTR_ASSERT_SAFE(rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY); - - int chan_index = 0; - if (rr_type == e_rr_type::CHANY) { - chan_index = 1; - } - VTR_ASSERT_SAFE(from_layer_num < static_cast(f_wire_cost_map.dim_size(0))); VTR_ASSERT_SAFE(to_layer_num < static_cast(f_wire_cost_map.dim_size(1))); VTR_ASSERT_SAFE(seg_index < static_cast(f_wire_cost_map.dim_size(3))); VTR_ASSERT_SAFE(delta_x < static_cast(f_wire_cost_map.dim_size(4))); VTR_ASSERT_SAFE(delta_y < static_cast(f_wire_cost_map.dim_size(5))); + int chan_index = 0; + if (rr_type == e_rr_type::CHANY) { + chan_index = 1; + } + return f_wire_cost_map[from_layer_num][to_layer_num][chan_index][seg_index][delta_x][delta_y]; } static void compute_router_wire_lookahead(const std::vector& segment_inf_vec) { vtr::ScopedStartFinishTimer timer("Computing wire lookahead"); - auto& device_ctx = g_vpr_ctx.device(); - - auto& grid = device_ctx.grid; + const auto& device_ctx = g_vpr_ctx.device(); + const auto& grid = device_ctx.grid; //Re-allocate f_wire_cost_map = t_wire_cost_map({static_cast(grid.get_num_layers()), diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp index 782c4ed5d9..90ef3903e1 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp @@ -32,7 +32,6 @@ static void dijkstra_flood_to_wires(int itile, RRNodeId inode, util::t_src_opin_ static void dijkstra_flood_to_ipins(RRNodeId node, util::t_chan_ipins_delays& chan_ipins_delays); /** - * @param itile * @return Return the maximum ptc number of the SOURCE/OPINs of a tile type */ static int get_tile_src_opin_max_ptc(int itile); @@ -109,8 +108,8 @@ static std::pair get_adjusted_rr_src_sink_position(RRNodeId rr); // x_max: 5 (x + X_OFFSET) // y_min: 3 (y - Y_OFFSET) // y_max: 7 (y + Y_OFFSET) -#define X_OFFSET 2 -#define Y_OFFSET 2 +static constexpr int X_OFFSET = 2; +static constexpr int Y_OFFSET = 2; // Maximum dijkstra expansions when exploring the CHAN --> IPIN connections // This sets a limit on the dijkstra expansions to reach an IPIN connection. Given that we @@ -120,7 +119,7 @@ static std::pair get_adjusted_rr_src_sink_position(RRNodeId rr); // E.g.: if the constant value is set to 2, the following expansions are perfomed: // - CHANX --> CHANX --> exploration interrupted: Maximum expansion level reached // - CHANX --> IPIN --> exploration interrupted: IPIN found, no need to expand further -#define MAX_EXPANSION_LEVEL 1 +static constexpr int MAX_EXPANSION_LEVEL = 1; // The special segment type index used to identify a direct connection between an OPIN to IPIN that // does not go through the CHANX/CHANY nodes. @@ -481,7 +480,7 @@ t_chan_ipins_delays compute_router_chan_ipin_lookahead() { //We assume that the routing connectivity of each instance of a physical tile is the same, //and so only measure one instance of each type for (int layer_num = 0; layer_num < device_ctx.grid.get_num_layers(); layer_num++) { - for (auto tile_type : device_ctx.physical_tile_types) { + for (const t_physical_tile_type& tile_type : device_ctx.physical_tile_types) { if (device_ctx.grid.num_instances(&tile_type, layer_num) == 0) { continue; } @@ -546,7 +545,7 @@ t_ipin_primitive_sink_delays compute_intra_tile_dijkstra(const RRGraphView& rr_g /* returns index of a node from which to start routing */ RRNodeId get_start_node(int layer, int start_x, int start_y, int target_x, int target_y, e_rr_type rr_type, int seg_index, int track_offset) { - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; const auto& node_lookup = rr_graph.node_lookup(); @@ -587,7 +586,7 @@ RRNodeId get_start_node(int layer, int start_x, int start_y, int target_x, int t } std::pair get_xy_deltas(RRNodeId from_node, RRNodeId to_node) { - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; e_rr_type from_type = rr_graph.node_type(from_node); @@ -780,7 +779,7 @@ t_routing_cost_map get_routing_cost_map(int longest_seg_length, //Finally, now that we have a list of sample locations, run a Dijkstra flood from //each sample location to profile the routing network from this type - t_routing_cost_map routing_cost_map({static_cast(device_ctx.grid.get_num_layers()), device_ctx.grid.width(), device_ctx.grid.height()}); + t_routing_cost_map routing_cost_map({(size_t)device_ctx.grid.get_num_layers(), device_ctx.grid.width(), device_ctx.grid.height()}); if (sample_nodes.empty()) { VTR_LOG_WARN("Unable to find any sample location for segment %s type '%s' (length %d)\n", @@ -928,13 +927,12 @@ void dump_readable_router_lookahead_map(const std::string& file_name, const std: } } } - } // namespace util static void dijkstra_flood_to_wires(int itile, RRNodeId node, util::t_src_opin_delays& src_opin_delays) { - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; struct t_pq_entry { diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.h b/vpr/src/route/router_lookahead/router_lookahead_map_utils.h index 01ea3e9be3..f3d9fc5b8d 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.h +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.h @@ -308,8 +308,6 @@ typedef Cost_Entry (*WireCostFunc)(e_rr_type, int, int, int, int, int); /** * @brief For each tile, iterate over its OPINs and store which segment types are accessible from each OPIN - * @param is_flat - * @return */ t_src_opin_delays compute_router_src_opin_lookahead(bool is_flat); @@ -344,7 +342,6 @@ t_routing_cost_map get_routing_cost_map(int longest_seg_length, /** * @brief Iterate over all of the wire segments accessible from the SOURCE/OPIN (stored in src_opin_delay_map) and return the minimum cost (congestion and delay) across them to the sink * @param src_opin_delay_map - * @param layer_num * @param delta_x * @param delta_y * @param to_layer_num @@ -357,5 +354,7 @@ std::pair get_cost_from_src_opin(const std::map& dim_sizes, WireCostCallBackFunction wire_cost_func); +void dump_readable_router_lookahead_map(const std::string& file_name, + const std::vector& dim_sizes, + WireCostCallBackFunction wire_cost_func); } // namespace util diff --git a/vpr/src/route/rr_graph_generation/clock_connection_builders.cpp b/vpr/src/route/rr_graph_generation/clock_connection_builders.cpp index 074e3b7565..188e1384e0 100644 --- a/vpr/src/route/rr_graph_generation/clock_connection_builders.cpp +++ b/vpr/src/route/rr_graph_generation/clock_connection_builders.cpp @@ -24,7 +24,7 @@ void RoutingToClockConnection::set_clock_switch_point_name(std::string clock_swi void RoutingToClockConnection::set_switch_location(int x, int y, int layer /* =0 */) { switch_location.x = x; switch_location.y = y; - switch_location.layer = layer; + switch_location.layer_num = layer; } void RoutingToClockConnection::set_switch(int arch_switch_index) { @@ -55,12 +55,12 @@ void RoutingToClockConnection::create_switches(const ClockRRGraphBuilder& clock_ auto& rr_graph_builder = device_ctx.rr_graph_builder; const auto& node_lookup = device_ctx.rr_graph.node_lookup(); - RRNodeId virtual_clock_network_root_idx = create_virtual_clock_network_sink_node(switch_location.layer, switch_location.x, switch_location.y); + RRNodeId virtual_clock_network_root_idx = create_virtual_clock_network_sink_node(switch_location.layer_num, switch_location.x, switch_location.y); rr_graph_builder.set_virtual_clock_network_root_idx(virtual_clock_network_root_idx); // rr_node indices for x and y channel routing wires and clock wires to connect to - auto x_wire_indices = node_lookup.find_channel_nodes(switch_location.layer, switch_location.x, switch_location.y, e_rr_type::CHANX); - auto y_wire_indices = node_lookup.find_channel_nodes(switch_location.layer, switch_location.x, switch_location.y, e_rr_type::CHANY); + auto x_wire_indices = node_lookup.find_channel_nodes(switch_location.layer_num, switch_location.x, switch_location.y, e_rr_type::CHANX); + auto y_wire_indices = node_lookup.find_channel_nodes(switch_location.layer_num, switch_location.x, switch_location.y, e_rr_type::CHANY); auto clock_indices = clock_graph.get_rr_node_indices_at_switch_location( clock_to_connect_to, switch_point_name, switch_location.x, switch_location.y); @@ -168,13 +168,11 @@ size_t ClockToClockConneciton::estimate_additional_nodes() { void ClockToClockConneciton::create_switches(const ClockRRGraphBuilder& clock_graph, t_rr_edge_info_set* rr_edges_to_create) { auto& grid = clock_graph.grid(); - auto to_locations = clock_graph.get_switch_locations(to_clock, to_switch); + std::set> to_locations = clock_graph.get_switch_locations(to_clock, to_switch); - for (auto location : to_locations) { - auto x = location.first; - auto y = location.second; + for (auto [x, y] : to_locations) { - auto to_rr_node_indices = clock_graph.get_rr_node_indices_at_switch_location( + std::vector to_rr_node_indices = clock_graph.get_rr_node_indices_at_switch_location( to_clock, to_switch, x, @@ -257,20 +255,20 @@ void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_gra continue; } - auto type = grid.get_physical_type({x, y, layer_num}); + t_physical_tile_type_ptr type = grid.get_physical_type({x, y, layer_num}); // Skip EMPTY type if (is_empty_type(type)) { continue; } - auto width_offset = grid.get_width_offset({x, y, layer_num}); - auto height_offset = grid.get_height_offset({x, y, layer_num}); + int width_offset = grid.get_width_offset({x, y, layer_num}); + int height_offset = grid.get_height_offset({x, y, layer_num}); // Ignore grid locations that do not have blocks bool has_pb_type = false; - auto equivalent_sites = get_equivalent_sites_set(type); - for (auto logical_block : equivalent_sites) { + std::unordered_set equivalent_sites = get_equivalent_sites_set(type); + for (t_logical_block_type_ptr logical_block : equivalent_sites) { if (logical_block->pb_type) { has_pb_type = true; break; @@ -287,7 +285,7 @@ void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_gra continue; } - for (auto clock_pin_idx : type->get_clock_pins_indices()) { + for (int clock_pin_idx : type->get_clock_pins_indices()) { //Can't do anything if pin isn't at this location if (0 == type->pinloc[width_offset][height_offset][side][clock_pin_idx]) { continue; @@ -308,14 +306,14 @@ void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_gra clock_y_offset = -1; // pick the chanx below the block } - auto clock_pin_node_idx = node_lookup.find_node(layer_num, - x, - y, - e_rr_type::IPIN, - clock_pin_idx, - side); + RRNodeId clock_pin_node_idx = node_lookup.find_node(layer_num, + x, + y, + e_rr_type::IPIN, + clock_pin_idx, + side); - auto clock_network_indices = clock_graph.get_rr_node_indices_at_switch_location( + std::vector clock_network_indices = clock_graph.get_rr_node_indices_at_switch_location( clock_to_connect_from, switch_point_name, x + clock_x_offset, diff --git a/vpr/src/route/rr_graph_generation/clock_connection_builders.h b/vpr/src/route/rr_graph_generation/clock_connection_builders.h index 87aefe8d98..72ee94278b 100644 --- a/vpr/src/route/rr_graph_generation/clock_connection_builders.h +++ b/vpr/src/route/rr_graph_generation/clock_connection_builders.h @@ -2,8 +2,6 @@ #include -#include "clock_fwd.h" - #include "rr_graph_clock.h" class ClockRRGraphBuilder; @@ -33,7 +31,7 @@ class RoutingToClockConnection : public ClockConnection { private: std::string clock_to_connect_to; std::string switch_point_name; - Coordinates switch_location; + t_physical_tile_loc switch_location; int arch_switch_idx = OPEN; float fc = 0.; diff --git a/vpr/src/route/rr_graph_generation/clock_fwd.h b/vpr/src/route/rr_graph_generation/clock_fwd.h deleted file mode 100644 index 540b2aa9b3..0000000000 --- a/vpr/src/route/rr_graph_generation/clock_fwd.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -struct Coordinates { - int x = -1; - int y = -1; - int layer = -1; -}; diff --git a/vpr/src/route/rr_graph_generation/clock_network_builders.h b/vpr/src/route/rr_graph_generation/clock_network_builders.h index 584ab78e57..4b9db746d6 100644 --- a/vpr/src/route/rr_graph_generation/clock_network_builders.h +++ b/vpr/src/route/rr_graph_generation/clock_network_builders.h @@ -3,8 +3,6 @@ #include #include -#include "clock_fwd.h" - #include "device_grid.h" #include "rr_graph_builder.h" #include "rr_graph_clock.h" @@ -62,14 +60,14 @@ struct SpineTaps { struct HtreeDrive { std::string name; - Coordinates offset; + t_physical_tile_loc offset; int switch_idx = OPEN; }; struct HtreeTaps { std::string name; - Coordinates offset; - Coordinates increment; + t_physical_tile_loc offset; + t_physical_tile_loc increment; }; class ClockNetwork { diff --git a/vpr/src/route/rr_graph_generation/rr_graph_clock.h b/vpr/src/route/rr_graph_generation/rr_graph_clock.h index 9acd06a436..f387424252 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph_clock.h +++ b/vpr/src/route/rr_graph_generation/rr_graph_clock.h @@ -18,7 +18,7 @@ class ClockConnection; class t_rr_graph_storage; class SwitchPoint { - /* A switch point object: keeps information on the location and and rr_node indices + /* A switch point object: keeps information on the location and rr_node indices * for a certain clock switch. clock connections are grouped with their own unique * name; this object holds information for only one such grouping. * Examples of SwitchPoint(s) are rib-to-spine, driver-to-spine. */ @@ -26,7 +26,7 @@ class SwitchPoint { // [grid_width][grid_height][0..nodes_at_this_location-1] std::vector>> rr_node_indices; // Set of all the locations for this switch point. Used to quickly find - // if the switch point exists at a certian location. + // if the switch point exists at a certain location. std::set> locations; // x,y public: /** Accessors **/ @@ -50,7 +50,7 @@ class SwitchPoints { /* Example: x,y = middle of the chip, switch_point_name == name of main drive * of global clock spine, returns the rr_nodes of all the clock spines that - * start the newtork there*/ + * start the network there*/ std::vector get_rr_node_indices_at_location(std::string switch_point_name, int x, int y) const; @@ -70,7 +70,7 @@ class ClockRRGraphBuilder { int get_and_increment_chany_ptc_num(); /* Reverse lookup for to find the clock source and tap locations for each clock_network - * The map key is the the clock network name and value are all the switch points*/ + * The map key is the clock network name and value are all the switch points*/ std::unordered_map clock_name_to_switch_points; public: @@ -113,7 +113,7 @@ class ClockRRGraphBuilder { static size_t estimate_additional_nodes(const DeviceGrid& grid); /* AA: map the segment indices in all networks to corresponding indices in axis based segment vectors as defined in build_rr_graph - * Reffer to clock_network_builders.h: map_relative_seg_indices*/ + * Refer to clock_network_builders.h: map_relative_seg_indices*/ static void map_relative_seg_indices(const t_unified_to_parallel_seg_index& indices_map); @@ -132,7 +132,7 @@ class ClockRRGraphBuilder { bool edge_remapped) const; public: - /* Creates the routing resourse (rr) graph of the clock network and appends it to the + /* Creates the routing resource (rr) graph of the clock network and appends it to the * existing rr graph created in build_rr_graph for inter-block and intra-block routing. */ void create_and_append_clock_rr_graph(int num_segments_x, t_rr_edge_info_set* rr_edges_to_create); diff --git a/vpr/src/route/rr_graph_generation/rr_graph_sbox.cpp b/vpr/src/route/rr_graph_generation/rr_graph_sbox.cpp index 023b93b15e..3ddb41e0ed 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph_sbox.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph_sbox.cpp @@ -77,8 +77,6 @@ vtr::NdMatrix, 3> alloc_and_load_switch_block_conn(t_chan_width return switch_block_conn; } -#define SBOX_ERROR -1 - /* This routine permutes the track number to connect for topologies * SUBSET, UNIVERSAL, and WILTON. I added FULL (for fully flexible topology) * but the returned value is simply a dummy, since we don't need to permute @@ -94,7 +92,7 @@ int get_simple_switch_block_track(const enum e_side from_side, /* This routine returns the track number to which the from_tracks should * * connect. It supports three simple, Fs = 3, switch blocks. */ - int to_track = SBOX_ERROR; /* Can check to see if it's not set later. */ + int to_track = -1; // Can check to see if it's not set later. if (switch_block_type == SUBSET) { /* NB: Global routing uses SUBSET too */ to_track = from_track; diff --git a/vpr/src/route/rr_graph_generation/rr_graph_sbox.h b/vpr/src/route/rr_graph_generation/rr_graph_sbox.h index f4666f5396..69e098abe7 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph_sbox.h +++ b/vpr/src/route/rr_graph_generation/rr_graph_sbox.h @@ -18,4 +18,9 @@ vtr::NdMatrix, 3> alloc_and_load_switch_block_conn(t_chan_width enum e_switch_block_type switch_block_type, int Fs); -int get_simple_switch_block_track(enum e_side from_side, enum e_side to_side, int from_track, enum e_switch_block_type switch_block_type, const int from_chan_width, const int to_chan_width); +int get_simple_switch_block_track(enum e_side from_side, + enum e_side to_side, + int from_track, + enum e_switch_block_type switch_block_type, + const int from_chan_width, + const int to_chan_width); diff --git a/vpr/src/route/segment_stats.cpp b/vpr/src/route/segment_stats.cpp index 968a12d0c6..f3e693bfcf 100644 --- a/vpr/src/route/segment_stats.cpp +++ b/vpr/src/route/segment_stats.cpp @@ -1,12 +1,13 @@ -#include "vtr_log.h" +#include "segment_stats.h" +#include "vtr_log.h" #include "globals.h" -#include "segment_stats.h" +#include "route_common.h" /*************** Variables and defines local to this module ****************/ -#define LONGLINE 0 +static constexpr int LONGLINE = 0; /******************* Subroutine definitions ********************************/ @@ -33,11 +34,11 @@ void get_segment_usage_stats(std::vector& segment_inf) { {X_AXIS, std::map()}, {Y_AXIS, std::map()}}; - std::set> segment_lengths; - for (const auto& seg_inf : segment_inf) { + std::set> segment_lengths; + for (const t_segment_inf& seg_inf : segment_inf) { int seg_length = seg_inf.longline ? LONGLINE : seg_inf.length; - for (auto ax : {X_AXIS, Y_AXIS}) { + for (e_parallel_axis ax : {X_AXIS, Y_AXIS}) { directed_cap_by_length[ax].insert({seg_length, 0}); directed_occ_by_length[ax].insert({seg_length, 0}); } @@ -56,7 +57,7 @@ void get_segment_usage_stats(std::vector& segment_inf) { {Y_AXIS, std::vector(segment_inf.size(), 0)}}; for (RRNodeId inode : device_ctx.rr_graph.nodes()) { - auto node_type = rr_graph.node_type(inode); + e_rr_type node_type = rr_graph.node_type(inode); if (node_type == e_rr_type::CHANX || node_type == e_rr_type::CHANY) { cost_index = rr_graph.node_cost_index(inode); size_t seg_type = device_ctx.rr_indexed_data[cost_index].seg_index; @@ -64,7 +65,7 @@ void get_segment_usage_stats(std::vector& segment_inf) { const short& inode_capacity = rr_graph.node_capacity(inode); int occ = route_ctx.rr_node_route_inf[inode].occ(); - auto ax = (node_type == e_rr_type::CHANX) ? X_AXIS : Y_AXIS; + e_parallel_axis ax = (node_type == e_rr_type::CHANX) ? X_AXIS : Y_AXIS; directed_occ_by_length[ax][length] += occ; directed_cap_by_length[ax][length] += inode_capacity; @@ -77,8 +78,8 @@ void get_segment_usage_stats(std::vector& segment_inf) { VTR_LOG("\n"); VTR_LOG("Total Number of Wiring Segments by Direction: direction length number\n"); VTR_LOG(" --------- ------ -------\n"); - for (auto length : segment_lengths) { - for (auto ax : {X_AXIS, Y_AXIS}) { + for (int length : segment_lengths) { + for (e_parallel_axis ax : {X_AXIS, Y_AXIS}) { std::string ax_name = (ax == X_AXIS) ? "X" : "Y"; if (directed_cap_by_length[ax][length] != 0) { std::string length_str = (length == LONGLINE) ? "longline" : std::to_string(length); @@ -92,12 +93,12 @@ void get_segment_usage_stats(std::vector& segment_inf) { } } - for (auto ax : {X_AXIS, Y_AXIS}) { + for (e_parallel_axis ax : {X_AXIS, Y_AXIS}) { std::string ax_name = (ax == X_AXIS) ? "X" : "Y"; VTR_LOG("\n"); VTR_LOG("%s - Directed Wiring Segment usage by length: length utilization\n", ax_name.c_str()); VTR_LOG(" ------ -----------\n"); - for (auto length : segment_lengths) { + for (int length : segment_lengths) { if (directed_cap_by_length[ax][length] != 0) { std::string length_str = (length == LONGLINE) ? "longline" : std::to_string(length); utilization = (float)directed_occ_by_length[ax][length] / (float)directed_cap_by_length[ax][length]; @@ -112,13 +113,13 @@ void get_segment_usage_stats(std::vector& segment_inf) { VTR_LOG("\n"); VTR_LOG("Segment occupancy by length: Length utilization\n"); VTR_LOG(" ------ -----------\n"); - for (const auto& seg_length : segment_lengths) { + for (const int seg_length : segment_lengths) { if (directed_cap_by_length[X_AXIS][seg_length] != 0 || directed_cap_by_length[Y_AXIS][seg_length] != 0) { std::string seg_name = "L" + std::to_string(seg_length); int occ = 0; int cap = 0; - for (auto ax : {X_AXIS, Y_AXIS}) { + for (e_parallel_axis ax : {X_AXIS, Y_AXIS}) { occ += directed_occ_by_length[ax][seg_length]; cap += directed_cap_by_length[ax][seg_length]; } @@ -137,7 +138,7 @@ void get_segment_usage_stats(std::vector& segment_inf) { int seg_name_size = static_cast(seg_name.size()); int occ = 0; int cap = 0; - for (auto ax : {X_AXIS, Y_AXIS}) { + for (e_parallel_axis ax : {X_AXIS, Y_AXIS}) { occ += directed_occ_by_type[ax][seg_type]; cap += directed_cap_by_type[ax][seg_type]; }