summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2020-07-28 20:40:56 +0200
committer couriersud <couriersud@gmx.org>2020-07-28 20:40:59 +0200
commitffb37e9ae8d93808c51e11484a060a7a99ac57f3 (patch)
tree3974df3168e0a85b4b8d3acddf99adb65eab50a3 /src
parentcbba06308f56adfd9441a70f8f5b17d183ef4c55 (diff)
netlist: further nl_base.h splitting into headers in core subdir.
Diffstat (limited to 'src')
-rw-r--r--src/lib/netlist/build/makefile2
-rw-r--r--src/lib/netlist/core/analog.h162
-rw-r--r--src/lib/netlist/core/base_objects.h113
-rw-r--r--src/lib/netlist/core/device.h163
-rw-r--r--src/lib/netlist/core/logic.h208
-rw-r--r--src/lib/netlist/core/netlist_state.h275
-rw-r--r--src/lib/netlist/core/nets.h2
-rw-r--r--src/lib/netlist/core/object_array.h225
-rw-r--r--src/lib/netlist/core/param.h2
-rw-r--r--src/lib/netlist/core/queue.h114
-rw-r--r--src/lib/netlist/core/setup.h2
-rw-r--r--src/lib/netlist/devices/nld_devinc.h49
-rw-r--r--src/lib/netlist/devices/nld_log.cpp2
-rw-r--r--src/lib/netlist/devices/nlid_system.h4
-rw-r--r--src/lib/netlist/macro/nlm_base.cpp1
-rw-r--r--src/lib/netlist/nl_base.cpp21
-rw-r--r--src/lib/netlist/nl_base.h887
-rw-r--r--src/lib/netlist/nl_factory.h1
-rw-r--r--src/lib/netlist/nltypes.h31
-rw-r--r--src/lib/netlist/plib/palloc.h2
-rw-r--r--src/lib/netlist/plib/pfunction.cpp2
-rw-r--r--src/lib/netlist/plib/pmulti_threading.h2
-rw-r--r--src/lib/netlist/plib/ptests.h8
-rw-r--r--src/lib/netlist/plib/ptimed_queue.h2
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp2
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h2
-rw-r--r--src/lib/netlist/tests/test_pfunction.cpp2
27 files changed, 1278 insertions, 1008 deletions
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index e46e1ac4c26..0763c938b8a 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -53,7 +53,7 @@ TIDY_SOURCES = $(SOURCES)
#TIDY_SOURCES = $(SRC)/devices/nld_7442.cpp $(SRC)/devices/nld_7492.cpp
-#TIDY_FLAGS = -p $(OBJ) -checks=llvm-include-order,llvm-namespace-comment,modernize-use-override,modernize-use-using -fix
+TIDY_FLAGS = -p $(OBJ) -checks=llvm-include-order,llvm-namespace-comment,modernize-use-override,modernize-use-using -fix
#TIDY_FLAGS = -checks=llvm-include-order -fix
#TIDY_FLAGS = -checks=llvm-namespace-comment -fix
#TIDY_FLAGS = -checks=modernize-use-override -fix
diff --git a/src/lib/netlist/core/analog.h b/src/lib/netlist/core/analog.h
new file mode 100644
index 00000000000..a868443b8d2
--- /dev/null
+++ b/src/lib/netlist/core/analog.h
@@ -0,0 +1,162 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+///
+/// \file param.h
+///
+
+#ifndef NL_CORE_ANALOG_H_
+#define NL_CORE_ANALOG_H_
+
+#include "../nltypes.h"
+#include "base_objects.h"
+#include "nets.h"
+
+#include "../plib/plists.h"
+#include "../plib/pstring.h"
+
+#include <array>
+#include <utility>
+
+namespace netlist
+{
+ // -----------------------------------------------------------------------------
+ // analog_t
+ // -----------------------------------------------------------------------------
+
+ class analog_t : public detail::core_terminal_t
+ {
+ public:
+
+ analog_t(core_device_t &dev, const pstring &aname, state_e state,
+ nldelegate delegate);
+
+ const analog_net_t & net() const noexcept
+ {
+ return plib::downcast<const analog_net_t &>(core_terminal_t::net());
+ }
+
+ analog_net_t & net() noexcept
+ {
+ return plib::downcast<analog_net_t &>(core_terminal_t::net());
+ }
+
+ solver::matrix_solver_t *solver() const noexcept;
+ };
+
+ /// \brief Base class for terminals.
+ ///
+ /// Each \ref nld_twoterm object consists of two terminals. Terminals
+ /// are at the core of analog netlists and are connected to \ref net_t
+ /// objects.
+ ///
+ class terminal_t : public analog_t
+ {
+ public:
+
+ /// \brief constructor
+ ///
+ /// @param dev core_devict_t object owning the terminal
+ /// @param aname name of this terminal
+ /// @param otherterm pointer to the sibling terminal
+ terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm, nldelegate delegate);
+
+ /// \brief Returns voltage of connected net
+ ///
+ /// @return voltage of net this terminal is connected to
+ nl_fptype operator ()() const noexcept
+ {
+ return net().Q_Analog();
+ }
+
+ /// @brief sets conductivity value of this terminal
+ ///
+ /// @param G Conductivity
+ void set_conductivity(nl_fptype G) const noexcept
+ {
+ set_go_gt_I(-G, G, nlconst::zero());
+ }
+
+ void set_go_gt(nl_fptype GO, nl_fptype GT) const noexcept
+ {
+ set_go_gt_I(GO, GT, nlconst::zero());
+ }
+
+ void set_go_gt_I(nl_fptype GO, nl_fptype GT, nl_fptype I) const noexcept
+ {
+ // Check for rail nets ...
+ if (m_go != nullptr)
+ {
+ *m_Idr = I;
+ *m_go = GO;
+ *m_gt = GT;
+ }
+ }
+
+ void set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(false);
+
+ private:
+ nl_fptype *m_Idr; ///< drive current
+ nl_fptype *m_go; ///< conductance for Voltage from other term
+ nl_fptype *m_gt; ///< conductance for total conductance
+
+ };
+
+ // -----------------------------------------------------------------------------
+ // analog_input_t
+ // -----------------------------------------------------------------------------
+
+ /// \brief terminal providing analog input voltage.
+ ///
+ /// This terminal class provides a voltage measurement. The conductance against
+ /// ground is infinite.
+
+ class analog_input_t : public analog_t
+ {
+ public:
+ /// \brief Constructor
+ analog_input_t(core_device_t &dev, ///< owning device
+ const pstring &aname, ///< name of terminal
+ nldelegate delegate ///< delegate
+ );
+
+ /// \brief returns voltage at terminal.
+ /// \returns voltage at terminal.
+ nl_fptype operator()() const noexcept { return Q_Analog(); }
+
+ /// \brief returns voltage at terminal.
+ /// \returns voltage at terminal.
+ nl_fptype Q_Analog() const noexcept
+ {
+ return net().Q_Analog();
+ }
+ };
+
+ // -----------------------------------------------------------------------------
+ // analog_output_t
+ // -----------------------------------------------------------------------------
+
+ class analog_output_t : public analog_t
+ {
+ public:
+ analog_output_t(core_device_t &dev, const pstring &aname);
+
+ void 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());
+ }
+ }
+
+ void initial(nl_fptype val) noexcept;
+
+ private:
+ analog_net_t m_my_net;
+ };
+
+} // namespace netlist
+
+
+#endif // NL_CORE_ANALOG_H_
diff --git a/src/lib/netlist/core/base_objects.h b/src/lib/netlist/core/base_objects.h
index c697617e265..656898b21d0 100644
--- a/src/lib/netlist/core/base_objects.h
+++ b/src/lib/netlist/core/base_objects.h
@@ -8,48 +8,22 @@
#ifndef NL_CORE_BASE_OBJECTS_H_
#define NL_CORE_BASE_OBJECTS_H_
+#include "netlist_state.h"
#include "state_var.h"
#include "../nltypes.h"
#include "../plib/palloc.h"
-#include "../plib/pmempool.h"
#include "../plib/pchrono.h"
#include "../plib/pexception.h"
#include "../plib/plists.h"
+#include "../plib/pmempool.h"
#include <unordered_map>
namespace netlist
{
- //============================================================
- // Exceptions
- //============================================================
-
- /// \brief Generic netlist exception.
- /// The exception is used in all events which are considered fatal.
-
- class nl_exception : public plib::pexception
- {
- public:
- /// \brief Constructor.
- /// Allows a descriptive text to be passed to the exception
-
- explicit nl_exception(const pstring &text //!< text to be passed
- )
- : plib::pexception(text) { }
-
- /// \brief Constructor.
- /// Allows to use \ref plib::pfmt logic to be used in exception
-
- template<typename... Args>
- explicit nl_exception(const pstring &fmt //!< format to be used
- , Args&&... args //!< arguments to be passed
- )
- : plib::pexception(plib::pfmt(fmt)(std::forward<Args>(args)...)) { }
- };
-
namespace detail {
template <typename C, typename T>
@@ -142,6 +116,7 @@ namespace netlist
/// The object provides adds \ref netlist_state_t and \ref netlist_t
/// accessors.
///
+
class netlist_object_t : public object_t
{
public:
@@ -162,7 +137,10 @@ namespace netlist
// to ease template design
template<typename T, typename... Args>
- device_arena::unique_ptr<T> make_pool_object(Args&&... args);
+ device_arena::unique_ptr<T> make_pool_object(Args&&... args)
+ {
+ return state().make_pool_object<T>(std::forward<Args>(args)...);
+ }
private:
netlist_t & m_netlist;
@@ -305,83 +283,6 @@ namespace netlist
} // namespace detail
- // -----------------------------------------------------------------------------
- // 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;
- };
-
} // namespace netlist
diff --git a/src/lib/netlist/core/device.h b/src/lib/netlist/core/device.h
new file mode 100644
index 00000000000..99a5a1884ec
--- /dev/null
+++ b/src/lib/netlist/core/device.h
@@ -0,0 +1,163 @@
+// 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"
+#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
+ {
+ public:
+ device_t(netlist_state_t &owner, const pstring &name);
+ device_t(netlist_state_t &owner, const pstring &name,
+ const pstring &model);
+ // only needed by proxies
+ device_t(netlist_state_t &owner, const pstring &name,
+ const logic_family_desc_t *desc);
+
+ device_t(device_t &owner, const pstring &name);
+ // pass in a default model - this may be overwritten by PARAM(DEVICE.MODEL, "XYZ(...)")
+ device_t(device_t &owner, const pstring &name,
+ const pstring &model);
+
+ PCOPYASSIGNMOVE(device_t, delete)
+
+ ~device_t() noexcept override = default;
+
+ protected:
+
+ //NETLIB_UPDATE_TERMINALSI() { }
+
+ private:
+ param_model_t m_model;
+ };
+
+} // namespace netlist
+
+
+#endif // NL_CORE_DEVICE_H_
diff --git a/src/lib/netlist/core/logic.h b/src/lib/netlist/core/logic.h
new file mode 100644
index 00000000000..c8ff979cc65
--- /dev/null
+++ b/src/lib/netlist/core/logic.h
@@ -0,0 +1,208 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+///
+/// \file param.h
+///
+
+#ifndef NL_CORE_LOGIC_H_
+#define NL_CORE_LOGIC_H_
+
+#include "../nltypes.h"
+#include "base_objects.h"
+#include "logic_family.h"
+#include "nets.h"
+#include "state_var.h"
+
+#include "../plib/plists.h"
+#include "../plib/pstring.h"
+
+#include <array>
+#include <utility>
+
+namespace netlist
+{
+ // -----------------------------------------------------------------------------
+ // logic_t
+ // -----------------------------------------------------------------------------
+
+ class logic_t : public detail::core_terminal_t, public logic_family_t
+ {
+ public:
+ logic_t(device_t &dev, const pstring &aname,
+ state_e terminal_state, nldelegate delegate);
+
+ logic_net_t & net() noexcept
+ {
+ return plib::downcast<logic_net_t &>(core_terminal_t::net());
+ }
+ const logic_net_t & net() const noexcept
+ {
+ return plib::downcast<const logic_net_t &>(core_terminal_t::net());
+ }
+ };
+
+ // -----------------------------------------------------------------------------
+ // logic_input_t
+ // -----------------------------------------------------------------------------
+
+ class logic_input_t : public logic_t
+ {
+ public:
+ logic_input_t(device_t &dev, const pstring &aname,
+ nldelegate delegate);
+
+ inline netlist_sig_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
+ }
+
+ void inactivate() noexcept
+ {
+ if (!is_state(STATE_INP_PASSIVE))
+ {
+ set_state(STATE_INP_PASSIVE);
+ net().remove_from_active_list(*this);
+ }
+ }
+
+ void activate() noexcept
+ {
+ if (is_state(STATE_INP_PASSIVE))
+ {
+ net().add_to_active_list(*this);
+ set_state(STATE_INP_ACTIVE);
+ }
+ }
+
+ void activate_hl() noexcept
+ {
+ if (is_state(STATE_INP_PASSIVE))
+ {
+ net().add_to_active_list(*this);
+ set_state(STATE_INP_HL);
+ }
+ }
+
+ void activate_lh() noexcept
+ {
+ if (is_state(STATE_INP_PASSIVE))
+ {
+ net().add_to_active_list(*this);
+ set_state(STATE_INP_LH);
+ }
+ }
+ };
+
+ // -----------------------------------------------------------------------------
+ // logic_output_t
+ // -----------------------------------------------------------------------------
+
+ class logic_output_t : public logic_t
+ {
+ public:
+
+ /// \brief logic output constructor
+ ///
+ /// The third parameter does nothing. It is provided only for
+ /// compatibility with tristate_output_t in templatized device models
+ ///
+ /// \param dev Device owning this output
+ /// \param aname The name of this output
+ /// \param dummy Dummy parameter to allow construction like tristate output
+ ///
+ logic_output_t(device_t &dev, const pstring &aname, bool dummy = false);
+
+ void initial(netlist_sig_t val) noexcept;
+
+ inline void push(const netlist_sig_t &newQ, const netlist_time &delay) noexcept
+ {
+ m_my_net.set_Q_and_push(newQ, delay); // take the shortcut
+ }
+
+ inline void set_Q_time(const netlist_sig_t &newQ, const netlist_time_ext &at) noexcept
+ {
+ m_my_net.set_Q_time(newQ, at); // take the shortcut
+ }
+
+ /// \brief Dummy implementation for templatized generic devices
+ ///
+ /// This function shall never be called. It is defined here so that
+ /// templatized generic device models do not have to do tons of
+ /// template magic.
+ ///
+ /// This function terminates if actually called.
+ ///
+ [[noreturn]] static void set_tristate(netlist_sig_t v,
+ netlist_time ts_off_on, netlist_time ts_on_off)
+ {
+ plib::unused_var(v, ts_off_on, ts_on_off);
+ plib::terminate("set_tristate on logic_output should never be called!");
+ }
+ private:
+ logic_net_t m_my_net;
+ };
+
+ // -----------------------------------------------------------------------------
+ // tristate_output_t
+ // -----------------------------------------------------------------------------
+
+ /// \brief Tristate output
+ ///
+ /// In a lot of applications tristate enable inputs are just connected to
+ /// VCC/GND to permanently enable the outputs. In this case a pure
+ /// implementation using analog outputs would not perform well.
+ ///
+ /// For this object during creation it can be decided if a logic output or
+ /// a tristate output is used. Generally the owning device uses parameter
+ /// FORCE_TRISTATE_LOGIC to determine this.
+ ///
+ /// This is the preferred way to implement tristate outputs.
+ ///
+
+ class tristate_output_t : public logic_output_t
+ {
+ public:
+
+ tristate_output_t(device_t &dev, const pstring &aname, bool force_logic);
+
+ void push(netlist_sig_t newQ, netlist_time delay) noexcept
+ {
+ if (!m_tristate)
+ logic_output_t::push(newQ, delay);
+ m_last_logic = newQ;
+ }
+
+ void set_tristate(netlist_sig_t v,
+ netlist_time ts_off_on, netlist_time ts_on_off) noexcept
+ {
+ if (!m_force_logic)
+ if (v != m_tristate)
+ {
+ logic_output_t::push((v != 0) ? OUT_TRISTATE() : m_last_logic, v ? ts_off_on : ts_on_off);
+ m_tristate = v;
+ }
+ }
+
+ bool is_force_logic() const noexcept
+ {
+ return m_force_logic;
+ }
+
+ private:
+ using logic_output_t::initial;
+ using logic_output_t::set_Q_time;
+ state_var<netlist_sig_t> m_last_logic;
+ state_var<netlist_sig_t> m_tristate;
+ bool m_force_logic;
+ };
+
+} // namespace netlist
+
+
+#endif // NL_CORE_LOGIC_H_
diff --git a/src/lib/netlist/core/netlist_state.h b/src/lib/netlist/core/netlist_state.h
new file mode 100644
index 00000000000..318eaae6b2d
--- /dev/null
+++ b/src/lib/netlist/core/netlist_state.h
@@ -0,0 +1,275 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+///
+/// \file netlist_state.h
+///
+
+#ifndef NL_CORE_NETLIST_STATE_H_
+#define NL_CORE_NETLIST_STATE_H_
+
+#include "queue.h"
+
+#include "../nltypes.h"
+
+#include "../plib/plists.h"
+#include "../plib/pstate.h"
+#include "../plib/pstring.h"
+
+#include <array>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+namespace netlist
+{
+ // -----------------------------------------------------------------------------
+ // netlist_state__t
+ // -----------------------------------------------------------------------------
+
+ class netlist_state_t
+ {
+ public:
+
+ using nets_collection_type = std::vector<device_arena::owned_ptr<detail::net_t>>;
+ using family_collection_type = std::unordered_map<pstring, host_arena::unique_ptr<logic_family_desc_t>>;
+
+ // need to preserve order of device creation ...
+ using devices_collection_type = std::vector<std::pair<pstring, device_arena::owned_ptr<core_device_t>>>;
+ netlist_state_t(const pstring &name, host_arena::unique_ptr<callbacks_t> &&callbacks);
+
+ PCOPYASSIGNMOVE(netlist_state_t, delete)
+
+ /// \brief Destructor
+ ///
+ /// The destructor is virtual to allow implementation specific devices
+ /// to connect to the outside world. For examples see MAME netlist.cpp.
+ ///
+ virtual ~netlist_state_t() noexcept = default;
+
+ template<class C>
+ static bool check_class(core_device_t *p) noexcept
+ {
+ return dynamic_cast<C *>(p) != nullptr;
+ }
+
+ core_device_t *get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const noexcept(false);
+
+ /// \brief Get single device filtered by class and name
+ ///
+ /// \tparam C Device class for which devices will be returned
+ /// \param name Name of the device
+ ///
+ /// \return pointers to device
+
+ template<class C>
+ C *get_single_device(const pstring &name) const
+ {
+ return dynamic_cast<C *>(get_single_device(name, check_class<C>));
+ }
+
+ /// \brief Get vector of devices
+ ///
+ /// \tparam C Device class for which devices will be returned
+ ///
+ /// \return vector with pointers to devices
+
+ template<class C>
+ inline std::vector<C *> get_device_list() const
+ {
+ std::vector<C *> tmp;
+ for (const auto &d : m_devices)
+ {
+ auto * const dev = dynamic_cast<C *>(d.second.get());
+ if (dev != nullptr)
+ tmp.push_back(dev);
+ }
+ return tmp;
+ }
+
+ // logging
+
+ log_type & log() noexcept { return m_log; }
+ const log_type &log() const noexcept { return m_log; }
+
+ plib::dynlib_base &lib() const noexcept { return *m_lib; }
+
+ netlist_t &exec() noexcept { return *m_netlist; }
+ const netlist_t &exec() const noexcept { return *m_netlist; }
+
+ // state handling
+ plib::state_manager_t &run_state_manager() noexcept { return m_state; }
+
+ template<typename O, typename C>
+ void save(O &owner, C &state, const pstring &module, const pstring &stname)
+ {
+ this->run_state_manager().save_item(static_cast<void *>(&owner), state, module + "." + stname);
+ }
+
+ template<typename O, typename C>
+ void save(O &owner, C *state, const pstring &module, const pstring &stname, const std::size_t count)
+ {
+ this->run_state_manager().save_state_ptr(static_cast<void *>(&owner), module + "." + stname, plib::state_manager_t::dtype<C>(), count, state);
+ }
+
+ // FIXME: only used by queue_t save state
+ std::size_t find_net_id(const detail::net_t *net) const;
+ detail::net_t *net_by_id(std::size_t id) const;
+
+ template <typename T>
+ void register_net(device_arena::owned_ptr<T> &&net) { m_nets.push_back(std::move(net)); }
+
+ /// \brief Get device pointer by name
+ ///
+ ///
+ /// \param name Name of the device
+ ///
+ /// \return core_device_t pointer if device exists, else nullptr
+
+ core_device_t *find_device(const pstring &name) const
+ {
+ for (const auto & d : m_devices)
+ if (d.first == name)
+ return d.second.get();
+ return nullptr;
+ }
+
+ /// \brief Register device using owned_ptr
+ ///
+ /// Used to register owned devices. These are devices declared as objects
+ /// in another devices.
+ ///
+ /// \param name Name of the device
+ /// \param dev Device to be registered
+
+ template <typename T>
+ void register_device(const pstring &name, device_arena::owned_ptr<T> &&dev) noexcept(false)
+ {
+ for (auto & d : m_devices)
+ if (d.first == name)
+ {
+ dev.release();
+ log().fatal(MF_DUPLICATE_NAME_DEVICE_LIST(name));
+ throw nl_exception(MF_DUPLICATE_NAME_DEVICE_LIST(name));
+ }
+ //m_devices.push_back(std::move(dev));
+ m_devices.insert(m_devices.end(), { name, std::move(dev) });
+ }
+
+ /// \brief Register device using unique_ptr
+ ///
+ /// Used to register devices.
+ ///
+ /// \param name Name of the device
+ /// \param dev Device to be registered
+
+ template <typename T>
+ void register_device(const pstring &name, device_arena::unique_ptr<T> &&dev)
+ {
+ register_device(name, device_arena::owned_ptr<T>(dev.release(), true, dev.get_deleter()));
+ }
+
+ /// \brief Remove device
+ ///
+ /// Care needs to be applied if this is called to remove devices with
+ /// sub-devices which may have registered state.
+ ///
+ /// \param dev Device to be removed
+
+ void remove_device(core_device_t *dev);
+
+ setup_t &setup() noexcept { return *m_setup; }
+ const setup_t &setup() const noexcept { return *m_setup; }
+
+ nlparse_t &parser();
+ const nlparse_t &parser() const;
+
+ // FIXME: make a postload member and include code there
+ void rebuild_lists(); // must be called after post_load !
+
+ static void compile_defines(std::vector<std::pair<pstring, pstring>> &defs);
+ static pstring version();
+ static pstring version_patchlevel();
+
+ nets_collection_type & nets() noexcept { return m_nets; }
+ const nets_collection_type & nets() const noexcept { return m_nets; }
+
+ devices_collection_type & devices() noexcept { return m_devices; }
+ const devices_collection_type & devices() const noexcept { return m_devices; }
+
+ family_collection_type &family_cache() { return m_family_cache; }
+
+ template<typename T, typename... Args>
+ device_arena::unique_ptr<T> make_pool_object(Args&&... args)
+ {
+ return plib::make_unique<T>(m_pool, std::forward<Args>(args)...);
+ }
+ // memory pool - still needed in some places
+ device_arena &pool() noexcept { return m_pool; }
+ const device_arena &pool() const noexcept { return m_pool; }
+
+ /// \brief set extended validation mode.
+ ///
+ /// The extended validation mode is not intended for running.
+ /// The intention is to identify power pins which are not properly
+ /// connected. The downside is that this mode creates a netlist which
+ /// is different (and not able to run).
+ ///
+ /// Extended validation is supported by nltool validate option.
+ ///
+ /// \param val Boolean value enabling/disabling extended validation mode
+ void set_extended_validation(bool val) { m_extended_validation = val; }
+
+ /// \brief State of extended validation mode.
+ ///
+ /// \returns boolean value indicating if extended validation mode is
+ /// turned on.
+ bool is_extended_validation() const { return m_extended_validation; }
+
+ struct stats_info
+ {
+ const detail::queue_t &m_queue;// performance
+ const plib::pperftime_t<true> &m_stat_mainloop;
+ const plib::pperfcount_t<true> &m_perf_out_processed;
+ };
+
+ /// \brief print statistics gathered during run
+ ///
+ void print_stats(stats_info &si) const;
+
+ /// \brief call reset on all netlist components
+ ///
+ void reset();
+
+ /// \brief prior to running free no longer needed resources
+ ///
+ void free_setup_resources();
+
+ private:
+
+ device_arena m_pool; // must be deleted last!
+
+ device_arena::unique_ptr<netlist_t> m_netlist;
+ std::unique_ptr<plib::dynlib_base> m_lib;
+ plib::state_manager_t m_state;
+ host_arena::unique_ptr<callbacks_t> m_callbacks;
+ log_type m_log;
+
+ // FIXME: should only be available during device construcion
+ host_arena::unique_ptr<setup_t> m_setup;
+
+ nets_collection_type m_nets;
+ // sole use is to manage lifetime of net objects
+ devices_collection_type m_devices;
+ // sole use is to manage lifetime of family objects
+ family_collection_type m_family_cache;
+ bool m_extended_validation;
+
+ // dummy version
+ int m_dummy_version;
+ };
+
+} // namespace netlist
+
+
+#endif // NL_CORE_NETLIST_STATE_H_
diff --git a/src/lib/netlist/core/nets.h b/src/lib/netlist/core/nets.h
index 96ecdf1836f..5eced2379e4 100644
--- a/src/lib/netlist/core/nets.h
+++ b/src/lib/netlist/core/nets.h
@@ -12,8 +12,8 @@
#include "state_var.h"
#include "../nltypes.h"
-#include "../plib/pstring.h"
#include "../plib/plists.h"
+#include "../plib/pstring.h"
namespace netlist
{
diff --git a/src/lib/netlist/core/object_array.h b/src/lib/netlist/core/object_array.h
new file mode 100644
index 00000000000..0079d819c3e
--- /dev/null
+++ b/src/lib/netlist/core/object_array.h
@@ -0,0 +1,225 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+///
+/// \file param.h
+///
+
+#ifndef NL_CORE_OBJECT_ARRAY_H_
+#define NL_CORE_OBJECT_ARRAY_H_
+
+#include "../nltypes.h"
+
+#include "../plib/plists.h"
+#include "../plib/pstring.h"
+
+#include <array>
+#include <utility>
+
+namespace netlist
+{
+ template<class C, std::size_t N>
+ class object_array_base_t : public plib::static_vector<C, N>
+ {
+ public:
+ template<class D, typename... Args>
+ //object_array_base_t(D &dev, const std::initializer_list<const char *> &names, Args&&... args)
+ object_array_base_t(D &dev, std::array<const char *, N> &&names, Args&&... args)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ this->emplace_back(dev, pstring(names[i]), std::forward<Args>(args)...);
+ }
+
+ template<class D>
+ object_array_base_t(D &dev, const pstring &fmt)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ this->emplace_back(dev, formatted(fmt, i));
+ }
+
+ template<class D, typename... Args>
+ object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, Args&&... args)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ this->emplace_back(dev, formatted(fmt, i+offset), std::forward<Args>(args)...);
+ }
+
+ template<class D>
+ object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, nldelegate delegate)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ this->emplace_back(dev, formatted(fmt, i+offset), delegate);
+ }
+
+ template<class D>
+ object_array_base_t(D &dev, std::size_t offset, std::size_t qmask, const pstring &fmt)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ {
+ pstring name(formatted(fmt, i+offset));
+ if ((qmask >> i) & 1)
+ name += "Q";
+ this->emplace(i, dev, name);
+ }
+ }
+ protected:
+ object_array_base_t() = default;
+
+ static pstring formatted(const pstring &fmt, std::size_t n)
+ {
+ if (N != 1)
+ return plib::pfmt(fmt)(n);
+ return plib::pfmt(fmt)("");
+ }
+ };
+
+
+ template<class C, std::size_t N>
+ class object_array_t : public object_array_base_t<C, N>
+ {
+ public:
+ using base_type = object_array_base_t<C, N>;
+ using base_type::base_type;
+ };
+
+ template<std::size_t N>
+ class object_array_t<logic_input_t,N> : public object_array_base_t<logic_input_t, N>
+ {
+ public:
+ using base_type = object_array_base_t<logic_input_t, N>;
+ using base_type::base_type;
+
+ template<class D, std::size_t ND>
+ object_array_t(D &dev, std::size_t offset, std::size_t qmask,
+ const pstring &fmt, std::array<nldelegate, ND> &&delegates)
+ {
+ static_assert(N <= ND, "initializer_list size mismatch");
+ std::size_t i = 0;
+ for (auto &e : delegates)
+ {
+ if (i < N)
+ {
+ pstring name(this->formatted(fmt, i+offset));
+ if ((qmask >> i) & 1)
+ name += "Q";
+ this->emplace_back(dev, name, e);
+ }
+ i++;
+ }
+ }
+
+ //using value_type = typename plib::fast_type_for_bits<N>::type;
+ using value_type = std::uint32_t;
+ value_type operator ()()
+ {
+ if (N == 1) return e<0>() ;
+ if (N == 2) return e<0>() | (e<1>() << 1);
+ if (N == 3) return e<0>() | (e<1>() << 1) | (e<2>() << 2);
+ if (N == 4) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3);
+ if (N == 5) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
+ | (e<4>() << 4);
+ if (N == 6) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
+ | (e<4>() << 4) | (e<5>() << 5);
+ if (N == 7) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
+ | (e<4>() << 4) | (e<5>() << 5) | (e<6>() << 6);
+ if (N == 8) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
+ | (e<4>() << 4) | (e<5>() << 5) | (e<6>() << 6) | (e<7>() << 7);
+
+ value_type r(0);
+ for (std::size_t i = 0; i < N; i++)
+ r = static_cast<value_type>((*this)[i]() << (N-1)) | (r >> 1);
+ return r;
+ }
+
+ private:
+ template <std::size_t P>
+ inline constexpr value_type e() const { return (*this)[P](); }
+ };
+
+ template<std::size_t N>
+ class object_array_t<logic_output_t,N> : public object_array_base_t<logic_output_t, N>
+ {
+ public:
+ using base_type = object_array_base_t<logic_output_t, N>;
+ using base_type::base_type;
+
+ template <typename T>
+ inline void push(const T &v, const netlist_time &t)
+ {
+ if (N >= 1) (*this)[0].push((v >> 0) & 1, t);
+ if (N >= 2) (*this)[1].push((v >> 1) & 1, t);
+ if (N >= 3) (*this)[2].push((v >> 2) & 1, t);
+ if (N >= 4) (*this)[3].push((v >> 3) & 1, t);
+ if (N >= 5) (*this)[4].push((v >> 4) & 1, t);
+ if (N >= 6) (*this)[5].push((v >> 5) & 1, t);
+ if (N >= 7) (*this)[6].push((v >> 6) & 1, t);
+ if (N >= 8) (*this)[7].push((v >> 7) & 1, t);
+ for (std::size_t i = 8; i < N; i++)
+ (*this)[i].push((v >> i) & 1, t);
+ }
+
+ template<typename T>
+ void push(const T &v, const netlist_time * t)
+ {
+ if (N >= 1) (*this)[0].push((v >> 0) & 1, t[0]);
+ if (N >= 2) (*this)[1].push((v >> 1) & 1, t[1]);
+ if (N >= 3) (*this)[2].push((v >> 2) & 1, t[2]);
+ if (N >= 4) (*this)[3].push((v >> 3) & 1, t[3]);
+ if (N >= 5) (*this)[4].push((v >> 4) & 1, t[4]);
+ if (N >= 6) (*this)[5].push((v >> 5) & 1, t[5]);
+ if (N >= 7) (*this)[6].push((v >> 6) & 1, t[6]);
+ if (N >= 8) (*this)[7].push((v >> 7) & 1, t[7]);
+ for (std::size_t i = 8; i < N; i++)
+ (*this)[i].push((v >> i) & 1, t[i]);
+ }
+
+ template<typename T, std::size_t NT>
+ void push(const T &v, const std::array<netlist_time, NT> &t)
+ {
+ static_assert(NT >= N, "Not enough timing entries provided");
+
+ push(v, t.data());
+ }
+
+ void set_tristate(netlist_sig_t v,
+ netlist_time ts_off_on, netlist_time ts_on_off) noexcept
+ {
+ for (std::size_t i = 0; i < N; i++)
+ (*this)[i].set_tristate(v, ts_off_on, ts_on_off);
+ }
+ };
+
+ template<std::size_t N>
+ class object_array_t<tristate_output_t, N> : public object_array_base_t<tristate_output_t, N>
+ {
+ public:
+ using base_type = object_array_base_t<tristate_output_t, N>;
+ using base_type::base_type;
+
+ template <typename T>
+ inline void push(const T &v, const netlist_time &t)
+ {
+ if (N >= 1) (*this)[0].push((v >> 0) & 1, t);
+ if (N >= 2) (*this)[1].push((v >> 1) & 1, t);
+ if (N >= 3) (*this)[2].push((v >> 2) & 1, t);
+ if (N >= 4) (*this)[3].push((v >> 3) & 1, t);
+ if (N >= 5) (*this)[4].push((v >> 4) & 1, t);
+ if (N >= 6) (*this)[5].push((v >> 5) & 1, t);
+ if (N >= 7) (*this)[6].push((v >> 6) & 1, t);
+ if (N >= 8) (*this)[7].push((v >> 7) & 1, t);
+ for (std::size_t i = 8; i < N; i++)
+ (*this)[i].push((v >> i) & 1, t);
+ }
+
+ void set_tristate(netlist_sig_t v,
+ netlist_time ts_off_on, netlist_time ts_on_off) noexcept
+ {
+ for (std::size_t i = 0; i < N; i++)
+ (*this)[i].set_tristate(v, ts_off_on, ts_on_off);
+ }
+ };
+
+} // namespace netlist
+
+
+#endif // NL_CORE_OBJECT_ARRAY_H_
diff --git a/src/lib/netlist/core/param.h b/src/lib/netlist/core/param.h
index 80769f2d47e..87741765815 100644
--- a/src/lib/netlist/core/param.h
+++ b/src/lib/netlist/core/param.h
@@ -25,9 +25,9 @@
#include "base_objects.h"
+#include "../plib/palloc.h"
#include "../plib/pstream.h"
#include "../plib/pstring.h"
-#include "../plib/palloc.h"
#include <memory>
diff --git a/src/lib/netlist/core/queue.h b/src/lib/netlist/core/queue.h
new file mode 100644
index 00000000000..7e38c3f0ef9
--- /dev/null
+++ b/src/lib/netlist/core/queue.h
@@ -0,0 +1,114 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+///
+/// \file queue.h
+///
+
+#ifndef NL_CORE_QUEUE_H_
+#define NL_CORE_QUEUE_H_
+
+#include "queue.h"
+
+#include "../nl_errstr.h"
+#include "../nltypes.h"
+
+#include "../plib/pstate.h"
+#include "../plib/pstring.h"
+#include "../plib/ptimed_queue.h"
+
+#include <array>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+namespace netlist
+{
+ namespace detail {
+ // 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>
+ // using timed_queue = plib::timed_queue_heap<T, TS>;
+
+ template <class T, bool TS>
+ using timed_queue = plib::timed_queue_linear<T, TS>;
+
+ // -----------------------------------------------------------------------------
+ // queue_t
+ // -----------------------------------------------------------------------------
+
+ // We don't need a thread-safe queue currently. Parallel processing of
+ // solvers will update inputs after parallel processing.
+
+ template <typename O, bool TS>
+ class queue_base :
+ public timed_queue<plib::pqentry_t<netlist_time_ext, O *>, false>,
+ public plib::state_manager_t::callback_t
+ {
+ public:
+ using entry_t = plib::pqentry_t<netlist_time_ext, O *>;
+ using base_queue = timed_queue<entry_t, false>;
+ using id_delegate = plib::pmfp<std::size_t, const O *>;
+ using obj_delegate = plib::pmfp<O *, std::size_t>;
+
+ explicit queue_base(std::size_t size, id_delegate get_id, obj_delegate get_obj)
+ : timed_queue<plib::pqentry_t<netlist_time_ext, O *>, false>(size)
+ , m_qsize(0)
+ , m_times(size)
+ , m_net_ids(size)
+ , m_get_id(get_id)
+ , m_obj_by_id(get_obj)
+ {
+ }
+
+ ~queue_base() noexcept override = default;
+
+ queue_base(const queue_base &) = delete;
+ queue_base(queue_base &&) = delete;
+ queue_base &operator=(const queue_base &) = delete;
+ queue_base &operator=(queue_base &&) = delete;
+
+ protected:
+
+ void register_state(plib::state_manager_t &manager, const pstring &module) override
+ {
+ manager.save_item(this, m_qsize, module + "." + "qsize");
+ manager.save_item(this, &m_times[0], module + "." + "times", m_times.size());
+ manager.save_item(this, &m_net_ids[0], module + "." + "names", m_net_ids.size());
+ }
+ void on_pre_save(plib::state_manager_t &manager) override
+ {
+ plib::unused_var(manager);
+ m_qsize = this->size();
+ for (std::size_t i = 0; i < m_qsize; i++ )
+ {
+ m_times[i] = this->listptr()[i].exec_time().as_raw();
+ m_net_ids[i] = m_get_id(this->listptr()[i].object());
+ }
+ }
+ void on_post_load(plib::state_manager_t &manager) override
+ {
+ plib::unused_var(manager);
+ this->clear();
+ for (std::size_t i = 0; i < m_qsize; i++ )
+ {
+ O *n = m_obj_by_id(m_net_ids[i]);
+ this->template push<false>(entry_t(netlist_time_ext::from_raw(m_times[i]),n));
+ }
+ }
+
+ private:
+ std::size_t m_qsize;
+ std::vector<netlist_time_ext::internal_type> m_times;
+ std::vector<std::size_t> m_net_ids;
+ id_delegate m_get_id;
+ obj_delegate m_obj_by_id;
+ };
+
+ using queue_t = queue_base<net_t, false>;
+
+ } // namespace detail
+} // namespace netlist
+
+
+#endif // NL_CORE_QUEUE_H_
diff --git a/src/lib/netlist/core/setup.h b/src/lib/netlist/core/setup.h
index d21b948f4ee..0f1f12b0e29 100644
--- a/src/lib/netlist/core/setup.h
+++ b/src/lib/netlist/core/setup.h
@@ -9,9 +9,9 @@
#define NL_CORE_SETUP_H_
#include "../nl_config.h"
-#include "../nltypes.h"
#include "../nl_factory.h"
#include "../nl_setup.h"
+#include "../nltypes.h"
#include "../plib/ppreprocessor.h"
#include "../plib/pstream.h"
diff --git a/src/lib/netlist/devices/nld_devinc.h b/src/lib/netlist/devices/nld_devinc.h
index 46afe121fdb..dce8d60f103 100644
--- a/src/lib/netlist/devices/nld_devinc.h
+++ b/src/lib/netlist/devices/nld_devinc.h
@@ -148,7 +148,7 @@
#define CLOCK(...) \
NET_REGISTER_DEVEXT(CLOCK, __VA_ARGS__)
-// usage : VARCLOCK(name, pFUNC)
+// usage : VARCLOCK(name, pN, pFUNC)
#define VARCLOCK(...) \
NET_REGISTER_DEVEXT(VARCLOCK, __VA_ARGS__)
@@ -441,14 +441,14 @@
// ---------------------------------------------------------------------
// Source: src/lib/netlist/devices/nld_74123.cpp
// ---------------------------------------------------------------------
+// usage : TTL_74121(name)
+#define TTL_74121(...) \
+ NET_REGISTER_DEVEXT(TTL_74121, __VA_ARGS__)
+
// usage : TTL_74123(name)
#define TTL_74123(...) \
NET_REGISTER_DEVEXT(TTL_74123, __VA_ARGS__)
-// usage : TTL_74123_DIP(name)
-#define TTL_74123_DIP(...) \
- NET_REGISTER_DEVEXT(TTL_74123_DIP, __VA_ARGS__)
-
// ---------------------------------------------------------------------
// Source: src/lib/netlist/devices/nld_74125.cpp
// ---------------------------------------------------------------------
@@ -475,17 +475,22 @@
// ---------------------------------------------------------------------
// Source: src/lib/netlist/devices/nld_74161.cpp
// ---------------------------------------------------------------------
-// usage : TTL_74161(name, pA, pB, pC, pD, pCLRQ, pLOADQ, pCLK, pENABLEP, pENABLET)
+// usage : TTL_74161(name, pCLK, pENP, pENT, pCLRQ, pLOADQ, pA, pB, pC, pD)
// auto connect: VCC, GND
#define TTL_74161(...) \
NET_REGISTER_DEVEXT(TTL_74161, __VA_ARGS__)
+// usage : TTL_74161_FIXME(name, pA, pB, pC, pD, pCLRQ, pLOADQ, pCLK, pENP, pENT)
+// auto connect: VCC, GND
+#define TTL_74161_FIXME(...) \
+ NET_REGISTER_DEVEXT(TTL_74161_FIXME, __VA_ARGS__)
+
// usage : TTL_74161_DIP(name)
#define TTL_74161_DIP(...) \
NET_REGISTER_DEVEXT(TTL_74161_DIP, __VA_ARGS__)
// ---------------------------------------------------------------------
-// Source: src/lib/netlist/devices/nld_9316.cpp
+// Source: src/lib/netlist/devices/nld_74163.cpp
// ---------------------------------------------------------------------
// usage : TTL_74163(name, pCLK, pENP, pENT, pCLRQ, pLOADQ, pA, pB, pC, pD)
// auto connect: VCC, GND
@@ -727,9 +732,9 @@
// ---------------------------------------------------------------------
// Source: src/lib/netlist/devices/nld_74123.cpp
// ---------------------------------------------------------------------
-// usage : CD4538_DIP(name)
-#define CD4538_DIP(...) \
- NET_REGISTER_DEVEXT(CD4538_DIP, __VA_ARGS__)
+// usage : CD4538(name)
+#define CD4538(...) \
+ NET_REGISTER_DEVEXT(CD4538, __VA_ARGS__)
// ---------------------------------------------------------------------
// Source: src/lib/netlist/devices/nld_schmitt.cpp
@@ -846,9 +851,9 @@
// ---------------------------------------------------------------------
// Source: src/lib/netlist/devices/nld_74123.cpp
// ---------------------------------------------------------------------
-// usage : TTL_9602_DIP(name)
-#define TTL_9602_DIP(...) \
- NET_REGISTER_DEVEXT(TTL_9602_DIP, __VA_ARGS__)
+// usage : TTL_9602(name)
+#define TTL_9602(...) \
+ NET_REGISTER_DEVEXT(TTL_9602, __VA_ARGS__)
// ---------------------------------------------------------------------
// Source: src/lib/netlist/devices/nld_9310.cpp
@@ -986,7 +991,7 @@
// usage : TTL_7421_AND(name, pA, pB, pC, pD)
// auto connect: VCC, GND
-#define TTL_7421_AND(...) \
+#define TTL_7421_AND(...) \
NET_REGISTER_DEVEXT(TTL_7421_AND, __VA_ARGS__)
// usage : TTL_7425_GATE(name)
@@ -1164,6 +1169,18 @@
#define TTL_7486_DIP(...) \
NET_REGISTER_DEVEXT(TTL_7486_DIP, __VA_ARGS__)
+// usage : TTL_74121_DIP(name)
+#define TTL_74121_DIP(...) \
+ NET_REGISTER_DEVEXT(TTL_74121_DIP, __VA_ARGS__)
+
+// usage : TTL_74123_DIP(name)
+#define TTL_74123_DIP(...) \
+ NET_REGISTER_DEVEXT(TTL_74123_DIP, __VA_ARGS__)
+
+// usage : TTL_9602_DIP(name)
+#define TTL_9602_DIP(...) \
+ NET_REGISTER_DEVEXT(TTL_9602_DIP, __VA_ARGS__)
+
// usage : TTL_74125_DIP(name)
#define TTL_74125_DIP(...) \
NET_REGISTER_DEVEXT(TTL_74125_DIP, __VA_ARGS__)
@@ -1251,6 +1268,10 @@
#define CD4316_DIP(...) \
NET_REGISTER_DEVEXT(CD4316_DIP, __VA_ARGS__)
+// usage : CD4538_DIP(name)
+#define CD4538_DIP(...) \
+ NET_REGISTER_DEVEXT(CD4538_DIP, __VA_ARGS__)
+
// ---------------------------------------------------------------------
// Source: src/lib/netlist/macro/nlm_opamp.cpp
// ---------------------------------------------------------------------
diff --git a/src/lib/netlist/devices/nld_log.cpp b/src/lib/netlist/devices/nld_log.cpp
index b00dc62ff0d..5c0c550e11c 100644
--- a/src/lib/netlist/devices/nld_log.cpp
+++ b/src/lib/netlist/devices/nld_log.cpp
@@ -8,8 +8,8 @@
#include "netlist/nl_base.h"
#include "nld_log.h"
#include "plib/pfmtlog.h"
-#include "plib/pstream.h"
#include "plib/pmulti_threading.h"
+#include "plib/pstream.h"
//#include "sound/wavwrite.h"
#include <array>
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index b3bc9c6434e..a8ba6937164 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -102,7 +102,7 @@ namespace devices
for (int i=0; i < m_N(); i++)
{
pstring inpname = plib::pfmt("A{1}")(i);
- m_I.push_back(state().make_pool_object<analog_input_t>(*this, inpname, NETLIB_DELEGATE(fb)));
+ m_I.push_back(owner.template make_pool_object<analog_input_t>(*this, inpname, NETLIB_DELEGATE(fb)));
inps.push_back(inpname);
m_vals.push_back(nlconst::zero());
}
@@ -460,7 +460,7 @@ namespace devices
for (int i=0; i < m_N(); i++)
{
pstring inpname = plib::pfmt("A{1}")(i);
- m_I.push_back(state().make_pool_object<analog_input_t>(*this, inpname, NETLIB_DELEGATE(inputs)));
+ m_I.push_back(owner.template make_pool_object<analog_input_t>(*this, inpname, NETLIB_DELEGATE(inputs)));
inps.push_back(inpname);
m_vals.push_back(nlconst::zero());
}
diff --git a/src/lib/netlist/macro/nlm_base.cpp b/src/lib/netlist/macro/nlm_base.cpp
index b399a2c360c..1185f482e73 100644
--- a/src/lib/netlist/macro/nlm_base.cpp
+++ b/src/lib/netlist/macro/nlm_base.cpp
@@ -1,6 +1,5 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
-#include "netlist/nl_setup.h"
#include "netlist/devices/net_lib.h"
#include "nlm_base.h"
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 22baf636461..3b07912a8d4 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -759,6 +759,16 @@ namespace netlist
net().initial(val);
}
+ // -----------------------------------------------------------------------------
+ // tristate_output_t
+ // -----------------------------------------------------------------------------
+ tristate_output_t::tristate_output_t(device_t &dev, const pstring &aname, bool force_logic)
+ : logic_output_t(dev, aname)
+ , m_last_logic(dev, name() + "." + "m_last_logic", 1) // force change
+ , m_tristate(dev, name() + "." + "m_tristate", force_logic ? 0 : 2) // force change
+ , m_force_logic(force_logic)
+ {}
+
// ----------------------------------------------------------------------------------------
// analog_input_t
// ----------------------------------------------------------------------------------------
@@ -939,6 +949,17 @@ namespace netlist
nlparse_t &netlist_state_t::parser() { return m_setup->parser(); }
const nlparse_t &netlist_state_t::parser() const { return m_setup->parser(); }
+ void netlist_state_t::remove_device(core_device_t *dev)
+ {
+ for (auto it = m_devices.begin(); it != m_devices.end(); it++)
+ if (it->second.get() == dev)
+ {
+ m_state.remove_save_items(dev);
+ m_devices.erase(it);
+ return;
+ }
+ }
+
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 45b64c5e122..cf2acfd9d54 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -12,11 +12,16 @@
#error "nl_base.h included. Please correct."
#endif
+#include "core/analog.h"
#include "core/base_objects.h"
-#include "core/param.h"
-#include "core/state_var.h"
+#include "core/device.h"
+#include "core/logic.h"
#include "core/logic_family.h"
+#include "core/netlist_state.h"
#include "core/nets.h"
+#include "core/object_array.h"
+#include "core/param.h"
+#include "core/state_var.h"
#include "plib/palloc.h" // owned_ptr
#include "plib/pfunction.h"
@@ -211,664 +216,6 @@ namespace netlist
- // -----------------------------------------------------------------------------
- // analog_t
- // -----------------------------------------------------------------------------
-
- class analog_t : public detail::core_terminal_t
- {
- public:
-
- analog_t(core_device_t &dev, const pstring &aname, state_e state,
- nldelegate delegate);
-
- const analog_net_t & net() const noexcept;
- analog_net_t & net() noexcept;
-
- solver::matrix_solver_t *solver() const noexcept;
- };
-
- /// \brief Base clase for terminals.
- ///
- /// Each \ref nld_twoterm object consists of two terminals. Terminals
- /// are at the core of analog netlists and provide. \ref net_t objects
- /// connect terminals.
- ///
- class terminal_t : public analog_t
- {
- public:
-
- /// \brief constructor
- ///
- /// @param dev core_devict_t object owning the terminal
- /// @param aname name of this terminal
- /// @param otherterm pointer to the sibling terminal
- terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm, nldelegate delegate);
-
- /// \brief Returns voltage of connected net
- ///
- /// @return voltage of net this terminal is connected to
- nl_fptype operator ()() const noexcept;
-
- /// @brief sets conductivity value of this terminal
- ///
- /// @param G Conductivity
- void set_conductivity(nl_fptype G) const noexcept
- {
- set_go_gt_I(-G, G, nlconst::zero());
- }
-
- void set_go_gt(nl_fptype GO, nl_fptype GT) const noexcept
- {
- set_go_gt_I(GO, GT, nlconst::zero());
- }
-
- void set_go_gt_I(nl_fptype GO, nl_fptype GT, nl_fptype I) const noexcept
- {
- // Check for rail nets ...
- if (m_go != nullptr)
- {
- *m_Idr = I;
- *m_go = GO;
- *m_gt = GT;
- }
- }
-
- void set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(false);
-
- private:
- nl_fptype *m_Idr; ///< drive current
- nl_fptype *m_go; ///< conductance for Voltage from other term
- nl_fptype *m_gt; ///< conductance for total conductance
-
- };
-
-
- // -----------------------------------------------------------------------------
- // logic_t
- // -----------------------------------------------------------------------------
-
- class logic_t : public detail::core_terminal_t, public logic_family_t
- {
- public:
- logic_t(device_t &dev, const pstring &aname,
- state_e terminal_state, nldelegate delegate);
-
- logic_net_t & net() noexcept;
- const logic_net_t & net() const noexcept;
- };
-
- // -----------------------------------------------------------------------------
- // logic_input_t
- // -----------------------------------------------------------------------------
-
- class logic_input_t : public logic_t
- {
- public:
- logic_input_t(device_t &dev, const pstring &aname,
- nldelegate delegate);
-
- inline netlist_sig_t operator()() const noexcept;
-
- void inactivate() noexcept;
- void activate() noexcept;
- void activate_hl() noexcept;
- void activate_lh() noexcept;
- };
-
- // -----------------------------------------------------------------------------
- // analog_input_t
- // -----------------------------------------------------------------------------
-
- /// \brief terminal providing analog input voltage.
- ///
- /// This terminal class provides a voltage measurement. The conductance against
- /// ground is infinite.
-
- class analog_input_t : public analog_t
- {
- public:
- /// \brief Constructor
- analog_input_t(core_device_t &dev, ///< owning device
- const pstring &aname, ///< name of terminal
- nldelegate delegate ///< delegate
- );
-
- /// \brief returns voltage at terminal.
- /// \returns voltage at terminal.
- nl_fptype operator()() const noexcept { return Q_Analog(); }
-
- /// \brief returns voltage at terminal.
- /// \returns voltage at terminal.
- nl_fptype Q_Analog() const noexcept;
- };
-
- // -----------------------------------------------------------------------------
- // logic_output_t
- // -----------------------------------------------------------------------------
-
- class logic_output_t : public logic_t
- {
- public:
-
- /// \brief logic output constructor
- ///
- /// The third parameter does nothing. It is provided only for
- /// compatibility with tristate_output_t in templatized device models
- ///
- /// \param dev Device owning this output
- /// \param aname The name of this output
- /// \param dummy Dummy parameter to allow construction like tristate output
- ///
- logic_output_t(device_t &dev, const pstring &aname, bool dummy = false);
-
- void initial(netlist_sig_t val) noexcept;
-
- inline void push(const netlist_sig_t &newQ, const netlist_time &delay) noexcept
- {
- m_my_net.set_Q_and_push(newQ, delay); // take the shortcut
- }
-
- inline void set_Q_time(const netlist_sig_t &newQ, const netlist_time_ext &at) noexcept
- {
- m_my_net.set_Q_time(newQ, at); // take the shortcut
- }
-
- /// \brief Dummy implementation for templatized generic devices
- ///
- /// This function shall never be called. It is defined here so that
- /// templatized generic device models do not have to do tons of
- /// template magic.
- ///
- /// This function terminates if actually called.
- ///
- [[noreturn]] static void set_tristate(netlist_sig_t v,
- netlist_time ts_off_on, netlist_time ts_on_off)
- {
- plib::unused_var(v, ts_off_on, ts_on_off);
- plib::terminate("set_tristate on logic_output should never be called!");
- }
- private:
- logic_net_t m_my_net;
- };
-
- // -----------------------------------------------------------------------------
- // tristate_output_t
- // -----------------------------------------------------------------------------
-
- /// \brief Tristate output
- ///
- /// In a lot of applications tristate enable inputs are just connected to
- /// VCC/GND to permanently enable the outputs. In this case a pure
- /// implementation using analog outputs would not perform well.
- ///
- /// For this object during creation it can be decided if a logic output or
- /// a tristate output is used. Generally the owning device uses parameter
- /// FORCE_TRISTATE_LOGIC to determine this.
- ///
- /// This is the preferred way to implement tristate outputs.
- ///
-
- class tristate_output_t : public logic_output_t
- {
- public:
-
- tristate_output_t(device_t &dev, const pstring &aname, bool force_logic)
- : logic_output_t(dev, aname)
- , m_last_logic(dev, name() + "." + "m_last_logic", 1) // force change
- , m_tristate(dev, name() + "." + "m_tristate", force_logic ? 0 : 2) // force change
- , m_force_logic(force_logic)
- {}
-
- void push(netlist_sig_t newQ, netlist_time delay) noexcept
- {
- if (!m_tristate)
- logic_output_t::push(newQ, delay);
- m_last_logic = newQ;
- }
-
- void set_tristate(netlist_sig_t v,
- netlist_time ts_off_on, netlist_time ts_on_off) noexcept
- {
- if (!m_force_logic)
- if (v != m_tristate)
- {
- logic_output_t::push((v != 0) ? OUT_TRISTATE() : m_last_logic, v ? ts_off_on : ts_on_off);
- m_tristate = v;
- }
- }
-
- bool is_force_logic() const noexcept
- {
- return m_force_logic;
- }
-
- private:
- using logic_output_t::initial;
- using logic_output_t::set_Q_time;
- state_var<netlist_sig_t> m_last_logic;
- state_var<netlist_sig_t> m_tristate;
- bool m_force_logic;
- };
-
-
- // -----------------------------------------------------------------------------
- // analog_output_t
- // -----------------------------------------------------------------------------
-
- class analog_output_t : public analog_t
- {
- public:
- analog_output_t(core_device_t &dev, const pstring &aname);
-
- void push(nl_fptype val) noexcept;
- void initial(nl_fptype val) noexcept;
-
- private:
- analog_net_t m_my_net;
- };
-
-
- // -----------------------------------------------------------------------------
- // 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);
-
- 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
- {
- public:
- device_t(netlist_state_t &owner, const pstring &name);
- device_t(netlist_state_t &owner, const pstring &name,
- const pstring &model);
- // only needed by proxies
- device_t(netlist_state_t &owner, const pstring &name,
- const logic_family_desc_t *desc);
-
- device_t(device_t &owner, const pstring &name);
- // pass in a default model - this may be overwritten by PARAM(DEVICE.MODEL, "XYZ(...)")
- device_t(device_t &owner, const pstring &name,
- const pstring &model);
-
- PCOPYASSIGNMOVE(device_t, delete)
-
- ~device_t() noexcept override = default;
-
- protected:
-
- //NETLIB_UPDATE_TERMINALSI() { }
-
- private:
- param_model_t m_model;
- };
-
- namespace detail {
- // 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>
- // using timed_queue = plib::timed_queue_heap<T, TS>;
-
- template <class T, bool TS>
- using timed_queue = plib::timed_queue_linear<T, TS>;
-
- // -----------------------------------------------------------------------------
- // queue_t
- // -----------------------------------------------------------------------------
-
- // We don't need a thread-safe queue currently. Parallel processing of
- // solvers will update inputs after parallel processing.
-
- template <typename O, bool TS>
- class queue_base :
- public timed_queue<plib::pqentry_t<netlist_time_ext, O *>, false>,
- public plib::state_manager_t::callback_t
- {
- public:
- using entry_t = plib::pqentry_t<netlist_time_ext, O *>;
- using base_queue = timed_queue<entry_t, false>;
- using id_delegate = plib::pmfp<std::size_t, const O *>;
- using obj_delegate = plib::pmfp<O *, std::size_t>;
-
- explicit queue_base(std::size_t size, id_delegate get_id, obj_delegate get_obj)
- : timed_queue<plib::pqentry_t<netlist_time_ext, O *>, false>(size)
- , m_qsize(0)
- , m_times(size)
- , m_net_ids(size)
- , m_get_id(get_id)
- , m_obj_by_id(get_obj)
- {
- }
-
- ~queue_base() noexcept override = default;
-
- queue_base(const queue_base &) = delete;
- queue_base(queue_base &&) = delete;
- queue_base &operator=(const queue_base &) = delete;
- queue_base &operator=(queue_base &&) = delete;
-
- protected:
-
- void register_state(plib::state_manager_t &manager, const pstring &module) override
- {
- manager.save_item(this, m_qsize, module + "." + "qsize");
- manager.save_item(this, &m_times[0], module + "." + "times", m_times.size());
- manager.save_item(this, &m_net_ids[0], module + "." + "names", m_net_ids.size());
- }
- void on_pre_save(plib::state_manager_t &manager) override
- {
- plib::unused_var(manager);
- m_qsize = this->size();
- for (std::size_t i = 0; i < m_qsize; i++ )
- {
- m_times[i] = this->listptr()[i].exec_time().as_raw();
- m_net_ids[i] = m_get_id(this->listptr()[i].object());
- }
- }
- void on_post_load(plib::state_manager_t &manager) override
- {
- plib::unused_var(manager);
- this->clear();
- for (std::size_t i = 0; i < m_qsize; i++ )
- {
- O *n = m_obj_by_id(m_net_ids[i]);
- this->template push<false>(entry_t(netlist_time_ext::from_raw(m_times[i]),n));
- }
- }
-
- private:
- std::size_t m_qsize;
- std::vector<netlist_time_ext::internal_type> m_times;
- std::vector<std::size_t> m_net_ids;
- id_delegate m_get_id;
- obj_delegate m_obj_by_id;
- };
-
- using queue_t = queue_base<net_t, false>;
-
- } // namespace detail
-
- // -----------------------------------------------------------------------------
- // netlist_state__t
- // -----------------------------------------------------------------------------
-
- class netlist_state_t
- {
- public:
-
- using nets_collection_type = std::vector<device_arena::owned_ptr<detail::net_t>>;
- using family_collection_type = std::unordered_map<pstring, host_arena::unique_ptr<logic_family_desc_t>>;
-
- // need to preserve order of device creation ...
- using devices_collection_type = std::vector<std::pair<pstring, device_arena::owned_ptr<core_device_t>>>;
- netlist_state_t(const pstring &name, host_arena::unique_ptr<callbacks_t> &&callbacks);
-
- PCOPYASSIGNMOVE(netlist_state_t, delete)
-
- /// \brief Destructor
- ///
- /// The destructor is virtual to allow implementation specific devices
- /// to connect to the outside world. For examples see MAME netlist.cpp.
- ///
- virtual ~netlist_state_t() noexcept = default;
-
- template<class C>
- static bool check_class(core_device_t *p) noexcept
- {
- return dynamic_cast<C *>(p) != nullptr;
- }
-
- core_device_t *get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const noexcept(false);
-
- /// \brief Get single device filtered by class and name
- ///
- /// \tparam C Device class for which devices will be returned
- /// \param name Name of the device
- ///
- /// \return pointers to device
-
- template<class C>
- C *get_single_device(const pstring &name) const
- {
- return dynamic_cast<C *>(get_single_device(name, check_class<C>));
- }
-
- /// \brief Get vector of devices
- ///
- /// \tparam C Device class for which devices will be returned
- ///
- /// \return vector with pointers to devices
-
- template<class C>
- inline std::vector<C *> get_device_list() const
- {
- std::vector<C *> tmp;
- for (const auto &d : m_devices)
- {
- auto * const dev = dynamic_cast<C *>(d.second.get());
- if (dev != nullptr)
- tmp.push_back(dev);
- }
- return tmp;
- }
-
- // logging
-
- log_type & log() noexcept { return m_log; }
- const log_type &log() const noexcept { return m_log; }
-
- plib::dynlib_base &lib() const noexcept { return *m_lib; }
-
- netlist_t &exec() noexcept { return *m_netlist; }
- const netlist_t &exec() const noexcept { return *m_netlist; }
-
- // state handling
- plib::state_manager_t &run_state_manager() noexcept { return m_state; }
-
- template<typename O, typename C>
- void save(O &owner, C &state, const pstring &module, const pstring &stname)
- {
- this->run_state_manager().save_item(static_cast<void *>(&owner), state, module + "." + stname);
- }
-
- template<typename O, typename C>
- void save(O &owner, C *state, const pstring &module, const pstring &stname, const std::size_t count)
- {
- this->run_state_manager().save_state_ptr(static_cast<void *>(&owner), module + "." + stname, plib::state_manager_t::dtype<C>(), count, state);
- }
-
- // FIXME: only used by queue_t save state
- std::size_t find_net_id(const detail::net_t *net) const;
- detail::net_t *net_by_id(std::size_t id) const;
-
- template <typename T>
- void register_net(device_arena::owned_ptr<T> &&net) { m_nets.push_back(std::move(net)); }
-
- /// \brief Get device pointer by name
- ///
- ///
- /// \param name Name of the device
- ///
- /// \return core_device_t pointer if device exists, else nullptr
-
- core_device_t *find_device(const pstring &name) const
- {
- for (const auto & d : m_devices)
- if (d.first == name)
- return d.second.get();
- return nullptr;
- }
-
- /// \brief Register device using owned_ptr
- ///
- /// Used to register owned devices. These are devices declared as objects
- /// in another devices.
- ///
- /// \param name Name of the device
- /// \param dev Device to be registered
-
- template <typename T>
- void register_device(const pstring &name, device_arena::owned_ptr<T> &&dev) noexcept(false)
- {
- for (auto & d : m_devices)
- if (d.first == name)
- {
- dev.release();
- log().fatal(MF_DUPLICATE_NAME_DEVICE_LIST(name));
- throw nl_exception(MF_DUPLICATE_NAME_DEVICE_LIST(name));
- }
- //m_devices.push_back(std::move(dev));
- m_devices.insert(m_devices.end(), { name, std::move(dev) });
- }
-
- /// \brief Register device using unique_ptr
- ///
- /// Used to register devices.
- ///
- /// \param name Name of the device
- /// \param dev Device to be registered
-
- template <typename T>
- void register_device(const pstring &name, device_arena::unique_ptr<T> &&dev)
- {
- register_device(name, device_arena::owned_ptr<T>(dev.release(), true, dev.get_deleter()));
- }
-
- /// \brief Remove device
- ///
- /// Care needs to be applied if this is called to remove devices with
- /// sub-devices which may have registered state.
- ///
- /// \param dev Device to be removed
-
- void remove_device(core_device_t *dev)
- {
- for (auto it = m_devices.begin(); it != m_devices.end(); it++)
- if (it->second.get() == dev)
- {
- m_state.remove_save_items(dev);
- m_devices.erase(it);
- return;
- }
- }
-
- setup_t &setup() noexcept { return *m_setup; }
- const setup_t &setup() const noexcept { return *m_setup; }
-
- nlparse_t &parser();
- const nlparse_t &parser() const;
-
- // FIXME: make a postload member and include code there
- void rebuild_lists(); // must be called after post_load !
-
- static void compile_defines(std::vector<std::pair<pstring, pstring>> &defs);
- static pstring version();
- static pstring version_patchlevel();
-
- nets_collection_type & nets() noexcept { return m_nets; }
- const nets_collection_type & nets() const noexcept { return m_nets; }
-
- devices_collection_type & devices() noexcept { return m_devices; }
- const devices_collection_type & devices() const noexcept { return m_devices; }
-
- family_collection_type &family_cache() { return m_family_cache; }
-
- template<typename T, typename... Args>
- device_arena::unique_ptr<T> make_pool_object(Args&&... args)
- {
- return plib::make_unique<T>(m_pool, std::forward<Args>(args)...);
- }
- // memory pool - still needed in some places
- device_arena &pool() noexcept { return m_pool; }
- const device_arena &pool() const noexcept { return m_pool; }
-
- /// \brief set extended validation mode.
- ///
- /// The extended validation mode is not intended for running.
- /// The intention is to identify power pins which are not properly
- /// connected. The downside is that this mode creates a netlist which
- /// is different (and not able to run).
- ///
- /// Extended validation is supported by nltool validate option.
- ///
- /// \param val Boolean value enabling/disabling extended validation mode
- void set_extended_validation(bool val) { m_extended_validation = val; }
-
- /// \brief State of extended validation mode.
- ///
- /// \returns boolean value indicating if extended validation mode is
- /// turned on.
- bool is_extended_validation() const { return m_extended_validation; }
-
- struct stats_info
- {
- const detail::queue_t &m_queue;// performance
- const plib::pperftime_t<true> &m_stat_mainloop;
- const plib::pperfcount_t<true> &m_perf_out_processed;
- };
-
- /// \brief print statistics gathered during run
- ///
- void print_stats(stats_info &si) const;
-
- /// \brief call reset on all netlist components
- ///
- void reset();
-
- /// \brief prior to running free no longer needed resources
- ///
- void free_setup_resources();
-
- private:
-
- device_arena m_pool; // must be deleted last!
-
- device_arena::unique_ptr<netlist_t> m_netlist;
- std::unique_ptr<plib::dynlib_base> m_lib;
- plib::state_manager_t m_state;
- host_arena::unique_ptr<callbacks_t> m_callbacks;
- log_type m_log;
-
- // FIXME: should only be available during device construcion
- host_arena::unique_ptr<setup_t> m_setup;
-
- nets_collection_type m_nets;
- // sole use is to manage lifetime of net objects
- devices_collection_type m_devices;
- // sole use is to manage lifetime of family objects
- family_collection_type m_family_cache;
- bool m_extended_validation;
-
- // dummy version
- int m_dummy_version;
- };
namespace devices
{
@@ -1001,206 +348,6 @@ namespace netlist
// Support classes for devices
// -----------------------------------------------------------------------------
- template<class C, std::size_t N>
- class object_array_base_t : public plib::static_vector<C, N>
- {
- public:
- template<class D, typename... Args>
- //object_array_base_t(D &dev, const std::initializer_list<const char *> &names, Args&&... args)
- object_array_base_t(D &dev, std::array<const char *, N> &&names, Args&&... args)
- {
- for (std::size_t i = 0; i<N; i++)
- this->emplace_back(dev, pstring(names[i]), std::forward<Args>(args)...);
- }
-
- template<class D>
- object_array_base_t(D &dev, const pstring &fmt)
- {
- for (std::size_t i = 0; i<N; i++)
- this->emplace_back(dev, formatted(fmt, i));
- }
-
- template<class D, typename... Args>
- object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, Args&&... args)
- {
- for (std::size_t i = 0; i<N; i++)
- this->emplace_back(dev, formatted(fmt, i+offset), std::forward<Args>(args)...);
- }
-
- template<class D>
- object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, nldelegate delegate)
- {
- for (std::size_t i = 0; i<N; i++)
- this->emplace_back(dev, formatted(fmt, i+offset), delegate);
- }
-
- template<class D>
- object_array_base_t(D &dev, std::size_t offset, std::size_t qmask, const pstring &fmt)
- {
- for (std::size_t i = 0; i<N; i++)
- {
- pstring name(formatted(fmt, i+offset));
- if ((qmask >> i) & 1)
- name += "Q";
- this->emplace(i, dev, name);
- }
- }
- protected:
- object_array_base_t() = default;
-
- static pstring formatted(const pstring &fmt, std::size_t n)
- {
- if (N != 1)
- return plib::pfmt(fmt)(n);
- return plib::pfmt(fmt)("");
- }
- };
-
-
- template<class C, std::size_t N>
- class object_array_t : public object_array_base_t<C, N>
- {
- public:
- using base_type = object_array_base_t<C, N>;
- using base_type::base_type;
- };
-
- template<std::size_t N>
- class object_array_t<logic_input_t,N> : public object_array_base_t<logic_input_t, N>
- {
- public:
- using base_type = object_array_base_t<logic_input_t, N>;
- using base_type::base_type;
-
- template<class D, std::size_t ND>
- object_array_t(D &dev, std::size_t offset, std::size_t qmask,
- const pstring &fmt, std::array<nldelegate, ND> &&delegates)
- {
- static_assert(N <= ND, "initializer_list size mismatch");
- std::size_t i = 0;
- for (auto &e : delegates)
- {
- if (i < N)
- {
- pstring name(this->formatted(fmt, i+offset));
- if ((qmask >> i) & 1)
- name += "Q";
- this->emplace_back(dev, name, e);
- }
- i++;
- }
- }
-
- //using value_type = typename plib::fast_type_for_bits<N>::type;
- using value_type = std::uint32_t;
- value_type operator ()()
- {
- if (N == 1) return e<0>() ;
- if (N == 2) return e<0>() | (e<1>() << 1);
- if (N == 3) return e<0>() | (e<1>() << 1) | (e<2>() << 2);
- if (N == 4) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3);
- if (N == 5) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
- | (e<4>() << 4);
- if (N == 6) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
- | (e<4>() << 4) | (e<5>() << 5);
- if (N == 7) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
- | (e<4>() << 4) | (e<5>() << 5) | (e<6>() << 6);
- if (N == 8) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
- | (e<4>() << 4) | (e<5>() << 5) | (e<6>() << 6) | (e<7>() << 7);
-
- value_type r(0);
- for (std::size_t i = 0; i < N; i++)
- r = static_cast<value_type>((*this)[i]() << (N-1)) | (r >> 1);
- return r;
- }
-
- private:
- template <std::size_t P>
- inline constexpr value_type e() const { return (*this)[P](); }
- };
-
- template<std::size_t N>
- class object_array_t<logic_output_t,N> : public object_array_base_t<logic_output_t, N>
- {
- public:
- using base_type = object_array_base_t<logic_output_t, N>;
- using base_type::base_type;
-
- template <typename T>
- inline void push(const T &v, const netlist_time &t)
- {
- if (N >= 1) (*this)[0].push((v >> 0) & 1, t);
- if (N >= 2) (*this)[1].push((v >> 1) & 1, t);
- if (N >= 3) (*this)[2].push((v >> 2) & 1, t);
- if (N >= 4) (*this)[3].push((v >> 3) & 1, t);
- if (N >= 5) (*this)[4].push((v >> 4) & 1, t);
- if (N >= 6) (*this)[5].push((v >> 5) & 1, t);
- if (N >= 7) (*this)[6].push((v >> 6) & 1, t);
- if (N >= 8) (*this)[7].push((v >> 7) & 1, t);
- for (std::size_t i = 8; i < N; i++)
- (*this)[i].push((v >> i) & 1, t);
- }
-
- template<typename T>
- void push(const T &v, const netlist_time * t)
- {
- if (N >= 1) (*this)[0].push((v >> 0) & 1, t[0]);
- if (N >= 2) (*this)[1].push((v >> 1) & 1, t[1]);
- if (N >= 3) (*this)[2].push((v >> 2) & 1, t[2]);
- if (N >= 4) (*this)[3].push((v >> 3) & 1, t[3]);
- if (N >= 5) (*this)[4].push((v >> 4) & 1, t[4]);
- if (N >= 6) (*this)[5].push((v >> 5) & 1, t[5]);
- if (N >= 7) (*this)[6].push((v >> 6) & 1, t[6]);
- if (N >= 8) (*this)[7].push((v >> 7) & 1, t[7]);
- for (std::size_t i = 8; i < N; i++)
- (*this)[i].push((v >> i) & 1, t[i]);
- }
-
- template<typename T, std::size_t NT>
- void push(const T &v, const std::array<netlist_time, NT> &t)
- {
- static_assert(NT >= N, "Not enough timing entries provided");
-
- push(v, t.data());
- }
-
- void set_tristate(netlist_sig_t v,
- netlist_time ts_off_on, netlist_time ts_on_off) noexcept
- {
- for (std::size_t i = 0; i < N; i++)
- (*this)[i].set_tristate(v, ts_off_on, ts_on_off);
- }
- };
-
- template<std::size_t N>
- class object_array_t<tristate_output_t,N> : public object_array_base_t<tristate_output_t, N>
- {
- public:
- using base_type = object_array_base_t<tristate_output_t, N>;
- using base_type::base_type;
-
- template <typename T>
- inline void push(const T &v, const netlist_time &t)
- {
- if (N >= 1) (*this)[0].push((v >> 0) & 1, t);
- if (N >= 2) (*this)[1].push((v >> 1) & 1, t);
- if (N >= 3) (*this)[2].push((v >> 2) & 1, t);
- if (N >= 4) (*this)[3].push((v >> 3) & 1, t);
- if (N >= 5) (*this)[4].push((v >> 4) & 1, t);
- if (N >= 6) (*this)[5].push((v >> 5) & 1, t);
- if (N >= 7) (*this)[6].push((v >> 6) & 1, t);
- if (N >= 8) (*this)[7].push((v >> 7) & 1, t);
- for (std::size_t i = 8; i < N; i++)
- (*this)[i].push((v >> i) & 1, t);
- }
-
- void set_tristate(netlist_sig_t v,
- netlist_time ts_off_on, netlist_time ts_on_off) noexcept
- {
- for (std::size_t i = 0; i < N; i++)
- (*this)[i].set_tristate(v, ts_off_on, ts_on_off);
- }
- };
// -----------------------------------------------------------------------------
// power pins - not a device, but a helper
@@ -1254,7 +401,7 @@ namespace netlist
// -----------------------------------------------------------------------------
// logic_input_t
// -----------------------------------------------------------------------------
-
+#if 0
inline void logic_input_t::inactivate() noexcept
{
if (!is_state(STATE_INP_PASSIVE))
@@ -1290,7 +437,7 @@ namespace netlist
set_state(STATE_INP_LH);
}
}
-
+#endif
inline void detail::net_t::push_to_queue(const netlist_time &delay) noexcept
{
if (has_connections())
@@ -1352,6 +499,12 @@ namespace netlist
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());
@@ -1362,7 +515,6 @@ namespace netlist
return plib::downcast<analog_net_t &>(core_terminal_t::net());
}
- inline nl_fptype terminal_t::operator ()() const noexcept { return net().Q_Analog(); }
inline logic_net_t & logic_t::net() noexcept
{
@@ -1373,7 +525,6 @@ namespace netlist
{
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);
@@ -1397,6 +548,7 @@ namespace netlist
m_my_net.toggle_and_push_to_queue(netlist_time::quantum());
}
}
+#endif
inline netlist_t &detail::device_object_t::exec() noexcept
{
@@ -1524,13 +676,13 @@ namespace netlist
// -----------------------------------------------------------------------------
// 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();
@@ -1593,12 +745,13 @@ namespace netlist
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);
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index 25c957e5a07..ad26a505453 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -129,6 +129,7 @@ namespace factory {
const pstring &name, std::tuple<Args...>& args, std::index_sequence<Is...>)
{
return plib::make_unique<C>(pool, anetlist, name, std::forward<Args>(std::get<Is>(args))...);
+ //return anetlist.make_pool_object<C>(anetlist, name, std::forward<Args>(std::get<Is>(args))...);
}
dev_uptr make_device(device_arena &pool,
diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h
index be1de61aa44..1dcb1f943c9 100644
--- a/src/lib/netlist/nltypes.h
+++ b/src/lib/netlist/nltypes.h
@@ -14,11 +14,11 @@
#include "nl_config.h"
+#include "plib/pmempool.h"
+#include "plib/ppmf.h"
#include "plib/pstring.h"
#include "plib/ptime.h"
#include "plib/ptypes.h"
-#include "plib/ppmf.h"
-#include "plib/pmempool.h"
#include <memory>
@@ -45,6 +45,7 @@ namespace netlist
// -----------------------------------------------------------------------------
class logic_output_t;
+ class tristate_output_t;
class logic_input_t;
class analog_net_t;
class logic_net_t;
@@ -294,6 +295,32 @@ namespace netlist
using desc_const_t = std::integral_constant<const T, V>;
};
+ //============================================================
+ // Exceptions
+ //============================================================
+
+ /// \brief Generic netlist exception.
+ /// The exception is used in all events which are considered fatal.
+
+ class nl_exception : public plib::pexception
+ {
+ public:
+ /// \brief Constructor.
+ /// Allows a descriptive text to be passed to the exception
+
+ explicit nl_exception(const pstring &text //!< text to be passed
+ )
+ : plib::pexception(text) { }
+
+ /// \brief Constructor.
+ /// Allows to use \ref plib::pfmt logic to be used in exception
+
+ template<typename... Args>
+ explicit nl_exception(const pstring &fmt //!< format to be used
+ , Args&&... args //!< arguments to be passed
+ )
+ : plib::pexception(plib::pfmt(fmt)(std::forward<Args>(args)...)) { }
+ };
} // namespace netlist
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index 230b05f03c4..b0e21924dd7 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -10,9 +10,9 @@
#include "pconfig.h"
#include "pgsl.h"
+#include "pgsl.h"
#include "pmath.h" // FIXME: only uses lcm ... move to ptypes.
#include "ptypes.h"
-#include "pgsl.h"
#include <algorithm>
#include <cstddef> // for std::max_align_t (usually long long)
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index 1fc2615ed42..526243d4e90 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -11,10 +11,10 @@
#include <array>
#include <map>
+#include <map>
#include <stack>
#include <type_traits>
#include <utility>
-#include <map>
namespace plib {
diff --git a/src/lib/netlist/plib/pmulti_threading.h b/src/lib/netlist/plib/pmulti_threading.h
index b359af084e6..9f470054e2d 100644
--- a/src/lib/netlist/plib/pmulti_threading.h
+++ b/src/lib/netlist/plib/pmulti_threading.h
@@ -12,10 +12,10 @@
#include <algorithm>
#include <atomic>
+#include <condition_variable>
#include <mutex>
#include <type_traits>
#include <utility>
-#include <condition_variable>
namespace plib {
diff --git a/src/lib/netlist/plib/ptests.h b/src/lib/netlist/plib/ptests.h
index 9755d49c240..e0faaf99bbb 100644
--- a/src/lib/netlist/plib/ptests.h
+++ b/src/lib/netlist/plib/ptests.h
@@ -10,11 +10,11 @@
/// google tests compatible (hopefully) test macros. This is work in progress!
///
+#include <exception>
+#include <functional>
+#include <iostream>
#include <string>
#include <vector>
-#include <iostream>
-#include <functional>
-#include <exception>
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wglobal-constructors"
@@ -115,7 +115,7 @@ namespace testing
{
using reg_entry_base::reg_entry_base;
- virtual Test *create() const override { return new T(); }
+ Test *create() const override { return new T(); }
};
template <typename C, typename T1, typename T2>
diff --git a/src/lib/netlist/plib/ptimed_queue.h b/src/lib/netlist/plib/ptimed_queue.h
index 5e62d5b82aa..fe60fadb75f 100644
--- a/src/lib/netlist/plib/ptimed_queue.h
+++ b/src/lib/netlist/plib/ptimed_queue.h
@@ -8,10 +8,10 @@
/// \file ptimed_queue.h
///
+#include "palloc.h" // FIXME: for aligned_vector
#include "pchrono.h"
#include "pmulti_threading.h"
#include "ptypes.h"
-#include "palloc.h" // FIXME: for aligned_vector
#include <algorithm>
#include <mutex>
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
index b518e92918d..4076de4bd12 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.cpp
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -2,9 +2,9 @@
// copyright-holders:Couriersud
#include "nld_solver.h"
-#include "nld_matrix_solver.h"
#include "core/setup.h"
#include "nl_setup.h"
+#include "nld_matrix_solver.h"
#include "plib/putil.h"
namespace netlist
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index 3d1a025d289..a5bda6a070e 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -80,7 +80,7 @@ namespace solver
constexpr nl_fptype m_gmin() { return nlconst::magic(1e-9); }
constexpr bool m_pivot() { return false; }
constexpr nl_fptype m_nr_recalc_delay(){ return netlist_time::quantum().as_fp<nl_fptype>(); }
- constexpr std::size_t m_parallel() { return 0; }
+ constexpr int m_parallel() { return 0; }
constexpr nl_fptype m_min_ts_ts() { return nlconst::magic(1e-9); }
// automatic time step
diff --git a/src/lib/netlist/tests/test_pfunction.cpp b/src/lib/netlist/tests/test_pfunction.cpp
index cb0cad8e188..60e6753b7ac 100644
--- a/src/lib/netlist/tests/test_pfunction.cpp
+++ b/src/lib/netlist/tests/test_pfunction.cpp
@@ -9,8 +9,8 @@
#include "plib/ptests.h"
-#include "plib/pfunction.h"
#include "plib/pexception.h"
+#include "plib/pfunction.h"
#define PFUNCEXPECT(formula, val) \
PEXPECT_EQ(val, plib::pfunction<double>(formula)())