aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/arch.cc45
-rw-r--r--ecp5/arch.h29
-rw-r--r--ecp5/arch_pybindings.cc7
-rw-r--r--ecp5/main.cc4
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)