router2: A* main loop
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
dbb771dfe4
commit
37d5775694
@ -202,10 +202,15 @@ struct Router2
|
|||||||
double curr_cong_weight, hist_cong_weight, estimate_weight;
|
double curr_cong_weight, hist_cong_weight, estimate_weight;
|
||||||
// Soft-route a net (don't touch Arch data structures which might not be thread safe)
|
// Soft-route a net (don't touch Arch data structures which might not be thread safe)
|
||||||
// If is_mt is true, then strict bounding box rules are applied and log_* won't be called
|
// If is_mt is true, then strict bounding box rules are applied and log_* won't be called
|
||||||
|
struct VisitInfo
|
||||||
|
{
|
||||||
|
WireScore score;
|
||||||
|
PipId pip;
|
||||||
|
};
|
||||||
struct ThreadContext
|
struct ThreadContext
|
||||||
{
|
{
|
||||||
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;
|
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;
|
||||||
std::unordered_map<WireId, QueuedWire> visited;
|
std::unordered_map<WireId, VisitInfo> visited;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ArcRouteResult
|
enum ArcRouteResult
|
||||||
@ -280,8 +285,21 @@ struct Router2
|
|||||||
return base_cost * hist_cost * present_cost / (1 + source_uses) + bias_cost;
|
return base_cost * hist_cost * present_cost / (1 + source_uses) + bias_cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float get_togo_cost(NetInfo *net, size_t user, WireId wire, WireId sink)
|
||||||
|
{
|
||||||
|
auto &wd = wires.at(wire);
|
||||||
|
int source_uses = 0;
|
||||||
|
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(wire, sink)) / (1 + source_uses);
|
||||||
|
}
|
||||||
|
|
||||||
ArcRouteResult route_arc(ThreadContext &t, NetInfo *net, size_t i, bool is_mt, bool is_bb = true)
|
ArcRouteResult route_arc(ThreadContext &t, NetInfo *net, size_t i, bool is_mt, bool is_bb = true)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
auto &nd = nets[net->udata];
|
||||||
|
auto &ad = nd.arcs[i];
|
||||||
auto &usr = net->users.at(i);
|
auto &usr = net->users.at(i);
|
||||||
ROUTE_LOG_DBG("Routing arc %d of net '%s'", int(i), ctx->nameOf(net));
|
ROUTE_LOG_DBG("Routing arc %d of net '%s'", int(i), ctx->nameOf(net));
|
||||||
WireId src_wire = ctx->getNetinfoSourceWire(net), dst_wire = ctx->getNetinfoSinkWire(net, usr);
|
WireId src_wire = ctx->getNetinfoSourceWire(net), dst_wire = ctx->getNetinfoSinkWire(net, usr);
|
||||||
@ -292,20 +310,74 @@ struct Router2
|
|||||||
if (dst_wire == WireId())
|
if (dst_wire == WireId())
|
||||||
ARC_LOG_ERR("No wire found for port %s on destination cell %s.\n", ctx->nameOf(usr.port),
|
ARC_LOG_ERR("No wire found for port %s on destination cell %s.\n", ctx->nameOf(usr.port),
|
||||||
ctx->nameOf(usr.cell));
|
ctx->nameOf(usr.cell));
|
||||||
|
// Ripup arc to start with
|
||||||
|
ripup_arc(net, i);
|
||||||
|
|
||||||
bind_pip_internal(net, i, src_wire, PipId());
|
|
||||||
|
|
||||||
return ARC_SUCCESS;
|
|
||||||
}
|
|
||||||
#undef ARC_ERR
|
|
||||||
bool route_net(ThreadContext &t, NetInfo *net, bool is_mt)
|
|
||||||
{
|
|
||||||
ROUTE_LOG_DBG("Routing net '%s'...\n", ctx->nameOf(net));
|
|
||||||
if (!t.queue.empty()) {
|
if (!t.queue.empty()) {
|
||||||
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> new_queue;
|
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> new_queue;
|
||||||
t.queue.swap(new_queue);
|
t.queue.swap(new_queue);
|
||||||
}
|
}
|
||||||
t.visited.clear();
|
t.visited.clear();
|
||||||
|
|
||||||
|
// Add source wire to queue
|
||||||
|
WireScore base_score;
|
||||||
|
base_score.cost = 0;
|
||||||
|
base_score.delay = ctx->getWireDelay(src_wire).maxDelay();
|
||||||
|
base_score.togo_cost = get_togo_cost(net, i, src_wire, dst_wire);
|
||||||
|
t.queue.push(QueuedWire(src_wire, PipId(), Loc(), base_score));
|
||||||
|
t.visited[src_wire].score = base_score;
|
||||||
|
t.visited[src_wire].pip = PipId();
|
||||||
|
|
||||||
|
while (!t.queue.empty()) {
|
||||||
|
auto curr = t.queue.top();
|
||||||
|
t.queue.pop();
|
||||||
|
// Explore all pips downhill of cursor
|
||||||
|
for (auto dh : ctx->getPipsDownhill(curr.wire)) {
|
||||||
|
// Skip pips outside of box in bounding-box mode
|
||||||
|
if (is_bb && !hit_test_pip(ad.bb, ctx->getPipLocation(dh)))
|
||||||
|
continue;
|
||||||
|
// Evaluate score of next wire
|
||||||
|
WireId next = ctx->getPipSrcWire(dh);
|
||||||
|
WireScore next_score;
|
||||||
|
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 = get_togo_cost(net, i, next, dst_wire);
|
||||||
|
if (!t.visited.count(next) || (t.visited.at(next).score.total() > next_score.total())) {
|
||||||
|
// Add wire to queue if it meets criteria
|
||||||
|
t.queue.push(QueuedWire(next, dh, ctx->getPipLocation(dh), next_score, ctx->rng()));
|
||||||
|
t.visited[next].score = next_score;
|
||||||
|
t.visited[next].pip = dh;
|
||||||
|
if (next == dst_wire)
|
||||||
|
goto loop_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0) {
|
||||||
|
loop_done:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t.visited.count(dst_wire)) {
|
||||||
|
WireId cursor_bwd = dst_wire;
|
||||||
|
while (t.visited.count(cursor_bwd)) {
|
||||||
|
auto &v = t.visited.at(cursor_bwd);
|
||||||
|
bind_pip_internal(net, i, cursor_bwd, v.pip);
|
||||||
|
if (v.pip == PipId()) {
|
||||||
|
NPNR_ASSERT(cursor_bwd == src_wire);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cursor_bwd = ctx->getPipSrcWire(v.pip);
|
||||||
|
}
|
||||||
|
return ARC_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return ARC_RETRY_WITHOUT_BB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef ARC_ERR
|
||||||
|
bool route_net(ThreadContext &t, NetInfo *net, bool is_mt)
|
||||||
|
{
|
||||||
|
ROUTE_LOG_DBG("Routing net '%s'...\n", ctx->nameOf(net));
|
||||||
|
|
||||||
bool have_failures = false;
|
bool have_failures = false;
|
||||||
for (size_t i = 0; i < net->users.size(); i++) {
|
for (size_t i = 0; i < net->users.size(); i++) {
|
||||||
auto res1 = route_arc(t, net, i, is_mt, true);
|
auto res1 = route_arc(t, net, i, is_mt, true);
|
||||||
|
Loading…
Reference in New Issue
Block a user