diff options
-rw-r--r-- | common/router1.cc | 62 | ||||
-rw-r--r-- | common/router1.h | 1 | ||||
-rw-r--r-- | docs/archapi.md | 24 | ||||
-rw-r--r-- | ecp5/arch.h | 5 | ||||
-rw-r--r-- | generic/arch.cc | 2 | ||||
-rw-r--r-- | generic/arch.h | 1 | ||||
-rw-r--r-- | gui/designwidget.cc | 2 | ||||
-rw-r--r-- | ice40/arch.h | 26 |
8 files changed, 87 insertions, 36 deletions
diff --git a/common/router1.cc b/common/router1.cc index 14591232..f51155e8 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -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; diff --git a/common/router1.h b/common/router1.h index 120bf30e..65975d53 100644 --- a/common/router1.h +++ b/common/router1.h @@ -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; diff --git a/docs/archapi.md b/docs/archapi.md index 73443c15..1bfb7c5c 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -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 diff --git a/ecp5/arch.h b/ecp5/arch.h index 583d539f..c9b1bf43 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -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; diff --git a/generic/arch.cc b/generic/arch.cc index 3e95159a..4f2e07a2 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -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; } diff --git a/generic/arch.h b/generic/arch.h index 22966e2a..d64d03c3 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -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; diff --git a/gui/designwidget.cc b/gui/designwidget.cc index a45752fc..8eda8a76 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -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),
diff --git a/ice40/arch.h b/ice40/arch.h index 27d5db9f..46f2b348 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -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) { @@ -674,6 +675,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]; } |