From ffcead74a5f3e639f8592003151c4b68552332e0 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Wed, 4 Dec 2024 16:21:42 -0500 Subject: [PATCH 1/4] use std::vector instead of std::set to make sure that node_sets and edge_sets are stored in the same order --- vpr/src/base/vpr_types.h | 4 ++-- vpr/src/route/check_route.cpp | 26 ++++++++++++++++++++------ vpr/src/route/edge_groups.cpp | 10 +++++----- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index e33c1ac004e..5bf28be3efe 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1656,8 +1656,8 @@ struct t_node_edge { ///@brief Non-configurably connected nodes and edges in the RR graph struct t_non_configurable_rr_sets { - std::set> node_sets; - std::set> edge_sets; + std::vector> node_sets; + std::vector> edge_sets; }; ///@brief Power estimation options diff --git a/vpr/src/route/check_route.cpp b/vpr/src/route/check_route.cpp index fd239d39b52..073d8b1193a 100644 --- a/vpr/src/route/check_route.cpp +++ b/vpr/src/route/check_route.cpp @@ -1,4 +1,5 @@ -#include + +#include "check_route.h" #include "route_common.h" #include "vtr_assert.h" @@ -11,7 +12,7 @@ #include "globals.h" #include "route_export.h" -#include "check_route.h" + #include "rr_graph.h" #include "check_rr_graph.h" #include "read_xml_arch_file.h" @@ -598,9 +599,22 @@ static void check_node_and_range(RRNodeId inode, //Checks that all non-configurable edges are in a legal configuration //This check is slow, so it has been moved out of check_route() static void check_all_non_configurable_edges(const Netlist<>& net_list, bool is_flat) { + const auto& rr_graph = g_vpr_ctx.device().rr_graph; + vtr::ScopedStartFinishTimer timer("Checking to ensure non-configurable edges are legal"); auto non_configurable_rr_sets = identify_non_configurable_rr_sets(); + vtr::vector_map rrnode_nodeset_id(rr_graph.num_nodes(), -1); + + int node_set_id = 0; + for (const auto& node_set : non_configurable_rr_sets.node_sets) { + for (const RRNodeId node_id : node_set) { + VTR_ASSERT_SAFE(rrnode_nodeset_id[node_id] == -1); + rrnode_nodeset_id[node_id] = node_set_id; + } + node_set_id++; + } + for (auto net_id : net_list.nets()) { check_non_configurable_edges(net_list, net_id, @@ -626,7 +640,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, // Collect all the edges used by this net's routing std::set routing_edges; std::set routing_nodes; - for (auto& rt_node : route_ctx.route_trees[net].value().all_nodes()) { + for (const RouteTreeNode& rt_node : route_ctx.route_trees[net].value().all_nodes()) { routing_nodes.insert(rt_node.inode); if (!rt_node.parent()) continue; @@ -640,11 +654,11 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, // 2) That all (required) non-configurable edges are used // //We need to check (2) in addition to (1) to ensure that (1) did not pass - //because the nodes 'happend' to be connected together by configurable + //because the nodes 'happened' to be connected together by configurable //routing (to be legal, by definition, they must be connected by //non-configurable routing). - //Check that all nodes in each non-configurable set are full included if any element + //Check that all nodes in each non-configurable set are fully included if any element //within a set is used by the routing for (const auto& rr_nodes : non_configurable_rr_sets.node_sets) { //Compute the intersection of the routing and current non-configurable nodes set @@ -698,7 +712,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, //Since at least one non-configurable edge is used, to be legal //the full set of non-configurably connected edges must be used. // - //This is somewhat complicted by the fact that non-configurable edges + //This is somewhat complicated by the fact that non-configurable edges //are sometimes bi-directional (e.g. electrical shorts) and so appear //in rr_edges twice (once forward, once backward). Only one of the //paired edges need appear to be correct. diff --git a/vpr/src/route/edge_groups.cpp b/vpr/src/route/edge_groups.cpp index 6b63f7d8823..6ca1e36692a 100644 --- a/vpr/src/route/edge_groups.cpp +++ b/vpr/src/route/edge_groups.cpp @@ -52,14 +52,14 @@ t_non_configurable_rr_sets EdgeGroups::output_sets() { std::set edge_set; std::set node_set(nodes.begin(), nodes.end()); - for (const auto& src : node_set) { - for (const auto& dest : graph_[src].edges) { - edge_set.emplace(t_node_edge(src, dest)); + for (const RRNodeId src : node_set) { + for (const RRNodeId dest : graph_[src].edges) { + edge_set.emplace(src, dest); } } - sets.node_sets.emplace(std::move(node_set)); - sets.edge_sets.emplace(std::move(edge_set)); + sets.node_sets.emplace_back(std::move(node_set)); + sets.edge_sets.emplace_back(std::move(edge_set)); } return sets; From f0550286dd0824f1ce5ed607e0322c5f20c2dc0f Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Wed, 4 Dec 2024 16:29:13 -0500 Subject: [PATCH 2/4] take intersections with used non-configurable rr sets --- vpr/src/route/check_route.cpp | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/vpr/src/route/check_route.cpp b/vpr/src/route/check_route.cpp index 073d8b1193a..21a15d8156e 100644 --- a/vpr/src/route/check_route.cpp +++ b/vpr/src/route/check_route.cpp @@ -44,6 +44,7 @@ static void check_all_non_configurable_edges(const Netlist<>& net_list, bool is_ static bool check_non_configurable_edges(const Netlist<>& net_list, ParentNetId net, const t_non_configurable_rr_sets& non_configurable_rr_sets, + const vtr::vector_map& rrnode_set_id, bool is_flat); static void check_net_for_stubs(const Netlist<>& net_list, ParentNetId net, @@ -602,23 +603,24 @@ static void check_all_non_configurable_edges(const Netlist<>& net_list, bool is_ const auto& rr_graph = g_vpr_ctx.device().rr_graph; vtr::ScopedStartFinishTimer timer("Checking to ensure non-configurable edges are legal"); - auto non_configurable_rr_sets = identify_non_configurable_rr_sets(); + const t_non_configurable_rr_sets non_configurable_rr_sets = identify_non_configurable_rr_sets(); - vtr::vector_map rrnode_nodeset_id(rr_graph.num_nodes(), -1); + vtr::vector_map rrnode_set_ids(rr_graph.num_nodes(), -1); - int node_set_id = 0; + int non_configurable_rr_set_id = 0; for (const auto& node_set : non_configurable_rr_sets.node_sets) { for (const RRNodeId node_id : node_set) { - VTR_ASSERT_SAFE(rrnode_nodeset_id[node_id] == -1); - rrnode_nodeset_id[node_id] = node_set_id; + VTR_ASSERT_SAFE(rrnode_set_ids[node_id] == -1); + rrnode_set_ids[node_id] = non_configurable_rr_set_id; } - node_set_id++; + non_configurable_rr_set_id++; } for (auto net_id : net_list.nets()) { check_non_configurable_edges(net_list, net_id, non_configurable_rr_sets, + rrnode_set_ids, is_flat); } } @@ -630,9 +632,10 @@ static void check_all_non_configurable_edges(const Netlist<>& net_list, bool is_ static bool check_non_configurable_edges(const Netlist<>& net_list, ParentNetId net, const t_non_configurable_rr_sets& non_configurable_rr_sets, + const vtr::vector_map& rrnode_set_id, bool is_flat) { const auto& device_ctx = g_vpr_ctx.device(); - auto& route_ctx = g_vpr_ctx.mutable_routing(); + const auto& route_ctx = g_vpr_ctx.routing(); if (!route_ctx.route_trees[net]) // no routing return true; @@ -640,12 +643,25 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, // Collect all the edges used by this net's routing std::set routing_edges; std::set routing_nodes; + std::set routing_non_configurable_rr_set_ids; for (const RouteTreeNode& rt_node : route_ctx.route_trees[net].value().all_nodes()) { routing_nodes.insert(rt_node.inode); if (!rt_node.parent()) continue; t_node_edge edge = {rt_node.parent()->inode, rt_node.inode}; routing_edges.insert(edge); + + if (rrnode_set_id[rt_node.inode] >= 0) { + routing_non_configurable_rr_set_ids.insert(rrnode_set_id[rt_node.inode]); + } + } + + t_non_configurable_rr_sets used_non_configurable_rr_sets; + used_non_configurable_rr_sets.node_sets.reserve(routing_non_configurable_rr_set_ids.size()); + used_non_configurable_rr_sets.edge_sets.reserve(routing_non_configurable_rr_set_ids.size()); + for (const int set_idx : routing_non_configurable_rr_set_ids) { + used_non_configurable_rr_sets.node_sets.emplace_back(non_configurable_rr_sets.node_sets[set_idx]); + used_non_configurable_rr_sets.edge_sets.emplace_back(non_configurable_rr_sets.edge_sets[set_idx]); } //We need to perform two types of checks: @@ -660,7 +676,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, //Check that all nodes in each non-configurable set are fully included if any element //within a set is used by the routing - for (const auto& rr_nodes : non_configurable_rr_sets.node_sets) { + for (const auto& rr_nodes : used_non_configurable_rr_sets.node_sets) { //Compute the intersection of the routing and current non-configurable nodes set std::vector intersection; std::set_intersection(routing_nodes.begin(), routing_nodes.end(), @@ -699,7 +715,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, //Check that any sets of non-configurable RR graph edges are fully included //in the routing, if any of a set's edges are used - for (const auto& rr_edges : non_configurable_rr_sets.edge_sets) { + for (const auto& rr_edges : used_non_configurable_rr_sets.edge_sets) { //Compute the intersection of the routing and current non-configurable edge set std::vector intersection; std::set_intersection(routing_edges.begin(), routing_edges.end(), From 1a5f0ee32715bc99e0e5a237c246906472de61c7 Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Wed, 4 Dec 2024 16:51:49 -0500 Subject: [PATCH 3/4] add comments --- vpr/src/base/vpr_types.h | 7 ++++- vpr/src/route/check_route.cpp | 52 ++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 5bf28be3efe..56c128360ee 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1654,7 +1654,12 @@ struct t_node_edge { } }; -///@brief Non-configurably connected nodes and edges in the RR graph +/** + * @brief Non-configurably connected nodes and edges in the RR graph + * @note It is assumed that node_sets and edge_sets are stored in the same order, + * meaning that nodes and edges that create an RR set can be accesses using + * the same index. + */ struct t_non_configurable_rr_sets { std::vector> node_sets; std::vector> edge_sets; diff --git a/vpr/src/route/check_route.cpp b/vpr/src/route/check_route.cpp index 21a15d8156e..eed1caf3936 100644 --- a/vpr/src/route/check_route.cpp +++ b/vpr/src/route/check_route.cpp @@ -41,10 +41,24 @@ static void check_locally_used_clb_opins(const t_clb_opins_used& clb_opins_used_ bool is_flat); static void check_all_non_configurable_edges(const Netlist<>& net_list, bool is_flat); + +/** + * @brief Checks that the specified routing is legal with respect to non-configurable edges. + * For routing to be legal if *any* non-configurable edge is used, so must *all* + * other non-configurable edges in the same set + * + * @param net_list A reference to the netlist. + * @param net The net id for which the check is done. + * @param non_configurable_rr_sets Node and edge sets that constitute non-configurable RR sets. + * @param rrnode_set_id Specifies which RR sets each RR node is part of. These indices can be used to + * access elements of node_sets and edge_sets in non_configurable_rr_sets. + * @param is_flat Indicates whether flat routing is enabled. + * @return True if check is done successfully; otherwise false. + */ static bool check_non_configurable_edges(const Netlist<>& net_list, ParentNetId net, const t_non_configurable_rr_sets& non_configurable_rr_sets, - const vtr::vector_map& rrnode_set_id, + const vtr::vector& rrnode_set_id, bool is_flat); static void check_net_for_stubs(const Netlist<>& net_list, ParentNetId net, @@ -67,13 +81,9 @@ void check_route(const Netlist<>& net_list, return; } - int max_pins; - unsigned int ipin; - bool valid, connects; - - 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.routing(); + const auto& route_ctx = g_vpr_ctx.routing(); const size_t num_switches = rr_graph.num_rr_switches(); @@ -85,7 +95,7 @@ void check_route(const Netlist<>& net_list, * is a successful routing, but I want to double check it here. */ recompute_occupancy_from_scratch(net_list, is_flat); - valid = feasible_routing(); + const bool valid = feasible_routing(); if (valid == false) { VPR_ERROR(VPR_ERROR_ROUTE, "Error in check_route -- routing resources are overused.\n"); @@ -97,7 +107,7 @@ void check_route(const Netlist<>& net_list, is_flat); } - max_pins = 0; + int max_pins = 0; for (auto net_id : net_list.nets()) max_pins = std::max(max_pins, (int)net_list.net_pins(net_id).size()); @@ -131,7 +141,7 @@ void check_route(const Netlist<>& net_list, check_switch(rt_node, num_switches); if (rt_node.parent()) { - connects = check_adjacent(rt_node.parent()->inode, rt_node.inode, is_flat); + bool connects = check_adjacent(rt_node.parent()->inode, rt_node.inode, is_flat); if (!connects) { VPR_ERROR(VPR_ERROR_ROUTE, "in check_route: found non-adjacent segments in traceback while checking net %d:\n" @@ -156,7 +166,7 @@ void check_route(const Netlist<>& net_list, num_sinks, net_list.net_sinks(net_id).size()); } - for (ipin = 0; ipin < net_list.net_pins(net_id).size(); ipin++) { + for (size_t ipin = 0; ipin < net_list.net_pins(net_id).size(); ipin++) { if (pin_done[ipin] == false) { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "in check_route: net %zu does not connect to pin %d.\n", size_t(net_id), ipin); @@ -196,7 +206,7 @@ static void check_sink(const Netlist<>& net_list, inode, net_list.net_name(net_id).c_str(), size_t(net_id)); } - VTR_ASSERT(!pin_done[net_pin_index]); /* Should not have found a routed cnnection to it before */ + VTR_ASSERT(!pin_done[net_pin_index]); /* Should not have found a routed connection to it before */ pin_done[net_pin_index] = true; } @@ -605,7 +615,8 @@ static void check_all_non_configurable_edges(const Netlist<>& net_list, bool is_ vtr::ScopedStartFinishTimer timer("Checking to ensure non-configurable edges are legal"); const t_non_configurable_rr_sets non_configurable_rr_sets = identify_non_configurable_rr_sets(); - vtr::vector_map rrnode_set_ids(rr_graph.num_nodes(), -1); + // Specifies which RR set each node is part of. + vtr::vector rrnode_set_ids(rr_graph.num_nodes(), -1); int non_configurable_rr_set_id = 0; for (const auto& node_set : non_configurable_rr_sets.node_sets) { @@ -625,14 +636,10 @@ static void check_all_non_configurable_edges(const Netlist<>& net_list, bool is_ } } -// Checks that the specified routing is legal with respect to non-configurable edges -// -//For routing to be legal if *any* non-configurable edge is used, so must *all* -//other non-configurable edges in the same set static bool check_non_configurable_edges(const Netlist<>& net_list, ParentNetId net, const t_non_configurable_rr_sets& non_configurable_rr_sets, - const vtr::vector_map& rrnode_set_id, + const vtr::vector& rrnode_set_id, bool is_flat) { const auto& device_ctx = g_vpr_ctx.device(); const auto& route_ctx = g_vpr_ctx.routing(); @@ -640,7 +647,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, if (!route_ctx.route_trees[net]) // no routing return true; - // Collect all the edges used by this net's routing + // Collect all the nodes, edges, and RR sets ids used by this net's routing std::set routing_edges; std::set routing_nodes; std::set routing_non_configurable_rr_set_ids; @@ -656,6 +663,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, } } + // Copy used non-configurable RR sets t_non_configurable_rr_sets used_non_configurable_rr_sets; used_non_configurable_rr_sets.node_sets.reserve(routing_non_configurable_rr_set_ids.size()); used_non_configurable_rr_sets.edge_sets.reserve(routing_non_configurable_rr_set_ids.size()); @@ -698,7 +706,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list, routing_nodes.begin(), routing_nodes.end(), std::back_inserter(difference)); - VTR_ASSERT(difference.size() > 0); + VTR_ASSERT(!difference.empty()); std::string msg = vtr::string_fmt( "Illegal routing for net '%s' (#%zu) some " "required non-configurably connected nodes are missing:\n", @@ -821,9 +829,9 @@ class StubFinder { std::set stub_nodes_; }; -//Cheks for stubs in a net's routing. +//Checks for stubs in a net's routing. // -//Stubs (routing branches which don't connect to SINKs) serve no purpose, and only chew up wiring unecessarily. +//Stubs (routing branches which don't connect to SINKs) serve no purpose, and only chew up wiring unnecessarily. //The only exception are stubs required by non-configurable switches (e.g. shorts). // //We treat any configurable stubs as an error. From 96f649410de105397d8c8b8d946b252686d5e04c Mon Sep 17 00:00:00 2001 From: soheilshahrouz Date: Wed, 4 Dec 2024 16:52:13 -0500 Subject: [PATCH 4/4] fix compilation error in test_edge_groups --- vpr/test/test_edge_groups.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vpr/test/test_edge_groups.cpp b/vpr/test/test_edge_groups.cpp index 80bfea5e133..e8b83741afa 100644 --- a/vpr/test/test_edge_groups.cpp +++ b/vpr/test/test_edge_groups.cpp @@ -19,12 +19,12 @@ TEST_CASE("edge_groups_create_sets", "[vpr]") { // Build chains from the given connected sets int max_node_id = 0; std::vector> edges; - for (auto set : connected_sets) { + for (const auto& set : connected_sets) { int last = *set.cbegin(); std::for_each(std::next(set.cbegin()), set.cend(), [&](int node) { - edges.push_back(std::make_pair(last, node)); + edges.emplace_back(last, node); last = node; max_node_id = std::max(max_node_id, node); }); @@ -36,7 +36,7 @@ TEST_CASE("edge_groups_create_sets", "[vpr]") { // Initialize nodes to [0, 1, ..., max_node_id] std::iota(nodes.begin(), nodes.end(), 0); - // Create a Mersenne Twister psuedo-random number generator with seed 1 + // Create a Mersenne Twister pseudo-random number generator with seed 1 std::mt19937 g(1); // Run the test many times, the PRNG will give differently shuffled inputs @@ -66,12 +66,12 @@ TEST_CASE("edge_groups_create_sets", "[vpr]") { t_non_configurable_rr_sets sets = groups.output_sets(); // Check for the expected sets - for (auto set : connected_sets) { + for (const auto& set : connected_sets) { std::set random_set; for (auto elem : set) { random_set.insert(RRNodeId(random_nodes[elem])); } - REQUIRE(sets.node_sets.find(random_set) != sets.node_sets.end()); + REQUIRE(std::find(sets.node_sets.begin(), sets.node_sets.end(), random_set) != sets.node_sets.end()); } } }