summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2020-01-12 17:16:25 +0100
committer couriersud <couriersud@gmx.org>2020-01-12 17:16:25 +0100
commit9d7cbcaa4006f7c6dea32fdf29b2c8cce094b895 (patch)
tree918d2ca6d325e21599a39d00bc4d08f709704230
parent07f26f8e066d20acc39517ffc9ba65619981f757 (diff)
netlist: Code maintenance. (nw)
Introduce an additional absolute time type netlist_time_ext to identify whether absolute or relative time is used in the netlist code. Extend ptime code to allow operations between ptime derived types with different internal types. In addition rewrote main queue serve loops. Adds a very small performance increase.
-rw-r--r--src/devices/machine/netlist.cpp41
-rw-r--r--src/devices/machine/netlist.h10
-rw-r--r--src/lib/netlist/devices/nld_system.cpp2
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.h2
-rw-r--r--src/lib/netlist/nl_base.cpp15
-rw-r--r--src/lib/netlist/nl_base.h85
-rw-r--r--src/lib/netlist/nl_config.h13
-rw-r--r--src/lib/netlist/nltypes.h5
-rw-r--r--src/lib/netlist/plib/pconfig.h2
-rw-r--r--src/lib/netlist/plib/plists.h2
-rw-r--r--src/lib/netlist/plib/ptime.h57
-rw-r--r--src/lib/netlist/prg/nltool.cpp10
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp12
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h4
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp4
15 files changed, 161 insertions, 103 deletions
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index 6d2225fe9fc..a6a8325d818 100644
--- a/src/devices/machine/netlist.cpp
+++ b/src/devices/machine/netlist.cpp
@@ -422,7 +422,7 @@ public:
, m_in(*this, "IN")
, m_cur(0.0)
, m_last_pos(0)
- , m_last_buffer_time(*this, "m_last_buffer", netlist::netlist_time::zero())
+ , m_last_buffer_time(*this, "m_last_buffer", netlist::netlist_time_ext::zero())
{
}
@@ -432,12 +432,12 @@ public:
{
m_cur = 0.0;
m_last_pos = 0;
- m_last_buffer_time = netlist::netlist_time::zero();
+ m_last_buffer_time = netlist::netlist_time_ext::zero();
}
- ATTR_HOT void sound_update(const netlist::netlist_time &upto)
+ ATTR_HOT void sound_update(const netlist::netlist_time_ext &upto)
{
- int pos = (upto - m_last_buffer_time) / m_sample_time;
+ int pos = (upto - m_last_buffer_time()) / m_sample_time;
if (pos > m_bufsize)
throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), pos, m_bufsize);
while (m_last_pos < pos )
@@ -471,7 +471,7 @@ public:
}
public:
- ATTR_HOT void buffer_reset(const netlist::netlist_time &upto)
+ ATTR_HOT void buffer_reset(const netlist::netlist_time_ext &upto)
{
m_last_pos = 0;
m_last_buffer_time = upto;
@@ -489,7 +489,7 @@ private:
netlist::analog_input_t m_in;
double m_cur;
int m_last_pos;
- netlist::state_var<netlist::netlist_time> m_last_buffer_time;
+ netlist::state_var<netlist::netlist_time_ext> m_last_buffer_time;
};
// ----------------------------------------------------------------------------------------
@@ -1022,7 +1022,7 @@ netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const ch
netlist_mame_device::netlist_mame_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, m_icount(0)
- , m_old(netlist::netlist_time::zero())
+ , m_old(netlist::netlist_time_ext::zero())
, m_setup_func(nullptr)
{
}
@@ -1155,7 +1155,7 @@ void netlist_mame_device::device_start()
save_state();
- m_old = netlist::netlist_time::zero();
+ m_old = netlist::netlist_time_ext::zero();
m_rem = netlist::netlist_time::zero();
LOGDEVCALLS("device_start exit\n");
@@ -1171,7 +1171,7 @@ void netlist_mame_device::device_clock_changed()
void netlist_mame_device::device_reset()
{
LOGDEVCALLS("device_reset\n");
- m_old = netlist::netlist_time::zero();
+ m_old = netlist::netlist_time_ext::zero();
m_rem = netlist::netlist_time::zero();
netlist().exec().reset();
}
@@ -1197,13 +1197,12 @@ ATTR_COLD void netlist_mame_device::device_pre_save()
netlist().run_state_manager().pre_save();
}
-void netlist_mame_device::update_icount(netlist::netlist_time time) noexcept
+void netlist_mame_device::update_icount(netlist::netlist_time_ext time) noexcept
{
- const netlist::netlist_time newt(time);
- const netlist::netlist_time delta(newt - m_old + m_rem);
- const uint64_t d = delta / m_div;
- m_old = newt;
- m_rem = delta - (m_div * d);
+ const netlist::netlist_time_ext delta(time - m_old + m_rem);
+ const auto d(delta / m_div);
+ m_old = time;
+ m_rem = static_cast<netlist::netlist_time>(delta - (m_div * d));
m_icount -= d;
}
@@ -1321,13 +1320,13 @@ ATTR_HOT void netlist_mame_cpu_device::execute_run()
m_genPC++;
m_genPC &= 255;
debugger_instruction_hook(m_genPC);
- netlist().exec().process_queue(m_div);
+ netlist().exec().process_queue(static_cast<netlist::netlist_time_ext>(nl_clock_period()));
update_icount(netlist().exec().time());
}
}
else
{
- netlist().exec().process_queue(m_div * m_icount);
+ netlist().exec().process_queue(static_cast<netlist::netlist_time_ext>(nl_clock_period()) * m_icount);
update_icount(netlist().exec().time());
}
}
@@ -1475,11 +1474,11 @@ void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream
}
}
- netlist::netlist_time cur(netlist().exec().time());
+ auto cur(netlist().exec().time());
+ const auto delta(static_cast<netlist::netlist_time_ext>(nl_clock_period()) * samples);
+ netlist().exec().process_queue(delta);
- netlist().exec().process_queue(m_div * samples);
-
- cur += (m_div * samples);
+ cur += delta;
for (auto &e : m_out)
{
diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h
index a7667940809..0be9fcac109 100644
--- a/src/devices/machine/netlist.h
+++ b/src/devices/machine/netlist.h
@@ -70,12 +70,12 @@ public:
virtual ~netlist_mame_device();
- void set_setup_func(func_type &&func) { m_setup_func = std::move(func); }
+ void set_setup_func(func_type &&func) noexcept { m_setup_func = std::move(func); }
netlist::setup_t &setup();
netlist_mame_t &netlist() noexcept { return *m_netlist; }
- void update_icount(netlist::netlist_time time) noexcept;
+ void update_icount(netlist::netlist_time_ext time) noexcept;
void check_mame_abort_slice() noexcept;
static void register_memregion_source(netlist::nlparse_t &setup, device_t &dev, const char *name);
@@ -98,7 +98,7 @@ protected:
virtual void device_pre_save() override;
virtual void device_clock_changed() override;
- netlist::netlist_time m_div;
+ netlist::netlist_time nl_clock_period() const noexcept { return m_div; }
plib::unique_ptr<netlist::netlist_state_t> base_validity_check(validity_checker &valid) const;
@@ -107,9 +107,9 @@ private:
void common_dev_start(netlist::netlist_state_t *lnetlist) const;
- /* timing support here - so sound can hijack it ... */
+ netlist::netlist_time m_div;
netlist::netlist_time m_rem;
- netlist::netlist_time m_old;
+ netlist::netlist_time_ext m_old;
std::unique_ptr<netlist_mame_t> m_netlist;
diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp
index b4483b84ad7..8d8b090c5d0 100644
--- a/src/lib/netlist/devices/nld_system.cpp
+++ b/src/lib/netlist/devices/nld_system.cpp
@@ -47,7 +47,7 @@ namespace devices
NETLIB_UPDATE(extclock)
{
- m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off);
+ m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off());
m_off = netlist_time::zero();
if (++m_cnt >= m_size)
m_cnt = 0;
diff --git a/src/lib/netlist/devices/nlid_truthtable.h b/src/lib/netlist/devices/nlid_truthtable.h
index 2677ce7433a..a8143f909a8 100644
--- a/src/lib/netlist/devices/nlid_truthtable.h
+++ b/src/lib/netlist/devices/nlid_truthtable.h
@@ -142,7 +142,7 @@ namespace devices
template<bool doOUT>
void process() noexcept
{
- netlist_time mt(netlist_time::zero());
+ netlist_time_ext mt(netlist_time_ext::zero());
type_t nstate(0);
type_t ign(m_ign);
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 81892930967..fa789ba59a9 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -102,7 +102,7 @@ namespace netlist
// ----------------------------------------------------------------------------------------
detail::queue_t::queue_t(netlist_t &nl)
- : timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>(512)
+ : timed_queue<plib::pqentry_t<net_t *, netlist_time_ext>, false>(512)
, netlist_ref(nl)
, m_qsize(0)
, m_times(512)
@@ -129,7 +129,6 @@ namespace netlist
}
}
-
void detail::queue_t::on_post_load(plib::state_manager_t &manager)
{
plib::unused_var(manager);
@@ -137,7 +136,7 @@ namespace netlist
for (std::size_t i = 0; i < m_qsize; i++ )
{
detail::net_t *n = state().nets()[m_net_ids[i]].get();
- this->push<false>(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
+ this->push<false>(queue_t::entry_t(netlist_time_ext::from_raw(m_times[i]),n));
}
}
@@ -183,7 +182,7 @@ namespace netlist
netlist_t::netlist_t(netlist_state_t &state)
: m_state(state)
, m_solver(nullptr)
- , m_time(netlist_time::zero())
+ , m_time(netlist_time_ext::zero())
, m_mainclock(nullptr)
, m_queue(*this)
, m_use_stats(false)
@@ -325,10 +324,10 @@ namespace netlist
log().debug("Searching for solver\n");
m_solver = m_state.get_single_device<devices::NETLIB_NAME(solver)>("solver");
- m_time = netlist_time::zero();
+ m_time = netlist_time_ext::zero();
m_queue.clear();
if (m_mainclock != nullptr)
- m_mainclock->m_Q.net().set_next_scheduled_time(netlist_time::zero());
+ m_mainclock->m_Q.net().set_next_scheduled_time(netlist_time_ext::zero());
//if (m_solver != nullptr)
// m_solver->reset();
@@ -654,7 +653,7 @@ namespace netlist
, m_new_Q(*this, "m_new_Q", 0)
, m_cur_Q (*this, "m_cur_Q", 0)
, m_in_queue(*this, "m_in_queue", queue_status::DELIVERED)
- , m_next_scheduled_time(*this, "m_time", netlist_time::zero())
+ , m_next_scheduled_time(*this, "m_time", netlist_time_ext::zero())
, m_railterminal(railterminal)
{
}
@@ -675,7 +674,7 @@ namespace netlist
void detail::net_t::reset() noexcept
{
- m_next_scheduled_time = netlist_time::zero();
+ m_next_scheduled_time = netlist_time_ext::zero();
m_in_queue = queue_status::DELIVERED;
m_new_Q = 0;
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 430a73f4ee5..625696ddf93 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -350,6 +350,10 @@ namespace netlist
C14CONSTEXPR operator T & () noexcept { return m_value; }
//! Return const value of state variable.
constexpr operator const T & () const noexcept { return m_value; }
+ //! Return non-const value of state variable.
+ C14CONSTEXPR T & operator ()() noexcept { return m_value; }
+ //! Return const value of state variable.
+ constexpr const T & operator ()() const noexcept { return m_value; }
//! Return pointer to state variable.
C14CONSTEXPR T * ptr() noexcept { return &m_value; }
//! Return const pointer to state variable.
@@ -674,8 +678,8 @@ namespace netlist
template <bool KEEP_STATS>
void update_devs() noexcept;
- netlist_time next_scheduled_time() const noexcept { return m_next_scheduled_time; }
- void set_next_scheduled_time(netlist_time ntime) noexcept { m_next_scheduled_time = ntime; }
+ netlist_time_ext next_scheduled_time() const noexcept { return m_next_scheduled_time; }
+ void set_next_scheduled_time(netlist_time_ext ntime) noexcept { m_next_scheduled_time = ntime; }
bool isRailNet() const noexcept { return !(m_railterminal == nullptr); }
core_terminal_t & railterminal() const noexcept { return *m_railterminal; }
@@ -733,7 +737,7 @@ namespace netlist
}
// only used for logic nets
- void set_Q_time(netlist_sig_t newQ, netlist_time at) noexcept
+ void set_Q_time(netlist_sig_t newQ, netlist_time_ext at) noexcept
{
if (newQ != m_new_Q)
{
@@ -756,10 +760,10 @@ namespace netlist
netlist_sig_t *Q_state_ptr() noexcept { return m_cur_Q.ptr(); }
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<netlist_time> m_next_scheduled_time;
+ 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<netlist_time_ext> m_next_scheduled_time;
core_terminal_t * m_railterminal;
plib::linkedlist_t<core_terminal_t> m_list_active;
@@ -956,7 +960,7 @@ namespace netlist
m_my_net.set_Q_and_push(newQ, delay); // take the shortcut
}
- void set_Q_time(netlist_sig_t newQ, netlist_time at) noexcept
+ void set_Q_time(netlist_sig_t newQ, netlist_time_ext at) noexcept
{
m_my_net.set_Q_time(newQ, at); // take the shortcut
}
@@ -1317,13 +1321,13 @@ namespace netlist
class queue_t :
//public timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>,
- public timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>,
+ public timed_queue<plib::pqentry_t<net_t *, netlist_time_ext>, false>,
public netlist_ref,
public plib::state_manager_t::callback_t
{
public:
- using base_queue = timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>;
- using entry_t = plib::pqentry_t<net_t *, netlist_time>;
+ using entry_t = plib::pqentry_t<net_t *, netlist_time_ext>;
+ using base_queue = timed_queue<entry_t, false>;
explicit queue_t(netlist_t &nl);
~queue_t() noexcept override = default;
@@ -1340,7 +1344,7 @@ namespace netlist
private:
std::size_t m_qsize;
- std::vector<netlist_time::internal_type> m_times;
+ std::vector<netlist_time_ext::internal_type> m_times;
std::vector<std::size_t> m_net_ids;
};
@@ -1597,7 +1601,7 @@ namespace netlist
NETLIB_RESETI()
{
- m_Q.net().set_next_scheduled_time(netlist_time::zero());
+ m_Q.net().set_next_scheduled_time(netlist_time_ext::zero());
}
NETLIB_UPDATE_PARAMI()
@@ -1618,6 +1622,7 @@ namespace netlist
param_fp_t m_freq;
};
} // namespace devices
+
// -----------------------------------------------------------------------------
// netlist_t
// -----------------------------------------------------------------------------
@@ -1634,9 +1639,9 @@ namespace netlist
// run functions
- netlist_time time() const noexcept { return m_time; }
+ netlist_time_ext time() const noexcept { return m_time; }
- void process_queue(netlist_time delta) noexcept;
+ void process_queue(netlist_time_ext delta) noexcept;
void abort_current_queue_slice() noexcept
{
if (!NL_USE_QUEUE_STATS || !m_use_stats)
@@ -1695,14 +1700,14 @@ namespace netlist
private:
template <bool KEEP_STATS>
- void process_queue_stats(netlist_time delta) noexcept;
+ void process_queue_stats(netlist_time_ext delta) noexcept;
netlist_state_t & m_state;
devices::NETLIB_NAME(solver) * m_solver;
// mostly rw
PALIGNAS_CACHELINE()
- netlist_time m_time;
+ netlist_time_ext m_time;
devices::NETLIB_NAME(mainclock) * m_mainclock;
PALIGNAS_CACHELINE()
@@ -2064,57 +2069,63 @@ namespace netlist
}
template <bool KEEP_STATS>
- inline void netlist_t::process_queue_stats(const netlist_time delta) noexcept
+ inline void netlist_t::process_queue_stats(const netlist_time_ext delta) noexcept
{
- netlist_time stop(m_time + delta);
+ netlist_time_ext stop(m_time + delta);
qpush(detail::queue_t::entry_t(stop, nullptr));
if (m_mainclock == nullptr)
{
- detail::queue_t::entry_t e(m_queue.pop());
- m_time = e.exec_time();
- while (e.object() != nullptr)
+ m_time = m_queue.top().exec_time();
+ detail::net_t *obj(m_queue.top().object());
+ m_queue.pop();
+
+ while (obj != nullptr)
{
- e.object()->template update_devs<KEEP_STATS>();
+ obj->template update_devs<KEEP_STATS>();
if (KEEP_STATS)
m_perf_out_processed.inc();
- e = m_queue.pop();
- m_time = e.exec_time();
+ const detail::queue_t::entry_t *top = &m_queue.top();
+ m_time = top->exec_time();
+ obj = top->object();
+ m_queue.pop();
}
}
else
{
logic_net_t &mc_net(m_mainclock->m_Q.net());
const netlist_time inc(m_mainclock->m_inc);
- netlist_time mc_time(mc_net.next_scheduled_time());
+ netlist_time_ext mc_time(mc_net.next_scheduled_time());
do
{
- while (m_queue.top().exec_time() > mc_time)
+ const detail::queue_t::entry_t *top = &m_queue.top();
+ while (top->exec_time() > mc_time)
{
m_time = mc_time;
mc_net.toggle_new_Q();
mc_net.update_devs<KEEP_STATS>();
+ top = &m_queue.top();
mc_time += inc;
}
- detail::queue_t::entry_t e(m_queue.pop());
- m_time = e.exec_time();
- if (e.object() != nullptr)
- {
- e.object()->template update_devs<KEEP_STATS>();
- if (KEEP_STATS)
- m_perf_out_processed.inc();
- }
+ m_time = top->exec_time();
+ const auto obj(top->object());
+ m_queue.pop();
+ if (obj != nullptr)
+ obj->template update_devs<KEEP_STATS>();
else
break;
- } while (true); //while (e.m_object != nullptr);
+ if (KEEP_STATS)
+ m_perf_out_processed.inc();
+ } while (true);
+
mc_net.set_next_scheduled_time(mc_time);
}
}
- inline void netlist_t::process_queue(netlist_time delta) noexcept
+ inline void netlist_t::process_queue(netlist_time_ext delta) noexcept
{
if (!m_use_stats)
process_queue_stats<false>(delta);
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index 663ab961275..47707af7d22 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -137,11 +137,16 @@
///
/// Uses nano-second resolution - Sufficient for now
-static constexpr const auto NETLIST_INTERNAL_RES = 1000000000;
-
-// FIXME: Belongs into MAME netlist.h
+#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
/// \brief Floating point types used
diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h
index af3ccd5828b..3688c41421d 100644
--- a/src/lib/netlist/nltypes.h
+++ b/src/lib/netlist/nltypes.h
@@ -100,9 +100,12 @@ namespace netlist
} // namespace detail
#if (PHAS_INT128)
- using netlist_time = ptime<INT128, NETLIST_INTERNAL_RES>;
+ //using netlist_time = plib::ptime<INT128, NETLIST_INTERNAL_RES>;
+ using netlist_time = plib::ptime<std::int64_t, NETLIST_INTERNAL_RES>;
+ using netlist_time_ext = plib::ptime<INT128, NETLIST_INTERNAL_RES>;
#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
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index f08c9c025ea..0870d8c59d5 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 5% slower on a kaby lake processor.
+/// This is about 15% slower on a kaby lake processor for pongf.
///
#ifndef PHAS_INT128
#define PHAS_INT128 (0)
diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h
index b6a65ff5d99..82a963735f5 100644
--- a/src/lib/netlist/plib/plists.h
+++ b/src/lib/netlist/plib/plists.h
@@ -326,7 +326,7 @@ namespace plib {
m_prof_call.inc();
}
- T pop() noexcept { return *(--m_end); }
+ void pop() noexcept { --m_end; }
const T &top() const noexcept { return *(m_end-1); }
template <bool KEEPSTAT, class R>
diff --git a/src/lib/netlist/plib/ptime.h b/src/lib/netlist/plib/ptime.h
index 214f121c2df..add901db872 100644
--- a/src/lib/netlist/plib/ptime.h
+++ b/src/lib/netlist/plib/ptime.h
@@ -8,6 +8,8 @@
/// \file ptime.h
///
+#include <type_traits>
+
#include "pconfig.h"
#include "pmath.h" // std::floor
#include "ptypes.h"
@@ -19,6 +21,19 @@
namespace plib
{
+ template <typename T, typename U>
+ struct ptime_le
+ {
+ const static bool value = sizeof(T) <= sizeof(U);
+ };
+
+#if 0
+ template<typename T, typename U>
+ struct ptime_res {
+ using type = typename std::conditional<sizeof(T) >= sizeof(U), T, U>::type;
+ };
+#endif
+
template <typename TYPE, TYPE RES>
struct ptime final
{
@@ -27,6 +42,9 @@ namespace plib
using internal_type = TYPE;
using mult_type = TYPE;
+ template <typename altTYPE, altTYPE>
+ friend class ptime;
+
constexpr ptime() noexcept : m_time(0) {}
~ptime() noexcept = default;
@@ -43,18 +61,39 @@ namespace plib
constexpr explicit ptime(const internal_type nom, const internal_type den) noexcept
: m_time(nom * (RES / den)) { }
- C14CONSTEXPR ptime &operator+=(const ptime &rhs) noexcept { m_time += rhs.m_time; return *this; }
- C14CONSTEXPR ptime &operator-=(const ptime &rhs) noexcept { m_time -= rhs.m_time; return *this; }
+ // FIXME: check for overflow
+ template <typename O>
+ constexpr explicit ptime(const ptime<O, RES> &rhs) noexcept
+ : m_time(rhs.as_raw()) { }
+
+ template <typename O>
+ C14CONSTEXPR ptime &operator+=(const ptime<O, RES> &rhs) noexcept
+ {
+ static_assert(ptime_le<ptime<O, RES>, ptime>::value, "Invalid ptime type");
+ m_time += rhs.m_time;
+ return *this;
+ }
+ template <typename O>
+ C14CONSTEXPR ptime &operator-=(const ptime<O, RES> &rhs) noexcept
+ {
+ static_assert(ptime_le<ptime<O, RES>, ptime>::value, "Invalid ptime type");
+ m_time -= rhs.m_time;
+ return *this;
+ }
C14CONSTEXPR ptime &operator*=(const mult_type factor) noexcept { m_time *= static_cast<internal_type>(factor); return *this; }
- friend constexpr const ptime operator-(ptime lhs, const ptime rhs) noexcept
+ template <typename O>
+ friend constexpr const ptime operator-(const ptime &lhs, const ptime<O, RES> &rhs) noexcept
{
- return ptime(lhs.m_time - rhs.m_time);
+ static_assert(ptime_le<ptime<O, RES>, ptime>::value, "Invalid ptime type");
+ return ptime(lhs.m_time - rhs.as_raw());
}
- friend constexpr const ptime operator+(ptime lhs, const ptime rhs) noexcept
+ template <typename O>
+ friend constexpr const ptime operator+(const ptime &lhs, const ptime<O, RES> &rhs) noexcept
{
- return ptime(lhs.m_time + rhs.m_time);
+ static_assert(ptime_le<ptime<O, RES>, ptime>::value, "Invalid ptime type");
+ return ptime(lhs.m_time + rhs.as_raw());
}
friend constexpr const ptime operator*(ptime lhs, const mult_type factor) noexcept
@@ -62,9 +101,11 @@ namespace plib
return ptime(lhs.m_time * factor);
}
- friend constexpr mult_type operator/(const ptime lhs, const ptime rhs) noexcept
+ template <typename O>
+ friend constexpr mult_type operator/(const ptime lhs, const ptime<O, RES> rhs) noexcept
{
- return static_cast<mult_type>(lhs.m_time / rhs.m_time);
+ static_assert(ptime_le<ptime<O, RES>, ptime>::value, "Invalid ptime type");
+ return static_cast<mult_type>(lhs.m_time / rhs.as_raw());
}
friend constexpr bool operator<(const ptime lhs, const ptime rhs) noexcept
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index f19cd2a339c..b6594b02d79 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -323,7 +323,7 @@ struct input_t
if (e != 3)
plib::pthrow<netlist::nl_exception>(plib::pfmt("error {1} scanning line {2}\n")(e)(line));
m_value = static_cast<nl_fptype>(val);
- m_time = netlist::netlist_time::from_fp(t);
+ m_time = netlist::netlist_time_ext::from_fp(t);
m_param = setup.find_param(pstring(buf.data()), true);
}
@@ -346,7 +346,7 @@ struct input_t
}
}
- netlist::netlist_time m_time;
+ netlist::netlist_time_ext m_time;
netlist::param_t *m_param;
nl_fptype m_value;
};
@@ -377,7 +377,7 @@ void tool_app_t::run()
{
plib::chrono::timer<plib::chrono::system_ticks> t;
std::vector<input_t> inps;
- netlist::netlist_time ttr;
+ netlist::netlist_time_ext ttr;
netlist_tool_t nt(*this, "netlist");
{
@@ -398,7 +398,7 @@ void tool_app_t::run()
nt.exec().reset();
inps = read_input(nt.setup(), opt_inp());
- ttr = netlist::netlist_time::from_fp(opt_ttr());
+ ttr = netlist::netlist_time_ext::from_fp(opt_ttr());
}
@@ -406,7 +406,7 @@ void tool_app_t::run()
t.reset();
- netlist::netlist_time nlt = nt.exec().time();
+ netlist::netlist_time_ext nlt = nt.exec().time();
{
auto t_guard(t.guard());
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
index 2efa880fd87..493973d6dc2 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.cpp
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -45,7 +45,7 @@ namespace solver
, m_stat_calculations(*this, "m_stat_calculations", 0)
, m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0)
, m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0)
- , m_last_step(*this, "m_last_step", netlist_time::zero())
+ , m_last_step(*this, "m_last_step", netlist_time_ext::zero())
, m_fb_sync(*this, "FB_sync")
, m_Q_sync(*this, "Q_sync")
, m_ops(0)
@@ -358,7 +358,7 @@ namespace solver
void matrix_solver_t::reset()
{
- m_last_step = netlist_time::zero();
+ m_last_step = netlist_time_ext::zero();
}
void matrix_solver_t::update() noexcept
@@ -397,18 +397,18 @@ namespace solver
d->timestep(dd);
}
- const netlist_time matrix_solver_t::solve(netlist_time now)
+ const netlist_time matrix_solver_t::solve(netlist_time_ext now)
{
- const netlist_time delta = now - m_last_step;
+ const netlist_time_ext delta = now - m_last_step();
// We are already up to date. Avoid oscillations.
// FIXME: Make this a parameter!
- if (delta < netlist_time::quantum())
+ if (delta < netlist_time_ext::quantum())
return netlist_time::zero();
// update all terminals for new time step
m_last_step = now;
- step(delta);
+ step(static_cast<netlist_time>(delta));
++m_stat_vsolver_calls;
if (has_dynamic_devices())
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index cc6d248caa6..2c7bc4fff7b 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -177,7 +177,7 @@ namespace solver
// after every call to solve, update inputs must be called.
// this can be done as well as a batch to ease parallel processing.
- const netlist_time solve(netlist_time now);
+ const netlist_time solve(netlist_time_ext now);
void update_inputs();
bool has_dynamic_devices() const noexcept { return m_dynamic_devices.size() > 0; }
@@ -235,7 +235,7 @@ namespace solver
state_var<std::size_t> m_stat_newton_raphson;
state_var<std::size_t> m_stat_vsolver_calls;
- state_var<netlist_time> m_last_step;
+ state_var<netlist_time_ext> m_last_step;
std::vector<core_device_t *> m_step_devices;
std::vector<core_device_t *> m_dynamic_devices;
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 4b24e003d52..920e3a82452 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -68,10 +68,10 @@ namespace devices
if (m_params.m_dynamic_ts)
return;
- netlist_time now(exec().time());
+ netlist_time_ext now(exec().time());
// force solving during start up if there are no time-step devices
// FIXME: Needs a more elegant solution
- bool force_solve = (now < netlist_time::from_fp<decltype(m_params.m_max_timestep)>(2 * m_params.m_max_timestep));
+ bool force_solve = (now < netlist_time_ext::from_fp<decltype(m_params.m_max_timestep)>(2 * m_params.m_max_timestep));
std::size_t nthreads = std::min(static_cast<std::size_t>(m_params.m_parallel()), plib::omp::get_max_threads());