Add getConflictingPipWire() arch API, router1 improvements

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2018-11-11 11:34:38 +01:00
parent 285bffeac5
commit d2bdb670c0
8 changed files with 87 additions and 36 deletions

View File

@ -100,6 +100,7 @@ struct Router1
std::unordered_map<WireId, int> wireScores; std::unordered_map<WireId, int> wireScores;
std::unordered_map<PipId, int> pipScores; std::unordered_map<PipId, int> pipScores;
std::unordered_map<NetInfo*, int> netScores;
int arcs_with_ripup = 0; int arcs_with_ripup = 0;
int arcs_without_ripup = 0; int arcs_without_ripup = 0;
@ -146,21 +147,23 @@ struct Router1
if (ctx->debug) if (ctx->debug)
log(" ripup net %s\n", net->name.c_str(ctx)); log(" ripup net %s\n", net->name.c_str(ctx));
netScores[net]++;
auto net_wires_copy = net->wires; auto net_wires_copy = net->wires;
for (auto &it : net_wires_copy) { for (auto &it : net_wires_copy) {
if (it.second.pip == PipId()) if (it.second.pip == PipId())
ripup_wire(it.first, true); ripup_wire(it.first, 4);
else else
ripup_pip(it.second.pip, true); ripup_pip(it.second.pip, 4);
} }
ripup_flag = true; ripup_flag = true;
} }
void ripup_wire(WireId wire, bool extra_indent = false) void ripup_wire(WireId wire, int extra_indent = 0)
{ {
if (ctx->debug) if (ctx->debug)
log(" %sripup wire %s\n", extra_indent ? " " : "", ctx->getWireName(wire).c_str(ctx)); log(" %*sripup wire %s\n", extra_indent, "", ctx->getWireName(wire).c_str(ctx));
wireScores[wire]++; wireScores[wire]++;
@ -182,14 +185,13 @@ struct Router1
ripup_flag = true; ripup_flag = true;
} }
void ripup_pip(PipId pip, bool extra_indent = false) void ripup_pip(PipId pip, int extra_indent = 0)
{ {
WireId wire = ctx->getPipDstWire(pip); WireId wire = ctx->getPipDstWire(pip);
if (ctx->debug) if (ctx->debug)
log(" %sripup pip %s (%s)\n", extra_indent ? " " : "", ctx->getPipName(pip).c_str(ctx), ctx->getWireName(wire).c_str(ctx)); log(" %*sripup pip %s (%s)\n", extra_indent, "", ctx->getPipName(pip).c_str(ctx), ctx->getWireName(wire).c_str(ctx));
wireScores[wire]++;
pipScores[pip]++; pipScores[pip]++;
if (ctx->getBoundPipNet(pip)) { if (ctx->getBoundPipNet(pip)) {
@ -204,6 +206,7 @@ struct Router1
if (0) { if (0) {
remove_wire_arcs: remove_wire_arcs:
wireScores[wire]++;
for (auto &it : wire_to_arcs[wire]) { for (auto &it : wire_to_arcs[wire]) {
arc_to_wires[it].erase(wire); arc_to_wires[it].erase(wire);
arc_queue_insert(it); arc_queue_insert(it);
@ -213,9 +216,11 @@ remove_wire_arcs:
NetInfo *net = ctx->getConflictingPipNet(pip); NetInfo *net = ctx->getConflictingPipNet(pip);
if (net != nullptr) { if (net != nullptr) {
wireScores[wire] += net->wires.size(); wire = ctx->getConflictingPipWire(pip);
pipScores[pip] += net->wires.size(); if (wire != WireId())
ripup_net(net); ripup_wire(wire, 2);
else
ripup_net(net);
} }
ripup_flag = true; ripup_flag = true;
@ -436,11 +441,11 @@ remove_wire_arcs:
if (!ripup) if (!ripup)
continue; continue;
next_penalty += cfg.wireRipupPenalty;
auto scores_it = wireScores.find(next_wire); auto scores_it = wireScores.find(next_wire);
if (scores_it != wireScores.end()) if (scores_it != wireScores.end())
next_penalty += scores_it->second * cfg.wireRipupPenalty; next_penalty += scores_it->second * cfg.wireRipupPenalty;
else
next_penalty += cfg.wireRipupPenalty;
} }
} }
@ -451,16 +456,29 @@ remove_wire_arcs:
continue; continue;
if (ripupPipNet == net_info) { if (ripupPipNet == net_info) {
auto net_info_wire_it = net_info->wires.find(next_wire);
if (net_info_wire_it == net_info->wires.end() || net_info_wire_it->second.pip != pip)
goto pip_self_ripup;
next_bonus += cfg.pipReuseBonus; next_bonus += cfg.pipReuseBonus;
} else { } else {
pip_self_ripup:
if (!ripup) if (!ripup)
continue; continue;
auto scores_it = pipScores.find(pip); next_penalty += cfg.pipRipupPenalty;
if (scores_it != pipScores.end())
next_penalty += scores_it->second * cfg.pipRipupPenalty; auto pip_scores_it = pipScores.find(pip);
else if (pip_scores_it != pipScores.end())
next_penalty += cfg.pipRipupPenalty; next_penalty += pip_scores_it->second * cfg.pipRipupPenalty;
if (ctx->getConflictingPipWire(pip) == WireId()) {
auto net_scores_it = netScores.find(ripupPipNet);
if (net_scores_it != netScores.end())
next_penalty += net_scores_it->second * cfg.netRipupPenalty;
next_penalty += ripupPipNet->wires.size() * cfg.wireRipupPenalty;
next_penalty += (ripupPipNet->wires.size()-1) * cfg.pipRipupPenalty;
}
} }
} }
@ -479,9 +497,6 @@ remove_wire_arcs:
if (next_score + ctx->getDelayEpsilon() >= old_score) if (next_score + ctx->getDelayEpsilon() >= old_score)
continue; continue;
if (next_delay + ctx->getDelayEpsilon() >= old_delay)
continue;
#if 0 #if 0
if (ctx->debug) if (ctx->debug)
log("Found better route to %s. Old vs new delay estimate: %.3f (%.3f) %.3f (%.3f)\n", log("Found better route to %s. Old vs new delay estimate: %.3f (%.3f) %.3f (%.3f)\n",
@ -538,6 +553,12 @@ remove_wire_arcs:
return false; return false;
} }
if (ctx->debug) {
log(" final route delay: %8.2f\n", ctx->getDelayNS(visited[dst_wire].delay));
log(" final route penalty: %8.2f\n", ctx->getDelayNS(visited[dst_wire].penalty));
log(" final route bonus: %8.2f\n", ctx->getDelayNS(visited[dst_wire].bonus));
}
// bind resulting route (and maybe unroute other nets) // bind resulting route (and maybe unroute other nets)
std::unordered_set<WireId> unassign_wires = arc_to_wires[arc]; std::unordered_set<WireId> unassign_wires = arc_to_wires[arc];
@ -615,6 +636,7 @@ Router1Cfg::Router1Cfg(Context *ctx) : Settings(ctx)
wireRipupPenalty = ctx->getRipupDelayPenalty(); wireRipupPenalty = ctx->getRipupDelayPenalty();
pipRipupPenalty = ctx->getRipupDelayPenalty(); pipRipupPenalty = ctx->getRipupDelayPenalty();
netRipupPenalty = ctx->getRipupDelayPenalty();
wireReuseBonus = wireRipupPenalty/8; wireReuseBonus = wireRipupPenalty/8;
pipReuseBonus = pipRipupPenalty/8; pipReuseBonus = pipRipupPenalty/8;

View File

@ -35,6 +35,7 @@ struct Router1Cfg : Settings
bool useEstimate; bool useEstimate;
delay_t wireRipupPenalty; delay_t wireRipupPenalty;
delay_t pipRipupPenalty; delay_t pipRipupPenalty;
delay_t netRipupPenalty;
delay_t wireReuseBonus; delay_t wireReuseBonus;
delay_t pipReuseBonus; delay_t pipReuseBonus;
delay_t estimatePrecision; delay_t estimatePrecision;

View File

@ -217,12 +217,12 @@ Return the net a wire is bound to.
### NetInfo \*getConflictingWireNet(WireId wire) const ### NetInfo \*getConflictingWireNet(WireId wire) const
If this returns a non-nullptr, then unbinding that net If this returns a non-nullptr, then unbinding the wire from that net
will make the given wire available. will make the given wire available.
This returns nullptr if the wire is already available, This returns nullptr if the wire is already available,
or if there is no single net that can be unbound to make this or if there is no net that can be unbound from the wire to make it
wire available. available.
### DelayInfo getWireDelay(WireId wire) const ### DelayInfo getWireDelay(WireId wire) const
@ -289,11 +289,21 @@ Return the net this pip is bound to.
### NetInfo \*getConflictingPipNet(PipId pip) const ### NetInfo \*getConflictingPipNet(PipId pip) const
Return the net that needs to be unbound in order to make this Return the net that needs to be unbound in order to make this
pip available. pip available. Note that it may be neccessary to unroute that
entire net to make the pip available.
This does not need to (but may) return the conflicting wire if the conflict is This returns nullptr if the pip is already available,
limited to the conflicting wire being bound to the destination wire for this or if there is no single net that can be unrouted to make
pip. the pip available.
### WireId getConflictingPipWire(PipId pip) const
Return the single wire that needs to be unbound in order to make this pip
available.
This returns WireId() if the pip is already available,
or if there is no single wire that can be unbound to make
the pip available.
### const\_range\<PipId\> getPips() const ### const\_range\<PipId\> getPips() const

View File

@ -733,6 +733,11 @@ struct Arch : BaseCtx
return pip_to_net.at(pip); return pip_to_net.at(pip);
} }
WireId getConflictingPipWire(PipId pip) const
{
return WireId();
}
AllPipRange getPips() const AllPipRange getPips() const
{ {
AllPipRange range; AllPipRange range;

View File

@ -373,6 +373,8 @@ NetInfo *Arch::getBoundPipNet(PipId pip) const { return pips.at(pip).bound_net;
NetInfo *Arch::getConflictingPipNet(PipId pip) const { return pips.at(pip).bound_net; } NetInfo *Arch::getConflictingPipNet(PipId pip) const { return pips.at(pip).bound_net; }
WireId Arch::getConflictingPipWire(PipId pip) const { return pips.at(pip).bound_net ? pips.at(pip).dstWire : WireId(); }
const std::vector<PipId> &Arch::getPips() const { return pip_ids; } const std::vector<PipId> &Arch::getPips() const { return pip_ids; }
Loc Arch::getPipLocation(PipId pip) const { return pips.at(pip).loc; } Loc Arch::getPipLocation(PipId pip) const { return pips.at(pip).loc; }

View File

@ -187,6 +187,7 @@ struct Arch : BaseCtx
bool checkPipAvail(PipId pip) const; bool checkPipAvail(PipId pip) const;
NetInfo *getBoundPipNet(PipId pip) const; NetInfo *getBoundPipNet(PipId pip) const;
NetInfo *getConflictingPipNet(PipId pip) const; NetInfo *getConflictingPipNet(PipId pip) const;
WireId getConflictingPipWire(PipId pip) const;
const std::vector<PipId> &getPips() const; const std::vector<PipId> &getPips() const;
Loc getPipLocation(PipId pip) const; Loc getPipLocation(PipId pip) const;
WireId getPipSrcWire(PipId pip) const; WireId getPipSrcWire(PipId pip) const;

View File

@ -515,6 +515,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)), addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
ElementType::NET); ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->getWireName(ctx->getConflictingPipWire(pip)).c_str(ctx),
ElementType::WIRE);
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx), addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx),
ElementType::WIRE); ElementType::WIRE);
addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx), addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx),

