Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Faster check_non_configurable_edges #2839

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1654,10 +1654,15 @@ 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::set<std::set<RRNodeId>> node_sets;
std::set<std::set<t_node_edge>> edge_sets;
std::vector<std::set<RRNodeId>> node_sets;
std::vector<std::set<t_node_edge>> edge_sets;
};

///@brief Power estimation options
Expand Down
96 changes: 67 additions & 29 deletions vpr/src/route/check_route.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <cstdio>

#include "check_route.h"

#include "route_common.h"
#include "vtr_assert.h"
Expand All @@ -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"
Expand Down Expand Up @@ -40,9 +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<RRNodeId, int>& rrnode_set_id,
bool is_flat);
static void check_net_for_stubs(const Netlist<>& net_list,
ParentNetId net,
Expand All @@ -65,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();

Expand All @@ -83,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");
Expand All @@ -95,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());

Expand Down Expand Up @@ -129,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"
Expand All @@ -154,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);
Expand Down Expand Up @@ -194,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;
}

Expand Down Expand Up @@ -598,40 +610,66 @@ 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();
const t_non_configurable_rr_sets non_configurable_rr_sets = identify_non_configurable_rr_sets();

// Specifies which RR set each node is part of.
vtr::vector<RRNodeId, int> 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) {
for (const RRNodeId node_id : node_set) {
VTR_ASSERT_SAFE(rrnode_set_ids[node_id] == -1);
rrnode_set_ids[node_id] = non_configurable_rr_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);
}
}

// 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<RRNodeId, int>& 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;

// 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<t_node_edge> routing_edges;
std::set<RRNodeId> routing_nodes;
for (auto& rt_node : route_ctx.route_trees[net].value().all_nodes()) {
std::set<int> 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]);
}
}

// 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());
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:
Expand All @@ -640,13 +678,13 @@ 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) {
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<RRNodeId> intersection;
std::set_intersection(routing_nodes.begin(), routing_nodes.end(),
Expand All @@ -668,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",
Expand All @@ -685,7 +723,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<t_node_edge> intersection;
std::set_intersection(routing_edges.begin(), routing_edges.end(),
Expand All @@ -698,7 +736,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.
Expand Down Expand Up @@ -791,9 +829,9 @@ class StubFinder {
std::set<int> 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.
Expand Down
10 changes: 5 additions & 5 deletions vpr/src/route/edge_groups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ t_non_configurable_rr_sets EdgeGroups::output_sets() {
std::set<t_node_edge> edge_set;
std::set<RRNodeId> 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;
Expand Down
10 changes: 5 additions & 5 deletions vpr/test/test_edge_groups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::pair<int, int>> 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);
});
Expand All @@ -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
Expand Down Expand Up @@ -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<RRNodeId> 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());
}
}
}
Expand Down
Loading