diff options
Diffstat (limited to 'ecp5')
-rw-r--r-- | ecp5/arch.cc | 45 | ||||
-rw-r--r-- | ecp5/arch.h | 29 | ||||
-rw-r--r-- | ecp5/arch_pybindings.cc | 7 | ||||
-rw-r--r-- | ecp5/main.cc | 4 |
4 files changed, 77 insertions, 8 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc index da0f7b1a..9da8abdf 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -28,6 +28,7 @@ #include "log.h" #include "nextpnr.h" #include "placer1.h" +#include "placer_heap.h" #include "router1.h" #include "timing.h" #include "util.h" @@ -456,6 +457,7 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const auto src_loc = est_location(src), dst_loc = est_location(dst); int dx = abs(src_loc.first - dst_loc.first), dy = abs(src_loc.second - dst_loc.second); + return (130 - 25 * args.speed) * (6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); } @@ -467,7 +469,6 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const return 0; auto driver_loc = getBelLocation(driver.cell->bel); auto sink_loc = getBelLocation(sink.cell->bel); - // Encourage use of direct interconnect if (driver_loc.x == sink_loc.x && driver_loc.y == sink_loc.y) { if ((sink.port == id_A0 || sink.port == id_A1) && (driver.port == id_F1) && @@ -485,6 +486,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const } int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y); + return (130 - 25 * args.speed) * (6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5))); } @@ -506,10 +508,23 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay bool Arch::place() { - bool result = placer1(getCtx(), Placer1Cfg(getCtx())); - if (result) - permute_luts(); - return result; + std::string placer = str_or_default(settings, id("placer"), defaultPlacer); + + if (placer == "heap") { + PlacerHeapCfg cfg(getCtx()); + cfg.criticalityExponent = 7; + cfg.ioBufTypes.insert(id_TRELLIS_IO); + if (!placer_heap(getCtx(), cfg)) + return false; + } else if (placer == "sa") { + if (!placer1(getCtx(), Placer1Cfg(getCtx()))) + return false; + } else { + log_error("ECP5 architecture does not support placer '%s'\n", placer.c_str()); + } + + permute_luts(); + return true; } bool Arch::route() @@ -605,6 +620,11 @@ DecalXY Arch::getGroupDecal(GroupId pip) const { return {}; }; bool Arch::getDelayFromTimingDatabase(IdString tctype, IdString from, IdString to, DelayInfo &delay) const { + auto fnd_dk = celldelay_cache.find({tctype, from, to}); + if (fnd_dk != celldelay_cache.end()) { + delay = fnd_dk->second.second; + return fnd_dk->second.first; + } for (int i = 0; i < speed_grade->num_cell_timings; i++) { const auto &tc = speed_grade->cell_timings[i]; if (tc.cell_type == tctype.index) { @@ -613,9 +633,11 @@ bool Arch::getDelayFromTimingDatabase(IdString tctype, IdString from, IdString t if (dly.from_port == from.index && dly.to_port == to.index) { delay.max_delay = dly.max_delay; delay.min_delay = dly.min_delay; + celldelay_cache[{tctype, from, to}] = std::make_pair(true, delay); return true; } } + celldelay_cache[{tctype, from, to}] = std::make_pair(false, DelayInfo()); return false; } } @@ -645,7 +667,6 @@ void Arch::getSetupHoldFromTimingDatabase(IdString tctype, IdString clock, IdStr bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const { - // Data for -8 grade if (cell->type == id_TRELLIS_SLICE) { bool has_carry = cell->sliceInfo.is_carry; @@ -965,4 +986,16 @@ WireId Arch::getBankECLK(int bank, int eclk) return getWireByLocAndBasename(Location(0, 0), "G_BANK" + std::to_string(bank) + "ECLK" + std::to_string(eclk)); } +#ifdef WITH_HEAP +const std::string Arch::defaultPlacer = "heap"; +#else +const std::string Arch::defaultPlacer = "sa"; +#endif + +const std::vector<std::string> Arch::availablePlacers = {"sa", +#ifdef WITH_HEAP + "heap" +#endif +}; + NEXTPNR_NAMESPACE_END diff --git a/ecp5/arch.h b/ecp5/arch.h index ab4a4e00..3de06a42 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -448,6 +448,30 @@ struct ArchArgs } speed = SPEED_6; }; +struct DelayKey +{ + IdString celltype, from, to; + inline bool operator==(const DelayKey &other) const + { + return celltype == other.celltype && from == other.from && to == other.to; + } +}; + +NEXTPNR_NAMESPACE_END +namespace std { +template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DelayKey> +{ + std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DelayKey &dk) const noexcept + { + std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.celltype); + seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.from) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.to) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } +}; +} // namespace std +NEXTPNR_NAMESPACE_BEGIN + struct Arch : BaseCtx { const ChipInfoPOD *chip_info; @@ -1019,6 +1043,11 @@ struct Arch : BaseCtx IdString id_clk, id_lsr; IdString id_clkmux, id_lsrmux; IdString id_srmode, id_mode; + + mutable std::unordered_map<DelayKey, std::pair<bool, DelayInfo>> celldelay_cache; + + static const std::string defaultPlacer; + static const std::vector<std::string> availablePlacers; }; NEXTPNR_NAMESPACE_END diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc index 5e73a673..18d21112 100644 --- a/ecp5/arch_pybindings.cc +++ b/ecp5/arch_pybindings.cc @@ -133,6 +133,13 @@ void arch_wrap_python() fn_wrapper_2a_v<Context, decltype(&Context::addClock), &Context::addClock, conv_from_str<IdString>, pass_through<float>>::def_wrap(ctx_cls, "addClock"); + fn_wrapper_5a_v<Context, decltype(&Context::createRectangularRegion), &Context::createRectangularRegion, + conv_from_str<IdString>, pass_through<int>, pass_through<int>, pass_through<int>, + pass_through<int>>::def_wrap(ctx_cls, "createRectangularRegion"); + fn_wrapper_2a_v<Context, decltype(&Context::addBelToRegion), &Context::addBelToRegion, conv_from_str<IdString>, + conv_from_str<BelId>>::def_wrap(ctx_cls, "addBelToRegion"); + fn_wrapper_2a_v<Context, decltype(&Context::constrainCellToRegion), &Context::constrainCellToRegion, + conv_from_str<IdString>, conv_from_str<IdString>>::def_wrap(ctx_cls, "constrainCellToRegion"); WRAP_RANGE(Bel, conv_to_str<BelId>); WRAP_RANGE(Wire, conv_to_str<WireId>); diff --git a/ecp5/main.cc b/ecp5/main.cc index 15027a5a..bb18aa58 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -149,8 +149,8 @@ std::unique_ptr<Context> ECP5CommandHandler::createContext() chipArgs.speed = ArchArgs::SPEED_6; } } - - return std::unique_ptr<Context>(new Context(chipArgs)); + auto ctx = std::unique_ptr<Context>(new Context(chipArgs)); + return ctx; } void ECP5CommandHandler::customAfterLoad(Context *ctx) |