aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2018-06-20 13:32:50 +0200
committerClifford Wolf <clifford@clifford.at>2018-06-20 13:32:50 +0200
commit3fda636e7058fb2a7c82d0233da76174ad8b431a (patch)
tree26c19b3ada4c96c6c275318ac9d87080f442f31d
parentd5a032d00e83863222bc4f5407bb72c845697c1b (diff)
downloadnextpnr-3fda636e7058fb2a7c82d0233da76174ad8b431a.tar.gz
nextpnr-3fda636e7058fb2a7c82d0233da76174ad8b431a.tar.bz2
nextpnr-3fda636e7058fb2a7c82d0233da76174ad8b431a.zip
Minor refactoring of router infrastructure
Signed-off-by: Clifford Wolf <clifford@clifford.at>
-rw-r--r--common/route.cc180
1 files changed, 102 insertions, 78 deletions
diff --git a/common/route.cc b/common/route.cc
index 42a705a1..657075ce 100644
--- a/common/route.cc
+++ b/common/route.cc
@@ -61,14 +61,112 @@ void ripup_net(Context *ctx, IdString net_name)
struct Router
{
+ Context *ctx;
+ IdString net_name;
+ bool ripup;
+ delay_t ripup_penalty;
+
std::unordered_set<IdString> rippedNets;
+ std::unordered_map<WireId, QueuedWire> visited;
int visitCnt = 0, revisitCnt = 0;
bool routedOkay = false;
delay_t maxDelay = 0.0;
WireId failedDest;
+ void route(const std::unordered_map<WireId, delay_t> &src_wires,
+ WireId dst_wire)
+ {
+ std::priority_queue<QueuedWire, std::vector<QueuedWire>,
+ QueuedWire::Greater>
+ queue;
+
+ visited.clear();
+
+ for (auto &it : src_wires) {
+ QueuedWire qw;
+ qw.wire = it.first;
+ qw.pip = PipId();
+ qw.delay = it.second;
+ qw.togo = ctx->estimateDelay(qw.wire, dst_wire);
+ qw.randtag = ctx->rng();
+
+ queue.push(qw);
+ visited[qw.wire] = qw;
+ }
+
+ while (!queue.empty() && !visited.count(dst_wire)) {
+ QueuedWire qw = queue.top();
+ queue.pop();
+
+ for (auto pip : ctx->getPipsDownhill(qw.wire)) {
+ delay_t next_delay = qw.delay;
+ IdString ripupNet = net_name;
+ visitCnt++;
+
+ if (!ctx->checkPipAvail(pip)) {
+ if (!ripup)
+ continue;
+ ripupNet = ctx->getPipNet(pip, true);
+ if (ripupNet == net_name)
+ continue;
+ }
+
+ WireId next_wire = ctx->getPipDstWire(pip);
+ next_delay += ctx->getPipDelay(pip).avgDelay();
+
+ if (!ctx->checkWireAvail(next_wire)) {
+ if (!ripup)
+ continue;
+ ripupNet = ctx->getWireNet(next_wire, true);
+ if (ripupNet == net_name)
+ continue;
+ }
+
+ if (ripupNet != net_name)
+ next_delay += ripup_penalty;
+ assert(next_delay >= 0);
+
+ if (visited.count(next_wire)) {
+ if (visited.at(next_wire).delay <=
+ next_delay + ctx->getDelayEpsilon())
+ continue;
+#if 0 // FIXME
+ if (ctx->verbose)
+ log("Found better route to %s. Old vs new delay "
+ "estimate: %.3f %.3f\n",
+ ctx->getWireName(next_wire).c_str(),
+ ctx->getDelayNS(visited.at(next_wire).delay),
+ ctx->getDelayNS(next_delay));
+#endif
+ revisitCnt++;
+ }
+
+ QueuedWire next_qw;
+ next_qw.wire = next_wire;
+ next_qw.pip = pip;
+ next_qw.delay = next_delay;
+ next_qw.togo = ctx->estimateDelay(next_wire, dst_wire);
+ qw.randtag = ctx->rng();
+
+ visited[next_qw.wire] = next_qw;
+ queue.push(next_qw);
+ }
+ }
+ }
+
+ Router(Context *ctx, WireId src_wire, WireId dst_wire, bool ripup = false,
+ delay_t ripup_penalty = 0)
+ : ctx(ctx), ripup(ripup), ripup_penalty(ripup_penalty)
+ {
+ std::unordered_map<WireId, delay_t> src_wires;
+ src_wires[src_wire] = 0;
+ route(src_wires, dst_wire);
+ }
+
Router(Context *ctx, IdString net_name, bool ripup = false,
delay_t ripup_penalty = 0)
+ : ctx(ctx), net_name(net_name), ripup(ripup),
+ ripup_penalty(ripup_penalty)
{
auto net_info = ctx->nets.at(net_name);
@@ -108,8 +206,8 @@ struct Router
if (ctx->verbose)
log(" Source wire: %s\n", ctx->getWireName(src_wire).c_str(ctx));
- std::unordered_map<WireId, DelayInfo> src_wires;
- src_wires[src_wire] = DelayInfo();
+ std::unordered_map<WireId, delay_t> src_wires;
+ src_wires[src_wire] = 0;
net_info->wires[src_wire] = PipId();
ctx->bindWire(src_wire, net_name);
@@ -156,81 +254,7 @@ struct Router
float(ctx->estimateDelay(src_wire, dst_wire)));
}
- std::unordered_map<WireId, QueuedWire> visited;
- std::priority_queue<QueuedWire, std::vector<QueuedWire>,
- QueuedWire::Greater>
- queue;
-
- for (auto &it : src_wires) {
- QueuedWire qw;
- qw.wire = it.first;
- qw.pip = PipId();
- qw.delay = it.second.avgDelay();
- qw.togo = ctx->estimateDelay(qw.wire, dst_wire);
- qw.randtag = ctx->rng();
-
- queue.push(qw);
- visited[qw.wire] = qw;
- }
-
- while (!queue.empty() && !visited.count(dst_wire)) {
- QueuedWire qw = queue.top();
- queue.pop();
-
- for (auto pip : ctx->getPipsDownhill(qw.wire)) {
- delay_t next_delay = qw.delay;
- IdString ripupNet = net_name;
- visitCnt++;
-
- if (!ctx->checkPipAvail(pip)) {
- if (!ripup)
- continue;
- ripupNet = ctx->getPipNet(pip, true);
- if (ripupNet == net_name)
- continue;
- }
-
- WireId next_wire = ctx->getPipDstWire(pip);
- next_delay += ctx->getPipDelay(pip).avgDelay();
-
- if (!ctx->checkWireAvail(next_wire)) {
- if (!ripup)
- continue;
- ripupNet = ctx->getWireNet(next_wire, true);
- if (ripupNet == net_name)
- continue;
- }
-
- if (ripupNet != net_name)
- next_delay += ripup_penalty;
- assert(next_delay >= 0);
-
- if (visited.count(next_wire)) {
- if (visited.at(next_wire).delay <=
- next_delay + ctx->getDelayEpsilon())
- continue;
-#if 0 // FIXME
- if (ctx->verbose)
- log("Found better route to %s. Old vs new delay "
- "estimate: %.3f %.3f\n",
- ctx->getWireName(next_wire).c_str(),
- ctx->getDelayNS(visited.at(next_wire).delay),
- ctx->getDelayNS(next_delay));
-#endif
- revisitCnt++;
- }
-
- QueuedWire next_qw;
- next_qw.wire = next_wire;
- next_qw.pip = pip;
- next_qw.delay = next_delay;
- next_qw.togo = ctx->estimateDelay(next_wire, dst_wire);
- qw.randtag = ctx->rng();
-
- visited[next_qw.wire] = next_qw;
- queue.push(next_qw);
- }
- }
+ route(src_wires, dst_wire);
if (visited.count(dst_wire) == 0) {
if (ctx->verbose)
@@ -287,7 +311,7 @@ struct Router
ctx->bindWire(cursor, net_name);
ctx->bindPip(visited[cursor].pip, net_name);
- src_wires[cursor] = ctx->getPipDelay(visited[cursor].pip);
+ src_wires[cursor] = visited[cursor].delay;
cursor = ctx->getPipSrcWire(visited[cursor].pip);
}
}