diff options
31 files changed, 610 insertions, 440 deletions
diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h index e25f985a3e0..0aa437b227c 100644 --- a/src/lib/netlist/analog/nlid_twoterm.h +++ b/src/lib/netlist/analog/nlid_twoterm.h @@ -57,7 +57,7 @@ namespace netlist::analog auto *h = dynamic_cast<core_device_t *>(&d1); return b ? *h : d2; } - template<> + template <> inline core_device_t &bselect(bool b, [[maybe_unused]] netlist_state_t &d1, core_device_t &d2) { if (b) diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index 7bf75f85a87..979df4a16ea 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -304,8 +304,8 @@ clang: -Wno-exit-time-destructors -Winconsistent-missing-destructor-override \ -Wno-embedded-directive \ -Wno-undefined-reinterpret-cast \ - -Wunreachable-code \ - -Wmissing-prototypes" + -Wunreachable-code -Wno-gnu-alignof-expression \ + -Wmissing-prototypes -Wno-error=deprecated" clang-libc: #clang-11 currently broken diff --git a/src/lib/netlist/core/base_objects.h b/src/lib/netlist/core/base_objects.h index 31fb8f8944d..ac392de21e6 100644 --- a/src/lib/netlist/core/base_objects.h +++ b/src/lib/netlist/core/base_objects.h @@ -135,7 +135,7 @@ namespace netlist::detail { const netlist_t & exec() const noexcept { return m_netlist; } // to ease template design - template<typename T, typename... Args> + template <typename T, typename... Args> device_arena::unique_ptr<T> make_pool_object(Args&&... args) { return state().make_pool_object<T>(std::forward<Args>(args)...); diff --git a/src/lib/netlist/core/core_device.h b/src/lib/netlist/core/core_device.h index 2cefb3d4c58..a40a417e414 100644 --- a/src/lib/netlist/core/core_device.h +++ b/src/lib/netlist/core/core_device.h @@ -113,7 +113,7 @@ namespace netlist ~base_device_t() noexcept override = default; - template<class O, class C, typename... Args> + template <class O, class C, typename... Args> void create_and_register_subdevice(O& owner, const pstring &name, device_arena::unique_ptr<C> &dev, Args&&... args) { dev = state().make_pool_object<C>(owner, name, std::forward<Args>(args)...); diff --git a/src/lib/netlist/core/exec.h b/src/lib/netlist/core/exec.h index a47b84df29e..83a41239d91 100644 --- a/src/lib/netlist/core/exec.h +++ b/src/lib/netlist/core/exec.h @@ -44,7 +44,7 @@ namespace netlist const detail::queue_t &queue() const noexcept { return m_queue; } - template<typename... Args> + template <typename... Args> void qpush(Args&&...args) noexcept { if (config::use_queue_stats::value && m_use_stats) diff --git a/src/lib/netlist/core/netlist_state.h b/src/lib/netlist/core/netlist_state.h index 0fb9dab61c9..517dbc36474 100644 --- a/src/lib/netlist/core/netlist_state.h +++ b/src/lib/netlist/core/netlist_state.h @@ -48,7 +48,7 @@ namespace netlist /// virtual ~netlist_state_t() noexcept = default; - template<class C> + template <class C> static bool check_class(core_device_t *p) noexcept { return dynamic_cast<C *>(p) != nullptr; @@ -63,7 +63,7 @@ namespace netlist /// /// \return pointers to device - template<class C> + template <class C> C *get_single_device(const pstring &name) const { return dynamic_cast<C *>(get_single_device(name, check_class<C>)); @@ -75,7 +75,7 @@ namespace netlist /// /// \return vector with pointers to devices - template<class C> + template <class C> std::vector<C *> get_device_list() const { std::vector<C *> tmp; @@ -109,13 +109,13 @@ namespace netlist // state handling plib::state_manager_t &run_state_manager() noexcept { return m_state; } - template<typename O, typename C> + template <typename O, typename C> void save(O &owner, C &state, const pstring &module, const pstring &stname) { this->run_state_manager().save_item(plib::void_ptr_cast(&owner), state, module + "." + stname); } - template<typename O, typename C> + template <typename O, typename C> void save(O &owner, C *state, const pstring &module, const pstring &stname, const std::size_t count) { this->run_state_manager().save_state_ptr(plib::void_ptr_cast(&owner), module + "." + stname, plib::state_manager_t::dtype<C>(), count, state); @@ -208,7 +208,7 @@ namespace netlist family_collection_type &family_cache() { return m_family_cache; } - template<typename T, typename... Args> + template <typename T, typename... Args> device_arena::unique_ptr<T> make_pool_object(Args&&... args) { return plib::make_unique<T>(m_pool, std::forward<Args>(args)...); diff --git a/src/lib/netlist/core/param.h b/src/lib/netlist/core/param.h index 59f51e44d9b..445b309c67b 100644 --- a/src/lib/netlist/core/param.h +++ b/src/lib/netlist/core/param.h @@ -55,7 +55,7 @@ namespace netlist pstring get_initial(const core_device_t *dev, bool *found) const; - template<typename C> + template <typename C> void set_and_update_param(C &p, const C v) noexcept { if (p != v) diff --git a/src/lib/netlist/core/queue.h b/src/lib/netlist/core/queue.h index ea76c6851bc..b4b0c427c83 100644 --- a/src/lib/netlist/core/queue.h +++ b/src/lib/netlist/core/queue.h @@ -27,11 +27,11 @@ namespace netlist::detail { // Use timed_queue_heap to use stdc++ heap functions instead of linear processing. // This slows down processing by about 35% on a Kaby Lake. - // template <class T, bool TS> - // using timed_queue = plib::timed_queue_heap<T, TS>; + // template <class A, class T, bool TS> + // using timed_queue = plib::timed_queue_heap<A, T, TS>; - template <class T, bool TS> - using timed_queue = plib::timed_queue_linear<T, TS>; + template <typename A, typename T, bool TS> + using timed_queue = plib::timed_queue_linear<A, T, TS>; // ----------------------------------------------------------------------------- // queue_t @@ -40,19 +40,19 @@ namespace netlist::detail // We don't need a thread-safe queue currently. Parallel processing of // solvers will update inputs after parallel processing. - template <typename O, bool TS> + template <typename A, typename O, bool TS> class queue_base : - public timed_queue<plib::pqentry_t<netlist_time_ext, O *>, false>, + public timed_queue<A, plib::pqentry_t<netlist_time_ext, O *>, false>, public plib::state_manager_t::callback_t { public: using entry_t = plib::pqentry_t<netlist_time_ext, O *>; - using base_queue = timed_queue<entry_t, false>; + using base_queue = timed_queue<A, entry_t, false>; using id_delegate = plib::pmfp<std::size_t (const O *)>; using obj_delegate = plib::pmfp<O * (std::size_t)>; - explicit queue_base(std::size_t size, id_delegate get_id, obj_delegate get_obj) - : timed_queue<plib::pqentry_t<netlist_time_ext, O *>, false>(size) + explicit queue_base(A &arena, std::size_t size, id_delegate get_id, obj_delegate get_obj) + : timed_queue<A, plib::pqentry_t<netlist_time_ext, O *>, false>(arena, size) , m_qsize(0) , m_times(size) , m_net_ids(size) @@ -103,7 +103,7 @@ namespace netlist::detail obj_delegate m_obj_by_id; }; - using queue_t = queue_base<net_t, false>; + using queue_t = queue_base<device_arena, net_t, false>; } // namespace netlist::detail diff --git a/src/lib/netlist/core/setup.h b/src/lib/netlist/core/setup.h index 896b71a1e15..86f298fc333 100644 --- a/src/lib/netlist/core/setup.h +++ b/src/lib/netlist/core/setup.h @@ -13,7 +13,6 @@ #include "../nl_setup.h" #include "../nltypes.h" -//#include "../plib/ppreprocessor.h" #include "../plib/pstream.h" #include "../plib/pstring.h" diff --git a/src/lib/netlist/core/state_var.h b/src/lib/netlist/core/state_var.h index 118088ca795..253ae832c8a 100644 --- a/src/lib/netlist/core/state_var.h +++ b/src/lib/netlist/core/state_var.h @@ -179,7 +179,7 @@ namespace netlist namespace plib { - template<typename X> + template <typename X> struct ptype_traits<netlist::state_var<X>> : ptype_traits<X> { }; diff --git a/src/lib/netlist/devices/nld_7475.cpp b/src/lib/netlist/devices/nld_7475.cpp index 73b32a34807..afe42e84c70 100644 --- a/src/lib/netlist/devices/nld_7475.cpp +++ b/src/lib/netlist/devices/nld_7475.cpp @@ -38,7 +38,7 @@ namespace netlist::devices { - template<bool HasQQ> + template <bool HasQQ> NETLIB_OBJECT(7475_GATE_BASE) { NETLIB_CONSTRUCTOR(7475_GATE_BASE) diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index 920f4738237..c5d4af6ef8f 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -91,7 +91,7 @@ namespace netlist , m_time(netlist_time_ext::zero()) , m_main_clock(nullptr) , m_use_stats(false) - , m_queue(config::max_queue_size::value, + , m_queue(state.pool(), config::max_queue_size::value, detail::queue_t::id_delegate(&netlist_state_t :: find_net_id, &state), detail::queue_t::obj_delegate(&netlist_state_t :: net_by_id, &state)) { diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index f56b1cc6248..b42cf8c4e23 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -144,9 +144,9 @@ namespace netlist /// using device_arena = std::conditional_t<config::use_mempool::value, - plib::mempool_arena<plib::aligned_arena, config::mempool_align::value>, - plib::aligned_arena>; - using host_arena = plib::aligned_arena; + plib::mempool_arena<plib::aligned_arena<>, config::mempool_align::value>, + plib::aligned_arena<>>; + using host_arena = plib::aligned_arena<>; using log_type = plib::plog_base<NL_DEBUG>; diff --git a/src/lib/netlist/plib/gmres.h b/src/lib/netlist/plib/gmres.h index 4fd3263b2b3..34250c56b55 100644 --- a/src/lib/netlist/plib/gmres.h +++ b/src/lib/netlist/plib/gmres.h @@ -34,16 +34,16 @@ namespace plib static constexpr float value = 0.0; }; - template <typename FT, int SIZE> + template <typename ARENA, typename FT, int SIZE> struct mat_precondition_ILU { - using mat_type = plib::pmatrix_cr<FT, SIZE>; + using mat_type = plib::pmatrix_cr<ARENA, FT, SIZE>; using matLU_type = plib::pLUmatrix_cr<mat_type>; - mat_precondition_ILU(std::size_t size, std::size_t ilu_scale = 4 - , std::size_t bw = plib::pmatrix_cr<FT, SIZE>::FILL_INFINITY) - : m_mat(narrow_cast<typename mat_type::index_type>(size)) - , m_LU(narrow_cast<typename mat_type::index_type>(size)) + mat_precondition_ILU(ARENA &arena, std::size_t size, std::size_t ilu_scale = 4 + , std::size_t bw = plib::pmatrix_cr<ARENA, FT, SIZE>::FILL_INFINITY) + : m_mat(arena, narrow_cast<typename mat_type::index_type>(size)) + , m_LU(arena, narrow_cast<typename mat_type::index_type>(size)) , m_ILU_scale(narrow_cast<std::size_t>(ilu_scale)) , m_band_width(bw) { @@ -57,7 +57,7 @@ namespace plib } - template<typename R, typename V> + template <typename R, typename V> void calc_rhs(R &rhs, const V &v) { m_mat.mult_vec(rhs, v); @@ -68,7 +68,7 @@ namespace plib m_LU.incomplete_LU_factorization(m_mat); } - template<typename V> + template <typename V> void solve_inplace(V &v) { m_LU.solveLU(v); @@ -82,11 +82,11 @@ namespace plib std::size_t m_band_width; }; - template <typename FT, int SIZE> + template <typename ARENA, typename FT, int SIZE> struct mat_precondition_diag { - mat_precondition_diag(std::size_t size, [[maybe_unused]] int dummy = 0) - : m_mat(size) + mat_precondition_diag(ARENA &arena, std::size_t size, [[maybe_unused]] int dummy = 0) + : m_mat(arena, size) , m_diag(size) , nzcol(size) { @@ -110,7 +110,7 @@ namespace plib } } - template<typename R, typename V> + template <typename R, typename V> void calc_rhs(R &rhs, const V &v) { m_mat.mult_vec(rhs, v); @@ -163,19 +163,19 @@ namespace plib } } - template<typename V> + template <typename V> void solve_inplace(V &v) { for (std::size_t i = 0; i< m_diag.size(); i++) v[i] = v[i] * m_diag[i]; } - plib::pmatrix_cr<FT, SIZE> m_mat; + plib::pmatrix_cr<ARENA, FT, SIZE> m_mat; plib::parray<FT, SIZE> m_diag; plib::parray<std::vector<std::size_t>, SIZE > nzcol; }; - template <typename FT, int SIZE> + template <typename ARENA, typename FT, int SIZE> struct mat_precondition_none { mat_precondition_none(std::size_t size, [[maybe_unused]] int dummy = 0) @@ -189,7 +189,7 @@ namespace plib m_mat.build_from_fill_mat(fill, 0); } - template<typename R, typename V> + template <typename R, typename V> void calc_rhs(R &rhs, const V &v) { m_mat.mult_vec(rhs, v); @@ -199,12 +199,12 @@ namespace plib { } - template<typename V> + template <typename V> void solve_inplace([[maybe_unused]] V &v) { } - plib::pmatrix_cr<FT, SIZE> m_mat; + plib::pmatrix_cr<ARENA, FT, SIZE> m_mat; }; // FIXME: hard coding RESTART to 20 becomes an issue on very large diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index eff105e224f..01bc131f926 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -28,94 +28,84 @@ namespace plib { //============================================================ - // aligned types - //============================================================ - -#if 0 -#if (PUSE_ALIGNED_HINTS) - template <typename T, std::size_t A> - using aligned_type __attribute__((aligned(A))) = T; -#else - template <typename T, std::size_t A> - using aligned_type = T; -#endif - - template <typename T, std::size_t A> - using aligned_pointer = aligned_type<T, A> *; - - template <typename T, std::size_t A> - using const_aligned_pointer = const aligned_type<T, A> *; - - template <typename T, std::size_t A> - using aligned_reference = aligned_type<T, A> &; - - template <typename T, std::size_t A> - using const_aligned_reference = const aligned_type<T, A> &; -#endif - //============================================================ // Standard arena_deleter //============================================================ - template <typename P, typename T, bool X> + template <typename P, typename T, std::size_t ALIGN, bool X> struct arena_deleter_base { }; - - template <typename P, typename T> - struct arena_deleter_base<P, T, false> + struct deleter_info_t { - using arena_storage_type = P; + std::size_t alignment; + std::size_t size; + }; - constexpr arena_deleter_base(arena_storage_type *a = nullptr) noexcept - : m_a(a) { } + template <typename P, typename T, std::size_t ALIGN> + struct arena_deleter_base<P, T, ALIGN, false> + { + constexpr arena_deleter_base(P *a = nullptr) noexcept + : m_arena(a), m_info({ALIGN ? ALIGN : alignof(T), sizeof(T)} ) { } template<typename U, typename = - std::enable_if_t<std::is_convertible< U*, T*>::value>> - arena_deleter_base(const arena_deleter_base<P, U, false> &rhs) noexcept - : m_a(rhs.m_a) { } + std::enable_if_t<std::is_convertible_v< U*, T*>>> + constexpr arena_deleter_base(const arena_deleter_base<P, U, ALIGN, false> &rhs) noexcept + : m_arena(rhs.m_arena), m_info(rhs.m_info) { } void operator()(T *p) noexcept { // call destructor p->~T(); - m_a->deallocate(p, sizeof(T)); + m_arena->deallocate(p, m_info.alignment, m_info.size); } - //private: - arena_storage_type *m_a; + + P *m_arena; + deleter_info_t m_info; }; - template <typename P, typename T> - struct arena_deleter_base<P, T, true> + template <typename P, typename T, std::size_t ALIGN> + struct arena_deleter_base<P, T, ALIGN, true> { - using arena_storage_type = P; - - constexpr arena_deleter_base( /*[[maybe_unused]]*/ arena_storage_type *a = nullptr) noexcept + constexpr arena_deleter_base(/*[[maybe_unused]]*/ P *a = nullptr) noexcept + : m_info({ALIGN ? ALIGN : alignof(T), sizeof(T)}) { - // gcc 7.2 (mingw) and 7.5 (ubuntu) don't accept maybe_unused here - plib::unused_var(a); + plib::unused_var(a); // GCC 7.x does not like the maybe_unused } - template<typename U, typename = typename - std::enable_if<std::is_convertible< U*, T*>::value>::type> - arena_deleter_base( /*[[maybe_unused]]*/ const arena_deleter_base<P, U, true> &rhs) noexcept + template<typename U, typename = + std::enable_if_t<std::is_convertible_v< U*, T*>>> + constexpr arena_deleter_base(const arena_deleter_base<P, U, ALIGN, true> &rhs) noexcept + : m_info(rhs.m_info) { - // gcc 7.2 (mingw) and 7.5 (ubuntu) don't accept maybe_unused here - plib::unused_var(rhs); } void operator()(T *p) noexcept { // call destructor p->~T(); - P::deallocate(p, sizeof(T)); + P::deallocate(p, m_info.alignment, m_info.size); } + + deleter_info_t m_info; }; - template <typename P, typename T> - struct arena_deleter : public arena_deleter_base<P, T, P::has_static_deallocator> + + /// + /// \brief alignment aware deleter class + /// + /// The deleter class expects the object to have been allocated with + /// `alignof(T)` alignment if the ALIGN parameter is omitted. If ALIGN is + /// given, this is used. + /// + /// \tparam A Arena type + /// \tparam T Object type + /// \tparam ALIGN alignment + /// + template <typename A, typename T, std::size_t ALIGN = 0> + struct arena_deleter : public arena_deleter_base<A, T, ALIGN, A::has_static_deallocator> { - using base_type = arena_deleter_base<P, T, P::has_static_deallocator>; + using base_type = arena_deleter_base<A, T, ALIGN, A::has_static_deallocator>; using base_type::base_type; }; @@ -143,22 +133,21 @@ namespace plib { { } owned_ptr(pointer p, bool owned, D deleter) - : m_ptr(p), m_deleter(deleter), m_is_owned(owned) + : m_ptr(p), m_deleter(std::move(deleter)), m_is_owned(owned) { } owned_ptr(const owned_ptr &r) = delete; owned_ptr & operator =(owned_ptr &r) = delete; - template<typename DC, typename DC_D> + template <typename DC, typename DC_D> owned_ptr & operator =(owned_ptr<DC, DC_D> &&r) noexcept { if (m_is_owned && (m_ptr != nullptr)) - //delete m_ptr; m_deleter(m_ptr); m_is_owned = r.m_is_owned; m_ptr = r.m_ptr; - m_deleter = r.m_deleter; + m_deleter = std::move(r.m_deleter); r.m_is_owned = false; r.m_ptr = nullptr; return *this; @@ -166,7 +155,7 @@ namespace plib { owned_ptr(owned_ptr &&r) noexcept : m_ptr(r.m_ptr) - , m_deleter(r.m_deleter) + , m_deleter(std::move(r.m_deleter)) , m_is_owned(r.m_is_owned) { r.m_is_owned = false; @@ -176,11 +165,10 @@ namespace plib { owned_ptr &operator=(owned_ptr &&r) noexcept { if (m_is_owned && (m_ptr != nullptr)) - //delete m_ptr; m_deleter(m_ptr); m_is_owned = r.m_is_owned; m_ptr = r.m_ptr; - m_deleter = r.m_deleter; + m_deleter = std::move(r.m_deleter); r.m_is_owned = false; r.m_ptr = nullptr; return *this; @@ -189,7 +177,7 @@ namespace plib { template<typename DC, typename DC_D> owned_ptr(owned_ptr<DC, DC_D> &&r) noexcept : m_ptr(static_cast<pointer >(r.get())) - , m_deleter(r.m_deleter) + , m_deleter(std::move(r.m_deleter)) , m_is_owned(r.is_owned()) { r.release(); @@ -238,20 +226,20 @@ namespace plib { // Arena allocator for use with containers //============================================================ - template <class ARENA, class T, std::size_t ALIGN = alignof(T)> + template <class ARENA, class T, std::size_t ALIGN, bool HSA> class arena_allocator { public: using value_type = T; using pointer = T *; - static /*constexpr*/ const std::size_t align_size = ALIGN; + static constexpr const std::size_t align_size = ALIGN ? ALIGN : alignof(T); using arena_type = ARENA; - static_assert(align_size >= alignof(T), - "ALIGN must be greater than alignof(T) and a multiple"); static_assert((align_size % alignof(T)) == 0, "ALIGN must be greater than alignof(T) and a multiple"); + template <typename U = int, typename = std::enable_if_t<HSA && sizeof(U)>> + //[[deprecated]] arena_allocator() noexcept : m_a(arena_type::instance()) { } @@ -263,12 +251,22 @@ namespace plib { arena_allocator(arena_allocator &&) noexcept = default; arena_allocator &operator=(arena_allocator &&) noexcept = default; - explicit arena_allocator(arena_type & a) noexcept : m_a(a) + template <typename U = int> + arena_allocator(/*[[maybe_unused]]*/ std::enable_if_t<HSA && sizeof(U), arena_type> & a) noexcept + : m_a(arena_type::instance()) { + plib::unused_var(a); // GCC 7.x does not like the maybe_unused } - template <class U> - arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs) noexcept + template <typename U = int> + arena_allocator(/*[[maybe_unused]]*/ std::enable_if_t<!HSA && sizeof(U), arena_type> & a) noexcept + : m_a(a) + { + plib::unused_var(a); // GCC 7.x does not like the maybe_unused + } + + template <class U, typename = std::enable_if_t<!std::is_same<T, U>::value>> + arena_allocator(const arena_allocator<ARENA, U, ALIGN, HSA>& rhs) noexcept : m_a(rhs.m_a) { } @@ -276,17 +274,17 @@ namespace plib { template <class U> struct rebind { - using other = arena_allocator<ARENA, U, ALIGN>; + using other = arena_allocator<ARENA, U, ALIGN, HSA>; }; pointer allocate(std::size_t n) { - return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n)); //NOLINT + return reinterpret_cast<T *>(m_a.allocate(align_size, sizeof(T) * n)); //NOLINT } void deallocate(pointer p, std::size_t n) noexcept { - m_a.deallocate(p, sizeof(T) * n); + m_a.deallocate(p, align_size, sizeof(T) * n); } template<typename U, typename... Args> @@ -302,26 +300,26 @@ namespace plib { p->~U(); } - template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2> - friend bool operator==(const arena_allocator<AR1, T1, A1>& lhs, // NOLINT - const arena_allocator<AR2, T2, A2>& rhs) noexcept; + template <class AR1, class T1, std::size_t A1, bool HSA1, class AR2, class T2, std::size_t A2, bool HSA2> + friend bool operator==(const arena_allocator<AR1, T1, A1, HSA1>& lhs, // NOLINT + const arena_allocator<AR2, T2, A2, HSA2>& rhs) noexcept; - template <class AU, class U, std::size_t A> + template <class AU1, class U1, std::size_t A1, bool HSA1> friend class arena_allocator; private: arena_type &m_a; }; - template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2> - inline bool operator==(const arena_allocator<AR1, T1, A1>& lhs, - const arena_allocator<AR2, T2, A2>& rhs) noexcept + template <class AR1, class T1, std::size_t A1, bool HSA1, class AR2, class T2, std::size_t A2, bool HSA2> + inline bool operator==(const arena_allocator<AR1, T1, A1, HSA1>& lhs, + const arena_allocator<AR2, T2, A2, HSA2>& rhs) noexcept { return A1 == A2 && rhs.m_a == lhs.m_a; } - template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2> - inline bool operator!=(const arena_allocator<AR1, T1, A1>& lhs, - const arena_allocator<AR2, T2, A2>& rhs) noexcept + template <class AR1, class T1, std::size_t A1, bool HSA1,class AR2, class T2, std::size_t A2, bool HSA2> + inline bool operator!=(const arena_allocator<AR1, T1, A1, HSA1>& lhs, + const arena_allocator<AR2, T2, A2, HSA2>& rhs) noexcept { return !(lhs == rhs); } @@ -330,55 +328,61 @@ namespace plib { // Memory allocation //============================================================ - // MSVC has an issue with SFINAE and overloading resolution. - // A discussion can be found here: - // - // https://stackoverflow.com/questions/31062892/overloading-on-static-in-conjunction-with-sfinae - // - // The previous code compiled with gcc and clang on all platforms and - // compilers apart from MSVC. - - template <typename P, bool HSD, bool HSA> - struct arena_base; + //template <typename P, std::size_t MINALIGN, bool HSD, bool HSA> + //struct arena_base; - template <typename P, bool HSD, bool HSA> + template <typename P, std::size_t MINALIGN, bool HSD, bool HSA> struct arena_core { static constexpr const bool has_static_deallocator = HSD; static constexpr const bool has_static_allocator = HSA; + static constexpr const std::size_t min_align = MINALIGN; using size_type = std::size_t; - template <class T, size_type ALIGN = alignof(T)> - using allocator_type = arena_allocator<P, T, ALIGN>; + template <class T, size_type ALIGN = 0> + using allocator_type = arena_allocator<P, T, (ALIGN < MINALIGN) ? MINALIGN : ALIGN, HSA>; + + template <class T, size_type ALIGN = 0> + using deleter_type = arena_deleter<P, T, (ALIGN < MINALIGN) ? MINALIGN : ALIGN>; - template <class T> - using deleter_type = arena_deleter<P, T>; + template <typename T, size_type ALIGN = 0> + using unique_ptr = std::unique_ptr<T, deleter_type<T, (ALIGN < MINALIGN) ? MINALIGN : ALIGN>>; - template <typename T> - using unique_ptr = std::unique_ptr<T, deleter_type<T>>; + template <typename T, size_type ALIGN = 0> + using owned_ptr = plib::owned_ptr<T, deleter_type<T, (ALIGN < MINALIGN) ? MINALIGN : ALIGN>>; - template <typename T> - using owned_ptr = plib::owned_ptr<T, deleter_type<T>>; + static P &instance() noexcept; - static inline P &instance() noexcept + template <class T, size_type ALIGN = 0> + allocator_type<T, ALIGN> get_allocator() { - static P s_arena; - return s_arena; + return *static_cast<P *>(this); } - friend struct arena_base<P, HSD, HSA>; - private: + protected: size_t m_stat_cur_alloc = 0; size_t m_stat_max_alloc = 0; }; - template <typename P, bool HSD, bool HSA> - struct arena_base : public arena_core<P, HSD, HSA> + template <typename P, std::size_t MINALIGN, bool HSD, bool HSA> + inline P & arena_core<P, MINALIGN, HSD, HSA>::instance() noexcept { - using base_type = arena_core<P, HSD, HSA>; + static P s_arena; + return s_arena; + } + + template <typename P, std::size_t MINALIGN, bool HSD, bool HSA> + struct arena_base : public arena_core<P, MINALIGN, HSD, HSA> + { + using base_type = arena_core<P, MINALIGN, HSD, HSA>; using size_type = typename base_type::size_type; + ~arena_base() + { + //printf("%s %lu %lu %lu\n", typeid(*this).name(), MINALIGN, cur_alloc(), max_alloc()); + } + static size_type cur_alloc() noexcept { return base_type::instance().m_stat_cur_alloc; } static size_type max_alloc() noexcept { return base_type::instance().m_stat_max_alloc; } @@ -395,10 +399,15 @@ namespace plib { } }; - template <typename P> - struct arena_base<P, false, false> : public arena_core<P, false, false> + template <typename P, std::size_t MINALIGN> + struct arena_base<P, MINALIGN, false, false> : public arena_core<P, MINALIGN, false, false> { - using size_type = typename arena_core<P, false, false>::size_type; + using size_type = typename arena_core<P, MINALIGN, false, false>::size_type; + + ~arena_base() + { + //printf("%s %lu %lu %lu\n", typeid(*this).name(), MINALIGN, cur_alloc(), max_alloc()); + } size_type cur_alloc() const noexcept { return this->m_stat_cur_alloc; } size_type max_alloc() const noexcept { return this->m_stat_max_alloc; } @@ -415,12 +424,15 @@ namespace plib { } }; - struct aligned_arena : public arena_base<aligned_arena, true, true> + template <std::size_t MINALIGN> + struct aligned_arena : public arena_base<aligned_arena<MINALIGN>, MINALIGN, true, true> { + using base_type = arena_base<aligned_arena<MINALIGN>, MINALIGN, true, true>; + static inline gsl::owner<void *> allocate( size_t alignment, size_t size ) { - inc_alloc_stat(size); - + base_type::inc_alloc_stat(size); +#if 0 #if (PUSE_ALIGNED_ALLOCATION) #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) return _aligned_malloc(size, alignment); @@ -439,12 +451,16 @@ namespace plib { unused_var(alignment); return ::operator new(size); #endif +#else + return ::operator new(size, std::align_val_t(alignment)); +#endif } - static inline void deallocate(gsl::owner<void *> ptr, size_t size ) noexcept + static inline void deallocate(gsl::owner<void *> ptr, [[maybe_unused]] size_t alignment, size_t size ) noexcept { //unused_var(size); - dec_alloc_stat(size); + base_type::dec_alloc_stat(size); +#if 0 #if (PUSE_ALIGNED_ALLOCATION) #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) @@ -456,6 +472,9 @@ namespace plib { #else ::operator delete(ptr); #endif +#else + ::operator delete(ptr, std::align_val_t(alignment)); +#endif } bool operator ==([[maybe_unused]] const aligned_arena &rhs) const noexcept @@ -465,21 +484,21 @@ namespace plib { }; - struct std_arena : public arena_base<std_arena, true, true> + struct std_arena : public arena_base<std_arena, 0, true, true> { - static inline void *allocate([[maybe_unused]] size_t alignment, size_t size ) + static inline void *allocate(size_t alignment, size_t size ) { inc_alloc_stat(size); - return ::operator new(size); + return ::operator new(size, static_cast<std::align_val_t>(alignment)); } - static inline void deallocate( void *ptr, size_t size ) noexcept + static inline void deallocate( void *ptr, size_t alignment, size_t size ) noexcept { dec_alloc_stat(size); - ::operator delete(ptr); + ::operator delete(ptr, static_cast<std::align_val_t>(alignment)); } - bool operator ==([[maybe_unused]] const aligned_arena &rhs) const noexcept + bool operator ==([[maybe_unused]] const std_arena &rhs) const noexcept { return true; } @@ -487,10 +506,25 @@ namespace plib { namespace detail { - template<typename T, typename ARENA, typename... Args> + /// + /// \brief Create new object T with an aligned memory + /// + /// The create object can be deallocate using \ref free or + /// using the arena_deleter type. This is the specialization for arenas + /// which have no state. + /// + /// \tparam T Object type + /// \tparam ALIGN Alignment of object to be created. If ALIGN equals 0, alignof(T) is used. + /// \tparam ARENA Arena type + /// \tparam Args Argument types + /// + /// \param args Arguments to be passed to constructor + /// + template<typename T, std::size_t ALIGN, typename ARENA, typename... Args> static inline T * alloc(Args&&... args) { - auto *mem = ARENA::allocate(alignof(T), sizeof(T)); + //using alloc_type = typename ARENA :: template allocator_type<T, alignof(T)>; + auto *mem = ARENA::allocate(ALIGN ? ALIGN : alignof(T), sizeof(T)); try { // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) @@ -498,22 +532,37 @@ namespace plib { } catch (...) { - ARENA::deallocate(mem, sizeof(T)); + ARENA::deallocate(mem, ALIGN ? ALIGN : alignof(T), sizeof(T)); throw; } } - template<typename ARENA, typename T> + template<std::size_t ALIGN, typename ARENA, typename T> static inline void free(T *ptr) noexcept { ptr->~T(); - ARENA::deallocate(ptr, sizeof(T)); + ARENA::deallocate(ptr, ALIGN ? ALIGN : alignof(T), sizeof(T)); } - template<typename T, typename ARENA, typename... Args> + /// + /// \brief Create new object T with an aligned memory + /// + /// The create object can be deallocate using \ref free or + /// using the arena_deleter type. This is the specialization for arenas + /// which do have state. + /// + /// \tparam T Object type + /// \tparam ALIGN Alignment of object to be created. If ALIGN equals 0, alignof(T) is used. + /// \tparam ARENA Arena type + /// \tparam Args Argument types + /// + /// \param arena Arena to provide memory + /// \param args Arguments to be passed to constructor + /// + template<typename T, std::size_t ALIGN, typename ARENA, typename... Args> static inline T * alloc(ARENA &arena, Args&&... args) { - auto *mem = arena.allocate(alignof(T), sizeof(T)); + auto *mem = arena.allocate(ALIGN ? ALIGN : alignof(T), sizeof(T)); try { // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) @@ -521,83 +570,135 @@ namespace plib { } catch (...) { - arena.deallocate(mem, sizeof(T)); + arena.deallocate(mem, ALIGN ? ALIGN : alignof(T), sizeof(T)); throw; } } - template<typename ARENA, typename T> + template<std::size_t ALIGN, typename ARENA, typename T> static inline void free(ARENA &arena, T *ptr) noexcept { ptr->~T(); - arena.deallocate(ptr, sizeof(T)); + arena.deallocate(ptr, ALIGN ? ALIGN : alignof(T), sizeof(T)); } } // namespace detail - - template<typename T, typename ARENA, typename... Args> - static inline - std::enable_if_t<ARENA::has_static_allocator, typename ARENA::template unique_ptr<T>> + /// + /// \brief Create new alignment and size aware std::unique_ptr + /// + /// `make_unique` creates a new shared pointer to the object it creates. + /// These version ensure that on deallocation the correct alignment and + /// size is used. Should the unique_ptr be down casted the deleter objects + /// used here track the size and alignment of the object created. + /// + /// std::standard_delete will use size and alignment of the base class. + /// + /// This function is deprecated since it hides the use of arenas. + /// + /// \tparam T Object type + /// \tparam ARENA Arena type + /// \tparam ALIGN Alignment of object to be created. If ALIGN equals 0, alignof(T) is used. + /// \tparam Args Argument types + /// + /// \param args Arguments to be passed to constructor + /// + template<typename T, typename ARENA, std::size_t ALIGN = 0, typename... Args> + //[[deprecated]] + std::enable_if_t<ARENA::has_static_allocator, typename ARENA::template unique_ptr<T, ALIGN>> make_unique(Args&&... args) { - using up_type = typename ARENA::template unique_ptr<T>; - using deleter_type = typename ARENA::template deleter_type<T>; - auto *mem = detail::alloc<T, ARENA>(std::forward<Args>(args)...); + using up_type = typename ARENA::template unique_ptr<T, ALIGN>; + using deleter_type = typename ARENA::template deleter_type<T, ALIGN>; + auto *mem = detail::alloc<T, ALIGN, ARENA>(std::forward<Args>(args)...); return up_type(mem, deleter_type()); } - template<typename T, typename ARENA, typename... Args> - static inline - std::enable_if_t<!ARENA::has_static_allocator, typename ARENA::template unique_ptr<T>> - make_unique(Args&&... args) - { - return make_unique<T>(ARENA::instance(), std::forward<Args>(args)...); - } - - template<typename T, typename ARENA, typename... Args> - static inline - typename ARENA::template unique_ptr<T> + /// + /// \brief Create new alignment and size aware std::unique_ptr + /// + /// `make_unique` creates a new shared pointer to the object it creates. + /// These version ensure that on deallocation the correct alignment and + /// size is used. Should the unique_ptr be down casted the deleter objects + /// used here track the size and alignment of the object created. + /// + /// std::standard_delete will use size and alignment of the base class. + /// + /// \tparam T Object type + /// \tparam ARENA Arena type + /// \tparam ALIGN Alignment of object to be created. If ALIGN equals 0, alignof(T) is used. + /// \tparam Args Argument types + /// + /// \param arena Arena to provide memory + /// \param args Arguments to be passed to constructor + /// + template<typename T, typename ARENA, std::size_t ALIGN = 0, typename... Args> + typename ARENA::template unique_ptr<T, ALIGN> make_unique(ARENA &arena, Args&&... args) { - using up_type = typename ARENA::template unique_ptr<T>; - using deleter_type = typename ARENA::template deleter_type<T>; - auto *mem = detail::alloc<T>(arena, std::forward<Args>(args)...); + using up_type = typename ARENA::template unique_ptr<T, ALIGN>; + using deleter_type = typename ARENA::template deleter_type<T, ALIGN>; + auto *mem = detail::alloc<T, ALIGN>(arena, std::forward<Args>(args)...); return up_type(mem, deleter_type(&arena)); } - template<typename T, typename ARENA, typename... Args> - static inline - std::enable_if_t<ARENA::has_static_allocator, typename ARENA::template owned_ptr<T>> + /// + /// \brief Create new alignment and size aware plib::owned_ptr + /// + /// `make_unique` creates a new shared pointer to the object it creates. + /// These version ensure that on deallocation the correct alignment and + /// size is used. Should the unique_ptr be down casted the deleter objects + /// used here track the size and alignment of the object created. + /// + /// std::standard_delete will use size and alignment of the base class. + /// + /// This function is deprecated since it hides the use of arenas. + /// + /// \tparam T Object type + /// \tparam ARENA Arena type + /// \tparam ALIGN Alignment of object to be created. If ALIGN equals 0, alignof(T) is used. + /// \tparam Args Argument types + /// + /// \param args Arguments to be passed to constructor + /// + template<typename T, typename ARENA, std::size_t ALIGN = 0, typename... Args> + //[[deprecated]] + std::enable_if_t<ARENA::has_static_allocator, typename ARENA::template owned_ptr<T, ALIGN>> make_owned(Args&&... args) { - using op_type = typename ARENA::template owned_ptr<T>; - using deleter_type = typename ARENA::template deleter_type<T>; - auto *mem = detail::alloc<T, ARENA>(std::forward<Args>(args)...); + using op_type = typename ARENA::template owned_ptr<T, ALIGN>; + using deleter_type = typename ARENA::template deleter_type<T, ALIGN>; + auto *mem = detail::alloc<T, ALIGN, ARENA>(std::forward<Args>(args)...); return op_type(mem, true, deleter_type()); } - template<typename T, typename ARENA, typename... Args> - static inline - std::enable_if_t<!ARENA::has_static_allocator, typename ARENA::template owned_ptr<T>> - make_owned(Args&&... args) - { - return make_owned<T>(ARENA::instance(), std::forward<Args>(args)...); - } - - template<typename T, typename ARENA, typename... Args> - static inline typename ARENA::template owned_ptr<T> make_owned(ARENA &arena, Args&&... args) + /// + /// \brief Create new alignment and size aware plib::owned_ptr + /// + /// `make_unique` creates a new shared pointer to the object it creates. + /// These version ensure that on deallocation the correct alignment and + /// size is used. Should the unique_ptr be down casted the deleter objects + /// used here track the size and alignment of the object created. + /// + /// std::standard_delete will use size and alignment of the base class. + /// + /// \tparam T Object type + /// \tparam ARENA Arena type + /// \tparam ALIGN Alignment of object to be created. If ALIGN equals 0, alignof(T) is used. + /// \tparam Args Argument types + /// + /// \param arena Arena to provide memory + /// \param args Arguments to be passed to constructor + /// + template<typename T, typename ARENA, std::size_t ALIGN = 0, typename... Args> + typename ARENA::template owned_ptr<T> make_owned(ARENA &arena, Args&&... args) { - using op_type = typename ARENA::template owned_ptr<T>; - using deleter_type = typename ARENA::template deleter_type<T>; - auto *mem = detail::alloc<T>(arena, std::forward<Args>(args)...); + using op_type = typename ARENA::template owned_ptr<T, ALIGN>; + using deleter_type = typename ARENA::template deleter_type<T, ALIGN>; + auto *mem = detail::alloc<T, ALIGN>(arena, std::forward<Args>(args)...); return op_type(mem, true, deleter_type(&arena)); } - - template <class T, std::size_t ALIGN = alignof(T)> - using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>; - //============================================================ // traits to determine alignment size and stride size // from types supporting alignment @@ -627,46 +728,78 @@ namespace plib { struct align_traits : public align_traits_base<T, has_align<T>::value> {}; - template <typename BASEARENA = aligned_arena, std::size_t PG_SIZE = 1024> - class paged_arena : public arena_base<paged_arena<BASEARENA, PG_SIZE>, true, true> + /// + /// \brief Force BASEARENA to align memory allocations on page boundaries + /// + /// \tparam BASEARENA The base arena to use (optional, defaults to aligned_arena) + /// \tparam PG_SIZE The page size to use (optional, defaults to 1024) + /// + template <template<std::size_t> class BASEARENA = aligned_arena, std::size_t PG_SIZE = 1024> + using paged_arena = BASEARENA<PG_SIZE>; + + /// + /// \brief Helper class to create arena versions of standard library sequences + /// + /// \ref arena_vector on how to use this class + /// + /// \tparam A Arena typeThe base arena to use (optional, defaults to aligned_arena) + /// \tparam T Object type of objects in sequence + /// \tparam S Sequence, e.g. std::vector, std::list + /// \tparam ALIGN Alignment to use + /// + template <typename A, typename T, template <typename, typename> class S, std::size_t ALIGN = PALIGN_VECTOROPT> + class arena_sequence : public S<T, typename A::template allocator_type<T, ALIGN>> { public: - paged_arena() = default; + using arena_allocator_type = typename A::template allocator_type<T, ALIGN>; + using arena_sequence_base = S<T, arena_allocator_type>; + using arena_sequence_base::arena_sequence_base; - PCOPYASSIGNMOVE(paged_arena, delete) + using size_type = typename arena_sequence_base::size_type; - ~paged_arena() = default; - - static void *allocate([[maybe_unused]] size_t align, size_t size) + arena_sequence(A &arena) + : arena_sequence_base(seq_alloc(arena)) { - //size = ((size + PG_SIZE - 1) / PG_SIZE) * PG_SIZE; - return arena().allocate(PG_SIZE, size); } - static void deallocate(void *ptr, size_t size) noexcept + arena_sequence(A &arena, size_type n) + : arena_sequence_base(n, seq_alloc(arena)) { - //size = ((size + PG_SIZE - 1) / PG_SIZE) * PG_SIZE; - arena().deallocate(ptr, size); } - bool operator ==(const paged_arena &rhs) const noexcept { return this == &rhs; } - - static BASEARENA &arena() noexcept { static BASEARENA m_arena; return m_arena; } private: + arena_allocator_type seq_alloc(A &arena) const { return arena.template get_allocator<T, ALIGN>(); } }; - //============================================================ - // Aligned vector - //============================================================ - - // FIXME: needs a separate file - template <typename T, std::size_t ALIGN = PALIGN_VECTOROPT, typename A = paged_arena<>>//aligned_arena> - class aligned_vector : public std::vector<T, typename A::template allocator_type<T, ALIGN>> + /// + /// \brief Vector with arena allocations + /// + /// The Vector allocation will use the arena of type A of which an instance + /// has to be passed to the constructor. Should the minimum alignment exceed + /// the object size, min_align / sizeof(T) elements are reserved. + /// + /// \tparam A Arena type + /// \tparam T Object type of objects in sequence + /// \tparam ALIGN Alignment to use + /// + template <typename A, typename T, std::size_t ALIGN = PALIGN_VECTOROPT> + class arena_vector : public arena_sequence<A, T, std::vector, ALIGN> { public: - using base = std::vector<T, typename A::template allocator_type<T, ALIGN>>; + using arena_vector_base = arena_sequence<A, T, std::vector, ALIGN>; + using arena_vector_base::arena_vector_base; - using base::base; + /// + /// \brief Constructor + /// + /// \param arena Arena instance to use + /// + arena_vector(A &arena) + : arena_vector_base(arena) + { + if (A::min_align / sizeof(T) > 0) + this->reserve(A::min_align / sizeof(T)); + } }; diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h index 97f7a0d9e99..81c56f36691 100644 --- a/src/lib/netlist/plib/parray.h +++ b/src/lib/netlist/plib/parray.h @@ -52,7 +52,7 @@ namespace plib { /// I consider > 10% performance difference to be a use case. /// - template <typename FT, int SIZE, typename ARENA = aligned_arena> + template <typename FT, int SIZE, typename ARENA = aligned_arena<>> struct parray { public: diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h index 629d7573239..e245e955665 100644 --- a/src/lib/netlist/plib/pchrono.h +++ b/src/lib/netlist/plib/pchrono.h @@ -184,7 +184,7 @@ namespace plib { }; - template< typename T, bool enabled_ = true> + template <typename T, bool enabled_ = true> struct timer { using type = typename T::type; @@ -269,10 +269,10 @@ namespace plib { // Performance tracking //============================================================ - template<bool enabled_> + template <bool enabled_> using pperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, enabled_>; - template<bool enabled_> + template <bool enabled_> using pperfcount_t = plib::chrono::counter<enabled_>; } // namespace plib diff --git a/src/lib/netlist/plib/pmatrix2d.h b/src/lib/netlist/plib/pmatrix2d.h index 9fc816f118b..baed05c76fa 100644 --- a/src/lib/netlist/plib/pmatrix2d.h +++ b/src/lib/netlist/plib/pmatrix2d.h @@ -17,7 +17,7 @@ namespace plib { - template<typename T, typename A = aligned_arena> + template<typename A, typename T> class pmatrix2d { public: @@ -35,13 +35,13 @@ namespace plib using pointer = T *; using const_pointer = const T *; - pmatrix2d() noexcept - : m_N(0), m_M(0), m_stride(8), m_v(nullptr) + pmatrix2d(A &arena) noexcept + : m_N(0), m_M(0), m_stride(8), m_v(nullptr), m_a(arena) { } - pmatrix2d(size_type N, size_type M) - : m_N(N), m_M(M), m_v() + pmatrix2d(A &arena, size_type N, size_type M) + : m_N(N), m_M(M), m_v(), m_a(arena) { gsl_Expects(N>0); gsl_Expects(M>0); @@ -136,25 +136,26 @@ namespace plib }; // variable row length matrix - template<typename T, typename A = aligned_arena> + template<typename A, typename T> class pmatrix2d_vrl { public: using size_type = std::size_t; using value_type = T; using arena_type = A; + using allocator_type = typename A::template allocator_type<T, PALIGN_VECTOROPT>; static constexpr const size_type align_size = align_traits<allocator_type>::align_size; static constexpr const size_type stride_size = align_traits<allocator_type>::stride_size; - pmatrix2d_vrl() noexcept - : m_N(0), m_M(0), m_v() + pmatrix2d_vrl(A &arena) noexcept + : m_N(0), m_M(0), m_row(arena), m_v(arena) { } - pmatrix2d_vrl(size_type N, size_type M) - : m_N(N), m_M(M), m_v() + pmatrix2d_vrl(A &arena, size_type N, size_type M) + : m_N(N), m_M(M), m_row(arena), m_v(arena) { m_row.resize(N + 1, 0); m_v.resize(N); //FIXME @@ -237,8 +238,8 @@ namespace plib size_type m_N; size_type m_M; - std::vector<size_type, typename A::template allocator_type<size_type>> m_row; - std::vector<T, allocator_type> m_v; + plib::arena_vector<A, size_type, PALIGN_VECTOROPT> m_row; + plib::arena_vector<A, T, PALIGN_VECTOROPT> m_v; }; diff --git a/src/lib/netlist/plib/pmatrix_cr.h b/src/lib/netlist/plib/pmatrix_cr.h index 0456190bb1b..3fa4cd84aca 100644 --- a/src/lib/netlist/plib/pmatrix_cr.h +++ b/src/lib/netlist/plib/pmatrix_cr.h @@ -26,7 +26,7 @@ namespace plib { - template<typename T, int N, typename C = uint16_t> + template<typename ARENA, typename T, int N, typename C = uint16_t> struct pmatrix_cr { using index_type = C; @@ -38,7 +38,7 @@ namespace plib pmatrix_cr(const pmatrix_cr &) = default; pmatrix_cr &operator=(const pmatrix_cr &) = default; pmatrix_cr(pmatrix_cr &&) noexcept(std::is_nothrow_move_constructible<parray<value_type, NSQ>>::value) = default; - pmatrix_cr &operator=(pmatrix_cr &&) noexcept(std::is_nothrow_move_assignable<parray<value_type, NSQ>>::value && std::is_nothrow_move_assignable<pmatrix2d_vrl<index_type>>::value) = default; + pmatrix_cr &operator=(pmatrix_cr &&) noexcept(std::is_nothrow_move_assignable<parray<value_type, NSQ>>::value && std::is_nothrow_move_assignable<pmatrix2d_vrl<ARENA, index_type>>::value) = default; enum constants_e { @@ -57,14 +57,14 @@ namespace plib // NOLINTNEXTLINE std::size_t nz_num; - explicit pmatrix_cr(std::size_t n) + explicit pmatrix_cr(ARENA &arena, std::size_t n) : diag(n) , row_idx(n+1) , col_idx(n*n) , A(n*n) , nz_num(0) //, nzbd(n * (n+1) / 2) - , m_nzbd(n, n) + , m_nzbd(arena, n, n) , m_size(n) { for (std::size_t i=0; i<n+1; i++) @@ -237,7 +237,7 @@ namespace plib // FIXME: this should be private // NOLINTNEXTLINE //parray<std::vector<index_type>, N > m_nzbd; // Support for gaussian elimination - pmatrix2d_vrl<index_type> m_nzbd; // Support for gaussian elimination + pmatrix2d_vrl<ARENA, index_type> m_nzbd; // Support for gaussian elimination private: //parray<C, N < 0 ? -N * (N-1) / 2 : N * (N+1) / 2 > nzbd; // Support for gaussian elimination std::size_t m_size; @@ -254,8 +254,9 @@ namespace plib pGEmatrix_cr(pGEmatrix_cr &&) noexcept(std::is_nothrow_move_constructible<base_type>::value) = default; pGEmatrix_cr &operator=(pGEmatrix_cr &&) noexcept(std::is_nothrow_move_assignable<base_type>::value) = default; - explicit pGEmatrix_cr(std::size_t n) - : B(n) + template<typename ARENA> + explicit pGEmatrix_cr(ARENA &arena, std::size_t n) + : B(arena, n) { } @@ -491,8 +492,9 @@ namespace plib pLUmatrix_cr(pLUmatrix_cr &&) noexcept(std::is_nothrow_move_constructible<base_type>::value) = default; pLUmatrix_cr &operator=(pLUmatrix_cr &&) noexcept(std::is_nothrow_move_assignable<base_type>::value) = default; - explicit pLUmatrix_cr(std::size_t n) - : B(n) + template<typename ARENA> + explicit pLUmatrix_cr(ARENA &arena, std::size_t n) + : B(arena, n) , ilu_rows(n+1) , m_ILUp(0) { diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h index 877e9d906bd..29712601237 100644 --- a/src/lib/netlist/plib/pmempool.h +++ b/src/lib/netlist/plib/pmempool.h @@ -28,127 +28,38 @@ namespace plib { //============================================================ template <typename BASEARENA, std::size_t MINALIGN = PALIGN_MIN_SIZE> - class mempool_arena : public arena_base<mempool_arena<BASEARENA, MINALIGN>, false, false> + class mempool_arena : public arena_base<mempool_arena<BASEARENA, MINALIGN>, MINALIGN, false, false> { public: using size_type = typename BASEARENA::size_type; - using base_type = arena_base<mempool_arena<BASEARENA, MINALIGN>, false, false>; + using base_type = arena_base<mempool_arena<BASEARENA, MINALIGN>, MINALIGN, false, false>; + template <class T> using base_allocator_type = typename BASEARENA::template allocator_type<T>; + using block_align = std::integral_constant<size_t, 1024>; - mempool_arena(size_t min_align = MINALIGN, size_t min_alloc = (1<<21)) - : m_min_alloc(min_alloc) - , m_min_align(min_align) - , m_block_align(1024) - , m_blocks(base_allocator_type<block *>(m_arena)) - { - } + mempool_arena(size_t min_alloc = (1<<21)); PCOPYASSIGNMOVE(mempool_arena, delete) - ~mempool_arena() - { - for (auto & b : m_blocks) - { - if (b->m_num_alloc != 0) - { - plib::perrlogger("Found {} info blocks\n", m_info.size()); - plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc); - } - detail::free(m_arena, b); - } - if (!m_info.empty()) - plib::perrlogger("Still found {} info blocks after mempool deleted\n", m_info.size()); - } + ~mempool_arena(); - void *allocate(size_t align, size_t size) - { - block *b = nullptr; - - if (align < m_min_align) - align = m_min_align; + void *allocate(size_t align, size_t size); - size_t rs = size + align; - - for (auto &bs : m_blocks) - { - if (bs->m_free > rs) - { - b = bs; - break; - } - } - if (b == nullptr) - { - b = new_block(rs); - } - b->m_free -= rs; - b->m_num_alloc++; - void *ret = reinterpret_cast<void *>(b->m_data + b->m_cur); // NOLINT(cppcoreguidelines-pro-type-reinterpret - auto capacity(rs); - ret = std::align(align, size, ret, capacity); - m_info.insert({ ret, info(b, b->m_cur)}); - rs -= (capacity - size); - b->m_cur += rs; - this->inc_alloc_stat(size); - - return ret; - } - - void deallocate(void *ptr, size_t size) noexcept - { - auto it = m_info.find(ptr); - if (it == m_info.end()) - plib::terminate("mempool::free - pointer not found"); - block *b = it->second.m_block; - if (b->m_num_alloc == 0) - plib::terminate("mempool::free - double free was called"); - else - { - mempool_arena &mp = b->m_mempool; - b->m_num_alloc--; - mp.dec_alloc_stat(size); - if (b->m_num_alloc == 0) - { - auto itb = std::find(mp.m_blocks.begin(), mp.m_blocks.end(), b); - if (itb == mp.m_blocks.end()) - plib::terminate("mempool::free - block not found"); - - mp.m_blocks.erase(itb); - detail::free(mp.base_arena(), b); - } - m_info.erase(it); - } - } + void deallocate(void *ptr, std::size_t alignment, size_t size) noexcept; bool operator ==(const mempool_arena &rhs) const noexcept { return this == &rhs; } - BASEARENA &base_arena() noexcept { return m_arena; } private: struct block { - block(mempool_arena &mp, size_type min_bytes) - : m_num_alloc(0) - , m_cur(0) - , m_data(nullptr) - , m_mempool(mp) - { - min_bytes = std::max(mp.m_min_alloc, min_bytes); - m_free = min_bytes; - m_bytes_allocated = (min_bytes + mp.m_block_align); // - 1); // & ~(mp.m_min_align - 1); - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - //m_data_allocated = new std::uint8_t[alloc_bytes]; - m_data_allocated = static_cast<std::uint8_t *>(mp.base_arena().allocate(mp.m_block_align, m_bytes_allocated)); - void *r = m_data_allocated; - std::align(mp.m_block_align, min_bytes, r, m_bytes_allocated); - m_data = reinterpret_cast<std::uint8_t *>(r); // NOLINT(cppcoreguidelines-pro-type-reinterpret - } + block(mempool_arena &mp, size_type min_bytes); ~block() { //::operator delete(m_data_allocated); //delete [] m_data_allocated; - m_mempool.base_arena().deallocate(m_data_allocated, m_bytes_allocated); + m_mempool.base_arena().deallocate(m_data_allocated, mempool_arena::block_align(), m_bytes_allocated); } block(const block &) = delete; @@ -167,7 +78,7 @@ namespace plib { struct info { - info(block *b, size_type p) : m_block(b), m_pos(p) { } + info(block *b, size_type p, size_type orig_size) : m_block(b), m_pos(p), m_orig_size(orig_size) { } info(const info &) = default; info &operator=(const info &) = default; info(info &&) noexcept = default; @@ -176,28 +87,137 @@ namespace plib { block * m_block; size_type m_pos; + size_type m_orig_size; }; block * new_block(size_type min_bytes) { - auto *b = detail::alloc<block>(m_arena, *this, min_bytes); + auto *b = detail::alloc<block, 0>(base_arena(), *this, min_bytes); m_blocks.push_back(b); return b; } size_t m_min_alloc; - size_t m_min_align; - size_t m_block_align; - BASEARENA m_arena; + static BASEARENA &base_arena() + { + static BASEARENA s_arena; + return s_arena; + } + + using info_type = std::pair<void * const, info>; - using base_allocator_typex = typename BASEARENA::template allocator_type<std::pair<void * const, info>>; + using info_allocator_type = typename BASEARENA::template allocator_type<info_type>; std::unordered_map<void *, info, std::hash<void *>, std::equal_to<>, - base_allocator_typex> m_info; -// std::unordered_map<void *, info> m_info; - std::vector<block *, typename BASEARENA::template allocator_type<block *>> m_blocks; + info_allocator_type> m_info; + + plib::arena_vector<BASEARENA, block *> m_blocks; }; + template <typename BASEARENA, std::size_t MINALIGN> + mempool_arena<BASEARENA, MINALIGN>::mempool_arena(size_t min_alloc) + : m_min_alloc(min_alloc) + //, m_blocks(base_allocator_type<block *>(base_arena())) + , m_blocks(base_arena()) + { + } + + template <typename BASEARENA, std::size_t MINALIGN> + mempool_arena<BASEARENA, MINALIGN>::~mempool_arena() + { + for (auto & b : m_blocks) + { + if (b->m_num_alloc != 0) + { + plib::perrlogger("Found {} info blocks\n", m_info.size()); + plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc); + } + detail::free<0>(base_arena(), b); + } + if (!m_info.empty()) + plib::perrlogger("Still found {} info blocks after mempool deleted\n", m_info.size()); + } + + template <typename BASEARENA, std::size_t MINALIGN> + void * mempool_arena<BASEARENA, MINALIGN>::allocate(size_t align, size_t size) + { + block *b = nullptr; + + if (align < MINALIGN) + align = MINALIGN; + + size_t rs = size + align; + + for (auto &bs : m_blocks) + { + if (bs->m_free > rs) + { + b = bs; + break; + } + } + if (b == nullptr) + { + b = new_block(rs); + } + b->m_free -= rs; + b->m_num_alloc++; + void *ret = reinterpret_cast<void *>(b->m_data + b->m_cur); // NOLINT(cppcoreguidelines-pro-type-reinterpret + auto capacity(rs); + ret = std::align(align, size, ret, capacity); + m_info.insert({ ret, info(b, b->m_cur, size)}); + rs -= (capacity - size); + b->m_cur += rs; + this->inc_alloc_stat(size); + + return ret; + } + + template <typename BASEARENA, std::size_t MINALIGN> + void mempool_arena<BASEARENA, MINALIGN>::deallocate(void *ptr, [[maybe_unused]] std::size_t alignment, size_t size) noexcept + { + auto it = m_info.find(ptr); + if (it == m_info.end()) + plib::terminate("mempool::free - pointer not found"); + block *b = it->second.m_block; + if (b->m_num_alloc == 0) + plib::terminate("mempool::free - double free was called"); + if (it->second.m_orig_size != size) + plib::perrlogger("Size mismatch original {} vs {}\n", it->second.m_orig_size, size); + + mempool_arena &mp = b->m_mempool; + b->m_num_alloc--; + mp.dec_alloc_stat(size); + if (b->m_num_alloc == 0) + { + auto itb = std::find(mp.m_blocks.begin(), mp.m_blocks.end(), b); + if (itb == mp.m_blocks.end()) + plib::terminate("mempool::free - block not found"); + + mp.m_blocks.erase(itb); + detail::free<0>(mp.base_arena(), b); + } + m_info.erase(it); + } + + template <typename BASEARENA, std::size_t MINALIGN> + mempool_arena<BASEARENA, MINALIGN>::block::block(mempool_arena &mp, size_type min_bytes) + : m_num_alloc(0) + , m_cur(0) + , m_data(nullptr) + , m_mempool(mp) + { + min_bytes = std::max(mp.m_min_alloc, min_bytes); + m_free = min_bytes; + m_bytes_allocated = (min_bytes + mempool_arena::block_align()); // - 1); // & ~(mp.m_min_align - 1); + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + //m_data_allocated = new std::uint8_t[alloc_bytes]; + m_data_allocated = static_cast<std::uint8_t *>(mp.base_arena().allocate(mempool_arena::block_align(), m_bytes_allocated)); + void *r = m_data_allocated; + std::align(mempool_arena::block_align(), min_bytes, r, m_bytes_allocated); + m_data = reinterpret_cast<std::uint8_t *>(r); // NOLINT(cppcoreguidelines-pro-type-reinterpret + } + } // namespace plib #endif // PMEMPOOL_H_ diff --git a/src/lib/netlist/plib/ptimed_queue.h b/src/lib/netlist/plib/ptimed_queue.h index ad44c0d432f..49bdd6db1a9 100644 --- a/src/lib/netlist/plib/ptimed_queue.h +++ b/src/lib/netlist/plib/ptimed_queue.h @@ -75,13 +75,13 @@ namespace plib { }; // Use TS = true for a threadsafe queue - template <class T, bool TS> + template <class A, class T, bool TS> class timed_queue_linear { public: - explicit timed_queue_linear(const std::size_t list_size) - : m_list(list_size) + explicit timed_queue_linear(A &arena, const std::size_t list_size) + : m_list(arena, list_size) { clear(); } @@ -195,7 +195,7 @@ namespace plib { mutex_type m_lock; T * m_end; - aligned_vector<T> m_list; + plib::arena_vector<A, T> m_list; public: // profiling @@ -205,7 +205,7 @@ namespace plib { pperfcount_t<true> m_prof_remove; // NOLINT }; - template <class T, bool TS> + template <class A, class T, bool TS> class timed_queue_heap { public: @@ -215,8 +215,8 @@ namespace plib { constexpr bool operator()(const T &a, const T &b) const noexcept { return b <= a; } }; - explicit timed_queue_heap(const std::size_t list_size) - : m_list(list_size) + explicit timed_queue_heap(A &arena, const std::size_t list_size) + : m_list(arena, list_size) { clear(); } @@ -292,9 +292,9 @@ namespace plib { using mutex_type = pspin_mutex<TS>; using lock_guard_type = std::lock_guard<mutex_type>; - mutex_type m_lock; - T * m_end; - aligned_vector<T> m_list; + mutex_type m_lock; + T * m_end; + plib::arena_vector<A, T> m_list; public: // profiling diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h index 815b4c8e404..9bb7ae3923e 100644 --- a/src/lib/netlist/plib/ptypes.h +++ b/src/lib/netlist/plib/ptypes.h @@ -47,7 +47,9 @@ namespace plib template <typename BASEARENA, std::size_t MINALIGN> class mempool_arena; + template <std::size_t MINALLOC = 0> struct aligned_arena; + class dynlib_base; template<bool debug_enabled> diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp index f807fd82d85..11fc9e7f739 100644 --- a/src/lib/netlist/prg/nlwav.cpp +++ b/src/lib/netlist/prg/nlwav.cpp @@ -27,7 +27,7 @@ // http://de.wikipedia.org/wiki/RIFF_WAVE // -using arena = plib::aligned_arena; +using arena = plib::aligned_arena<>; class wav_t { diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index 8403666f61e..4188070b099 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -16,8 +16,13 @@ namespace netlist::solver { - terms_for_net_t::terms_for_net_t(analog_net_t * net) - : m_net(net) + terms_for_net_t::terms_for_net_t(arena_type &arena, analog_net_t * net) + : m_nz(arena) + , m_nzrd(arena) + , m_nzbd(arena) + , m_connected_net_idx(arena) + , m_terms(arena) + , m_net(net) , m_rail_start(0) { } @@ -47,6 +52,10 @@ namespace netlist::solver const solver::solver_parameters_t *params) : device_t(static_cast<device_t &>(main_solver), name) , m_params(*params) + , m_gonn(m_arena) + , m_gtn(m_arena) + , m_Idrn(m_arena) + , m_connected_net_Vn(m_arena) , m_iterative_fail(*this, "m_iterative_fail", 0) , m_iterative_total(*this, "m_iterative_total", 0) , m_main_solver(main_solver) @@ -55,6 +64,9 @@ namespace netlist::solver , m_stat_newton_raphson_fail(*this, "m_stat_newton_raphson_fail", 0) , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0) , m_last_step(*this, "m_last_step", netlist_time_ext::zero()) + , m_step_funcs(m_arena) + , m_dynamic_funcs(m_arena) + , m_inps(m_arena) , m_ops(0) { setup_base(this->state().setup(), nets); @@ -84,8 +96,8 @@ namespace netlist::solver for (const auto & net : nets) { - m_terms.emplace_back(net); - m_rails_temp.emplace_back(); + m_terms.emplace_back(m_arena, net); + m_rails_temp.emplace_back(m_arena); } for (std::size_t k = 0; k < nets.size(); k++) diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h index 06bb8dcb1f3..6fd04e49d51 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.h +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -61,6 +61,7 @@ namespace netlist::solver , FLOATQ128 ) + using arena_type = plib::mempool_arena<plib::aligned_arena<>, 1024>; using static_compile_container = std::vector<std::pair<pstring, pstring>>; struct solver_parameter_defaults @@ -178,7 +179,7 @@ namespace netlist::solver class terms_for_net_t { public: - terms_for_net_t(analog_net_t * net = nullptr); + terms_for_net_t(arena_type &arena, analog_net_t * net = nullptr); void clear(); @@ -200,14 +201,14 @@ namespace netlist::solver PALIGNAS_VECTOROPT() - plib::aligned_vector<unsigned> m_nz; //!< all non zero for multiplication - plib::aligned_vector<unsigned> m_nzrd; //!< non zero right of the diagonal for elimination, may include RHS element - plib::aligned_vector<unsigned> m_nzbd; //!< non zero below of the diagonal for elimination + plib::arena_vector<arena_type, unsigned> m_nz; //!< all non zero for multiplication + plib::arena_vector<arena_type, unsigned> m_nzrd; //!< non zero right of the diagonal for elimination, may include RHS element + plib::arena_vector<arena_type, unsigned> m_nzbd; //!< non zero below of the diagonal for elimination - plib::aligned_vector<int> m_connected_net_idx; + plib::arena_vector<arena_type, int> m_connected_net_idx; private: + plib::arena_vector<arena_type, terminal_t *> m_terms; analog_net_t * m_net; - plib::aligned_vector<terminal_t *> m_terms; std::size_t m_rail_start; }; @@ -230,8 +231,7 @@ namespace netlist::solver public: using list_t = std::vector<matrix_solver_t *>; using fptype = nl_fptype; - using arena_type = plib::mempool_arena<plib::aligned_arena, PALIGN_VECTOROPT>; - using net_list_t = plib::aligned_vector<analog_net_t *>; + using net_list_t = std::vector<analog_net_t *>; // after every call to solve, update inputs must be called. // this can be done as well as a batch to ease parallel processing. @@ -328,16 +328,17 @@ namespace netlist::solver } const solver_parameters_t &m_params; + arena_type m_arena; - plib::pmatrix2d_vrl<fptype, arena_type> m_gonn; - plib::pmatrix2d_vrl<fptype, arena_type> m_gtn; - plib::pmatrix2d_vrl<fptype, arena_type> m_Idrn; - plib::pmatrix2d_vrl<fptype *, arena_type> m_connected_net_Vn; + plib::pmatrix2d_vrl<arena_type, fptype> m_gonn; + plib::pmatrix2d_vrl<arena_type, fptype> m_gtn; + plib::pmatrix2d_vrl<arena_type, fptype> m_Idrn; + plib::pmatrix2d_vrl<arena_type, fptype *> m_connected_net_Vn; state_var<std::size_t> m_iterative_fail; state_var<std::size_t> m_iterative_total; - plib::aligned_vector<terms_for_net_t> m_terms; // setup only + std::vector<terms_for_net_t> m_terms; // setup only private: @@ -373,13 +374,13 @@ namespace netlist::solver state_var<std::size_t> m_stat_vsolver_calls; state_var<netlist_time_ext> m_last_step; - plib::aligned_vector<nldelegate_ts> m_step_funcs; - plib::aligned_vector<nldelegate_dyn> m_dynamic_funcs; - plib::aligned_vector<device_arena::unique_ptr<proxied_analog_output_t>> m_inps; + plib::arena_vector<arena_type, nldelegate_ts> m_step_funcs; + plib::arena_vector<arena_type, nldelegate_dyn> m_dynamic_funcs; + plib::arena_vector<arena_type, device_arena::unique_ptr<proxied_analog_output_t>> m_inps; std::size_t m_ops; - plib::aligned_vector<terms_for_net_t> m_rails_temp; // setup only + std::vector<terms_for_net_t> m_rails_temp; // setup only }; } // namespace netlist::solver diff --git a/src/lib/netlist/solver/nld_matrix_solver_ext.h b/src/lib/netlist/solver/nld_matrix_solver_ext.h index a77d1a40900..59d81f9cf6e 100644 --- a/src/lib/netlist/solver/nld_matrix_solver_ext.h +++ b/src/lib/netlist/solver/nld_matrix_solver_ext.h @@ -28,7 +28,7 @@ namespace netlist::solver : matrix_solver_t(main_solver, name, nets, params) , m_new_V(size) , m_RHS(size) - , m_mat_ptr(size, this->max_rail_start() + 1) + , m_mat_ptr(m_arena, size, this->max_rail_start() + 1) , m_last_V(size, nlconst::zero()) , m_DD_n_m_1(size, nlconst::zero()) , m_h_n_m_1(size, nlconst::magic(1e-6)) // we need a non zero value here @@ -52,7 +52,7 @@ namespace netlist::solver plib::parray<float_type, SIZE> m_RHS; //PALIGNAS_VECTOROPT() `parray` defines alignment already - plib::pmatrix2d<float_type *> m_mat_ptr; + plib::pmatrix2d<arena_type, float_type *> m_mat_ptr; template <typename T, typename M> void log_fill(const T &fill, [[maybe_unused]] M &mat) diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h index 70ce41782be..552d067e341 100644 --- a/src/lib/netlist/solver/nld_ms_gcr.h +++ b/src/lib/netlist/solver/nld_ms_gcr.h @@ -27,7 +27,7 @@ namespace netlist::solver { public: - using mat_type = plib::pGEmatrix_cr<plib::pmatrix_cr<FT, SIZE>>; + using mat_type = plib::pGEmatrix_cr<plib::pmatrix_cr<arena_type, FT, SIZE>>; using base_type = matrix_solver_ext_t<FT, SIZE>; using fptype = typename base_type::fptype; @@ -35,7 +35,7 @@ namespace netlist::solver const matrix_solver_t::net_list_t &nets, const solver::solver_parameters_t *params, const std::size_t size) : matrix_solver_ext_t<FT, SIZE>(main_solver, name, nets, params, size) - , mat(static_cast<typename mat_type::index_type>(size)) + , mat(this->m_arena, static_cast<typename mat_type::index_type>(size)) , m_proc() { const std::size_t iN = this->size(); @@ -112,7 +112,7 @@ namespace netlist::solver private: - using mat_index_type = typename plib::pmatrix_cr<FT, SIZE>::index_type; + using mat_index_type = typename plib::pmatrix_cr<arena_type, FT, SIZE>::index_type; void generate_code(plib::putf8_fmt_writer &strm); diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h index 8803dda06c8..dd0abf12729 100644 --- a/src/lib/netlist/solver/nld_ms_gmres.h +++ b/src/lib/netlist/solver/nld_ms_gmres.h @@ -37,7 +37,7 @@ namespace netlist::solver const solver::solver_parameters_t *params, const std::size_t size) : matrix_solver_direct_t<FT, SIZE>(main_solver, name, nets, params, size) - , m_ops(size, 0) + , m_ops(this->m_arena, size, 0) , m_gmres(size) { const std::size_t iN = this->size(); @@ -81,10 +81,10 @@ namespace netlist::solver private: - using mattype = typename plib::pmatrix_cr<FT, SIZE>::index_type; + using mattype = typename plib::pmatrix_cr<arena_type, FT, SIZE>::index_type; //plib::mat_precondition_none<FT, SIZE> m_ops; - plib::mat_precondition_ILU<FT, SIZE> m_ops; + plib::mat_precondition_ILU<arena_type, FT, SIZE> m_ops; //plib::mat_precondition_diag<FT, SIZE> m_ops; plib::gmres_t<FT, SIZE> m_gmres; }; diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index f806001332b..8b6fac749ef 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -50,7 +50,7 @@ namespace netlist::devices #if 1 - template<bool KEEP_STATS> + template <bool KEEP_STATS> NETLIB_HANDLER(solver, fb_step) { const netlist_time_ext now(exec().time()); @@ -173,12 +173,12 @@ namespace netlist::devices #endif // FIXME: should be created in device space - template <class C> - NETLIB_NAME(solver)::solver_ptr create_it(NETLIB_NAME(solver) &main_solver, pstring name, + template <class C, class A> + NETLIB_NAME(solver)::solver_ptr create_it(A &arena, NETLIB_NAME(solver) &main_solver, pstring name, NETLIB_NAME(solver)::net_list_t &nets, const solver::solver_parameters_t *params, std::size_t size) { - return plib::make_unique<C, device_arena>(main_solver, name, nets, params, size); + return plib::make_unique<C>(arena, main_solver, name, nets, params, size); } template <typename FT, int SIZE> @@ -189,22 +189,22 @@ namespace netlist::devices switch (params->m_method()) { case solver::matrix_type_e::MAT_CR: - return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(*this, solvername, nets, params, size); + return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(state().pool(), *this, solvername, nets, params, size); case solver::matrix_type_e::MAT: - return create_it<solver::matrix_solver_direct_t<FT, SIZE>>(*this, solvername, nets, params, size); + return create_it<solver::matrix_solver_direct_t<FT, SIZE>>(state().pool(), *this, solvername, nets, params, size); case solver::matrix_type_e::GMRES: - return create_it<solver::matrix_solver_GMRES_t<FT, SIZE>>(*this, solvername, nets, params, size); + return create_it<solver::matrix_solver_GMRES_t<FT, SIZE>>(state().pool(), *this, solvername, nets, params, size); #if (NL_USE_ACADEMIC_SOLVERS) case solver::matrix_type_e::SOR: - return create_it<solver::matrix_solver_SOR_t<FT, SIZE>>(*this, solvername, nets, params, size); + return create_it<solver::matrix_solver_SOR_t<FT, SIZE>>(state().pool(), *this, solvername, nets, params, size); case solver::matrix_type_e::SOR_MAT: - return create_it<solver::matrix_solver_SOR_mat_t<FT, SIZE>>(*this, solvername, nets, params, size); + return create_it<solver::matrix_solver_SOR_mat_t<FT, SIZE>>(state().pool(), *this, solvername, nets, params, size); case solver::matrix_type_e::SM: // Sherman-Morrison Formula - return create_it<solver::matrix_solver_sm_t<FT, SIZE>>(*this, solvername, nets, params, size); + return create_it<solver::matrix_solver_sm_t<FT, SIZE>>(state().pool(), *this, solvername, nets, params, size); case solver::matrix_type_e::W: // Woodbury Formula - return create_it<solver::matrix_solver_w_t<FT, SIZE>>(*this, solvername, nets, params, size); + return create_it<solver::matrix_solver_w_t<FT, SIZE>>(state().pool(), *this, solvername, nets, params, size); #else //case solver::matrix_type_e::GMRES: case solver::matrix_type_e::SOR: @@ -212,7 +212,7 @@ namespace netlist::devices case solver::matrix_type_e::SM: case solver::matrix_type_e::W: state().log().warning(MW_SOLVER_METHOD_NOT_SUPPORTED(params->m_method().name(), "MAT_CR")); - return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(*this, solvername, nets, params, size); + return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(state().pool(), *this, solvername, nets, params, size); #endif } return solver_ptr(); @@ -228,9 +228,9 @@ namespace netlist::devices { #if !defined(__EMSCRIPTEN__) case 1: - return plib::make_unique<solver::matrix_solver_direct1_t<FT>, device_arena>(*this, sname, nets, params); + return plib::make_unique<solver::matrix_solver_direct1_t<FT>>(state().pool(), *this, sname, nets, params); case 2: - return plib::make_unique<solver::matrix_solver_direct2_t<FT>, device_arena>(*this, sname, nets, params); + return plib::make_unique<solver::matrix_solver_direct2_t<FT>>(state().pool(), *this, sname, nets, params); case 3: return create_solver<FT, 3>(3, sname, params, nets); case 4: @@ -437,7 +437,7 @@ namespace netlist::devices { solver_ptr ms; pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size()); - params_uptr params = plib::make_unique<solver::solver_parameters_t, solver_arena>(*this, sname + ".", m_params); + params_uptr params = plib::make_unique<solver::solver_parameters_t>(state().pool(), *this, sname + ".", m_params); switch (params->m_fp_type()) { diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h index 97a995f8d9f..1d8300b8e5d 100644 --- a/src/lib/netlist/solver/nld_solver.h +++ b/src/lib/netlist/solver/nld_solver.h @@ -25,14 +25,14 @@ namespace netlist::devices NETLIB_OBJECT(solver) { public: - using queue_type = detail::queue_base<solver::matrix_solver_t, false>; using solver_arena = device_arena; + using queue_type = detail::queue_base<solver_arena, solver::matrix_solver_t, false>; NETLIB_CONSTRUCTOR(solver) , m_fb_step(*this, "FB_step", NETLIB_DELEGATE(fb_step<false>)) , m_Q_step(*this, "Q_step") , m_params(*this, "", solver::solver_parameter_defaults::get_instance()) - , m_queue(config::max_solver_queue_size(), + , m_queue(this->state().pool(), config::max_solver_queue_size(), queue_type::id_delegate(&NETLIB_NAME(solver) :: get_solver_id, this), queue_type::obj_delegate(&NETLIB_NAME(solver) :: solver_by_id, this)) { diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h index 2b5a4ec8aeb..106f3e65162 100644 --- a/src/lib/netlist/tools/nl_convert.h +++ b/src/lib/netlist/tools/nl_convert.h @@ -23,7 +23,7 @@ namespace netlist::convert { -using arena = plib::aligned_arena; +using arena = plib::aligned_arena<>; class nl_convert_base_t { |