From 36c07a0f45b13e4cf34e6db3b73ccf864af522f0 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 25 Oct 2019 09:37:13 +0100 Subject: [PATCH] ecp5: Fix routing to shared DSP control inputs Signed-off-by: David Shah --- ecp5/arch.cc | 9 ++++++++- ecp5/arch.h | 5 +++++ ecp5/arch_place.cc | 24 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 8ce0653c..5f62d5ae 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -477,7 +477,13 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const } }; - auto src_loc = est_location(src), dst_loc = est_location(dst); + auto src_loc = est_location(src); + std::pair dst_loc; + if (wire_loc_overrides.count(dst)) { + dst_loc = wire_loc_overrides.at(dst); + } else { + dst_loc = est_location(dst); + } int dx = abs(src_loc.first - dst_loc.first), dy = abs(src_loc.second - dst_loc.second); @@ -562,6 +568,7 @@ bool Arch::place() bool Arch::route() { + setupWireLocations(); route_ecp5_globals(getCtx()); assignArchInfo(); assign_budget(getCtx(), true); diff --git a/ecp5/arch.h b/ecp5/arch.h index a479abb6..444dfa07 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -1048,6 +1048,11 @@ struct Arch : BaseCtx // Special case for delay estimates due to its physical location // being far from the logical location of its primitive WireId gsrclk_wire; + // Improves directivity of routing to DSP inputs, avoids issues + // with different routes to the same physical reset wire causing + // conflicts and slow routing + std::unordered_map> wire_loc_overrides; + void setupWireLocations(); mutable std::unordered_map> celldelay_cache; diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc index d5c345af..6057605b 100644 --- a/ecp5/arch_place.cc +++ b/ecp5/arch_place.cc @@ -196,4 +196,28 @@ void Arch::permute_luts() } } +void Arch::setupWireLocations() +{ + wire_loc_overrides.clear(); + for (auto cell : sorted(cells)) { + CellInfo *ci = cell.second; + if (ci->bel == BelId()) + continue; + if (ci->type == id_MULT18X18D || ci->type == id_DCUA) { + for (auto &port : ci->ports) { + if (port.second.type != PORT_IN || port.second.net == nullptr) + continue; + WireId pw = getBelPinWire(ci->bel, port.first); + if (pw == WireId()) + continue; + for (auto uh : getPipsUphill(pw)) { + WireId pip_src = getPipSrcWire(uh); + wire_loc_overrides[pw] = std::make_pair(pip_src.location.x, pip_src.location.y); + break; + } + } + } + } +} + NEXTPNR_NAMESPACE_END