diff options
-rw-r--r-- | scripts/src/netlist.lua | 1 | ||||
-rw-r--r-- | src/devices/machine/netlist.cpp | 214 | ||||
-rw-r--r-- | src/devices/machine/netlist.h | 27 | ||||
-rw-r--r-- | src/lib/netlist/nl_factory.h | 43 | ||||
-rw-r--r-- | src/lib/netlist/nl_interface.h | 129 | ||||
-rwxr-xr-x | src/lib/netlist/nl_setup.cpp | 1 |
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)) |