diff options
Diffstat (limited to 'src/devices/machine/netlist.cpp')
-rw-r--r-- | src/devices/machine/netlist.cpp | 199 |
1 files changed, 110 insertions, 89 deletions
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index 6d2225fe9fc..799dbe7d640 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -36,8 +36,6 @@ #define MOVE_UNIQUE_PTR(x) (x) #endif - - DEFINE_DEVICE_TYPE(NETLIST_CORE, netlist_mame_device, "netlist_core", "Netlist Core Device") DEFINE_DEVICE_TYPE(NETLIST_CPU, netlist_mame_cpu_device, "netlist_cpu", "Netlist CPU Device") DEFINE_DEVICE_TYPE(NETLIST_SOUND, netlist_mame_sound_device, "netlist_sound", "Netlist Sound Device") @@ -182,12 +180,12 @@ public: m_cpu_device = downcast<netlist_mame_cpu_device *>(&nl->parent()); } - ATTR_COLD void reset() override + void reset() override { m_last = 0.0; } - ATTR_COLD void register_callback(netlist_mame_analog_output_device::output_delegate &&callback) + 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))); } @@ -240,12 +238,12 @@ public: m_cpu_device = downcast<netlist_mame_cpu_device *>(&nl->parent()); } - ATTR_COLD void reset() override + void reset() override { m_last = 0; } - ATTR_COLD void register_callback(netlist_mame_logic_output_device::output_delegate &&callback) + 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))); } @@ -418,42 +416,21 @@ public: , m_offset(*this, "OFFSET", 0.0) , m_buffer(nullptr) , m_bufsize(0) - , m_sample_time(netlist::netlist_time::from_hz(1)) //sufficiently big enough + , m_sample_time(netlist::netlist_time::from_hz(1)) , m_in(*this, "IN") , m_cur(0.0) , m_last_pos(0) - , m_last_buffer_time(*this, "m_last_buffer", netlist::netlist_time::zero()) + , m_last_buffer_time(*this, "m_last_buffer", netlist::netlist_time_ext::zero()) { } - //static const int BUFSIZE = 2048; +protected: - ATTR_COLD void reset() override + void reset() override { m_cur = 0.0; m_last_pos = 0; - m_last_buffer_time = netlist::netlist_time::zero(); - } - - ATTR_HOT void sound_update(const netlist::netlist_time &upto) - { - int pos = (upto - m_last_buffer_time) / m_sample_time; - if (pos > m_bufsize) - throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), pos, m_bufsize); - while (m_last_pos < pos ) - { - m_buffer[m_last_pos++] = (stream_sample_t) m_cur; - } - } - - ATTR_HOT void sound_update_fill(int samples) - { - if (samples > m_bufsize) - throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), samples, m_bufsize); - while (m_last_pos < samples ) - { - m_buffer[m_last_pos++] = (stream_sample_t) m_cur; - } + m_last_buffer_time = netlist::netlist_time_ext::zero(); } NETLIB_UPDATEI() @@ -471,12 +448,34 @@ public: } public: - ATTR_HOT void buffer_reset(const netlist::netlist_time &upto) + void buffer_reset(const netlist::netlist_time_ext &upto) { m_last_pos = 0; m_last_buffer_time = upto; } + void sound_update(const netlist::netlist_time_ext &upto) + { + int pos = (upto - m_last_buffer_time()) / m_sample_time; + if (pos > m_bufsize) + throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), pos, m_bufsize); + while (m_last_pos < pos ) + { + m_buffer[m_last_pos++] = (stream_sample_t) m_cur; + } + } + + void sound_update_fill(int samples) + { + if (samples > m_bufsize) + throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), samples, m_bufsize); + while (m_last_pos < samples ) + { + m_buffer[m_last_pos++] = (stream_sample_t) m_cur; + } + } + + netlist::param_int_t m_channel; netlist::param_fp_t m_mult; netlist::param_fp_t m_offset; @@ -489,7 +488,7 @@ private: netlist::analog_input_t m_in; double m_cur; int m_last_pos; - netlist::state_var<netlist::netlist_time> m_last_buffer_time; + netlist::state_var<netlist::netlist_time_ext> m_last_buffer_time; }; // ---------------------------------------------------------------------------------------- @@ -504,10 +503,11 @@ public: NETLIB_NAME(sound_in)(netlist::netlist_state_t &anetlist, const pstring &name) : netlist::device_t(anetlist, name) - , m_inc(netlist::netlist_time::from_nsec(1)) + , m_sample_time(netlist::netlist_time::from_nsec(1)) , m_feedback(*this, "FB") // clock part , m_Q(*this, "Q") , m_pos(0) + , m_samples(0) , m_num_channels(0) { connect(m_feedback, m_Q); @@ -520,16 +520,44 @@ public: } } - ATTR_COLD void reset() override +protected: + void reset() override { m_pos = 0; for (auto & elem : m_channels) elem.m_buffer = nullptr; } - ATTR_COLD void resolve() + NETLIB_UPDATEI() + { + if (m_pos < m_samples) + { + for (int i=0; i<m_num_channels; i++) + { + if (m_channels[i].m_buffer == nullptr) + break; // stop, called outside of stream_update + const nl_fptype v = m_channels[i].m_buffer[m_pos]; + m_channels[i].m_param->setTo(v * (*m_channels[i].m_param_mult)() + (*m_channels[i].m_param_offset)()); + } + } + else + { + // FIXME: The logic has a rounding issue because time resolution divided + // by 48,000 is not a natural number. The fractional part + // adds up to one samples every 13 seconds for 100 ps resolution. + // Fixing this is possible but complicated and expensive. + } + m_pos++; + + m_Q.net().toggle_and_push_to_queue(m_sample_time); + } + +public: + void resolve(netlist::netlist_time sample_time) { m_pos = 0; + m_sample_time = sample_time; + for (int i = 0; i < MAX_INPUT_CHANNELS; i++) { if ((*m_channels[i].m_param_name)() != pstring("")) @@ -542,23 +570,17 @@ public: } } - NETLIB_UPDATEI() + template <typename S> + void buffer_reset(netlist::netlist_time sample_time, int num_samples, S **inputs) { - for (int i=0; i<m_num_channels; i++) - { - if (m_channels[i].m_buffer == nullptr) - break; // stop, called outside of stream_update - const nl_fptype v = m_channels[i].m_buffer[m_pos]; - m_channels[i].m_param->setTo(v * (*m_channels[i].m_param_mult)() + (*m_channels[i].m_param_offset)()); - } - m_pos++; - m_Q.net().toggle_and_push_to_queue(m_inc); - } + m_samples = num_samples; + m_sample_time = sample_time; -public: - ATTR_HOT void buffer_reset() - { m_pos = 0; + for (int i=0; i < m_num_channels; i++) + { + m_channels[i].m_buffer = inputs[i]; + } } struct channel @@ -569,16 +591,18 @@ public: netlist::unique_pool_ptr<netlist::param_fp_t> m_param_mult; netlist::unique_pool_ptr<netlist::param_fp_t> m_param_offset; }; - channel m_channels[MAX_INPUT_CHANNELS]; - netlist::netlist_time m_inc; int num_channels() { return m_num_channels; } private: + channel m_channels[MAX_INPUT_CHANNELS]; + netlist::netlist_time m_sample_time; + netlist::logic_input_t m_feedback; netlist::logic_output_t m_Q; int m_pos; + int m_samples; int m_num_channels; }; @@ -967,9 +991,9 @@ void netlist_mame_stream_input_device::custom_netlist_additions(netlist::netlist pstring sparam = plib::pfmt("STREAM_INPUT.CHAN{1}")(m_channel); nlstate.setup().register_param(sparam, pstring(m_param_name)); sparam = plib::pfmt("STREAM_INPUT.MULT{1}")(m_channel); - nlstate.setup().register_param(sparam, m_mult); + nlstate.setup().register_param_val(sparam, m_mult); sparam = plib::pfmt("STREAM_INPUT.OFFSET{1}")(m_channel); - nlstate.setup().register_param(sparam, m_offset); + nlstate.setup().register_param_val(sparam, m_offset); } // ---------------------------------------------------------------------------------------- @@ -1003,9 +1027,9 @@ void netlist_mame_stream_output_device::custom_netlist_additions(netlist::netlis //snd_out = dynamic_cast<NETLIB_NAME(sound_out) *>(setup.register_dev("nld_sound_out", sname)); nlstate.setup().register_dev("NETDEV_SOUND_OUT", sname); - nlstate.setup().register_param(sname + ".CHAN" , m_channel); - nlstate.setup().register_param(sname + ".MULT", m_mult); - nlstate.setup().register_param(sname + ".OFFSET", m_offset); + nlstate.setup().register_param_val(sname + ".CHAN" , m_channel); + nlstate.setup().register_param_val(sname + ".MULT", m_mult); + nlstate.setup().register_param_val(sname + ".OFFSET", m_offset); nlstate.setup().register_link(sname + ".IN", pstring(m_out_name)); } @@ -1022,7 +1046,7 @@ netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const ch netlist_mame_device::netlist_mame_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) , m_icount(0) - , m_old(netlist::netlist_time::zero()) + , m_old(netlist::netlist_time_ext::zero()) , m_setup_func(nullptr) { } @@ -1155,15 +1179,17 @@ void netlist_mame_device::device_start() save_state(); - m_old = netlist::netlist_time::zero(); - m_rem = netlist::netlist_time::zero(); + m_old = netlist::netlist_time_ext::zero(); + m_rem = netlist::netlist_time_ext::zero(); LOGDEVCALLS("device_start exit\n"); } void netlist_mame_device::device_clock_changed() { - m_div = netlist::netlist_time::from_hz(clock()); + m_div = static_cast<netlist::netlist_time_ext>( + (netlist::netlist_time_ext::resolution() << MDIV_SHIFT) / clock()); + //printf("m_div %d\n", (int) m_div.as_raw()); netlist().log().debug("Setting clock {1} and divisor {2}\n", clock(), m_div.as_double()); } @@ -1171,8 +1197,8 @@ void netlist_mame_device::device_clock_changed() void netlist_mame_device::device_reset() { LOGDEVCALLS("device_reset\n"); - m_old = netlist::netlist_time::zero(); - m_rem = netlist::netlist_time::zero(); + m_old = netlist::netlist_time_ext::zero(); + m_rem = netlist::netlist_time_ext::zero(); netlist().exec().reset(); } @@ -1182,7 +1208,7 @@ void netlist_mame_device::device_stop() netlist().exec().stop(); } -ATTR_COLD void netlist_mame_device::device_post_load() +void netlist_mame_device::device_post_load() { LOGDEVCALLS("device_post_load\n"); @@ -1190,20 +1216,20 @@ ATTR_COLD void netlist_mame_device::device_post_load() netlist().rebuild_lists(); } -ATTR_COLD void netlist_mame_device::device_pre_save() +void netlist_mame_device::device_pre_save() { LOGDEVCALLS("device_pre_save\n"); netlist().run_state_manager().pre_save(); } -void netlist_mame_device::update_icount(netlist::netlist_time time) noexcept +void netlist_mame_device::update_icount(netlist::netlist_time_ext time) noexcept { - const netlist::netlist_time newt(time); - const netlist::netlist_time delta(newt - m_old + m_rem); + const netlist::netlist_time_ext delta = (time - m_old).shl(MDIV_SHIFT) + m_rem; const uint64_t d = delta / m_div; - m_old = newt; - m_rem = delta - (m_div * d); + m_old = time; + m_rem = (delta - (m_div * d)); + //printf("d %d m_rem %d\n", (int) d, (int) m_rem.as_raw()); m_icount -= d; } @@ -1213,7 +1239,7 @@ void netlist_mame_device::check_mame_abort_slice() noexcept netlist().exec().abort_current_queue_slice(); } -ATTR_COLD void netlist_mame_device::save_state() +void netlist_mame_device::save_state() { for (auto const & s : netlist().run_state_manager().save_list()) { @@ -1301,17 +1327,17 @@ void netlist_mame_cpu_device::nl_register_devices(netlist::setup_t &lsetup) cons lsetup.factory().register_device<nld_analog_callback>( "NETDEV_CALLBACK", "nld_analog_callback", "-"); } -ATTR_COLD uint64_t netlist_mame_cpu_device::execute_clocks_to_cycles(uint64_t clocks) const noexcept +uint64_t netlist_mame_cpu_device::execute_clocks_to_cycles(uint64_t clocks) const noexcept { return clocks; } -ATTR_COLD uint64_t netlist_mame_cpu_device::execute_cycles_to_clocks(uint64_t cycles) const noexcept +uint64_t netlist_mame_cpu_device::execute_cycles_to_clocks(uint64_t cycles) const noexcept { return cycles; } -ATTR_HOT void netlist_mame_cpu_device::execute_run() +void netlist_mame_cpu_device::execute_run() { //m_ppc = m_pc; // copy PC to previous PC if (debugger_enabled()) @@ -1321,13 +1347,13 @@ ATTR_HOT void netlist_mame_cpu_device::execute_run() m_genPC++; m_genPC &= 255; debugger_instruction_hook(m_genPC); - netlist().exec().process_queue(m_div); + netlist().exec().process_queue(nltime_ext_from_clocks(1)); update_icount(netlist().exec().time()); } } else { - netlist().exec().process_queue(m_div * m_icount); + netlist().exec().process_queue(nltime_ext_from_clocks(m_icount)); update_icount(netlist().exec().time()); } } @@ -1441,8 +1467,7 @@ void netlist_mame_sound_device::device_start() if (indevs.size() == 1) { m_in = indevs[0]; - m_in->resolve(); - m_in->m_inc = netlist::netlist_time::from_hz(clock()); + m_in->resolve(nltime_from_clocks(1)); } /* initialize the stream(s) */ @@ -1463,23 +1488,19 @@ void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream { e.second->m_buffer = outputs[e.first]; e.second->m_bufsize = samples; + e.second->m_sample_time = nltime_from_clocks(1); } - if (m_in) { - m_in->buffer_reset(); - for (int i=0; i < m_in->num_channels(); i++) - { - m_in->m_channels[i].m_buffer = inputs[i]; - } + m_in->buffer_reset(nltime_from_clocks(1), samples, inputs); } - netlist::netlist_time cur(netlist().exec().time()); - - netlist().exec().process_queue(m_div * samples); + auto cur(netlist().exec().time()); + const auto delta(nltime_ext_from_clocks(samples)); + netlist().exec().process_queue(delta); - cur += (m_div * samples); + cur += delta; for (auto &e : m_out) { |