summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2020-06-01 19:58:07 +0200
committer couriersud <couriersud@gmx.org>2020-06-01 19:59:52 +0200
commit3fd176a7a6700a1818059df4faf58e57d523119b (patch)
tree7ab1286aad65b0d13cb41571e902472396b8d43c
parentefa12efc37bebe169b17833bcbe5f817dd27ea43 (diff)
netlist: device factory enhancements. (nw)
Factory elements can now pass additional parameters to device constructors. This makes the design of interface objects like analog callbacks easier. The change also allowed to remove some "deep" calls into the core from the MAME interface in netlist.h
-rw-r--r--scripts/src/netlist.lua1
-rw-r--r--src/devices/machine/netlist.cpp214
-rw-r--r--src/devices/machine/netlist.h27
-rw-r--r--src/lib/netlist/nl_factory.h43
-rw-r--r--src/lib/netlist/nl_interface.h129
-rwxr-xr-xsrc/lib/netlist/nl_setup.cpp1
6 files changed, 252 insertions, 163 deletions
diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua
index 49d8371a1c4..b260e8e3dec 100644
--- a/scripts/src/netlist.lua
+++ b/scripts/src/netlist.lua
@@ -44,6 +44,7 @@ project "netlist"
MAME_DIR .. "src/lib/netlist/nl_dice_compat.h",
MAME_DIR .. "src/lib/netlist/nl_factory.cpp",
MAME_DIR .. "src/lib/netlist/nl_factory.h",
+ MAME_DIR .. "src/lib/netlist/nl_interface.h",
MAME_DIR .. "src/lib/netlist/nl_parser.cpp",
MAME_DIR .. "src/lib/netlist/nl_parser.h",
MAME_DIR .. "src/lib/netlist/nl_setup.cpp",
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index 26c1b16cf00..fdcd6db0753 100644
--- a/src/devices/machine/netlist.cpp
+++ b/src/devices/machine/netlist.cpp
@@ -15,6 +15,7 @@
#include "netlist/nl_setup.h"
#include "netlist/nl_factory.h"
#include "netlist/nl_parser.h"
+#include "netlist/nl_interface.h"
#include "netlist/devices/net_lib.h"
#include "netlist/devices/nlid_system.h"
@@ -187,114 +188,6 @@ private:
namespace {
-// ----------------------------------------------------------------------------------------
-// analog_callback
-// ----------------------------------------------------------------------------------------
-
-class NETLIB_NAME(analog_callback) : public netlist::device_t
-{
-public:
- NETLIB_NAME(analog_callback)(netlist::netlist_state_t &anetlist, const pstring &name)
- : device_t(anetlist, name)
- , m_in(*this, "IN")
- , m_cpu_device(nullptr)
- , m_last(*this, "m_last", 0)
- {
- auto *nl = dynamic_cast<netlist_mame_device::netlist_mame_t *>(&state());
- if (nl != nullptr)
- m_cpu_device = downcast<netlist_mame_cpu_device *>(&nl->parent());
- }
-
- void reset() override
- {
- m_last = 0.0;
- }
-
- void register_callback(netlist_mame_analog_output_device::output_delegate &&callback)
- {
- m_callback.reset(new netlist_mame_analog_output_device::output_delegate(std::move(callback)));
- }
-
- NETLIB_UPDATEI()
- {
- netlist::nl_fptype cur = m_in();
-
- // FIXME: make this a parameter
- // avoid calls due to noise
- if (plib::abs(cur - m_last) > 1e-6)
- {
- m_cpu_device->update_icount(exec().time());
- (*m_callback)(cur, m_cpu_device->local_time());
- m_cpu_device->check_mame_abort_slice();
- m_last = cur;
- }
- }
-
-private:
- netlist::analog_input_t m_in;
- std::unique_ptr<netlist_mame_analog_output_device::output_delegate> m_callback; // TODO: change to std::optional for C++17
- netlist_mame_cpu_device *m_cpu_device;
- netlist::state_var<netlist::nl_fptype> m_last;
-};
-
-// ----------------------------------------------------------------------------------------
-// logic_callback
-//
-// This device must be connected to a logic net. It has no power terminals
-// and conversion with proxies will not work.
-//
-// Background: This is inserted later into the driver and should not modify
-// the resulting analog representation of the netlist.
-//
-// ----------------------------------------------------------------------------------------
-
-class NETLIB_NAME(logic_callback) : public netlist::device_t
-{
-public:
- NETLIB_NAME(logic_callback)(netlist::netlist_state_t &anetlist, const pstring &name)
- : device_t(anetlist, name)
- , m_in(*this, "IN")
- , m_cpu_device(nullptr)
- , m_last(*this, "m_last", 0)
-// , m_supply(*this)
- {
- auto *nl = dynamic_cast<netlist_mame_device::netlist_mame_t *>(&state());
- if (nl != nullptr)
- m_cpu_device = downcast<netlist_mame_cpu_device *>(&nl->parent());
- }
-
- void reset() override
- {
- m_last = 0;
- }
-
- void register_callback(netlist_mame_logic_output_device::output_delegate &&callback)
- {
- m_callback.reset(new netlist_mame_logic_output_device::output_delegate(std::move(callback)));
- }
-
- NETLIB_UPDATEI()
- {
- netlist::netlist_sig_t cur = m_in();
-
- // FIXME: make this a parameter
- // avoid calls due to noise
- if (cur != m_last)
- {
- m_cpu_device->update_icount(exec().time());
- (*m_callback)(cur, m_cpu_device->local_time());
- m_cpu_device->check_mame_abort_slice();
- m_last = cur;
- }
- }
-
-private:
- netlist::logic_input_t m_in;
- std::unique_ptr<netlist_mame_logic_output_device::output_delegate> m_callback; // TODO: change to std::optional for C++17
- netlist_mame_cpu_device *m_cpu_device;
- netlist::state_var<netlist::netlist_sig_t> m_last;
- //netlist::devices::NETLIB_NAME(power_pins) m_supply;
-};
// ----------------------------------------------------------------------------------------
@@ -799,19 +692,38 @@ netlist_mame_analog_output_device::netlist_mame_analog_output_device(const machi
{
}
-void netlist_mame_analog_output_device::custom_netlist_additions(netlist::netlist_state_t &nlstate)
-{
- const pstring pin(m_in);
- pstring dname = pstring("OUT_") + pin;
+
+void netlist_mame_analog_output_device::custom_netlist_additions(netlist::nlparse_t &parser)
+{
/* ignore if no running machine -> called within device_validity_check context */
if (owner()->has_running_machine())
m_delegate.resolve();
- auto dev = nlstate.make_pool_object<NETLIB_NAME(analog_callback)>(nlstate, dname);
- dev->register_callback(std::move(m_delegate));
- nlstate.register_device(dname, std::move(dev));
- nlstate.parser().register_link(dname + ".IN", pin);
+ const pstring pin(m_in);
+ pstring dname = pstring("OUT_") + pin;
+
+ parser.register_dev(dname, dname);
+ parser.register_link(dname + ".IN", pin);
+}
+
+void netlist_mame_analog_output_device::pre_parse_action(netlist::nlparse_t &parser)
+{
+ const pstring pin(m_in);
+ pstring dname = pstring("OUT_") + pin;
+
+ const auto lambda = [this](auto &in, netlist::nl_fptype val)
+ {
+ this->cpu()->update_icount(in.exec().time());
+ this->m_delegate(val, this->cpu()->local_time());
+ this->cpu()->check_mame_abort_slice();
+ };
+
+ using lb_t = decltype(lambda);
+ using cb_t = netlist::interface::NETLIB_NAME(analog_callback)<lb_t>;
+
+ parser.factory().add<cb_t, netlist::nl_fptype, lb_t>(dname,
+ netlist::factory::properties("-", PSOURCELOC()), 1e-6, std::forward<lb_t>(lambda));
}
void netlist_mame_analog_output_device::device_start()
@@ -832,21 +744,39 @@ netlist_mame_logic_output_device::netlist_mame_logic_output_device(const machine
{
}
-void netlist_mame_logic_output_device::custom_netlist_additions(netlist::netlist_state_t &nlstate)
+void netlist_mame_logic_output_device::custom_netlist_additions(netlist::nlparse_t &parser)
{
- pstring pin(m_in);
- pstring dname = "OUT_" + pin;
-
/* ignore if no running machine -> called within device_validity_check context */
if (owner()->has_running_machine())
m_delegate.resolve();
- auto dev = nlstate.make_pool_object<NETLIB_NAME(logic_callback)>(nlstate, dname);
- dev->register_callback(std::move(m_delegate));
- nlstate.register_device(dname, std::move(dev));
- nlstate.parser().register_link(dname + ".IN", pin);
+ const pstring pin(m_in);
+ pstring dname = pstring("OUT_") + pin;
+
+ parser.register_dev(dname, dname);
+ parser.register_link(dname + ".IN", pin);
}
+void netlist_mame_logic_output_device::pre_parse_action(netlist::nlparse_t &parser)
+{
+ const pstring pin(m_in);
+ pstring dname = pstring("OUT_") + pin;
+
+ const auto lambda = [this](auto &in, netlist::netlist_sig_t val)
+ {
+ this->cpu()->update_icount(in.exec().time());
+ this->m_delegate(val, this->cpu()->local_time());
+ this->cpu()->check_mame_abort_slice();
+ };
+
+ using lb_t = decltype(lambda);
+ using cb_t = netlist::interface::NETLIB_NAME(logic_callback)<lb_t>;
+
+ parser.factory().add<cb_t, lb_t>(dname,
+ netlist::factory::properties("-", PSOURCELOC()), std::forward<lb_t>(lambda));
+}
+
+
void netlist_mame_logic_output_device::device_start()
{
LOGDEVCALLS("start\n");
@@ -1015,17 +945,17 @@ void netlist_mame_stream_input_device::device_start()
LOGDEVCALLS("start\n");
}
-void netlist_mame_stream_input_device::custom_netlist_additions(netlist::netlist_state_t &nlstate)
+void netlist_mame_stream_input_device::custom_netlist_additions(netlist::nlparse_t &parser)
{
- if (!nlstate.parser().device_exists("STREAM_INPUT"))
- nlstate.parser().register_dev("NETDEV_SOUND_IN", "STREAM_INPUT");
+ if (!parser.device_exists("STREAM_INPUT"))
+ parser.register_dev("NETDEV_SOUND_IN", "STREAM_INPUT");
pstring sparam = plib::pfmt("STREAM_INPUT.CHAN{1}")(m_channel);
- nlstate.parser().register_param(sparam, pstring(m_param_name));
+ parser.register_param(sparam, pstring(m_param_name));
sparam = plib::pfmt("STREAM_INPUT.MULT{1}")(m_channel);
- nlstate.parser().register_param_val(sparam, m_mult);
+ parser.register_param_val(sparam, m_mult);
sparam = plib::pfmt("STREAM_INPUT.OFFSET{1}")(m_channel);
- nlstate.parser().register_param_val(sparam, m_offset);
+ parser.register_param_val(sparam, m_offset);
}
// ----------------------------------------------------------------------------------------
@@ -1051,18 +981,18 @@ void netlist_mame_stream_output_device::device_start()
LOGDEVCALLS("start\n");
}
-void netlist_mame_stream_output_device::custom_netlist_additions(netlist::netlist_state_t &nlstate)
+void netlist_mame_stream_output_device::custom_netlist_additions(netlist::nlparse_t &parser)
{
//NETLIB_NAME(sound_out) *snd_out;
pstring sname = plib::pfmt("STREAM_OUT_{1}")(m_channel);
//snd_out = dynamic_cast<NETLIB_NAME(sound_out) *>(setup.register_dev("nld_sound_out", sname));
- nlstate.parser().register_dev("NETDEV_SOUND_OUT", sname);
+ parser.register_dev("NETDEV_SOUND_OUT", sname);
- nlstate.parser().register_param_val(sname + ".CHAN" , m_channel);
- nlstate.parser().register_param_val(sname + ".MULT", m_mult);
- nlstate.parser().register_param_val(sname + ".OFFSET", m_offset);
- nlstate.parser().register_link(sname + ".IN", pstring(m_out_name));
+ parser.register_param_val(sname + ".CHAN" , m_channel);
+ parser.register_param_val(sname + ".MULT", m_mult);
+ parser.register_param_val(sname + ".OFFSET", m_offset);
+ parser.register_link(sname + ".IN", pstring(m_out_name));
}
@@ -1127,20 +1057,20 @@ void netlist_mame_device::common_dev_start(netlist::netlist_state_t *lnetlist) c
}
}
- /* add default data provider for roms - if not in validity check*/
- //if (has_running_machine())
- lsetup.parser().register_source<netlist_data_memregions_t>(*this);
+ // add default data provider for roms - if not in validity check
+ lsetup.parser().register_source<netlist_data_memregions_t>(*this);
+ // Read the netlist
m_setup_func(lsetup.parser());
- /* let sub-devices tweak the netlist */
+ // let sub-devices tweak the netlist
for (device_t &d : subdevices())
{
netlist_mame_sub_interface *sdev = dynamic_cast<netlist_mame_sub_interface *>(&d);
if( sdev != nullptr )
{
LOGDEVCALLS("Found subdevice %s/%s\n", d.name(), d.shortname());
- sdev->custom_netlist_additions(*lnetlist);
+ sdev->custom_netlist_additions(lsetup.parser());
}
}
}
@@ -1402,8 +1332,6 @@ void netlist_mame_cpu_device::device_start()
void netlist_mame_cpu_device::nl_register_devices(netlist::nlparse_t &parser) const
{
- parser.factory().add<nld_analog_callback>( "NETDEV_CALLBACK",
- netlist::factory::properties("-", PSOURCELOC()));
}
uint64_t netlist_mame_cpu_device::execute_clocks_to_cycles(uint64_t clocks) const noexcept
diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h
index dfd67a88afe..062a61edffa 100644
--- a/src/devices/machine/netlist.h
+++ b/src/devices/machine/netlist.h
@@ -263,10 +263,11 @@ class netlist_mame_sub_interface
{
public:
// construction/destruction
- netlist_mame_sub_interface(device_t &aowner)
+ netlist_mame_sub_interface(device_t &owner)
: m_offset(0.0), m_mult(1.0)
- , m_owner(dynamic_cast<netlist_mame_device *>(&aowner))
- , m_sound(dynamic_cast<netlist_mame_sound_device *>(&aowner))
+ , m_owner(dynamic_cast<netlist_mame_device *>(&owner))
+ , m_sound(dynamic_cast<netlist_mame_sound_device *>(&owner))
+ , m_cpu(dynamic_cast<netlist_mame_cpu_device *>(&owner))
{
}
@@ -274,7 +275,7 @@ public:
{
}
- virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) { }
+ virtual void custom_netlist_additions(netlist::nlparse_t &parser) { }
virtual void pre_parse_action(netlist::nlparse_t &parser) { }
virtual void validity_helper(validity_checker &valid,
netlist::netlist_state_t &nlstate) const { }
@@ -292,13 +293,16 @@ public:
void set_mult_offset(const double mult, const double offset);
netlist_mame_sound_device *sound() { return m_sound;}
+ netlist_mame_cpu_device *cpu() { return m_cpu;}
+
protected:
double m_offset;
double m_mult;
private:
- netlist_mame_device *const m_owner;
+ netlist_mame_device *const m_owner;
netlist_mame_sound_device *const m_sound;
+ netlist_mame_cpu_device *const m_cpu;
};
// ----------------------------------------------------------------------------------------
@@ -357,7 +361,8 @@ public:
// construction/destruction
netlist_mame_analog_output_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- template <typename... T> void set_params(const char *in_name, T &&... args)
+ template <typename... T>
+ void set_params(const char *in_name, T &&... args)
{
m_in = in_name;
m_delegate.set(std::forward<T>(args)...);
@@ -367,7 +372,8 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
- virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) override;
+ virtual void pre_parse_action(netlist::nlparse_t &parser) override;
+ virtual void custom_netlist_additions(netlist::nlparse_t &parser) override;
private:
const char *m_in;
@@ -395,7 +401,8 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
- virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) override;
+ virtual void pre_parse_action(netlist::nlparse_t &parser) override;
+ virtual void custom_netlist_additions(netlist::nlparse_t &parser) override;
private:
const char *m_in;
@@ -531,7 +538,7 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
- virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) override;
+ virtual void custom_netlist_additions(netlist::nlparse_t &parser) override;
private:
uint32_t m_channel;
const char *m_param_name;
@@ -557,7 +564,7 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
- virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) override;
+ virtual void custom_netlist_additions(netlist::nlparse_t &parser) override;
private:
uint32_t m_channel;
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index 15b15470180..de5265bee69 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -14,6 +14,8 @@
#include "plib/putil.h"
#include <vector>
+#include <tuple>
+#include <utility>
#define NETLIB_DEVICE_IMPL_ALIAS(p_alias, chip, p_name, p_def_param) \
NETLIB_DEVICE_IMPL_BASE(devices, p_alias, chip, p_name, p_def_param) \
@@ -112,25 +114,47 @@ namespace factory {
properties m_properties; ///< source file and other information and settings
};
- template <class C>
+ template <class C, typename... Args>
class device_element_t : public element_t
{
public:
- device_element_t(const pstring &name, properties &&props)
- : element_t(name, std::move(props)) { }
+ device_element_t(const pstring &name, properties &&props, Args&&... args)
+ : element_t(name, std::move(props))
+ , m_args(std::forward<Args>(args)...)
+ { }
+
+
+ template <std::size_t... Is>
+ dev_uptr make_device(nlmempool &pool,
+ netlist_state_t &anetlist,
+ const pstring &name, std::tuple<Args...>& args, std::index_sequence<Is...>)
+ {
+ return pool.make_unique<C>(anetlist, name, std::forward<Args>(std::get<Is>(args))...);
+ }
+
+ dev_uptr make_device(nlmempool &pool,
+ netlist_state_t &anetlist,
+ const pstring &name, std::tuple<Args...>& args)
+ {
+ return make_device(pool, anetlist, name, args, std::index_sequence_for<Args...>{});
+ }
dev_uptr make_device(nlmempool &pool,
netlist_state_t &anetlist,
const pstring &name) override
{
- return pool.make_unique<C>(anetlist, name);
+ return make_device(pool, anetlist, name, m_args);
+ //return pool.make_unique<C>(anetlist, name);
}
- static uptr create(const pstring &name, properties &&props)
+ static uptr create(const pstring &name, properties &&props, Args&&... args)
{
- return plib::make_unique<device_element_t<C>>(name, std::move(props));
+ return plib::make_unique<device_element_t<C, Args...>>(name,
+ std::move(props), std::forward<Args>(args)...);
}
+ private:
+ std::tuple<Args...> m_args;
};
class list_t : public std::vector<element_t::uptr>
@@ -141,10 +165,11 @@ namespace factory {
PCOPYASSIGNMOVE(list_t, delete)
- template<class device_class>
- void add(const pstring &name, properties &&props)
+ template<class device_class, typename... Args>
+ void add(const pstring &name, properties &&props, Args&&... args)
{
- add(device_element_t<device_class>::create(name, std::move(props)));
+ add(device_element_t<device_class, Args...>::create(name, std::move(props),
+ std::forward<Args>(args)...));
}
void add(element_t::uptr &&factory) noexcept(false);
diff --git a/src/lib/netlist/nl_interface.h b/src/lib/netlist/nl_interface.h
new file mode 100644
index 00000000000..55c8185aa5b
--- /dev/null
+++ b/src/lib/netlist/nl_interface.h
@@ -0,0 +1,129 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+///
+/// \file nl_interface.h
+///
+/// This header contains objects for interfacing with the netlist core.
+///
+
+#ifndef NLINTERFACE_H_
+#define NLINTERFACE_H_
+
+#include "nl_base.h"
+
+#include <initializer_list>
+#include <memory>
+#include <stack>
+#include <unordered_map>
+#include <vector>
+
+namespace netlist
+{
+
+ namespace interface
+ {
+ /// \brief analog_callback device
+ ///
+ /// This device is used to call back into the application which
+ /// is controlling the execution of the netlist.
+ ///
+ /// The device will call the provided lambda with a reference to
+ /// itself and the current value of the net it is connected to.
+ ///
+ /// The following code is an example on how to add the device to
+ /// the netlist factory.
+ ///
+ /// const pstring pin(m_in);
+ /// pstring dname = pstring("OUT_") + pin;
+ ///
+ /// const auto lambda = [this](auto &in, netlist::nl_fptype val)
+ /// {
+ /// this->cpu()->update_icount(in.exec().time());
+ /// this->m_delegate(val, this->cpu()->local_time());
+ /// this->cpu()->check_mame_abort_slice();
+ /// };
+ ///
+ /// using lb_t = decltype(lambda);
+ /// using cb_t = netlist::interface::NETLIB_NAME(analog_callback)<lb_t>;
+ ///
+ /// parser.factory().add<cb_t, netlist::nl_fptype, lb_t>(dname,
+ /// netlist::factory::properties("-", PSOURCELOC()), 1e-6, std::forward<lb_t>(lambda));
+ ///
+
+ template <typename FUNC>
+ class NETLIB_NAME(analog_callback) : public device_t
+ {
+ public:
+ NETLIB_NAME(analog_callback)(netlist_state_t &anetlist,
+ const pstring &name, nl_fptype threshold, FUNC &&func)
+ : device_t(anetlist, name)
+ , m_in(*this, "IN")
+ , m_threshold(threshold)
+ , m_last(*this, "m_last", 0)
+ , m_func(func)
+ {
+ }
+
+ NETLIB_RESETI()
+ {
+ m_last = 0.0;
+ }
+
+ NETLIB_UPDATEI()
+ {
+ const nl_fptype cur = m_in();
+ if (plib::abs(cur - m_last) > m_threshold)
+ {
+ m_last = cur;
+ m_func(*this, cur);
+ }
+ }
+
+ private:
+ analog_input_t m_in;
+ nl_fptype m_threshold;
+ state_var<nl_fptype> m_last;
+ FUNC m_func;
+ };
+
+
+ /// \brief logic_callback device
+ ///
+ /// This device must be connected to a logic net. It has no power terminals
+ /// and conversion with proxies will not work.
+ ///
+ /// Background: This device may be inserted later into the driver and should
+ /// not modify the resulting analog representation of the netlist.
+ ///
+ /// If you get error messages on missing power terminals you have to use the
+ /// analog callback device instead.
+
+ template <typename FUNC>
+ class NETLIB_NAME(logic_callback) : public device_t
+ {
+ public:
+ NETLIB_NAME(logic_callback)(netlist_state_t &anetlist, const pstring &name, FUNC &&func)
+ : device_t(anetlist, name)
+ , m_in(*this, "IN")
+ , m_func(func)
+ {
+ }
+
+ NETLIB_UPDATEI()
+ {
+ const netlist_sig_t cur = m_in();
+ m_func(*this, cur);
+ }
+
+ private:
+ logic_input_t m_in;
+ FUNC m_func;
+ };
+
+ } // namespace interface
+
+} // namespace netlist
+
+
+#endif // NLINTERFACE_H_
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 9b0bc5f4340..8e535a45a83 100755
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -81,7 +81,6 @@ namespace netlist
include(f->name());
namespace_pop();
}
- //f->macro_actions(*this, name);
pstring key = build_fqn(name);
if (device_exists(key))