1
1
#pragma once
2
2
3
3
#include < functional>
4
- #include < iostream>
5
4
#include < iterator>
6
5
#include < list>
7
6
#include < stack>
8
7
#include < unordered_map>
9
- #include < unordered_set>
10
8
11
9
#include " connection_based_routing_fwd.h"
12
10
#include " route_tree_fwd.h"
13
- #include " rr_graph_fwd.h"
14
11
#include " spatial_route_tree_lookup.h"
15
12
#include " vtr_optional.h"
16
13
17
- class RTRecIterator ;
18
-
19
14
/* *
20
15
* @brief A single route tree node
21
16
*
@@ -69,9 +64,15 @@ class RouteTreeNode {
69
64
70
65
/* * Emplace child to the front of _child_nodes.
71
66
* For best performance, call with constructor args
72
- * (will construct the node in the parent's list directly and save a copy) */
67
+ * (will construct the node in the parent's list directly and save a copy)
68
+ * Implemented in this file to enable template deduction */
73
69
template <class ... Args>
74
- RouteTreeNode& emplace_child (Args&&... args);
70
+ inline RouteTreeNode& emplace_child (Args&&... args) {
71
+ _child_nodes.emplace_front (std::forward<Args>(args)...);
72
+ RouteTreeNode& new_node = _child_nodes.front ();
73
+ new_node.parent = *this ; // Zeroed out after copy constructor
74
+ return new_node;
75
+ }
75
76
76
77
/* * Remove child node by value. O(N) operation. */
77
78
void remove_child (const RouteTreeNode&);
@@ -84,7 +85,9 @@ class RouteTreeNode {
84
85
void remove_child_if (const std::function<bool (RouteTreeNode&)>&);
85
86
86
87
/* * Get a list of child nodes. Useful for traversal. */
87
- const std::list<RouteTreeNode>& child_nodes (void ) const ;
88
+ inline const std::list<RouteTreeNode>& child_nodes (void ) const {
89
+ return _child_nodes;
90
+ }
88
91
89
92
/* * Print information about this subtree to stdout. */
90
93
void print (void ) const ;
@@ -106,6 +109,78 @@ class RouteTreeNode {
106
109
std::list<RouteTreeNode> _child_nodes;
107
110
};
108
111
112
+ /* * Recursive iterator implementation for a RouteTreeNode.
113
+ * This replaces the traceback traversal, which goes over the tree
114
+ * in a depth-first, pre-order fashion.
115
+ * This implementation uses a stack to do this,
116
+ * which is not optimal for copying, so expect bad performance if using
117
+ * <algorithm> fns on it.
118
+ * Ideas about how to do it with less state are welcome.
119
+ * (Using raw ptrs instead of optional here since this code can be a hotspot) */
120
+ class RTRecIterator {
121
+ public:
122
+ using iterator_category = std::forward_iterator_tag;
123
+ using difference_type = std::ptrdiff_t ;
124
+ using value_type = RouteTreeNode;
125
+ using pointer = RouteTreeNode*;
126
+ using reference = const RouteTreeNode&;
127
+
128
+ inline RTRecIterator () = default;
129
+ inline RTRecIterator (const RouteTreeNode* node) {
130
+ if (!node) return ;
131
+ _root = node;
132
+ _stack.push (node);
133
+ }
134
+
135
+ /* * Access element. UB if stack is empty. (iterator == end()) */
136
+ inline reference operator *() const {
137
+ return *_stack.top ();
138
+ }
139
+ /* * ++it: Move to the next node. */
140
+ inline RTRecIterator& operator ++() {
141
+ if (_stack.empty ()) // we are at end(), do nothing
142
+ return *this ;
143
+ const RouteTreeNode* node = _stack.top ();
144
+ _stack.pop ();
145
+ if (node->child_nodes ().empty ()) // no child nodes to expand, do nothing
146
+ return *this ;
147
+ // push child nodes in reverse order
148
+ for (auto it = node->child_nodes ().rbegin (); it != node->child_nodes ().rend (); ++it) {
149
+ _stack.push (std::addressof (*it));
150
+ }
151
+ return *this ;
152
+ }
153
+ /* * it++: Make a copy of this iterator and move to the next node. (expect performance hit) */
154
+ inline RTRecIterator operator ++(int ) {
155
+ RTRecIterator tmp = *this ;
156
+ ++(*this );
157
+ return tmp;
158
+ }
159
+ /* * Compare the original root and the current stack top. */
160
+ inline bool operator ==(const RTRecIterator& rhs) {
161
+ if (_root != rhs._root ) // root nodes aren't equal (most common case when rhs == end())
162
+ return false ;
163
+ if (_stack.empty () && rhs._stack .empty ()) // both are end()
164
+ return true ;
165
+ if (_stack.empty () || rhs._stack .empty ()) // only one of the stacks are empty
166
+ return false ;
167
+ // true if same root nodes and same stack tops
168
+ // (a bug if the tree changed in between but that's going to break things anyway)
169
+ return *(*this ) == *(rhs);
170
+ }
171
+ inline bool operator !=(const RTRecIterator& rhs) {
172
+ return !(*this == rhs);
173
+ }
174
+
175
+ private:
176
+ /* * Stack of nodes to visit.
177
+ * std::stack can't be too slow here: it's std::deque under the hood which allocates
178
+ * a 512B chunk right away and doesn't realloc */
179
+ std::stack<const RouteTreeNode*> _stack;
180
+ /* The root node of the iterator. Useful for comparisons. */
181
+ const RouteTreeNode* _root = nullptr ;
182
+ };
183
+
109
184
/* * Top level route tree used in timing analysis and keeping partial routing state.
110
185
* Contains the root node and a lookup from RRNodeIds to RouteTreeNode&s in the tree. */
111
186
class RouteTree {
@@ -174,17 +249,21 @@ class RouteTree {
174
249
using iterator = RTRecIterator;
175
250
class Iterable {
176
251
public:
177
- Iterable (const RouteTreeNode& root)
252
+ inline Iterable (const RouteTreeNode* root)
178
253
: _root(root) {}
179
- const RouteTreeNode& _root;
180
- iterator begin () const ;
181
- iterator end () const ;
254
+ const RouteTreeNode* _root;
255
+ inline iterator begin () const {
256
+ return iterator (_root);
257
+ }
258
+ inline iterator end () const {
259
+ return iterator ();
260
+ }
182
261
};
183
262
184
263
/* * Get an iterable for all nodes under this RouteTree (walks the tree).
185
264
* Take care to iterate by reference.
186
265
* Copying a RouteTreeNode is a recursive action and it zeroes out the parent reference. */
187
- Iterable all_nodes (void ) const ;
266
+ inline Iterable all_nodes (void ) const { return Iterable ( std::addressof (_root)); }
188
267
189
268
/* * Get a reference to the root RouteTreeNode. */
190
269
inline const RouteTreeNode& root (void ) const { return _root; }
@@ -230,47 +309,3 @@ class RouteTree {
230
309
* index "inode". */
231
310
std::unordered_map<RRNodeId, vtr::optional<RouteTreeNode&>> _rr_node_to_rt_node;
232
311
};
233
-
234
- /* Recursive iterator implementation for a RouteTreeNode.
235
- * This replaces the traceback traversal, which goes over the tree
236
- * in a depth-first, pre-order fashion.
237
- * This implementation uses a stack to do this,
238
- * which is not optimal for copying, so expect bad performance if using
239
- * <algorithm> fns on it.
240
- * Ideas about how to do it with less state are welcome. */
241
- class RTRecIterator {
242
- public:
243
- using iterator_category = std::forward_iterator_tag;
244
- using difference_type = std::ptrdiff_t ;
245
- using value_type = RouteTreeNode;
246
- using pointer = RouteTreeNode*;
247
- using reference = const RouteTreeNode&;
248
-
249
- RTRecIterator () = default ;
250
- RTRecIterator (vtr::optional<const RouteTreeNode&> node);
251
-
252
- /* Required operators for a forward iterator. */
253
- reference operator *() const ;
254
- RTRecIterator& operator ++();
255
- RTRecIterator operator ++(int );
256
- bool operator ==(const RTRecIterator& rhs);
257
- bool operator !=(const RTRecIterator& rhs);
258
-
259
- private:
260
- /* Stack of nodes to visit. */
261
- std::stack<vtr::optional<const RouteTreeNode&>> _stack;
262
- /* The root node of the iterator. Useful for comparisons. */
263
- vtr::optional<const RouteTreeNode&> _root;
264
- };
265
-
266
- /* Emplace child to the front of _child_nodes.
267
- * For best performance, call with constructor args
268
- * (will construct the node in the parent's list directly and save a copy)
269
- * Implemented in this file to enable template deduction */
270
- template <class ... Args>
271
- RouteTreeNode& RouteTreeNode::emplace_child (Args&&... args) {
272
- _child_nodes.emplace_front (std::forward<Args>(args)...);
273
- RouteTreeNode& new_node = _child_nodes.front ();
274
- new_node.parent = *this ; // Zeroed out after copy constructor
275
- return new_node;
276
- }
0 commit comments