Skip to content

Commit 2966d66

Browse files
committed
[Router] Resolved Comments and Fixed the RCV Pre-Push Prune Condition
Resolved the comments in the PR code reviews, mostly addressing the code comments and coding style issues. Fixed the RCV pre-push prune condition such that when RCV is on, the connection router prunes based on the RCV-specific total path cost to allow detours in order to achieve better QoR.
1 parent c360f71 commit 2966d66

File tree

6 files changed

+114
-101
lines changed

6 files changed

+114
-101
lines changed

vpr/src/base/vpr_types.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1607,14 +1607,18 @@ constexpr bool is_src_sink(e_rr_type type) { return (type == SOURCE || type == S
16071607
* is being used.
16081608
* @param backward_path_cost Total cost of the path up to and including this
16091609
* node.
1610-
* @param occ The current occupancy of the associated rr node
1610+
* @param R_upstream Upstream resistance to ground from this node in the current
1611+
* path search (connection routing), including the resistance
1612+
* of the node itself (device_ctx.rr_nodes[index].R).
1613+
* @param occ The current occupancy of the associated rr node.
16111614
*/
16121615
struct t_rr_node_route_inf {
16131616
RREdgeId prev_edge;
16141617

16151618
float acc_cost;
16161619
float path_cost;
16171620
float backward_path_cost;
1621+
float R_upstream;
16181622

16191623
public: //Accessors
16201624
short occ() const { return occ_; }

vpr/src/route/connection_router.cpp

Lines changed: 47 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -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
190185
template<typename Heap>
191186
void 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.
299291
template<typename Heap>
300292
vtr::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() {
678671
template<typename Heap>
679672
void 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
684680
template<typename Heap>
685681
void 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

Comments
 (0)