diff options
author | couriersud <couriersud@gmx.org> | 2019-10-15 23:36:48 +0200 |
---|---|---|
committer | couriersud <couriersud@gmx.org> | 2019-10-15 23:36:48 +0200 |
commit | e5cceda2189fc04f4f4ed19748f78522b9033029 (patch) | |
tree | 3ca6c7eba136e5def9c03844fcbd5730b24d7003 /src/lib/netlist | |
parent | 88f544f02fddf6d15f2b3de90c8d3514d39b55d5 (diff) |
Netlist: code maintenance and bug fixes. [Couriersud]
- optimized the core queue dispatching logic. Minor performance
increase.
- fixed a number of bugs in parray. Now parray<double, 0> will be purely
dynamic allocation with the number of elements passed in the
constructor.
- Added noexpr where appropriate.
- Simplified the queue
Checked with gcc-7 (ubuntu), gcc-9, clang-10, macosx clang 10, mingw
cross compile on linux.
Diffstat (limited to 'src/lib/netlist')
-rw-r--r-- | src/lib/netlist/build/makefile | 1 | ||||
-rw-r--r-- | src/lib/netlist/devices/nld_4020.cpp | 2 | ||||
-rw-r--r-- | src/lib/netlist/devices/nld_7448.cpp | 2 | ||||
-rw-r--r-- | src/lib/netlist/devices/nld_7490.cpp | 2 | ||||
-rw-r--r-- | src/lib/netlist/devices/nld_am2847.cpp | 2 | ||||
-rw-r--r-- | src/lib/netlist/nl_base.cpp | 28 | ||||
-rw-r--r-- | src/lib/netlist/nl_base.h | 117 | ||||
-rw-r--r-- | src/lib/netlist/nl_config.h | 2 | ||||
-rw-r--r-- | src/lib/netlist/nl_errstr.h | 3 | ||||
-rw-r--r-- | src/lib/netlist/nl_lists.h | 120 | ||||
-rw-r--r-- | src/lib/netlist/plib/gmres.h | 8 | ||||
-rw-r--r-- | src/lib/netlist/plib/mat_cr.h | 13 | ||||
-rw-r--r-- | src/lib/netlist/plib/parray.h | 48 | ||||
-rw-r--r-- | src/lib/netlist/plib/plists.h | 19 | ||||
-rw-r--r-- | src/lib/netlist/plib/ppmf.h | 12 | ||||
-rw-r--r-- | src/lib/netlist/solver/nld_solver.cpp | 3 |
16 files changed, 209 insertions, 173 deletions
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index 961a2f4cc89..6f75a1d9612 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -26,6 +26,7 @@ TIDY_FLAGSX += -bugprone-macro-parentheses,-misc-macro-parentheses, TIDY_FLAGSX += -modernize-use-trailing-return-type TIDY_FLAGSX += -bugprone-too-small-loop-variable TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay +TIDY_FLAGSX += -modernize-use-trailing-return-type space := space += diff --git a/src/lib/netlist/devices/nld_4020.cpp b/src/lib/netlist/devices/nld_4020.cpp index d0e35f502b7..97161071306 100644 --- a/src/lib/netlist/devices/nld_4020.cpp +++ b/src/lib/netlist/devices/nld_4020.cpp @@ -34,7 +34,7 @@ namespace netlist NETLIB_UPDATEI(); public: - void update_outputs(const unsigned cnt); + void update_outputs(const unsigned cnt) NL_NOEXCEPT; logic_input_t m_IP; object_array_t<logic_output_t, 14> m_Q; diff --git a/src/lib/netlist/devices/nld_7448.cpp b/src/lib/netlist/devices/nld_7448.cpp index 23daf983174..34826a068f9 100644 --- a/src/lib/netlist/devices/nld_7448.cpp +++ b/src/lib/netlist/devices/nld_7448.cpp @@ -36,7 +36,7 @@ namespace netlist NETLIB_UPDATEI(); public: - void update_outputs(unsigned v); + void update_outputs(unsigned v) NL_NOEXCEPT; logic_input_t m_A; logic_input_t m_B; diff --git a/src/lib/netlist/devices/nld_7490.cpp b/src/lib/netlist/devices/nld_7490.cpp index 157563f5f0c..497547c3630 100644 --- a/src/lib/netlist/devices/nld_7490.cpp +++ b/src/lib/netlist/devices/nld_7490.cpp @@ -34,7 +34,7 @@ namespace netlist NETLIB_UPDATEI(); NETLIB_RESETI(); - void update_outputs(); + void update_outputs() NL_NOEXCEPT; logic_input_t m_A; logic_input_t m_B; diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp index d4a7cbe53b7..8153274e523 100644 --- a/src/lib/netlist/devices/nld_am2847.cpp +++ b/src/lib/netlist/devices/nld_am2847.cpp @@ -27,7 +27,7 @@ namespace netlist NETLIB_UPDATEI(); public: - void shift(); + void shift() NL_NOEXCEPT; logic_input_t m_RC; logic_input_t m_IN; diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index 7035aa73b2e..034422792cd 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -107,7 +107,7 @@ const logic_family_desc_t *family_CD4XXX() // ---------------------------------------------------------------------------------------- detail::queue_t::queue_t(netlist_state_t &nl) - : timed_queue<pqentry_t<net_t *, netlist_time>, false, true>(512) + : timed_queue<pqentry_t<net_t *, netlist_time>, false>(512) , netlist_ref(nl) , m_qsize(0) , m_times(512) @@ -142,7 +142,7 @@ void detail::queue_t::on_post_load(plib::state_manager_t &manager) for (std::size_t i = 0; i < m_qsize; i++ ) { detail::net_t *n = state().nets()[m_net_ids[i]].get(); - this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n)); + this->push<false>(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n)); } } @@ -740,7 +740,7 @@ void detail::net_t::update_devs() NL_NOEXCEPT { case core_terminal_t::STATE_INP_HL: case core_terminal_t::STATE_INP_LH: - process<KEEP_STATS>(mask | core_terminal_t::STATE_INP_ACTIVE, new_Q); + process<KEEP_STATS>(mask, new_Q); break; default: /* do nothing */ @@ -749,20 +749,10 @@ void detail::net_t::update_devs() NL_NOEXCEPT #else nl_assert(this->isRailNet()); - const unsigned int mask((m_new_Q << core_terminal_t::INP_LH_SHIFT) - | (m_cur_Q << core_terminal_t::INP_HL_SHIFT)); - m_in_queue = queue_status::DELIVERED; /* mark as taken ... */ - switch (mask) - { - case core_terminal_t::STATE_INP_HL: - case core_terminal_t::STATE_INP_LH: - process<KEEP_STATS>(mask | core_terminal_t::STATE_INP_ACTIVE, m_new_Q); - break; - default: - /* do nothing */ - break; - } + if (m_new_Q ^ m_cur_Q) + process<KEEP_STATS>((m_new_Q << core_terminal_t::INP_LH_SHIFT) + | (m_cur_Q << core_terminal_t::INP_HL_SHIFT), m_new_Q); #endif } @@ -791,7 +781,7 @@ void detail::net_t::reset() } } -void detail::net_t::add_terminal(detail::core_terminal_t &terminal) +void detail::net_t::add_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT { for (auto &t : m_core_terms) if (t == &terminal) @@ -802,7 +792,7 @@ void detail::net_t::add_terminal(detail::core_terminal_t &terminal) m_core_terms.push_back(&terminal); } -void detail::net_t::remove_terminal(detail::core_terminal_t &terminal) +void detail::net_t::remove_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT { if (plib::container::contains(m_core_terms, &terminal)) { @@ -1002,7 +992,7 @@ param_t::param_type_t param_t::param_type() const } -void param_t::update_param() +void param_t::update_param() NL_NOEXCEPT { device().update_param(); } diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index e58a439a35c..e3868944d7d 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -98,7 +98,7 @@ class NETLIB_NAME(name) : public device_t * device a dynamic device if parameter m_func is set. */ #define NETLIB_IS_DYNAMIC(expr) \ - public: virtual bool is_dynamic() const override { return expr; } + public: virtual bool is_dynamic() const NL_NOEXCEPT override { return expr; } /*! Add this to a device definition to mark the device as a time-stepping device. * @@ -122,26 +122,26 @@ class NETLIB_NAME(name) : public device_t * */ #define NETLIB_IS_TIMESTEP(expr) \ - public: virtual bool is_timestep() const override { return expr; } + public: virtual bool is_timestep() const NL_NOEXCEPT override { return expr; } /*! Used to implement the time stepping code. * * Please see NETLIB_IS_TIMESTEP for an example. */ #define NETLIB_TIMESTEPI() \ - public: virtual void timestep(const nl_double step) override + public: virtual void timestep(const nl_double step) NL_NOEXCEPT override #define NETLIB_FAMILY(family) , m_famsetter(*this, family) #define NETLIB_DELEGATE(chip, name) nldelegate(&NETLIB_NAME(chip) :: name, this) -#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() override +#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() NL_NOEXCEPT override #define NETLIB_HANDLERI(name) virtual void name() NL_NOEXCEPT #define NETLIB_UPDATEI() virtual void update() NL_NOEXCEPT override -#define NETLIB_UPDATE_PARAMI() virtual void update_param() override +#define NETLIB_UPDATE_PARAMI() virtual void update_param() NL_NOEXCEPT override #define NETLIB_RESETI() virtual void reset() override -#define NETLIB_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(const nl_double step) +#define NETLIB_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(nl_double step) NL_NOEXCEPT #define NETLIB_SUB(chip) nld_ ## chip #define NETLIB_SUBXX(ns, chip) unique_pool_ptr< ns :: nld_ ## chip > @@ -151,10 +151,10 @@ class NETLIB_NAME(name) : public device_t #define NETLIB_RESET(chip) void NETLIB_NAME(chip) :: reset(void) -#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param() -#define NETLIB_FUNC_VOID(chip, name, params) void NETLIB_NAME(chip) :: name params +#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param() NL_NOEXCEPT +#define NETLIB_FUNC_VOID(chip, name, params) void NETLIB_NAME(chip) :: name params NL_NOEXCEPT -#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals() +#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals() NL_NOEXCEPT //============================================================ // Asserts @@ -254,13 +254,13 @@ namespace netlist virtual unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const = 0; - double fixed_V() const { return m_fixed_V; } - double low_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_low_thresh_PCNT; } - double high_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_high_thresh_PCNT; } - double low_offset_V() const { return m_low_VO; } - double high_offset_V() const { return m_high_VO; } - double R_low() const { return m_R_low; } - double R_high() const { return m_R_high; } + double fixed_V() const noexcept{ return m_fixed_V; } + double low_thresh_V(const double VN, const double VP) const noexcept{ return VN + (VP - VN) * m_low_thresh_PCNT; } + double high_thresh_V(const double VN, const double VP) const noexcept{ return VN + (VP - VN) * m_high_thresh_PCNT; } + double low_offset_V() const noexcept{ return m_low_VO; } + double high_offset_V() const noexcept{ return m_high_VO; } + double R_low() const noexcept{ return m_R_low; } + double R_high() const noexcept{ return m_R_high; } double m_fixed_V; //!< For variable voltage families, specify 0. For TTL this would be 5. */ double m_low_thresh_PCNT; //!< low input threshhold offset. If the input voltage is below this value times supply voltage, a "0" input is signalled @@ -285,11 +285,9 @@ namespace netlist class logic_family_t { public: - logic_family_t() : m_logic_family(nullptr) {} COPYASSIGNMOVE(logic_family_t, delete) - const logic_family_desc_t *logic_family() const { return m_logic_family; } void set_logic_family(const logic_family_desc_t *fam) { m_logic_family = fam; } @@ -321,7 +319,7 @@ namespace netlist template <typename O> //! Constructor. state_var(O &owner, //!< owner must have a netlist() method. - const pstring &name, //!< identifier/name for this state variable + const pstring &name, //!< identifier/name for this state variable const T &value //!< Initial value after construction ); @@ -332,7 +330,7 @@ namespace netlist //! Move Constructor. constexpr state_var(state_var &&rhs) noexcept = default; //! Assignment operator to assign value of a state var. - C14CONSTEXPR state_var &operator=(const state_var &rhs) = default; + C14CONSTEXPR state_var &operator=(const state_var &rhs) /*noexcept*/ = default; // OSX doesn't like noexcept //! Assignment move operator to assign value of a state var. C14CONSTEXPR state_var &operator=(state_var &&rhs) noexcept = default; //! Assignment operator to assign value of type T. @@ -355,7 +353,7 @@ namespace netlist * Please refer to \ref state_var. */ template <typename T, std::size_t N> - struct state_array + struct state_array : public std::array<T, N> { public: //! Constructor. @@ -372,12 +370,6 @@ namespace netlist state_array(state_array &&rhs) noexcept = default; state_array &operator=(const state_array &rhs) noexcept = default; state_array &operator=(state_array &&rhs) noexcept = default; - - state_array &operator=(const T &rhs) noexcept { m_value = rhs; return *this; } - T & operator[](const std::size_t i) noexcept { return m_value[i]; } - constexpr const T & operator[](const std::size_t i) const noexcept { return m_value[i]; } - private: - std::array<T, N> m_value; }; // ----------------------------------------------------------------------------- @@ -401,22 +393,22 @@ namespace netlist template <typename C, typename T> struct property_store_t { - static void add(const C *obj, const T &aname) + static void add(const C *obj, const T &aname) noexcept { store().insert({obj, aname}); } - static const T get(const C *obj) + static const T get(const C *obj) noexcept { return store().find(obj)->second; } - static void remove(const C *obj) + static void remove(const C *obj) noexcept { store().erase(store().find(obj)); } - static std::unordered_map<const C *, T> &store() + static std::unordered_map<const C *, T> &store() noexcept { static std::unordered_map<const C *, T> lstore; return lstore; @@ -453,7 +445,7 @@ namespace netlist * * \returns name of the object. */ - pstring name() const + pstring name() const noexcept { return props::get(this); } @@ -549,17 +541,14 @@ namespace netlist { public: - using list_t = std::vector<core_terminal_t *>; - static constexpr const unsigned int INP_HL_SHIFT = 0; static constexpr const unsigned int INP_LH_SHIFT = 1; - static constexpr const unsigned int INP_ACTIVE_SHIFT = 2; enum state_e { STATE_INP_PASSIVE = 0, STATE_INP_HL = (1 << INP_HL_SHIFT), STATE_INP_LH = (1 << INP_LH_SHIFT), - STATE_INP_ACTIVE = (1 << INP_ACTIVE_SHIFT), + STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH, STATE_OUT = 128, STATE_BIDIR = 256 }; @@ -669,8 +658,8 @@ namespace netlist /* setup stuff */ - void add_terminal(core_terminal_t &terminal); - void remove_terminal(core_terminal_t &terminal); + void add_terminal(core_terminal_t &terminal) NL_NOEXCEPT; + void remove_terminal(core_terminal_t &terminal) NL_NOEXCEPT; bool is_logic() const NL_NOEXCEPT; bool is_analog() const NL_NOEXCEPT; @@ -730,7 +719,7 @@ namespace netlist * FIXME: get rid of this and implement export/import in MAME */ /* only used for logic nets */ - netlist_sig_t *Q_state_ptr() { return m_cur_Q.ptr(); } + netlist_sig_t *Q_state_ptr() noexcept { return m_cur_Q.ptr(); } private: state_var<netlist_sig_t> m_new_Q; @@ -989,12 +978,12 @@ namespace netlist protected: virtual ~param_t() noexcept = default; /* not intended to be destroyed */ - void update_param(); + void update_param() NL_NOEXCEPT; pstring get_initial(const device_t &dev, bool *found); template<typename C> - void set(C &p, const C v) + void set(C &p, const C v) noexcept { if (p != v) { @@ -1018,7 +1007,7 @@ namespace netlist T operator()() const NL_NOEXCEPT { return m_param; } operator T() const NL_NOEXCEPT { return m_param; } - void setTo(const T ¶m) { set(m_param, param); } + void setTo(const T ¶m) noexcept { set(m_param, param); } private: T m_param; }; @@ -1031,7 +1020,7 @@ namespace netlist T operator()() const NL_NOEXCEPT { return T(m_param); } operator T() const NL_NOEXCEPT { return T(m_param); } - void setTo(const T ¶m) { set(m_param, static_cast<int>(param)); } + void setTo(const T ¶m) noexcept { set(m_param, static_cast<int>(param)); } private: int m_param; }; @@ -1050,7 +1039,7 @@ namespace netlist public: param_ptr_t(device_t &device, const pstring &name, std::uint8_t* val); std::uint8_t * operator()() const NL_NOEXCEPT { return m_param; } - void setTo(std::uint8_t *param) { set(m_param, param); } + void setTo(std::uint8_t *param) noexcept { set(m_param, param); } private: std::uint8_t* m_param; }; @@ -1200,10 +1189,10 @@ namespace netlist } } - void set_hint_deactivate(bool v) { m_hint_deactivate = v; } - bool get_hint_deactivate() { return m_hint_deactivate; } + void set_hint_deactivate(bool v) noexcept { m_hint_deactivate = v; } + bool get_hint_deactivate() const noexcept { return m_hint_deactivate; } /* Has to be set in device reset */ - void set_active_outputs(int n) { m_active_outputs = n; } + void set_active_outputs(int n) noexcept { m_active_outputs = n; } void set_default_delegate(detail::core_terminal_t &term); @@ -1229,12 +1218,12 @@ namespace netlist log_type & log(); public: - virtual void timestep(const nl_double st) { plib::unused_var(st); } - virtual void update_terminals() { } + virtual void timestep(const nl_double st) NL_NOEXCEPT { plib::unused_var(st); } + virtual void update_terminals() NL_NOEXCEPT { } - virtual void update_param() {} - virtual bool is_dynamic() const { return false; } - virtual bool is_timestep() const { return false; } + virtual void update_param() NL_NOEXCEPT {} + virtual bool is_dynamic() const NL_NOEXCEPT { return false; } + virtual bool is_timestep() const NL_NOEXCEPT { return false; } private: bool m_hint_deactivate; @@ -1303,12 +1292,12 @@ namespace netlist */ class detail::queue_t : //public timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>, - public timed_queue<pqentry_t<net_t *, netlist_time>, false, true>, + public timed_queue<pqentry_t<net_t *, netlist_time>, false>, public detail::netlist_ref, public plib::state_manager_t::callback_t { public: - using base_queue = timed_queue<pqentry_t<net_t *, netlist_time>, false, true>; + using base_queue = timed_queue<pqentry_t<net_t *, netlist_time>, false>; using entry_t = pqentry_t<net_t *, netlist_time>; explicit queue_t(netlist_state_t &nl); virtual ~queue_t() noexcept = default; @@ -1550,25 +1539,31 @@ namespace netlist netlist_time time() const NL_NOEXCEPT { return m_time; } void process_queue(netlist_time delta) NL_NOEXCEPT; - void abort_current_queue_slice() NL_NOEXCEPT { m_queue.retime(detail::queue_t::entry_t(m_time, nullptr)); } + void abort_current_queue_slice() NL_NOEXCEPT + { + if (!USE_QUEUE_STATS || !m_use_stats) + m_queue.retime<false>(detail::queue_t::entry_t(m_time, nullptr)); + else + m_queue.retime<true>(detail::queue_t::entry_t(m_time, nullptr)); + } const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; } void qpush(detail::queue_t::entry_t && e) noexcept { if (!USE_QUEUE_STATS || !m_use_stats) - m_queue.push_nostats(std::move(e)); // NOLINT(performance-move-const-arg) + m_queue.push<false>(std::move(e)); // NOLINT(performance-move-const-arg) else - m_queue.push(std::move(e)); // NOLINT(performance-move-const-arg) + m_queue.push<true>(std::move(e)); // NOLINT(performance-move-const-arg) } template <class R> void qremove(const R &elem) noexcept { if (!USE_QUEUE_STATS || !m_use_stats) - m_queue.remove_nostats(elem); + m_queue.remove<false>(elem); else - m_queue.remove(elem); + m_queue.remove<true>(elem); } /* Control functions */ @@ -1905,9 +1900,9 @@ namespace netlist template <typename O> state_array<T,N>::state_array(O &owner, const pstring &name, const T & value) { - owner.state().save(owner, m_value, owner.name(), name); + owner.state().save(owner, *static_cast<std::array<T, N> *>(this), owner.name(), name); for (std::size_t i=0; i<N; i++) - m_value[i] = value; + (*this)[i] = value; } } // namespace netlist diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index f2005602443..71a0e6c028c 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -50,7 +50,7 @@ * This approach is stricter and should identify bugs in * the netlist core faster. * By default it is disabled since it is not as fast as - * the default approach. It is up to 5% slower. + * the default approach. It is up to 10% slower. * */ #ifndef USE_COPY_INSTEAD_OF_REFERENCE diff --git a/src/lib/netlist/nl_errstr.h b/src/lib/netlist/nl_errstr.h index c2464d0ef69..12cf72769a9 100644 --- a/src/lib/netlist/nl_errstr.h +++ b/src/lib/netlist/nl_errstr.h @@ -125,9 +125,6 @@ namespace netlist // nld_solver.cpp - //PERRMSGV(MF_UNKNOWN_SOLVER_TYPE, 1, "Unknown solver type: {1}") - PERRMSGV(MF_NETGROUP_SIZE_EXCEEDED_1, 1, "Encountered netgroup with > {1} nets") - PERRMSGV(MI_NO_SPECIFIC_SOLVER, 1, "No specific solver found for netlist of size {1}") // nld_mm5837.cpp diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h index f4b1c4e8ff5..27db664cc05 100644 --- a/src/lib/netlist/nl_lists.h +++ b/src/lib/netlist/nl_lists.h @@ -69,37 +69,34 @@ namespace netlist std::swap(m_object, other.m_object); } #endif - struct QueueOp + inline bool operator ==(const pqentry_t &rhs) const noexcept { - inline static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept - { - return (lhs.m_exec_time < rhs.m_exec_time); - } + return m_object == rhs.m_object; + } - inline static constexpr bool lessequal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept - { - return (lhs.m_exec_time <= rhs.m_exec_time); - } + inline bool operator ==(const Element &rhs) const noexcept + { + return m_object == rhs; + } - inline static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept - { - return lhs.m_object == rhs.m_object; - } + inline bool operator <=(const pqentry_t &rhs) const noexcept + { + return (m_exec_time <= rhs.m_exec_time); + } - inline static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept - { - return lhs.m_object == rhs; - } + inline bool operator <(const pqentry_t &rhs) const noexcept + { + return (m_exec_time < rhs.m_exec_time); + } - inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); } - }; + inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); } Time m_exec_time; Element m_object; }; /* Use TS = true for a threadsafe queue */ - template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp> + template <class T, bool TS> class timed_queue_linear : plib::nocopyassignmove { public: @@ -113,28 +110,31 @@ namespace netlist std::size_t capacity() const noexcept { return m_list.capacity() - 1; } bool empty() const noexcept { return (m_end == &m_list[1]); } + template<bool KEEPSTAT> void push(T && e) noexcept { /* Lock */ lock_guard_type lck(m_lock); T * i(m_end-1); - for (; QueueOp::less(*(i), e); --i) + for (; *i < e; --i) { *(i+1) = *(i); - m_prof_sortmove.inc(); + if (KEEPSTAT) + m_prof_sortmove.inc(); } *(i+1) = std::move(e); ++m_end; - m_prof_call.inc(); + if (KEEPSTAT) + m_prof_call.inc(); } - void push_nostats(T && e) noexcept + void push_nostatsx(T && e) noexcept { /* Lock */ lock_guard_type lck(m_lock); #if 1 T * i(m_end-1); - for (; QueueOp::less(*(i), e); --i) + for (; *i < e; --i) { *(i+1) = *(i); } @@ -153,22 +153,18 @@ namespace netlist T pop() noexcept { return *(--m_end); } const T &top() const noexcept { return *(m_end-1); } - template <class R> + template <bool KEEPSTAT, class R> void remove(const R &elem) noexcept { - m_prof_remove.inc(); - remove_nostats(elem); - } - - template <class R> - void remove_nostats(const R &elem) noexcept - { /* Lock */ lock_guard_type lck(m_lock); + if (KEEPSTAT) + m_prof_remove.inc(); #if 1 for (T * i = m_end - 1; i > &m_list[0]; --i) { - if (QueueOp::equal(*i, elem)) + // == operator ignores time! + if (*i == elem) { std::copy(i+1, m_end--, i); return; @@ -186,23 +182,25 @@ namespace netlist #endif } - void retime(T && elem) noexcept + template <bool KEEPSTAT, class R> + void retime(R && elem) noexcept { /* Lock */ lock_guard_type lck(m_lock); - m_prof_retime.inc(); + if (KEEPSTAT) + m_prof_retime.inc(); - for (T * i = m_end - 1; i > &m_list[0]; --i) + for (R * i = m_end - 1; i > &m_list[0]; --i) { - if (QueueOp::equal(*i, elem)) // partial equal! + if (*i == elem) // partial equal! { *i = std::move(elem); - while (QueueOp::less(*(i-1), *i)) + while (*(i-1) < *i) { std::swap(*(i-1), *i); --i; } - while (i < m_end && QueueOp::less(*i, *(i+1))) + while (i < m_end && *i < *(i+1)) { std::swap(*(i+1), *i); ++i; @@ -220,7 +218,7 @@ namespace netlist * the insert algo above will run into this element and doesn't * need a comparison with queue start. */ - m_list[0] = QueueOp::never(); + m_list[0] = T::never(); m_end++; } @@ -241,20 +239,20 @@ namespace netlist public: // profiling - nperfcount_t<KEEPSTAT> m_prof_sortmove; - nperfcount_t<KEEPSTAT> m_prof_call; - nperfcount_t<KEEPSTAT> m_prof_remove; - nperfcount_t<KEEPSTAT> m_prof_retime; + nperfcount_t<true> m_prof_sortmove; + nperfcount_t<true> m_prof_call; + nperfcount_t<true> m_prof_remove; + nperfcount_t<true> m_prof_retime; }; - template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp> + template <class T, bool TS> class timed_queue_heap : plib::nocopyassignmove { public: struct compare { - constexpr bool operator()(const T &a, const T &b) const { return QueueOp::lessequal(b,a); } + constexpr bool operator()(const T &a, const T &b) const { return b <= a; } }; explicit timed_queue_heap(const std::size_t list_size) @@ -266,13 +264,15 @@ namespace netlist std::size_t capacity() const noexcept { return m_list.capacity(); } bool empty() const noexcept { return &m_list[0] == m_end; } + template <bool KEEPSTAT> void push(T &&e) noexcept { /* Lock */ lock_guard_type lck(m_lock); *m_end++ = e; std::push_heap(&m_list[0], m_end, compare()); - m_prof_call.inc(); + if (KEEPSTAT) + m_prof_call.inc(); } T pop() noexcept @@ -285,14 +285,16 @@ namespace netlist const T &top() const noexcept { return m_list[0]; } - template <class R> + template <bool KEEPSTAT, class R> void remove(const R &elem) noexcept { /* Lock */ lock_guard_type lck(m_lock); + if (KEEPSTAT) + m_prof_remove.inc(); for (T * i = m_end - 1; i >= &m_list[0]; i--) { - if (QueueOp::equal(*i, elem)) + if (*i == elem) { m_end--; for (;i < m_end; i++) @@ -303,13 +305,16 @@ namespace netlist } } + template <bool KEEPSTAT> void retime(const T &elem) noexcept { /* Lock */ lock_guard_type lck(m_lock); + if (KEEPSTAT) + m_prof_retime.inc(); for (T * i = m_end - 1; i >= &m_list[0]; i--) { - if (QueueOp::equal(*i, elem)) // partial equal! + if (*i == elem) // partial equal! { *i = elem; std::make_heap(&m_list[0], m_end, compare()); @@ -340,18 +345,23 @@ namespace netlist public: // profiling - nperfcount_t<KEEPSTAT> m_prof_sortmove; - nperfcount_t<KEEPSTAT> m_prof_call; + nperfcount_t<true> m_prof_sortmove; + nperfcount_t<true> m_prof_call; + nperfcount_t<true> m_prof_remove; + nperfcount_t<true> m_prof_retime; }; + template <class T, bool TS> + using timed_queue = timed_queue_linear<T, TS>; + /* * Use timed_queue_heap to use stdc++ heap functions instead of linear processing. * * This slows down processing by about 25% on a Kaby Lake. */ - template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp> - using timed_queue = timed_queue_linear<T, TS, KEEPSTAT, QueueOp>; + //template <class T, bool TS> + //using timed_queue = timed_queue_heap<T, TS>; } // namespace netlist diff --git a/src/lib/netlist/plib/gmres.h b/src/lib/netlist/plib/gmres.h index 8ceee16d9cc..8c5c724c581 100644 --- a/src/lib/netlist/plib/gmres.h +++ b/src/lib/netlist/plib/gmres.h @@ -223,6 +223,8 @@ namespace plib gmres_t(std::size_t size) : residual(size) , Ax(size) + , m_ht(RESTART +1, RESTART) + , m_v(RESTART + 1, size) , m_size(size) , m_use_more_precise_stop_condition(false) { @@ -416,12 +418,12 @@ namespace plib plib::parray<float_type, RESTART + 1> m_c; /* mr + 1 */ plib::parray<float_type, RESTART + 1> m_g; /* mr + 1 */ - plib::parray<plib::parray<float_type, RESTART>, RESTART + 1> m_ht; /* (mr + 1), mr */ + plib::parray2D<float_type, RESTART + 1, RESTART> m_ht; /* (mr + 1), mr */ plib::parray<float_type, RESTART + 1> m_s; /* mr + 1 */ plib::parray<float_type, RESTART + 1> m_y; /* mr + 1 */ - //plib::parray<float_type, SIZE> m_v[RESTART + 1]; /* mr + 1, n */ - plib::parray<plib::parray<float_type, storage_N>, RESTART + 1> m_v; /* mr + 1, n */ + //plib::parray<plib::parray<float_type, storage_N>, RESTART + 1> m_v; /* mr + 1, n */ + plib::parray2D<float_type, RESTART + 1, SIZE> m_v; /* mr + 1, n */ std::size_t m_size; diff --git a/src/lib/netlist/plib/mat_cr.h b/src/lib/netlist/plib/mat_cr.h index 9ddf2f2d39f..bc06d151042 100644 --- a/src/lib/netlist/plib/mat_cr.h +++ b/src/lib/netlist/plib/mat_cr.h @@ -36,7 +36,7 @@ namespace plib using index_type = C; using value_type = T; - static constexpr const int NSQ = (N > 0 ? -N * N : N * N); + static constexpr const int NSQ = (N < 0 ? -N * N : N * N); static constexpr const int Np1 = (N == 0) ? 0 : (N < 0 ? N - 1 : N + 1); COPYASSIGNMOVE(pmatrix_cr_t, default) @@ -64,7 +64,9 @@ namespace plib , m_size(n) { for (index_type i=0; i<n+1; i++) + { row_idx[i] = 0; + } } ~pmatrix_cr_t() = default; @@ -495,19 +497,18 @@ namespace plib { index_type p(0); /* build ilu_rows */ - for (index_type i=1; i < fill.size(); i++) + for (decltype(fill.size()) i=1; i < fill.size(); i++) { bool found(false); - for (index_type k = 0; k < i; k++) + for (decltype(fill.size()) k = 0; k < i; k++) { // if (fill[i][k] < base::FILL_INFINITY) if (fill[i][k] <= ilup) { // assume A[k][k]!=0 - for (index_type j=k+1; j < fill.size(); j++) + for (decltype(fill.size()) j=k+1; j < fill.size(); j++) { auto f = std::min(fill[i][j], 1 + fill[i][k] + fill[k][j]); - //if (f < base::FILL_INFINITY) if (f <= ilup) { #if 0 @@ -522,7 +523,7 @@ namespace plib } } if (found) - ilu_rows[p++] = i; + ilu_rows[p++] = static_cast<index_type>(i); } ilu_rows[p] = 0; // end of array this->build_from_fill_mat(fill, ilup); //, m_band_width); // ILU(2) diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h index 577de2d3dfc..b385da56eab 100644 --- a/src/lib/netlist/plib/parray.h +++ b/src/lib/netlist/plib/parray.h @@ -30,8 +30,9 @@ namespace plib { template <typename FT> struct sizeabs<FT, 0> { - static constexpr const std::size_t ABS = 0; - using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>; + static constexpr std::size_t ABS() { return 0; } + //using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>; + using container = typename std::vector<FT>; }; /** @@ -63,27 +64,35 @@ namespace plib { using value_type = typename base_type::value_type; template <int X = SIZE > - parray(size_type size, typename std::enable_if<X==0, int>::type = 0) + parray(size_type size, typename std::enable_if<(X==0), int>::type = 0) : m_a(size), m_size(size) { } #if 1 +#if 0 + struct tag {}; /* allow construction in fixed size arrays */ template <int X = SIZE > - parray(typename std::enable_if<(X > 0), int>::type = 0) + parray(tag A = tag(), typename std::enable_if<(X >= 0), int>::type = 0) : m_size(X) { } +#else + /* allow construction in fixed size arrays */ + parray() + : m_size(SIZEABS()) + { + } +#endif #endif template <int X = SIZE > - parray(size_type size, typename std::enable_if<X!=0, int>::type = 0) + parray(size_type size, typename std::enable_if<(X != 0), int>::type = 0) : m_size(size) { - if (SIZE < 0 && size > SIZEABS()) - throw plib::pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZEABS())); - else if (SIZE > 0 && size != SIZEABS()) - throw plib::pexception("parray: size error"); + if ((SIZE < 0 && size > SIZEABS()) + || (SIZE > 0 && size != SIZEABS())) + throw plib::pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZE)); } inline size_type size() const noexcept { return SIZE <= 0 ? m_size : SIZEABS(); } @@ -122,6 +131,27 @@ namespace plib { PALIGNAS_CACHELINE() size_type m_size; }; + + template <typename FT, int SIZE1, int SIZE2> + struct parray2D : public parray<parray<FT, SIZE2>, SIZE1> + { + public: + + using size_type = std::size_t; + + parray2D(size_type size1, size_type size2) + : parray<parray<FT, SIZE2>, SIZE1>(size1) + { + if (SIZE2 <= 0) + { + for (size_type i=0; i < this->size(); i++) + (*this)[i] = parray<FT, SIZE2>(size2); + } + } + }; + } // namespace plib + + #endif /* PARRAY_H_ */ diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h index 525a65a97f2..727dad5d936 100644 --- a/src/lib/netlist/plib/plists.h +++ b/src/lib/netlist/plib/plists.h @@ -209,7 +209,7 @@ public: explicit constexpr iter_t(LC* x) noexcept : p(x) { } constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { } iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); } - iter_t& operator=(const iter_t &rhs) noexcept { iter_t t(rhs); std::swap(*this, t); return *this; } + iter_t& operator=(const iter_t &rhs) noexcept { p = rhs.p; return *this; } iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; } iter_t& operator++() noexcept {p = p->next();return *this;} // NOLINTNEXTLINE(cert-dcl21-cpp) @@ -219,8 +219,8 @@ public: constexpr bool operator==(const iter_t& rhs) const noexcept {return p == rhs.p;} constexpr bool operator!=(const iter_t& rhs) const noexcept {return p != rhs.p;} - /* constexpr */ LC& operator*() noexcept {return *p;} - /* constexpr */ LC* operator->() noexcept {return p;} + constexpr LC& operator*() noexcept {return *p;} + constexpr LC* operator->() noexcept {return p;} constexpr LC& operator*() const noexcept {return *p;} constexpr LC* operator->() const noexcept {return p;} @@ -269,8 +269,19 @@ public: } LC *front() const noexcept { return m_head; } - void clear() noexcept { m_head = nullptr; } constexpr bool empty() const noexcept { return (m_head == nullptr); } + void clear() noexcept + { + LC *p(m_head); + while (p != nullptr) + { + LC *n(p->m_next); + p->m_next = nullptr; + p->m_prev = nullptr; + p = n; + } + m_head = nullptr; + } private: LC *m_head; diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h index 6ce65d4e960..9c5c989da0b 100644 --- a/src/lib/netlist/plib/ppmf.h +++ b/src/lib/netlist/plib/ppmf.h @@ -176,13 +176,13 @@ namespace plib { *reinterpret_cast<function_ptr *>(&m_func) = t; } template<typename O> - inline R call(O *obj, Targs... args) + inline R call(O *obj, Targs... args) const noexcept(true) { using function_ptr = R (O::*)(Targs...); function_ptr t = *reinterpret_cast<function_ptr *>(&m_func); return (obj->*t)(std::forward<Targs>(args)...); } - bool is_set() { + bool is_set() const { #if defined(_MSC_VER) || (defined (__INTEL_COMPILER) && defined (_M_X64)) int *p = reinterpret_cast<int *>(&m_func); int *e = p + sizeof(generic_function) / sizeof(int); @@ -225,12 +225,12 @@ namespace plib { #endif } template<typename O> - R call(O *obj, Targs... args) const + R call(O *obj, Targs... args) const noexcept(true) { using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args); return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...); } - bool is_set() noexcept { return m_func != nullptr; } + bool is_set() const noexcept { return m_func != nullptr; } generic_function get_function() const noexcept { return m_func; } private: generic_function m_func; @@ -244,7 +244,7 @@ namespace plib { class generic_class; template <class C> - using MemberFunctionType = R (C::*)(Targs...); + using MemberFunctionType = R (C::*)(Targs...); // noexcept(true) --> c++-17 pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {} @@ -263,7 +263,7 @@ namespace plib { m_obj = reinterpret_cast<generic_class *>(object); } - inline R operator()(Targs ... args) + inline R operator()(Targs ... args) const noexcept(true) { return this->call(m_obj, std::forward<Targs>(args)...); } diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index c428a08ce25..0692824b97c 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -319,8 +319,7 @@ namespace devices } else { - log().fatal(MF_NETGROUP_SIZE_EXCEEDED_1(128)); - return; /* tease compilers */ + ms = create_solver<double, 0>(net_count, sname); } break; } |