Skip to content

Commit 89ed907

Browse files
committed
fix the non-configurable node case
1 parent c189588 commit 89ed907

File tree

5 files changed

+114
-76
lines changed

5 files changed

+114
-76
lines changed

vpr/src/route/route_timing.cpp

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,7 +1516,7 @@ static void setup_routing_resources(int itry,
15161516
vtr::optional<RouteTreeRoot&> rt_root_pruned = prune_route_tree(rt_root2, connections_inf);
15171517

15181518
// Subtract congestion using the non-pruned original
1519-
pathfinder_update_cost_from_route_tree(route_ctx.rt_roots[net_id].value(), -1);
1519+
pathfinder_update_cost_from_route_tree(rt_root.value(), -1);
15201520

15211521
if (rt_root_pruned) { //Partially pruned
15221522
profiling::route_tree_preserved();
@@ -2094,10 +2094,10 @@ static bool is_better_quality_routing(const vtr::vector<ParentNetId, vtr::option
20942094
const WirelengthInfo& wirelength_info,
20952095
std::shared_ptr<const SetupHoldTimingInfo> timing_info) {
20962096
if (best_routing.empty()) {
2097-
return true; //First legal routing
2097+
return true; // First legal routing
20982098
}
20992099

2100-
//Rank first based on sWNS, followed by other timing metrics
2100+
// Rank first based on sWNS, followed by other timing metrics
21012101
if (timing_info) {
21022102
if (timing_info->setup_worst_negative_slack() > best_routing_metrics.sWNS) {
21032103
return true;
@@ -2124,31 +2124,31 @@ static bool is_better_quality_routing(const vtr::vector<ParentNetId, vtr::option
21242124
}
21252125
}
21262126

2127-
//Finally, wirelength tie breaker
2127+
// Finally, wirelength tie breaker
21282128
return wirelength_info.used_wirelength() < best_routing_metrics.used_wirelength;
21292129
}
21302130

21312131
static bool early_reconvergence_exit_heuristic(const t_router_opts& router_opts,
21322132
int itry_since_last_convergence,
21332133
std::shared_ptr<const SetupHoldTimingInfo> timing_info,
21342134
const RoutingMetrics& best_routing_metrics) {
2135-
//Give-up on reconvergent routing if the CPD improvement after the
2136-
//first iteration since convergence is small, compared to the best
2137-
//CPD seen so far
2135+
// Give-up on reconvergent routing if the CPD improvement after the
2136+
// first iteration since convergence is small, compared to the best
2137+
// CPD seen so far
21382138
if (itry_since_last_convergence == 1) {
21392139
float cpd_ratio = timing_info->setup_worst_negative_slack() / best_routing_metrics.sWNS;
21402140

2141-
//Give up if we see less than a 1% CPD improvement,
2142-
//after reducing pres_fac. Typically larger initial
2143-
//improvements are needed to see an actual improvement
2144-
//in final legal routing quality.
2141+
// Give up if we see less than a 1% CPD improvement,
2142+
// after reducing pres_fac. Typically larger initial
2143+
// improvements are needed to see an actual improvement
2144+
// in final legal routing quality.
21452145
if (cpd_ratio >= router_opts.reconvergence_cpd_threshold) {
21462146
VTR_LOG("Giving up routing since additional routing convergences seem unlikely to improve quality (CPD ratio: %g)\n", cpd_ratio);
2147-
return true; //Potential CPD improvement is small, don't spend run-time trying to improve it
2147+
return true; // Potential CPD improvement is small, don't spend run-time trying to improve it
21482148
}
21492149
}
21502150

2151-
return false; //Don't give up
2151+
return false; // Don't give up
21522152
}
21532153

21542154
static void generate_route_timing_reports(const t_router_opts& router_opts,
@@ -2168,8 +2168,8 @@ static void generate_route_timing_reports(const t_router_opts& router_opts,
21682168
}
21692169

21702170
// If a route is ripped up during routing, non-configurable sets are left
2171-
// behind. As a result, the final routing may have stubs at
2172-
// non-configurable sets. This function tracks non-configurable set usage,
2171+
// behind. As a result, the final routing may have stubs at
2172+
// non-configurable sets. This function tracks non-configurable set usage,
21732173
// and if the sets are unused, prunes them.
21742174
static void prune_unused_non_configurable_nets(CBRR& connections_inf,
21752175
const Netlist<>& net_list,
@@ -2183,28 +2183,26 @@ static void prune_unused_non_configurable_nets(CBRR& connections_inf,
21832183
continue;
21842184
RouteTreeRoot& rt_root = route_ctx.rt_roots[net_id].value();
21852185

2186+
21862187
connections_inf.prepare_routing_for_net(net_id);
21872188
connections_inf.clear_force_reroute_for_net();
21882189

2189-
std::fill(non_config_node_set_usage.begin(), non_config_node_set_usage.end(), 0);
2190-
2191-
// check for edge correctness
2192-
VTR_ASSERT_SAFE(is_valid_skeleton_tree(rt_root));
2190+
std::vector<int> usage = get_non_config_node_set_usage(rt_root);
21932191

2194-
//Prune the branches of the tree that don't legally lead to sinks
2195-
prune_route_tree(rt_root, connections_inf, &non_config_node_set_usage);
2192+
// Prune the branches of the tree that don't legally lead to sinks
2193+
prune_route_tree(rt_root, connections_inf, &usage);
21962194
}
21972195
}
21982196

2199-
//Initializes net_delay based on best-case delay estimates from the router lookahead
2197+
// Initializes net_delay based on best-case delay estimates from the router lookahead
22002198
static void init_net_delay_from_lookahead(const RouterLookahead& router_lookahead,
22012199
const Netlist<>& net_list,
22022200
const vtr::vector<ParentNetId, std::vector<int>>& net_rr_terminals,
22032201
NetPinsMatrix<float>& net_delay,
22042202
const RRGraphView& rr_graph,
22052203
bool is_flat) {
22062204
t_conn_cost_params cost_params;
2207-
cost_params.criticality = 1.; //Ensures lookahead returns delay value
2205+
cost_params.criticality = 1.; // Ensures lookahead returns delay value
22082206

22092207
for (auto net_id : net_list.nets()) {
22102208
if (net_list.net_is_ignored(net_id)) continue;
@@ -2354,8 +2352,8 @@ vtr::vector<ParentNetId, std::vector<std::unordered_map<RRNodeId, int>>> set_net
23542352
}
23552353

23562354
#ifndef NO_GRAPHICS
2357-
//updates router iteration information and checks for router iteration and net id breakpoints
2358-
//stops after the specified router iteration or net id is encountered
2355+
// updates router iteration information and checks for router iteration and net id breakpoints
2356+
// stops after the specified router iteration or net id is encountered
23592357
void update_router_info_and_check_bp(bp_router_type type, int net_id) {
23602358
t_draw_state* draw_state = get_draw_state_vars();
23612359
if (draw_state->list_of_breakpoints.size() != 0) {

vpr/src/route/route_tree_timing.cpp

Lines changed: 77 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <vector>
44

55
#include "rr_graph_fwd.h"
6+
#include "rr_node_types.h"
67
#include "vtr_assert.h"
78
#include "vtr_log.h"
89
#include "vtr_memory.h"
@@ -116,10 +117,13 @@ update_route_tree(RouteTreeRoot& rt_root, t_heap* hptr, int target_net_pin_index
116117
update_route_tree_spatial_lookup_recur(start_of_new_subtree_rt_node.value(), *spatial_rt_lookup);
117118
}
118119

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};
123127

124128
return {start_of_new_subtree_rt_node.value(), sink_rt_node};
125129
}
@@ -182,6 +186,7 @@ add_subtree_to_route_tree(RouteTreeRoot& rt_root, t_heap* hptr, int target_net_p
182186
* ---
183187
* Walk through new_branch_iswitches and corresponding new_branch_inodes. */
184188
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 */
185190
RouteTreeNode tmp_node(new_branch_inodes[i], new_branch_iswitches[i], *last_node_ptr, rt_root);
186191

187192
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
202207
all_visited.insert(new_branch_inodes[i]);
203208
}
204209

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.
208213
for (RRNodeId rr_node : main_branch_visited) {
209214
add_non_configurable_to_route_tree(rr_node_to_rt_node.at(rr_node).value(), false, all_visited, is_flat);
210215
}
@@ -224,31 +229,34 @@ static void add_non_configurable_to_route_tree(RouteTreeNode& rt_node,
224229
if(visited.count(rt_node.inode) && reached_by_non_configurable_edge)
225230
return;
226231

232+
visited.insert(rt_node.inode);
233+
227234
auto& device_ctx = g_vpr_ctx.device();
228235
const auto& rr_graph = device_ctx.rr_graph;
229236

230237
VTR_ASSERT(rt_node.root);
231238
auto& rr_node_to_rt_node = rt_node.root.value().rr_node_to_rt_node;
232239
const RRNodeId rr_node = rt_node.inode;
233240

234-
for (int iedge : rr_graph.non_configurable_edges(RRNodeId(rr_node))) {
241+
for (int iedge : rr_graph.non_configurable_edges(rr_node)) {
235242
// 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);
239245

240246
if(rr_node_to_rt_node.count(to_rr_node)) // TODO: not 100% sure about this
241247
continue;
242248

243249
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;
246254
if (rr_graph.node_type(RRNodeId(to_rr_node)) == IPIN && !is_flat) {
247-
new_node.re_expand = false;
255+
tmp_node.re_expand = false;
248256
} else {
249-
new_node.re_expand = true;
257+
tmp_node.re_expand = true;
250258
}
251-
rt_node.add_child_front(new_node);
259+
RouteTreeNode& new_node = rt_node.add_child_front(tmp_node);
252260

253261
add_non_configurable_to_route_tree(new_node, true, visited, is_flat);
254262
}
@@ -438,7 +446,7 @@ void print_route_tree(const RouteTreeNode& rt_node, int depth) {
438446

439447
auto& device_ctx = g_vpr_ctx.device();
440448
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",
442450
indent.c_str(),
443451
rt_node.inode,
444452
rr_graph.node_type_string(RRNodeId(rt_node.inode)),
@@ -447,15 +455,16 @@ void print_route_tree(const RouteTreeNode& rt_node, int depth) {
447455
rt_node.C_downstream,
448456
rt_node.Tdel);
449457

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();
452461
if (!parent_edge_configurable) {
453462
VTR_LOG("*");
454463
}
455464
}
456465

457466
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)) {
459468
VTR_LOG(" x");
460469
}
461470

@@ -721,11 +730,11 @@ t_trace* traceback_from_route_tree(ParentNetId inet, const RouteTreeNode& root,
721730
static vtr::optional<RouteTreeNode&> prune_route_tree_recurr(RouteTreeNode& node, CBRR& connections_inf, bool force_prune, std::vector<int>* non_config_node_set_usage) {
722731
// Recursively traverse the route tree rooted at node and remove any congested
723732
// sub-trees
724-
725733
auto& device_ctx = g_vpr_ctx.device();
726734
const auto& rr_graph = device_ctx.rr_graph;
727735
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+
729738
int node_set = -1;
730739
auto itr = device_ctx.rr_node_to_non_config_node_set.find(size_t(node.inode));
731740
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
756765
}else{ // Pruned
757766
// After removing a child node, check if non_config_node_set_usage
758767
// 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()) {
760769
(*non_config_node_set_usage)[node_set] -= 1;
761770
VTR_ASSERT((*non_config_node_set_usage)[node_set] >= 0);
762771
}
@@ -771,14 +780,14 @@ static vtr::optional<RouteTreeNode&> prune_route_tree_recurr(RouteTreeNode& node
771780
//Record sink as reachable
772781
connections_inf.reached_rt_sink(node.inode);
773782

774-
return node; //Not pruned
783+
return node; // Not pruned
775784
} else {
776785
VTR_ASSERT(force_prune);
777786

778787
//Record as not reached
779788
connections_inf.toreach_rr_sink(node.net_pin_index);
780789

781-
return vtr::nullopt; //Pruned
790+
return vtr::nullopt; // Pruned
782791
}
783792
} else if (all_children_pruned) {
784793
//This node has no children
@@ -809,7 +818,7 @@ static vtr::optional<RouteTreeNode&> prune_route_tree_recurr(RouteTreeNode& node
809818

810819
bool reached_non_configurably = false;
811820
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();
813822

814823
if (reached_non_configurably) {
815824
// 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
910919
return vtr::nullopt;
911920
}
912921

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+
913964
void pathfinder_update_cost_from_route_tree(const RouteTreeNode& rt_node, int add_or_sub) {
914965
/* Update pathfinder cost of all nodes rooted at rt_node, including rt_node itself */
915966
pathfinder_update_single_node_occupancy(size_t(rt_node.inode), add_or_sub);

vpr/src/route/route_tree_timing.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ vtr::optional<RouteTreeRoot&> prune_route_tree(RouteTreeRoot& rt_root, CBRR& con
5757
// non_config_node_set_usage after pruning.
5858
vtr::optional<RouteTreeRoot&> prune_route_tree(RouteTreeRoot& rt_root, CBRR& connections_inf, std::vector<int>* non_config_node_set_usage);
5959

60+
/* Count configurable edges to non-configurable node sets. (rr_nonconf_node_sets index -> int)
61+
* Required when using prune_route_tree to prune non-configurable nodes. */
62+
std::vector<int> get_non_config_node_set_usage(const RouteTreeRoot& rt_root);
63+
6064
/* Move to other pathfinder functions */
6165
void pathfinder_update_cost_from_route_tree(const RouteTreeNode& rt_root, int add_or_sub);
6266

0 commit comments

Comments
 (0)