Add getConflictingPipWire() arch API, router1 improvements
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
parent
285bffeac5
commit
d2bdb670c0
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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; }
|
||||||
|
@ -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;
|
||||||
|
@ -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),
|
||||||
|
26
ice40/arch.h
26
ice40/arch.h
@ -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];
|
||||||
|
Loading…
Reference in New Issue
Block a user