diff options
author | gatecat <gatecat@ds0.me> | 2021-06-03 09:04:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-03 09:04:34 +0100 |
commit | a3d8b4f9d198226ec0903e34a8d290b376b45c0b (patch) | |
tree | ada2c6a5d48e766fa523e633aaa28179baea3273 /fpga_interchange | |
parent | 589ca8ded5da2012e4388a3ec4c8fae74dff75e4 (diff) | |
parent | dcbb322447a7fb59cabe197ec1dd2307acfa3681 (diff) | |
download | nextpnr-a3d8b4f9d198226ec0903e34a8d290b376b45c0b.tar.gz nextpnr-a3d8b4f9d198226ec0903e34a8d290b376b45c0b.tar.bz2 nextpnr-a3d8b4f9d198226ec0903e34a8d290b376b45c0b.zip |
Merge pull request #718 from YosysHQ/gatecat/hashlib
Moving from unordered_{map, set} to hashlib
Diffstat (limited to 'fpga_interchange')
28 files changed, 197 insertions, 405 deletions
diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index 71c68e66..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; @@ -2047,8 +2034,8 @@ void Arch::pack_default_conns() std::vector<IdString> dead_nets; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); const DefaultCellConnsPOD *conns = get_default_conns(ci->type); if (conns == nullptr) continue; 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/arch_pybindings.cc b/fpga_interchange/arch_pybindings.cc index 68619866..03b20841 100644 --- a/fpga_interchange/arch_pybindings.cc +++ b/fpga_interchange/arch_pybindings.cc @@ -49,10 +49,10 @@ void arch_wrap_python(py::module &m) fn_wrapper_1a_v<Context, decltype(&Context::explain_bel_status), &Context::explain_bel_status, conv_from_str<BelId>>::def_wrap(ctx_cls, "explain_bel_status"); - typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap; - typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap; - typedef std::unordered_map<IdString, IdString> AliasMap; - typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap; + typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap; + typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap; + typedef dict<IdString, IdString> AliasMap; + typedef dict<IdString, HierarchicalCell> HierarchyMap; auto belpin_cls = py::class_<ContextualWrapper<BelPin>>(m, "BelPin"); readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel"); diff --git a/fpga_interchange/archdefs.h b/fpga_interchange/archdefs.h index c145b893..a50df43a 100644 --- a/fpga_interchange/archdefs.h +++ b/fpga_interchange/archdefs.h @@ -21,10 +21,9 @@ #ifndef FPGA_INTERCHANGE_ARCHDEFS_H #define FPGA_INTERCHANGE_ARCHDEFS_H -#include <boost/functional/hash.hpp> #include <cstdint> -#include "hash_table.h" +#include "hashlib.h" #include "luts.h" #include "nextpnr_namespaces.h" @@ -48,6 +47,7 @@ struct BelId { return tile < other.tile || (tile == other.tile && index < other.index); } + unsigned int hash() const { return mkhash(tile, index); } }; struct WireId @@ -62,6 +62,7 @@ struct WireId { return tile < other.tile || (tile == other.tile && index < other.index); } + unsigned int hash() const { return mkhash(tile, index); } }; struct PipId @@ -75,18 +76,21 @@ struct PipId { return tile < other.tile || (tile == other.tile && index < other.index); } + unsigned int hash() const { return mkhash(tile, index); } }; struct GroupId { bool operator==(const GroupId &other) const { return true; } bool operator!=(const GroupId &other) const { return false; } + unsigned int hash() const { return 0; } }; struct DecalId { bool operator==(const DecalId &other) const { return true; } bool operator!=(const DecalId &other) const { return false; } + unsigned int hash() const { return 0; } }; struct BelBucketId @@ -96,6 +100,7 @@ struct BelBucketId bool operator==(const BelBucketId &other) const { return (name == other.name); } bool operator!=(const BelBucketId &other) const { return (name != other.name); } bool operator<(const BelBucketId &other) const { return name < other.name; } + unsigned int hash() const { return name.hash(); } }; typedef IdString ClusterId; @@ -112,76 +117,12 @@ 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; }; NEXTPNR_NAMESPACE_END -namespace std { -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelId &bel) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(bel.tile)); - boost::hash_combine(seed, hash<int>()(bel.index)); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX WireId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX WireId &wire) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(wire.tile)); - boost::hash_combine(seed, hash<int>()(wire.index)); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX PipId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX PipId &pip) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(pip.tile)); - boost::hash_combine(seed, hash<int>()(pip.index)); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX GroupId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX GroupId &group) const noexcept - { - std::size_t seed = 0; - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DecalId &decal) const noexcept - { - std::size_t seed = 0; - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelBucketId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelBucketId &bucket) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(bucket.name)); - return seed; - } -}; - -} // namespace std - #endif /* FPGA_INTERCHANGE_ARCHDEFS_H */ 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 66d04f75..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(); @@ -160,8 +160,8 @@ void Arch::place_globals() // TODO: for more complex PLL type setups, we might want a toposort or iterative loop as the PLL must be placed // before the GBs it drives - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); const GlobalCellPOD *glb_cell = global_cell_info(ci->type); if (glb_cell == nullptr) continue; @@ -239,8 +239,8 @@ void Arch::route_globals() IdString gnd_net_name(chip_info->constants->gnd_net_name); IdString vcc_net_name(chip_info->constants->vcc_net_name); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); const GlobalCellPOD *glb_cell = global_cell_info(ci->type); if (glb_cell == nullptr) continue; 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/macros.cc b/fpga_interchange/macros.cc index eee35d9f..8339829f 100644 --- a/fpga_interchange/macros.cc +++ b/fpga_interchange/macros.cc @@ -53,8 +53,8 @@ void Arch::expand_macros() // Make up a list of cells, so we don't have modify-while-iterating issues Context *ctx = getCtx(); std::vector<CellInfo *> cells; - for (auto cell : sorted(ctx->cells)) - cells.push_back(cell.second); + for (auto &cell : ctx->cells) + cells.push_back(cell.second.get()); std::vector<CellInfo *> next_cells; diff --git a/fpga_interchange/main.cc b/fpga_interchange/main.cc index 4d331a32..1e1ac71f 100644 --- a/fpga_interchange/main.cc +++ b/fpga_interchange/main.cc @@ -36,7 +36,7 @@ class FpgaInterchangeCommandHandler : public CommandHandler public: FpgaInterchangeCommandHandler(int argc, char **argv); virtual ~FpgaInterchangeCommandHandler(){}; - std::unique_ptr<Context> createContext(std::unordered_map<std::string, Property> &values) override; + std::unique_ptr<Context> createContext(dict<std::string, Property> &values) override; void setupArchContext(Context *ctx) override{}; void customBitstream(Context *ctx) override; void customAfterLoad(Context *ctx) override; @@ -69,7 +69,7 @@ void FpgaInterchangeCommandHandler::customBitstream(Context *ctx) } } -std::unique_ptr<Context> FpgaInterchangeCommandHandler::createContext(std::unordered_map<std::string, Property> &values) +std::unique_ptr<Context> FpgaInterchangeCommandHandler::createContext(dict<std::string, Property> &values) { auto start = std::chrono::high_resolution_clock::now(); 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 */ |