Skip to content

Commit ca13b7f

Browse files
authored
Merge pull request #1113 from HackerFoo/prevent_high_fanout_explosion
Prevent non-termination with high fanout routing logic
2 parents 0d731c1 + ec9cc14 commit ca13b7f

File tree

8 files changed

+48
-22
lines changed

8 files changed

+48
-22
lines changed

vpr/src/base/SetupVPR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts)
376376
RouterOpts->clock_modeling = Options.clock_modeling;
377377
RouterOpts->two_stage_clock_routing = Options.two_stage_clock_routing;
378378
RouterOpts->high_fanout_threshold = Options.router_high_fanout_threshold;
379+
RouterOpts->high_fanout_max_slope = Options.router_high_fanout_max_slope;
379380
RouterOpts->router_debug_net = Options.router_debug_net;
380381
RouterOpts->router_debug_sink_rr = Options.router_debug_sink_rr;
381382
RouterOpts->router_debug_iteration = Options.router_debug_iteration;

vpr/src/base/read_options.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,14 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
20412041
.default_value("64")
20422042
.show_in(argparse::ShowIn::HELP_ONLY);
20432043

2044+
route_timing_grp.add_argument<float>(args.router_high_fanout_max_slope, "--router_high_fanout_max_slope")
2045+
.help(
2046+
"Minimum routing progress where high fanout routing is enabled."
2047+
" This is a ratio of the actual congestion reduction to what is expected based in the history.\n"
2048+
" 1.0 is normal progress, 0 is no progress.")
2049+
.default_value("0.1")
2050+
.show_in(argparse::ShowIn::HELP_ONLY);
2051+
20442052
route_timing_grp.add_argument<e_router_lookahead, ParseRouterLookahead>(args.router_lookahead_type, "--router_lookahead")
20452053
.help(
20462054
"Controls what lookahead the router uses to calculate cost of completing a connection.\n"

vpr/src/base/read_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ struct t_options {
166166
argparse::ArgValue<float> congested_routing_iteration_threshold_frac;
167167
argparse::ArgValue<e_route_bb_update> route_bb_update;
168168
argparse::ArgValue<int> router_high_fanout_threshold;
169+
argparse::ArgValue<float> router_high_fanout_max_slope;
169170
argparse::ArgValue<int> router_debug_net;
170171
argparse::ArgValue<int> router_debug_sink_rr;
171172
argparse::ArgValue<int> router_debug_iteration;

vpr/src/base/vpr_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,7 @@ struct t_router_opts {
10891089
enum e_clock_modeling clock_modeling; ///<How clock pins and nets should be handled
10901090
bool two_stage_clock_routing; ///<How clock nets on dedicated networks should be routed
10911091
int high_fanout_threshold;
1092+
float high_fanout_max_slope;
10921093
int router_debug_net;
10931094
int router_debug_sink_rr;
10941095
int router_debug_iteration;

vpr/src/route/route_timing.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,12 @@ static bool timing_driven_route_sink(
8888
unsigned itarget,
8989
int target_pin,
9090
const t_conn_cost_params cost_params,
91-
int high_fanout_threshold,
91+
const t_router_opts& router_opts,
9292
t_rt_node* rt_root,
9393
t_rt_node** rt_node_of_sink,
9494
SpatialRouteTreeLookup& spatial_rt_lookup,
95-
RouterStats& router_stats);
95+
RouterStats& router_stats,
96+
const RoutingPredictor& routing_predictor);
9697

9798
template<typename ConnectionRouter>
9899
static bool timing_driven_pre_route_to_clock_root(
@@ -425,7 +426,8 @@ bool try_timing_driven_route_tmpl(const t_router_opts& router_opts,
425426
route_timing_info,
426427
pin_timing_invalidator.get(),
427428
budgeting_inf,
428-
was_rerouted);
429+
was_rerouted,
430+
routing_predictor);
429431
if (!is_routable) {
430432
return (false); //Impossible to route
431433
}
@@ -772,7 +774,8 @@ bool try_timing_driven_route_net(ConnectionRouter& router,
772774
std::shared_ptr<SetupTimingInfo> timing_info,
773775
ClusteredPinTimingInvalidator* pin_timing_invalidator,
774776
route_budgets& budgeting_inf,
775-
bool& was_rerouted) {
777+
bool& was_rerouted,
778+
const RoutingPredictor& routing_predictor) {
776779
auto& cluster_ctx = g_vpr_ctx.clustering();
777780
auto& route_ctx = g_vpr_ctx.mutable_routing();
778781

@@ -803,7 +806,8 @@ bool try_timing_driven_route_net(ConnectionRouter& router,
803806
netlist_pin_lookup,
804807
timing_info,
805808
pin_timing_invalidator,
806-
budgeting_inf);
809+
budgeting_inf,
810+
routing_predictor);
807811

808812
profiling::net_fanout_end(cluster_ctx.clb_nlist.net_sinks(net_id).size());
809813

@@ -927,7 +931,8 @@ bool timing_driven_route_net(ConnectionRouter& router,
927931
const ClusteredPinAtomPinsLookup& netlist_pin_lookup,
928932
std::shared_ptr<SetupTimingInfo> timing_info,
929933
ClusteredPinTimingInvalidator* pin_timing_invalidator,
930-
route_budgets& budgeting_inf) {
934+
route_budgets& budgeting_inf,
935+
const RoutingPredictor& routing_predictor) {
931936
/* Returns true as long as found some way to hook up this net, even if that *
932937
* way resulted in overuse of resources (congestion). If there is no way *
933938
* to route this net, even ignoring congestion, it returns false. In this *
@@ -1060,10 +1065,11 @@ bool timing_driven_route_net(ConnectionRouter& router,
10601065
itarget,
10611066
target_pin,
10621067
cost_params,
1063-
router_opts.high_fanout_threshold,
1068+
router_opts,
10641069
rt_root, rt_node_of_sink,
10651070
spatial_route_tree_lookup,
1066-
router_stats))
1071+
router_stats,
1072+
routing_predictor))
10671073
return false;
10681074

10691075
profiling::conn_finish(route_ctx.net_rr_terminals[net_id][0],
@@ -1205,11 +1211,12 @@ static bool timing_driven_route_sink(
12051211
unsigned itarget,
12061212
int target_pin,
12071213
const t_conn_cost_params cost_params,
1208-
int high_fanout_threshold,
1214+
const t_router_opts& router_opts,
12091215
t_rt_node* rt_root,
12101216
t_rt_node** rt_node_of_sink,
12111217
SpatialRouteTreeLookup& spatial_rt_lookup,
1212-
RouterStats& router_stats) {
1218+
RouterStats& router_stats,
1219+
const RoutingPredictor& routing_predictor) {
12131220
/* Build a path from the existing route tree rooted at rt_root to the target_node
12141221
* add this branch to the existing route tree and update pathfinder costs and rr_node_route_inf to reflect this */
12151222
auto& route_ctx = g_vpr_ctx.mutable_routing();
@@ -1229,15 +1236,15 @@ static bool timing_driven_route_sink(
12291236
t_bb bounding_box = route_ctx.route_bb[net_id];
12301237

12311238
bool net_is_global = cluster_ctx.clb_nlist.net_is_global(net_id);
1232-
bool high_fanout = is_high_fanout(cluster_ctx.clb_nlist.net_sinks(net_id).size(), high_fanout_threshold);
1239+
bool high_fanout = is_high_fanout(cluster_ctx.clb_nlist.net_sinks(net_id).size(), router_opts.high_fanout_threshold);
12331240
constexpr float HIGH_FANOUT_CRITICALITY_THRESHOLD = 0.9;
12341241
bool sink_critical = (cost_params.criticality > HIGH_FANOUT_CRITICALITY_THRESHOLD);
12351242
bool net_is_clock = route_ctx.is_clock_net[net_id] != 0;
12361243

12371244
//We normally route high fanout nets by only adding spatially close-by routing to the heap (reduces run-time).
12381245
//However, if the current sink is 'critical' from a timing perspective, we put the entire route tree back onto
12391246
//the heap to ensure it has more flexibility to find the best path.
1240-
if (high_fanout && !sink_critical && !net_is_global && !net_is_clock) {
1247+
if (high_fanout && !sink_critical && !net_is_global && !net_is_clock && -routing_predictor.get_slope() > router_opts.high_fanout_max_slope) {
12411248
std::tie(found_path, cheapest) = router.timing_driven_route_connection_from_route_tree_high_fanout(rt_root,
12421249
sink_node,
12431250
cost_params,

vpr/src/route/route_timing.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "spatial_route_tree_lookup.h"
1313
#include "connection_router_interface.h"
1414
#include "heap_type.h"
15+
#include "routing_predictor.h"
1516

1617
int get_max_pins_per_net();
1718

@@ -39,7 +40,8 @@ bool try_timing_driven_route_net(ConnectionRouter& router,
3940
std::shared_ptr<SetupTimingInfo> timing_info,
4041
ClusteredPinTimingInvalidator* pin_timing_invalidator,
4142
route_budgets& budgeting_inf,
42-
bool& was_rerouted);
43+
bool& was_rerouted,
44+
const RoutingPredictor& routing_predictor);
4345

4446
template<typename ConnectionRouter>
4547
bool timing_driven_route_net(ConnectionRouter& router,
@@ -55,7 +57,8 @@ bool timing_driven_route_net(ConnectionRouter& router,
5557
const ClusteredPinAtomPinsLookup& netlist_pin_lookup,
5658
std::shared_ptr<SetupTimingInfo> timing_info,
5759
ClusteredPinTimingInvalidator* pin_timing_invalidator,
58-
route_budgets& budgeting_inf);
60+
route_budgets& budgeting_inf,
61+
const RoutingPredictor& routing_predictor);
5962

6063
void alloc_timing_driven_route_structs(float** pin_criticality_ptr,
6164
int** sink_order_ptr,

vpr/src/route/routing_predictor.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,9 @@ float covariance(std::vector<size_t> x_values, std::vector<float> y_values, floa
6363
return cov;
6464
}
6565

66-
float RoutingPredictor::get_slope() {
67-
if (iterations_.size() > min_history_) {
68-
auto model = fit_model(iterations_, iteration_overused_rr_node_counts_, history_factor_);
69-
return model.get_slope();
70-
}
71-
return -1;
66+
float RoutingPredictor::get_slope() const {
67+
//Return cached slope, computed in add_iteration_overuse()
68+
return slope_;
7269
}
7370

7471
LinearModel simple_linear_regression(std::vector<size_t> x_values, std::vector<float> y_values) {
@@ -155,7 +152,8 @@ LinearModel fit_model(std::vector<size_t> iterations, std::vector<size_t> overus
155152

156153
RoutingPredictor::RoutingPredictor(size_t min_history, float history_factor)
157154
: min_history_(min_history)
158-
, history_factor_(history_factor) {
155+
, history_factor_(history_factor)
156+
, slope_(-1) {
159157
//nop
160158
}
161159

@@ -204,4 +202,10 @@ float RoutingPredictor::estimate_overuse_slope() {
204202
void RoutingPredictor::add_iteration_overuse(size_t iteration, size_t overused_rr_node_count) {
205203
iterations_.push_back(iteration);
206204
iteration_overused_rr_node_counts_.push_back(overused_rr_node_count);
205+
206+
//Update slope
207+
if (iterations_.size() > min_history_) {
208+
auto model = fit_model(iterations_, iteration_overused_rr_node_counts_, history_factor_);
209+
slope_ = model.get_slope();
210+
}
207211
}

vpr/src/route/routing_predictor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@ class RoutingPredictor {
2525

2626
void add_iteration_overuse(size_t iteration, size_t overused_rr_node_count);
2727

28-
float get_slope();
28+
float get_slope() const;
2929

3030
private:
3131
size_t min_history_;
3232
float history_factor_;
3333

3434
std::vector<size_t> iterations_;
3535
std::vector<size_t> iteration_overused_rr_node_counts_;
36+
float slope_;
3637
};
3738

3839
#endif

0 commit comments

Comments
 (0)