aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/router2.cc92
-rw-r--r--common/router2.h32
-rw-r--r--ecp5/arch.cc2
3 files changed, 86 insertions, 40 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
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index a10be174..52cfc187 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -625,7 +625,7 @@ bool Arch::route()
route_ecp5_globals(getCtx());
assignArchInfo();
assign_budget(getCtx(), true);
- router2(getCtx());
+ router2(getCtx(), Router2Cfg(getCtx()));
bool result = router1(getCtx(), Router1Cfg(getCtx()));
#if 0
std::vector<std::pair<WireId, int>> fanout_vector;