diff options
Diffstat (limited to 'src/lib/netlist')
-rw-r--r-- | src/lib/netlist/analog/nld_generic_models.h | 15 | ||||
-rw-r--r-- | src/lib/netlist/devices/nld_7493.cpp | 2 | ||||
-rw-r--r-- | src/lib/netlist/nl_base.h | 28 | ||||
-rw-r--r-- | src/lib/netlist/nl_config.h | 39 | ||||
-rw-r--r-- | src/lib/netlist/nltypes.h | 2 | ||||
-rw-r--r-- | src/lib/netlist/plib/palloc.h | 47 | ||||
-rw-r--r-- | src/lib/netlist/plib/pconfig.h | 2 | ||||
-rw-r--r-- | src/lib/netlist/plib/pmath.h | 86 | ||||
-rw-r--r-- | src/lib/netlist/plib/pmempool.h | 8 | ||||
-rw-r--r-- | src/lib/netlist/plib/ppmf.h | 4 | ||||
-rw-r--r-- | src/lib/netlist/plib/ptime.h | 32 | ||||
-rw-r--r-- | src/lib/netlist/plib/ptypes.h | 52 |
12 files changed, 195 insertions, 122 deletions
diff --git a/src/lib/netlist/analog/nld_generic_models.h b/src/lib/netlist/analog/nld_generic_models.h index a5d035ed32b..fac8bcb9a6d 100644 --- a/src/lib/netlist/analog/nld_generic_models.h +++ b/src/lib/netlist/analog/nld_generic_models.h @@ -153,16 +153,19 @@ namespace analog void update_diode(nl_fptype nVd) noexcept { - nl_fptype IseVDVt(nlconst::zero()); - if (TYPE == diode_e::BIPOLAR) { //printf("%s: %g %g\n", m_name.c_str(), nVd, (nl_fptype) m_Vd); if (nVd > m_Vcrit) { - const nl_fptype d = std::min(+fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd - m_Vd); + // if the old voltage is less than zero and new is above + // make sure we move enough so that matrix and current + // changes. + const nl_fptype old = std::max(nlconst::zero(), m_Vd()); + const nl_fptype d = std::min(+fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd - old); const nl_fptype a = plib::abs(d) * m_VtInv; - m_Vd = m_Vd + nlconst::magic(d < 0 ? -1.0 : 1.0) * plib::log1p(a) * m_Vt; + m_Vd = old + nlconst::magic(d < 0 ? -1.0 : 1.0) * plib::log1p(a) * m_Vt; + //printf("new VD: %g\n", (nl_fptype)m_Vd); } else m_Vd = std::max(-fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd); @@ -175,7 +178,7 @@ namespace analog } else { - IseVDVt = plib::exp(m_logIs + m_Vd * m_VtInv); + const auto IseVDVt = plib::exp(m_logIs + m_Vd * m_VtInv); m_Id = IseVDVt - m_Is; m_G = IseVDVt * m_VtInv + m_gmin; } @@ -191,7 +194,7 @@ namespace analog else // log stepping should already be done in mosfet { m_Vd = nVd; - IseVDVt = plib::exp(std::min(+fp_constants<nl_fptype>::DIODE_MAXVOLT(), m_logIs + m_Vd * m_VtInv)); + const auto IseVDVt = plib::exp(std::min(+fp_constants<nl_fptype>::DIODE_MAXVOLT(), m_logIs + m_Vd * m_VtInv)); m_Id = IseVDVt - m_Is; m_G = IseVDVt * m_VtInv + m_gmin; } diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp index 855bd8a3770..48c2b179073 100644 --- a/src/lib/netlist/devices/nld_7493.cpp +++ b/src/lib/netlist/devices/nld_7493.cpp @@ -131,7 +131,7 @@ namespace netlist NETLIB_HANDLERI(updB) { - auto cnt = (++m_bcd &= 0x07); + const auto cnt(++m_bcd &= 0x07); m_QD.push((cnt >> 2) & 1, out_delay3); m_QC.push((cnt >> 1) & 1, out_delay2); m_QB.push(cnt & 1, out_delay); diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index 625696ddf93..d2ec68800bf 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -569,17 +569,24 @@ namespace netlist public plib::linkedlist_t<core_terminal_t>::element_t { public: + /// \brief Number of signal bits + /// + /// Going forward setting this to 8 will allow 8-bit signal + /// busses to be used in netlist, e.g. for more complex memory + /// arrangements. + static constexpr const unsigned int INP_BITS = 1; + static constexpr const unsigned int INP_MASK = (1 << INP_BITS) - 1; static constexpr const unsigned int INP_HL_SHIFT = 0; - static constexpr const unsigned int INP_LH_SHIFT = 1; + static constexpr const unsigned int INP_LH_SHIFT = INP_BITS; enum state_e { STATE_INP_PASSIVE = 0, - STATE_INP_HL = (1 << INP_HL_SHIFT), - STATE_INP_LH = (1 << INP_LH_SHIFT), + STATE_INP_HL = (INP_MASK << INP_HL_SHIFT), + STATE_INP_LH = (INP_MASK << INP_LH_SHIFT), STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH, - STATE_OUT = 128, - STATE_BIDIR = 256 + STATE_OUT = (1 << (2*INP_BITS)), + STATE_BIDIR = (1 << (2*INP_BITS + 1)) }; core_terminal_t(core_device_t &dev, const pstring &aname, @@ -590,12 +597,11 @@ namespace netlist /// \brief The object type. /// \returns type of the object - terminal_type type() const noexcept(false); + /// \brief Checks if object is of specified type. /// \param atype type to check object against. /// \returns true if object is of specified type else false. - bool is_type(const terminal_type atype) const noexcept(false) { return (type() == atype); } void set_net(net_t *anet) noexcept { m_net = anet; } @@ -632,7 +638,7 @@ namespace netlist void set_delegate(const nldelegate &delegate) noexcept { m_delegate = delegate; } nldelegate &delegate() noexcept { return m_delegate; } const nldelegate &delegate() const noexcept { return m_delegate; } - void run_delegate() noexcept { m_delegate(); } + inline void run_delegate() noexcept { m_delegate(); } private: nldelegate m_delegate; net_t * m_net; @@ -762,7 +768,7 @@ namespace netlist private: state_var<netlist_sig_t> m_new_Q; state_var<netlist_sig_t> m_cur_Q; - state_var<queue_status> m_in_queue; // 0: not in queue, 1: in queue, 2: last was taken + state_var<queue_status> m_in_queue; state_var<netlist_time_ext> m_next_scheduled_time; core_terminal_t * m_railterminal; @@ -1858,7 +1864,7 @@ namespace netlist { m_next_scheduled_time = exec().time() + delay; - if (is_queued()) + if (!!is_queued()) exec().qremove(this); if (!m_list_active.empty()) @@ -2028,7 +2034,7 @@ namespace netlist // ----------------------------------------------------------------------------- template <bool KEEP_STATS, typename T> - inline void detail::net_t::process(const T mask, netlist_sig_t sig) noexcept + inline void detail::net_t::process(T mask, netlist_sig_t sig) noexcept { m_cur_Q = sig; diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index 47707af7d22..0fc82ae4f79 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -17,11 +17,11 @@ /// /// \brief Version - Minor. /// -#define NL_VERSION_MINOR 5 +#define NL_VERSION_MINOR 7 /// /// \brief Version - Patch level. /// -#define NL_VERSION_PATCHLEVEL 0 +#define NL_VERSION_PATCHLEVEL 1 /// /// \addtogroup compiledefine @@ -61,7 +61,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 10% slower. +/// the default approach. It is up to 20% slower. /// #ifndef NL_USE_COPY_INSTEAD_OF_REFERENCE @@ -135,19 +135,30 @@ /// \brief Resolution as clocks per second for timing /// -/// Uses nano-second resolution - Sufficient for now +/// Uses 100 pico second resolution. This is aligned to MAME's +/// attotime resolution. +/// +/// The table below shows the maximum run times depending on +/// time type size and resolution. +/// +/// | Bits | Res | Seconds | Days | Years | +/// | ====-| ===-| =======-| ====-| =====-| +/// | 63 | 1,000,000,000 | 9,223,372,037 | 106,752| 292.3 | +/// | 63 | 10,000,000,000 | 922,337,204 | 10,675| 29.2 | +/// | 63 | 100,000,000,000 | 92,233,720 | 1,068| 2.9 | +/// | 63 | 1,000,000,000,000 | 9,223,372 | 107| 0.3 | +/// -#if 1 -static constexpr const auto NETLIST_INTERNAL_RES = 1'000'000'000; -static constexpr const auto NETLIST_CLOCK = NETLIST_INTERNAL_RES; -#else -//static constexpr const auto NETLIST_INTERNAL_RES = (1<<30); // 1,073,741,824 -//static constexpr const std::int64_t NETLIST_INTERNAL_RES = (static_cast<std::int64_t>(1)<<33); // 8,589,934,592 -static constexpr const std::int64_t NETLIST_INTERNAL_RES = (static_cast<std::int64_t>(1)<<37); // 137,438,953,472 -// FIXME: Belongs into MAME netlist.h -static constexpr const std::int32_t NETLIST_CLOCK = (static_cast<std::int64_t>(1)<<30); // 1,073,741,824 -#endif +static constexpr const auto NETLIST_INTERNAL_RES = 10'000'000'000ll; + +/// \brief Recommended clock to be used +/// +/// This is the recommended clock to be used in fixed clock applications limited +/// to 32 bit clock resolution. The MAME code (netlist.cpp) contains code +/// illustrating how to deal with remainders if \ref NETLIST_INTERNAL_RES is +/// bigger than NETLIST_CLOCK. +static constexpr const int NETLIST_CLOCK = 1'000'000'000; /// \brief Floating point types used /// diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index 3688c41421d..ab106f9f59a 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -106,8 +106,8 @@ namespace netlist #else using netlist_time = plib::ptime<std::int64_t, NETLIST_INTERNAL_RES>; using netlist_time_ext = netlist_time; - static_assert(noexcept(netlist_time::from_nsec(1)) == true, "Not evaluated as constexpr"); #endif + static_assert(noexcept(netlist_time::from_nsec(1)) == true, "Not evaluated as constexpr"); //============================================================ // MACROS diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index 5262d0c569d..1aa23682ca6 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -11,6 +11,7 @@ #include "pconfig.h" #include "pstring.h" #include "ptypes.h" +#include "pmath.h" #include <cstddef> // for std::max_align_t (usually long long) #include <memory> @@ -281,6 +282,9 @@ namespace plib { static inline void *allocate( size_t alignment, size_t size ) { + m_stat_cur_alloc() += size; + m_stat_max_alloc() = std::max(m_stat_max_alloc(), m_stat_cur_alloc()); + #if (PUSE_ALIGNED_ALLOCATION) #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) return _aligned_malloc(size, alignment); @@ -301,7 +305,8 @@ namespace plib { static inline void deallocate( void *ptr, size_t size ) noexcept { - unused_var(size); + //unused_var(size); + m_stat_cur_alloc() -= size; #if (PUSE_ALIGNED_ALLOCATION) // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) free(ptr); @@ -342,12 +347,32 @@ namespace plib { } } + template<typename T, typename... Args> + static T *alloc(Args&&... args) + { + auto *p = allocate(alignof(T), sizeof(T)); + return new(p) T(std::forward<Args>(args)...); + } + + template<typename T> + static void free(T *ptr) noexcept + { + ptr->~T(); + aligned_arena::deallocate(ptr, sizeof(T)); + } + bool operator ==(const aligned_arena &rhs) const noexcept { plib::unused_var(rhs); return true; } + size_type cur_alloc() const noexcept { return m_stat_cur_alloc(); } + size_type max_alloc() const noexcept { return m_stat_max_alloc(); } + private: + static size_t &m_stat_cur_alloc() noexcept { static size_t val = 0; return val; } + static size_t &m_stat_max_alloc() noexcept { static size_t val = 0; return val; } + }; template <typename T, std::size_t ALIGN> @@ -377,29 +402,13 @@ namespace plib { #endif } - // FIXME: remove - template<typename T, typename... Args> - inline T *pnew(Args&&... args) - { - auto *p = aligned_arena::allocate(alignof(T), sizeof(T)); - return new(p) T(std::forward<Args>(args)...); - } - - template<typename T> - inline void pdelete(T *ptr) noexcept - { - ptr->~T(); - aligned_arena::deallocate(ptr, sizeof(T)); - } - - template <typename T> - using unique_ptr = std::unique_ptr<T, arena_deleter<aligned_arena, T>>; + using unique_ptr = aligned_arena::unique_pool_ptr<T>; template<typename T, typename... Args> plib::unique_ptr<T> make_unique(Args&&... args) { - return plib::unique_ptr<T>(pnew<T>(std::forward<Args>(args)...)); + return aligned_arena::instance().make_unique<T>(std::forward<Args>(args)...); } template <class T, std::size_t ALIGN = alignof(T)> diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h index 0870d8c59d5..115eafd2196 100644 --- a/src/lib/netlist/plib/pconfig.h +++ b/src/lib/netlist/plib/pconfig.h @@ -25,7 +25,7 @@ /// \brief System supports INT128 /// /// Set this to one if you want to use 128 bit int for ptime. -/// This is about 15% slower on a kaby lake processor for pongf. +/// This is about 10% slower on a skylake processor for pongf. /// #ifndef PHAS_INT128 #define PHAS_INT128 (0) diff --git a/src/lib/netlist/plib/pmath.h b/src/lib/netlist/plib/pmath.h index 9738994770d..4fd928ddb54 100644 --- a/src/lib/netlist/plib/pmath.h +++ b/src/lib/netlist/plib/pmath.h @@ -9,6 +9,7 @@ /// #include "pconfig.h" +#include "ptypes.h" #include <algorithm> #include <cmath> @@ -329,6 +330,91 @@ namespace plib #endif + /// \brief is argument a power of two? + /// + /// \tparam T type of the argument + /// \param v argument to be checked + /// \return true if argument is a power of two + /// + template <typename T> + constexpr bool is_pow2(T v) noexcept + { + static_assert(is_integral<T>::value, "is_pow2 needs integer arguments"); + return !(v & (v-1)); + } + + /// \brief return absolute value of signed argument + /// + /// \tparam T type of the argument + /// \param v argument + /// \return absolute value of argument + /// + template<typename T> + constexpr + typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type + abs(T v) noexcept + { + return v < 0 ? -v : v; + } + + /// \brief return absolute value of unsigned argument + /// + /// \tparam T type of the argument + /// \param v argument + /// \return argument since it has no sign + /// + template<typename T> + constexpr + typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, T>::type + abs(T v) noexcept + { + return v; + } + + /// \brief return greatest common denominator + /// + /// Function returns the greatest common denominator of m and n. For known + /// arguments, this function also works at compile time. + /// + /// \tparam M type of the first argument + /// \tparam N type of the second argument + /// \param m first argument + /// \param n first argument + /// \return greatest common denominator of m and n + /// + template<typename M, typename N> + constexpr typename std::common_type<M, N>::type + gcd(M m, N n) noexcept + { + static_assert(std::is_integral<M>::value, "gcd: M must be an integer"); + static_assert(std::is_integral<N>::value, "gcd: N must be an integer"); + + return m == 0 ? plib::abs(n) + : n == 0 ? plib::abs(m) + : gcd(n, m % n); + } + + /// \brief return least common multiple + /// + /// Function returns the least common multiple of m and n. For known + /// arguments, this function also works at compile time. + /// + /// \tparam M type of the first argument + /// \tparam N type of the second argument + /// \param m first argument + /// \param n first argument + /// \return least common multiple of m and n + /// + template<typename M, typename N> + constexpr typename std::common_type<M, N>::type + lcm(M m, N n) noexcept + { + static_assert(std::is_integral<M>::value, "lcm: M must be an integer"); + static_assert(std::is_integral<N>::value, "lcm: N must be an integer"); + + return (m != 0 && n != 0) ? (plib::abs(m) / gcd(m, n)) * plib::abs(n) : 0; + } + static_assert(noexcept(constants<double>::one()) == true, "Not evaluated as constexpr"); } // namespace plib diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h index 1e197fdfc82..a06c67acd8e 100644 --- a/src/lib/netlist/plib/pmempool.h +++ b/src/lib/netlist/plib/pmempool.h @@ -59,7 +59,7 @@ namespace plib { plib::perrlogger("Found {} info blocks\n", sinfo().size()); plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc); } - plib::pdelete(b); + aligned_arena::free(b); //::operator delete(b->m_data); } } @@ -126,7 +126,7 @@ namespace plib { plib::terminate("mempool::free - block not found"); mp.m_blocks.erase(itb); - plib::pdelete(b); + aligned_arena::free(b); } sinfo().erase(it); } @@ -222,15 +222,13 @@ namespace plib { size_type m_pos; }; - block * new_block(size_type min_bytes) { - auto *b = plib::pnew<block>(*this, min_bytes); + auto *b = aligned_arena::alloc<block>(*this, min_bytes); m_blocks.push_back(b); return b; } - static std::unordered_map<void *, info> &sinfo() { static std::unordered_map<void *, info> spinfo; diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h index bbbe95ded05..a9df2f6b4aa 100644 --- a/src/lib/netlist/plib/ppmf.h +++ b/src/lib/netlist/plib/ppmf.h @@ -273,7 +273,7 @@ namespace plib { #endif } template<typename O> - R call(O *obj, Targs... args) const noexcept(true) + 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)...); @@ -311,7 +311,7 @@ namespace plib { m_obj = reinterpret_cast<generic_class *>(object); } - inline R operator()(Targs ... args) const noexcept(true) + inline R operator()(Targs... args) const noexcept(true) { return this->call(m_obj, std::forward<Targs>(args)...); } diff --git a/src/lib/netlist/plib/ptime.h b/src/lib/netlist/plib/ptime.h index df0bac92477..82ee2213015 100644 --- a/src/lib/netlist/plib/ptime.h +++ b/src/lib/netlist/plib/ptime.h @@ -80,32 +80,41 @@ namespace plib m_time -= rhs.m_time; return *this; } - C14CONSTEXPR ptime &operator*=(const mult_type factor) noexcept { m_time *= static_cast<internal_type>(factor); return *this; } + + template <typename M> + C14CONSTEXPR ptime &operator*=(const M factor) noexcept + { + static_assert(plib::is_integral<M>::value, "Factor must be an integral type"); + m_time *= factor; + return *this; + } template <typename O> - friend constexpr const ptime operator-(const ptime &lhs, const ptime<O, RES> &rhs) noexcept + constexpr const ptime operator-(const ptime<O, RES> &rhs) const noexcept { static_assert(ptime_le<ptime<O, RES>, ptime>::value, "Invalid ptime type"); - return ptime(lhs.m_time - rhs.m_time); + return ptime(m_time - rhs.m_time); } template <typename O> - friend constexpr const ptime operator+(const ptime &lhs, const ptime<O, RES> &rhs) noexcept + constexpr const ptime operator+(const ptime<O, RES> &rhs) const noexcept { static_assert(ptime_le<ptime<O, RES>, ptime>::value, "Invalid ptime type"); - return ptime(lhs.m_time + rhs.m_time); + return ptime(m_time + rhs.m_time); } - friend constexpr const ptime operator*(ptime lhs, const mult_type factor) noexcept + template <typename M> + constexpr const ptime operator*(const M &factor) const noexcept { - return ptime(lhs.m_time * factor); + static_assert(plib::is_integral<M>::value, "Factor must be an integral type"); + return ptime(m_time * static_cast<mult_type>(factor)); } template <typename O> - friend constexpr mult_type operator/(const ptime lhs, const ptime<O, RES> rhs) noexcept + constexpr const mult_type operator/(const ptime<O, RES> &rhs) const noexcept { static_assert(ptime_le<ptime<O, RES>, ptime>::value, "Invalid ptime type"); - return static_cast<mult_type>(lhs.m_time / rhs.m_time); + return static_cast<mult_type>(m_time / rhs.m_time); } friend constexpr bool operator<(const ptime lhs, const ptime rhs) noexcept @@ -159,6 +168,10 @@ namespace plib constexpr double as_float() const noexcept { return as_fp<float>(); } constexpr double as_long_double() const noexcept { return as_fp<long double>(); } + + constexpr ptime shl(unsigned shift) const noexcept { return ptime(m_time << shift); } + constexpr ptime shr(unsigned shift) const noexcept { return ptime(m_time >> shift); } + // for save states .... C14CONSTEXPR internal_type *get_internaltype_ptr() noexcept { return &m_time; } @@ -202,7 +215,6 @@ namespace plib internal_type m_time; }; - } // namespace plib diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h index 7619faa1348..32ec6e7f9bf 100644 --- a/src/lib/netlist/plib/ptypes.h +++ b/src/lib/netlist/plib/ptypes.h @@ -82,58 +82,6 @@ namespace plib template<typename... Ts> inline void unused_var(Ts&&...) noexcept {} - //============================================================ - // is_pow2 - //============================================================ - template <typename T> - constexpr bool is_pow2(T v) noexcept - { - static_assert(is_integral<T>::value, "is_pow2 needs integer arguments"); - return !(v & (v-1)); - } - - //============================================================ - // abs, lcd, gcm - //============================================================ - - template<typename T> - constexpr - typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type - abs(T v) noexcept - { - return v < 0 ? -v : v; - } - - template<typename T> - constexpr - typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, T>::type - abs(T v) noexcept - { - return v; - } - - template<typename M, typename N> - constexpr typename std::common_type<M, N>::type - gcd(M m, N n) noexcept - { - static_assert(std::is_integral<M>::value, "gcd: M must be an integer"); - static_assert(std::is_integral<N>::value, "gcd: N must be an integer"); - - return m == 0 ? plib::abs(n) - : n == 0 ? plib::abs(m) - : gcd(n, m % n); - } - - template<typename M, typename N> - constexpr typename std::common_type<M, N>::type - lcm(M m, N n) noexcept - { - static_assert(std::is_integral<M>::value, "lcm: M must be an integer"); - static_assert(std::is_integral<N>::value, "lcm: N must be an integer"); - - return (m != 0 && n != 0) ? (plib::abs(m) / gcd(m, n)) * plib::abs(n) : 0; - } - } // namespace plib //============================================================ |