View File

@ -404,7 +404,7 @@ struct Arch : BaseCtx
std::vector<CellInfo *> bel_to_cell; std::vector<CellInfo *> bel_to_cell;
std::vector<NetInfo *> wire_to_net; std::vector<NetInfo *> wire_to_net;
std::vector<NetInfo *> pip_to_net; std::vector<NetInfo *> pip_to_net;
std::vector<NetInfo *> switches_locked; std::vector<WireId> switches_locked;
ArchArgs args; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
@ -546,7 +546,7 @@ struct Arch : BaseCtx
auto pip = it->second.pip; auto pip = it->second.pip;
if (pip != PipId()) { if (pip != PipId()) {
pip_to_net[pip.index] = nullptr; pip_to_net[pip.index] = nullptr;
switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr; switches_locked[chip_info->pip_data[pip.index].switch_index] = WireId();
} }
net_wires.erase(it); net_wires.erase(it);
@ -608,14 +608,15 @@ struct Arch : BaseCtx
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] == nullptr); NPNR_ASSERT(pip_to_net[pip.index] == nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == nullptr); NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == WireId());
pip_to_net[pip.index] = net;
switches_locked[chip_info->pip_data[pip.index].switch_index] = net;
WireId dst; WireId dst;
dst.index = chip_info->pip_data[pip.index].dst; dst.index = chip_info->pip_data[pip.index].dst;
NPNR_ASSERT(wire_to_net[dst.index] == nullptr); NPNR_ASSERT(wire_to_net[dst.index] == nullptr);
pip_to_net[pip.index] = net;
switches_locked[chip_info->pip_data[pip.index].switch_index] = dst;
wire_to_net[dst.index] = net; wire_to_net[dst.index] = net;
net->wires[dst].pip = pip; net->wires[dst].pip = pip;
net->wires[dst].strength = strength; net->wires[dst].strength = strength;
@ -627,7 +628,7 @@ struct Arch : BaseCtx
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] != nullptr); NPNR_ASSERT(pip_to_net[pip.index] != nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != nullptr); NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != WireId());
WireId dst; WireId dst;
dst.index = chip_info->pip_data[pip.index].dst; dst.index = chip_info->pip_data[pip.index].dst;
@ -636,7 +637,7 @@ struct Arch : BaseCtx
pip_to_net[pip.index]->wires.erase(dst); pip_to_net[pip.index]->wires.erase(dst);
pip_to_net[pip.index] = nullptr; pip_to_net[pip.index] = nullptr;
switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr; switches_locked[chip_info->pip_data[pip.index].switch_index] = WireId();
refreshUiPip(pip); refreshUiPip(pip);
refreshUiWire(dst); refreshUiWire(dst);
} }
@ -647,7 +648,7 @@ struct Arch : BaseCtx
auto &pi = chip_info->pip_data[pip.index]; auto &pi = chip_info->pip_data[pip.index];
auto &si = chip_info->bits_info->switches[pi.switch_index]; auto &si = chip_info->bits_info->switches[pi.switch_index];
if (switches_locked[pi.switch_index] != nullptr) if (switches_locked[pi.switch_index] != WireId())
return false; return false;
if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) { if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
@ -672,6 +673,13 @@ struct Arch : BaseCtx
} }
NetInfo *getConflictingPipNet(PipId pip) const NetInfo *getConflictingPipNet(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
WireId wire = switches_locked[chip_info->pip_data[pip.index].switch_index];
return wire == WireId() ? nullptr : wire_to_net[wire.index];
}
WireId getConflictingPipWire(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
return switches_locked[chip_info->pip_data[pip.index].switch_index]; return switches_locked[chip_info->pip_data[pip.index].switch_index];