diff options
Diffstat (limited to 'ecp5')
-rw-r--r-- | ecp5/arch.h | 26 | ||||
-rw-r--r-- | ecp5/arch_place.cc | 17 | ||||
-rw-r--r-- | ecp5/arch_pybindings.cc | 8 | ||||
-rw-r--r-- | ecp5/archdefs.h | 77 | ||||
-rw-r--r-- | ecp5/bitstream.cc | 7 | ||||
-rw-r--r-- | ecp5/cells.cc | 2 | ||||
-rw-r--r-- | ecp5/cells.h | 2 | ||||
-rw-r--r-- | ecp5/globals.cc | 26 | ||||
-rw-r--r-- | ecp5/lpf.cc | 5 | ||||
-rw-r--r-- | ecp5/main.cc | 8 | ||||
-rw-r--r-- | ecp5/pack.cc | 151 |
11 files changed, 120 insertions, 209 deletions
diff --git a/ecp5/arch.h b/ecp5/arch.h index 063a3df6..be1a44d8 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -419,23 +419,9 @@ struct DelayKey { return celltype == other.celltype && from == other.from && to == other.to; } + unsigned int hash() const { return mkhash(celltype.hash(), mkhash(from.hash(), to.hash())); } }; -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 ArchRanges : BaseArchRanges { using ArchArgsT = ArchArgs; @@ -458,15 +444,15 @@ struct Arch : BaseArch<ArchRanges> const PackageInfoPOD *package_info; const SpeedGradePOD *speed_grade; - mutable std::unordered_map<IdStringList, PipId> pip_by_name; + mutable dict<IdStringList, PipId> pip_by_name; std::vector<CellInfo *> bel_to_cell; - std::unordered_map<WireId, int> wire_fanout; + dict<WireId, int> wire_fanout; // fast access to X and Y IdStrings for building object names std::vector<IdString> x_ids, y_ids; // inverse of the above for name->object mapping - std::unordered_map<IdString, int> id_to_x, id_to_y; + dict<IdString, int> id_to_x, id_to_y; ArchArgs args; Arch(ArchArgs args); @@ -914,10 +900,10 @@ struct Arch : BaseArch<ArchRanges> // 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<WireId, std::pair<int, int>> wire_loc_overrides; + dict<WireId, std::pair<int, int>> wire_loc_overrides; void setup_wire_locations(); - mutable std::unordered_map<DelayKey, std::pair<bool, DelayQuad>> celldelay_cache; + mutable dict<DelayKey, std::pair<bool, DelayQuad>> celldelay_cache; static const std::string defaultPlacer; static const std::vector<std::string> availablePlacers; diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc index 57c3b181..a98d96ec 100644 --- a/ecp5/arch_place.cc +++ b/ecp5/arch_place.cc @@ -98,15 +98,6 @@ void Arch::permute_luts() TimingAnalyser tmg(getCtx()); tmg.setup(); - std::unordered_map<PortInfo *, size_t> port_to_user; - for (auto net : sorted(nets)) { - NetInfo *ni = net.second; - for (size_t i = 0; i < ni->users.size(); i++) { - auto &usr = ni->users.at(i); - port_to_user[&(usr.cell->ports.at(usr.port))] = i; - } - } - auto proc_lut = [&](CellInfo *ci, int lut) { std::vector<IdString> port_names; for (int i = 0; i < 4; i++) @@ -157,8 +148,8 @@ void Arch::permute_luts() ci->params[id("LUT" + std::to_string(lut) + "_INITVAL")] = Property(new_init, 16); }; - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_TRELLIS_SLICE && str_or_default(ci->params, id("MODE"), "LOGIC") == "LOGIC") { proc_lut(ci, 0); proc_lut(ci, 1); @@ -169,8 +160,8 @@ void Arch::permute_luts() void Arch::setup_wire_locations() { wire_loc_overrides.clear(); - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->bel == BelId()) continue; if (ci->type == id_MULT18X18D || ci->type == id_DCUA || ci->type == id_DDRDLL || ci->type == id_DQSBUFM || diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc index 5218ce36..35660afd 100644 --- a/ecp5/arch_pybindings.cc +++ b/ecp5/arch_pybindings.cc @@ -44,10 +44,10 @@ void arch_wrap_python(py::module &m) .def("place", &Context::place) .def("route", &Context::route); - typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap; - typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap; - typedef std::unordered_map<IdString, IdString> AliasMap; - typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap; + typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap; + typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap; + typedef dict<IdString, IdString> AliasMap; + typedef dict<IdString, HierarchicalCell> HierarchyMap; auto belpin_cls = py::class_<ContextualWrapper<BelPin>>(m, "BelPin"); readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel"); diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h index 2b4590e5..6243a9df 100644 --- a/ecp5/archdefs.h +++ b/ecp5/archdefs.h @@ -21,9 +21,8 @@ #ifndef ECP5_ARCHDEFS_H #define ECP5_ARCHDEFS_H -#include <boost/functional/hash.hpp> - #include "base_clusterinfo.h" +#include "hashlib.h" #include "idstring.h" #include "nextpnr_namespaces.h" @@ -63,6 +62,7 @@ struct Location bool operator==(const Location &other) const { return x == other.x && y == other.y; } bool operator!=(const Location &other) const { return x != other.x || y != other.y; } bool operator<(const Location &other) const { return y == other.y ? x < other.x : y < other.y; } + unsigned int hash() const { return mkhash(x, y); } }; inline Location operator+(const Location &a, const Location &b) { return Location(a.x + b.x, a.y + b.y); } @@ -78,6 +78,7 @@ struct BelId { return location == other.location ? index < other.index : location < other.location; } + unsigned int hash() const { return mkhash(location.hash(), index); } }; struct WireId @@ -91,6 +92,7 @@ struct WireId { return location == other.location ? index < other.index : location < other.location; } + unsigned int hash() const { return mkhash(location.hash(), index); } }; struct PipId @@ -104,6 +106,7 @@ struct PipId { return location == other.location ? index < other.index : location < other.location; } + unsigned int hash() const { return mkhash(location.hash(), index); } }; typedef IdString BelBucketId; @@ -119,6 +122,7 @@ struct GroupId bool operator==(const GroupId &other) const { return (type == other.type) && (location == other.location); } bool operator!=(const GroupId &other) const { return (type != other.type) || (location != other.location); } + unsigned int hash() const { return mkhash(location.hash(), int(type)); } }; struct DecalId @@ -142,6 +146,7 @@ struct DecalId { return type != other.type || location != other.location || z != other.z || active != other.active; } + unsigned int hash() const { return mkhash(location.hash(), mkhash(z, int(type))); } }; struct ArchNetInfo @@ -180,72 +185,4 @@ struct ArchCellInfo : BaseClusterInfo }; NEXTPNR_NAMESPACE_END - -namespace std { -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX Location> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX Location &loc) const noexcept - { - std::size_t seed = std::hash<int>()(loc.x); - seed ^= std::hash<int>()(loc.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelId &bel) const noexcept - { - std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(bel.location); - seed ^= std::hash<int>()(bel.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX WireId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX WireId &wire) const noexcept - { - std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(wire.location); - seed ^= std::hash<int>()(wire.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX PipId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX PipId &pip) const noexcept - { - std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(pip.location); - seed ^= std::hash<int>()(pip.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX GroupId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX GroupId &group) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(group.type)); - boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX Location>()(group.location)); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DecalId &decal) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(decal.type)); - boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX Location>()(decal.location)); - boost::hash_combine(seed, hash<int>()(decal.z)); - boost::hash_combine(seed, hash<bool>()(decal.active)); - return seed; - } -}; - -} // namespace std - #endif /* ECP5_ARCHDEFS_H */ diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index f8d11d39..ac9d4a4d 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -569,8 +569,7 @@ static std::vector<bool> parse_config_str(const Property &p, int length) return word; } -std::string intstr_or_default(const std::unordered_map<IdString, Property> &ct, const IdString &key, - std::string def = "0") +std::string intstr_or_default(const dict<IdString, Property> &ct, const IdString &key, std::string def = "0") { auto found = ct.find(key); if (found == ct.end()) @@ -670,8 +669,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex } } // Find bank voltages - std::unordered_map<int, IOVoltage> bankVcc; - std::unordered_map<int, bool> bankLvds, bankVref, bankDiff; + dict<int, IOVoltage> bankVcc; + dict<int, bool> bankLvds, bankVref, bankDiff; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); diff --git a/ecp5/cells.cc b/ecp5/cells.cc index 7f9f1579..edc80329 100644 --- a/ecp5/cells.cc +++ b/ecp5/cells.cc @@ -422,7 +422,7 @@ void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw } void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::unique_ptr<CellInfo>> &created_cells, - std::unordered_set<IdString> &todelete_cells) + pool<IdString> &todelete_cells) { if (nxio->type == ctx->id("$nextpnr_ibuf")) { trio->params[ctx->id("DIR")] = std::string("INPUT"); diff --git a/ecp5/cells.h b/ecp5/cells.h index e66f8f21..20ba97b4 100644 --- a/ecp5/cells.h +++ b/ecp5/cells.h @@ -65,7 +65,7 @@ void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw // Convert a nextpnr IO buffer to a TRELLIS_IO void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::unique_ptr<CellInfo>> &created_cells, - std::unordered_set<IdString> &todelete_cells); + pool<IdString> &todelete_cells); NEXTPNR_NAMESPACE_END diff --git a/ecp5/globals.cc b/ecp5/globals.cc index 36bec64c..b840ac91 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -72,7 +72,7 @@ class Ecp5GlobalRouter std::vector<NetInfo *> get_clocks() { - std::unordered_map<IdString, int> clockCount; + dict<IdString, int> clockCount; for (auto &net : ctx->nets) { NetInfo *ni = net.second.get(); if (ni->name == ctx->id("$PACKER_GND_NET") || ni->name == ctx->id("$PACKER_VCC_NET")) @@ -91,8 +91,8 @@ class Ecp5GlobalRouter } // DCCAs must always drive globals std::vector<NetInfo *> clocks; - for (auto &cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DCCA) { NetInfo *glb = ci->ports.at(id_CLKO).net; if (glb != nullptr) { @@ -147,7 +147,7 @@ class Ecp5GlobalRouter WireId globalWire; IdString global_name = ctx->id(fmt_str("G_HPBX" << std::setw(2) << std::setfill('0') << global_index << "00")); std::queue<WireId> upstream; - std::unordered_map<WireId, PipId> backtrace; + dict<WireId, PipId> backtrace; upstream.push(userWire); bool already_routed = false; WireId next; @@ -230,7 +230,7 @@ class Ecp5GlobalRouter bool simple_router(NetInfo *net, WireId src, WireId dst, bool allow_fail = false) { std::queue<WireId> visit; - std::unordered_map<WireId, PipId> backtrace; + dict<WireId, PipId> backtrace; visit.push(src); WireId cursor; while (true) { @@ -340,7 +340,7 @@ class Ecp5GlobalRouter bool has_short_route(WireId src, WireId dst, int thresh = 7) { std::queue<WireId> visit; - std::unordered_map<WireId, PipId> backtrace; + dict<WireId, PipId> backtrace; visit.push(src); WireId cursor; while (true) { @@ -376,7 +376,7 @@ class Ecp5GlobalRouter return length < thresh; } - std::unordered_set<WireId> used_pclkcib; + pool<WireId> used_pclkcib; std::set<WireId> get_candidate_pclkcibs(BelId dcc) { @@ -535,9 +535,9 @@ class Ecp5GlobalRouter fab_globals.insert(i); } std::vector<std::pair<PortRef *, int>> toroute; - std::unordered_map<int, NetInfo *> clocks; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + dict<int, NetInfo *> clocks; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DCCA) { NetInfo *clock = ci->ports.at(id_CLKO).net; NPNR_ASSERT(clock != nullptr); @@ -577,8 +577,8 @@ class Ecp5GlobalRouter void route_eclk_sources() { // Try and use dedicated paths if possible - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_ECLKSYNCB || ci->type == id_TRELLIS_ECLKBUF || ci->type == id_ECLKBRIDGECS) { std::vector<IdString> pins; if (ci->type == id_ECLKSYNCB || ci->type == id_TRELLIS_ECLKBUF) { @@ -595,7 +595,7 @@ class Ecp5GlobalRouter WireId src = ctx->getNetinfoSourceWire(ni); WireId dst = ctx->getBelPinWire(ci->bel, pin); std::queue<WireId> visit; - std::unordered_map<WireId, PipId> backtrace; + dict<WireId, PipId> backtrace; visit.push(dst); int iter = 0; WireId cursor; diff --git a/ecp5/lpf.cc b/ecp5/lpf.cc index 6d134e8d..39576fcb 100644 --- a/ecp5/lpf.cc +++ b/ecp5/lpf.cc @@ -19,7 +19,6 @@ #include <boost/algorithm/string.hpp> #include <sstream> -#include <unordered_set> #include "arch.h" #include "log.h" @@ -27,7 +26,7 @@ NEXTPNR_NAMESPACE_BEGIN -static const std::unordered_set<std::string> sysconfig_keys = { +static const pool<std::string> sysconfig_keys = { "SLAVE_SPI_PORT", "MASTER_SPI_PORT", "SLAVE_PARALLEL_PORT", "BACKGROUND_RECONFIG", "DONE_EX", "DONE_OD", "DONE_PULL", "MCCLK_FREQ", "TRANSFR", @@ -35,7 +34,7 @@ static const std::unordered_set<std::string> sysconfig_keys = { "COMPRESS_CONFIG", "CONFIG_MODE", "INBUF", }; -static const std::unordered_set<std::string> iobuf_keys = { +static const pool<std::string> iobuf_keys = { "IO_TYPE", "BANK", "BANK_VCC", "VREF", "PULLMODE", "DRIVE", "SLEWRATE", "CLAMP", "OPENDRAIN", "DIFFRESISTOR", "DIFFDRIVE", "HYSTERESIS", "TERMINATION", }; diff --git a/ecp5/main.cc b/ecp5/main.cc index 5d9fc965..711c4944 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -34,7 +34,7 @@ class ECP5CommandHandler : public CommandHandler public: ECP5CommandHandler(int argc, char **argv); virtual ~ECP5CommandHandler(){}; - std::unique_ptr<Context> createContext(std::unordered_map<std::string, Property> &values) override; + std::unique_ptr<Context> createContext(dict<std::string, Property> &values) override; void setupArchContext(Context *ctx) override{}; void customAfterLoad(Context *ctx) override; void validate() override; @@ -132,7 +132,7 @@ static std::string speedString(ArchArgs::SpeedGrade speed) return ""; } -std::unique_ptr<Context> ECP5CommandHandler::createContext(std::unordered_map<std::string, Property> &values) +std::unique_ptr<Context> ECP5CommandHandler::createContext(dict<std::string, Property> &values) { ArchArgs chipArgs; chipArgs.type = ArchArgs::NONE; @@ -270,8 +270,8 @@ void ECP5CommandHandler::customAfterLoad(Context *ctx) log_error("failed to parse LPF file '%s'\n", filename.c_str()); } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") || ci->type == ctx->id("$nextpnr_iobuf")) { if (!ci->attrs.count(ctx->id("LOC"))) { diff --git a/ecp5/pack.cc b/ecp5/pack.cc index bdf84bcf..19eda9e2 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -21,7 +21,6 @@ #include <boost/optional.hpp> #include <iterator> #include <queue> -#include <unordered_set> #include "cells.h" #include "chain_utils.h" #include "design_utils.h" @@ -106,8 +105,8 @@ class Ecp5Packer void find_lutff_pairs() { log_info("Finding LUTFF pairs...\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_lut(ctx, ci) || is_pfumx(ctx, ci) || is_l6mux(ctx, ci)) { NetInfo *znet = ci->ports.at(ctx->id("Z")).net; if (znet != nullptr) { @@ -261,9 +260,9 @@ class Ecp5Packer void pair_luts() { log_info("Finding LUT-LUT pairs...\n"); - std::unordered_set<IdString> procdLuts; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + pool<IdString> procdLuts; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_lut(ctx, ci) && procdLuts.find(cell.first) == procdLuts.end()) { NetInfo *znet = ci->ports.at(ctx->id("Z")).net; std::vector<NetInfo *> inpnets; @@ -392,8 +391,8 @@ class Ecp5Packer } if (ctx->debug) { log_info("Singleton LUTs (packer QoR debug): \n"); - for (auto cell : sorted(ctx->cells)) - if (is_lut(ctx, cell.second) && !procdLuts.count(cell.first)) + for (auto &cell : ctx->cells) + if (is_lut(ctx, cell.second.get()) && !procdLuts.count(cell.first)) log_info(" %s\n", cell.first.c_str(ctx)); } } @@ -443,8 +442,8 @@ class Ecp5Packer { log_info("Packing IOs..\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_nextpnr_iob(ctx, ci)) { CellInfo *trio = nullptr; NetInfo *ionet = nullptr; @@ -536,8 +535,8 @@ class Ecp5Packer void pack_lut5xs() { log_info("Packing LUT5-7s...\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_pfumx(ctx, ci)) { std::unique_ptr<CellInfo> packed = create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "_SLICE"); @@ -593,8 +592,8 @@ class Ecp5Packer } flush_cells(); // Pack LUT6s - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_l6mux(ctx, ci)) { NetInfo *ofx0_0 = ci->ports.at(ctx->id("D0")).net; if (ofx0_0 == nullptr) @@ -651,8 +650,8 @@ class Ecp5Packer } flush_cells(); // Pack LUT7s - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_l6mux(ctx, ci)) { NetInfo *ofx1_0 = ci->ports.at(ctx->id("D0")).net; if (ofx1_0 == nullptr) @@ -975,8 +974,8 @@ class Ecp5Packer // Pack distributed RAM void pack_dram() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_dpram(ctx, ci)) { // Create RAMW slice @@ -1108,8 +1107,8 @@ class Ecp5Packer void pack_remaining_luts() { log_info("Packing unpaired LUTs into a SLICE...\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_lut(ctx, ci)) { std::unique_ptr<CellInfo> slice = create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "_SLICE"); @@ -1134,7 +1133,7 @@ class Ecp5Packer // Used for packing an FF into a nearby SLICE template <typename TFunc> CellInfo *find_nearby_cell(CellInfo *origin, TFunc Func) { - std::unordered_set<CellInfo *> visited_cells; + pool<CellInfo *, hash_ptr_ops> visited_cells; std::queue<CellInfo *> to_visit; visited_cells.insert(origin); to_visit.push(origin); @@ -1181,8 +1180,8 @@ class Ecp5Packer ++used_slices; log_info("Packing unpaired FFs into a SLICE...\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_ff(ctx, ci)) { bool pack_dense = used_slices > (dense_pack_mode_thresh * available_slices); bool requires_m = get_net_or_empty(ci, ctx->id("M")) != nullptr; @@ -1403,8 +1402,8 @@ class Ecp5Packer bool gnd_used = false, vcc_used = false; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { IdString drv_cell = ni->driver.cell->name; set_net_constant(ctx, ni, gnd_net.get(), false); @@ -1461,8 +1460,8 @@ class Ecp5Packer c->params[n] = c->params[o]; c->params.erase(o); }; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Convert 36-bit PDP RAMs to regular 18-bit DP ones that match the Bel if (ci->type == ctx->id("PDPW16KD")) { ci->params[ctx->id("DATA_WIDTH_A")] = 36; // force PDP mode @@ -1503,8 +1502,8 @@ class Ecp5Packer ci->type = id_DP16KD; } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DP16KD) { // Add ports, even if disconnected, to ensure correct tie-offs for (int i = 0; i < 14; i++) { @@ -1544,8 +1543,8 @@ class Ecp5Packer // Pack DSPs void pack_dsps() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_MULT18X18D) { // Add ports, even if disconnected, to ensure correct tie-offs for (auto sig : {"CLK", "CE", "RST"}) @@ -1708,8 +1707,8 @@ class Ecp5Packer // "Pack" DCUs void pack_dcus() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DCUA) { if (ci->attrs.count(ctx->id("LOC"))) { std::string loc = ci->attrs.at(ctx->id("LOC")).as_string(); @@ -1759,8 +1758,8 @@ class Ecp5Packer } } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_EXTREFB) { const NetInfo *refo = net_or_nullptr(ci, id_REFCLKO); CellInfo *dcu = nullptr; @@ -1800,8 +1799,8 @@ class Ecp5Packer // Miscellaneous packer tasks void pack_misc() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_USRMCLK) { rename_port(ctx, ci, ctx->id("USRMCLKI"), id_PADDO); rename_port(ctx, ci, ctx->id("USRMCLKTS"), id_PADDT); @@ -1829,14 +1828,14 @@ class Ecp5Packer if (ctx->getBelType(bel) == id_EHXPLLL && ctx->checkBelAvail(bel)) available_plls.insert(bel); } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL"))) available_plls.erase(ctx->getBelByNameStr(ci->attrs.at(ctx->id("BEL")).as_string())); } // Place PLL connected to fixed drivers such as IO close to their source - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) { const NetInfo *drivernet = net_or_nullptr(ci, id_CLKI); if (drivernet == nullptr || drivernet->driver.cell == nullptr) @@ -1863,8 +1862,8 @@ class Ecp5Packer } } // Place PLLs driven by logic, etc, randomly - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) { if (available_plls.empty()) log_error("failed to place PLL '%s'\n", ci->name.c_str(ctx)); @@ -1971,7 +1970,7 @@ class Ecp5Packer IdString global_name = ctx->id("G_BANK" + std::to_string(bank) + "ECLK" + std::to_string(found_eclk)); std::queue<WireId> upstream; - std::unordered_map<WireId, PipId> backtrace; + dict<WireId, PipId> backtrace; upstream.push(userWire); WireId next; while (true) { @@ -2026,12 +2025,12 @@ class Ecp5Packer new_cells.push_back(std::move(zero_cell)); } - std::unordered_map<IdString, std::pair<bool, int>> dqsbuf_dqsg; + dict<IdString, std::pair<bool, int>> dqsbuf_dqsg; // Pack DQSBUFs void pack_dqsbuf() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DQSBUFM) { CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("DQSI")).net, is_trellis_io, id_O); if (pio == nullptr || ci->ports.at(ctx->id("DQSI")).net->users.size() > 1) @@ -2119,7 +2118,7 @@ class Ecp5Packer // Pack IOLOGIC void pack_iologic() { - std::unordered_map<IdString, CellInfo *> pio_iologic; + dict<IdString, CellInfo *> pio_iologic; auto set_iologic_sclk = [&](CellInfo *iol, CellInfo *prim, IdString port, bool input, bool disconnect = true) { NetInfo *sclk = nullptr; @@ -2265,8 +2264,8 @@ class Ecp5Packer } }; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == ctx->id("DELAYF") || ci->type == ctx->id("DELAYG")) { CellInfo *i_pio = net_driven_by(ctx, ci->ports.at(ctx->id("A")).net, is_trellis_io, id_O); CellInfo *o_pio = net_only_drives(ctx, ci->ports.at(ctx->id("Z")).net, is_trellis_io, id_I, true); @@ -2349,8 +2348,8 @@ class Ecp5Packer } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == ctx->id("IDDRX1F")) { CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("D")).net, is_trellis_io, id_O); if (pio == nullptr || ci->ports.at(ctx->id("D")).net->users.size() > 1) @@ -2692,8 +2691,8 @@ class Ecp5Packer } flush_cells(); // Constrain ECLK-related cells - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_ECLKBRIDGECS) { Loc loc; NetInfo *i0 = get_net_or_empty(ci, id_CLK0), *i1 = get_net_or_empty(ci, id_CLK1), @@ -2760,8 +2759,8 @@ class Ecp5Packer } } // Promote/route edge clocks - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) { if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr) continue; @@ -2779,9 +2778,9 @@ class Ecp5Packer } } flush_cells(); - std::unordered_set<BelId> used_eclksyncb; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + pool<BelId> used_eclksyncb; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_CLKDIVF) { const NetInfo *clki = net_or_nullptr(ci, id_CLKI); for (auto &eclk : eclks) { @@ -2896,8 +2895,8 @@ class Ecp5Packer } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_ECLKSYNCB) { // **All** ECLKSYNCBs must be constrained // Most will be dealt with above, but there might be some rogue cases @@ -2921,8 +2920,8 @@ class Ecp5Packer } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_CLKDIVF) { if (ci->attrs.count(ctx->id("BEL"))) continue; @@ -2967,7 +2966,7 @@ class Ecp5Packer auto equals_epsilon = [](delay_t a, delay_t b) { return (std::abs(a - b) / std::max(double(b), 1.0)) < 1e-3; }; - std::unordered_set<IdString> user_constrained, changed_nets; + pool<IdString> user_constrained, changed_nets; for (auto &net : ctx->nets) { if (net.second->clkconstr != nullptr) user_constrained.insert(net.first); @@ -3041,7 +3040,7 @@ class Ecp5Packer const int itermax = 5000; while (!changed_nets.empty() && iter < itermax) { ++iter; - std::unordered_set<IdString> changed_cells; + pool<IdString> changed_cells; for (auto net : changed_nets) { for (auto &user : ctx->nets.at(net)->users) if (user.port == id_CLKI || user.port == id_ECLKI || user.port == id_CLK0 || user.port == id_CLK1) @@ -3051,7 +3050,7 @@ class Ecp5Packer changed_cells.insert(drv.cell->name); } changed_nets.clear(); - for (auto cell : sorted(changed_cells)) { + for (auto cell : changed_cells) { CellInfo *ci = ctx->cells.at(cell).get(); if (ci->type == id_CLKDIVF) { std::string div = str_or_default(ci->params, ctx->id("DIV"), "2.0"); @@ -3114,8 +3113,8 @@ class Ecp5Packer { // Check for legacy-style JSON (use CEMUX as a clue) and error out, avoiding a confusing assertion failure // later - for (auto cell : sorted(ctx->cells)) { - if (is_ff(ctx, cell.second) && cell.second->params.count(ctx->id("CEMUX")) && + for (auto &cell : ctx->cells) { + if (is_ff(ctx, cell.second.get()) && cell.second->params.count(ctx->id("CEMUX")) && !cell.second->params[ctx->id("CEMUX")].is_string) log_error("Found netlist using legacy-style JSON parameter values, please update your Yosys.\n"); } @@ -3152,7 +3151,7 @@ class Ecp5Packer private: Context *ctx; - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; struct SliceUsage @@ -3163,10 +3162,10 @@ class Ecp5Packer bool mux5_used = false, muxx_used = false; }; - std::unordered_map<IdString, SliceUsage> sliceUsage; - std::unordered_map<IdString, IdString> lutffPairs; - std::unordered_map<IdString, IdString> fflutPairs; - std::unordered_map<IdString, IdString> lutPairs; + dict<IdString, SliceUsage> sliceUsage; + dict<IdString, IdString> lutffPairs; + dict<IdString, IdString> fflutPairs; + dict<IdString, IdString> lutPairs; }; // Main pack function bool Arch::pack() @@ -3188,8 +3187,8 @@ bool Arch::pack() void Arch::assignArchInfo() { - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_TRELLIS_SLICE) { ci->sliceInfo.using_dff = false; @@ -3301,7 +3300,7 @@ void Arch::assignArchInfo() ci->multInfo.is_clocked = ci->multInfo.timing_id != id_MULT18X18D_REGS_NONE; } } - for (auto net : sorted(nets)) { + for (auto &net : nets) { net.second->is_global = bool_or_default(net.second->attrs, id("ECP5_IS_GLOBAL")); } } |