summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/netlist.lua6
-rw-r--r--src/lib/netlist/core/analog.h5
-rw-r--r--src/lib/netlist/core/base_objects.h3
-rw-r--r--src/lib/netlist/core/core_device.h130
-rw-r--r--src/lib/netlist/core/device.h124
-rw-r--r--src/lib/netlist/core/exec.h120
-rw-r--r--src/lib/netlist/core/nets.h119
-rw-r--r--src/lib/netlist/core/param.h67
-rw-r--r--src/lib/netlist/nl_base.cpp77
-rw-r--r--src/lib/netlist/nl_base.h493
10 files changed, 521 insertions, 623 deletions
diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua
index 0d55049d7b3..b46dfec4d3a 100644
--- a/scripts/src/netlist.lua
+++ b/scripts/src/netlist.lua
@@ -50,9 +50,15 @@ project "netlist"
MAME_DIR .. "src/lib/netlist/nl_setup.cpp",
MAME_DIR .. "src/lib/netlist/nl_setup.h",
MAME_DIR .. "src/lib/netlist/nl_types.h",
+ MAME_DIR .. "src/lib/netlist/core/analog.h",
MAME_DIR .. "src/lib/netlist/core/base_objects.h",
+ MAME_DIR .. "src/lib/netlist/core/core_device.h",
+ MAME_DIR .. "src/lib/netlist/core/device.h",
+ MAME_DIR .. "src/lib/netlist/core/exec.h",
MAME_DIR .. "src/lib/netlist/core/logic_family.h",
+ MAME_DIR .. "src/lib/netlist/core/logic.h",
MAME_DIR .. "src/lib/netlist/core/nets.h",
+ MAME_DIR .. "src/lib/netlist/core/object_array.h",
MAME_DIR .. "src/lib/netlist/core/param.h",
MAME_DIR .. "src/lib/netlist/core/setup.h",
MAME_DIR .. "src/lib/netlist/core/state_var.h",
diff --git a/src/lib/netlist/core/analog.h b/src/lib/netlist/core/analog.h
index a868443b8d2..4bc986f48fc 100644
--- a/src/lib/netlist/core/analog.h
+++ b/src/lib/netlist/core/analog.h
@@ -156,6 +156,11 @@ namespace netlist
analog_net_t m_my_net;
};
+ inline solver::matrix_solver_t *analog_t::solver() const noexcept
+ {
+ return (this->has_net() ? net().solver() : nullptr);
+ }
+
} // namespace netlist
diff --git a/src/lib/netlist/core/base_objects.h b/src/lib/netlist/core/base_objects.h
index 656898b21d0..140fde1149e 100644
--- a/src/lib/netlist/core/base_objects.h
+++ b/src/lib/netlist/core/base_objects.h
@@ -181,9 +181,6 @@ namespace netlist
netlist_state_t &state() noexcept;
const netlist_state_t &state() const noexcept;
- netlist_t &exec() noexcept;
- const netlist_t &exec() const noexcept;
-
private:
core_device_t * m_device;
};
diff --git a/src/lib/netlist/core/core_device.h b/src/lib/netlist/core/core_device.h
new file mode 100644
index 00000000000..e1df57deb50
--- /dev/null
+++ b/src/lib/netlist/core/core_device.h
@@ -0,0 +1,130 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+///
+/// \file device.h
+///
+
+#ifndef NL_CORE_DEVICE_H_
+#define NL_CORE_DEVICE_H_
+
+#include "../nltypes.h"
+#include "../plib/pstring.h"
+#include "base_objects.h"
+#include "logic_family.h"
+
+namespace netlist
+{
+ // -----------------------------------------------------------------------------
+ // core_device_t
+ // -----------------------------------------------------------------------------
+ // FIXME: belongs into detail namespace
+ class core_device_t : public detail::netlist_object_t
+ {
+ public:
+ core_device_t(netlist_state_t &owner, const pstring &name);
+ core_device_t(core_device_t &owner, const pstring &name);
+
+ PCOPYASSIGNMOVE(core_device_t, delete)
+
+ virtual ~core_device_t() noexcept = default;
+
+ void do_inc_active() noexcept
+ {
+ if (m_hint_deactivate)
+ {
+ if (++m_active_outputs == 1)
+ {
+ if (m_stats)
+ m_stats->m_stat_inc_active.inc();
+ inc_active();
+ }
+ }
+ }
+
+ void do_dec_active() noexcept
+ {
+ if (m_hint_deactivate)
+ if (--m_active_outputs == 0)
+ {
+ dec_active();
+ }
+ }
+
+ 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) noexcept { m_active_outputs = n; }
+
+ // stats
+ struct stats_t
+ {
+ // NL_KEEP_STATISTICS
+ plib::pperftime_t<true> m_stat_total_time;
+ plib::pperfcount_t<true> m_stat_call_count;
+ plib::pperfcount_t<true> m_stat_inc_active;
+ };
+
+ stats_t * stats() const noexcept { return m_stats.get(); }
+#if 0
+ virtual void update() noexcept { }
+#endif
+ virtual void reset() { }
+
+ protected:
+
+ virtual void inc_active() noexcept { }
+ virtual void dec_active() noexcept { }
+
+ log_type & log();
+
+ public:
+ virtual void timestep(timestep_type ts_type, nl_fptype st) noexcept { plib::unused_var(ts_type, st); }
+ virtual void update_terminals() noexcept { }
+
+ virtual void update_param() noexcept {}
+ virtual bool is_dynamic() const noexcept { return false; }
+ virtual bool is_timestep() const noexcept { return false; }
+
+ private:
+ bool m_hint_deactivate;
+ state_var_s32 m_active_outputs;
+ device_arena::unique_ptr<stats_t> m_stats;
+ };
+
+ // -----------------------------------------------------------------------------
+ // base_device_t
+ // -----------------------------------------------------------------------------
+
+ class base_device_t : public core_device_t
+ {
+ public:
+ base_device_t(netlist_state_t &owner, const pstring &name);
+ base_device_t(base_device_t &owner, const pstring &name);
+
+ PCOPYASSIGNMOVE(base_device_t, delete)
+
+ ~base_device_t() noexcept override = default;
+
+ 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)...);
+ }
+
+ void register_subalias(const pstring &name, const detail::core_terminal_t &term);
+ void register_subalias(const pstring &name, const pstring &aliased);
+
+ void connect(const pstring &t1, const pstring &t2);
+ void connect(const detail::core_terminal_t &t1, const detail::core_terminal_t &t2);
+ protected:
+
+ //NETLIB_UPDATE_TERMINALSI() { }
+
+ private:
+ };
+
+} // namespace netlist
+
+
+#endif // NL_CORE_DEVICE_H_
diff --git a/src/lib/netlist/core/device.h b/src/lib/netlist/core/device.h
index 99a5a1884ec..c087686b0dc 100644
--- a/src/lib/netlist/core/device.h
+++ b/src/lib/netlist/core/device.h
@@ -5,132 +5,20 @@
/// \file device.h
///
-#ifndef NL_CORE_DEVICE_H_
-#define NL_CORE_DEVICE_H_
+#ifndef NL_DEVICE_H_
+#define NL_DEVICE_H_
-#include "../nltypes.h"
-#include "../plib/pstring.h"
-#include "base_objects.h"
-#include "logic_family.h"
+#include "core_device.h"
#include "param.h"
namespace netlist
{
// -----------------------------------------------------------------------------
- // core_device_t
- // -----------------------------------------------------------------------------
- // FIXME: belongs into detail namespace
- class core_device_t : public detail::netlist_object_t
- {
- public:
- core_device_t(netlist_state_t &owner, const pstring &name);
- core_device_t(core_device_t &owner, const pstring &name);
-
- PCOPYASSIGNMOVE(core_device_t, delete)
-
- virtual ~core_device_t() noexcept = default;
-
- void do_inc_active() noexcept
- {
- if (m_hint_deactivate)
- {
- if (++m_active_outputs == 1)
- {
- if (m_stats)
- m_stats->m_stat_inc_active.inc();
- inc_active();
- }
- }
- }
-
- void do_dec_active() noexcept
- {
- if (m_hint_deactivate)
- if (--m_active_outputs == 0)
- {
- dec_active();
- }
- }
-
- 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) noexcept { m_active_outputs = n; }
-
- // stats
- struct stats_t
- {
- // NL_KEEP_STATISTICS
- plib::pperftime_t<true> m_stat_total_time;
- plib::pperfcount_t<true> m_stat_call_count;
- plib::pperfcount_t<true> m_stat_inc_active;
- };
-
- stats_t * stats() const noexcept { return m_stats.get(); }
-#if 0
- virtual void update() noexcept { }
-#endif
- virtual void reset() { }
-
- protected:
-
- virtual void inc_active() noexcept { }
- virtual void dec_active() noexcept { }
-
- log_type & log();
-
- public:
- virtual void timestep(timestep_type ts_type, nl_fptype st) noexcept { plib::unused_var(ts_type, st); }
- virtual void update_terminals() noexcept { }
-
- virtual void update_param() noexcept {}
- virtual bool is_dynamic() const noexcept { return false; }
- virtual bool is_timestep() const noexcept { return false; }
-
- private:
- bool m_hint_deactivate;
- state_var_s32 m_active_outputs;
- device_arena::unique_ptr<stats_t> m_stats;
- };
-
- // -----------------------------------------------------------------------------
- // base_device_t
- // -----------------------------------------------------------------------------
-
- class base_device_t : public core_device_t
- {
- public:
- base_device_t(netlist_state_t &owner, const pstring &name);
- base_device_t(base_device_t &owner, const pstring &name);
-
- PCOPYASSIGNMOVE(base_device_t, delete)
-
- ~base_device_t() noexcept override = default;
-
- 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)...);
- }
-
- void register_subalias(const pstring &name, const detail::core_terminal_t &term);
- void register_subalias(const pstring &name, const pstring &aliased);
-
- void connect(const pstring &t1, const pstring &t2);
- void connect(const detail::core_terminal_t &t1, const detail::core_terminal_t &t2);
- protected:
-
- //NETLIB_UPDATE_TERMINALSI() { }
-
- private:
- };
-
- // -----------------------------------------------------------------------------
// device_t
// -----------------------------------------------------------------------------
- class device_t : public base_device_t,
- public logic_family_t
+ class device_t : public base_device_t,
+ public logic_family_t
{
public:
device_t(netlist_state_t &owner, const pstring &name);
@@ -160,4 +48,4 @@ namespace netlist
} // namespace netlist
-#endif // NL_CORE_DEVICE_H_
+#endif // NL_DEVICE_H_
diff --git a/src/lib/netlist/core/exec.h b/src/lib/netlist/core/exec.h
new file mode 100644
index 00000000000..307baa6b0f2
--- /dev/null
+++ b/src/lib/netlist/core/exec.h
@@ -0,0 +1,120 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+///
+/// \file exec.h
+///
+
+#ifndef NL_CORE_EXEC_H_
+#define NL_CORE_EXEC_H_
+
+#include "base_objects.h"
+#include "state_var.h"
+
+#include "../nltypes.h"
+#include "../plib/plists.h"
+#include "../plib/pstring.h"
+
+namespace netlist
+{
+ // -----------------------------------------------------------------------------
+ // netlist_t
+ // -----------------------------------------------------------------------------
+
+ class netlist_t // NOLINT(clang-analyzer-optin.performance.Padding)
+ {
+ public:
+
+ explicit netlist_t(netlist_state_t &state, const pstring &aname);
+
+ PCOPYASSIGNMOVE(netlist_t, delete)
+
+ virtual ~netlist_t() noexcept = default;
+
+ // run functions
+
+ netlist_time_ext time() const noexcept { return m_time; }
+
+ void process_queue(netlist_time_ext delta) noexcept;
+ void abort_current_queue_slice() noexcept
+ {
+ if (!NL_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 noexcept { return m_queue; }
+
+ template<typename... Args>
+ void qpush(Args&&...args) noexcept
+ {
+ if (!NL_USE_QUEUE_STATS || !m_use_stats)
+ m_queue.emplace<false>(std::forward<Args>(args)...); // NOLINT(performance-move-const-arg)
+ else
+ m_queue.emplace<true>(std::forward<Args>(args)...); // NOLINT(performance-move-const-arg)
+ }
+
+ template <class R>
+ void qremove(const R &elem) noexcept
+ {
+ if (!NL_USE_QUEUE_STATS || !m_use_stats)
+ m_queue.remove<false>(elem);
+ else
+ m_queue.remove<true>(elem);
+ }
+
+ // Control functions
+
+ void stop();
+ void reset();
+
+ // only used by nltool to create static c-code
+ devices::nld_solver *solver() const noexcept { return m_solver; }
+
+ // force late type resolution
+ template <typename X = devices::nld_solver>
+ nl_fptype gmin(X *solv = nullptr) const noexcept
+ {
+ plib::unused_var(solv);
+ return static_cast<X *>(m_solver)->gmin();
+ }
+
+ netlist_state_t &nlstate() noexcept { return m_state; }
+ const netlist_state_t &nlstate() const noexcept { return m_state; }
+
+ log_type & log() noexcept { return m_state.log(); }
+ const log_type &log() const noexcept { return m_state.log(); }
+
+ void print_stats() const;
+ bool use_stats() const { return m_use_stats; }
+
+ bool stats_enabled() const noexcept { return m_use_stats; }
+ void enable_stats(bool val) noexcept { m_use_stats = val; }
+
+ private:
+
+ template <bool KEEP_STATS>
+ void process_queue_stats(netlist_time_ext delta) noexcept;
+
+ netlist_state_t & m_state;
+ devices::nld_solver * m_solver;
+
+ // mostly rw
+ //PALIGNAS(16)
+ netlist_time_ext m_time;
+ devices::nld_mainclock * m_mainclock;
+
+ //PALIGNAS_CACHELINE()
+ //PALIGNAS(16)
+ detail::queue_t m_queue;
+ bool m_use_stats;
+ // performance
+ plib::pperftime_t<true> m_stat_mainloop;
+ plib::pperfcount_t<true> m_perf_out_processed;
+ };
+
+} // namespace netlist
+
+
+#endif // NL_CORE_EXEC_H_
diff --git a/src/lib/netlist/core/nets.h b/src/lib/netlist/core/nets.h
index 5eced2379e4..7b872250d56 100644
--- a/src/lib/netlist/core/nets.h
+++ b/src/lib/netlist/core/nets.h
@@ -10,6 +10,8 @@
#include "base_objects.h"
#include "state_var.h"
+#include "core_device.h"
+#include "exec.h"
#include "../nltypes.h"
#include "../plib/plists.h"
@@ -43,6 +45,12 @@ namespace netlist
virtual void reset() noexcept;
+ // -----------------------------------------------------------------------------
+ // Hot section
+ //
+ // Any changes below will impact performance.
+ // -----------------------------------------------------------------------------
+
void toggle_new_Q() noexcept { m_new_Q = (m_cur_Q ^ 1); }
void toggle_and_push_to_queue(const netlist_time &delay) noexcept
@@ -51,11 +59,42 @@ namespace netlist
push_to_queue(delay);
}
- void push_to_queue(const netlist_time &delay) noexcept;
+ void push_to_queue(const netlist_time &delay) noexcept
+ {
+ if (has_connections())
+ {
+ if (!!is_queued())
+ exec().qremove(this);
+
+ const auto nst(exec().time() + delay);
+ m_next_scheduled_time = nst;
+
+ if (!m_list_active.empty())
+ {
+ m_in_queue = queue_status::QUEUED;
+ exec().qpush(nst, this);
+ }
+ else
+ {
+ m_in_queue = queue_status::DELAYED_DUE_TO_INACTIVE;
+ update_inputs();
+ }
+ }
+ }
NVCC_CONSTEXPR bool is_queued() const noexcept { return m_in_queue == queue_status::QUEUED; }
template <bool KEEP_STATS>
- inline void update_devs() noexcept;
+ inline void update_devs() noexcept
+ {
+ nl_assert(this->is_rail_net());
+
+ m_in_queue = queue_status::DELIVERED; // mark as taken ...
+ 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);
+ }
+ }
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; }
@@ -65,10 +104,47 @@ namespace netlist
bool has_connections() const noexcept { return !m_core_terms.empty(); }
- void add_to_active_list(core_terminal_t &term) noexcept;
- void remove_from_active_list(core_terminal_t &term) noexcept;
+ void add_to_active_list(core_terminal_t &term) noexcept
+ {
+ if (!m_list_active.empty())
+ {
+ term.set_copied_input(m_cur_Q);
+ m_list_active.push_front(&term);
+ }
+ else
+ {
+ m_list_active.push_front(&term);
+ railterminal().device().do_inc_active();
+ if (m_in_queue == queue_status::DELAYED_DUE_TO_INACTIVE)
+ {
+ if (m_next_scheduled_time > exec().time())
+ {
+ m_in_queue = queue_status::QUEUED; // pending
+ exec().qpush(m_next_scheduled_time, this);
+ }
+ else
+ {
+ m_in_queue = queue_status::DELIVERED;
+ m_cur_Q = m_new_Q;
+ }
+ update_inputs();
+ }
+ else
+ term.set_copied_input(m_cur_Q);
+ }
+ }
- // setup stuff
+ void remove_from_active_list(core_terminal_t &term) noexcept
+ {
+ gsl_Expects(!m_list_active.empty());
+ m_list_active.remove(&term);
+ if (m_list_active.empty())
+ railterminal().device().do_dec_active();
+ }
+
+ // -----------------------------------------------------------------------------
+ // setup stuff - cold
+ // -----------------------------------------------------------------------------
bool is_logic() const noexcept;
bool is_analog() const noexcept;
@@ -135,8 +211,39 @@ namespace netlist
plib::linkedlist_t<core_terminal_t> m_list_active;
std::vector<core_terminal_t *> m_core_terms; // save post-start m_list ...
+ // -----------------------------------------------------------------------------
+ // Very hot
+ // -----------------------------------------------------------------------------
+
template <bool KEEP_STATS, typename T, typename S>
- void process(T mask, const S &sig) noexcept;
+ void process(T mask, const S &sig) noexcept
+ {
+ m_cur_Q = sig;
+
+ if (KEEP_STATS)
+ {
+ for (auto & p : m_list_active)
+ {
+ p.set_copied_input(sig);
+ auto *stats(p.device().stats());
+ stats->m_stat_call_count.inc();
+ if ((p.terminal_state() & mask))
+ {
+ auto g(stats->m_stat_total_time.guard());
+ p.run_delegate();
+ }
+ }
+ }
+ else
+ {
+ for (auto &p : m_list_active)
+ {
+ p.set_copied_input(sig);
+ if ((p.terminal_state() & mask) != 0)
+ p.run_delegate();
+ }
+ }
+ }
};
} // namespace detail
diff --git a/src/lib/netlist/core/param.h b/src/lib/netlist/core/param.h
index 9b353d0bdef..609c89d1cf3 100644
--- a/src/lib/netlist/core/param.h
+++ b/src/lib/netlist/core/param.h
@@ -24,11 +24,14 @@
#include "../nltypes.h"
#include "base_objects.h"
+#include "core_device.h"
+#include "setup.h"
#include "../plib/palloc.h"
#include "../plib/pstream.h"
#include "../plib/pstring.h"
#include "../plib/putil.h" // psource_t
+#include "../plib/pfunction.h"
#include <memory>
@@ -63,8 +66,6 @@ namespace netlist
protected:
- void update_param() noexcept;
-
pstring get_initial(const core_device_t *dev, bool *found) const;
template<typename C>
@@ -73,7 +74,7 @@ namespace netlist
if (p != v)
{
p = v;
- update_param();
+ device().update_param();
}
}
@@ -170,13 +171,14 @@ namespace netlist
{
*m_param = param;
changed();
- update_param();
+ device().update_param();
}
}
pstring valstr() const override
{
return *m_param;
}
+
protected:
virtual void changed() noexcept;
pstring str() const noexcept { return *m_param; }
@@ -269,6 +271,63 @@ namespace netlist
std::array<ST, 1 << AW> m_data;
};
+ template <typename T>
+ param_num_t<T>::param_num_t(core_device_t &device, const pstring &name, const T val)
+ : param_t(device, name)
+ , m_param(val)
+ {
+ bool found = false;
+ pstring p = this->get_initial(&device, &found);
+ if (found)
+ {
+ plib::pfunction<nl_fptype> func;
+ func.compile_infix(p, {});
+ auto valx = func.evaluate();
+ if (plib::is_integral<T>::value)
+ if (plib::abs(valx - plib::trunc(valx)) > nlconst::magic(1e-6))
+ throw nl_exception(MF_INVALID_NUMBER_CONVERSION_1_2(device.name() + "." + name, p));
+ m_param = plib::narrow_cast<T>(valx);
+ }
+
+ device.state().save(*this, m_param, this->name(), "m_param");
+ }
+
+ template <typename T>
+ param_enum_t<T>::param_enum_t(core_device_t &device, const pstring &name, const T val)
+ : param_t(device, name)
+ , m_param(val)
+ {
+ bool found = false;
+ pstring p = this->get_initial(&device, &found);
+ if (found)
+ {
+ T temp(val);
+ bool ok = temp.set_from_string(p);
+ if (!ok)
+ {
+ device.state().log().fatal(MF_INVALID_ENUM_CONVERSION_1_2(name, p));
+ throw nl_exception(MF_INVALID_ENUM_CONVERSION_1_2(name, p));
+ }
+ m_param = temp;
+ }
+
+ device.state().save(*this, m_param, this->name(), "m_param");
+ }
+
+ template <typename ST, std::size_t AW, std::size_t DW>
+ param_rom_t<ST, AW, DW>::param_rom_t(core_device_t &device, const pstring &name)
+ : param_data_t(device, name)
+ {
+ auto f = this->stream();
+ if (!f.empty())
+ {
+ plib::istream_read(f.stream(), m_data.data(), 1<<AW);
+ // FIXME: check for failbit if not in validation.
+ }
+ else
+ device.state().log().warning(MW_ROM_NOT_FOUND(str()));
+ }
+
} // namespace netlist
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index d53606e52b8..1ea7817dc72 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -975,6 +975,83 @@ namespace netlist
}
}
+ // ----------------------------------------------------------------------------------------
+ // netlist_t
+ //
+ // Hot section
+ //
+ // Any changes below will impact performance.
+ // -----------------------------------------------------------------------------
+
+ template <bool KEEP_STATS>
+ void netlist_t::process_queue_stats(const netlist_time_ext delta) noexcept
+ {
+ netlist_time_ext stop(m_time + delta);
+
+ qpush(stop, nullptr);
+
+ if (m_mainclock == nullptr)
+ {
+ m_time = m_queue.top().exec_time();
+ detail::net_t *obj(m_queue.top().object());
+ m_queue.pop();
+
+ while (obj != nullptr)
+ {
+ obj->template update_devs<KEEP_STATS>();
+ if (KEEP_STATS)
+ m_perf_out_processed.inc();
+ 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_ext mc_time(mc_net.next_scheduled_time());
+
+ do
+ {
+ 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;
+ }
+
+ m_time = top->exec_time();
+ auto *const obj(top->object());
+ m_queue.pop();
+ if (obj != nullptr)
+ obj->template update_devs<KEEP_STATS>();
+ else
+ break;
+ if (KEEP_STATS)
+ m_perf_out_processed.inc();
+ } while (true);
+
+ mc_net.set_next_scheduled_time(mc_time);
+ }
+ }
+
+ void netlist_t::process_queue(netlist_time_ext delta) noexcept
+ {
+ if (!m_use_stats)
+ process_queue_stats<false>(delta);
+ else
+ {
+ auto sm_guard(m_stat_mainloop.guard());
+ process_queue_stats<true>(delta);
+ }
+ }
+
+
template struct state_var<std::uint8_t>;
template struct state_var<std::uint16_t>;
template struct state_var<std::uint32_t>;
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index b6f5da80461..32cc1f0eacc 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -22,24 +22,7 @@
#include "core/object_array.h"
#include "core/param.h"
#include "core/state_var.h"
-
-#include "plib/palloc.h" // owned_ptr
-#include "plib/pfunction.h"
-#include "plib/plists.h"
-#include "plib/pmempool.h"
-#include "plib/ppmf.h"
-#include "plib/pstate.h"
-#include "plib/pstream.h"
-#include "plib/ptimed_queue.h"
-#include "plib/ptypes.h"
-
-#include "nl_errstr.h"
-#include "nl_factory.h"
-#include "nltypes.h"
-
-#include <initializer_list>
-#include <unordered_map>
-#include <vector>
+#include "core/exec.h"
//============================================================
// MACROS / New Syntax
@@ -196,11 +179,6 @@ class NETLIB_NAME(name) : public delegator_t<base_device_t>
#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip) :: name() noexcept
-#if 0
-#define NETLIB_UPDATEI() virtual void update() noexcept override
-#define NETLIB_UPDATE(chip) NETLIB_HANDLER(chip, update)
-#endif
-
#define NETLIB_RESET(chip) void NETLIB_NAME(chip) :: reset(void)
#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param() noexcept
@@ -214,9 +192,6 @@ class NETLIB_NAME(name) : public delegator_t<base_device_t>
namespace netlist
{
-
-
-
namespace devices
{
// -----------------------------------------------------------------------------
@@ -247,107 +222,6 @@ namespace netlist
};
} // namespace devices
- // -----------------------------------------------------------------------------
- // netlist_t
- // -----------------------------------------------------------------------------
-
- class netlist_t // NOLINT(clang-analyzer-optin.performance.Padding)
- {
- public:
-
- explicit netlist_t(netlist_state_t &state, const pstring &aname);
-
- PCOPYASSIGNMOVE(netlist_t, delete)
-
- virtual ~netlist_t() noexcept = default;
-
- // run functions
-
- netlist_time_ext time() const noexcept { return m_time; }
-
- void process_queue(netlist_time_ext delta) noexcept;
- void abort_current_queue_slice() noexcept
- {
- if (!NL_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 noexcept { return m_queue; }
-
- template<typename... Args>
- void qpush(Args&&...args) noexcept
- {
- if (!NL_USE_QUEUE_STATS || !m_use_stats)
- m_queue.emplace<false>(std::forward<Args>(args)...); // NOLINT(performance-move-const-arg)
- else
- m_queue.emplace<true>(std::forward<Args>(args)...); // NOLINT(performance-move-const-arg)
- }
-
- template <class R>
- void qremove(const R &elem) noexcept
- {
- if (!NL_USE_QUEUE_STATS || !m_use_stats)
- m_queue.remove<false>(elem);
- else
- m_queue.remove<true>(elem);
- }
-
- // Control functions
-
- void stop();
- void reset();
-
- // only used by nltool to create static c-code
- devices::NETLIB_NAME(solver) *solver() const noexcept { return m_solver; }
-
- // force late type resolution
- template <typename X = devices::NETLIB_NAME(solver)>
- nl_fptype gmin(X *solv = nullptr) const noexcept
- {
- plib::unused_var(solv);
- return static_cast<X *>(m_solver)->gmin();
- }
-
- netlist_state_t &nlstate() noexcept { return m_state; }
- const netlist_state_t &nlstate() const noexcept { return m_state; }
-
- log_type & log() noexcept { return m_state.log(); }
- const log_type &log() const noexcept { return m_state.log(); }
-
- void print_stats() const;
- bool use_stats() const { return m_use_stats; }
-
- bool stats_enabled() const noexcept { return m_use_stats; }
- void enable_stats(bool val) noexcept { m_use_stats = val; }
-
- private:
-
- template <bool KEEP_STATS>
- void process_queue_stats(netlist_time_ext delta) noexcept;
-
- netlist_state_t & m_state;
- devices::NETLIB_NAME(solver) * m_solver;
-
- // mostly rw
- //PALIGNAS(16)
- netlist_time_ext m_time;
- devices::NETLIB_NAME(mainclock) * m_mainclock;
-
- //PALIGNAS_CACHELINE()
- //PALIGNAS(16)
- detail::queue_t m_queue;
- bool m_use_stats;
- // performance
- plib::pperftime_t<true> m_stat_mainloop;
- plib::pperfcount_t<true> m_perf_out_processed;
- };
-
- // -----------------------------------------------------------------------------
- // Support classes for devices
- // -----------------------------------------------------------------------------
-
// -----------------------------------------------------------------------------
// power pins - not a device, but a helper
@@ -400,371 +274,6 @@ namespace netlist
}
} // namespace devices
- // -----------------------------------------------------------------------------
- // Hot section
- //
- // Any changes below will impact performance.
- // -----------------------------------------------------------------------------
-
- // -----------------------------------------------------------------------------
- // logic_input_t
- // -----------------------------------------------------------------------------
-#if 0
- inline void logic_input_t::inactivate() noexcept
- {
- if (!is_state(STATE_INP_PASSIVE))
- {
- set_state(STATE_INP_PASSIVE);
- net().remove_from_active_list(*this);
- }
- }
-
- inline void logic_input_t::activate() noexcept
- {
- if (is_state(STATE_INP_PASSIVE))
- {
- net().add_to_active_list(*this);
- set_state(STATE_INP_ACTIVE);
- }
- }
-
- inline void logic_input_t::activate_hl() noexcept
- {
- if (is_state(STATE_INP_PASSIVE))
- {
- net().add_to_active_list(*this);
- set_state(STATE_INP_HL);
- }
- }
-
- inline void logic_input_t::activate_lh() noexcept
- {
- if (is_state(STATE_INP_PASSIVE))
- {
- net().add_to_active_list(*this);
- set_state(STATE_INP_LH);
- }
- }
-#endif
- inline void detail::net_t::push_to_queue(const netlist_time &delay) noexcept
- {
- if (has_connections())
- {
- if (!!is_queued())
- exec().qremove(this);
-
- const auto nst(exec().time() + delay);
- m_next_scheduled_time = nst;
-
- if (!m_list_active.empty())
- {
- m_in_queue = queue_status::QUEUED;
- exec().qpush(nst, this);
- }
- else
- {
- m_in_queue = queue_status::DELAYED_DUE_TO_INACTIVE;
- update_inputs();
- }
- }
- }
-
- inline void detail::net_t::add_to_active_list(core_terminal_t &term) noexcept
- {
- if (!m_list_active.empty())
- {
- term.set_copied_input(m_cur_Q);
- m_list_active.push_front(&term);
- }
- else
- {
- m_list_active.push_front(&term);
- railterminal().device().do_inc_active();
- if (m_in_queue == queue_status::DELAYED_DUE_TO_INACTIVE)
- {
- if (m_next_scheduled_time > exec().time())
- {
- m_in_queue = queue_status::QUEUED; // pending
- exec().qpush(m_next_scheduled_time, this);
- }
- else
- {
- m_in_queue = queue_status::DELIVERED;
- m_cur_Q = m_new_Q;
- }
- update_inputs();
- }
- else
- term.set_copied_input(m_cur_Q);
- }
- }
-
- inline void detail::net_t::remove_from_active_list(core_terminal_t &term) noexcept
- {
- gsl_Expects(!m_list_active.empty());
- m_list_active.remove(&term);
- if (m_list_active.empty())
- railterminal().device().do_dec_active();
- }
-
-#if 0
- inline nl_fptype terminal_t::operator ()() const noexcept
- {
- return net().Q_Analog();
- }
-
- inline const analog_net_t & analog_t::net() const noexcept
- {
- return plib::downcast<const analog_net_t &>(core_terminal_t::net());
- }
-
- inline analog_net_t & analog_t::net() noexcept
- {
- return plib::downcast<analog_net_t &>(core_terminal_t::net());
- }
-
-
- inline logic_net_t & logic_t::net() noexcept
- {
- return plib::downcast<logic_net_t &>(core_terminal_t::net());
- }
-
- inline const logic_net_t & logic_t::net() const noexcept
- {
- return plib::downcast<const logic_net_t &>(core_terminal_t::net());
- }
- inline netlist_sig_t logic_input_t::operator()() const noexcept
- {
- nl_assert(terminal_state() != STATE_INP_PASSIVE);
-#if NL_USE_COPY_INSTEAD_OF_REFERENCE
- return m_Q;
-#else
- return net().Q();
-#endif
- }
-
- inline nl_fptype analog_input_t::Q_Analog() const noexcept
- {
- return net().Q_Analog();
- }
-
- inline void analog_output_t::push(nl_fptype val) noexcept
- {
- if (val != m_my_net.Q_Analog())
- {
- m_my_net.set_Q_Analog(val);
- m_my_net.toggle_and_push_to_queue(netlist_time::quantum());
- }
- }
-#endif
-
- inline netlist_t &detail::device_object_t::exec() noexcept
- {
- return m_device->exec();
- }
-
- inline const netlist_t &detail::device_object_t::exec() const noexcept
- {
- return m_device->exec();
- }
-
- template <bool KEEP_STATS, typename T, typename S>
- inline void detail::net_t::process(T mask, const S &sig) noexcept
- {
- m_cur_Q = sig;
-
- if (KEEP_STATS)
- {
- for (auto & p : m_list_active)
- {
- p.set_copied_input(sig);
- auto *stats(p.device().stats());
- stats->m_stat_call_count.inc();
- if ((p.terminal_state() & mask))
- {
- auto g(stats->m_stat_total_time.guard());
- p.run_delegate();
- }
- }
- }
- else
- {
- for (auto &p : m_list_active)
- {
- p.set_copied_input(sig);
- if ((p.terminal_state() & mask) != 0)
- p.run_delegate();
- }
- }
- }
-
- template <bool KEEP_STATS>
- inline void detail::net_t::update_devs() noexcept
- {
- nl_assert(this->is_rail_net());
-
- m_in_queue = queue_status::DELIVERED; // mark as taken ...
- 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);
- }
- }
-
- template <bool KEEP_STATS>
- inline void netlist_t::process_queue_stats(const netlist_time_ext delta) noexcept
- {
- netlist_time_ext stop(m_time + delta);
-
- qpush(stop, nullptr);
-
- if (m_mainclock == nullptr)
- {
- m_time = m_queue.top().exec_time();
- detail::net_t *obj(m_queue.top().object());
- m_queue.pop();
-
- while (obj != nullptr)
- {
- obj->template update_devs<KEEP_STATS>();
- if (KEEP_STATS)
- m_perf_out_processed.inc();
- 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_ext mc_time(mc_net.next_scheduled_time());
-
- do
- {
- 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;
- }
-
- m_time = top->exec_time();
- auto *const obj(top->object());
- m_queue.pop();
- if (obj != nullptr)
- obj->template update_devs<KEEP_STATS>();
- else
- break;
- 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_ext delta) noexcept
- {
- if (!m_use_stats)
- process_queue_stats<false>(delta);
- else
- {
- auto sm_guard(m_stat_mainloop.guard());
- process_queue_stats<true>(delta);
- }
- }
-
-
-
- // -----------------------------------------------------------------------------
- // inline implementations - cold
- // -----------------------------------------------------------------------------
-#if 0
- template<typename T, typename... Args>
- inline device_arena::unique_ptr<T> detail::netlist_object_t::make_pool_object(Args&&... args)
- {
- return state().make_pool_object<T>(std::forward<Args>(args)...);
- }
-#endif
- inline void param_t::update_param() noexcept
- {
- device().update_param();
- }
-
- template <typename T>
- param_num_t<T>::param_num_t(core_device_t &device, const pstring &name, const T val)
- : param_t(device, name)
- , m_param(val)
- {
- bool found = false;
- pstring p = this->get_initial(&device, &found);
- if (found)
- {
- plib::pfunction<nl_fptype> func;
- func.compile_infix(p, {});
- auto valx = func.evaluate();
- if (plib::is_integral<T>::value)
- if (plib::abs(valx - plib::trunc(valx)) > nlconst::magic(1e-6))
- throw nl_exception(MF_INVALID_NUMBER_CONVERSION_1_2(device.name() + "." + name, p));
- m_param = plib::narrow_cast<T>(valx);
- }
-
- device.state().save(*this, m_param, this->name(), "m_param");
- }
-
- template <typename T>
- param_enum_t<T>::param_enum_t(core_device_t &device, const pstring &name, const T val)
- : param_t(device, name)
- , m_param(val)
- {
- bool found = false;
- pstring p = this->get_initial(&device, &found);
- if (found)
- {
- T temp(val);
- bool ok = temp.set_from_string(p);
- if (!ok)
- {
- device.state().log().fatal(MF_INVALID_ENUM_CONVERSION_1_2(name, p));
- throw nl_exception(MF_INVALID_ENUM_CONVERSION_1_2(name, p));
- }
- m_param = temp;
- }
-
- device.state().save(*this, m_param, this->name(), "m_param");
- }
-
- template <typename ST, std::size_t AW, std::size_t DW>
- param_rom_t<ST, AW, DW>::param_rom_t(core_device_t &device, const pstring &name)
- : param_data_t(device, name)
- {
- auto f = this->stream();
- if (!f.empty())
- {
- plib::istream_read(f.stream(), m_data.data(), 1<<AW);
- // FIXME: check for failbit if not in validation.
- }
- else
- device.state().log().warning(MW_ROM_NOT_FOUND(str()));
- }
-
-#if 0
- template<class O, class C, typename... Args>
- void base_device_t::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)...);
- }
-#endif
- inline solver::matrix_solver_t *analog_t::solver() const noexcept
- {
- return (this->has_net() ? net().solver() : nullptr);
- }
-
extern template struct state_var<std::uint8_t>;
extern template struct state_var<std::uint16_t>;