diff options
author | David Shah <dave@ds0.me> | 2020-02-03 11:38:15 +0000 |
---|---|---|
committer | David Shah <dave@ds0.me> | 2020-02-03 11:38:31 +0000 |
commit | ad1cc12df1aa13c1618d85c07805a4987e0e041f (patch) | |
tree | 3cb1a7fadeb1e338d2aa87cdaa189fd24956eb0c /common | |
parent | 5e1aac67db4bec579ca9e8075aa32e4183d1004f (diff) | |
download | nextpnr-ad1cc12df1aa13c1618d85c07805a4987e0e041f.tar.gz nextpnr-ad1cc12df1aa13c1618d85c07805a4987e0e041f.tar.bz2 nextpnr-ad1cc12df1aa13c1618d85c07805a4987e0e041f.zip |
router2: Make magic numbers configurable
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'common')
-rw-r--r-- | common/router2.cc | 92 | ||||
-rw-r--r-- | common/router2.h | 32 |
2 files changed, 85 insertions, 39 deletions
diff --git a/common/router2.cc b/common/router2.cc index 3dad4583..5ed007c3 100644 --- a/common/router2.cc +++ b/common/router2.cc @@ -26,6 +26,7 @@ * */ +#include "router2.h" #include <algorithm> #include <boost/container/flat_map.hpp> #include <chrono> @@ -39,8 +40,6 @@ NEXTPNR_NAMESPACE_BEGIN -#define RUNTIME_PROFILE - namespace { struct Router2 { @@ -105,6 +104,9 @@ struct Router2 } Context *ctx; + Router2Cfg cfg; + + Router2(Context *ctx, const Router2Cfg &cfg) : ctx(ctx), cfg(cfg) {} // Use 'udata' for fast net lookups and indexing std::vector<NetInfo *> nets_by_udata; @@ -221,11 +223,10 @@ struct Router2 }; }; - int bb_margin_x = 4, bb_margin_y = 4; // number of units outside the bounding box we may go bool hit_test_pip(ArcBounds &bb, Loc l) { - return l.x >= (bb.x0 - bb_margin_x) && l.x <= (bb.x1 + bb_margin_x) && l.y >= (bb.y0 - bb_margin_y) && - l.y <= (bb.y1 + bb_margin_y); + return l.x >= (bb.x0 - cfg.bb_margin_x) && l.x <= (bb.x1 + cfg.bb_margin_x) && + l.y >= (bb.y0 - cfg.bb_margin_y) && l.y <= (bb.y1 + cfg.bb_margin_y); } double curr_cong_weight, hist_cong_weight, estimate_weight; @@ -320,7 +321,7 @@ struct Router2 source_uses = wd.bound_nets.at(net->udata).first; if (pip != PipId()) { Loc pl = ctx->getPipLocation(pip); - bias_cost = 0.25f * (base_cost / int(net->users.size())) * + bias_cost = cfg.bias_cost_factor * (base_cost / int(net->users.size())) * ((std::abs(pl.x - nd.cx) + std::abs(pl.y - nd.cy)) / float(nd.hpwl)); } return base_cost * hist_cost * present_cost / (1 + source_uses) + bias_cost; @@ -333,7 +334,7 @@ struct Router2 if (wd.bound_nets.count(net->udata)) source_uses = wd.bound_nets.at(net->udata).first; // FIXME: timing/wirelength balance? - return ctx->getDelayNS(ctx->estimateDelay(wd.w, sink)) / (1 + source_uses); + return (ctx->getDelayNS(ctx->estimateDelay(wd.w, sink)) / (1 + source_uses)) + cfg.ipin_cost_adder; } bool check_arc_routing(NetInfo *net, size_t usr) @@ -469,7 +470,8 @@ struct Router2 // This could also be used to speed up forwards routing by a hybrid // bidirectional approach int backwards_iter = 0; - int backwards_limit = ctx->getBelGlobalBuf(net->driver.cell->bel) ? 20000 : 15; + int backwards_limit = + ctx->getBelGlobalBuf(net->driver.cell->bel) ? cfg.global_backwards_max_iter : cfg.backwards_max_iter; t.backwards_queue.push(wire_to_idx.at(dst_wire)); while (!t.backwards_queue.empty() && backwards_iter < backwards_limit) { int cursor = t.backwards_queue.front(); @@ -611,7 +613,7 @@ struct Router2 next_score.cost = curr.score.cost + score_wire_for_arc(net, i, next, dh); next_score.delay = curr.score.delay + ctx->getPipDelay(dh).maxDelay() + ctx->getWireDelay(next).maxDelay(); - next_score.togo_cost = 1.75 * get_togo_cost(net, i, next_idx, dst_wire); + next_score.togo_cost = cfg.estimate_weight * get_togo_cost(net, i, next_idx, dst_wire); const auto &v = nwd.visit; if (!v.visited || (v.score.total() > next_score.total())) { ++explored; @@ -669,9 +671,7 @@ struct Router2 ROUTE_LOG_DBG("Routing net '%s'...\n", ctx->nameOf(net)); -#ifdef RUNTIME_PROFILE auto rstart = std::chrono::high_resolution_clock::now(); -#endif // Nothing to do if net is undriven if (net->driver.cell == nullptr) @@ -715,11 +715,11 @@ struct Router2 } } } -#ifdef RUNTIME_PROFILE - auto rend = std::chrono::high_resolution_clock::now(); - nets.at(net->udata).total_route_us += - (std::chrono::duration_cast<std::chrono::microseconds>(rend - rstart).count()); -#endif + if (cfg.perf_profile) { + auto rend = std::chrono::high_resolution_clock::now(); + nets.at(net->udata).total_route_us += + (std::chrono::duration_cast<std::chrono::microseconds>(rend - rstart).count()); + } return !have_failures; } #undef ROUTE_LOG_DBG @@ -951,10 +951,10 @@ struct Router2 auto &nd = nets.at(n); auto ni = nets_by_udata.at(n); int bin = N; - int le_x = mid_x - bb_margin_x; - int rs_x = mid_x + bb_margin_x; - int le_y = mid_y - bb_margin_y; - int rs_y = mid_y + bb_margin_y; + int le_x = mid_x - cfg.bb_margin_x; + int rs_x = mid_x + cfg.bb_margin_x; + int le_y = mid_y - cfg.bb_margin_y; + int rs_y = mid_y + cfg.bb_margin_y; // Quadrants if (nd.bb.x0 < le_x && nd.bb.x1 < le_x && nd.bb.y0 < le_y && nd.bb.y1 < le_y) bin = 0; @@ -1010,14 +1010,14 @@ struct Router2 route_net(tcs.at(N), fail, false); } - void router_test() + void operator()() { setup_nets(); setup_wires(); find_all_reserved_wires(); partition_nets(); - curr_cong_weight = 0.5; - hist_cong_weight = 1.0; + curr_cong_weight = cfg.init_curr_cong_weight; + hist_cong_weight = cfg.hist_cong_weight; ThreadContext st; int iter = 1; @@ -1051,32 +1051,48 @@ struct Router2 log_info("iter=%d wires=%d overused=%d overuse=%d archfail=%s\n", iter, total_wire_use, overused_wires, total_overuse, overused_wires > 0 ? "NA" : std::to_string(arch_fail).c_str()); ++iter; - curr_cong_weight *= 2; + curr_cong_weight *= cfg.curr_cong_mult; } while (!failed_nets.empty()); -#ifdef RUNTIME_PROFILE - std::vector<std::pair<int, IdString>> nets_by_runtime; - for (auto &n : nets_by_udata) { - nets_by_runtime.emplace_back(nets.at(n->udata).total_route_us, n->name); - } - std::sort(nets_by_runtime.begin(), nets_by_runtime.end(), std::greater<std::pair<int, IdString>>()); - log_info("1000 slowest nets by runtime:\n"); - for (int i = 0; i < std::min(int(nets_by_runtime.size()), 1000); i++) { - log(" %80s %6d %.1fms\n", nets_by_runtime.at(i).second.c_str(ctx), - int(ctx->nets.at(nets_by_runtime.at(i).second)->users.size()), nets_by_runtime.at(i).first / 1000.0); + if (cfg.perf_profile) { + std::vector<std::pair<int, IdString>> nets_by_runtime; + for (auto &n : nets_by_udata) { + nets_by_runtime.emplace_back(nets.at(n->udata).total_route_us, n->name); + } + std::sort(nets_by_runtime.begin(), nets_by_runtime.end(), std::greater<std::pair<int, IdString>>()); + log_info("1000 slowest nets by runtime:\n"); + for (int i = 0; i < std::min(int(nets_by_runtime.size()), 1000); i++) { + log(" %80s %6d %.1fms\n", nets_by_runtime.at(i).second.c_str(ctx), + int(ctx->nets.at(nets_by_runtime.at(i).second)->users.size()), + nets_by_runtime.at(i).first / 1000.0); + } } -#endif } }; } // namespace -void router2(Context *ctx) +void router2(Context *ctx, const Router2Cfg &cfg) { - Router2 rt; + Router2 rt(ctx, cfg); rt.ctx = ctx; auto rstart = std::chrono::high_resolution_clock::now(); - rt.router_test(); + rt(); auto rend = std::chrono::high_resolution_clock::now(); log_info("Router2 time %.02fs\n", std::chrono::duration<float>(rend - rstart).count()); } +Router2Cfg::Router2Cfg(Context *ctx) +{ + backwards_max_iter = ctx->setting<int>("router2/bwdMaxIter", 20); + global_backwards_max_iter = ctx->setting<int>("router2/glbBwdMaxIter", 200); + bb_margin_x = ctx->setting<int>("router2/bbMargin/x", 3); + bb_margin_y = ctx->setting<int>("router2/bbMargin/y", 3); + ipin_cost_adder = ctx->setting<float>("router2/ipinCostAdder", 0.0f); + bias_cost_factor = ctx->setting<float>("router2/biasCostFactor", 0.25f); + init_curr_cong_weight = ctx->setting<float>("router2/initCurrCongWeight", 0.5f); + hist_cong_weight = ctx->setting<float>("router2/histCongWeight", 1.0f); + curr_cong_mult = ctx->setting<float>("router2/currCongWeightMult", 2.0f); + estimate_weight = ctx->setting<float>("router2/estimateWeight", 1.75f); + perf_profile = ctx->setting<float>("router2/perfProfile", false); +} + NEXTPNR_NAMESPACE_END
\ No newline at end of file diff --git a/common/router2.h b/common/router2.h index e1f850b9..fb11f92d 100644 --- a/common/router2.h +++ b/common/router2.h @@ -21,6 +21,36 @@ NEXTPNR_NAMESPACE_BEGIN -void router2(Context *ctx); +struct Router2Cfg +{ + Router2Cfg(Context *ctx); + + // Maximum iterations for backwards routing attempt + int backwards_max_iter; + // Maximum iterations for backwards routing attempt for global nets + int global_backwards_max_iter; + // Padding added to bounding boxes to account for imperfect routing, + // congestion, etc + int bb_margin_x, bb_margin_y; + // Cost factor added to input pin wires; effectively reduces the + // benefit of sharing interconnect + float ipin_cost_adder; + // Cost factor for "bias" towards center location of net + float bias_cost_factor; + // Starting current and historical congestion cost factor + float init_curr_cong_weight, hist_cong_weight; + // Current congestion cost multiplier + float curr_cong_mult; + + // Weight given to delay estimate in A*. Higher values + // mean faster and more directed routing, at the risk + // of choosing a less congestion/delay-optimal route + float estimate_weight; + + // Print additional performance profiling information + bool perf_profile = false; +}; + +void router2(Context *ctx, const Router2Cfg &cfg); NEXTPNR_NAMESPACE_END
\ No newline at end of file |