Skip to content

Commit ce72d60

Browse files
committed
fix EdgeGroups class
Signed-off-by: Dusty DeWeese <[email protected]>
1 parent 0684775 commit ce72d60

File tree

2 files changed

+72
-129
lines changed

2 files changed

+72
-129
lines changed

vpr/src/route/rr_graph.cpp

Lines changed: 62 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <ctime>
55
#include <algorithm>
66
#include <vector>
7+
#include <stack>
78
#include "vtr_assert.h"
89

910
#include "vtr_util.h"
@@ -2960,22 +2961,13 @@ static int pick_best_direct_connect_target_rr_node(const t_rr_graph_storage& rr_
29602961
// Class for building a group of connected edges.
29612962
class EdgeGroups {
29622963
public:
2963-
EdgeGroups()
2964-
: node_count_(std::numeric_limits<size_t>::max()) {}
2964+
EdgeGroups() {}
29652965

2966-
// set_node_count must be invoked before create_sets with the count of
2967-
// nodes. Assumption is that from_node/to_node arguments to
2968-
// add_non_config_edge are less than node_count.
2969-
void set_node_count(size_t node_count) {
2970-
node_count_ = node_count;
2971-
}
2972-
2973-
// Adds non-configurable edge to be group.
2966+
// Adds non-configurable (undirected) edge to be grouped.
29742967
//
29752968
// Returns true if this is a new edge.
29762969
bool add_non_config_edge(int from_node, int to_node) {
2977-
auto result = node_edges_.insert(std::make_pair(from_node, to_node));
2978-
return result.second;
2970+
return graph_[from_node].edges.insert(to_node).second && graph_[to_node].edges.insert(from_node).second;
29792971
}
29802972

29812973
// After add_non_config_edge has been called for all edges, create_sets
@@ -2984,93 +2976,45 @@ class EdgeGroups {
29842976
void create_sets() {
29852977
rr_non_config_node_sets_map_.clear();
29862978

2987-
size_t num_groups = 0;
2988-
std::vector<std::pair<int, int>> merges;
2989-
2990-
VTR_ASSERT(node_count_ != std::numeric_limits<size_t>::max());
2991-
std::vector<int> node_to_node_set(node_count_, OPEN);
2992-
2993-
// First nievely make node groups. When an edge joins two groups,
2994-
// mark it for cleanup latter.
2995-
for (const auto& edge : node_edges_) {
2996-
VTR_ASSERT(edge.first >= 0 && static_cast<size_t>(edge.first) < node_count_);
2997-
VTR_ASSERT(edge.second >= 0 && static_cast<size_t>(edge.second) < node_count_);
2998-
2999-
int& from_set = node_to_node_set[edge.first];
3000-
int& to_set = node_to_node_set[edge.second];
3001-
3002-
if (from_set == OPEN && to_set == OPEN) {
3003-
from_set = num_groups++;
3004-
to_set = from_set;
3005-
} else if (from_set == OPEN && to_set != OPEN) {
3006-
from_set = to_set;
3007-
} else if (from_set != OPEN && to_set == OPEN) {
3008-
to_set = from_set;
3009-
} else {
3010-
VTR_ASSERT(from_set != OPEN);
3011-
VTR_ASSERT(to_set != OPEN);
3012-
3013-
if (from_set != to_set) {
3014-
merges.push_back(std::make_pair(
3015-
std::min(from_set, to_set),
3016-
std::max(from_set, to_set)));
3017-
}
2979+
// https://en.wikipedia.org/wiki/Component_(graph_theory)#Algorithms
2980+
std::vector<size_t> group_size;
2981+
for (auto& node : graph_) {
2982+
if (node.second.set == OPEN) {
2983+
node.second.set = group_size.size();
2984+
group_size.push_back(add_connected_group(node.second));
30182985
}
30192986
}
30202987

3021-
// We are going to always collapse sets to lower ids, so sort
3022-
// the merge list to ensure that the merge first elements are always
3023-
// increasing.
3024-
std::sort(merges.begin(), merges.end(), [](const std::pair<int, int>& a, const std::pair<int, int>& b) {
3025-
return a.first < b.first;
3026-
});
3027-
3028-
// Update final_set_map with the final merge id for the second element.
3029-
// The first element will either be the final value, or already have
3030-
// an entry in the final_set_map (because sorting), so we can depend on
3031-
// find_target_set(first) returning a stable value.
3032-
std::unordered_map<int, int> final_set_map;
3033-
for (const auto& merge : merges) {
3034-
VTR_ASSERT(merge.first < merge.second);
3035-
VTR_ASSERT(merge.first != OPEN);
3036-
VTR_ASSERT(merge.second != OPEN);
3037-
3038-
int target_set = find_target_set(final_set_map, merge.first);
3039-
3040-
final_set_map.insert(std::make_pair(merge.second, target_set));
3041-
}
3042-
3043-
// Finalize merges between node set ids.
3044-
for (auto& set : node_to_node_set) {
3045-
set = find_target_set(final_set_map, set);
3046-
}
3047-
final_set_map.clear();
3048-
30492988
// Sanity check the node sets.
3050-
for (const auto& edge : node_edges_) {
3051-
VTR_ASSERT(node_to_node_set[edge.first] != OPEN);
3052-
VTR_ASSERT(node_to_node_set[edge.second] != OPEN);
3053-
VTR_ASSERT(node_to_node_set[edge.first] == node_to_node_set[edge.second]);
2989+
for (const auto& node : graph_) {
2990+
VTR_ASSERT(node.second.set != OPEN);
2991+
for (const auto& e : node.second.edges) {
2992+
int set = graph_[e].set;
2993+
VTR_ASSERT(set == node.second.set);
2994+
}
30542995
}
30552996

30562997
// Create compact set of sets.
3057-
for (size_t inode = 0; inode < node_to_node_set.size(); ++inode) {
3058-
if (node_to_node_set[inode] != OPEN) {
3059-
rr_non_config_node_sets_map_[node_to_node_set[inode]].push_back(inode);
3060-
}
2998+
rr_non_config_node_sets_map_.resize(group_size.size());
2999+
for (size_t i = 0; i < group_size.size(); i++) {
3000+
rr_non_config_node_sets_map_[i].reserve(group_size[i]);
3001+
}
3002+
for (const auto& node : graph_) {
3003+
rr_non_config_node_sets_map_[node.second.set].push_back(node.first);
30613004
}
30623005
}
30633006

30643007
// Create t_non_configurable_rr_sets from set data.
3008+
// NOTE: The stored graph is undirected, so this may generate reverse edges that don't exist.
30653009
t_non_configurable_rr_sets output_sets() {
30663010
t_non_configurable_rr_sets sets;
3067-
for (auto& item : rr_non_config_node_sets_map_) {
3011+
for (const auto& nodes : rr_non_config_node_sets_map_) {
30683012
std::set<t_node_edge> edge_set;
3069-
std::set<int> node_set(item.second.begin(), item.second.end());
3013+
std::set<int> node_set(nodes.begin(), nodes.end());
30703014

3071-
for (const auto& edge : node_edges_) {
3072-
if (node_set.find(edge.first) != node_set.end()) {
3073-
edge_set.emplace(t_node_edge(edge.first, edge.second));
3015+
for (const auto& src : node_set) {
3016+
for (const auto& dest : graph_[src].edges) {
3017+
edge_set.emplace(t_node_edge(src, dest));
30743018
}
30753019
}
30763020

@@ -3084,8 +3028,8 @@ class EdgeGroups {
30843028
// Set device context structures for non-configurable node sets.
30853029
void set_device_context() {
30863030
std::vector<std::vector<int>> rr_non_config_node_sets;
3087-
for (auto& item : rr_non_config_node_sets_map_) {
3088-
rr_non_config_node_sets.emplace_back(std::move(item.second));
3031+
for (const auto& item : rr_non_config_node_sets_map_) {
3032+
rr_non_config_node_sets.emplace_back(std::move(item));
30893033
}
30903034

30913035
std::unordered_map<int, int> rr_node_to_non_config_node_set;
@@ -3102,67 +3046,56 @@ class EdgeGroups {
31023046
}
31033047

31043048
private:
3105-
// Final target set for given set id.
3106-
static int find_target_set(
3107-
const std::unordered_map<int, int>& final_set_map,
3108-
int set) {
3109-
int target_set = set;
3110-
while (true) {
3111-
auto iter = final_set_map.find(target_set);
3112-
if (iter != final_set_map.end()) {
3113-
target_set = iter->second;
3114-
} else {
3115-
break;
3049+
struct node_data {
3050+
std::unordered_set<int> edges;
3051+
int set = OPEN;
3052+
};
3053+
3054+
// Perform a DFS traversal marking everything reachable with the same set id
3055+
size_t add_connected_group(const node_data& node) {
3056+
// stack contains nodes with edges to mark with node.set
3057+
// The set for each node must be set before pushing it onto the stack
3058+
std::stack<const node_data*> stack;
3059+
stack.push(&node);
3060+
size_t n = 1;
3061+
while (!stack.empty()) {
3062+
auto top = stack.top();
3063+
stack.pop();
3064+
for (auto e : top->edges) {
3065+
auto& next = graph_[e];
3066+
if (next.set != node.set) {
3067+
VTR_ASSERT(next.set == OPEN);
3068+
n++;
3069+
next.set = node.set;
3070+
stack.push(&next);
3071+
}
31163072
}
31173073
}
3118-
3119-
return target_set;
3074+
return n;
31203075
}
31213076

3122-
// Number of nodes. All elements of node_edges_ should be less than this
3123-
// value.
3124-
size_t node_count_;
3125-
31263077
// Set of non-configurable edges.
3127-
std::set<std::pair<int, int>> node_edges_;
3078+
std::unordered_map<int, node_data> graph_;
31283079

31293080
// Compact set of node sets. Map key is arbitrary.
3130-
std::map<int, std::vector<int>> rr_non_config_node_sets_map_;
3081+
std::vector<std::vector<int>> rr_non_config_node_sets_map_;
31313082
};
31323083

3133-
static void expand_non_configurable(int inode, EdgeGroups* groups);
3134-
31353084
//Collects the sets of connected non-configurable edges in the RR graph
31363085
static void create_edge_groups(EdgeGroups* groups) {
3137-
//Walk through the RR graph and recursively expand non-configurable edges
3138-
//to collect the sets of non-configurably connected nodes
31393086
auto& device_ctx = g_vpr_ctx.device();
3140-
groups->set_node_count(device_ctx.rr_nodes.size());
3087+
auto& rr_nodes = device_ctx.rr_nodes;
31413088

3142-
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
3143-
expand_non_configurable(inode, groups);
3089+
for (size_t iedge = 0; iedge < rr_nodes.edges_size(); ++iedge) {
3090+
RREdgeId edge(iedge);
3091+
if (!device_ctx.rr_switch_inf[rr_nodes.edge_switch(edge)].configurable()) {
3092+
groups->add_non_config_edge(size_t(rr_nodes.edge_source_node(edge)), size_t(rr_nodes.edge_sink_node(edge)));
3093+
}
31443094
}
31453095

31463096
groups->create_sets();
31473097
}
31483098

3149-
//Builds a set of non-configurably connected RR graph edges
3150-
static void expand_non_configurable(int inode, EdgeGroups* groups) {
3151-
auto& device_ctx = g_vpr_ctx.device();
3152-
3153-
for (t_edge_size iedge = 0; iedge < device_ctx.rr_nodes[inode].num_edges(); ++iedge) {
3154-
bool edge_non_configurable = !device_ctx.rr_nodes[inode].edge_is_configurable(iedge);
3155-
3156-
if (edge_non_configurable) {
3157-
int to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge);
3158-
3159-
if (groups->add_non_config_edge(inode, to_node)) {
3160-
expand_non_configurable(to_node, groups);
3161-
}
3162-
}
3163-
}
3164-
}
3165-
31663099
t_non_configurable_rr_sets identify_non_configurable_rr_sets() {
31673100
EdgeGroups groups;
31683101
create_edge_groups(&groups);

vpr/src/route/rr_graph_storage.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,11 @@ class t_rr_graph_storage {
289289
return edge_dest_node_[edge];
290290
}
291291

292+
// Get the source node for the specified edge.
293+
RRNodeId edge_source_node(const RREdgeId& edge) const {
294+
return edge_src_node_[edge];
295+
}
296+
292297
// Get the destination node for the iedge'th edge from specified RRNodeId.
293298
//
294299
// This method should generally not be used, and instead first_edge and
@@ -381,6 +386,11 @@ class t_rr_graph_storage {
381386
return node_storage_.size();
382387
}
383388

389+
// Number of RR nodes that can be accessed.
390+
size_t edges_size() const {
391+
return edge_dest_node_.size();
392+
}
393+
384394
// Is the RR graph currently empty?
385395
bool empty() const {
386396
return node_storage_.empty();

0 commit comments

Comments
 (0)