aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt11
-rw-r--r--common/hash_table.h33
-rw-r--r--common/timing_opt.cc45
-rw-r--r--fpga_interchange/cell_parameters.h2
-rw-r--r--fpga_interchange/cost_map.cc2
-rw-r--r--fpga_interchange/cost_map.h2
-rw-r--r--fpga_interchange/lookahead.cc5
-rw-r--r--fpga_interchange/pseudo_pip_model.h2
-rw-r--r--fpga_interchange/site_router.cc8
-rw-r--r--gui/CMakeLists.txt5
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 <unordered_map>
-#include <unordered_set>
-#else
+#if defined(USE_ABSEIL)
#include <absl/container/flat_hash_map.h>
#include <absl/container/flat_hash_set.h>
+#else
+#include <unordered_map>
+#include <unordered_set>
#endif
+#include <boost/functional/hash.hpp>
+
#include "nextpnr_namespaces.h"
NEXTPNR_NAMESPACE_BEGIN
namespace HashTables {
-#if defined(NPNR_DISABLE_THREADS)
-template <typename Key, typename Value> using HashMap = std::unordered_map<Key, Value>;
-template <typename Value> using HashSet = std::unordered_set<Value>;
+#if defined(USE_ABSEIL)
+template <typename Key, typename Value, typename Hash = std::hash<Key>>
+using HashMap = absl::flat_hash_map<Key, Value, Hash>;
+template <typename Value, typename Hash = std::hash<Value>> using HashSet = absl::flat_hash_set<Value, Hash>;
#else
-template <typename Key, typename Value> using HashMap = absl::flat_hash_map<Key, Value>;
-template <typename Value> using HashSet = absl::flat_hash_set<Value>;
+template <typename Key, typename Value, typename Hash = std::hash<Key>>
+using HashMap = std::unordered_map<Key, Value, Hash>;
+template <typename Value, typename Hash = std::hash<Value>> using HashSet = std::unordered_set<Value, Hash>;
#endif
}; // namespace HashTables
+struct PairHash
+{
+ template <typename T1, typename T2> std::size_t operator()(const std::pair<T1, T2> &idp) const noexcept
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, std::hash<T1>()(idp.first));
+ boost::hash_combine(seed, std::hash<T2>()(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::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString>>
-{
- std::size_t operator()(
- const std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString> &idp) const noexcept
- {
- std::size_t seed = 0;
- boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(idp.first));
- boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(idp.second));
- return seed;
- }
-};
-
-template <> struct hash<std::pair<int, NEXTPNR_NAMESPACE_PREFIX BelId>>
-{
- std::size_t operator()(const std::pair<int, NEXTPNR_NAMESPACE_PREFIX BelId> &idp) const noexcept
- {
- std::size_t seed = 0;
- boost::hash_combine(seed, hash<int>()(idp.first));
- boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX BelId>()(idp.second));
- return seed;
- }
-};
-#if !defined(ARCH_GOWIN)
-template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX BelId>>
-{
- std::size_t
- operator()(const std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX BelId> &idp) const noexcept
- {
- std::size_t seed = 0;
- boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(idp.first));
- boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX BelId>()(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<IdString, std::unordered_map<BelId, delay_t>> cumul_costs;
- std::unordered_map<std::pair<IdString, BelId>, std::pair<IdString, BelId>> backtrace;
+ std::unordered_map<std::pair<IdString, BelId>, std::pair<IdString, BelId>, PairHash> backtrace;
std::queue<std::pair<int, BelId>> visit;
- std::unordered_set<std::pair<int, BelId>> to_visit;
+ std::unordered_set<std::pair<int, BelId>, 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<IdString, std::unordered_set<BelId>> cell_neighbour_bels;
std::unordered_map<BelId, std::unordered_set<IdString>> bel_candidate_cells;
// Map cell ports to net delay limit
- std::unordered_map<std::pair<IdString, IdString>, delay_t> max_net_delay;
+ std::unordered_map<std::pair<IdString, IdString>, 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<std::pair<IdString, IdString>, const CellParameterPOD *> parameters;
+ HashTables::HashMap<std::pair<IdString, IdString>, 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<std::pair<int32_t, int32_t>, delay_t> &delays)
+ const HashTables::HashMap<std::pair<int32_t, int32_t>, 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<std::pair<int32_t, int32_t>, delay_t> &delays);
+ const HashTables::HashMap<std::pair<int32_t, int32_t>, 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<TypeWirePair, HashTables::HashMap<std::pair<int32_t, int32_t>, delay_t>> storage;
+ HashTables::HashMap<TypeWirePair, HashTables::HashMap<std::pair<int32_t, int32_t>, 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<TypeWirePair, HashTables::HashMap<std::pair<int32_t, int32_t>, delay_t>> &type_pair) {
+ [&](const std::pair<TypeWirePair, HashTables::HashMap<std::pair<int32_t, int32_t>, 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<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>> possibles_sites_for_pip;
+ 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;
};
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<std::pair<IdString, IdString>> *blocked_wires)
+ HashTables::HashSet<std::pair<IdString, IdString>, PairHash> *blocked_wires)
{
const Context *ctx = site_info.ctx;
const std::vector<LutElement> &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<std::pair<IdString, IdString>> &blocked_wires)
+ const HashTables::HashSet<std::pair<IdString, IdString>, 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<std::pair<IdString, IdString>> blocked_wires;
+ HashTables::HashSet<std::pair<IdString, IdString>, 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<std::pair<IdString, IdString>> blocked_wires;
+ HashTables::HashSet<std::pair<IdString, IdString>, 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})