From d904a3713800409f376b78021b7d890c7c5f505f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 10 Nov 2018 23:50:08 +0100 Subject: [PATCH 01/10] flush logs when throwing an assertion_failure Signed-off-by: Clifford Wolf --- common/nextpnr.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 4e6407b2..2a581cc6 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -18,6 +18,7 @@ */ #include "nextpnr.h" +#include "log.h" NEXTPNR_NAMESPACE_BEGIN @@ -25,6 +26,7 @@ assertion_failure::assertion_failure(std::string msg, std::string expr_str, std: : runtime_error("Assertion failure: " + msg + " (" + filename + ":" + std::to_string(line) + ")"), msg(msg), expr_str(expr_str), filename(filename), line(line) { + log_flush(); } void IdString::set(const BaseCtx *ctx, const std::string &s) From 5b8c8bb966f7d4d2e7fe97137834a75b4e141d2e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 10 Nov 2018 23:50:49 +0100 Subject: [PATCH 02/10] Some router1 cleanups Signed-off-by: Clifford Wolf --- common/router1.cc | 51 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/common/router1.cc b/common/router1.cc index 958edf7d..cac60104 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -649,7 +649,9 @@ bool router1(Context *ctx, const Router1Cfg &cfg) router.arcs_without_ripup - last_arcs_without_ripup, int(router.arc_queue.size())); last_arcs_with_ripup = router.arcs_with_ripup; last_arcs_without_ripup = router.arcs_without_ripup; +#ifndef NDEBUG router.check(); +#endif } arc_key arc = router.arc_queue_pop(); @@ -669,18 +671,17 @@ bool router1(Context *ctx, const Router1Cfg &cfg) iter_cnt, router.arcs_with_ripup, router.arcs_without_ripup, router.arcs_with_ripup - last_arcs_with_ripup, router.arcs_without_ripup - last_arcs_without_ripup, int(router.arc_queue.size())); + log_info("Routing complete.\n"); + #ifndef NDEBUG router.check(); + ctx->check(); + log_assert(ctx->checkRoutedDesign()); #endif - log_info("Routing complete.\n"); - ctx->checkRoutedDesign(); - log_info("Checksum: 0x%08x\n", ctx->checksum()); -#ifndef NDEBUG - ctx->check(); -#endif timing_analysis(ctx, true /* slack_histogram */, true /* print_path */); + ctx->unlock(); return true; } catch (log_execution_error_exception) { @@ -772,9 +773,11 @@ bool Context::checkRoutedDesign() const } if (db_entry.children.empty()) { if (dest_wires.count(w) != 0) { - log(" %*s=> sink %d\n", 2*num, "", dest_wires.at(w)); + if (ctx->debug) + log(" %*s=> sink %d\n", 2*num, "", dest_wires.at(w)); } else { - log(" %*s=> stub\n", 2*num, ""); + if (ctx->debug) + log(" %*s=> stub\n", 2*num, ""); found_stub = true; } } @@ -820,10 +823,34 @@ bool Context::checkRoutedDesign() const } } - log_assert(!found_unrouted); - log_assert(!found_loop); - log_assert(!found_stub); - log_assert(dangling_wires.empty()); + bool fail = false; + + if (found_unrouted) { + if (ctx->debug) + log("check failed: found unrouted arcs\n"); + fail = true; + } + + if (found_loop) { + if (ctx->debug) + log("check failed: found loops\n"); + fail = true; + } + + if (found_stub) { + if (ctx->debug) + log("check failed: found stubs\n"); + fail = true; + } + + if (!dangling_wires.empty()) { + if (ctx->debug) + log("check failed: found dangling wires\n"); + fail = true; + } + + if (fail) + return false; } return true; From e7ae28cafeb72b6e427431c28868516fae170216 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Nov 2018 00:29:25 +0100 Subject: [PATCH 03/10] Minor improvements in router1 Signed-off-by: Clifford Wolf --- common/router1.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/common/router1.cc b/common/router1.cc index cac60104..ed9ac39a 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -247,6 +247,8 @@ remove_wire_arcs: if (skip_net(net_info)) continue; + // log("[check] net: %s\n", net_info->name.c_str(ctx)); + auto src_wire = ctx->getNetinfoSourceWire(net_info); log_assert(src_wire != WireId()); @@ -259,8 +261,10 @@ remove_wire_arcs: arc.user_idx = user_idx; valid_arcs.insert(arc); + // log("[check] arc: %s %s\n", ctx->getWireName(src_wire).c_str(ctx), ctx->getWireName(dst_wire).c_str(ctx)); for (WireId wire : arc_to_wires[arc]) { + // log("[check] wire: %s\n", ctx->getWireName(wire).c_str(ctx)); valid_wires_for_net.insert(wire); log_assert(wire_to_arcs[wire].count(arc)); log_assert(net_info->wires.count(wire)); @@ -567,14 +571,14 @@ remove_wire_arcs: } } - if (ctx->checkWireAvail(cursor)) { + if (net_info->wires.count(cursor) == 0 || net_info->wires.at(cursor).pip != pip) { if (pip == PipId()) { if (ctx->debug) - log(" bind %s\n", ctx->getWireName(cursor).c_str(ctx)); + log(" bind wire %s\n", ctx->getWireName(cursor).c_str(ctx)); ctx->bindWire(cursor, net_info, STRENGTH_WEAK); - } else if (ctx->checkPipAvail(pip)) { + } else { if (ctx->debug) - log(" bind %s\n", ctx->getPipName(pip).c_str(ctx)); + log(" bind pip %s\n", ctx->getPipName(pip).c_str(ctx)); ctx->bindPip(pip, net_info, STRENGTH_WEAK); } } @@ -660,6 +664,7 @@ bool router1(Context *ctx, const Router1Cfg &cfg) log_warning("Failed to find a route for arc %d of net %s.\n", arc.user_idx, arc.net_info->name.c_str(ctx)); #ifndef NDEBUG + router.check(); ctx->check(); #endif ctx->unlock(); From 5cc9b9f61f3e01c05a8895640f6111fe73611fc3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Nov 2018 10:02:32 +0100 Subject: [PATCH 04/10] Bugfix in router1 Signed-off-by: Clifford Wolf --- common/router1.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/common/router1.cc b/common/router1.cc index ed9ac39a..a4b37daf 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -544,21 +544,22 @@ remove_wire_arcs: WireId cursor = dst_wire; while (1) { + auto pip = visited[cursor].pip; + if (ctx->debug) log(" node %s\n", ctx->getWireName(cursor).c_str(ctx)); if (!ctx->checkWireAvail(cursor)) { NetInfo *ripupWireNet = ctx->getConflictingWireNet(cursor); NPNR_ASSERT(ripupWireNet != nullptr); + NPNR_ASSERT(ripupWireNet->wires.count(cursor)); - if (ripupWireNet != net_info) { + if (ripupWireNet != net_info || net_info->wires.at(cursor).pip != pip) { ripup_wire(cursor); NPNR_ASSERT(ctx->checkWireAvail(cursor)); } } - auto pip = visited[cursor].pip; - if (pip == PipId()) { NPNR_ASSERT(cursor == src_wire); } else { @@ -658,6 +659,9 @@ bool router1(Context *ctx, const Router1Cfg &cfg) #endif } + if (ctx->debug) + log("-- %d --\n", iter_cnt); + arc_key arc = router.arc_queue_pop(); if (!router.route_arc(arc, true)) { From 285bffeac5ace1679489c2d23c8c5dc4b06f0bfc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Nov 2018 10:11:55 +0100 Subject: [PATCH 05/10] Another bugfix in router1 Signed-off-by: Clifford Wolf --- common/router1.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/router1.cc b/common/router1.cc index a4b37daf..14591232 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -567,7 +567,7 @@ remove_wire_arcs: NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip); NPNR_ASSERT(ripupPipNet != nullptr); - if (ripupPipNet != net_info || net_info->wires.at(cursor).pip != pip) + if (ripupPipNet != net_info || !net_info->wires.count(cursor) || net_info->wires.at(cursor).pip != pip) ripup_pip(pip); } } From d2bdb670c0be9e18722f79c170fc99d7f41768f1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Nov 2018 11:34:38 +0100 Subject: [PATCH 06/10] Add getConflictingPipWire() arch API, router1 improvements Signed-off-by: Clifford Wolf --- common/router1.cc | 62 ++++++++++++++++++++++++++++++--------------- common/router1.h | 1 + docs/archapi.md | 24 +++++++++++++----- ecp5/arch.h | 5 ++++ generic/arch.cc | 2 ++ generic/arch.h | 1 + gui/designwidget.cc | 2 ++ 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 wireScores; std::unordered_map pipScores; + std::unordered_map 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 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\ 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 &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 &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 bel_to_cell; std::vector wire_to_net; std::vector pip_to_net; - std::vector switches_locked; + std::vector 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]; From dac553cab4b72a052f9738017d13ea40495f610c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Nov 2018 12:04:02 +0100 Subject: [PATCH 07/10] Add some additional checks to router1 to find issues in input netlist Signed-off-by: Clifford Wolf --- common/router1.cc | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/common/router1.cc b/common/router1.cc index f51155e8..578e287b 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -294,6 +294,9 @@ remove_wire_arcs: void setup() { + std::unordered_map src_to_net; + std::unordered_map dst_to_arc; + for (auto &net_it : ctx->nets) { NetInfo *net_info = net_it.second.get(); @@ -307,6 +310,14 @@ remove_wire_arcs: log_error("No wire found for port %s on source cell %s.\n", net_info->driver.port.c_str(ctx), net_info->driver.cell->name.c_str(ctx)); + if (src_to_net.count(src_wire)) + log_error("Found two nets with same source wire %s: %s vs %s\n", ctx->getWireName(src_wire).c_str(ctx), + ctx->nameOf(net_info), ctx->nameOf(src_to_net.at(src_wire))); + + if (dst_to_arc.count(src_wire)) + log_error("Wire %s is used as source and sink in different nets: %s vs %s (%d)\n", ctx->getWireName(src_wire).c_str(ctx), + ctx->nameOf(net_info), ctx->nameOf(dst_to_arc.at(src_wire).net_info), dst_to_arc.at(src_wire).user_idx); + for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx]); @@ -314,10 +325,20 @@ remove_wire_arcs: log_error("No wire found for port %s on destination cell %s.\n", net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); + if (dst_to_arc.count(dst_wire)) + log_error("Found two arcs with same sink wire %s: %s (%d) vs %s (%d)\n", ctx->getWireName(dst_wire).c_str(ctx), + ctx->nameOf(net_info), user_idx, ctx->nameOf(dst_to_arc.at(dst_wire).net_info), dst_to_arc.at(dst_wire).user_idx); + + if (src_to_net.count(dst_wire)) + log_error("Wire %s is used as source and sink in different nets: %s vs %s (%d)\n", ctx->getWireName(dst_wire).c_str(ctx), + ctx->nameOf(src_to_net.at(dst_wire)), ctx->nameOf(net_info), user_idx); + arc_key arc; arc.net_info = net_info; arc.user_idx = user_idx; + dst_to_arc[dst_wire] = arc; + if (net_info->wires.count(src_wire) == 0) { arc_queue_insert(arc, src_wire, dst_wire); continue; @@ -341,6 +362,8 @@ remove_wire_arcs: } } + src_to_net[src_wire] = net_info; + std::vector unbind_wires; for (auto &it : net_info->wires) From ee8826b6e86fdce793a4c58ee685bd6cae5d796e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Nov 2018 12:16:25 +0100 Subject: [PATCH 08/10] Ignore "duplicate" arcs in the same net in router1 Signed-off-by: Clifford Wolf --- common/router1.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/router1.cc b/common/router1.cc index 578e287b..6a888c45 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -325,9 +325,12 @@ remove_wire_arcs: log_error("No wire found for port %s on destination cell %s.\n", net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); - if (dst_to_arc.count(dst_wire)) + if (dst_to_arc.count(dst_wire)) { + if (dst_to_arc.at(dst_wire).net_info == net_info) + continue; log_error("Found two arcs with same sink wire %s: %s (%d) vs %s (%d)\n", ctx->getWireName(dst_wire).c_str(ctx), ctx->nameOf(net_info), user_idx, ctx->nameOf(dst_to_arc.at(dst_wire).net_info), dst_to_arc.at(dst_wire).user_idx); + } if (src_to_net.count(dst_wire)) log_error("Wire %s is used as source and sink in different nets: %s vs %s (%d)\n", ctx->getWireName(dst_wire).c_str(ctx), From f93129634b479ba54d8e33186eb79f412eaeb4a9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Nov 2018 17:28:41 +0100 Subject: [PATCH 09/10] Add getConflictingWireWire() arch API, streamline getConflictingXY semantic Signed-off-by: Clifford Wolf --- common/router1.cc | 229 +++++++++++++++++++++++--------------------- common/router1.h | 1 - docs/archapi.md | 36 ++++--- ecp5/arch.h | 15 ++- generic/arch.h | 3 +- gui/designwidget.cc | 6 +- ice40/arch.h | 45 ++++++--- 7 files changed, 183 insertions(+), 152 deletions(-) diff --git a/common/router1.cc b/common/router1.cc index 6a888c45..64f01c0d 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -99,7 +99,6 @@ struct Router1 std::priority_queue, QueuedWire::Greater> queue; std::unordered_map wireScores; - std::unordered_map pipScores; std::unordered_map netScores; int arcs_with_ripup = 0; @@ -125,6 +124,9 @@ struct Router1 void arc_queue_insert(const arc_key &arc) { + if (queued_arcs.count(arc)) + return; + NetInfo *net_info = arc.net_info; int user_idx = arc.user_idx; @@ -151,10 +153,19 @@ struct Router1 auto net_wires_copy = net->wires; for (auto &it : net_wires_copy) { - if (it.second.pip == PipId()) - ripup_wire(it.first, 4); - else - ripup_pip(it.second.pip, 4); + WireId w = it.first; + + for (auto &it : wire_to_arcs[w]) { + arc_to_wires[it].erase(w); + arc_queue_insert(it); + } + wire_to_arcs[w].clear(); + + if (ctx->debug) + log(" unbind wire %s\n", ctx->getWireName(w).c_str(ctx)); + + ctx->unbindWire(w); + wireScores[w]++; } ripup_flag = true; @@ -163,64 +174,54 @@ struct Router1 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(" ripup wire %s\n", ctx->getWireName(wire).c_str(ctx)); - wireScores[wire]++; + WireId w = ctx->getConflictingWireWire(wire); - if (ctx->getBoundWireNet(wire)) { - for (auto &it : wire_to_arcs[wire]) { - arc_to_wires[it].erase(wire); + if (w == WireId()) { + NetInfo *n = ctx->getConflictingWireNet(wire); + if (n != nullptr) + ripup_net(n); + } else { + for (auto &it : wire_to_arcs[w]) { + arc_to_wires[it].erase(w); arc_queue_insert(it); } - wire_to_arcs[wire].clear(); - ctx->unbindWire(wire); - } + wire_to_arcs[w].clear(); - NetInfo *net = ctx->getConflictingWireNet(wire); - if (net != nullptr) { - wireScores[wire] += net->wires.size(); - ripup_net(net); + if (ctx->debug) + log(" unbind wire %s\n", ctx->getWireName(w).c_str(ctx)); + + ctx->unbindWire(w); + wireScores[w]++; } ripup_flag = true; } - void ripup_pip(PipId pip, int extra_indent = 0) + void ripup_pip(PipId pip) { - 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(" ripup pip %s\n", ctx->getPipName(pip).c_str(ctx)); - pipScores[pip]++; + WireId w = ctx->getConflictingPipWire(pip); - if (ctx->getBoundPipNet(pip)) { - ctx->unbindPip(pip); - goto remove_wire_arcs; - } - - if (ctx->getBoundWireNet(wire)) { - ctx->unbindWire(wire); - goto remove_wire_arcs; - } - - if (0) { -remove_wire_arcs: - wireScores[wire]++; - for (auto &it : wire_to_arcs[wire]) { - arc_to_wires[it].erase(wire); + if (w == WireId()) { + NetInfo *n = ctx->getConflictingPipNet(pip); + if (n != nullptr) + ripup_net(n); + } else { + for (auto &it : wire_to_arcs[w]) { + arc_to_wires[it].erase(w); arc_queue_insert(it); } - wire_to_arcs[wire].clear(); - } + wire_to_arcs[w].clear(); - NetInfo *net = ctx->getConflictingPipNet(pip); - if (net != nullptr) { - wire = ctx->getConflictingPipWire(pip); - if (wire != WireId()) - ripup_wire(wire, 2); - else - ripup_net(net); + if (ctx->debug) + log(" unbind wire %s\n", ctx->getWireName(w).c_str(ctx)); + + ctx->unbindWire(w); + wireScores[w]++; } ripup_flag = true; @@ -455,59 +456,82 @@ remove_wire_arcs: WireId next_wire = ctx->getPipDstWire(pip); next_delay += ctx->getWireDelay(next_wire).maxDelay(); - if (!ctx->checkWireAvail(next_wire)) { - NetInfo *ripupWireNet = ctx->getConflictingWireNet(next_wire); + WireId conflictWireWire = WireId(), conflictPipWire = WireId(); + NetInfo *conflictWireNet = nullptr, *conflictPipNet = nullptr; - if (ripupWireNet == nullptr) + bool wire_reuse = net_info->wires.count(next_wire); + bool pip_reuse = wire_reuse && net_info->wires.at(next_wire).pip == pip; + + if (!ctx->checkWireAvail(next_wire) && !wire_reuse) { + if (!ripup) continue; - - if (ripupWireNet == net_info) { - next_bonus += cfg.wireReuseBonus; - } else { - if (!ripup) + conflictWireWire = ctx->getConflictingWireWire(next_wire); + if (conflictWireWire == WireId()) { + conflictWireNet = ctx->getConflictingWireNet(next_wire); + if (conflictWireNet == nullptr) continue; - - next_penalty += cfg.wireRipupPenalty; - - auto scores_it = wireScores.find(next_wire); - if (scores_it != wireScores.end()) - next_penalty += scores_it->second * cfg.wireRipupPenalty; } } - if (!ctx->checkPipAvail(pip)) { - NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip); - - if (ripupPipNet == nullptr) + if (!ctx->checkPipAvail(pip) && !pip_reuse) { + if (!ripup) 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) + conflictPipWire = ctx->getConflictingPipWire(pip); + if (conflictPipWire == WireId()) { + conflictPipNet = ctx->getConflictingPipNet(pip); + if (conflictPipNet == nullptr) continue; - - 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; - } } } + if (conflictWireNet != nullptr && conflictPipWire != WireId() && conflictWireNet->wires.count(conflictPipWire)) + conflictPipWire = WireId(); + + if (conflictPipNet != nullptr && conflictWireWire != WireId() && conflictPipNet->wires.count(conflictWireWire)) + conflictWireWire = WireId(); + + if (conflictWireWire == conflictPipWire) + conflictWireWire = WireId(); + + if (conflictWireNet == conflictPipNet) + conflictWireNet = nullptr; + + if (wire_reuse) + next_bonus += cfg.wireReuseBonus; + + if (pip_reuse) + next_bonus += cfg.pipReuseBonus; + + if (conflictWireWire != WireId()) { + auto scores_it = wireScores.find(conflictWireWire); + if (scores_it != wireScores.end()) + next_penalty += scores_it->second * cfg.wireRipupPenalty; + next_penalty += cfg.wireRipupPenalty; + } + + if (conflictPipWire != WireId()) { + auto scores_it = wireScores.find(conflictPipWire); + if (scores_it != wireScores.end()) + next_penalty += scores_it->second * cfg.wireRipupPenalty; + next_penalty += cfg.wireRipupPenalty; + } + + if (conflictWireNet != nullptr) { + auto scores_it = netScores.find(conflictWireNet); + if (scores_it != netScores.end()) + next_penalty += scores_it->second * cfg.netRipupPenalty; + next_penalty += cfg.netRipupPenalty; + next_penalty += conflictWireNet->wires.size() * cfg.wireRipupPenalty; + } + + if (conflictPipNet != nullptr) { + auto scores_it = netScores.find(conflictPipNet); + if (scores_it != netScores.end()) + next_penalty += scores_it->second * cfg.netRipupPenalty; + next_penalty += cfg.netRipupPenalty; + next_penalty += conflictPipNet->wires.size() * cfg.wireRipupPenalty; + } + delay_t next_score = next_delay + next_penalty; NPNR_ASSERT(next_score >= 0); @@ -596,30 +620,20 @@ pip_self_ripup: if (ctx->debug) log(" node %s\n", ctx->getWireName(cursor).c_str(ctx)); - if (!ctx->checkWireAvail(cursor)) { - NetInfo *ripupWireNet = ctx->getConflictingWireNet(cursor); - NPNR_ASSERT(ripupWireNet != nullptr); - NPNR_ASSERT(ripupWireNet->wires.count(cursor)); + if (pip == PipId()) + NPNR_ASSERT(cursor == src_wire); - if (ripupWireNet != net_info || net_info->wires.at(cursor).pip != pip) { + if (!net_info->wires.count(cursor) || net_info->wires.at(cursor).pip != pip) { + if (!ctx->checkWireAvail(cursor)) { ripup_wire(cursor); NPNR_ASSERT(ctx->checkWireAvail(cursor)); } - } - if (pip == PipId()) { - NPNR_ASSERT(cursor == src_wire); - } else { - if (!ctx->checkPipAvail(pip)) { - NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip); - NPNR_ASSERT(ripupPipNet != nullptr); - - if (ripupPipNet != net_info || !net_info->wires.count(cursor) || net_info->wires.at(cursor).pip != pip) - ripup_pip(pip); + if (pip != PipId() && !ctx->checkPipAvail(pip)) { + ripup_pip(pip); + NPNR_ASSERT(ctx->checkPipAvail(pip)); } - } - if (net_info->wires.count(cursor) == 0 || net_info->wires.at(cursor).pip != pip) { if (pip == PipId()) { if (ctx->debug) log(" bind wire %s\n", ctx->getWireName(cursor).c_str(ctx)); @@ -661,11 +675,10 @@ Router1Cfg::Router1Cfg(Context *ctx) : Settings(ctx) useEstimate = get("router1/useEstimate", true); wireRipupPenalty = ctx->getRipupDelayPenalty(); - pipRipupPenalty = ctx->getRipupDelayPenalty(); - netRipupPenalty = ctx->getRipupDelayPenalty(); + netRipupPenalty = 10*ctx->getRipupDelayPenalty(); wireReuseBonus = wireRipupPenalty/8; - pipReuseBonus = pipRipupPenalty/8; + pipReuseBonus = wireRipupPenalty/2; estimatePrecision = 100 * ctx->getRipupDelayPenalty(); } diff --git a/common/router1.h b/common/router1.h index 65975d53..d6113441 100644 --- a/common/router1.h +++ b/common/router1.h @@ -34,7 +34,6 @@ struct Router1Cfg : Settings bool fullCleanupReroute; bool useEstimate; delay_t wireRipupPenalty; - delay_t pipRipupPenalty; delay_t netRipupPenalty; delay_t wireReuseBonus; delay_t pipReuseBonus; diff --git a/docs/archapi.md b/docs/archapi.md index 1bfb7c5c..85bc6ccd 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -215,14 +215,15 @@ Return true if the wire is available, i.e. can be bound to a net. Return the net a wire is bound to. -### NetInfo \*getConflictingWireNet(WireId wire) const +### WireId getConflictingWireWire(WireId wire) const -If this returns a non-nullptr, then unbinding the wire from that net +If this returns a non-WireId(), then unbinding that wire will make the given wire available. -This returns nullptr if the wire is already available, -or if there is no net that can be unbound from the wire to make it -available. +### NetInfo \*getConflictingWireNet(WireId wire) const + +If this returns a non-nullptr, then unbinding that entire net +will make the given wire available. ### DelayInfo getWireDelay(WireId wire) const @@ -282,28 +283,23 @@ This method must also update `NetInfo::wires`. Returns true if the given pip is available to be bound to a net. +Users must also check if the pip destination wire is available +with `checkWireAvail(getPipDstWire(pip))` before binding the +pip to a net. + ### NetInfo \*getBoundPipNet(PipId pip) const 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. Note that it may be neccessary to unroute that -entire net to make the pip available. - -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. +If this returns a non-WireId(), then unbinding that wire +will make the given 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. +### NetInfo \*getConflictingPipNet(PipId pip) const + +If this returns a non-nullptr, then unbinding that entire net +will make the given pip available. ### const\_range\ getPips() const diff --git a/ecp5/arch.h b/ecp5/arch.h index c9b1bf43..bd4881c2 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -619,6 +619,11 @@ struct Arch : BaseCtx return wire_to_net.at(wire); } + WireId getConflictingWireWire(WireId wire) const + { + return wire; + } + NetInfo *getConflictingWireNet(WireId wire) const { NPNR_ASSERT(wire != WireId()); @@ -724,6 +729,11 @@ struct Arch : BaseCtx return pip_to_net.at(pip); } + WireId getConflictingPipWire(PipId pip) const + { + return WireId(); + } + NetInfo *getConflictingPipNet(PipId pip) const { NPNR_ASSERT(pip != PipId()); @@ -733,11 +743,6 @@ 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.h b/generic/arch.h index d64d03c3..9311464e 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -172,6 +172,7 @@ struct Arch : BaseCtx void unbindWire(WireId wire); bool checkWireAvail(WireId wire) const; NetInfo *getBoundWireNet(WireId wire) const; + WireId getConflictingWireWire(WireId wire) const { return wire; } NetInfo *getConflictingWireNet(WireId wire) const; DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); } const std::vector &getWires() const; @@ -186,8 +187,8 @@ struct Arch : BaseCtx void unbindPip(PipId pip); bool checkPipAvail(PipId pip) const; NetInfo *getBoundPipNet(PipId pip) const; - NetInfo *getConflictingPipNet(PipId pip) const; WireId getConflictingPipWire(PipId pip) const; + NetInfo *getConflictingPipNet(PipId pip) const; const std::vector &getPips() const; Loc getPipLocation(PipId pip) const; WireId getPipSrcWire(PipId pip) const; diff --git a/gui/designwidget.cc b/gui/designwidget.cc index 8eda8a76..8a134c1f 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -453,6 +453,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire)); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET); + addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->getWireName(ctx->getConflictingWireWire(wire)).c_str(ctx), + ElementType::WIRE); addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)), ElementType::NET); @@ -513,10 +515,10 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip)); 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, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)), + ElementType::NET); 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 46f2b348..2967ee1f 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -566,6 +566,11 @@ struct Arch : BaseCtx return wire_to_net[wire.index]; } + WireId getConflictingWireWire(WireId wire) const + { + return wire; + } + NetInfo *getConflictingWireNet(WireId wire) const { NPNR_ASSERT(wire != WireId()); @@ -642,28 +647,34 @@ struct Arch : BaseCtx refreshUiWire(dst); } - bool checkPipAvail(PipId pip) const + bool ice40_pip_hard_unavail(PipId pip) const { NPNR_ASSERT(pip != PipId()); auto &pi = chip_info->pip_data[pip.index]; auto &si = chip_info->bits_info->switches[pi.switch_index]; - if (switches_locked[pi.switch_index] != WireId()) - return false; - if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) { NPNR_ASSERT(si.bel >= 0); if (bel_to_cell[si.bel] != nullptr) - return false; + return true; } if (pi.flags & PipInfoPOD::FLAG_NOCARRY) { NPNR_ASSERT(si.bel >= 0); if (bel_carry[si.bel]) - return false; + return true; } - return true; + return false; + } + + bool checkPipAvail(PipId pip) const + { + if (ice40_pip_hard_unavail(pip)) + return false; + + auto &pi = chip_info->pip_data[pip.index]; + return switches_locked[pi.switch_index] == WireId(); } NetInfo *getBoundPipNet(PipId pip) const @@ -672,19 +683,23 @@ struct Arch : BaseCtx return pip_to_net[pip.index]; } - 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()); + if (ice40_pip_hard_unavail(pip)) + return WireId(); + return switches_locked[chip_info->pip_data[pip.index].switch_index]; } + NetInfo *getConflictingPipNet(PipId pip) const + { + if (ice40_pip_hard_unavail(pip)) + return nullptr; + + WireId wire = switches_locked[chip_info->pip_data[pip.index].switch_index]; + return wire == WireId() ? nullptr : wire_to_net[wire.index]; + } + AllPipRange getPips() const { AllPipRange range; From f9a512633840a88d8c846f1387681c62161ea6a7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Nov 2018 17:50:42 +0100 Subject: [PATCH 10/10] Another router1 bugfix Signed-off-by: Clifford Wolf --- common/router1.cc | 115 ++++++++++++++++++++++------------------------ common/router1.h | 3 +- 2 files changed, 55 insertions(+), 63 deletions(-) diff --git a/common/router1.cc b/common/router1.cc index 64f01c0d..ad2b6757 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -459,77 +459,72 @@ struct Router1 WireId conflictWireWire = WireId(), conflictPipWire = WireId(); NetInfo *conflictWireNet = nullptr, *conflictPipNet = nullptr; - bool wire_reuse = net_info->wires.count(next_wire); - bool pip_reuse = wire_reuse && net_info->wires.at(next_wire).pip == pip; - - if (!ctx->checkWireAvail(next_wire) && !wire_reuse) { - if (!ripup) - continue; - conflictWireWire = ctx->getConflictingWireWire(next_wire); - if (conflictWireWire == WireId()) { - conflictWireNet = ctx->getConflictingWireNet(next_wire); - if (conflictWireNet == nullptr) + if (net_info->wires.count(next_wire) && net_info->wires.at(next_wire).pip == pip) { + next_bonus += cfg.reuseBonus; + } else { + if (!ctx->checkWireAvail(next_wire)) { + if (!ripup) continue; + conflictWireWire = ctx->getConflictingWireWire(next_wire); + if (conflictWireWire == WireId()) { + conflictWireNet = ctx->getConflictingWireNet(next_wire); + if (conflictWireNet == nullptr) + continue; + } } - } - if (!ctx->checkPipAvail(pip) && !pip_reuse) { - if (!ripup) - continue; - conflictPipWire = ctx->getConflictingPipWire(pip); - if (conflictPipWire == WireId()) { - conflictPipNet = ctx->getConflictingPipNet(pip); - if (conflictPipNet == nullptr) + if (!ctx->checkPipAvail(pip)) { + if (!ripup) continue; + conflictPipWire = ctx->getConflictingPipWire(pip); + if (conflictPipWire == WireId()) { + conflictPipNet = ctx->getConflictingPipNet(pip); + if (conflictPipNet == nullptr) + continue; + } } - } - if (conflictWireNet != nullptr && conflictPipWire != WireId() && conflictWireNet->wires.count(conflictPipWire)) - conflictPipWire = WireId(); + if (conflictWireNet != nullptr && conflictPipWire != WireId() && conflictWireNet->wires.count(conflictPipWire)) + conflictPipWire = WireId(); - if (conflictPipNet != nullptr && conflictWireWire != WireId() && conflictPipNet->wires.count(conflictWireWire)) - conflictWireWire = WireId(); + if (conflictPipNet != nullptr && conflictWireWire != WireId() && conflictPipNet->wires.count(conflictWireWire)) + conflictWireWire = WireId(); - if (conflictWireWire == conflictPipWire) - conflictWireWire = WireId(); + if (conflictWireWire == conflictPipWire) + conflictWireWire = WireId(); - if (conflictWireNet == conflictPipNet) - conflictWireNet = nullptr; + if (conflictWireNet == conflictPipNet) + conflictWireNet = nullptr; - if (wire_reuse) - next_bonus += cfg.wireReuseBonus; + if (conflictWireWire != WireId()) { + auto scores_it = wireScores.find(conflictWireWire); + if (scores_it != wireScores.end()) + next_penalty += scores_it->second * cfg.wireRipupPenalty; + next_penalty += cfg.wireRipupPenalty; + } - if (pip_reuse) - next_bonus += cfg.pipReuseBonus; + if (conflictPipWire != WireId()) { + auto scores_it = wireScores.find(conflictPipWire); + if (scores_it != wireScores.end()) + next_penalty += scores_it->second * cfg.wireRipupPenalty; + next_penalty += cfg.wireRipupPenalty; + } - if (conflictWireWire != WireId()) { - auto scores_it = wireScores.find(conflictWireWire); - if (scores_it != wireScores.end()) - next_penalty += scores_it->second * cfg.wireRipupPenalty; - next_penalty += cfg.wireRipupPenalty; - } + if (conflictWireNet != nullptr) { + auto scores_it = netScores.find(conflictWireNet); + if (scores_it != netScores.end()) + next_penalty += scores_it->second * cfg.netRipupPenalty; + next_penalty += cfg.netRipupPenalty; + next_penalty += conflictWireNet->wires.size() * cfg.wireRipupPenalty; + } - if (conflictPipWire != WireId()) { - auto scores_it = wireScores.find(conflictPipWire); - if (scores_it != wireScores.end()) - next_penalty += scores_it->second * cfg.wireRipupPenalty; - next_penalty += cfg.wireRipupPenalty; - } - - if (conflictWireNet != nullptr) { - auto scores_it = netScores.find(conflictWireNet); - if (scores_it != netScores.end()) - next_penalty += scores_it->second * cfg.netRipupPenalty; - next_penalty += cfg.netRipupPenalty; - next_penalty += conflictWireNet->wires.size() * cfg.wireRipupPenalty; - } - - if (conflictPipNet != nullptr) { - auto scores_it = netScores.find(conflictPipNet); - if (scores_it != netScores.end()) - next_penalty += scores_it->second * cfg.netRipupPenalty; - next_penalty += cfg.netRipupPenalty; - next_penalty += conflictPipNet->wires.size() * cfg.wireRipupPenalty; + if (conflictPipNet != nullptr) { + auto scores_it = netScores.find(conflictPipNet); + if (scores_it != netScores.end()) + next_penalty += scores_it->second * cfg.netRipupPenalty; + next_penalty += cfg.netRipupPenalty; + next_penalty += conflictPipNet->wires.size() * cfg.wireRipupPenalty; + } } delay_t next_score = next_delay + next_penalty; @@ -676,9 +671,7 @@ Router1Cfg::Router1Cfg(Context *ctx) : Settings(ctx) wireRipupPenalty = ctx->getRipupDelayPenalty(); netRipupPenalty = 10*ctx->getRipupDelayPenalty(); - - wireReuseBonus = wireRipupPenalty/8; - pipReuseBonus = wireRipupPenalty/2; + reuseBonus = wireRipupPenalty/2; estimatePrecision = 100 * ctx->getRipupDelayPenalty(); } diff --git a/common/router1.h b/common/router1.h index d6113441..80d7aa96 100644 --- a/common/router1.h +++ b/common/router1.h @@ -35,8 +35,7 @@ struct Router1Cfg : Settings bool useEstimate; delay_t wireRipupPenalty; delay_t netRipupPenalty; - delay_t wireReuseBonus; - delay_t pipReuseBonus; + delay_t reuseBonus; delay_t estimatePrecision; };