aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-12-03 13:44:16 +0000
committerDavid Shah <dave@ds0.me>2020-02-03 11:38:31 +0000
commit3d739b5916277357283da225d98255aaad85e70c (patch)
tree0ad47f6b532f881179634a77e81802a8803e200a
parent50b120528a1744e64eeb6a886dc392793a4659ab (diff)
downloadnextpnr-3d739b5916277357283da225d98255aaad85e70c.tar.gz
nextpnr-3d739b5916277357283da225d98255aaad85e70c.tar.bz2
nextpnr-3d739b5916277357283da225d98255aaad85e70c.zip
router2: first pass at reserved wires
Signed-off-by: David Shah <dave@ds0.me>
-rw-r--r--common/router2.cc68
1 files changed, 65 insertions, 3 deletions
diff --git a/common/router2.cc b/common/router2.cc
index c992f274..496a4bfc 100644
--- a/common/router2.cc
+++ b/common/router2.cc
@@ -62,12 +62,12 @@ struct Router2
{
// net --> number of arcs; driving pip
std::unordered_map<int, std::pair<int, PipId>> bound_nets;
- // Which net is bound in the Arch API
- int arch_bound_net = -1;
// Historical congestion cost
float hist_cong_cost = 1.0;
// Wire is unavailable as locked to another arc
bool unavailable = false;
+ // This wire has to be used for this net
+ int reserved_net = -1;
};
float present_wire_cost(const PerWireData &w, int net_uid)
@@ -165,7 +165,6 @@ struct Router2
NetInfo *bound = ctx->getBoundWireNet(wire);
if (bound != nullptr) {
wires[wire].bound_nets[bound->udata] = std::make_pair(1, bound->wires.at(wire).pip);
- wires[wire].arch_bound_net = bound->udata;
if (bound->wires.at(wire).strength > STRENGTH_STRONG)
wires[wire].unavailable = true;
}
@@ -332,6 +331,64 @@ struct Router2
return (cursor == src_wire);
}
+ // Returns true if a wire contains no source ports or driving pips
+ bool is_wire_undriveable(WireId wire)
+ {
+ for (auto bp : ctx->getWireBelPins(wire))
+ if (ctx->getBelPinType(bp.bel, bp.pin) != PORT_IN)
+ return false;
+ for (auto p : ctx->getPipsUphill(wire))
+ return false;
+ return true;
+ }
+
+ // Find all the wires that must be used to route a given arc
+ void reserve_wires_for_arc(NetInfo *net, size_t i)
+ {
+ // This is slightly tricky, because of the possibility of "diamonds"
+ // eg /--C--\\
+ // sink ----B----D--...
+ // we need to discover that D is a reserved wire; despite the branch and choice of B/C
+ WireId src = ctx->getNetinfoSourceWire(net);
+ WireId sink = ctx->getNetinfoSinkWire(net, net->users.at(i));
+ if (sink == WireId())
+ return;
+ std::unordered_set<WireId> rsv;
+ WireId cursor = sink;
+ bool done = false;
+ while (!done) {
+ auto &wd = wires.at(cursor);
+ wd.reserved_net = net->udata;
+ if (cursor == src)
+ break;
+ WireId next_cursor;
+ for (auto uh : ctx->getPipsUphill(cursor)) {
+ WireId w = ctx->getPipSrcWire(uh);
+ if (is_wire_undriveable(w))
+ continue;
+ if (next_cursor != WireId()) {
+ done = true;
+ break;
+ }
+ next_cursor = w;
+ }
+ if (next_cursor == WireId())
+ break;
+ cursor = next_cursor;
+ }
+ }
+
+ void find_all_reserved_wires()
+ {
+ for (auto net : nets_by_udata) {
+ WireId src = ctx->getNetinfoSourceWire(net);
+ if (src == WireId())
+ continue;
+ for (size_t i = 0; i < net->users.size(); i++)
+ reserve_wires_for_arc(net, i);
+ }
+ }
+
ArcRouteResult route_arc(ThreadContext &t, NetInfo *net, size_t i, bool is_mt, bool is_bb = true)
{
@@ -416,6 +473,8 @@ struct Router2
auto &wd = wires.at(next);
if (wd.unavailable)
continue;
+ if (wd.reserved_net != -1 && wd.reserved_net != net->udata)
+ continue;
if (wd.bound_nets.size() > 1 || (wd.bound_nets.size() == 1 && !wd.bound_nets.count(net->udata)))
continue; // never allow congestion in backwards routing
t.backwards_queue.push(next);
@@ -490,6 +549,8 @@ struct Router2
auto &nwd = wires.at(next);
if (nwd.unavailable)
continue;
+ if (nwd.reserved_net != -1 && nwd.reserved_net != net->udata)
+ continue;
if (nwd.bound_nets.count(net->udata) && nwd.bound_nets.at(net->udata).second != dh)
continue;
WireScore next_score;
@@ -859,6 +920,7 @@ struct Router2
{
setup_nets();
setup_wires();
+ find_all_reserved_wires();
partition_nets();
curr_cong_weight = 0.5;
hist_cong_weight = 1.0;