From 4e346ecfba86880c2528e3463b9beb42932d8567 Mon Sep 17 00:00:00 2001 From: gatecat Date: Wed, 14 Apr 2021 10:14:51 +0100 Subject: [PATCH] Hash table refactoring Signed-off-by: gatecat --- CMakeLists.txt | 11 +++++-- common/hash_table.h | 33 +++++++++++++++------ common/timing_opt.cc | 45 +++-------------------------- fpga_interchange/cell_parameters.h | 2 +- fpga_interchange/cost_map.cc | 2 +- fpga_interchange/cost_map.h | 2 +- fpga_interchange/lookahead.cc | 5 ++-- fpga_interchange/pseudo_pip_model.h | 2 +- fpga_interchange/site_router.cc | 8 ++--- gui/CMakeLists.txt | 5 ++++ 10 files changed, 53 insertions(+), 62 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 538ad1a4..8291a21f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ option(EXTERNAL_CHIPDB "Create build with pre-built chipdb binaries" OFF) option(WERROR "pass -Werror to compiler (used for CI)" OFF) option(PROFILER "Link against libprofiler" OFF) option(USE_IPO "Compile nextpnr with IPO" ON) +option(USE_ABSEIL "Compile nextpnr with Abseil for faster hash map" OFF) if (USE_IPO) if (ipo_supported) @@ -198,7 +199,7 @@ if (NOT DEFINED CURRENT_GIT_VERSION) ) endif() -if (NOT WASI) +if (USE_ABSEIL) add_subdirectory(3rdparty/abseil-cpp EXCLUDE_FROM_ALL) endif() @@ -251,7 +252,10 @@ else() endif() set(EXTRA_LIB_DEPS) -if (USE_THREADS) +if (USE_ABSEIL) + if (NOT USE_THREADS) + message(FATAL_ERROR "Abseil without threads is not supported") + endif() list(APPEND EXTRA_LIB_DEPS absl::flat_hash_map) list(APPEND EXTRA_LIB_DEPS absl::flat_hash_set) endif() @@ -332,6 +336,9 @@ foreach (family ${ARCH}) target_compile_definitions(${target} PRIVATE QT_NO_KEYWORDS) target_link_libraries(${target} LINK_PUBLIC gui_${family} ${GUI_LIBRARY_FILES_${ufamily}}) endif() + if (USE_ABSEIL) + target_compile_definitions(${target} PRIVATE USE_ABSEIL) + endif() if (BUILD_PYTHON) target_link_libraries(${target} LINK_PUBLIC ${PYTHON_LIBRARIES}) if (STATIC_BUILD) diff --git a/common/hash_table.h b/common/hash_table.h index 759580da..21ca8887 100644 --- a/common/hash_table.h +++ b/common/hash_table.h @@ -20,29 +20,44 @@ #ifndef HASH_TABLE_H #define HASH_TABLE_H -#if defined(NPNR_DISABLE_THREADS) -#include -#include -#else +#if defined(USE_ABSEIL) #include #include +#else +#include +#include #endif +#include + #include "nextpnr_namespaces.h" NEXTPNR_NAMESPACE_BEGIN namespace HashTables { -#if defined(NPNR_DISABLE_THREADS) -template using HashMap = std::unordered_map; -template using HashSet = std::unordered_set; +#if defined(USE_ABSEIL) +template > +using HashMap = absl::flat_hash_map; +template > using HashSet = absl::flat_hash_set; #else -template using HashMap = absl::flat_hash_map; -template using HashSet = absl::flat_hash_set; +template > +using HashMap = std::unordered_map; +template > using HashSet = std::unordered_set; #endif }; // namespace HashTables +struct PairHash +{ + template std::size_t operator()(const std::pair &idp) const noexcept + { + std::size_t seed = 0; + boost::hash_combine(seed, std::hash()(idp.first)); + boost::hash_combine(seed, std::hash()(idp.second)); + return seed; + } +}; + NEXTPNR_NAMESPACE_END #endif /* HASH_TABLE_H */ diff --git a/common/timing_opt.cc b/common/timing_opt.cc index fd2a3f83..dba96bf1 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -35,44 +35,7 @@ #include "timing.h" #include "util.h" -namespace std { - -template <> struct hash> -{ - std::size_t operator()( - const std::pair &idp) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash()(idp.first)); - boost::hash_combine(seed, hash()(idp.second)); - return seed; - } -}; - -template <> struct hash> -{ - std::size_t operator()(const std::pair &idp) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash()(idp.first)); - boost::hash_combine(seed, hash()(idp.second)); - return seed; - } -}; -#if !defined(ARCH_GOWIN) -template <> struct hash> -{ - std::size_t - operator()(const std::pair &idp) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash()(idp.first)); - boost::hash_combine(seed, hash()(idp.second)); - return seed; - } -}; -#endif -} // namespace std +#include "hash_table.h" NEXTPNR_NAMESPACE_BEGIN @@ -478,9 +441,9 @@ class TimingOptimiser // Actual BFS path optimisation algorithm std::unordered_map> cumul_costs; - std::unordered_map, std::pair> backtrace; + std::unordered_map, std::pair, PairHash> backtrace; std::queue> visit; - std::unordered_set> to_visit; + std::unordered_set, PairHash> to_visit; for (auto startbel : cell_neighbour_bels[path_cells.front()]) { // Swap for legality check @@ -609,7 +572,7 @@ class TimingOptimiser std::unordered_map> cell_neighbour_bels; std::unordered_map> bel_candidate_cells; // Map cell ports to net delay limit - std::unordered_map, delay_t> max_net_delay; + std::unordered_map, delay_t, PairHash> max_net_delay; Context *ctx; TimingOptCfg cfg; TimingAnalyser tmg; diff --git a/fpga_interchange/cell_parameters.h b/fpga_interchange/cell_parameters.h index 3507a81f..de82e76b 100644 --- a/fpga_interchange/cell_parameters.h +++ b/fpga_interchange/cell_parameters.h @@ -42,7 +42,7 @@ struct CellParameters bool compare_property(const Context *ctx, IdString cell_type, IdString parameter, const Property &property, IdString value_to_compare) const; - HashTables::HashMap, const CellParameterPOD *> parameters; + HashTables::HashMap, const CellParameterPOD *, PairHash> 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 b42f115d..868fdca0 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, delay_t> &delays) + const HashTables::HashMap, delay_t, PairHash> &delays) { CostMapEntry delay_matrix; diff --git a/fpga_interchange/cost_map.h b/fpga_interchange/cost_map.h index e57a1027..810d0198 100644 --- a/fpga_interchange/cost_map.h +++ b/fpga_interchange/cost_map.h @@ -39,7 +39,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, delay_t> &delays); + const HashTables::HashMap, delay_t, PairHash> &delays); void from_reader(lookahead_storage::CostMap::Reader reader); void to_builder(lookahead_storage::CostMap::Builder builder) const; diff --git a/fpga_interchange/lookahead.cc b/fpga_interchange/lookahead.cc index cd05c16f..6dc8c43a 100644 --- a/fpga_interchange/lookahead.cc +++ b/fpga_interchange/lookahead.cc @@ -250,7 +250,7 @@ static void expand_input_type(const Context *ctx, DeterministicRNG *rng, const S struct DelayStorage { - HashTables::HashMap, delay_t>> storage; + HashTables::HashMap, delay_t, PairHash>> storage; int32_t max_explore_depth; }; @@ -996,7 +996,8 @@ 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, delay_t>> &type_pair) { + [&](const std::pair, delay_t, PairHash>> + &type_pair) { #else for (const auto &type_pair : all_tiles_storage.storage) { #endif diff --git a/fpga_interchange/pseudo_pip_model.h b/fpga_interchange/pseudo_pip_model.h index 53e2b3a3..1e79071d 100644 --- a/fpga_interchange/pseudo_pip_model.h +++ b/fpga_interchange/pseudo_pip_model.h @@ -98,7 +98,7 @@ struct PseudoPipData const std::vector &get_logic_bels_for_pip(const Context *ctx, int32_t site, PipId pip) const; HashTables::HashMap max_pseudo_pip_for_tile_type; - HashTables::HashMap, std::vector> possibles_sites_for_pip; + HashTables::HashMap, std::vector, PairHash> possibles_sites_for_pip; HashTables::HashMap> logic_bels_for_pip; }; diff --git a/fpga_interchange/site_router.cc b/fpga_interchange/site_router.cc index 51b8bef3..f8cc2208 100644 --- a/fpga_interchange/site_router.cc +++ b/fpga_interchange/site_router.cc @@ -988,7 +988,7 @@ static void apply_routing(Context *ctx, const SiteArch &site_arch) } static bool map_luts_in_site(const SiteInformation &site_info, - HashTables::HashSet> *blocked_wires) + HashTables::HashSet, PairHash> *blocked_wires) { const Context *ctx = site_info.ctx; const std::vector &lut_elements = ctx->lut_elements.at(site_info.tile_type); @@ -1031,7 +1031,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> &blocked_wires) + const HashTables::HashSet, PairHash> &blocked_wires) { const Context *ctx = site_arch->site_info->ctx; auto &tile_info = ctx->chip_info->tile_types[site_arch->site_info->tile_type]; @@ -1112,7 +1112,7 @@ bool SiteRouter::checkSiteRouting(const Context *ctx, const TileStatus &tile_sta } SiteInformation site_info(ctx, tile, site, cells_in_site); - HashTables::HashSet> blocked_wires; + HashTables::HashSet, PairHash> blocked_wires; if (!map_luts_in_site(site_info, &blocked_wires)) { site_ok = false; return site_ok; @@ -1190,7 +1190,7 @@ void SiteRouter::bindSiteRouting(Context *ctx) } SiteInformation site_info(ctx, tile, site, cells_in_site); - HashTables::HashSet> blocked_wires; + HashTables::HashSet, PairHash> blocked_wires; NPNR_ASSERT(map_luts_in_site(site_info, &blocked_wires)); SiteArch site_arch(&site_info); diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index e692eee9..21d0c1e0 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -39,6 +39,11 @@ if (BUILD_PYTHON) endif() target_compile_definitions(gui_${family} PRIVATE NEXTPNR_NAMESPACE=nextpnr_${family} ARCH_${ufamily} ARCHNAME=${family} QT_NO_KEYWORDS) + +if (USE_ABSEIL) + target_compile_definitions(gui_${family} PRIVATE USE_ABSEIL) +endif() + target_link_libraries(gui_${family} Qt5::Widgets) foreach(lib_dep ${EXTRA_LIB_DEPS})