@@ -36,17 +36,17 @@ std::tuple<bool, bool, RTExploredNode> ConnectionRouter<Heap>::timing_driven_rou
36
36
retry = timing_driven_route_connection_common_setup (rt_root, sink_node, cost_params, bounding_box);
37
37
38
38
if (!std::isinf (rr_node_route_inf_[sink_node].path_cost )) {
39
- rcv_path_manager.update_route_tree_set (rcv_path_data[sink_node]);
40
39
// Only the `index`, `prev_edge`, and `rcv_path_backward_delay` fields of `out`
41
40
// are used after this function returns.
42
41
RTExploredNode out;
43
42
out.index = sink_node;
44
43
out.prev_edge = rr_node_route_inf_[sink_node].prev_edge ;
45
44
if (rcv_path_manager.is_enabled ()) {
46
45
out.rcv_path_backward_delay = rcv_path_data[sink_node]->backward_delay ;
46
+ rcv_path_manager.update_route_tree_set (rcv_path_data[sink_node]);
47
+ rcv_path_manager.empty_heap ();
47
48
}
48
49
heap_.empty_heap ();
49
- rcv_path_manager.empty_heap ();
50
50
return std::make_tuple (true , /* retry=*/ false , out);
51
51
} else {
52
52
reset_path_costs ();
@@ -159,34 +159,29 @@ std::tuple<bool, bool, RTExploredNode> ConnectionRouter<Heap>::timing_driven_rou
159
159
sink_node,
160
160
cost_params,
161
161
net_bounding_box);
162
- }
163
162
164
- if (std::isinf (rr_node_route_inf_[sink_node].path_cost )) {
165
163
VTR_LOG (" %s\n " , describe_unrouteable_connection (source_node, sink_node, is_flat_).c_str ());
166
164
167
165
heap_.empty_heap ();
168
166
rcv_path_manager.empty_heap ();
169
167
return std::make_tuple (false , retry_with_full_bb, RTExploredNode ());
170
168
}
171
169
172
- rcv_path_manager.update_route_tree_set (rcv_path_data[sink_node]);
173
170
RTExploredNode out;
174
171
out.index = sink_node;
175
172
out.prev_edge = rr_node_route_inf_[sink_node].prev_edge ;
176
173
if (rcv_path_manager.is_enabled ()) {
177
174
out.rcv_path_backward_delay = rcv_path_data[sink_node]->backward_delay ;
175
+ rcv_path_manager.update_route_tree_set (rcv_path_data[sink_node]);
176
+ rcv_path_manager.empty_heap ();
178
177
}
179
178
heap_.empty_heap ();
180
- rcv_path_manager.empty_heap ();
181
179
182
180
return std::make_tuple (true , retry_with_full_bb, out);
183
181
}
184
182
185
- // Finds a path to sink_node, starting from the elements currently in the heap.
186
- //
183
+ // Finds a path to sink_node, starting from the elements currently in the heap.
187
184
// This is the core maze routing routine.
188
- //
189
- // Returns either the last element of the path, or nullptr if no path is found
190
185
template <typename Heap>
191
186
void ConnectionRouter<Heap>::timing_driven_route_connection_from_heap(RRNodeId sink_node,
192
187
const t_conn_cost_params& cost_params,
@@ -223,7 +218,7 @@ void ConnectionRouter<Heap>::timing_driven_route_connection_from_heap(RRNodeId s
223
218
target_bb.layer_min = rr_graph_->node_layer (RRNodeId (sink_node));
224
219
target_bb.layer_max = rr_graph_->node_layer (RRNodeId (sink_node));
225
220
226
- // Start measuring time before the barrier
221
+ // Start measuring path search time
227
222
std::chrono::steady_clock::time_point begin_time = std::chrono::steady_clock::now ();
228
223
229
224
HeapNode cheapest;
@@ -262,9 +257,9 @@ void ConnectionRouter<Heap>::timing_driven_route_connection_from_heap(RRNodeId s
262
257
target_bb);
263
258
}
264
259
265
- // Stop measuring time after the barrier and the heap is reset.
260
+ // Stop measuring path search time
266
261
std::chrono::steady_clock::time_point end_time = std::chrono::steady_clock::now ();
267
- this -> sssp_total_time += std::chrono::duration_cast<std::chrono::microseconds>(end_time - begin_time);
262
+ path_search_cumulative_time += std::chrono::duration_cast<std::chrono::microseconds>(end_time - begin_time);
268
263
}
269
264
270
265
// Find shortest paths from specified route tree to all nodes in the RR graph
@@ -293,9 +288,6 @@ vtr::vector<RRNodeId, RTExploredNode> ConnectionRouter<Heap>::timing_driven_find
293
288
//
294
289
// Since there is no single *target* node this uses Dijkstra's algorithm
295
290
// with a modified exit condition (runs until heap is empty).
296
- //
297
- // Note that to re-use code used for the regular A*-based router we use a
298
- // no-operation lookahead which always returns zero.
299
291
template <typename Heap>
300
292
vtr::vector<RRNodeId, RTExploredNode> ConnectionRouter<Heap>::timing_driven_find_all_shortest_paths_from_heap(
301
293
const t_conn_cost_params& cost_params,
@@ -308,6 +300,9 @@ vtr::vector<RRNodeId, RTExploredNode> ConnectionRouter<Heap>::timing_driven_find
308
300
VTR_LOGV_DEBUG (router_debug_, " Initial heap empty (no source)\n " );
309
301
}
310
302
303
+ // Start measuring path search time
304
+ std::chrono::steady_clock::time_point begin_time = std::chrono::steady_clock::now ();
305
+
311
306
HeapNode cheapest;
312
307
while (heap_.try_pop (cheapest)) {
313
308
// inode with cheapest total cost in current route tree to be expanded on
@@ -344,6 +339,10 @@ vtr::vector<RRNodeId, RTExploredNode> ConnectionRouter<Heap>::timing_driven_find
344
339
}
345
340
}
346
341
342
+ // Stop measuring path search time
343
+ std::chrono::steady_clock::time_point end_time = std::chrono::steady_clock::now ();
344
+ path_search_cumulative_time += std::chrono::duration_cast<std::chrono::microseconds>(end_time - begin_time);
345
+
347
346
return cheapest_paths;
348
347
}
349
348
@@ -354,14 +353,6 @@ void ConnectionRouter<Heap>::timing_driven_expand_cheapest(RRNodeId from_node,
354
353
const t_conn_cost_params& cost_params,
355
354
const t_bb& bounding_box,
356
355
const t_bb& target_bb) {
357
- /* I only re-expand a node if both the "known" backward cost is lower *
358
- * in the new expansion (this is necessary to prevent loops from *
359
- * forming in the routing and causing havoc) *and* the expected total *
360
- * cost to the sink is lower than the old value. Different R_upstream *
361
- * values could make a path with lower back_path_cost less desirable *
362
- * than one with higher cost. Test whether or not I should disallow *
363
- * re-expansion based on a higher total cost. */
364
-
365
356
float best_total_cost = rr_node_route_inf_[from_node].path_cost ;
366
357
if (best_total_cost == new_total_cost) {
367
358
// Explore from this node, since its total cost is exactly the same as
@@ -374,7 +365,7 @@ void ConnectionRouter<Heap>::timing_driven_expand_cheapest(RRNodeId from_node,
374
365
current.index = from_node;
375
366
current.backward_path_cost = rr_node_route_inf_[from_node].backward_path_cost ;
376
367
current.prev_edge = rr_node_route_inf_[from_node].prev_edge ;
377
- current.R_upstream = rr_node_R_upstream [from_node];
368
+ current.R_upstream = rr_node_route_inf_ [from_node]. R_upstream ;
378
369
379
370
VTR_LOGV_DEBUG (router_debug_, " Better cost to %d\n " , from_node);
380
371
VTR_LOGV_DEBUG (router_debug_, " New total cost: %g\n " , new_total_cost);
@@ -541,6 +532,7 @@ void ConnectionRouter<Heap>::timing_driven_add_to_heap(const t_conn_cost_params&
541
532
// Initialized to current
542
533
RTExploredNode next;
543
534
next.R_upstream = current.R_upstream ;
535
+ next.index = to_node;
544
536
next.prev_edge = from_edge;
545
537
next.total_cost = std::numeric_limits<float >::infinity (); // Not used directly
546
538
next.backward_path_cost = current.backward_path_cost ;
@@ -556,8 +548,6 @@ void ConnectionRouter<Heap>::timing_driven_add_to_heap(const t_conn_cost_params&
556
548
evaluate_timing_driven_node_costs (&next,
557
549
cost_params,
558
550
from_node,
559
- to_node,
560
- from_edge,
561
551
target_node);
562
552
563
553
float best_total_cost = rr_node_route_inf_[to_node].path_cost ;
@@ -566,7 +556,19 @@ void ConnectionRouter<Heap>::timing_driven_add_to_heap(const t_conn_cost_params&
566
556
float new_total_cost = next.total_cost ;
567
557
float new_back_cost = next.backward_path_cost ;
568
558
569
- if (best_back_cost > new_back_cost) { // TODO: double check the performance of expansion condition
559
+ // We need to only expand this node if it is a better path. And we need to
560
+ // update its `rr_node_route_inf` data as we put it into the heap; there may
561
+ // be other (previously explored) paths to this node in the heap already,
562
+ // but they will be pruned when we pop those heap nodes later as we'll see
563
+ // they have inferior costs to what is in the `rr_node_route_inf` data for
564
+ // this node.
565
+ // FIXME: Adding a link to the FPT paper when it is public
566
+ //
567
+ // When RCV is enabled, prune based on the RCV-specific total path cost (see
568
+ // in `compute_node_cost_using_rcv` in `evaluate_timing_driven_node_costs`)
569
+ // to allow detours to get better QoR.
570
+ if ((!rcv_path_manager.is_enabled () && best_back_cost > new_back_cost) ||
571
+ (rcv_path_manager.is_enabled () && best_total_cost > new_total_cost)) {
570
572
VTR_LOGV_DEBUG (router_debug_, " Expanding to node %d (%s)\n " , to_node,
571
573
describe_rr_node (device_ctx.rr_graph ,
572
574
device_ctx.grid ,
@@ -581,16 +583,7 @@ void ConnectionRouter<Heap>::timing_driven_add_to_heap(const t_conn_cost_params&
581
583
// Pre-heap prune to keep the heap small, by not putting paths which are known to be
582
584
// sub-optimal (at this point in time) into the heap.
583
585
584
- update_cheapest (next, to_node);
585
- // Use the already created next path structure pointer when RCV is enabled
586
- if (rcv_path_manager.is_enabled ()) {
587
- rcv_path_manager.move (rcv_path_data[to_node], next.path_data );
588
-
589
- rcv_path_data[to_node]->path_rr = rcv_path_data[from_node]->path_rr ;
590
- rcv_path_data[to_node]->edge = rcv_path_data[from_node]->edge ;
591
- rcv_path_data[to_node]->path_rr .push_back (from_node);
592
- rcv_path_data[to_node]->edge .push_back (from_edge);
593
- }
586
+ update_cheapest (next, from_node);
594
587
595
588
heap_.add_to_heap ({new_total_cost, to_node});
596
589
update_router_stats (router_stats_,
@@ -678,15 +671,16 @@ void ConnectionRouter<Heap>::empty_rcv_route_tree_set() {
678
671
template <typename Heap>
679
672
void ConnectionRouter<Heap>::set_rcv_enabled(bool enable) {
680
673
rcv_path_manager.set_enabled (enable);
674
+ if (enable) {
675
+ rcv_path_data.resize (rr_node_route_inf_.size ());
676
+ }
681
677
}
682
678
683
679
// Calculates the cost of reaching to_node
684
680
template <typename Heap>
685
681
void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* to,
686
682
const t_conn_cost_params& cost_params,
687
683
RRNodeId from_node,
688
- RRNodeId to_node,
689
- RREdgeId from_edge,
690
684
RRNodeId target_node) {
691
685
/* new_costs.backward_cost: is the "known" part of the cost to this node -- the
692
686
* congestion cost of all the routing resources back to the existing route
@@ -698,15 +692,15 @@ void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* t
698
692
*/
699
693
700
694
// Info for the switch connecting from_node to_node
701
- int iswitch = rr_nodes_.edge_switch (from_edge );
695
+ int iswitch = rr_nodes_.edge_switch (to-> prev_edge );
702
696
bool switch_buffered = rr_switch_inf_[iswitch].buffered ();
703
697
bool reached_configurably = rr_switch_inf_[iswitch].configurable ();
704
698
float switch_R = rr_switch_inf_[iswitch].R ;
705
699
float switch_Tdel = rr_switch_inf_[iswitch].Tdel ;
706
700
float switch_Cinternal = rr_switch_inf_[iswitch].Cinternal ;
707
701
708
702
// To node info
709
- auto rc_index = rr_graph_->node_rc_index (to_node );
703
+ auto rc_index = rr_graph_->node_rc_index (to-> index );
710
704
float node_C = rr_rc_data_[rc_index].C ;
711
705
float node_R = rr_rc_data_[rc_index].R ;
712
706
@@ -745,7 +739,7 @@ void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* t
745
739
746
740
float cong_cost = 0 .;
747
741
if (reached_configurably) {
748
- cong_cost = get_rr_cong_cost (to_node , cost_params.pres_fac );
742
+ cong_cost = get_rr_cong_cost (to-> index , cost_params.pres_fac );
749
743
} else {
750
744
// Reached by a non-configurable edge.
751
745
// Therefore the from_node and to_node are part of the same non-configurable node set.
@@ -759,8 +753,8 @@ void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* t
759
753
// cost.
760
754
cong_cost = 0 .;
761
755
}
762
- if (conn_params_->has_choking_spot_ && is_flat_ && rr_graph_->node_type (to_node ) == IPIN) {
763
- auto find_res = conn_params_->connection_choking_spots_ .find (to_node );
756
+ if (conn_params_->has_choking_spot_ && is_flat_ && rr_graph_->node_type (to-> index ) == IPIN) {
757
+ auto find_res = conn_params_->connection_choking_spots_ .find (to-> index );
764
758
if (find_res != conn_params_->connection_choking_spots_ .end ()) {
765
759
cong_cost = cong_cost / pow (2 , (float )find_res->second );
766
760
}
@@ -772,7 +766,7 @@ void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* t
772
766
773
767
if (cost_params.bend_cost != 0 .) {
774
768
t_rr_type from_type = rr_graph_->node_type (from_node);
775
- t_rr_type to_type = rr_graph_->node_type (to_node );
769
+ t_rr_type to_type = rr_graph_->node_type (to-> index );
776
770
if ((from_type == CHANX && to_type == CHANY) || (from_type == CHANY && to_type == CHANX)) {
777
771
to->backward_path_cost += cost_params.bend_cost ; // Bend cost
778
772
}
@@ -782,20 +776,17 @@ void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* t
782
776
783
777
if (rcv_path_manager.is_enabled () && to->path_data != nullptr ) {
784
778
to->path_data ->backward_delay += cost_params.criticality * Tdel;
785
- to->path_data ->backward_cong += (1 . - cost_params.criticality ) * get_rr_cong_cost (to_node , cost_params.pres_fac );
779
+ to->path_data ->backward_cong += (1 . - cost_params.criticality ) * get_rr_cong_cost (to-> index , cost_params.pres_fac );
786
780
787
- total_cost = compute_node_cost_using_rcv (cost_params, to_node , target_node, to->path_data ->backward_delay , to->path_data ->backward_cong , to->R_upstream );
781
+ total_cost = compute_node_cost_using_rcv (cost_params, to-> index , target_node, to->path_data ->backward_delay , to->path_data ->backward_cong , to->R_upstream );
788
782
} else {
789
783
const auto & device_ctx = g_vpr_ctx.device ();
790
784
// Update total cost
791
- float expected_cost = router_lookahead_.get_expected_cost (to_node,
792
- target_node,
793
- cost_params,
794
- to->R_upstream );
785
+ float expected_cost = router_lookahead_.get_expected_cost (to->index , target_node, cost_params, to->R_upstream );
795
786
VTR_LOGV_DEBUG (router_debug_ && !std::isfinite (expected_cost),
796
787
" Lookahead from %s (%s) to %s (%s) is non-finite, expected_cost = %f, to->R_upstream = %f\n " ,
797
- rr_node_arch_name (to_node , is_flat_).c_str (),
798
- describe_rr_node (device_ctx.rr_graph , device_ctx.grid , device_ctx.rr_indexed_data , to_node , is_flat_).c_str (),
788
+ rr_node_arch_name (to-> index , is_flat_).c_str (),
789
+ describe_rr_node (device_ctx.rr_graph , device_ctx.grid , device_ctx.rr_indexed_data , to-> index , is_flat_).c_str (),
799
790
rr_node_arch_name (target_node, is_flat_).c_str (),
800
791
describe_rr_node (device_ctx.rr_graph , device_ctx.grid , device_ctx.rr_indexed_data , target_node, is_flat_).c_str (),
801
792
expected_cost, to->R_upstream );
@@ -885,7 +876,7 @@ void ConnectionRouter<Heap>::add_route_tree_node_to_heap(
885
876
rr_node_route_inf_[inode].path_cost = tot_cost;
886
877
rr_node_route_inf_[inode].prev_edge = RREdgeId::INVALID ();
887
878
rr_node_route_inf_[inode].backward_path_cost = backward_path_cost;
888
- rr_node_R_upstream [inode] = R_upstream;
879
+ rr_node_route_inf_ [inode]. R_upstream = R_upstream;
889
880
heap_.push_back ({tot_cost, inode});
890
881
891
882
// push_back_node(&heap_, rr_node_route_inf_,
@@ -898,7 +889,7 @@ void ConnectionRouter<Heap>::add_route_tree_node_to_heap(
898
889
rr_node_route_inf_[inode].path_cost = expected_total_cost;
899
890
rr_node_route_inf_[inode].prev_edge = RREdgeId::INVALID ();
900
891
rr_node_route_inf_[inode].backward_path_cost = backward_path_cost;
901
- rr_node_R_upstream [inode] = R_upstream;
892
+ rr_node_route_inf_ [inode]. R_upstream = R_upstream;
902
893
903
894
rcv_path_manager.alloc_path_struct (rcv_path_data[inode]);
904
895
rcv_path_data[inode]->backward_delay = rt_node.Tdel ;
0 commit comments