Skip to content

Commit 64f07ca

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

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"
@@ -2958,22 +2959,13 @@ static int pick_best_direct_connect_target_rr_node(const t_rr_graph_storage& rr_
29582959
// Class for building a group of connected edges.
29592960
class EdgeGroups {
29602961
public:
2961-
EdgeGroups()
2962-
: node_count_(std::numeric_limits<size_t>::max()) {}
2962+
EdgeGroups() {}
29632963

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

29792971
// After add_non_config_edge has been called for all edges, create_sets
@@ -2982,93 +2974,45 @@ class EdgeGroups {
29822974
void create_sets() {
29832975
rr_non_config_node_sets_map_.clear();
29842976

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

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

30542995
// Create compact set of sets.
3055-
for (size_t inode = 0; inode < node_to_node_set.size(); ++inode) {
3056-
if (node_to_node_set[inode] != OPEN) {
3057-
rr_non_config_node_sets_map_[node_to_node_set[inode]].push_back(inode);
3058-
}
2996+
rr_non_config_node_sets_map_.resize(group_size.size());
2997+
for (size_t i = 0; i < group_size.size(); i++) {
2998+
rr_non_config_node_sets_map_[i].reserve(group_size[i]);
2999+
}
3000+
for (const auto& node : graph_) {
3001+
rr_non_config_node_sets_map_[node.second.set].push_back(node.first);
30593002
}
30603003
}
30613004

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

3069-
for (const auto& edge : node_edges_) {
3070-
if (node_set.find(edge.first) != node_set.end()) {
3071-
edge_set.emplace(t_node_edge(edge.first, edge.second));
3013+
for (const auto& src : node_set) {
3014+
for (const auto& dest : graph_[src].edges) {
3015+
edge_set.emplace(t_node_edge(src, dest));
30723016
}
30733017
}
30743018

@@ -3082,8 +3026,8 @@ class EdgeGroups {
30823026
// Set device context structures for non-configurable node sets.
30833027
void set_device_context() {
30843028
std::vector<std::vector<int>> rr_non_config_node_sets;
3085-
for (auto& item : rr_non_config_node_sets_map_) {
3086-
rr_non_config_node_sets.emplace_back(std::move(item.second));
3029+
for (const auto& item : rr_non_config_node_sets_map_) {
3030+
rr_non_config_node_sets.emplace_back(std::move(item));
30873031
}
30883032

30893033
std::unordered_map<int, int> rr_node_to_non_config_node_set;
@@ -3100,67 +3044,56 @@ class EdgeGroups {
31003044
}
31013045

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

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

31273078
// Compact set of node sets. Map key is arbitrary.
3128-
std::map<int, std::vector<int>> rr_non_config_node_sets_map_;
3079+
std::vector<std::vector<int>> rr_non_config_node_sets_map_;
31293080
};
31303081

3131-
static void expand_non_configurable(int inode, EdgeGroups* groups);
3132-
31333082
//Collects the sets of connected non-configurable edges in the RR graph
31343083
static void create_edge_groups(EdgeGroups* groups) {
3135-
//Walk through the RR graph and recursively expand non-configurable edges
3136-
//to collect the sets of non-configurably connected nodes
31373084
auto& device_ctx = g_vpr_ctx.device();
3138-
groups->set_node_count(device_ctx.rr_nodes.size());
3085+
auto& rr_nodes = device_ctx.rr_nodes;
31393086

3140-
for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
3141-
expand_non_configurable(inode, groups);
3087+
for (size_t iedge = 0; iedge < rr_nodes.edges_size(); ++iedge) {
3088+
RREdgeId edge(iedge);
3089+
if (!device_ctx.rr_switch_inf[rr_nodes.edge_switch(edge)].configurable()) {
3090+
groups->add_non_config_edge(size_t(rr_nodes.edge_source_node(edge)), size_t(rr_nodes.edge_sink_node(edge)));
3091+
}
31423092
}
31433093

31443094
groups->create_sets();
31453095
}
31463096

3147-
//Builds a set of non-configurably connected RR graph edges
3148-
static void expand_non_configurable(int inode, EdgeGroups* groups) {
3149-
auto& device_ctx = g_vpr_ctx.device();
3150-
3151-
for (t_edge_size iedge = 0; iedge < device_ctx.rr_nodes[inode].num_edges(); ++iedge) {
3152-
bool edge_non_configurable = !device_ctx.rr_nodes[inode].edge_is_configurable(iedge);
3153-
3154-
if (edge_non_configurable) {
3155-
int to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge);
3156-
3157-
if (groups->add_non_config_edge(inode, to_node)) {
3158-
expand_non_configurable(to_node, groups);
3159-
}
3160-
}
3161-
}
3162-
}
3163-
31643097
t_non_configurable_rr_sets identify_non_configurable_rr_sets() {
31653098
EdgeGroups groups;
31663099
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
@@ -293,6 +293,11 @@ class t_rr_graph_storage {
293293
return edge_dest_node_[edge];
294294
}
295295

296+
// Get the source node for the specified edge.
297+
RRNodeId edge_source_node(const RREdgeId& edge) const {
298+
return edge_src_node_[edge];
299+
}
300+
296301
// Get the destination node for the iedge'th edge from specified RRNodeId.
297302
//
298303
// This method should generally not be used, and instead first_edge and
@@ -385,6 +390,11 @@ class t_rr_graph_storage {
385390
return node_storage_.size();
386391
}
387392

393+
// Number of RR nodes that can be accessed.
394+
size_t edges_size() const {
395+
return edge_dest_node_.size();
396+
}
397+
388398
// Is the RR graph currently empty?
389399
bool empty() const {
390400
return node_storage_.empty();

0 commit comments

Comments
 (0)