router2: rework heuristics
This commit is contained in:
parent
f4e6bbd383
commit
a1ad114069
@ -99,6 +99,8 @@ struct TimingAnalyser
|
|||||||
bool have_loops = false;
|
bool have_loops = false;
|
||||||
bool updated_domains = false;
|
bool updated_domains = false;
|
||||||
|
|
||||||
|
void print_fmax();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init_ports();
|
void init_ports();
|
||||||
void get_cell_delays();
|
void get_cell_delays();
|
||||||
@ -115,7 +117,6 @@ struct TimingAnalyser
|
|||||||
void compute_slack();
|
void compute_slack();
|
||||||
void compute_criticality();
|
void compute_criticality();
|
||||||
|
|
||||||
void print_fmax();
|
|
||||||
// get the N most failing endpoints for a given domain pair
|
// get the N most failing endpoints for a given domain pair
|
||||||
std::vector<CellPortKey> get_failing_eps(domain_id_t domain_pair, int count);
|
std::vector<CellPortKey> get_failing_eps(domain_id_t domain_pair, int count);
|
||||||
// print the critical path for an endpoint and domain pair
|
// print the critical path for an endpoint and domain pair
|
||||||
|
@ -899,6 +899,8 @@ bool router1(Context *ctx, const Router1Cfg &cfg)
|
|||||||
last_arcs_with_ripup = router.arcs_with_ripup;
|
last_arcs_with_ripup = router.arcs_with_ripup;
|
||||||
last_arcs_without_ripup = router.arcs_without_ripup;
|
last_arcs_without_ripup = router.arcs_without_ripup;
|
||||||
ctx->yield();
|
ctx->yield();
|
||||||
|
router.tmg.run();
|
||||||
|
router.tmg.print_fmax();
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
router.check();
|
router.check();
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,9 +72,11 @@ struct Router2
|
|||||||
|
|
||||||
struct WireScore
|
struct WireScore
|
||||||
{
|
{
|
||||||
float cost;
|
float delay;
|
||||||
float togo_cost;
|
float togo;
|
||||||
float total() const { return cost + togo_cost; }
|
float congest;
|
||||||
|
float criticality;
|
||||||
|
float total() const { return (delay * criticality) + (congest * (1.0f - criticality)) + togo; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PerWireData
|
struct PerWireData
|
||||||
@ -232,7 +234,7 @@ struct Router2
|
|||||||
{
|
{
|
||||||
|
|
||||||
explicit QueuedWire(int wire = -1, WireScore score = WireScore{}, int randtag = 0)
|
explicit QueuedWire(int wire = -1, WireScore score = WireScore{}, int randtag = 0)
|
||||||
: wire(wire), score(score), randtag(randtag){};
|
: wire(wire), score(score), randtag(randtag) {};
|
||||||
|
|
||||||
int wire;
|
int wire;
|
||||||
WireScore score;
|
WireScore score;
|
||||||
@ -242,8 +244,8 @@ struct Router2
|
|||||||
{
|
{
|
||||||
bool operator()(const QueuedWire &lhs, const QueuedWire &rhs) const noexcept
|
bool operator()(const QueuedWire &lhs, const QueuedWire &rhs) const noexcept
|
||||||
{
|
{
|
||||||
float lhs_score = lhs.score.cost + lhs.score.togo_cost,
|
float lhs_score = lhs.score.total(),
|
||||||
rhs_score = rhs.score.cost + rhs.score.togo_cost;
|
rhs_score = rhs.score.total();
|
||||||
return lhs_score == rhs_score ? lhs.randtag > rhs.randtag : lhs_score > rhs_score;
|
return lhs_score == rhs_score ? lhs.randtag > rhs.randtag : lhs_score > rhs_score;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -350,27 +352,18 @@ struct Router2
|
|||||||
ad.routed = false;
|
ad.routed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float score_wire_for_arc(NetInfo *net, store_index<PortRef> user, size_t phys_pin, WireId wire, PipId pip,
|
float score_wire_for_arc_congest(NetInfo *net, store_index<PortRef> user, size_t phys_pin, WireId wire, PipId pip,
|
||||||
float crit_weight)
|
float crit_weight)
|
||||||
{
|
{
|
||||||
auto &wd = wire_data(wire);
|
auto &wd = wire_data(wire);
|
||||||
auto &nd = nets.at(net->udata);
|
float delay = cfg.get_base_cost(ctx, wire, pip, crit_weight);
|
||||||
float base_cost = cfg.get_base_cost(ctx, wire, pip, crit_weight);
|
return (wd.hist_cong_cost + delay) * (1.0f + float(wd.curr_cong) * 5.0f);
|
||||||
int overuse = wd.curr_cong;
|
|
||||||
float hist_cost = 1.0f + crit_weight * (wd.hist_cong_cost - 1.0f);
|
|
||||||
float bias_cost = 0;
|
|
||||||
int source_uses = 0;
|
|
||||||
if (nd.wires.count(wire)) {
|
|
||||||
overuse -= 1;
|
|
||||||
source_uses = nd.wires.at(wire).second;
|
|
||||||
}
|
}
|
||||||
float present_cost = 1.0f + overuse * curr_cong_weight * crit_weight;
|
|
||||||
if (pip != PipId()) {
|
float score_wire_for_arc_delay(NetInfo *net, store_index<PortRef> user, size_t phys_pin, WireId wire, PipId pip,
|
||||||
Loc pl = ctx->getPipLocation(pip);
|
float crit_weight)
|
||||||
bias_cost = cfg.bias_cost_factor * (base_cost / int(net->users.entries())) *
|
{
|
||||||
((std::abs(pl.x - nd.cx) + std::abs(pl.y - nd.cy)) / float(nd.hpwl));
|
return cfg.get_base_cost(ctx, wire, pip, crit_weight);
|
||||||
}
|
|
||||||
return base_cost * hist_cost * present_cost / (1 + (source_uses * crit_weight)) + bias_cost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float get_togo_cost(NetInfo *net, store_index<PortRef> user, int wire, WireId src_sink, bool bwd, float crit_weight)
|
float get_togo_cost(NetInfo *net, store_index<PortRef> user, int wire, WireId src_sink, bool bwd, float crit_weight)
|
||||||
@ -383,7 +376,7 @@ struct Router2
|
|||||||
}
|
}
|
||||||
// FIXME: timing/wirelength balance?
|
// FIXME: timing/wirelength balance?
|
||||||
delay_t est_delay = ctx->estimateDelay(bwd ? src_sink : wd.w, bwd ? wd.w : src_sink);
|
delay_t est_delay = ctx->estimateDelay(bwd ? src_sink : wd.w, bwd ? wd.w : src_sink);
|
||||||
return (ctx->getDelayNS(est_delay) / (1 + source_uses * crit_weight)) + cfg.ipin_cost_adder;
|
return ctx->getDelayNS(est_delay) * cfg.estimate_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_arc_routing(NetInfo *net, store_index<PortRef> usr, size_t phys_pin)
|
bool check_arc_routing(NetInfo *net, store_index<PortRef> usr, size_t phys_pin)
|
||||||
@ -647,9 +640,11 @@ struct Router2
|
|||||||
// Add 'forward' direction startpoints to queue
|
// Add 'forward' direction startpoints to queue
|
||||||
auto seed_queue_fwd = [&](WireId wire, float wire_cost = 0) {
|
auto seed_queue_fwd = [&](WireId wire, float wire_cost = 0) {
|
||||||
WireScore base_score;
|
WireScore base_score;
|
||||||
base_score.cost = wire_cost;
|
base_score.criticality = crit;
|
||||||
|
base_score.congest = 0.0;
|
||||||
|
base_score.delay = wire_cost;
|
||||||
int wire_idx = wire_to_idx.at(wire);
|
int wire_idx = wire_to_idx.at(wire);
|
||||||
base_score.togo_cost = get_togo_cost(net, i, wire_idx, dst_wire, false, crit_weight);
|
base_score.togo = get_togo_cost(net, i, wire_idx, dst_wire, false, crit);
|
||||||
t.fwd_queue.push(QueuedWire(wire_idx, base_score));
|
t.fwd_queue.push(QueuedWire(wire_idx, base_score));
|
||||||
set_visited_fwd(t, wire_idx, PipId());
|
set_visited_fwd(t, wire_idx, PipId());
|
||||||
};
|
};
|
||||||
@ -677,9 +672,11 @@ struct Router2
|
|||||||
}
|
}
|
||||||
auto seed_queue_bwd = [&](WireId wire) {
|
auto seed_queue_bwd = [&](WireId wire) {
|
||||||
WireScore base_score;
|
WireScore base_score;
|
||||||
base_score.cost = 0;
|
base_score.criticality = crit;
|
||||||
|
base_score.congest = 0.0;
|
||||||
|
base_score.delay = 0;
|
||||||
int wire_idx = wire_to_idx.at(wire);
|
int wire_idx = wire_to_idx.at(wire);
|
||||||
base_score.togo_cost = get_togo_cost(net, i, wire_idx, src_wire, true, crit_weight);
|
base_score.togo = get_togo_cost(net, i, wire_idx, src_wire, true, crit);
|
||||||
t.bwd_queue.push(QueuedWire(wire_idx, base_score));
|
t.bwd_queue.push(QueuedWire(wire_idx, base_score));
|
||||||
set_visited_bwd(t, wire_idx, PipId());
|
set_visited_bwd(t, wire_idx, PipId());
|
||||||
};
|
};
|
||||||
@ -731,9 +728,10 @@ struct Router2
|
|||||||
if (!thread_test_wire(t, nwd))
|
if (!thread_test_wire(t, nwd))
|
||||||
continue; // thread safety issue
|
continue; // thread safety issue
|
||||||
WireScore next_score;
|
WireScore next_score;
|
||||||
next_score.cost = curr.score.cost + score_wire_for_arc(net, i, phys_pin, next, dh, crit_weight);
|
next_score.criticality = crit;
|
||||||
next_score.togo_cost =
|
next_score.congest = curr.score.congest + score_wire_for_arc_congest(net, i, phys_pin, next, dh, crit_weight);
|
||||||
cfg.estimate_weight * get_togo_cost(net, i, next_idx, dst_wire, false, crit_weight);
|
next_score.delay = curr.score.delay + score_wire_for_arc_delay(net, i, phys_pin, next, dh, crit_weight);
|
||||||
|
next_score.togo = get_togo_cost(net, i, next_idx, dst_wire, false, crit_weight);
|
||||||
set_visited_fwd(t, next_idx, dh);
|
set_visited_fwd(t, next_idx, dh);
|
||||||
t.fwd_queue.push(QueuedWire(next_idx, next_score, t.rng.rng()));
|
t.fwd_queue.push(QueuedWire(next_idx, next_score, t.rng.rng()));
|
||||||
}
|
}
|
||||||
@ -777,9 +775,10 @@ struct Router2
|
|||||||
if (!thread_test_wire(t, nwd))
|
if (!thread_test_wire(t, nwd))
|
||||||
continue; // thread safety issue
|
continue; // thread safety issue
|
||||||
WireScore next_score;
|
WireScore next_score;
|
||||||
next_score.cost = curr.score.cost + score_wire_for_arc(net, i, phys_pin, next, uh, crit_weight);
|
next_score.criticality = crit;
|
||||||
next_score.togo_cost =
|
next_score.congest = curr.score.congest + score_wire_for_arc_congest(net, i, phys_pin, next, uh, crit_weight);
|
||||||
cfg.estimate_weight * get_togo_cost(net, i, next_idx, src_wire, true, crit_weight);
|
next_score.delay = curr.score.delay + score_wire_for_arc_delay(net, i, phys_pin, next, uh, crit_weight);
|
||||||
|
next_score.togo = get_togo_cost(net, i, next_idx, src_wire, true, crit_weight);
|
||||||
set_visited_bwd(t, next_idx, uh);
|
set_visited_bwd(t, next_idx, uh);
|
||||||
t.bwd_queue.push(QueuedWire(next_idx, next_score, t.rng.rng()));
|
t.bwd_queue.push(QueuedWire(next_idx, next_score, t.rng.rng()));
|
||||||
}
|
}
|
||||||
@ -1422,7 +1421,7 @@ struct Router2
|
|||||||
int tmgfail = 0;
|
int tmgfail = 0;
|
||||||
if (timing_driven)
|
if (timing_driven)
|
||||||
tmg.run(false);
|
tmg.run(false);
|
||||||
if (timing_driven_ripup && iter < 500) {
|
if (timing_driven_ripup && iter < 500 && overused_wires == 0) {
|
||||||
for (size_t i = 0; i < nets_by_udata.size(); i++) {
|
for (size_t i = 0; i < nets_by_udata.size(); i++) {
|
||||||
NetInfo *ni = nets_by_udata.at(i);
|
NetInfo *ni = nets_by_udata.at(i);
|
||||||
for (auto usr : ni->users.enumerate()) {
|
for (auto usr : ni->users.enumerate()) {
|
||||||
@ -1433,6 +1432,12 @@ struct Router2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (overused_wires > 0) {
|
||||||
|
failed_nets.clear();
|
||||||
|
for (size_t i = 0; i < nets_by_udata.size(); i++) {
|
||||||
|
failed_nets.insert(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (overused_wires == 0 && tmgfail == 0) {
|
if (overused_wires == 0 && tmgfail == 0) {
|
||||||
// Try and actually bind nextpnr Arch API wires
|
// Try and actually bind nextpnr Arch API wires
|
||||||
bind_and_check_all();
|
bind_and_check_all();
|
||||||
@ -1450,6 +1455,7 @@ struct Router2
|
|||||||
++iter;
|
++iter;
|
||||||
if (curr_cong_weight < 1e9)
|
if (curr_cong_weight < 1e9)
|
||||||
curr_cong_weight += cfg.curr_cong_mult;
|
curr_cong_weight += cfg.curr_cong_mult;
|
||||||
|
tmg.print_fmax();
|
||||||
} while (!failed_nets.empty());
|
} while (!failed_nets.empty());
|
||||||
if (cfg.perf_profile) {
|
if (cfg.perf_profile) {
|
||||||
std::vector<std::pair<int, IdString>> nets_by_runtime;
|
std::vector<std::pair<int, IdString>> nets_by_runtime;
|
||||||
|
Loading…
Reference in New Issue
Block a user