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<PipId, int> pipScores;
std::unordered_map<NetInfo*, int> netScores;
int arcs_with_ripup = 0;
int arcs_without_ripup = 0;
@ -146,21 +147,23 @@ struct Router1
if (ctx->debug)
log(" ripup net %s\n", net->name.c_str(ctx));
netScores[net]++;
auto net_wires_copy = net->wires;
for (auto &it : net_wires_copy) {
if (it.second.pip == PipId())
ripup_wire(it.first, true);
ripup_wire(it.first, 4);
else
ripup_pip(it.second.pip, true);
ripup_pip(it.second.pip, 4);
}
ripup_flag = true;
}
void ripup_wire(WireId wire, bool extra_indent = false)
void ripup_wire(WireId wire, int extra_indent = 0)
{
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]++;
@ -182,14 +185,13 @@ struct Router1
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);
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]++;
if (ctx->getBoundPipNet(pip)) {
@ -204,6 +206,7 @@ struct Router1
if (0) {
remove_wire_arcs:
wireScores[wire]++;
for (auto &it : wire_to_arcs[wire]) {
arc_to_wires[it].erase(wire);
arc_queue_insert(it);
@ -213,9 +216,11 @@ remove_wire_arcs:
NetInfo *net = ctx->getConflictingPipNet(pip);
if (net != nullptr) {
wireScores[wire] += net->wires.size();
pipScores[pip] += net->wires.size();
ripup_net(net);
wire = ctx->getConflictingPipWire(pip);
if (wire != WireId())
ripup_wire(wire, 2);
else
ripup_net(net);
}
ripup_flag = true;
@ -436,11 +441,11 @@ remove_wire_arcs:
if (!ripup)
continue;
next_penalty += cfg.wireRipupPenalty;
auto scores_it = wireScores.find(next_wire);
if (scores_it != wireScores.end())
next_penalty += scores_it->second * cfg.wireRipupPenalty;
else
next_penalty += cfg.wireRipupPenalty;
}
}
@ -451,16 +456,29 @@ remove_wire_arcs:
continue;
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;
} else {
pip_self_ripup:
if (!ripup)
continue;
auto scores_it = pipScores.find(pip);
if (scores_it != pipScores.end())
next_penalty += scores_it->second * cfg.pipRipupPenalty;
else
next_penalty += cfg.pipRipupPenalty;
next_penalty += cfg.pipRipupPenalty;
auto pip_scores_it = pipScores.find(pip);
if (pip_scores_it != pipScores.end())
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)
continue;
if (next_delay + ctx->getDelayEpsilon() >= old_delay)
continue;
#if 0
if (ctx->debug)
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;
}
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)
std::unordered_set<WireId> unassign_wires = arc_to_wires[arc];
@ -615,6 +636,7 @@ Router1Cfg::Router1Cfg(Context *ctx) : Settings(ctx)
wireRipupPenalty = ctx->getRipupDelayPenalty();
pipRipupPenalty = ctx->getRipupDelayPenalty();
netRipupPenalty = ctx->getRipupDelayPenalty();
wireReuseBonus = wireRipupPenalty/8;
pipReuseBonus = pipRipupPenalty/8;

View File

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

View File

@ -217,12 +217,12 @@ Return the net a wire is bound to.
### 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.
This returns nullptr if the wire is already available,
or if there is no single net that can be unbound to make this
wire available.
or if there is no net that can be unbound from the wire to make it
available.
### DelayInfo getWireDelay(WireId wire) const
@ -289,11 +289,21 @@ Return the net this pip is bound to.
### NetInfo \*getConflictingPipNet(PipId pip) const
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
limited to the conflicting wire being bound to the destination wire for this
pip.
This returns nullptr if the pip is already available,
or if there is no single net that can be unrouted to make
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

View File

@ -733,6 +733,11 @@ struct Arch : BaseCtx
return pip_to_net.at(pip);
}
WireId getConflictingPipWire(PipId pip) const
{
return WireId();
}
AllPipRange getPips() const
{
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; }
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; }
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;
NetInfo *getBoundPipNet(PipId pip) const;
NetInfo *getConflictingPipNet(PipId pip) const;
WireId getConflictingPipWire(PipId pip) const;
const std::vector<PipId> &getPips() const;
Loc getPipLocation(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, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
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),
ElementType::WIRE);
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<NetInfo *> wire_to_net;
std::vector<NetInfo *> pip_to_net;
std::vector<NetInfo *> switches_locked;
std::vector<WireId> switches_locked;
ArchArgs args;
Arch(ArchArgs args);
@ -546,7 +546,7 @@ struct Arch : BaseCtx
auto pip = it->second.pip;
if (pip != PipId()) {
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);
@ -608,14 +608,15 @@ struct Arch : BaseCtx
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] == nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == nullptr);
pip_to_net[pip.index] = net;
switches_locked[chip_info->pip_data[pip.index].switch_index] = net;
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == WireId());
WireId dst;
dst.index = chip_info->pip_data[pip.index].dst;
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;
net->wires[dst].pip = pip;
net->wires[dst].strength = strength;
@ -627,7 +628,7 @@ struct Arch : BaseCtx
{
NPNR_ASSERT(pip != PipId());
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;
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] = 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);
refreshUiWire(dst);
}
@ -647,7 +648,7 @@ struct Arch : BaseCtx
auto &pi = chip_info->pip_data[pip.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;
if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
@ -672,6 +673,13 @@ struct Arch : BaseCtx
}
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());
return switches_locked[chip_info->pip_data[pip.index].switch_index];