Skip to content

Commit 5da5db1

Browse files
authored
Merge pull request #3316 from verilog-to-routing/rr_graph_edge_sorting
Add edge sorting method to rr_graph_storage
2 parents 82c0e54 + a3e451f commit 5da5db1

File tree

11 files changed

+124
-317
lines changed

11 files changed

+124
-317
lines changed

libs/librrgraph/src/base/rr_graph_storage.cpp

Lines changed: 51 additions & 291 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#include <climits>
2-
#include "arch_types.h"
32
#include "rr_graph_storage.h"
43
#include "physical_types.h"
4+
#include "rr_graph_fwd.h"
55
#include "vtr_error.h"
66
#include "librrgraph_types.h"
77

88
#include <algorithm>
9+
#include <cstddef>
910

1011
void t_rr_graph_storage::reserve_edges(size_t num_edges) {
1112
edge_src_node_.reserve(num_edges);
@@ -56,289 +57,6 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges
5657
}
5758
}
5859

59-
/* edge_swapper / edge_sort_iterator / edge_compare_src_node_and_configurable_first
60-
* are used to sort the edge data arrays
61-
* edge_src_node_ / edge_dest_node_ / edge_switch_.
62-
*
63-
* edge_sort_iterator is a random access iterator for the edge data arrays.
64-
*
65-
* edge_swapper is a reference for the src/dest/switch tuple, and can convert
66-
* to and from t_rr_edge_info, the value_type for edge_sort_iterator.
67-
*
68-
* edge_compare_src_node_and_configurable_first is a comparision operator
69-
* that first partitions the edge data by source rr node, and then by
70-
* configurable switches first. Sorting by this comparision operator means that
71-
* the edge data is directly usable for each node by simply slicing the arrays.
72-
*
73-
* */
74-
struct edge_swapper {
75-
edge_swapper(t_rr_graph_storage* storage, size_t idx)
76-
: storage_(storage)
77-
, idx_(idx) {}
78-
t_rr_graph_storage* storage_;
79-
size_t idx_;
80-
81-
edge_swapper(const edge_swapper&) = delete;
82-
edge_swapper& operator=(const edge_swapper& other) {
83-
VTR_ASSERT(idx_ < storage_->edge_src_node_.size());
84-
VTR_ASSERT(other.idx_ < storage_->edge_src_node_.size());
85-
86-
RREdgeId edge(idx_);
87-
RREdgeId other_edge(other.idx_);
88-
storage_->edge_src_node_[edge] = storage_->edge_src_node_[other_edge];
89-
storage_->edge_dest_node_[edge] = storage_->edge_dest_node_[other_edge];
90-
storage_->edge_switch_[edge] = storage_->edge_switch_[other_edge];
91-
storage_->edge_remapped_[edge] = storage_->edge_remapped_[other_edge];
92-
return *this;
93-
}
94-
95-
edge_swapper& operator=(const t_rr_edge_info& edge) {
96-
VTR_ASSERT(idx_ < storage_->edge_src_node_.size());
97-
98-
storage_->edge_src_node_[RREdgeId(idx_)] = RRNodeId(edge.from_node);
99-
storage_->edge_dest_node_[RREdgeId(idx_)] = RRNodeId(edge.to_node);
100-
storage_->edge_switch_[RREdgeId(idx_)] = edge.switch_type;
101-
storage_->edge_remapped_[RREdgeId(idx_)] = edge.remapped;
102-
return *this;
103-
}
104-
105-
operator t_rr_edge_info() const {
106-
VTR_ASSERT(idx_ < storage_->edge_src_node_.size());
107-
t_rr_edge_info info(
108-
storage_->edge_src_node_[RREdgeId(idx_)],
109-
storage_->edge_dest_node_[RREdgeId(idx_)],
110-
storage_->edge_switch_[RREdgeId(idx_)],
111-
storage_->edge_remapped_[RREdgeId(idx_)]);
112-
113-
return info;
114-
}
115-
116-
friend class edge_compare;
117-
118-
static void swap(edge_swapper& a, edge_swapper& b) {
119-
VTR_ASSERT(a.idx_ < a.storage_->edge_src_node_.size());
120-
VTR_ASSERT(b.idx_ < a.storage_->edge_src_node_.size());
121-
RREdgeId a_edge(a.idx_);
122-
RREdgeId b_edge(b.idx_);
123-
124-
std::swap(a.storage_->edge_src_node_[a_edge], a.storage_->edge_src_node_[b_edge]);
125-
std::swap(a.storage_->edge_dest_node_[a_edge], a.storage_->edge_dest_node_[b_edge]);
126-
std::swap(a.storage_->edge_switch_[a_edge], a.storage_->edge_switch_[b_edge]);
127-
std::vector<bool>::swap(a.storage_->edge_remapped_[a_edge], a.storage_->edge_remapped_[b_edge]);
128-
}
129-
130-
friend void swap(edge_swapper& a, edge_swapper& b) {
131-
edge_swapper::swap(a, b);
132-
}
133-
};
134-
135-
class edge_sort_iterator {
136-
public:
137-
edge_sort_iterator()
138-
: swapper_(nullptr, 0) {}
139-
edge_sort_iterator(t_rr_graph_storage* storage, size_t idx)
140-
: swapper_(storage, idx) {}
141-
142-
edge_sort_iterator(const edge_sort_iterator& other)
143-
: swapper_(
144-
other.swapper_.storage_,
145-
other.swapper_.idx_) {
146-
}
147-
148-
edge_sort_iterator& operator=(const edge_sort_iterator& other) {
149-
swapper_.storage_ = other.swapper_.storage_;
150-
swapper_.idx_ = other.swapper_.idx_;
151-
152-
return *this;
153-
}
154-
155-
using iterator_category = std::random_access_iterator_tag;
156-
using value_type = t_rr_edge_info;
157-
using reference = edge_swapper&;
158-
using pointer = edge_swapper*;
159-
using difference_type = ssize_t;
160-
161-
// In order for this class to be used as an iterator within the std library,
162-
// it needs to "act" like a pointer. One thing that it should do is that a
163-
// const variable of this type should be de-referenceable. Therefore, this
164-
// method should be const method; however, this requires modifying the class
165-
// and may yield worst performance. For now the std::stable_sort allows this
166-
// but in the future it may not. If this breaks, this is why.
167-
// See issue #2517 and PR #2522
168-
edge_swapper& operator*() {
169-
return this->swapper_;
170-
}
171-
172-
edge_swapper* operator->() {
173-
return &this->swapper_;
174-
}
175-
176-
edge_sort_iterator& operator+=(ssize_t n) {
177-
swapper_.idx_ += n;
178-
return *this;
179-
}
180-
181-
edge_sort_iterator& operator-=(ssize_t n) {
182-
swapper_.idx_ -= n;
183-
return *this;
184-
}
185-
186-
edge_sort_iterator& operator++() {
187-
++swapper_.idx_;
188-
return *this;
189-
}
190-
191-
edge_sort_iterator& operator--() {
192-
--swapper_.idx_;
193-
return *this;
194-
}
195-
196-
friend edge_sort_iterator operator+(const edge_sort_iterator& lhs, ssize_t n) {
197-
edge_sort_iterator ret = lhs;
198-
ret.swapper_.idx_ += n;
199-
return ret;
200-
}
201-
202-
friend edge_sort_iterator operator-(const edge_sort_iterator& lhs, ssize_t n) {
203-
edge_sort_iterator ret = lhs;
204-
ret.swapper_.idx_ -= n;
205-
return ret;
206-
}
207-
208-
friend ssize_t operator-(const edge_sort_iterator& lhs, const edge_sort_iterator& rhs) {
209-
ssize_t diff = lhs.swapper_.idx_;
210-
diff -= rhs.swapper_.idx_;
211-
return diff;
212-
}
213-
214-
friend bool operator==(const edge_sort_iterator& lhs, const edge_sort_iterator& rhs) {
215-
return lhs.swapper_.idx_ == rhs.swapper_.idx_;
216-
}
217-
218-
friend bool operator!=(const edge_sort_iterator& lhs, const edge_sort_iterator& rhs) {
219-
return lhs.swapper_.idx_ != rhs.swapper_.idx_;
220-
}
221-
222-
friend bool operator<(const edge_sort_iterator& lhs, const edge_sort_iterator& rhs) {
223-
return lhs.swapper_.idx_ < rhs.swapper_.idx_;
224-
}
225-
226-
friend bool operator>(const edge_sort_iterator& lhs, const edge_sort_iterator& rhs) {
227-
return lhs.swapper_.idx_ > rhs.swapper_.idx_;
228-
}
229-
230-
friend bool operator>=(const edge_sort_iterator& lhs, const edge_sort_iterator& rhs) {
231-
return lhs.swapper_.idx_ >= rhs.swapper_.idx_;
232-
}
233-
234-
friend bool operator<=(const edge_sort_iterator& lhs, const edge_sort_iterator& rhs) {
235-
return lhs.swapper_.idx_ <= rhs.swapper_.idx_;
236-
}
237-
238-
RREdgeId edge() const {
239-
return RREdgeId(swapper_.idx_);
240-
}
241-
242-
private:
243-
edge_swapper swapper_;
244-
};
245-
246-
class edge_compare_src_node_and_configurable_first {
247-
public:
248-
edge_compare_src_node_and_configurable_first(const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switch_inf)
249-
: rr_switch_inf_(rr_switch_inf) {}
250-
251-
bool operator()(const t_rr_edge_info& lhs, const edge_swapper& rhs) {
252-
auto lhs_src_node = RRNodeId(lhs.from_node);
253-
auto lhs_dest_node = RRNodeId(lhs.to_node);
254-
auto lhs_is_configurable = rr_switch_inf_[RRSwitchId(lhs.switch_type)].configurable();
255-
256-
auto rhs_edge = RREdgeId(rhs.idx_);
257-
auto rhs_src_node = rhs.storage_->edge_src_node_[rhs_edge];
258-
auto rhs_dest_node = rhs.storage_->edge_dest_node_[rhs_edge];
259-
auto rhs_is_configurable = rr_switch_inf_[RRSwitchId(rhs.storage_->edge_switch_[rhs_edge])].configurable();
260-
261-
return std::make_tuple(lhs_src_node, !lhs_is_configurable, lhs_dest_node, lhs.switch_type) < std::make_tuple(rhs_src_node, !rhs_is_configurable, rhs_dest_node, rhs.storage_->edge_switch_[rhs_edge]);
262-
}
263-
264-
bool operator()(const t_rr_edge_info& lhs, const t_rr_edge_info& rhs) {
265-
auto lhs_src_node = lhs.from_node;
266-
auto lhs_dest_node = lhs.to_node;
267-
auto lhs_is_configurable = rr_switch_inf_[RRSwitchId(lhs.switch_type)].configurable();
268-
269-
auto rhs_src_node = rhs.from_node;
270-
auto rhs_dest_node = rhs.to_node;
271-
auto rhs_is_configurable = rr_switch_inf_[RRSwitchId(rhs.switch_type)].configurable();
272-
273-
return std::make_tuple(lhs_src_node, !lhs_is_configurable, lhs_dest_node, lhs.switch_type) < std::make_tuple(rhs_src_node, !rhs_is_configurable, rhs_dest_node, rhs.switch_type);
274-
}
275-
bool operator()(const edge_swapper& lhs, const t_rr_edge_info& rhs) {
276-
auto lhs_edge = RREdgeId(lhs.idx_);
277-
auto lhs_src_node = lhs.storage_->edge_src_node_[lhs_edge];
278-
auto lhs_dest_node = lhs.storage_->edge_dest_node_[lhs_edge];
279-
auto lhs_is_configurable = rr_switch_inf_[RRSwitchId(lhs.storage_->edge_switch_[lhs_edge])].configurable();
280-
281-
auto rhs_src_node = RRNodeId(rhs.from_node);
282-
auto rhs_dest_node = RRNodeId(rhs.to_node);
283-
auto rhs_is_configurable = rr_switch_inf_[RRSwitchId(rhs.switch_type)].configurable();
284-
285-
return std::make_tuple(lhs_src_node, !lhs_is_configurable, lhs_dest_node, lhs.storage_->edge_switch_[lhs_edge]) < std::make_tuple(rhs_src_node, !rhs_is_configurable, rhs_dest_node, rhs.switch_type);
286-
}
287-
bool operator()(const edge_swapper& lhs, const edge_swapper& rhs) {
288-
auto lhs_edge = RREdgeId(lhs.idx_);
289-
auto lhs_src_node = lhs.storage_->edge_src_node_[lhs_edge];
290-
auto lhs_dest_node = lhs.storage_->edge_dest_node_[lhs_edge];
291-
auto lhs_is_configurable = rr_switch_inf_[RRSwitchId(lhs.storage_->edge_switch_[lhs_edge])].configurable();
292-
293-
auto rhs_edge = RREdgeId(rhs.idx_);
294-
auto rhs_src_node = rhs.storage_->edge_src_node_[rhs_edge];
295-
auto rhs_dest_node = rhs.storage_->edge_dest_node_[rhs_edge];
296-
auto rhs_is_configurable = rr_switch_inf_[RRSwitchId(rhs.storage_->edge_switch_[rhs_edge])].configurable();
297-
298-
return std::make_tuple(lhs_src_node, !lhs_is_configurable, lhs_dest_node, lhs.storage_->edge_switch_[lhs_edge]) < std::make_tuple(rhs_src_node, !rhs_is_configurable, rhs_dest_node, rhs.storage_->edge_switch_[rhs_edge]);
299-
}
300-
301-
private:
302-
const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switch_inf_;
303-
};
304-
305-
class edge_compare_dest_node {
306-
public:
307-
bool operator()(const t_rr_edge_info& lhs, const edge_swapper& rhs) {
308-
auto lhs_dest_node = RRNodeId(lhs.to_node);
309-
310-
auto rhs_edge = RREdgeId(rhs.idx_);
311-
auto rhs_dest_node = rhs.storage_->edge_dest_node_[rhs_edge];
312-
313-
return lhs_dest_node < rhs_dest_node;
314-
}
315-
316-
bool operator()(const t_rr_edge_info& lhs, const t_rr_edge_info& rhs) {
317-
auto lhs_dest_node = lhs.to_node;
318-
319-
auto rhs_dest_node = rhs.to_node;
320-
321-
return lhs_dest_node < rhs_dest_node;
322-
}
323-
bool operator()(const edge_swapper& lhs, const t_rr_edge_info& rhs) {
324-
auto lhs_edge = RREdgeId(lhs.idx_);
325-
auto lhs_dest_node = lhs.storage_->edge_dest_node_[lhs_edge];
326-
327-
auto rhs_dest_node = RRNodeId(rhs.to_node);
328-
329-
return lhs_dest_node < rhs_dest_node;
330-
}
331-
bool operator()(const edge_swapper& lhs, const edge_swapper& rhs) {
332-
auto lhs_edge = RREdgeId(lhs.idx_);
333-
auto lhs_dest_node = lhs.storage_->edge_dest_node_[lhs_edge];
334-
335-
auto rhs_edge = RREdgeId(rhs.idx_);
336-
auto rhs_dest_node = rhs.storage_->edge_dest_node_[rhs_edge];
337-
338-
return lhs_dest_node < rhs_dest_node;
339-
}
340-
};
341-
34260
void t_rr_graph_storage::assign_first_edges() {
34361
VTR_ASSERT(node_first_edge_.empty());
34462

@@ -419,6 +137,24 @@ void t_rr_graph_storage::init_fan_in() {
419137
}
420138
}
421139

