@@ -36,17 +36,17 @@ std::tuple<bool, bool, RTExploredNode> ConnectionRouter<Heap>::timing_driven_rou
3636 retry = timing_driven_route_connection_common_setup (rt_root, sink_node, cost_params, bounding_box);
3737
3838 if (!std::isinf (rr_node_route_inf_[sink_node].path_cost )) {
39- rcv_path_manager.update_route_tree_set (rcv_path_data[sink_node]);
4039 // Only the `index`, `prev_edge`, and `rcv_path_backward_delay` fields of `out`
4140 // are used after this function returns.
4241 RTExploredNode out;
4342 out.index = sink_node;
4443 out.prev_edge = rr_node_route_inf_[sink_node].prev_edge ;
4544 if (rcv_path_manager.is_enabled ()) {
4645 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 ();
4748 }
4849 heap_.empty_heap ();
49- rcv_path_manager.empty_heap ();
5050 return std::make_tuple (true , /* retry=*/ false , out);
5151 } else {
5252 reset_path_costs ();
@@ -159,34 +159,29 @@ std::tuple<bool, bool, RTExploredNode> ConnectionRouter<Heap>::timing_driven_rou
159159 sink_node,
160160 cost_params,
161161 net_bounding_box);
162- }
163162
164- if (std::isinf (rr_node_route_inf_[sink_node].path_cost )) {
165163 VTR_LOG (" %s\n " , describe_unrouteable_connection (source_node, sink_node, is_flat_).c_str ());
166164
167165 heap_.empty_heap ();
168166 rcv_path_manager.empty_heap ();
169167 return std::make_tuple (false , retry_with_full_bb, RTExploredNode ());
170168 }
171169
172- rcv_path_manager.update_route_tree_set (rcv_path_data[sink_node]);
173170 RTExploredNode out;
174171 out.index = sink_node;
175172 out.prev_edge = rr_node_route_inf_[sink_node].prev_edge ;
176173 if (rcv_path_manager.is_enabled ()) {
177174 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 ();
178177 }
179178 heap_.empty_heap ();
180- rcv_path_manager.empty_heap ();
181179
182180 return std::make_tuple (true , retry_with_full_bb, out);
183181}
184182
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.
187184// This is the core maze routing routine.
188- //
189- // Returns either the last element of the path, or nullptr if no path is found
190185template <typename Heap>
191186void ConnectionRouter<Heap>::timing_driven_route_connection_from_heap(RRNodeId sink_node,
192187 const t_conn_cost_params& cost_params,
@@ -223,7 +218,7 @@ void ConnectionRouter<Heap>::timing_driven_route_connection_from_heap(RRNodeId s
223218 target_bb.layer_min = rr_graph_->node_layer (RRNodeId (sink_node));
224219 target_bb.layer_max = rr_graph_->node_layer (RRNodeId (sink_node));
225220
226- // Start measuring time before the barrier
221+ // Start measuring path search time
227222 std::chrono::steady_clock::time_point begin_time = std::chrono::steady_clock::now ();
228223
229224 HeapNode cheapest;
@@ -262,9 +257,9 @@ void ConnectionRouter<Heap>::timing_driven_route_connection_from_heap(RRNodeId s
262257 target_bb);
263258 }
264259
265- // Stop measuring time after the barrier and the heap is reset.
260+ // Stop measuring path search time
266261 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);
268263}
269264
270265// 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
293288//
294289// Since there is no single *target* node this uses Dijkstra's algorithm
295290// 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.
299291template <typename Heap>
300292vtr::vector<RRNodeId, RTExploredNode> ConnectionRouter<Heap>::timing_driven_find_all_shortest_paths_from_heap(
301293 const t_conn_cost_params& cost_params,
@@ -308,6 +300,9 @@ vtr::vector<RRNodeId, RTExploredNode> ConnectionRouter<Heap>::timing_driven_find
308300 VTR_LOGV_DEBUG (router_debug_, " Initial heap empty (no source)\n " );
309301 }
310302
303+ // Start measuring path search time
304+ std::chrono::steady_clock::time_point begin_time = std::chrono::steady_clock::now ();
305+
311306 HeapNode cheapest;
312307 while (heap_.try_pop (cheapest)) {
313308 // 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
344339 }
345340 }
346341
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+
347346 return cheapest_paths;
348347}
349348
@@ -354,14 +353,6 @@ void ConnectionRouter<Heap>::timing_driven_expand_cheapest(RRNodeId from_node,
354353 const t_conn_cost_params& cost_params,
355354 const t_bb& bounding_box,
356355 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-
365356 float best_total_cost = rr_node_route_inf_[from_node].path_cost ;
366357 if (best_total_cost == new_total_cost) {
367358 // 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,
374365 current.index = from_node;
375366 current.backward_path_cost = rr_node_route_inf_[from_node].backward_path_cost ;
376367 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 ;
378369
379370 VTR_LOGV_DEBUG (router_debug_, " Better cost to %d\n " , from_node);
380371 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&
541532 // Initialized to current
542533 RTExploredNode next;
543534 next.R_upstream = current.R_upstream ;
535+ next.index = to_node;
544536 next.prev_edge = from_edge;
545537 next.total_cost = std::numeric_limits<float >::infinity (); // Not used directly
546538 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&
556548 evaluate_timing_driven_node_costs (&next,
557549 cost_params,
558550 from_node,
559- to_node,
560- from_edge,
561551 target_node);
562552
563553 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&
566556 float new_total_cost = next.total_cost ;
567557 float new_back_cost = next.backward_path_cost ;
568558
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)) {
570572 VTR_LOGV_DEBUG (router_debug_, " Expanding to node %d (%s)\n " , to_node,
571573 describe_rr_node (device_ctx.rr_graph ,
572574 device_ctx.grid ,
@@ -581,16 +583,7 @@ void ConnectionRouter<Heap>::timing_driven_add_to_heap(const t_conn_cost_params&
581583 // Pre-heap prune to keep the heap small, by not putting paths which are known to be
582584 // sub-optimal (at this point in time) into the heap.
583585
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);
594587
595588 heap_.add_to_heap ({new_total_cost, to_node});
596589 update_router_stats (router_stats_,
@@ -678,15 +671,16 @@ void ConnectionRouter<Heap>::empty_rcv_route_tree_set() {
678671template <typename Heap>
679672void ConnectionRouter<Heap>::set_rcv_enabled(bool enable) {
680673 rcv_path_manager.set_enabled (enable);
674+ if (enable) {
675+ rcv_path_data.resize (rr_node_route_inf_.size ());
676+ }
681677}
682678
683679// Calculates the cost of reaching to_node
684680template <typename Heap>
685681void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* to,
686682 const t_conn_cost_params& cost_params,
687683 RRNodeId from_node,
688- RRNodeId to_node,
689- RREdgeId from_edge,
690684 RRNodeId target_node) {
691685 /* new_costs.backward_cost: is the "known" part of the cost to this node -- the
692686 * 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
698692 */
699693
700694 // 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 );
702696 bool switch_buffered = rr_switch_inf_[iswitch].buffered ();
703697 bool reached_configurably = rr_switch_inf_[iswitch].configurable ();
704698 float switch_R = rr_switch_inf_[iswitch].R ;
705699 float switch_Tdel = rr_switch_inf_[iswitch].Tdel ;
706700 float switch_Cinternal = rr_switch_inf_[iswitch].Cinternal ;
707701
708702 // 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 );
710704 float node_C = rr_rc_data_[rc_index].C ;
711705 float node_R = rr_rc_data_[rc_index].R ;
712706
@@ -745,7 +739,7 @@ void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* t
745739
746740 float cong_cost = 0 .;
747741 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 );
749743 } else {
750744 // Reached by a non-configurable edge.
751745 // 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
759753 // cost.
760754 cong_cost = 0 .;
761755 }
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 );
764758 if (find_res != conn_params_->connection_choking_spots_ .end ()) {
765759 cong_cost = cong_cost / pow (2 , (float )find_res->second );
766760 }
@@ -772,7 +766,7 @@ void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* t
772766
773767 if (cost_params.bend_cost != 0 .) {
774768 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 );
776770 if ((from_type == CHANX && to_type == CHANY) || (from_type == CHANY && to_type == CHANX)) {
777771 to->backward_path_cost += cost_params.bend_cost ; // Bend cost
778772 }
@@ -782,20 +776,17 @@ void ConnectionRouter<Heap>::evaluate_timing_driven_node_costs(RTExploredNode* t
782776
783777 if (rcv_path_manager.is_enabled () && to->path_data != nullptr ) {
784778 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 );
786780
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 );
788782 } else {
789783 const auto & device_ctx = g_vpr_ctx.device ();
790784 // 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 );
795786 VTR_LOGV_DEBUG (router_debug_ && !std::isfinite (expected_cost),
796787 " 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 (),
799790 rr_node_arch_name (target_node, is_flat_).c_str (),
800791 describe_rr_node (device_ctx.rr_graph , device_ctx.grid , device_ctx.rr_indexed_data , target_node, is_flat_).c_str (),
801792 expected_cost, to->R_upstream );
@@ -885,7 +876,7 @@ void ConnectionRouter<Heap>::add_route_tree_node_to_heap(
885876 rr_node_route_inf_[inode].path_cost = tot_cost;
886877 rr_node_route_inf_[inode].prev_edge = RREdgeId::INVALID ();
887878 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;
889880 heap_.push_back ({tot_cost, inode});
890881
891882 // push_back_node(&heap_, rr_node_route_inf_,
@@ -898,7 +889,7 @@ void ConnectionRouter<Heap>::add_route_tree_node_to_heap(
898889 rr_node_route_inf_[inode].path_cost = expected_total_cost;
899890 rr_node_route_inf_[inode].prev_edge = RREdgeId::INVALID ();
900891 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;
902893
903894 rcv_path_manager.alloc_path_struct (rcv_path_data[inode]);
904895 rcv_path_data[inode]->backward_delay = rt_node.Tdel ;
0 commit comments