Hash table refactoring
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
2912860c97
commit
4e346ecfba
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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})
|
||||
|
Loading…
Reference in New Issue
Block a user