140+
namespace {
141+
/// Functor for sorting edges according to destination node's ID.
142+
class edge_compare_dest_node {
143+
public:
144+
edge_compare_dest_node(const t_rr_graph_storage& rr_graph_storage) : rr_graph_storage_(rr_graph_storage) {}
145+
146+
bool operator()(RREdgeId lhs, RREdgeId rhs) const {
147+
RRNodeId lhs_dest_node = rr_graph_storage_.edge_sink_node(lhs);
148+
RRNodeId rhs_dest_node = rr_graph_storage_.edge_sink_node(rhs);
149+
150+
return lhs_dest_node < rhs_dest_node;
151+
}
152+
153+
private:
154+
const t_rr_graph_storage& rr_graph_storage_;
155+
};
156+
} // namespace
157+
422158
size_t t_rr_graph_storage::count_rr_switches(const std::vector<t_arch_switch_inf>& arch_switch_inf,
423159
t_arch_switch_fanin& arch_switch_fanins) {
424160
VTR_ASSERT(!partitioned_);
@@ -429,10 +165,7 @@ size_t t_rr_graph_storage::count_rr_switches(const std::vector<t_arch_switch_inf
429165

430166
// Sort by destination node to collect per node/per switch fan in values
431167
// This sort is safe to do because partition_edges() has not been invoked yet.
432-
std::stable_sort(
433-
edge_sort_iterator(this, 0),
434-
edge_sort_iterator(this, edge_dest_node_.size()),
435-
edge_compare_dest_node());
168+
sort_edges(edge_compare_dest_node(*this));
436169

437170
// Collect the fan-in per switch type for each node in the graph
438171
// Record the unique switch type/fanin combinations
@@ -527,6 +260,35 @@ void t_rr_graph_storage::mark_edges_as_rr_switch_ids() {
527260
remapped_edges_ = true;
528261
}
529262

263+
namespace{
264+
/// Functor for sorting edges according to source node, with configurable edges coming first
265+
class edge_compare_src_node_and_configurable_first {
266+
public:
267+
edge_compare_src_node_and_configurable_first(const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switch_inf, const t_rr_graph_storage& rr_graph_storage)
268+
: rr_switch_inf_(rr_switch_inf),
269+
rr_graph_storage_(rr_graph_storage) {}
270+
271+
bool operator()(RREdgeId lhs, RREdgeId rhs) const {
272+
273+
RRNodeId lhs_dest_node = rr_graph_storage_.edge_sink_node(lhs);
274+
RRNodeId lhs_src_node = rr_graph_storage_.edge_source_node(lhs);
275+
RRSwitchId lhs_switch_type = RRSwitchId(rr_graph_storage_.edge_switch(lhs));
276+
bool lhs_is_configurable = rr_switch_inf_[lhs_switch_type].configurable();
277+
278+
RRNodeId rhs_dest_node = rr_graph_storage_.edge_sink_node(rhs);
279+
RRNodeId rhs_src_node = rr_graph_storage_.edge_source_node(rhs);
280+
RRSwitchId rhs_switch_type = RRSwitchId(rr_graph_storage_.edge_switch(rhs));
281+
bool rhs_is_configurable = rr_switch_inf_[rhs_switch_type].configurable();
282+
283+
return std::make_tuple(lhs_src_node, !lhs_is_configurable, lhs_dest_node, lhs_switch_type) < std::make_tuple(rhs_src_node, !rhs_is_configurable, rhs_dest_node, rhs_switch_type);
284+
}
285+
286+
private:
287+
const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switch_inf_;
288+
const t_rr_graph_storage& rr_graph_storage_;
289+
};
290+
} // namespace
291+
530292
void t_rr_graph_storage::partition_edges(const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switches) {
531293
if (partitioned_) {
532294
return;
@@ -539,9 +301,7 @@ void t_rr_graph_storage::partition_edges(const vtr::vector<RRSwitchId, t_rr_swit
539301
// by assign_first_edges()
540302
// - Edges within a source node have the configurable edges before the
541303
// non-configurable edges.
542-
std::stable_sort(edge_sort_iterator(this, 0),
543-
edge_sort_iterator(this, edge_src_node_.size()),
544-
edge_compare_src_node_and_configurable_first(rr_switches));
304+
sort_edges(edge_compare_src_node_and_configurable_first(rr_switches, *this));
545305

546306
partitioned_ = true;
547307

0 commit comments

Comments
 (0)