3
3
#include < vector>
4
4
5
5
#include " rr_graph_fwd.h"
6
+ #include " rr_node_types.h"
6
7
#include " vtr_assert.h"
7
8
#include " vtr_log.h"
8
9
#include " vtr_memory.h"
@@ -116,10 +117,13 @@ update_route_tree(RouteTreeRoot& rt_root, t_heap* hptr, int target_net_pin_index
116
117
update_route_tree_spatial_lookup_recur (start_of_new_subtree_rt_node.value (), *spatial_rt_lookup);
117
118
}
118
119
119
- /* if the new branch is the only child of its parent, this is the first time
120
- * we are creating this tree, so include the parent in the new branch return */
121
- if (start_of_new_subtree_rt_node.value ().parent .value ().child_nodes ().size () == 1 )
122
- return {start_of_new_subtree_rt_node.value ().parent .value (), sink_rt_node};
120
+ /* if the new branch is the only child of its parent and the parent is a SOURCE,
121
+ * it is the first time we are creating this tree, so include the parent in the new branch return
122
+ * so that it can be included in occupancy calculation.
123
+ * TODO: probably this should be cleaner */
124
+ RouteTreeNode& parent = start_of_new_subtree_rt_node.value ().parent .value ();
125
+ if (parent.child_nodes ().size () == 1 && rr_graph.node_type (parent.inode ) == SOURCE)
126
+ return {parent, sink_rt_node};
123
127
124
128
return {start_of_new_subtree_rt_node.value (), sink_rt_node};
125
129
}
@@ -182,6 +186,7 @@ add_subtree_to_route_tree(RouteTreeRoot& rt_root, t_heap* hptr, int target_net_p
182
186
* ---
183
187
* Walk through new_branch_iswitches and corresponding new_branch_inodes. */
184
188
for (int i=new_branch_inodes.size ()-1 ; i>=0 ; i--){
189
+ /* have to create a tmp_node because add_child copies the node --> reference changes */
185
190
RouteTreeNode tmp_node (new_branch_inodes[i], new_branch_iswitches[i], *last_node_ptr, rt_root);
186
191
187
192
e_rr_type node_type = rr_graph.node_type (new_branch_inodes[i]);
@@ -202,9 +207,9 @@ add_subtree_to_route_tree(RouteTreeRoot& rt_root, t_heap* hptr, int target_net_p
202
207
all_visited.insert (new_branch_inodes[i]);
203
208
}
204
209
205
- // Expand (recursively) each of the main-branch nodes adding any
206
- // non-configurably connected nodes
207
- // Sink is not included, so no need to pass in the node's ipin value.
210
+ // Expand (recursively) each of the main-branch nodes adding any
211
+ // non-configurably connected nodes
212
+ // Sink is not included, so no need to pass in the node's ipin value.
208
213
for (RRNodeId rr_node : main_branch_visited) {
209
214
add_non_configurable_to_route_tree (rr_node_to_rt_node.at (rr_node).value (), false , all_visited, is_flat);
210
215
}
@@ -224,31 +229,34 @@ static void add_non_configurable_to_route_tree(RouteTreeNode& rt_node,
224
229
if (visited.count (rt_node.inode ) && reached_by_non_configurable_edge)
225
230
return ;
226
231
232
+ visited.insert (rt_node.inode );
233
+
227
234
auto & device_ctx = g_vpr_ctx.device ();
228
235
const auto & rr_graph = device_ctx.rr_graph ;
229
236
230
237
VTR_ASSERT (rt_node.root );
231
238
auto & rr_node_to_rt_node = rt_node.root .value ().rr_node_to_rt_node ;
232
239
const RRNodeId rr_node = rt_node.inode ;
233
240
234
- for (int iedge : rr_graph.non_configurable_edges (RRNodeId ( rr_node) )) {
241
+ for (int iedge : rr_graph.non_configurable_edges (rr_node)) {
235
242
// Recursive case: expand children
236
- VTR_ASSERT (!rr_graph.edge_is_configurable (RRNodeId (rr_node), iedge));
237
- RRNodeId to_rr_node = rr_graph.edge_sink_node (RRNodeId (rr_node), iedge);
238
- visited.insert (to_rr_node);
243
+ VTR_ASSERT (!rr_graph.edge_is_configurable (rr_node, iedge));
244
+ RRNodeId to_rr_node = rr_graph.edge_sink_node (rr_node, iedge);
239
245
240
246
if (rr_node_to_rt_node.count (to_rr_node)) // TODO: not 100% sure about this
241
247
continue ;
242
248
243
249
RRSwitchId edge_switch = RRSwitchId (rr_graph.edge_switch (RRNodeId (to_rr_node), iedge));
244
- RouteTreeNode new_node = RouteTreeNode (to_rr_node, edge_switch, rt_node, rt_node.root );
245
- new_node.net_pin_index = OPEN;
250
+
251
+ /* have to create a tmp_node because add_child_front copies the node --> reference changes */
252
+ RouteTreeNode tmp_node = RouteTreeNode (to_rr_node, edge_switch, rt_node, rt_node.root );
253
+ tmp_node.net_pin_index = OPEN;
246
254
if (rr_graph.node_type (RRNodeId (to_rr_node)) == IPIN && !is_flat) {
247
- new_node .re_expand = false ;
255
+ tmp_node .re_expand = false ;
248
256
} else {
249
- new_node .re_expand = true ;
257
+ tmp_node .re_expand = true ;
250
258
}
251
- rt_node.add_child_front (new_node );
259
+ RouteTreeNode& new_node = rt_node.add_child_front (tmp_node );
252
260
253
261
add_non_configurable_to_route_tree (new_node, true , visited, is_flat);
254
262
}
@@ -438,7 +446,7 @@ void print_route_tree(const RouteTreeNode& rt_node, int depth) {
438
446
439
447
auto & device_ctx = g_vpr_ctx.device ();
440
448
const auto & rr_graph = device_ctx.rr_graph ;
441
- VTR_LOG (" %srt_node: %d (%s) \t ipin: %d \t R: %g \t C: %g \t delay: %g" ,
449
+ VTR_LOG (" %srt_node: %d (%s) \t ipin: %d \t R: %g \t C: %g \t delay: %g \t " ,
442
450
indent.c_str (),
443
451
rt_node.inode ,
444
452
rr_graph.node_type_string (RRNodeId (rt_node.inode )),
@@ -447,15 +455,16 @@ void print_route_tree(const RouteTreeNode& rt_node, int depth) {
447
455
rt_node.C_downstream ,
448
456
rt_node.Tdel );
449
457
450
- if (rt_node.parent_switch != RRSwitchId (OPEN)) {
451
- bool parent_edge_configurable = rr_graph.rr_switch_inf (RRSwitchId (rt_node.parent_switch )).configurable ();
458
+ if (rt_node.parent ) {
459
+ VTR_LOG (" parent: %d \t parent_switch: %d" , rt_node.parent .value ().inode , rt_node.parent_switch );
460
+ bool parent_edge_configurable = rr_graph.rr_switch_inf (rt_node.parent_switch ).configurable ();
452
461
if (!parent_edge_configurable) {
453
462
VTR_LOG (" *" );
454
463
}
455
464
}
456
465
457
466
auto & route_ctx = g_vpr_ctx.routing ();
458
- if (route_ctx.rr_node_route_inf [size_t (rt_node.inode )].occ () > rr_graph.node_capacity (RRNodeId ( rt_node.inode ) )) {
467
+ if (route_ctx.rr_node_route_inf [size_t (rt_node.inode )].occ () > rr_graph.node_capacity (rt_node.inode )) {
459
468
VTR_LOG (" x" );
460
469
}
461
470
@@ -721,11 +730,11 @@ t_trace* traceback_from_route_tree(ParentNetId inet, const RouteTreeNode& root,
721
730
static vtr::optional<RouteTreeNode&> prune_route_tree_recurr (RouteTreeNode& node, CBRR& connections_inf, bool force_prune, std::vector<int >* non_config_node_set_usage) {
722
731
// Recursively traverse the route tree rooted at node and remove any congested
723
732
// sub-trees
724
-
725
733
auto & device_ctx = g_vpr_ctx.device ();
726
734
const auto & rr_graph = device_ctx.rr_graph ;
727
735
auto & route_ctx = g_vpr_ctx.routing ();
728
- bool congested = (route_ctx.rr_node_route_inf [size_t (node.inode )].occ () > rr_graph.node_capacity (RRNodeId (node.inode )));
736
+ bool congested = (route_ctx.rr_node_route_inf [size_t (node.inode )].occ () > rr_graph.node_capacity (node.inode ));
737
+
729
738
int node_set = -1 ;
730
739
auto itr = device_ctx.rr_node_to_non_config_node_set .find (size_t (node.inode ));
731
740
if (itr != device_ctx.rr_node_to_non_config_node_set .end ()) {
@@ -756,7 +765,7 @@ static vtr::optional<RouteTreeNode&> prune_route_tree_recurr(RouteTreeNode& node
756
765
}else { // Pruned
757
766
// After removing a child node, check if non_config_node_set_usage
758
767
// needs an update.
759
- if (non_config_node_set_usage != nullptr && node_set != -1 && rr_graph.rr_switch_inf (RRSwitchId ( child.parent_switch ) ).configurable ()) {
768
+ if (non_config_node_set_usage != nullptr && node_set != -1 && rr_graph.rr_switch_inf (child.parent_switch ).configurable ()) {
760
769
(*non_config_node_set_usage)[node_set] -= 1 ;
761
770
VTR_ASSERT ((*non_config_node_set_usage)[node_set] >= 0 );
762
771
}
@@ -771,14 +780,14 @@ static vtr::optional<RouteTreeNode&> prune_route_tree_recurr(RouteTreeNode& node
771
780
// Record sink as reachable
772
781
connections_inf.reached_rt_sink (node.inode );
773
782
774
- return node; // Not pruned
783
+ return node; // Not pruned
775
784
} else {
776
785
VTR_ASSERT (force_prune);
777
786
778
787
// Record as not reached
779
788
connections_inf.toreach_rr_sink (node.net_pin_index );
780
789
781
- return vtr::nullopt; // Pruned
790
+ return vtr::nullopt; // Pruned
782
791
}
783
792
} else if (all_children_pruned) {
784
793
// This node has no children
@@ -809,7 +818,7 @@ static vtr::optional<RouteTreeNode&> prune_route_tree_recurr(RouteTreeNode& node
809
818
810
819
bool reached_non_configurably = false ;
811
820
if (node.parent ) {
812
- reached_non_configurably = !rr_graph.rr_switch_inf (RRSwitchId ( node.parent_switch ) ).configurable ();
821
+ reached_non_configurably = !rr_graph.rr_switch_inf (node.parent_switch ).configurable ();
813
822
814
823
if (reached_non_configurably) {
815
824
// Check if this non-configurable node set is in use.
@@ -910,6 +919,48 @@ vtr::optional<RouteTreeRoot&> prune_route_tree(RouteTreeRoot& rt_root, CBRR& con
910
919
return vtr::nullopt;
911
920
}
912
921
922
+ /* For each non-configurable node set, count the cases in the route tree where:
923
+ * 1. the node is a member of a nonconf set (duh)
924
+ * if not SINK:
925
+ * 2. and there *is* an outgoing edge (we are not at the end of a stub)
926
+ * 3. and that outgoing edge is a configurable switch
927
+ * if SINK:
928
+ * 2. and the incoming edge is a configurable switch
929
+ * (Note: the old code's comments mention that a "non-configurable edge"
930
+ * "to" a sink is a usage of the set, but the code used to check if the
931
+ * edge "from" the SINK, which shouldn't exist, was "configurable". This
932
+ * might be some faulty code carried over.) */
933
+ std::vector<int > get_non_config_node_set_usage (const RouteTreeRoot& rt_root){
934
+ auto & device_ctx = g_vpr_ctx.device ();
935
+ std::vector<int > usage (device_ctx.rr_non_config_node_sets .size (), 0 );
936
+
937
+ const auto & rr_to_nonconf = device_ctx.rr_node_to_non_config_node_set ;
938
+
939
+ for (auto & rt_node: rt_root){
940
+ auto it = rr_to_nonconf.find (size_t (rt_node.inode ));
941
+ if (it == rr_to_nonconf.end ())
942
+ continue ;
943
+
944
+ if (device_ctx.rr_graph .node_type (rt_node.inode ) == SINK){
945
+ if (device_ctx.rr_graph .rr_switch_inf (rt_node.parent_switch ).configurable ()){
946
+ usage[it->second ] += 1 ;
947
+ }
948
+ continue ;
949
+ }
950
+
951
+ if (rt_node.child_nodes ().empty ())
952
+ continue ;
953
+
954
+ for (auto &child: rt_node.child_nodes ()){
955
+ if (device_ctx.rr_graph .rr_switch_inf (child.parent_switch ).configurable ()) {
956
+ usage[it->second ] += 1 ;
957
+ }
958
+ }
959
+ }
960
+
961
+ return usage;
962
+ }
963
+
913
964
void pathfinder_update_cost_from_route_tree (const RouteTreeNode& rt_node, int add_or_sub) {
914
965
/* Update pathfinder cost of all nodes rooted at rt_node, including rt_node itself */
915
966
pathfinder_update_single_node_occupancy (size_t (rt_node.inode ), add_or_sub);
0 commit comments