diff options
author | gatecat <gatecat@ds0.me> | 2021-06-02 10:01:36 +0100 |
---|---|---|
committer | gatecat <gatecat@ds0.me> | 2021-06-02 15:05:19 +0100 |
commit | ecc19c2c083f7e3ed7da95557731ded803d2cb1d (patch) | |
tree | 864780d38cb9a49b6846a0045ac93e1b4dfcc88d | |
parent | f4fed62c05a9595e22a8ec54add5531225911741 (diff) | |
download | nextpnr-ecc19c2c083f7e3ed7da95557731ded803d2cb1d.tar.gz nextpnr-ecc19c2c083f7e3ed7da95557731ded803d2cb1d.tar.bz2 nextpnr-ecc19c2c083f7e3ed7da95557731ded803d2cb1d.zip |
Using hashlib in arches
Signed-off-by: gatecat <gatecat@ds0.me>
66 files changed, 358 insertions, 549 deletions
diff --git a/common/base_arch.h b/common/base_arch.h index fbafee99..c7d9f380 100644 --- a/common/base_arch.h +++ b/common/base_arch.h @@ -441,23 +441,23 @@ template <typename R> struct BaseArch : ArchAPI<R> // -------------------------------------------------------------- // These structures are used to provide default implementations of bel/wire/pip binding. Arches might want to - // replace them with their own, for example to use faster access structures than unordered_map. Arches might also + // replace them with their own, for example to use faster access structures than dict. Arches might also // want to add extra checks around these functions - std::unordered_map<BelId, CellInfo *> base_bel2cell; - std::unordered_map<WireId, NetInfo *> base_wire2net; - std::unordered_map<PipId, NetInfo *> base_pip2net; + dict<BelId, CellInfo *> base_bel2cell; + dict<WireId, NetInfo *> base_wire2net; + dict<PipId, NetInfo *> base_pip2net; // For the default cell/bel bucket implementations std::vector<IdString> cell_types; std::vector<BelBucketId> bel_buckets; - std::unordered_map<BelBucketId, std::vector<BelId>> bucket_bels; + dict<BelBucketId, std::vector<BelId>> bucket_bels; // Arches that want to use the default cell types and bel buckets *must* call these functions in their constructor bool cell_types_initialised = false; bool bel_buckets_initialised = false; void init_cell_types() { - std::unordered_set<IdString> bel_types; + pool<IdString> bel_types; for (auto bel : this->getBels()) bel_types.insert(this->getBelType(bel)); std::copy(bel_types.begin(), bel_types.end(), std::back_inserter(cell_types)); diff --git a/common/hashlib.h b/common/hashlib.h index 30fefc65..063df78f 100644 --- a/common/hashlib.h +++ b/common/hashlib.h @@ -74,6 +74,15 @@ template <> struct hash_ops<int64_t> : hash_int_ops static inline unsigned int hash(int64_t a) { return mkhash((unsigned int)(a), (unsigned int)(a >> 32)); } }; +template <> struct hash_ops<uint32_t> : hash_int_ops +{ + static inline unsigned int hash(uint32_t a) { return a; } +}; +template <> struct hash_ops<uint64_t> : hash_int_ops +{ + static inline unsigned int hash(uint64_t a) { return mkhash((unsigned int)(a), (unsigned int)(a >> 32)); } +}; + template <> struct hash_ops<std::string> { static inline bool cmp(const std::string &a, const std::string &b) { return a == b; } 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/bitstream.cc b/ecp5/bitstream.cc index c8349f88..ac9d4a4d 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -669,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 1e86fe6b..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")) @@ -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,7 +535,7 @@ class Ecp5GlobalRouter fab_globals.insert(i); } std::vector<std::pair<PortRef *, int>> toroute; - std::unordered_map<int, NetInfo *> clocks; + dict<int, NetInfo *> clocks; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); if (ci->type == id_DCCA) { @@ -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/pack.cc b/ecp5/pack.cc index db5d22a1..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" @@ -261,7 +260,7 @@ class Ecp5Packer void pair_luts() { log_info("Finding LUT-LUT pairs...\n"); - std::unordered_set<IdString> procdLuts; + pool<IdString> procdLuts; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); if (is_lut(ctx, ci) && procdLuts.find(cell.first) == procdLuts.end()) { @@ -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); @@ -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,7 +2025,7 @@ 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() { @@ -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; @@ -2779,7 +2778,7 @@ class Ecp5Packer } } flush_cells(); - std::unordered_set<BelId> used_eclksyncb; + pool<BelId> used_eclksyncb; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); if (ci->type == id_CLKDIVF) { @@ -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"); @@ -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() diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index 663587fd..8e7fe2a3 100644 --- a/fpga_interchange/arch.cc +++ b/fpga_interchange/arch.cc @@ -63,21 +63,8 @@ struct SiteBelPair SiteBelPair(std::string site, IdString bel) : site(site), bel(bel) {} bool operator==(const SiteBelPair &other) const { return site == other.site && bel == other.bel; } + unsigned int hash() const { return mkhash(std::hash<std::string>()(site), bel.hash()); } }; -NEXTPNR_NAMESPACE_END - -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX SiteBelPair> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX SiteBelPair &site_bel) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<std::string>()(site_bel.site)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(site_bel.bel)); - return seed; - } -}; - -NEXTPNR_NAMESPACE_BEGIN static std::pair<std::string, std::string> split_identifier_name_dot(const std::string &name) { @@ -180,7 +167,7 @@ Arch::Arch(ArchArgs args) : args(args), disallow_site_routing(false) } } - std::unordered_set<SiteBelPair> site_bel_pads; + pool<SiteBelPair> site_bel_pads; for (const auto &package_pin : chip_info->packages[package_index].pins) { IdString site(package_pin.site); IdString bel(package_pin.bel); @@ -1951,7 +1938,7 @@ void Arch::unmask_bel_pins() void Arch::remove_site_routing() { - HashTables::HashSet<WireId> wires_to_unbind; + pool<WireId> wires_to_unbind; for (auto &net_pair : nets) { for (auto &wire_pair : net_pair.second->wires) { WireId wire = wire_pair.first; diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index 5c7bbc52..c8a61430 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -103,14 +103,14 @@ struct Arch : ArchAPI<ArchRanges> // Guard initialization of "by_name" maps if accessed from multiple // threads on a "const Context *". mutable std::mutex by_name_mutex; - mutable std::unordered_map<IdString, int> tile_by_name; - mutable std::unordered_map<IdString, std::pair<int, int>> site_by_name; + mutable dict<IdString, int> tile_by_name; + mutable dict<IdString, std::pair<int, int>> site_by_name; - std::unordered_map<WireId, NetInfo *> wire_to_net; - std::unordered_map<PipId, NetInfo *> pip_to_net; + dict<WireId, NetInfo *> wire_to_net; + dict<PipId, NetInfo *> pip_to_net; DedicatedInterconnect dedicated_interconnect; - HashTables::HashMap<int32_t, TileStatus> tileStatus; + dict<int32_t, TileStatus> tileStatus; PseudoPipData pseudo_pip_data; ArchArgs args; @@ -685,8 +685,8 @@ struct Arch : ArchAPI<ArchRanges> // ------------------------------------------------- - void place_iobufs(WireId pad_wire, NetInfo *net, const std::unordered_set<CellInfo *> &tightly_attached_bels, - std::unordered_set<CellInfo *> *placed_cells); + void place_iobufs(WireId pad_wire, NetInfo *net, const pool<CellInfo *, hash_ptr_ops> &tightly_attached_bels, + pool<CellInfo *, hash_ptr_ops> *placed_cells); void pack_ports(); void decode_lut_cells(); @@ -858,7 +858,7 @@ struct Arch : ArchAPI<ArchRanges> IdString get_bel_tiletype(BelId bel) const { return IdString(loc_info(chip_info, bel).name); } - std::unordered_map<WireId, Loc> sink_locs, source_locs; + dict<WireId, Loc> sink_locs, source_locs; // ------------------------------------------------- void assignArchInfo() final {} @@ -875,8 +875,8 @@ struct Arch : ArchAPI<ArchRanges> void write_physical_netlist(const std::string &filename) const; void parse_xdc(const std::string &filename); - std::unordered_set<IdString> io_port_types; - std::unordered_set<BelId> pads; + pool<IdString> io_port_types; + pool<BelId> pads; bool is_site_port(PipId pip) const { @@ -1083,7 +1083,7 @@ struct Arch : ArchAPI<ArchRanges> IdString gnd_cell_pin; IdString vcc_cell_pin; std::vector<std::vector<LutElement>> lut_elements; - std::unordered_map<IdString, const LutCellPOD *> lut_cells; + dict<IdString, const LutCellPOD *> lut_cells; // Of the LUT cells, which is used for wires? // Note: May be null in arch's without wire LUT types. Assumption is diff --git a/fpga_interchange/arch_pack_io.cc b/fpga_interchange/arch_pack_io.cc index 9322d028..fdbb1130 100644 --- a/fpga_interchange/arch_pack_io.cc +++ b/fpga_interchange/arch_pack_io.cc @@ -24,8 +24,8 @@ NEXTPNR_NAMESPACE_BEGIN -void Arch::place_iobufs(WireId pad_wire, NetInfo *net, const std::unordered_set<CellInfo *> &tightly_attached_bels, - std::unordered_set<CellInfo *> *placed_cells) +void Arch::place_iobufs(WireId pad_wire, NetInfo *net, const pool<CellInfo *, hash_ptr_ops> &tightly_attached_bels, + pool<CellInfo *, hash_ptr_ops> *placed_cells) { for (BelPin bel_pin : getWireBelPins(pad_wire)) { BelId bel = bel_pin.bel; @@ -57,7 +57,7 @@ void Arch::place_iobufs(WireId pad_wire, NetInfo *net, const std::unordered_set< void Arch::pack_ports() { - std::unordered_map<IdString, const TileInstInfoPOD *> tile_type_prototypes; + dict<IdString, const TileInstInfoPOD *> tile_type_prototypes; for (size_t i = 0; i < chip_info->tiles.size(); ++i) { const auto &tile = chip_info->tiles[i]; const auto &tile_type = chip_info->tile_types[tile.type]; @@ -66,9 +66,9 @@ void Arch::pack_ports() } // set(site_types) for package pins - std::unordered_set<IdString> package_sites; + pool<IdString> package_sites; // Package pin -> (Site type -> BelId) - std::unordered_map<IdString, std::vector<std::pair<IdString, BelId>>> package_pin_bels; + dict<IdString, std::vector<std::pair<IdString, BelId>>> package_pin_bels; for (const PackagePinPOD &package_pin : chip_info->packages[package_index].pins) { IdString pin(package_pin.package_pin); IdString bel(package_pin.bel); @@ -78,7 +78,7 @@ void Arch::pack_ports() for (size_t i = 0; i < chip_info->tiles.size(); ++i) { const auto &tile = chip_info->tiles[i]; - std::unordered_set<uint32_t> package_pin_sites; + pool<uint32_t> package_pin_sites; for (size_t j = 0; j < tile.sites.size(); ++j) { auto &site_data = chip_info->sites[tile.sites[j]]; if (site == id(site_data.site_name.get())) { @@ -102,8 +102,8 @@ void Arch::pack_ports() } // Determine for each package site type, which site types are possible. - std::unordered_set<IdString> package_pin_site_types; - std::unordered_map<IdString, std::unordered_set<IdString>> possible_package_site_types; + pool<IdString> package_pin_site_types; + dict<IdString, pool<IdString>> possible_package_site_types; for (const TileInstInfoPOD &tile : chip_info->tiles) { for (size_t site_index : tile.sites) { const SiteInstInfoPOD &site = chip_info->sites[site_index]; @@ -121,7 +121,7 @@ void Arch::pack_ports() for (auto port_pair : port_cells) { IdString port_name = port_pair.first; CellInfo *port_cell = port_pair.second; - std::unordered_set<CellInfo *> tightly_attached_bels; + pool<CellInfo *, hash_ptr_ops> tightly_attached_bels; for (auto port_pair : port_cell->ports) { const PortInfo &port_info = port_pair.second; @@ -145,7 +145,7 @@ void Arch::pack_ports() } NPNR_ASSERT(tightly_attached_bels.erase(port_cell) == 1); - std::unordered_set<IdString> cell_types_in_io_group; + pool<IdString> cell_types_in_io_group; for (CellInfo *cell : tightly_attached_bels) { NPNR_ASSERT(port_cells.find(cell->name) == port_cells.end()); cell_types_in_io_group.emplace(cell->type); @@ -153,7 +153,7 @@ void Arch::pack_ports() // Get possible placement locations for tightly coupled BELs with // port. - std::unordered_set<IdString> possible_site_types; + pool<IdString> possible_site_types; for (const TileTypeInfoPOD &tile_type : chip_info->tile_types) { IdString tile_type_name(tile_type.name); for (const BelInfoPOD &bel_info : tile_type.bel_data) { @@ -195,7 +195,7 @@ void Arch::pack_ports() } } - // std::unordered_map<IdString, std::unordered_map<IdString, BelId>> package_pin_bels; + // dict<IdString, dict<IdString, BelId>> package_pin_bels; IdString package_pin_id = id(iter->second.as_string()); auto pin_iter = package_pin_bels.find(package_pin_id); if (pin_iter == package_pin_bels.end()) { @@ -233,7 +233,7 @@ void Arch::pack_ports() log_info("Binding port %s to BEL %s\n", port_name.c_str(getCtx()), getCtx()->nameOfBel(package_bel)); } - std::unordered_set<CellInfo *> placed_cells; + pool<CellInfo *, hash_ptr_ops> placed_cells; bindBel(package_bel, port_cell, STRENGTH_FIXED); placed_cells.emplace(port_cell); diff --git a/fpga_interchange/archdefs.h b/fpga_interchange/archdefs.h index ba4fe054..2d27cccf 100644 --- a/fpga_interchange/archdefs.h +++ b/fpga_interchange/archdefs.h @@ -24,7 +24,6 @@ #include <boost/functional/hash.hpp> #include <cstdint> -#include "hash_table.h" #include "hashlib.h" #include "luts.h" #include "nextpnr_namespaces.h" @@ -119,9 +118,9 @@ struct ArchNetInfo struct ArchCellInfo { int32_t cell_mapping = -1; - HashTables::HashMap<IdString, std::vector<IdString>> cell_bel_pins; - HashTables::HashMap<IdString, std::vector<IdString>> masked_cell_bel_pins; - HashTables::HashSet<IdString> const_ports; + dict<IdString, std::vector<IdString>> cell_bel_pins; + dict<IdString, std::vector<IdString>> masked_cell_bel_pins; + pool<IdString> const_ports; LutCell lut_cell; }; diff --git a/fpga_interchange/cell_parameters.h b/fpga_interchange/cell_parameters.h index de82e76b..d6d4ccec 100644 --- a/fpga_interchange/cell_parameters.h +++ b/fpga_interchange/cell_parameters.h @@ -25,7 +25,6 @@ #include "chipdb.h" #include "dynamic_bitarray.h" -#include "hash_table.h" #include "nextpnr_namespaces.h" #include "property.h" @@ -42,7 +41,7 @@ struct CellParameters bool compare_property(const Context *ctx, IdString cell_type, IdString parameter, const Property &property, IdString value_to_compare) const; - HashTables::HashMap<std::pair<IdString, IdString>, const CellParameterPOD *, PairHash> parameters; + dict<std::pair<IdString, IdString>, const CellParameterPOD *> parameters; std::regex verilog_binary_re; std::regex verilog_hex_re; diff --git a/fpga_interchange/cost_map.cc b/fpga_interchange/cost_map.cc index 868fdca0..c20ba11b 100644 --- a/fpga_interchange/cost_map.cc +++ b/fpga_interchange/cost_map.cc @@ -121,7 +121,7 @@ delay_t CostMap::get_delay(const Context *ctx, WireId src_wire, WireId dst_wire) } void CostMap::set_cost_map(const Context *ctx, const TypeWirePair &wire_pair, - const HashTables::HashMap<std::pair<int32_t, int32_t>, delay_t, PairHash> &delays) + const dict<std::pair<int32_t, int32_t>, delay_t> &delays) { CostMapEntry delay_matrix; diff --git a/fpga_interchange/cost_map.h b/fpga_interchange/cost_map.h index 810d0198..88fb97e4 100644 --- a/fpga_interchange/cost_map.h +++ b/fpga_interchange/cost_map.h @@ -24,7 +24,6 @@ #include <boost/multi_array.hpp> #include <mutex> -#include "hash_table.h" #include "lookahead.capnp.h" #include "nextpnr_namespaces.h" #include "nextpnr_types.h" @@ -39,7 +38,7 @@ class CostMap public: delay_t get_delay(const Context *ctx, WireId src, WireId dst) const; void set_cost_map(const Context *ctx, const TypeWirePair &wire_pair, - const HashTables::HashMap<std::pair<int32_t, int32_t>, delay_t, PairHash> &delays); + const dict<std::pair<int32_t, int32_t>, delay_t> &delays); void from_reader(lookahead_storage::CostMap::Reader reader); void to_builder(lookahead_storage::CostMap::Builder builder) const; @@ -53,7 +52,7 @@ class CostMap }; std::mutex cost_map_mutex_; - HashTables::HashMap<TypeWirePair, CostMapEntry> cost_map_; + dict<TypeWirePair, CostMapEntry> cost_map_; void fill_holes(const Context *ctx, const TypeWirePair &wire_pair, boost::multi_array<delay_t, 2> &matrix, delay_t delay_penality); diff --git a/fpga_interchange/dedicated_interconnect.cc b/fpga_interchange/dedicated_interconnect.cc index 9f7e83ab..2f6fbcd3 100644 --- a/fpga_interchange/dedicated_interconnect.cc +++ b/fpga_interchange/dedicated_interconnect.cc @@ -496,7 +496,7 @@ void DedicatedInterconnect::find_dedicated_interconnect() } } - std::unordered_set<TileTypeBelPin> seen_pins; + pool<TileTypeBelPin> seen_pins; for (auto sink_pair : sinks) { for (auto src : sink_pair.second) { seen_pins.emplace(src.type_bel_pin); @@ -558,7 +558,7 @@ void DedicatedInterconnect::expand_sink_bel(BelId sink_bel, IdString sink_pin, W nodes_to_expand.push_back(wire_node); Loc sink_loc = ctx->getBelLocation(sink_bel); - std::unordered_set<DeltaTileTypeBelPin> srcs; + pool<DeltaTileTypeBelPin> srcs; while (!nodes_to_expand.empty()) { WireNode node_to_expand = nodes_to_expand.back(); @@ -701,7 +701,7 @@ void DedicatedInterconnect::expand_source_bel(BelId src_bel, IdString src_pin, W nodes_to_expand.push_back(wire_node); Loc src_loc = ctx->getBelLocation(src_bel); - std::unordered_set<DeltaTileTypeBelPin> dsts; + pool<DeltaTileTypeBelPin> dsts; while (!nodes_to_expand.empty()) { WireNode node_to_expand = nodes_to_expand.back(); diff --git a/fpga_interchange/dedicated_interconnect.h b/fpga_interchange/dedicated_interconnect.h index 9ddb05fd..085ced26 100644 --- a/fpga_interchange/dedicated_interconnect.h +++ b/fpga_interchange/dedicated_interconnect.h @@ -23,9 +23,9 @@ #include <boost/functional/hash.hpp> #include <cstdint> -#include <unordered_map> #include "archdefs.h" +#include "hashlib.h" #include "idstring.h" #include "nextpnr_namespaces.h" @@ -58,6 +58,7 @@ struct TileTypeBelPin { return tile_type != other.tile_type || bel_index != other.bel_index || bel_pin != other.bel_pin; } + unsigned int hash() const { return mkhash(mkhash(tile_type, bel_index), bel_pin.hash()); } }; struct DeltaTileTypeBelPin @@ -74,36 +75,9 @@ struct DeltaTileTypeBelPin { return delta_x != other.delta_x || delta_y != other.delta_y || type_bel_pin != other.type_bel_pin; } + unsigned int hash() const { return mkhash(mkhash(delta_x, delta_y), type_bel_pin.hash()); } }; -NEXTPNR_NAMESPACE_END - -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX TileTypeBelPin> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX TileTypeBelPin &type_bel_pin) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<int32_t>()(type_bel_pin.tile_type)); - boost::hash_combine(seed, std::hash<int32_t>()(type_bel_pin.bel_index)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(type_bel_pin.bel_pin)); - return seed; - } -}; - -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX DeltaTileTypeBelPin> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DeltaTileTypeBelPin &delta_bel_pin) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<int32_t>()(delta_bel_pin.delta_x)); - boost::hash_combine(seed, std::hash<int32_t>()(delta_bel_pin.delta_y)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX TileTypeBelPin>()(delta_bel_pin.type_bel_pin)); - return seed; - } -}; - -NEXTPNR_NAMESPACE_BEGIN - struct Context; // This class models dedicated interconnect present in the given fabric. @@ -123,8 +97,8 @@ struct DedicatedInterconnect { const Context *ctx; - std::unordered_map<TileTypeBelPin, std::unordered_set<DeltaTileTypeBelPin>> sinks; - std::unordered_map<TileTypeBelPin, std::unordered_set<DeltaTileTypeBelPin>> sources; + dict<TileTypeBelPin, pool<DeltaTileTypeBelPin>> sinks; + dict<TileTypeBelPin, pool<DeltaTileTypeBelPin>> sources; void init(const Context *ctx); diff --git a/fpga_interchange/fpga_interchange.cpp b/fpga_interchange/fpga_interchange.cpp index cf89ef1c..1d08b128 100644 --- a/fpga_interchange/fpga_interchange.cpp +++ b/fpga_interchange/fpga_interchange.cpp @@ -43,7 +43,7 @@ static void write_message(::capnp::MallocMessageBuilder & message, const std::st struct StringEnumerator { std::vector<std::string> strings; - std::unordered_map<std::string, size_t> string_to_index; + dict<std::string, size_t> string_to_index; size_t get_index(const std::string &s) { auto result = string_to_index.emplace(s, strings.size()); @@ -59,7 +59,7 @@ struct StringEnumerator { static PhysicalNetlist::PhysNetlist::RouteBranch::Builder emit_branch( const Context * ctx, StringEnumerator * strings, - const std::unordered_map<PipId, PlaceStrength> &pip_place_strength, + const dict<PipId, PlaceStrength> &pip_place_strength, PipId pip, PhysicalNetlist::PhysNetlist::RouteBranch::Builder branch) { if(ctx->is_pip_synthetic(pip)) { @@ -264,10 +264,10 @@ static void init_bel_pin( static void emit_net( const Context * ctx, StringEnumerator * strings, - const std::unordered_map<WireId, std::vector<PipId>> &pip_downhill, - const std::unordered_map<WireId, std::vector<BelPin>> &sinks, - std::unordered_set<PipId> *pips, - const std::unordered_map<PipId, PlaceStrength> &pip_place_strength, + const dict<WireId, std::vector<PipId>> &pip_downhill, + const dict<WireId, std::vector<BelPin>> &sinks, + pool<PipId> *pips, + const dict<PipId, PlaceStrength> &pip_place_strength, WireId wire, PhysicalNetlist::PhysNetlist::RouteBranch::Builder branch) { size_t number_branches = 0; @@ -349,7 +349,7 @@ static PhysicalNetlist::PhysNetlist::RouteBranch::Builder init_local_source( StringEnumerator * strings, PhysicalNetlist::PhysNetlist::RouteBranch::Builder source_branch, PipId root, - const std::unordered_map<PipId, PlaceStrength> &pip_place_strength, + const dict<PipId, PlaceStrength> &pip_place_strength, WireId *root_wire) { WireId source_wire = ctx->getPipSrcWire(root); BelPin source_bel_pin = find_source(ctx, source_wire); @@ -365,7 +365,7 @@ static PhysicalNetlist::PhysNetlist::RouteBranch::Builder init_local_source( } static void find_non_synthetic_edges(const Context * ctx, WireId root_wire, - const std::unordered_map<WireId, std::vector<PipId>> &pip_downhill, + const dict<WireId, std::vector<PipId>> &pip_downhill, std::vector<PipId> *root_pips) { std::vector<WireId> wires_to_expand; @@ -403,7 +403,7 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str phys_netlist.setPart(ctx->get_part()); - std::unordered_set<IdString> placed_cells; + pool<IdString> placed_cells; for(const auto & cell_pair : ctx->cells) { const CellInfo & cell = *cell_pair.second; if(cell.bel == BelId()) { @@ -444,7 +444,7 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str std::vector<IdString> ports; - std::unordered_map<std::string, std::string> sites; + dict<std::string, std::string> sites; auto placements = phys_netlist.initPlacements(number_placements); auto placement_iter = placements.begin(); @@ -556,9 +556,9 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str net_out.setName(strings.get_index(net.name.str(ctx))); } - std::unordered_map<WireId, BelPin> root_wires; - std::unordered_map<WireId, std::vector<PipId>> pip_downhill; - std::unordered_set<PipId> pips; + dict<WireId, BelPin> root_wires; + dict<WireId, std::vector<PipId>> pip_downhill; + pool<PipId> pips; if (driver_cell != nullptr && driver_cell->bel != BelId() && ctx->isBelLocationValid(driver_cell->bel)) { for(IdString bel_pin_name : driver_cell->cell_bel_pins.at(net.driver.port)) { @@ -573,7 +573,7 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str } } - std::unordered_map<WireId, std::vector<BelPin>> sinks; + dict<WireId, std::vector<BelPin>> sinks; for(const auto &port_ref : net.users) { if(port_ref.cell != nullptr && port_ref.cell->bel != BelId() && ctx->isBelLocationValid(port_ref.cell->bel)) { auto pin_iter = port_ref.cell->cell_bel_pins.find(port_ref.port); @@ -598,7 +598,7 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str } } - std::unordered_map<PipId, PlaceStrength> pip_place_strength; + dict<PipId, PlaceStrength> pip_place_strength; for(auto &wire_pair : net.wires) { WireId downhill_wire = wire_pair.first; @@ -723,23 +723,11 @@ struct PortKey { bool operator == (const PortKey &other) const { return inst_idx == other.inst_idx && port_idx == other.port_idx; } -}; - -NEXTPNR_NAMESPACE_END - -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX PortKey> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX PortKey &key) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<int32_t>()(key.inst_idx)); - boost::hash_combine(seed, std::hash<uint32_t>()(key.port_idx)); - return seed; + unsigned int hash() const { + return mkhash(inst_idx, port_idx); } }; -NEXTPNR_NAMESPACE_BEGIN - struct ModuleReader { const LogicalNetlistImpl *root; @@ -748,9 +736,9 @@ struct ModuleReader { LogicalNetlist::Netlist::Cell::Reader cell; LogicalNetlist::Netlist::CellDeclaration::Reader cell_decl; - std::unordered_map<int32_t, LogicalNetlist::Netlist::Net::Reader> net_indicies; - std::unordered_map<int32_t, std::string> disconnected_nets; - std::unordered_map<PortKey, std::vector<int32_t>> connections; + dict<int32_t, LogicalNetlist::Netlist::Net::Reader> net_indicies; + dict<int32_t, std::string> disconnected_nets; + dict<PortKey, std::vector<int32_t>> connections; ModuleReader(const LogicalNetlistImpl *root, LogicalNetlist::Netlist::CellInstance::Reader cell_inst, bool is_top); @@ -834,7 +822,6 @@ struct LogicalNetlistImpl template <typename TFunc> void foreach_netname(const ModuleReader &mod, TFunc Func) const { - // std::unordered_map<int32_t, LogicalNetlist::Netlist::Net::Reader> net_indicies; for(auto net_pair : mod.net_indicies) { NetReader net_reader(&mod, net_pair.first); auto net = net_pair.second; @@ -842,7 +829,6 @@ struct LogicalNetlistImpl Func(strings.at(net.getName()), net_reader); } - // std::unordered_map<int32_t, IdString> disconnected_nets; for(auto net_pair : mod.disconnected_nets) { NetReader net_reader(&mod, net_pair.first); Func(net_pair.second, net_reader); diff --git a/fpga_interchange/globals.cc b/fpga_interchange/globals.cc index 918b916e..ed9f73a6 100644 --- a/fpga_interchange/globals.cc +++ b/fpga_interchange/globals.cc @@ -67,7 +67,7 @@ static int route_global_arc(Context *ctx, NetInfo *net, size_t usr_idx, size_t p WireId startpoint; GlobalVist best_visit; std::queue<WireId> visit_queue; - std::unordered_map<WireId, GlobalVist> visits; + dict<WireId, GlobalVist> visits; visit_queue.push(dest); visits[dest].downhill = PipId(); diff --git a/fpga_interchange/lookahead.cc b/fpga_interchange/lookahead.cc index 6dc8c43a..f1cb13e1 100644 --- a/fpga_interchange/lookahead.cc +++ b/fpga_interchange/lookahead.cc @@ -64,9 +64,9 @@ struct PipAndCost int32_t depth; }; -static void expand_input(const Context *ctx, WireId input_wire, HashTables::HashMap<TypeWireId, delay_t> *input_costs) +static void expand_input(const Context *ctx, WireId input_wire, dict<TypeWireId, delay_t> *input_costs) { - HashTables::HashSet<WireId> seen; + pool<WireId> seen; std::priority_queue<RoutingNode> to_expand; RoutingNode initial; @@ -120,9 +120,8 @@ static void expand_input(const Context *ctx, WireId input_wire, HashTables::Hash } } -static void update_site_to_site_costs(const Context *ctx, WireId first_wire, - const HashTables::HashMap<WireId, PipAndCost> &best_path, - HashTables::HashMap<TypeWirePair, delay_t> *site_to_site_cost) +static void update_site_to_site_costs(const Context *ctx, WireId first_wire, const dict<WireId, PipAndCost> &best_path, + dict<TypeWirePair, delay_t> *site_to_site_cost) { for (auto &best_pair : best_path) { WireId last_wire = best_pair.first; @@ -161,9 +160,9 @@ static void update_site_to_site_costs(const Context *ctx, WireId first_wire, } static void expand_output(const Context *ctx, WireId output_wire, Lookahead::OutputSiteWireCost *output_cost, - HashTables::HashMap<TypeWirePair, delay_t> *site_to_site_cost) + dict<TypeWirePair, delay_t> *site_to_site_cost) { - HashTables::HashSet<WireId> seen; + pool<WireId> seen; std::priority_queue<RoutingNode> to_expand; RoutingNode initial; @@ -172,7 +171,7 @@ static void expand_output(const Context *ctx, WireId output_wire, Lookahead::Out to_expand.push(initial); - HashTables::HashMap<WireId, PipAndCost> best_path; + dict<WireId, PipAndCost> best_path; while (!to_expand.empty()) { RoutingNode node = to_expand.top(); @@ -228,7 +227,7 @@ static void expand_output(const Context *ctx, WireId output_wire, Lookahead::Out static void expand_input_type(const Context *ctx, DeterministicRNG *rng, const Sampler &tiles_of_type, TypeWireId input_wire, std::vector<Lookahead::InputSiteWireCost> *input_costs) { - HashTables::HashMap<TypeWireId, delay_t> input_costs_map; + dict<TypeWireId, delay_t> input_costs_map; for (size_t region = 0; region < tiles_of_type.number_of_regions(); ++region) { size_t tile = tiles_of_type.get_sample_from_region(region, [rng]() -> int32_t { return rng->rng(); }); @@ -250,7 +249,7 @@ static void expand_input_type(const Context *ctx, DeterministicRNG *rng, const S struct DelayStorage { - HashTables::HashMap<TypeWirePair, HashTables::HashMap<std::pair<int32_t, int32_t>, delay_t, PairHash>> storage; + dict<TypeWirePair, dict<std::pair<int32_t, int32_t>, delay_t>> storage; int32_t max_explore_depth; }; @@ -290,7 +289,7 @@ static void update_results(const Context *ctx, const FlatWireMap<PipAndCost> &be // Starting from end of result, walk backwards and record the path into // the delay storage. WireId cursor = sink_wire; - HashTables::HashSet<WireId> seen; + pool<WireId> seen; while (cursor != src_wire) { // No loops allowed in routing! auto result = seen.emplace(cursor); @@ -335,7 +334,7 @@ static void update_results(const Context *ctx, const FlatWireMap<PipAndCost> &be static void expand_routing_graph_from_wire(const Context *ctx, WireId first_wire, FlatWireMap<PipAndCost> *best_path, DelayStorage *storage) { - HashTables::HashSet<WireId> seen; + pool<WireId> seen; std::priority_queue<RoutingNode> to_expand; int src_tile; @@ -436,11 +435,10 @@ static bool has_multiple_outputs(const Context *ctx, WireId wire) } static void expand_routing_graph(const Context *ctx, DeterministicRNG *rng, const Sampler &tiles_of_type, - TypeWireId wire_type, HashTables::HashSet<TypeWireSet> *types_explored, - DelayStorage *storage, HashTables::HashSet<TypeWireId> *types_deferred, - FlatWireMap<PipAndCost> *best_path) + TypeWireId wire_type, pool<TypeWireSet> *types_explored, DelayStorage *storage, + pool<TypeWireId> *types_deferred, FlatWireMap<PipAndCost> *best_path) { - HashTables::HashSet<TypeWireSet> new_types_explored; + pool<TypeWireSet> new_types_explored; for (size_t region = 0; region < tiles_of_type.number_of_regions(); ++region) { size_t tile = tiles_of_type.get_sample_from_region(region, [rng]() -> int32_t { return rng->rng(); }); @@ -562,10 +560,10 @@ static WireId follow_pip_chain_up(const Context *ctx, WireId wire, delay_t *dela } static void expand_deferred_routing_graph(const Context *ctx, DeterministicRNG *rng, const Sampler &tiles_of_type, - TypeWireId wire_type, HashTables::HashSet<TypeWireSet> *types_explored, + TypeWireId wire_type, pool<TypeWireSet> *types_explored, DelayStorage *storage, FlatWireMap<PipAndCost> *best_path) { - HashTables::HashSet<TypeWireSet> new_types_explored; + pool<TypeWireSet> new_types_explored; for (size_t region = 0; region < tiles_of_type.number_of_regions(); ++region) { size_t tile = tiles_of_type.get_sample_from_region(region, [rng]() -> int32_t { return rng->rng(); }); @@ -603,7 +601,7 @@ static void expand_deferred_routing_graph(const Context *ctx, DeterministicRNG * static void expand_output_type(const Context *ctx, DeterministicRNG *rng, const Sampler &tiles_of_type, TypeWireId output_wire, Lookahead::OutputSiteWireCost *output_cost, - HashTables::HashMap<TypeWirePair, delay_t> *site_to_site_cost) + dict<TypeWirePair, delay_t> *site_to_site_cost) { for (size_t region = 0; region < tiles_of_type.number_of_regions(); ++region) { size_t tile = tiles_of_type.get_sample_from_region(region, [rng]() -> int32_t { return rng->rng(); }); @@ -651,8 +649,8 @@ struct ExpandLocals DeterministicRNG *rng; FlatWireMap<PipAndCost> *best_path; DelayStorage *storage; - HashTables::HashSet<TypeWireSet> *explored; - HashTables::HashSet<TypeWireId> *deferred; + pool<TypeWireSet> *explored; + pool<TypeWireId> *deferred; virtual void lock() {} virtual void unlock() {} @@ -698,8 +696,7 @@ static void expand_tile_type(const Context *ctx, int32_t tile_type, ExpandLocals static void expand_tile_type_serial(const Context *ctx, const std::vector<int32_t> &tile_types, const std::vector<Sampler> &tiles_of_type, DeterministicRNG *rng, FlatWireMap<PipAndCost> *best_path, DelayStorage *storage, - HashTables::HashSet<TypeWireSet> *explored, - HashTables::HashSet<TypeWireId> *deferred, HashTables::HashSet<int32_t> *tiles_left) + pool<TypeWireSet> *explored, pool<TypeWireId> *deferred, pool<int32_t> *tiles_left) { for (int32_t tile_type : tile_types) { @@ -725,9 +722,9 @@ struct TbbExpandLocals : public ExpandLocals std::mutex *all_costs_mutex; DelayStorage *all_tiles_storage; - HashTables::HashSet<TypeWireSet> *types_explored; - HashTables::HashSet<TypeWireId> *types_deferred; - HashTables::HashSet<int32_t> *tiles_left; + pool<TypeWireSet> *types_explored; + pool<TypeWireId> *types_deferred; + pool<int32_t> *tiles_left; void lock() override { all_costs_mutex->lock(); } @@ -785,16 +782,15 @@ struct TbbExpandLocals : public ExpandLocals // the data is joined with the global data. static void expand_tile_type_parallel(const Context *ctx, int32_t tile_type, const std::vector<Sampler> &tiles_of_type, DeterministicRNG *rng, std::mutex *all_costs_mutex, - DelayStorage *all_tiles_storage, HashTables::HashSet<TypeWireSet> *types_explored, - HashTables::HashSet<TypeWireId> *types_deferred, - HashTables::HashSet<int32_t> *tiles_left) + DelayStorage *all_tiles_storage, pool<TypeWireSet> *types_explored, + pool<TypeWireId> *types_deferred, pool<int32_t> *tiles_left) { TbbExpandLocals locals; DeterministicRNG rng_copy = *rng; FlatWireMap<PipAndCost> best_path(ctx); - HashTables::HashSet<TypeWireSet> explored; - HashTables::HashSet<TypeWireId> deferred; + pool<TypeWireSet> explored; + pool<TypeWireId> deferred; DelayStorage storage; storage.max_explore_depth = all_tiles_storage->max_explore_depth; @@ -823,7 +819,7 @@ void Lookahead::build_lookahead(const Context *ctx, DeterministicRNG *rng) log_info("Building lookahead, first gathering input and output site wires\n"); } - HashTables::HashSet<TypeWireId> input_site_ports; + pool<TypeWireId> input_site_ports; for (BelId bel : ctx->getBels()) { const auto &bel_data = bel_info(ctx->chip_info, bel); @@ -917,15 +913,15 @@ void Lookahead::build_lookahead(const Context *ctx, DeterministicRNG *rng) all_tiles_storage.max_explore_depth = kInitialExploreDepth; // These are wire types that have been explored. - HashTables::HashSet<TypeWireSet> types_explored; + pool<TypeWireSet> types_explored; // These are wire types that have been deferred because they are trival // copies of another wire type. These can be cheaply computed after the // graph has been explored. - HashTables::HashSet<TypeWireId> types_deferred; + pool<TypeWireId> types_deferred; std::vector<int32_t> tile_types; - HashTables::HashSet<int32_t> tiles_left; + pool<int32_t> tiles_left; tile_types.reserve(ctx->chip_info->tile_types.size()); for (int32_t tile_type = 0; tile_type < ctx->chip_info->tile_types.ssize(); ++tile_type) { tile_types.push_back(tile_type); @@ -994,16 +990,14 @@ void Lookahead::build_lookahead(const Context *ctx, DeterministicRNG *rng) } #if defined(NEXTPNR_USE_TBB) // Run parallely - tbb::parallel_for_each( - all_tiles_storage.storage, - [&](const std::pair<TypeWirePair, HashTables::HashMap<std::pair<int32_t, int32_t>, delay_t, PairHash>> - &type_pair) { + tbb::parallel_for_each(all_tiles_storage.storage, + [&](const std::pair<TypeWirePair, dict<std::pair<int32_t, int32_t>, delay_t>> &type_pair) { #else for (const auto &type_pair : all_tiles_storage.storage) { #endif - cost_map.set_cost_map(ctx, type_pair.first, type_pair.second); + cost_map.set_cost_map(ctx, type_pair.first, type_pair.second); #if defined(NEXTPNR_USE_TBB) // Run parallely - }); + }); #else } #endif diff --git a/fpga_interchange/lookahead.h b/fpga_interchange/lookahead.h index b9d352d5..9655e13e 100644 --- a/fpga_interchange/lookahead.h +++ b/fpga_interchange/lookahead.h @@ -26,7 +26,6 @@ #include "cost_map.h" #include "deterministic_rng.h" -#include "hash_table.h" #include "lookahead.capnp.h" #include "nextpnr_namespaces.h" #include "type_wire.h" @@ -88,9 +87,9 @@ struct Lookahead delay_t cost; }; - HashTables::HashMap<TypeWireId, std::vector<InputSiteWireCost>> input_site_wires; - HashTables::HashMap<TypeWireId, OutputSiteWireCost> output_site_wires; - HashTables::HashMap<TypeWirePair, delay_t> site_to_site_cost; + dict<TypeWireId, std::vector<InputSiteWireCost>> input_site_wires; + dict<TypeWireId, OutputSiteWireCost> output_site_wires; + dict<TypeWirePair, delay_t> site_to_site_cost; CostMap cost_map; }; diff --git a/fpga_interchange/luts.cc b/fpga_interchange/luts.cc index 882cc474..0156d379 100644 --- a/fpga_interchange/luts.cc +++ b/fpga_interchange/luts.cc @@ -166,13 +166,13 @@ uint32_t LutMapper::check_wires(const Context *ctx) const } } - HashTables::HashSet<const LutBel *> blocked_luts; + pool<const LutBel *, hash_ptr_ops> blocked_luts; return check_wires(bel_to_cell_pin_remaps, lut_bels, used_pins, &blocked_luts); } uint32_t LutMapper::check_wires(const std::vector<std::vector<int32_t>> &bel_to_cell_pin_remaps, const std::vector<const LutBel *> &lut_bels, uint32_t used_pins, - HashTables::HashSet<const LutBel *> *blocked_luts) const + pool<const LutBel *, hash_ptr_ops> *blocked_luts) const { std::vector<const LutBel *> unused_luts; for (auto &lut_bel_pair : element.lut_bels) { @@ -253,9 +253,9 @@ uint32_t LutMapper::check_wires(const std::vector<std::vector<int32_t>> &bel_to_ return vcc_mask; } -bool LutMapper::remap_luts(const Context *ctx, HashTables::HashSet<const LutBel *> *blocked_luts) +bool LutMapper::remap_luts(const Context *ctx, pool<const LutBel *, hash_ptr_ops> *blocked_luts) { - std::unordered_map<NetInfo *, LutPin> lut_pin_map; + dict<NetInfo *, LutPin, hash_ptr_ops> lut_pin_map; std::vector<const LutBel *> lut_bels; lut_bels.resize(cells.size()); @@ -366,7 +366,7 @@ bool LutMapper::remap_luts(const Context *ctx, HashTables::HashSet<const LutBel CellInfo *cell = cells[cell_idx]; auto &lut_bel = *lut_bels[cell_idx]; - std::unordered_map<IdString, IdString> cell_to_bel_map; + dict<IdString, IdString> cell_to_bel_map; for (size_t pin_idx = 0; pin_idx < cell->lut_cell.pins.size(); ++pin_idx) { size_t bel_pin_idx = cell_to_bel_pin_remaps[cell_idx][pin_idx]; NPNR_ASSERT(bel_pin_idx < lut_bel.pins.size()); @@ -452,8 +452,8 @@ bool LutMapper::remap_luts(const Context *ctx, HashTables::HashSet<const LutBel return true; } -void check_equation(const LutCell &lut_cell, const std::unordered_map<IdString, IdString> &cell_to_bel_map, - const LutBel &lut_bel, const std::vector<LogicLevel> &equation, uint32_t used_pins) +void check_equation(const LutCell &lut_cell, const dict<IdString, IdString> &cell_to_bel_map, const LutBel &lut_bel, + const std::vector<LogicLevel> &equation, uint32_t used_pins) { std::vector<int8_t> pin_map; pin_map.resize(lut_bel.pins.size(), -1); diff --git a/fpga_interchange/luts.h b/fpga_interchange/luts.h index df0ac124..cbb817c9 100644 --- a/fpga_interchange/luts.h +++ b/fpga_interchange/luts.h @@ -20,14 +20,11 @@ #ifndef LUTS_H #define LUTS_H -#include <unordered_map> -#include <unordered_set> - #include "idstring.h" #include "nextpnr_namespaces.h" #include "dynamic_bitarray.h" -#include "hash_table.h" +#include "hashlib.h" NEXTPNR_NAMESPACE_BEGIN @@ -45,8 +42,8 @@ struct LutCell { // LUT cell pins for equation, LSB first. std::vector<IdString> pins; - std::unordered_set<IdString> lut_pins; - std::unordered_set<IdString> vcc_pins; + pool<IdString> lut_pins; + pool<IdString> vcc_pins; DynamicBitarray<> equation; }; @@ -56,7 +53,7 @@ struct LutBel // LUT BEL pins to LUT array index. std::vector<IdString> pins; - std::unordered_map<IdString, size_t> pin_to_index; + dict<IdString, size_t> pin_to_index; IdString output_pin; @@ -71,18 +68,18 @@ struct LutBel // Work forward from cell definition and cell -> bel pin map and check that // equation is valid. -void check_equation(const LutCell &lut_cell, const std::unordered_map<IdString, IdString> &cell_to_bel_map, - const LutBel &lut_bel, const std::vector<LogicLevel> &equation, uint32_t used_pins); +void check_equation(const LutCell &lut_cell, const dict<IdString, IdString> &cell_to_bel_map, const LutBel &lut_bel, + const std::vector<LogicLevel> &equation, uint32_t used_pins); struct LutElement { size_t width; - std::unordered_map<IdString, LutBel> lut_bels; + dict<IdString, LutBel> lut_bels; void compute_pin_order(); std::vector<IdString> pins; - std::unordered_map<IdString, size_t> pin_to_index; + dict<IdString, size_t> pin_to_index; }; struct LutMapper @@ -92,7 +89,7 @@ struct LutMapper std::vector<CellInfo *> cells; - bool remap_luts(const Context *ctx, HashTables::HashSet<const LutBel *> *blocked_luts); + bool remap_luts(const Context *ctx, pool<const LutBel *, hash_ptr_ops> *blocked_luts); // Determine which wires given the current mapping must be tied to the // default constant. @@ -101,7 +98,7 @@ struct LutMapper // the pin is free to be a signal. uint32_t check_wires(const std::vector<std::vector<int32_t>> &bel_to_cell_pin_remaps, const std::vector<const LutBel *> &lut_bels, uint32_t used_pins, - HashTables::HashSet<const LutBel *> *blocked_luts) const; + pool<const LutBel *, hash_ptr_ops> *blocked_luts) const; // Version of check_wires that uses current state of cells based on pin // mapping in cells variable. diff --git a/fpga_interchange/pseudo_pip_model.cc b/fpga_interchange/pseudo_pip_model.cc index 64da4548..2441c8a9 100644 --- a/fpga_interchange/pseudo_pip_model.cc +++ b/fpga_interchange/pseudo_pip_model.cc @@ -44,7 +44,7 @@ void PseudoPipData::init_tile_type(const Context *ctx, int32_t tile_type) max_pseudo_pip_index = pip_idx; } - HashTables::HashSet<size_t> sites; + pool<size_t> sites; std::vector<PseudoPipBel> pseudo_pip_bels; for (int32_t wire_index : pip_data.pseudo_cell_wires) { const TileWireInfoPOD &wire_data = type_data.wire_data[wire_index]; @@ -122,7 +122,7 @@ void PseudoPipData::init_tile_type(const Context *ctx, int32_t tile_type) } if (!pseudo_pip_bels.empty()) { - HashTables::HashSet<int32_t> pseudo_cell_wires; + pool<int32_t> pseudo_cell_wires; pseudo_cell_wires.insert(pip_data.pseudo_cell_wires.begin(), pip_data.pseudo_cell_wires.end()); // For each BEL, find the input bel pin used, and attach it to @@ -195,7 +195,7 @@ void PseudoPipModel::prepare_for_routing(const Context *ctx, const std::vector<S { // First determine which sites have placed cells, these sites are consider // active. - HashTables::HashSet<size_t> active_sites; + pool<size_t> active_sites; for (size_t site = 0; site < sites.size(); ++site) { if (!sites[site].cells_in_site.empty()) { active_sites.emplace(site); @@ -309,7 +309,7 @@ void PseudoPipModel::update_site(const Context *ctx, size_t site) unused_pseudo_pips.clear(); unused_pseudo_pips.reserve(pseudo_pips_for_site.size()); - HashTables::HashMap<int32_t, PseudoPipBel> used_bels; + dict<int32_t, PseudoPipBel> used_bels; for (int32_t pseudo_pip : pseudo_pips_for_site) { if (!active_pseudo_pips.count(pseudo_pip)) { unused_pseudo_pips.push_back(pseudo_pip); diff --git a/fpga_interchange/pseudo_pip_model.h b/fpga_interchange/pseudo_pip_model.h index 1e79071d..b0e28059 100644 --- a/fpga_interchange/pseudo_pip_model.h +++ b/fpga_interchange/pseudo_pip_model.h @@ -24,7 +24,6 @@ #include <tuple> #include "dynamic_bitarray.h" -#include "hash_table.h" #include "nextpnr_namespaces.h" #include "nextpnr_types.h" #include "site_router.h" @@ -58,28 +57,10 @@ struct LogicBelKey bool operator==(const LogicBelKey &other) const { return make_tuple() == other.make_tuple(); } bool operator<(const LogicBelKey &other) const { return make_tuple() < other.make_tuple(); } -}; - -NEXTPNR_NAMESPACE_END -namespace std { -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX LogicBelKey> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX LogicBelKey &key) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int32_t>()(key.tile_type)); - boost::hash_combine(seed, hash<int32_t>()(key.pip_index)); - boost::hash_combine(seed, hash<int32_t>()(key.site)); - - return seed; - } + unsigned int hash() const { return mkhash(mkhash(tile_type, pip_index), site); } }; -}; // namespace std - -NEXTPNR_NAMESPACE_BEGIN - // Storage for tile type generic pseudo pip data and lookup. struct PseudoPipData { @@ -97,9 +78,9 @@ struct PseudoPipData // This does **not** include site ports or site pips. const std::vector<PseudoPipBel> &get_logic_bels_for_pip(const Context *ctx, int32_t site, PipId pip) const; - HashTables::HashMap<int32_t, size_t> max_pseudo_pip_for_tile_type; - HashTables::HashMap<std::pair<int32_t, int32_t>, std::vector<size_t>, PairHash> possibles_sites_for_pip; - HashTables::HashMap<LogicBelKey, std::vector<PseudoPipBel>> logic_bels_for_pip; + dict<int32_t, size_t> max_pseudo_pip_for_tile_type; + dict<std::pair<int32_t, int32_t>, std::vector<size_t>> possibles_sites_for_pip; + dict<LogicBelKey, std::vector<PseudoPipBel>> logic_bels_for_pip; }; // Tile instance fast pseudo pip lookup. @@ -107,9 +88,9 @@ struct PseudoPipModel { int32_t tile; DynamicBitarray<> allowed_pseudo_pips; - HashTables::HashMap<int32_t, size_t> pseudo_pip_sites; - HashTables::HashMap<size_t, std::vector<int32_t>> site_to_pseudo_pips; - HashTables::HashSet<int32_t> active_pseudo_pips; + dict<int32_t, size_t> pseudo_pip_sites; + dict<size_t, std::vector<int32_t>> site_to_pseudo_pips; + pool<int32_t> active_pseudo_pips; std::vector<int32_t> scratch; // Call when a tile is initialized. diff --git a/fpga_interchange/site_arch.cc b/fpga_interchange/site_arch.cc index ed2f6c8d..6398d858 100644 --- a/fpga_interchange/site_arch.cc +++ b/fpga_interchange/site_arch.cc @@ -24,7 +24,7 @@ NEXTPNR_NAMESPACE_BEGIN SiteInformation::SiteInformation(const Context *ctx, int32_t tile, int32_t site, - const std::unordered_set<CellInfo *> &cells_in_site) + const pool<CellInfo *, hash_ptr_ops> &cells_in_site) : ctx(ctx), tile(tile), tile_type(ctx->chip_info->tiles[tile].type), site(site), cells_in_site(cells_in_site) { } diff --git a/fpga_interchange/site_arch.h b/fpga_interchange/site_arch.h index a7da5c68..54b91a4a 100644 --- a/fpga_interchange/site_arch.h +++ b/fpga_interchange/site_arch.h @@ -22,13 +22,12 @@ #define SITE_ARCH_H #include <cstdint> -#include <unordered_set> #include <vector> #include "PhysicalNetlist.capnp.h" #include "arch_iterators.h" #include "chipdb.h" -#include "hash_table.h" +#include "hashlib.h" #include "log.h" #include "nextpnr_namespaces.h" #include "nextpnr_types.h" @@ -44,10 +43,10 @@ struct SiteInformation const int32_t tile; const int32_t tile_type; const int32_t site; - const std::unordered_set<CellInfo *> &cells_in_site; + const pool<CellInfo *, hash_ptr_ops> &cells_in_site; SiteInformation(const Context *ctx, int32_t tile, int32_t site, - const std::unordered_set<CellInfo *> &cells_in_site); + const pool<CellInfo *, hash_ptr_ops> &cells_in_site); inline const ChipInfoPOD &chip_info() const NPNR_ALWAYS_INLINE; @@ -143,6 +142,7 @@ struct SiteWire WireId wire; PipId pip; NetInfo *net = nullptr; + unsigned int hash() const { return mkhash(mkhash(int(type), wire.hash()), mkhash(pip.hash(), uintptr_t(net))); } }; struct SitePip @@ -214,36 +214,8 @@ struct SitePip { return type != other.type || pip != other.pip || wire != other.wire || other_pip != other.other_pip; } + unsigned int hash() const { return mkhash(mkhash(int(type), pip.hash()), mkhash(wire.hash(), other_pip.hash())); } }; -NEXTPNR_NAMESPACE_END - -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX SiteWire> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX SiteWire &site_wire) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX SiteWire::Type>()(site_wire.type)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX WireId>()(site_wire.wire)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX PipId>()(site_wire.pip)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX NetInfo *>()(site_wire.net)); - return seed; - } -}; - -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX SitePip> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX SitePip &site_pip) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX SitePip::Type>()(site_pip.type)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX PipId>()(site_pip.pip)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX SiteWire>()(site_pip.wire)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX PipId>()(site_pip.other_pip)); - return seed; - } -}; - -NEXTPNR_NAMESPACE_BEGIN struct SitePipDownhillRange; struct SitePipUphillRange; @@ -266,9 +238,9 @@ struct SiteNetInfo { NetInfo *net; SiteWire driver; - HashTables::HashSet<SiteWire> users; + pool<SiteWire> users; - HashTables::HashMap<SiteWire, SitePipMap> wires; + dict<SiteWire, SitePipMap> wires; }; struct SiteArch @@ -276,8 +248,8 @@ struct SiteArch const Context *const ctx; const SiteInformation *const site_info; - HashTables::HashMap<NetInfo *, SiteNetInfo> nets; - HashTables::HashMap<SiteWire, SiteNetMap> wire_to_nets; + dict<NetInfo *, SiteNetInfo, hash_ptr_ops> nets; + dict<SiteWire, SiteNetMap> wire_to_nets; NetInfo blocking_net; SiteNetInfo blocking_site_net; diff --git a/fpga_interchange/site_router.cc b/fpga_interchange/site_router.cc index 69bd366f..090b9342 100644 --- a/fpga_interchange/site_router.cc +++ b/fpga_interchange/site_router.cc @@ -21,7 +21,6 @@ #include "design_utils.h" #include "dynamic_bitarray.h" -#include "hash_table.h" #include "log.h" #include "site_routing_cache.h" @@ -53,7 +52,7 @@ bool check_initial_wires(const Context *ctx, SiteInformation *site_info) { // Propagate from BEL pins to first wire, checking for trivial routing // conflicts. - HashTables::HashMap<WireId, NetInfo *> wires; + dict<WireId, NetInfo *> wires; for (CellInfo *cell : site_info->cells_in_site) { BelId bel = cell->bel; @@ -132,7 +131,7 @@ struct SiteExpansionLoop bool expand_result; SiteWire net_driver; - HashTables::HashSet<SiteWire> net_users; + pool<SiteWire> net_users; SiteRoutingSolution solution; @@ -206,7 +205,7 @@ struct SiteExpansionLoop auto node = new_node(net->driver, SitePip(), /*parent=*/nullptr); - HashTables::HashSet<SiteWire> targets; + pool<SiteWire> targets; targets.insert(net->users.begin(), net->users.end()); if (verbose_site_router(ctx)) { @@ -722,7 +721,7 @@ static bool route_site(SiteArch *ctx, SiteRoutingCache *site_routing_cache, Rout // Create a flat sink list and map. std::vector<SiteWire> sinks; - HashTables::HashMap<SiteWire, size_t> sink_map; + dict<SiteWire, size_t> sink_map; size_t number_solutions = 0; for (const auto *expansion : expansions) { number_solutions += expansion->num_solutions(); @@ -963,8 +962,7 @@ static void apply_constant_routing(Context *ctx, const SiteArch &site_arch, NetI } } -static void apply_routing(Context *ctx, const SiteArch &site_arch, - HashTables::HashSet<std::pair<IdString, int32_t>, PairHash> &lut_thrus) +static void apply_routing(Context *ctx, const SiteArch &site_arch, pool<std::pair<IdString, int32_t>> &lut_thrus) { IdString gnd_net_name(ctx->chip_info->constants->gnd_net_name); NetInfo *gnd_net = ctx->nets.at(gnd_net_name).get(); @@ -1019,8 +1017,7 @@ static void apply_routing(Context *ctx, const SiteArch &site_arch, } } -static bool map_luts_in_site(const SiteInformation &site_info, - HashTables::HashSet<std::pair<IdString, IdString>, PairHash> *blocked_wires) +static bool map_luts_in_site(const SiteInformation &site_info, pool<std::pair<IdString, IdString>> *blocked_wires) { const Context *ctx = site_info.ctx; const std::vector<LutElement> &lut_elements = ctx->lut_elements.at(site_info.tile_type); @@ -1048,7 +1045,7 @@ static bool map_luts_in_site(const SiteInformation &site_info, continue; } - HashTables::HashSet<const LutBel *> blocked_luts; + pool<const LutBel *, hash_ptr_ops> blocked_luts; if (!lut_mapper.remap_luts(ctx, &blocked_luts)) { return false; } @@ -1062,8 +1059,7 @@ static bool map_luts_in_site(const SiteInformation &site_info, } // Block outputs of unavailable LUTs to prevent site router from using them. -static void block_lut_outputs(SiteArch *site_arch, - const HashTables::HashSet<std::pair<IdString, IdString>, PairHash> &blocked_wires) +static void block_lut_outputs(SiteArch *site_arch, const pool<std::pair<IdString, IdString>> &blocked_wires) { const Context *ctx = site_arch->site_info->ctx; auto &tile_info = ctx->chip_info->tile_types[site_arch->site_info->tile_type]; @@ -1185,7 +1181,7 @@ bool SiteRouter::checkSiteRouting(const Context *ctx, const TileStatus &tile_sta } SiteInformation site_info(ctx, tile, site, cells_in_site); - HashTables::HashSet<std::pair<IdString, IdString>, PairHash> blocked_wires; + pool<std::pair<IdString, IdString>> blocked_wires; if (!map_luts_in_site(site_info, &blocked_wires)) { site_ok = false; return site_ok; @@ -1263,7 +1259,7 @@ void SiteRouter::bindSiteRouting(Context *ctx) } SiteInformation site_info(ctx, tile, site, cells_in_site); - HashTables::HashSet<std::pair<IdString, IdString>, PairHash> blocked_wires; + pool<std::pair<IdString, IdString>> blocked_wires; NPNR_ASSERT(map_luts_in_site(site_info, &blocked_wires)); SiteArch site_arch(&site_info); diff --git a/fpga_interchange/site_router.h b/fpga_interchange/site_router.h index 0328b6b2..ad1cbf66 100644 --- a/fpga_interchange/site_router.h +++ b/fpga_interchange/site_router.h @@ -23,6 +23,7 @@ #include <cstdint> +#include "hashlib.h" #include "nextpnr_namespaces.h" #include "nextpnr_types.h" #include "site_arch.h" @@ -37,9 +38,9 @@ struct SiteRouter { SiteRouter(int16_t site) : site(site), dirty(false), site_ok(true) {} - std::unordered_set<CellInfo *> cells_in_site; + pool<CellInfo *, hash_ptr_ops> cells_in_site; std::vector<PipId> valid_pips; - HashTables::HashSet<std::pair<IdString, int32_t>, PairHash> lut_thrus; + pool<std::pair<IdString, int32_t>> lut_thrus; const int16_t site; mutable bool dirty; diff --git a/fpga_interchange/site_routing_cache.cc b/fpga_interchange/site_routing_cache.cc index e6f4dc70..512ca2ac 100644 --- a/fpga_interchange/site_routing_cache.cc +++ b/fpga_interchange/site_routing_cache.cc @@ -70,7 +70,7 @@ void SiteRoutingSolution::store_solution(const SiteArch *ctx, const RouteNodeSto void SiteRoutingSolution::verify(const SiteArch *ctx, const SiteNetInfo &net) { - HashTables::HashSet<SiteWire> seen_users; + pool<SiteWire> seen_users; for (size_t i = 0; i < num_solutions(); ++i) { SiteWire cursor = solution_sink(i); NPNR_ASSERT(net.users.count(cursor) == 1); diff --git a/fpga_interchange/site_routing_cache.h b/fpga_interchange/site_routing_cache.h index 6ad218c7..b4baf65a 100644 --- a/fpga_interchange/site_routing_cache.h +++ b/fpga_interchange/site_routing_cache.h @@ -22,7 +22,6 @@ #define SITE_ROUTING_CACHE_H #include "PhysicalNetlist.capnp.h" -#include "hash_table.h" #include "nextpnr_namespaces.h" #include "site_arch.h" #include "site_routing_storage.h" @@ -97,35 +96,25 @@ struct SiteRoutingKey } static SiteRoutingKey make(const SiteArch *ctx, const SiteNetInfo &site_net); -}; - -NEXTPNR_NAMESPACE_END -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX SiteRoutingKey> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX SiteRoutingKey &key) const noexcept + unsigned int hash() const { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<int32_t>()(key.tile_type)); - boost::hash_combine(seed, std::hash<int32_t>()(key.site)); - boost::hash_combine(seed, std::hash<PhysicalNetlist::PhysNetlist::NetType>()(key.net_type)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX SiteWire::Type>()(key.driver_type)); - boost::hash_combine(seed, std::hash<int32_t>()(key.driver_index)); - boost::hash_combine(seed, std::hash<std::size_t>()(key.user_types.size())); - for (NEXTPNR_NAMESPACE_PREFIX SiteWire::Type user_type : key.user_types) { - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX SiteWire::Type>()(user_type)); - } - - boost::hash_combine(seed, std::hash<std::size_t>()(key.user_indicies.size())); - for (int32_t index : key.user_indicies) { - boost::hash_combine(seed, std::hash<int32_t>()(index)); - } + unsigned int seed = 0; + seed = mkhash(seed, tile_type); + seed = mkhash(seed, site); + seed = mkhash(seed, int(net_type)); + seed = mkhash(seed, int(driver_type)); + seed = mkhash(seed, driver_index); + seed = mkhash(seed, user_types.size()); + for (auto t : user_types) + seed = mkhash(seed, int(t)); + seed = mkhash(seed, user_indicies.size()); + for (auto i : user_indicies) + seed = mkhash(seed, i); return seed; } }; -NEXTPNR_NAMESPACE_BEGIN - // Provides an LRU cache for site routing solutions. class SiteRoutingCache { @@ -134,7 +123,7 @@ class SiteRoutingCache void add_solutions(const SiteArch *ctx, const SiteNetInfo &net, const SiteRoutingSolution &solution); private: - HashTables::HashMap<SiteRoutingKey, SiteRoutingSolution> cache_; + dict<SiteRoutingKey, SiteRoutingSolution> cache_; }; NEXTPNR_NAMESPACE_END diff --git a/fpga_interchange/type_wire.cc b/fpga_interchange/type_wire.cc index a08e024b..d1bdaed0 100644 --- a/fpga_interchange/type_wire.cc +++ b/fpga_interchange/type_wire.cc @@ -54,10 +54,9 @@ TypeWireSet::TypeWireSet(const Context *ctx, WireId wire) std::sort(wire_types_.begin(), wire_types_.end()); - hash_ = 0; - boost::hash_combine(hash_, std::hash<size_t>()(wire_types_.size())); + hash_ = wire_types_.size(); for (const auto &wire : wire_types_) { - boost::hash_combine(hash_, std::hash<NEXTPNR_NAMESPACE_PREFIX TypeWireId>()(wire)); + hash_ = mkhash(hash_, wire.hash()); } } diff --git a/fpga_interchange/type_wire.h b/fpga_interchange/type_wire.h index f2a675ef..a472bccc 100644 --- a/fpga_interchange/type_wire.h +++ b/fpga_interchange/type_wire.h @@ -24,6 +24,7 @@ #include <algorithm> #include <vector> +#include "hashlib.h" #include "nextpnr_namespaces.h" #include "nextpnr_types.h" @@ -48,6 +49,8 @@ struct TypeWireId return type < other.type || (type == other.type && index < other.index); } + unsigned int hash() const { return mkhash(type, index); } + int32_t type; int32_t index; }; @@ -63,49 +66,24 @@ struct TypeWirePair bool operator==(const TypeWirePair &other) const { return src == other.src && dst == other.dst; } bool operator!=(const TypeWirePair &other) const { return src != other.src || dst != other.dst; } + + unsigned int hash() const { return mkhash(src.hash(), dst.hash()); } }; struct TypeWireSet { public: TypeWireSet(const Context *ctx, WireId wire); - std::size_t hash() const { return hash_; } + unsigned int hash() const { return hash_; } bool operator==(const TypeWireSet &other) const { return wire_types_ == other.wire_types_; } bool operator!=(const TypeWireSet &other) const { return wire_types_ != other.wire_types_; } private: - std::size_t hash_; + unsigned int hash_; std::vector<TypeWireId> wire_types_; }; NEXTPNR_NAMESPACE_END -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX TypeWireId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX TypeWireId &wire) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<int>()(wire.type)); - boost::hash_combine(seed, std::hash<int>()(wire.index)); - return seed; - } -}; - -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX TypeWirePair> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX TypeWirePair &pair) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX TypeWireId>()(pair.src)); - boost::hash_combine(seed, std::hash<NEXTPNR_NAMESPACE_PREFIX TypeWireId>()(pair.dst)); - return seed; - } -}; - -template <> struct std::hash<NEXTPNR_NAMESPACE_PREFIX TypeWireSet> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX TypeWireSet &set) const noexcept { return set.hash(); } -}; - #endif /* TYPE_WIRE_H */ diff --git a/generic/arch.h b/generic/arch.h index 50d2731c..9b16d873 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -80,7 +80,7 @@ struct BelInfo IdString type; std::map<IdString, std::string> attrs; CellInfo *bound_cell; - std::unordered_map<IdString, PinInfo> pins; + dict<IdString, PinInfo> pins; DecalXY decalxy; int x, y, z; bool gb; @@ -101,27 +101,14 @@ struct CellDelayKey { IdString from, to; inline bool operator==(const CellDelayKey &other) const { return from == other.from && to == other.to; } + unsigned int hash() const { return mkhash(from.hash(), to.hash()); } }; -NEXTPNR_NAMESPACE_END -namespace std { -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX CellDelayKey> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX CellDelayKey &dk) const noexcept - { - std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.from); - seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.to) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - return seed; - } -}; -} // namespace std -NEXTPNR_NAMESPACE_BEGIN - struct CellTiming { - std::unordered_map<IdString, TimingPortClass> portClasses; - std::unordered_map<CellDelayKey, DelayQuad> combDelays; - std::unordered_map<IdString, std::vector<TimingClockingInfo>> clockingInfo; + dict<IdString, TimingPortClass> portClasses; + dict<CellDelayKey, DelayQuad> combDelays; + dict<IdString, std::vector<TimingClockingInfo>> clockingInfo; }; struct ArchRanges @@ -160,10 +147,10 @@ struct Arch : ArchAPI<ArchRanges> { std::string chipName; - std::unordered_map<IdStringList, WireInfo> wires; - std::unordered_map<IdStringList, PipInfo> pips; - std::unordered_map<IdStringList, BelInfo> bels; - std::unordered_map<GroupId, GroupInfo> groups; + dict<IdStringList, WireInfo> wires; + dict<IdStringList, PipInfo> pips; + dict<IdStringList, BelInfo> bels; + dict<GroupId, GroupInfo> groups; // These functions include useful errors if not found WireInfo &wire_info(IdStringList wire); @@ -172,16 +159,16 @@ struct Arch : ArchAPI<ArchRanges> std::vector<IdStringList> bel_ids, wire_ids, pip_ids; - std::unordered_map<Loc, BelId> bel_by_loc; + dict<Loc, BelId> bel_by_loc; std::vector<std::vector<std::vector<BelId>>> bels_by_tile; - std::unordered_map<DecalId, std::vector<GraphicElement>> decal_graphics; + dict<DecalId, std::vector<GraphicElement>> decal_graphics; int gridDimX, gridDimY; std::vector<std::vector<int>> tileBelDimZ; std::vector<std::vector<int>> tilePipDimZ; - std::unordered_map<IdString, CellTiming> cellTiming; + dict<IdString, CellTiming> cellTiming; void addWire(IdStringList name, IdString type, int x, int y); void addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, delay_t delay, Loc loc); @@ -318,7 +305,7 @@ struct Arch : ArchAPI<ArchRanges> std::vector<IdString> getCellTypes() const override { - std::unordered_set<IdString> cell_types; + pool<IdString> cell_types; for (auto bel : bels) { cell_types.insert(bel.second.type); } diff --git a/generic/archdefs.h b/generic/archdefs.h index 0489ab04..06680cc1 100644 --- a/generic/archdefs.h +++ b/generic/archdefs.h @@ -20,8 +20,7 @@ #ifndef GENERIC_ARCHDEFS_H #define GENERIC_ARCHDEFS_H -#include <unordered_map> - +#include "hashlib.h" #include "idstringlist.h" NEXTPNR_NAMESPACE_BEGIN @@ -52,7 +51,7 @@ struct ArchCellInfo // Only packing rule for slice type primitives is a single clock per tile const NetInfo *slice_clk; // Cell to bel pin mapping - std::unordered_map<IdString, std::vector<IdString>> bel_pins; + dict<IdString, std::vector<IdString>> bel_pins; }; NEXTPNR_NAMESPACE_END diff --git a/generic/cells.cc b/generic/cells.cc index c4421f90..e1892353 100644 --- a/generic/cells.cc +++ b/generic/cells.cc @@ -106,7 +106,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l replace_port(dff, ctx->id("Q"), lc, ctx->id("Q")); } -void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, std::unordered_set<IdString> &todelete_cells) +void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &todelete_cells) { if (nxio->type == ctx->id("$nextpnr_ibuf")) { iob->params[ctx->id("INPUT_USED")] = 1; diff --git a/generic/cells.h b/generic/cells.h index 646d738d..7a8443c5 100644 --- a/generic/cells.h +++ b/generic/cells.h @@ -48,7 +48,7 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff = tr void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false); // Convert a nextpnr IO buffer to a GENERIC_IOB -void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, std::unordered_set<IdString> &todelete_cells); +void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells); NEXTPNR_NAMESPACE_END diff --git a/generic/pack.cc b/generic/pack.cc index a1c325f8..dba86cce 100644 --- a/generic/pack.cc +++ b/generic/pack.cc @@ -19,7 +19,6 @@ #include <algorithm> #include <iterator> -#include <unordered_set> #include "cells.h" #include "design_utils.h" #include "log.h" @@ -32,7 +31,7 @@ static void pack_lut_lutffs(Context *ctx) { log_info("Packing LUT-FFs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); @@ -89,7 +88,7 @@ static void pack_nonlut_ffs(Context *ctx) { log_info("Packing non-LUT FFs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { @@ -203,8 +202,8 @@ static bool is_generic_iob(const Context *ctx, const CellInfo *cell) { return ce // Pack IO buffers static void pack_io(Context *ctx) { - std::unordered_set<IdString> packed_cells; - std::unordered_set<IdString> delete_nets; + pool<IdString> packed_cells; + pool<IdString> delete_nets; std::vector<std::unique_ptr<CellInfo>> new_cells; log_info("Packing IOs..\n"); diff --git a/gowin/arch.h b/gowin/arch.h index 0f975f77..82fcb8c1 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -209,7 +209,7 @@ struct BelInfo IdString name, type; std::map<IdString, std::string> attrs; CellInfo *bound_cell; - std::unordered_map<IdString, PinInfo> pins; + dict<IdString, PinInfo> pins; DecalXY decalxy; int x, y, z; bool gb; @@ -229,27 +229,14 @@ struct CellDelayKey { IdString from, to; inline bool operator==(const CellDelayKey &other) const { return from == other.from && to == other.to; } + unsigned int hash() const { return mkhash(from.hash(), to.hash()); } }; -NEXTPNR_NAMESPACE_END -namespace std { -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX CellDelayKey> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX CellDelayKey &dk) const noexcept - { - std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.from); - seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.to) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - return seed; - } -}; -} // namespace std -NEXTPNR_NAMESPACE_BEGIN - struct CellTiming { - std::unordered_map<IdString, TimingPortClass> portClasses; - std::unordered_map<CellDelayKey, DelayQuad> combDelays; - std::unordered_map<IdString, std::vector<TimingClockingInfo>> clockingInfo; + dict<IdString, TimingPortClass> portClasses; + dict<CellDelayKey, DelayQuad> combDelays; + dict<IdString, std::vector<TimingClockingInfo>> clockingInfo; }; struct ArchRanges : BaseArchRanges @@ -287,10 +274,10 @@ struct Arch : BaseArch<ArchRanges> const PackagePOD *package; const TimingGroupsPOD *speed; - std::unordered_map<IdString, WireInfo> wires; - std::unordered_map<IdString, PipInfo> pips; - std::unordered_map<IdString, BelInfo> bels; - std::unordered_map<GroupId, GroupInfo> groups; + dict<IdString, WireInfo> wires; + dict<IdString, PipInfo> pips; + dict<IdString, BelInfo> bels; + dict<GroupId, GroupInfo> groups; // These functions include useful errors if not found WireInfo &wire_info(IdString wire); @@ -299,16 +286,16 @@ struct Arch : BaseArch<ArchRanges> std::vector<IdString> bel_ids, wire_ids, pip_ids; - std::unordered_map<Loc, BelId> bel_by_loc; + dict<Loc, BelId> bel_by_loc; std::vector<std::vector<std::vector<BelId>>> bels_by_tile; - std::unordered_map<DecalId, std::vector<GraphicElement>> decal_graphics; + dict<DecalId, std::vector<GraphicElement>> decal_graphics; int gridDimX, gridDimY; std::vector<std::vector<int>> tileBelDimZ; std::vector<std::vector<int>> tilePipDimZ; - std::unordered_map<IdString, CellTiming> cellTiming; + dict<IdString, CellTiming> cellTiming; void addWire(IdString name, IdString type, int x, int y); void addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayQuad delay, Loc loc); diff --git a/gowin/cells.cc b/gowin/cells.cc index e45cd482..93f1246f 100644 --- a/gowin/cells.cc +++ b/gowin/cells.cc @@ -114,7 +114,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l replace_port(dff, id_Q, lc, id_Q); } -void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, std::unordered_set<IdString> &todelete_cells) +void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &todelete_cells) { if (nxio->type == id_IBUF) { iob->params[id_INPUT_USED] = 1; diff --git a/gowin/cells.h b/gowin/cells.h index 30b29f5b..7bf1befd 100644 --- a/gowin/cells.h +++ b/gowin/cells.h @@ -87,7 +87,7 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff = tr void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false); // Convert a Gowin IO buffer to a IOB bel -void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, std::unordered_set<IdString> &todelete_cells); +void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells); NEXTPNR_NAMESPACE_END diff --git a/gowin/pack.cc b/gowin/pack.cc index a2998c63..d3a749ea 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -21,7 +21,6 @@ #include <algorithm> #include <iostream> #include <iterator> -#include <unordered_set> #include "cells.h" #include "design_utils.h" #include "log.h" @@ -34,7 +33,7 @@ static void pack_lut_lutffs(Context *ctx) { log_info("Packing LUT-FFs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); @@ -90,7 +89,7 @@ static void pack_nonlut_ffs(Context *ctx) { log_info("Packing non-LUT FFs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { @@ -212,8 +211,8 @@ static bool is_gowin_iob(const Context *ctx, const CellInfo *cell) // Pack IO buffers static void pack_io(Context *ctx) { - std::unordered_set<IdString> packed_cells; - std::unordered_set<IdString> delete_nets; + pool<IdString> packed_cells; + pool<IdString> delete_nets; std::vector<std::unique_ptr<CellInfo>> new_cells; log_info("Packing IOs..\n"); diff --git a/ice40/arch.h b/ice40/arch.h index 29396f49..9c9a118f 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -400,10 +400,10 @@ struct Arch : BaseArch<ArchRanges> const ChipInfoPOD *chip_info; const PackageInfoPOD *package_info; - mutable std::unordered_map<IdStringList, int> bel_by_name; - mutable std::unordered_map<IdStringList, int> wire_by_name; - mutable std::unordered_map<IdStringList, int> pip_by_name; - mutable std::unordered_map<Loc, int> bel_by_loc; + mutable dict<IdStringList, int> bel_by_name; + mutable dict<IdStringList, int> wire_by_name; + mutable dict<IdStringList, int> pip_by_name; + mutable dict<Loc, int> bel_by_loc; std::vector<bool> bel_carry; std::vector<CellInfo *> bel_to_cell; @@ -414,7 +414,7 @@ struct Arch : BaseArch<ArchRanges> // 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); diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 6b625b6a..56b5561c 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -252,7 +252,7 @@ static BelPin get_one_bel_pin(const Context *ctx, WireId wire) } // Permute LUT init value given map (LUT input -> ext input) -unsigned permute_lut(unsigned orig_init, const std::unordered_map<int, int> &input_permute) +unsigned permute_lut(unsigned orig_init, const dict<int, int> &input_permute) { unsigned new_init = 0; @@ -387,8 +387,8 @@ void write_asc(const Context *ctx, std::ostream &out) } // Scan for PLL and collects the affected SB_IOs - std::unordered_set<Loc> sb_io_used_by_pll_out; - std::unordered_set<Loc> sb_io_used_by_pll_pad; + pool<Loc> sb_io_used_by_pll_out; + pool<Loc> sb_io_used_by_pll_pad; for (auto &cell : ctx->cells) { if (cell.second->type != ctx->id("ICESTORM_PLL")) @@ -447,7 +447,7 @@ void write_asc(const Context *ctx, std::ostream &out) std::vector<bool> lc(20, false); // Discover permutation - std::unordered_map<int, int> input_perm; + dict<int, int> input_perm; std::set<int> unused; for (int i = 0; i < 4; i++) unused.insert(i); diff --git a/ice40/cells.cc b/ice40/cells.cc index d23b6c49..9517c590 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -412,7 +412,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l replace_port(dff, ctx->id("Q"), lc, ctx->id("O")); } -void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, std::unordered_set<IdString> &todelete_cells) +void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells) { if (nxio->type == ctx->id("$nextpnr_ibuf")) { sbio->params[ctx->id("PIN_TYPE")] = 1; diff --git a/ice40/cells.h b/ice40/cells.h index 777ca3e2..d4c0edf4 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -130,7 +130,7 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff = tr void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false); // Convert a nextpnr IO buffer to a SB_IO -void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, std::unordered_set<IdString> &todelete_cells); +void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells); // Return true if a port is a clock port bool is_clock_port(const BaseCtx *ctx, const PortRef &port); diff --git a/ice40/chains.cc b/ice40/chains.cc index f75d329f..cfc8b4a1 100644 --- a/ice40/chains.cc +++ b/ice40/chains.cc @@ -253,7 +253,7 @@ class ChainConstrainer return i3_next; return (CellInfo *)nullptr; }); - std::unordered_set<IdString> chained; + pool<IdString> chained; for (auto &base_chain : carry_chains) { for (auto c : base_chain.cells) chained.insert(c->name); diff --git a/ice40/pack.cc b/ice40/pack.cc index 1d05a8c2..62b08534 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -21,7 +21,6 @@ #include <algorithm> #include <iterator> -#include <unordered_set> #include "cells.h" #include "chains.h" #include "design_utils.h" @@ -35,7 +34,7 @@ static void pack_lut_lutffs(Context *ctx) { log_info("Packing LUT-FFs..\n"); int lut_only = 0, lut_and_ff = 0; - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); @@ -100,7 +99,7 @@ static void pack_nonlut_ffs(Context *ctx) { log_info("Packing non-LUT FFs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; int ff_only = 0; @@ -144,8 +143,8 @@ static bool net_is_constant(const Context *ctx, NetInfo *net, bool &value) static void pack_carries(Context *ctx) { log_info("Packing carries..\n"); - std::unordered_set<IdString> exhausted_cells; - std::unordered_set<IdString> packed_cells; + pool<IdString> exhausted_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; int carry_only = 0; @@ -274,7 +273,7 @@ static void pack_ram(Context *ctx) { log_info("Packing RAMs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { @@ -466,8 +465,8 @@ static bool is_ice_iob(const Context *ctx, const CellInfo *cell) // Pack IO buffers static void pack_io(Context *ctx) { - std::unordered_set<IdString> packed_cells; - std::unordered_set<IdString> delete_nets; + pool<IdString> packed_cells; + pool<IdString> delete_nets; std::vector<std::unique_ptr<CellInfo>> new_cells; log_info("Packing IOs..\n"); @@ -1119,7 +1118,7 @@ static void pack_special(Context *ctx) { log_info("Packing special functions..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; // Handle LED_DRV_CUR first to set the ledCurConnected flag before RGB_DRV is handled below. @@ -1299,7 +1298,7 @@ void pack_plls(Context *ctx) { log_info("Packing PLLs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); diff --git a/machxo2/arch.h b/machxo2/arch.h index 15535fe1..219e87f2 100644 --- a/machxo2/arch.h +++ b/machxo2/arch.h @@ -403,12 +403,12 @@ struct Arch : BaseArch<ArchRanges> const ChipInfoPOD *chip_info; const PackageInfoPOD *package_info; - mutable std::unordered_map<IdStringList, PipId> pip_by_name; + mutable dict<IdStringList, PipId> pip_by_name; // 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; // Helpers template <typename Id> const TileTypePOD *tile_info(Id &id) const diff --git a/machxo2/cells.cc b/machxo2/cells.cc index 03ba0a41..c71247f2 100644 --- a/machxo2/cells.cc +++ b/machxo2/cells.cc @@ -175,6 +175,6 @@ void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut) } } -void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, std::unordered_set<IdString> &todelete_cells) {} +void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &todelete_cells) {} NEXTPNR_NAMESPACE_END diff --git a/machxo2/cells.h b/machxo2/cells.h index a6de219e..afb08138 100644 --- a/machxo2/cells.h +++ b/machxo2/cells.h @@ -49,7 +49,7 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff = tr void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false); // Convert a nextpnr IO buffer to a GENERIC_IOB -void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, std::unordered_set<IdString> &todelete_cells); +void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells); NEXTPNR_NAMESPACE_END diff --git a/machxo2/pack.cc b/machxo2/pack.cc index 26bda946..6f2ee8e4 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -20,7 +20,6 @@ #include <algorithm> #include <iterator> -#include <unordered_set> #include "cells.h" #include "design_utils.h" #include "log.h" @@ -33,7 +32,7 @@ static void pack_lut_lutffs(Context *ctx) { log_info("Packing LUT-FFs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); @@ -91,7 +90,7 @@ static void pack_remaining_ffs(Context *ctx) { log_info("Packing remaining FFs..\n"); - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; for (auto &cell : ctx->cells) { @@ -130,7 +129,7 @@ static void set_net_constant(Context *ctx, NetInfo *orig, NetInfo *constnet, boo { (void)constval; - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; std::vector<std::unique_ptr<CellInfo>> new_cells; orig->driver.cell = nullptr; @@ -233,7 +232,7 @@ static bool is_facade_iob(const Context *ctx, const CellInfo *cell) { return cel // attributes. static void pack_io(Context *ctx) { - std::unordered_set<IdString> packed_cells; + pool<IdString> packed_cells; log_info("Packing IOs..\n"); diff --git a/mistral/arch.h b/mistral/arch.h index ee2c84a3..1a42530a 100644 --- a/mistral/arch.h +++ b/mistral/arch.h @@ -85,7 +85,7 @@ struct BelInfo // For cases where we need to determine an original block index, due to multiple bels at the same tile this // might not be the same as the nextpnr z-coordinate int block_index; - std::unordered_map<IdString, PinInfo> pins; + dict<IdString, PinInfo> pins; // Info for different kinds of bels union { @@ -153,7 +153,7 @@ struct UpDownhillPipRange UpDownhillPipIterator b, e; UpDownhillPipRange(const std::vector<WireId> &v, WireId other_wire, bool is_uphill) - : b(v.cbegin(), other_wire, is_uphill), e(v.cend(), other_wire, is_uphill){}; + : b(v.begin(), other_wire, is_uphill), e(v.end(), other_wire, is_uphill){}; UpDownhillPipIterator begin() const { return b; } UpDownhillPipIterator end() const { return e; } @@ -161,7 +161,7 @@ struct UpDownhillPipRange // This iterates over the list of wires, and for each wire yields its uphill pips, as an efficient way of going over // all the pips in the device -using WireMapIterator = std::unordered_map<WireId, WireInfo>::const_iterator; +using WireMapIterator = dict<WireId, WireInfo>::const_iterator; struct AllPipIterator { WireMapIterator base, end; @@ -196,8 +196,7 @@ struct AllPipRange { AllPipIterator b, e; - AllPipRange(const std::unordered_map<WireId, WireInfo> &wires) - : b(wires.cbegin(), wires.cend(), -1), e(wires.cend(), wires.cend(), 0) + AllPipRange(const dict<WireId, WireInfo> &wires) : b(wires.begin(), wires.end(), -1), e(wires.end(), wires.end(), 0) { // Starting the begin iterator at index -1 and incrementing it ensures we skip over the first wire if it has no // uphill pips @@ -211,7 +210,7 @@ struct AllPipRange // This transforms a map to a range of keys, used as the wire iterator template <typename T> struct key_range { - key_range(const T &t) : b(t.cbegin()), e(t.cend()){}; + key_range(const T &t) : b(t.begin()), e(t.end()){}; typename T::const_iterator b, e; struct xformed_iterator : public T::const_iterator @@ -224,7 +223,7 @@ template <typename T> struct key_range xformed_iterator end() const { return xformed_iterator(e); } }; -using AllWireRange = key_range<std::unordered_map<WireId, WireInfo>>; +using AllWireRange = key_range<dict<WireId, WireInfo>>; struct ArchRanges : BaseArchRanges { @@ -489,7 +488,7 @@ struct Arch : BaseArch<ArchRanges> static const std::string defaultRouter; static const std::vector<std::string> availableRouters; - std::unordered_map<WireId, WireInfo> wires; + dict<WireId, WireInfo> wires; // List of LABs std::vector<LABInfo> labs; @@ -499,13 +498,13 @@ struct Arch : BaseArch<ArchRanges> // Conversion between numbers and rnode types and IdString, for fast wire name implementation std::vector<IdString> int2id; - std::unordered_map<IdString, int> id2int; + dict<IdString, int> id2int; std::vector<IdString> rn_t2id; - std::unordered_map<IdString, CycloneV::rnode_type_t> id2rn_t; + dict<IdString, CycloneV::rnode_type_t> id2rn_t; // This structure is only used for nextpnr-created wires - std::unordered_map<IdStringList, WireId> npnr_wirebyname; + dict<IdStringList, WireId> npnr_wirebyname; std::vector<std::vector<BelInfo>> bels_by_tile; std::vector<BelId> all_bels; @@ -525,18 +524,18 @@ struct Arch : BaseArch<ArchRanges> // ------------------------------------------------- void assign_default_pinmap(CellInfo *cell); - static const std::unordered_map<IdString, IdString> comb_pinmap; + static const dict<IdString, IdString> comb_pinmap; // ------------------------------------------------- - typedef std::unordered_map<IdString, CellPinStyle> CellPinsData; // pins.cc - static const std::unordered_map<IdString, CellPinsData> cell_pins_db; // pins.cc + typedef dict<IdString, CellPinStyle> CellPinsData; // pins.cc + static const dict<IdString, CellPinsData> cell_pins_db; // pins.cc CellPinStyle get_cell_pin_style(const CellInfo *cell, IdString port) const; // pins.cc // ------------------------------------------------- // List of IO constraints, used by QSF parser - std::unordered_map<IdString, std::unordered_map<IdString, Property>> io_attr; + dict<IdString, dict<IdString, Property>> io_attr; void read_qsf(std::istream &in); // qsf.cc // ------------------------------------------------- diff --git a/mistral/archdefs.h b/mistral/archdefs.h index 9d953223..71e14ec2 100644 --- a/mistral/archdefs.h +++ b/mistral/archdefs.h @@ -203,7 +203,7 @@ struct ArchCellInfo : BaseClusterInfo } ffInfo; }; - std::unordered_map<IdString, ArchPinInfo> pin_data; + dict<IdString, ArchPinInfo> pin_data; CellPinState get_pin_state(IdString pin) const; }; diff --git a/mistral/lab.cc b/mistral/lab.cc index abd0fec3..56bc604a 100644 --- a/mistral/lab.cc +++ b/mistral/lab.cc @@ -718,7 +718,7 @@ void Arch::reassign_alm_inputs(uint32_t lab, uint8_t alm) // - C, E0, and F0 are exclusive to the top LUT5 secion // - D, E1, and F1 are exclusive to the bottom LUT5 section // First find up to two shared inputs - std::unordered_map<IdString, int> shared_nets; + dict<IdString, int> shared_nets; if (luts[0] && luts[1]) { for (int i = 0; i < luts[0]->combInfo.lut_input_count; i++) { for (int j = 0; j < luts[1]->combInfo.lut_input_count; j++) { @@ -826,7 +826,7 @@ void Arch::reassign_alm_inputs(uint32_t lab, uint8_t alm) // This default cell-bel pin mapping is used to provide estimates during placement only. It will have errors and // overlaps and a correct mapping will be resolved twixt placement and routing -const std::unordered_map<IdString, IdString> Arch::comb_pinmap = { +const dict<IdString, IdString> Arch::comb_pinmap = { {id_A, id_F0}, // fastest input first {id_B, id_E0}, {id_C, id_D}, {id_D, id_C}, {id_D0, id_C}, {id_D1, id_B}, {id_E, id_B}, {id_F, id_A}, {id_Q, id_COMBOUT}, {id_SO, id_COMBOUT}, diff --git a/mistral/pins.cc b/mistral/pins.cc index c3637115..51cb83c4 100644 --- a/mistral/pins.cc +++ b/mistral/pins.cc @@ -23,7 +23,7 @@ NEXTPNR_NAMESPACE_BEGIN -const std::unordered_map<IdString, Arch::CellPinsData> Arch::cell_pins_db = { +const dict<IdString, Arch::CellPinsData> Arch::cell_pins_db = { // For combinational cells, inversion and tieing can be implemented by manipulating the LUT function {id_MISTRAL_ALUT2, {{{}, PINSTYLE_COMB}}}, {id_MISTRAL_ALUT3, {{{}, PINSTYLE_COMB}}}, diff --git a/mistral/qsf.cc b/mistral/qsf.cc index 9a128595..88f51b1b 100644 --- a/mistral/qsf.cc +++ b/mistral/qsf.cc @@ -34,7 +34,7 @@ struct QsfOption bool required; // error out if this option isn't passed }; -typedef std::unordered_map<std::string, std::vector<std::string>> option_map_t; +typedef dict<std::string, std::vector<std::string>> option_map_t; struct QsfCommand { diff --git a/nexus/arch.h b/nexus/arch.h index b3558413..a669be0d 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -916,7 +916,7 @@ struct Arch : BaseArch<ArchRanges> // 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; // ------------------------------------------------- @@ -1181,7 +1181,7 @@ struct Arch : BaseArch<ArchRanges> // for better DSP bounding boxes void pre_routing(); - std::unordered_set<WireId> dsp_wires, lram_wires; + pool<WireId> dsp_wires, lram_wires; // ------------------------------------------------- @@ -1271,9 +1271,9 @@ struct Arch : BaseArch<ArchRanges> // ------------------------------------------------- - typedef std::unordered_map<IdString, CellPinStyle> CellPinsData; + typedef dict<IdString, CellPinStyle> CellPinsData; - std::unordered_map<IdString, CellPinsData> cell_pins_db; + dict<IdString, CellPinsData> cell_pins_db; CellPinStyle get_cell_pin_style(const CellInfo *cell, IdString port) const; void init_cell_pin_data(); @@ -1361,7 +1361,7 @@ struct Arch : BaseArch<ArchRanges> // ------------------------------------------------- // Data about different IO standard, mostly used by bitgen - static const std::unordered_map<std::string, IOTypeData> io_types; + static const dict<std::string, IOTypeData> io_types; int get_io_type_vcc(const std::string &io_type) const; bool is_io_type_diff(const std::string &io_type) const; bool is_io_type_ref(const std::string &io_type) const; @@ -1388,7 +1388,7 @@ struct Arch : BaseArch<ArchRanges> // ------------------------------------------------- // List of IO constraints, used by PDC parser - std::unordered_map<IdString, std::unordered_map<IdString, Property>> io_attr; + dict<IdString, dict<IdString, Property>> io_attr; void read_pdc(std::istream &in); diff --git a/nexus/archdefs.h b/nexus/archdefs.h index db8a3af4..76ba605b 100644 --- a/nexus/archdefs.h +++ b/nexus/archdefs.h @@ -21,7 +21,6 @@ #define NEXUS_ARCHDEFS_H #include <boost/functional/hash.hpp> -#include <unordered_map> #include "base_clusterinfo.h" #include "hashlib.h" @@ -184,7 +183,7 @@ struct ArchCellInfo : BaseClusterInfo int tmg_index = -1; // Map from cell/bel ports to logical timing ports - std::unordered_map<IdString, IdString> tmg_portmap; + dict<IdString, IdString> tmg_portmap; }; NEXTPNR_NAMESPACE_END diff --git a/nexus/fasm.cc b/nexus/fasm.cc index 13fe00c1..48483bfe 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -336,7 +336,7 @@ struct NexusFasmWriter pop(2); } - std::unordered_set<BelId> used_io; + pool<BelId> used_io; struct BankConfig { @@ -556,7 +556,7 @@ struct NexusFasmWriter // Which PLL params are 'word' values /* clang-format off */ - const std::unordered_map<std::string, int> pll_word_params = { + const dict<std::string, int> pll_word_params = { {"DIVA", 7}, {"DELA", 7}, {"PHIA", 3}, {"DIVB", 7}, {"DELB", 7}, {"PHIB", 3}, {"DIVC", 7}, {"DELC", 7}, {"PHIC", 3}, {"DIVD", 7}, {"DELD", 7}, {"PHID", 3}, @@ -582,7 +582,7 @@ struct NexusFasmWriter }; // Which MIPI params are 'word' values - const std::unordered_map<std::string, int> dphy_word_params = { + const dict<std::string, int> dphy_word_params = { {"CM", 8}, {"CN", 5}, {"CO", 3}, {"RSEL", 2}, {"RXCDRP", 2}, {"RXDATAWIDTHHS", 2}, {"RXLPRP", 3}, {"TEST_ENBL", 6}, {"TEST_PATTERN", 32}, {"TST", 4}, {"TXDATAWIDTHHS", 2}, @@ -683,7 +683,7 @@ struct NexusFasmWriter write_comment("# Unused bels"); // DSP primitives are configured to a default mode; even if unused - static const std::unordered_map<IdString, std::vector<std::string>> dsp_defconf = { + static const dict<IdString, std::vector<std::string>> dsp_defconf = { {id_MULT9_CORE, { "GSR.ENABLED", @@ -733,7 +733,7 @@ struct NexusFasmWriter } } } - std::unordered_map<int, int> bank_vcco; + dict<int, int> bank_vcco; // bank VccO in mV int get_bank_vcco(const std::string &iostd) { diff --git a/nexus/global.cc b/nexus/global.cc index fa6212e8..9a0d095b 100644 --- a/nexus/global.cc +++ b/nexus/global.cc @@ -49,7 +49,7 @@ struct NexusGlobalRouter // Queue of wires to visit std::queue<WireId> visit; // Wire -> upstream pip - std::unordered_map<WireId, PipId> backtrace; + dict<WireId, PipId> backtrace; // Lookup source and destination wires WireId src = ctx->getNetinfoSourceWire(net); diff --git a/nexus/io.cc b/nexus/io.cc index fd5e584f..314d80b6 100644 --- a/nexus/io.cc +++ b/nexus/io.cc @@ -23,7 +23,7 @@ NEXTPNR_NAMESPACE_BEGIN -const std::unordered_map<std::string, IOTypeData> Arch::io_types = { +const dict<std::string, IOTypeData> Arch::io_types = { {"LVCMOS33", {IOSTYLE_SE_WR, 330}}, {"LVCMOS25", {IOSTYLE_SE_WR, 250}}, {"LVCMOS18", {IOSTYLE_SE_WR, 180}}, {"LVCMOS15", {IOSTYLE_SE_WR, 150}}, {"LVCMOS12", {IOSTYLE_SE_WR, 120}}, {"LVCMOS10", {IOSTYLE_SE_WR, 120}}, diff --git a/nexus/pack.cc b/nexus/pack.cc index 812731cf..1d977f2c 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -106,16 +106,16 @@ struct NexusPacker struct XFormRule { IdString new_type; - std::unordered_map<IdString, IdString> port_xform; - std::unordered_map<IdString, std::vector<IdString>> port_multixform; - std::unordered_map<IdString, IdString> param_xform; + dict<IdString, IdString> port_xform; + dict<IdString, std::vector<IdString>> port_multixform; + dict<IdString, IdString> param_xform; std::vector<std::pair<IdString, std::string>> set_attrs; std::vector<std::pair<IdString, Property>> set_params; std::vector<std::pair<IdString, Property>> default_params; std::vector<std::tuple<IdString, IdString, int, int64_t>> parse_params; }; - void xform_cell(const std::unordered_map<IdString, XFormRule> &rules, CellInfo *ci) + void xform_cell(const dict<IdString, XFormRule> &rules, CellInfo *ci) { auto &rule = rules.at(ci->type); ci->type = rule.new_type; @@ -178,7 +178,7 @@ struct NexusPacker ci->params[param.first] = param.second; } - void generic_xform(const std::unordered_map<IdString, XFormRule> &rules, bool print_summary = false) + void generic_xform(const dict<IdString, XFormRule> &rules, bool print_summary = false) { std::map<std::string, int> cell_count; std::map<std::string, int> new_types; @@ -205,7 +205,7 @@ struct NexusPacker void pack_luts() { log_info("Packing LUTs...\n"); - std::unordered_map<IdString, XFormRule> lut_rules; + dict<IdString, XFormRule> lut_rules; lut_rules[id_LUT4].new_type = id_OXIDE_COMB; lut_rules[id_LUT4].port_xform[id_Z] = id_F; lut_rules[id_LUT4].parse_params.emplace_back(id_INIT, id_INIT, 16, 0); @@ -229,7 +229,7 @@ struct NexusPacker void pack_ffs() { log_info("Packing FFs...\n"); - std::unordered_map<IdString, XFormRule> ff_rules; + dict<IdString, XFormRule> ff_rules; for (auto type : {id_FD1P3BX, id_FD1P3DX, id_FD1P3IX, id_FD1P3JX}) { ff_rules[type].new_type = id_OXIDE_FF; ff_rules[type].port_xform[id_CK] = id_CLK; @@ -262,7 +262,7 @@ struct NexusPacker generic_xform(ff_rules, true); } - std::unordered_map<IdString, BelId> reference_bels; + dict<IdString, BelId> reference_bels; void autocreate_ports(CellInfo *cell) { @@ -549,11 +549,10 @@ struct NexusPacker void pack_io() { - std::unordered_set<IdString> iob_types = {id_IB, id_OB, id_OBZ, id_BB, - id_BB_I3C_A, id_SEIO33, id_SEIO18, id_DIFFIO18, - id_SEIO33_CORE, id_SEIO18_CORE, id_DIFFIO18_CORE}; + pool<IdString> iob_types = {id_IB, id_OB, id_OBZ, id_BB, id_BB_I3C_A, id_SEIO33, + id_SEIO18, id_DIFFIO18, id_SEIO33_CORE, id_SEIO18_CORE, id_DIFFIO18_CORE}; - std::unordered_map<IdString, XFormRule> io_rules; + dict<IdString, XFormRule> io_rules; // For the low level primitives, make sure we always preserve their type io_rules[id_SEIO33_CORE].new_type = id_SEIO33_CORE; @@ -567,12 +566,12 @@ struct NexusPacker io_rules[id_SEIO33].port_xform[id_PADDT] = id_T; io_rules[id_SEIO33].port_xform[id_IOPAD] = id_B; - io_rules[id_BB_I3C_A] = io_rules[id_SEIO33]; + io_rules[id_BB_I3C_A] = XFormRule(io_rules[id_SEIO33]); - io_rules[id_SEIO18] = io_rules[id_SEIO33]; + io_rules[id_SEIO18] = XFormRule(io_rules[id_SEIO33]); io_rules[id_SEIO18].new_type = id_SEIO18_CORE; - io_rules[id_DIFFIO18] = io_rules[id_SEIO33]; + io_rules[id_DIFFIO18] = XFormRule(io_rules[id_SEIO33]); io_rules[id_DIFFIO18].new_type = id_DIFFIO18_CORE; // Stage 0: deal with top level inserted IO buffers @@ -677,8 +676,8 @@ struct NexusPacker { int iter = 0; std::queue<WireId> visit; - std::unordered_set<WireId> seen_wires; - std::unordered_set<BelId> seen_bels; + pool<WireId> seen_wires; + pool<BelId> seen_bels; BelId bel = get_bel_attr(cell); if (bel == BelId()) @@ -751,7 +750,7 @@ struct NexusPacker return best_bel; } - std::unordered_set<BelId> used_bels; + pool<BelId> used_bels; // Pre-place a primitive based on routeability first and distance second bool preplace_prim(CellInfo *cell, IdString pin, bool strict_routing) @@ -1024,7 +1023,7 @@ struct NexusPacker void convert_prims() { // Convert primitives from their non-CORE variant to their CORE variant - static const std::unordered_map<IdString, IdString> prim_map = { + static const dict<IdString, IdString> prim_map = { {id_OSCA, id_OSC_CORE}, {id_DP16K, id_DP16K_MODE}, {id_PDP16K, id_PDP16K_MODE}, {id_PDPSC16K, id_PDPSC16K_MODE}, {id_SP16K, id_SP16K_MODE}, {id_FIFO16K, id_FIFO16K_MODE}, {id_SP512K, id_SP512K_MODE}, {id_DPSC512K, id_DPSC512K_MODE}, {id_PDPSC512K, id_PDPSC512K_MODE}, @@ -1048,7 +1047,7 @@ struct NexusPacker void pack_bram() { - std::unordered_map<IdString, XFormRule> bram_rules; + dict<IdString, XFormRule> bram_rules; bram_rules[id_DP16K_MODE].new_type = id_OXIDE_EBR; bram_rules[id_DP16K_MODE].set_params.emplace_back(id_MODE, std::string("DP16K")); bram_rules[id_DP16K_MODE].parse_params.emplace_back(id_CSDECODE_A, id_CSDECODE_A, 3, 7); @@ -1074,7 +1073,7 @@ struct NexusPacker add_bus_xform(bram_rules[id_PDP16K_MODE], "DO", "DOA", 18, 18, 0); // Pseudo dual port; single clock - bram_rules[id_PDPSC16K_MODE] = bram_rules[id_PDP16K_MODE]; + bram_rules[id_PDPSC16K_MODE] = XFormRule(bram_rules[id_PDP16K_MODE]); bram_rules[id_PDPSC16K_MODE].set_params.clear(); bram_rules[id_PDPSC16K_MODE].set_params.emplace_back(id_MODE, std::string("PDPSC16K")); bram_rules[id_PDPSC16K_MODE].set_params.emplace_back(id_WEAMUX, std::string("1")); @@ -1096,7 +1095,7 @@ struct NexusPacker void pack_lram() { - std::unordered_map<IdString, XFormRule> lram_rules; + dict<IdString, XFormRule> lram_rules; lram_rules[id_SP512K_MODE].new_type = id_LRAM_CORE; lram_rules[id_SP512K_MODE].set_params.emplace_back(id_EBR_SP_EN, std::string("ENABLE")); lram_rules[id_SP512K_MODE].port_xform[id_CE] = id_CEA; @@ -1296,7 +1295,7 @@ struct NexusPacker // Automatically generate cascade connections downstream of a cell // using the temporary placement that we use solely to access the routing graph - void auto_cascade_cell(CellInfo *cell, BelId bel, const std::unordered_map<BelId, CellInfo *> &bel2cell) + void auto_cascade_cell(CellInfo *cell, BelId bel, const dict<BelId, CellInfo *> &bel2cell) { // Create outputs based on the actual bel for (auto bp : ctx->getBelPins(bel)) { @@ -1322,7 +1321,7 @@ struct NexusPacker // Standard BFS-type exploration std::queue<WireId> visit; - std::unordered_set<WireId> in_queue; + pool<WireId> in_queue; visit.push(start_wire); in_queue.insert(start_wire); int iter = 0; @@ -1403,8 +1402,8 @@ struct NexusPacker // We first create a temporary placement so we can access the routing graph bool found = false; - std::unordered_map<BelId, CellInfo *> bel2cell; - std::unordered_map<IdString, BelId> cell2bel; + dict<BelId, CellInfo *> bel2cell; + dict<IdString, BelId> cell2bel; for (BelId root_bel : ctx->getBels()) { if (ctx->getBelType(root_bel) != root->type) @@ -1592,7 +1591,7 @@ struct NexusPacker int wide; // DSP is a "wide" (dot-product) variant }; - const std::unordered_map<IdString, DSPMacroType> dsp_types = { + const dict<IdString, DSPMacroType> dsp_types = { {id_MULT9X9, {9, 9, 0, 18, 1, 0, 0, false, false, -1}}, {id_MULT18X18, {18, 18, 0, 36, 2, 1, 0, false, false, -1}}, {id_MULT18X36, {18, 36, 0, 54, 4, 2, 1, false, false, -1}}, @@ -1805,7 +1804,7 @@ struct NexusPacker 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); @@ -1883,7 +1882,7 @@ struct NexusPacker 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_REFCK) @@ -1893,7 +1892,7 @@ struct NexusPacker 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_DCC) { copy_constraint(ci, id_CLKI, id_CLKO, 1); @@ -1945,7 +1944,7 @@ struct NexusPacker void pack_plls() { - const std::unordered_map<IdString, std::string> pll_defaults = { + const dict<IdString, std::string> pll_defaults = { {id_FLOCK_CTRL, "2X"}, {id_FLOCK_EN, "ENABLED"}, {id_FLOCK_SRC_SEL, "REFCLK"}, {id_DIV_DEL, "0b0000001"}, {id_FBK_PI_RC, "0b1100"}, {id_FBK_PR_IC, "0b1000"}, }; @@ -1966,7 +1965,7 @@ struct NexusPacker // Map LOC attribute on DPHY_CORE to a bel // TDPHY_CORE2 is Radiant 2.0 style, DPHY0 is Radiant 2.2 // TODO: LIFCL-17 (perhaps remove the hardcoded map) - const std::unordered_map<std::string, std::string> dphy_loc_map = { + const dict<std::string, std::string> dphy_loc_map = { {"TDPHY_CORE2", "X4/Y0/TDPHY_CORE2"}, {"DPHY0", "X4/Y0/TDPHY_CORE2"}, {"TDPHY_CORE26", "X28/Y0/TDPHY_CORE26"}, diff --git a/nexus/pdc.cc b/nexus/pdc.cc index 1ffe0a64..f81bb74e 100644 --- a/nexus/pdc.cc +++ b/nexus/pdc.cc @@ -406,7 +406,7 @@ struct PDCParser TCLValue cmd_ldc_set_port(const std::vector<TCLValue> &arguments) { - std::unordered_map<IdString, Property> args; + dict<IdString, Property> args; for (int i = 1; i < int(arguments.size()); i++) { auto &arg = arguments.at(i); if (arg.is_string) { diff --git a/nexus/pins.cc b/nexus/pins.cc index a283953b..e9841f4b 100644 --- a/nexus/pins.cc +++ b/nexus/pins.cc @@ -24,7 +24,7 @@ NEXTPNR_NAMESPACE_BEGIN namespace { -static const std::unordered_map<IdString, Arch::CellPinsData> base_cell_pin_data = { +static const dict<IdString, Arch::CellPinsData> base_cell_pin_data = { {id_OXIDE_COMB, { {id_WCK, PINSTYLE_DEDI}, |