netlist: untangle sound and cpu devices.

* member variables are now where they belong.
* Avoid over/underclocking of netlist sound devices.
This commit is contained in:
couriersud 2020-08-14 22:05:30 +02:00
parent 51503ac1c9
commit c721e728f4
2 changed files with 92 additions and 90 deletions

View File

@ -35,12 +35,15 @@
#define LOG_GENERAL (1U << 0) #define LOG_GENERAL (1U << 0)
#define LOG_DEV_CALLS (1U << 1) #define LOG_DEV_CALLS (1U << 1)
#define LOG_DEBUG (1U << 2) #define LOG_DEBUG (1U << 2)
#define LOG_TIMING (1U << 3)
//#define LOG_MASK (LOG_GENERAL | LOG_DEV_CALLS | LOG_DEBUG) //#define LOG_MASK (LOG_GENERAL | LOG_DEV_CALLS | LOG_DEBUG)
//#define LOG_MASK (LOG_TIMING)
#define LOG_MASK (0) #define LOG_MASK (0)
#define LOGDEVCALLS(...) LOGMASKED(LOG_DEV_CALLS, __VA_ARGS__) #define LOGDEVCALLS(...) LOGMASKED(LOG_DEV_CALLS, __VA_ARGS__)
#define LOGDEBUG(...) LOGMASKED(LOG_DEBUG, __VA_ARGS__) #define LOGDEBUG(...) LOGMASKED(LOG_DEBUG, __VA_ARGS__)
#define LOGTIMING(...) LOGMASKED(LOG_TIMING, __VA_ARGS__)
#define LOG_OUTPUT_FUNC printf #define LOG_OUTPUT_FUNC printf
@ -904,10 +907,6 @@ 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) 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) : device_t(mconfig, type, tag, owner, clock)
, m_icount(0)
, m_cur_time(attotime::zero)
, m_attotime_per_clock(attotime::zero)
, m_old(netlist::netlist_time_ext::zero())
, m_setup_func(nullptr) , m_setup_func(nullptr)
, m_device_reset_called(false) , m_device_reset_called(false)
{ {
@ -1025,15 +1024,8 @@ void netlist_mame_device::device_validity_check(validity_checker &valid) const
} }
void netlist_mame_device::device_start() void netlist_mame_device::device_start_common()
{ {
LOGDEVCALLS("device_start entry\n");
m_attotime_per_clock = attotime(0, m_attoseconds_per_clock);
//netlist().save(*this, m_cur_time, pstring(this->name()), "m_cur_time");
save_item(NAME(m_cur_time));
save_item(NAME(m_attotime_per_clock));
m_netlist = std::make_unique<netlist_mame_t>(*this, "netlist"); m_netlist = std::make_unique<netlist_mame_t>(*this, "netlist");
if (!machine().options().verbose()) if (!machine().options().verbose())
{ {
@ -1044,29 +1036,19 @@ void netlist_mame_device::device_start()
common_dev_start(m_netlist.get()); common_dev_start(m_netlist.get());
m_netlist->setup().prepare_to_run(); m_netlist->setup().prepare_to_run();
// FIXME: use save_helper
m_netlist->save(*this, m_rem, pstring(this->name()), "m_rem");
m_netlist->save(*this, m_div, pstring(this->name()), "m_div");
m_netlist->save(*this, m_old, pstring(this->name()), "m_old");
save_state();
m_old = netlist::netlist_time_ext::zero();
m_rem = netlist::netlist_time_ext::zero();
m_cur_time = attotime::zero;
m_device_reset_called = false; m_device_reset_called = false;
LOGDEVCALLS("device_start exit\n");
} }
void netlist_mame_device::device_clock_changed()
void netlist_mame_device::device_start()
{ {
m_div = static_cast<netlist::netlist_time_ext>( LOGDEVCALLS("device_start entry\n");
(netlist::netlist_time_ext::resolution() << MDIV_SHIFT) / clock());
//printf("m_div %d\n", (int) m_div.as_raw()); device_start_common();
netlist().log().debug("Setting clock {1} and divisor {2}\n", clock(), m_div.as_double()); save_state();
m_attotime_per_clock = attotime(0, m_attoseconds_per_clock);
LOGDEVCALLS("device_start exit\n");
} }
@ -1108,7 +1090,7 @@ void netlist_mame_device::device_pre_save()
netlist().run_state_manager().pre_save(); netlist().run_state_manager().pre_save();
} }
void netlist_mame_device::update_icount(netlist::netlist_time_ext time) noexcept void netlist_mame_cpu_device::update_icount(netlist::netlist_time_ext time) noexcept
{ {
const netlist::netlist_time_ext delta = (time - m_old).shl(MDIV_SHIFT) + m_rem; const netlist::netlist_time_ext delta = (time - m_old).shl(MDIV_SHIFT) + m_rem;
const uint64_t d = delta / m_div; const uint64_t d = delta / m_div;
@ -1118,7 +1100,7 @@ void netlist_mame_device::update_icount(netlist::netlist_time_ext time) noexcept
m_icount -= d; m_icount -= d;
} }
void netlist_mame_device::check_mame_abort_slice() noexcept void netlist_mame_cpu_device::check_mame_abort_slice() noexcept
{ {
if (m_icount <= 0) if (m_icount <= 0)
netlist().exec().abort_current_queue_slice(); netlist().exec().abort_current_queue_slice();
@ -1173,6 +1155,8 @@ netlist_mame_cpu_device::netlist_mame_cpu_device(const machine_config &mconfig,
, device_disasm_interface(mconfig, *this) , device_disasm_interface(mconfig, *this)
, device_memory_interface(mconfig, *this) , device_memory_interface(mconfig, *this)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 12) // Interface is needed to keep debugger happy , m_program_config("program", ENDIANNESS_LITTLE, 8, 12) // Interface is needed to keep debugger happy
, m_icount(0)
, m_old(netlist::netlist_time_ext::zero())
, m_genPC(0) , m_genPC(0)
{ {
} }
@ -1209,9 +1193,18 @@ private:
void netlist_mame_cpu_device::device_start() void netlist_mame_cpu_device::device_start()
{ {
netlist_mame_device::device_start(); LOGDEVCALLS("device_start entry\n");
// State support device_start_common();
// FIXME: use save_helper
netlist().save(*this, m_rem, pstring(this->name()), "m_rem");
netlist().save(*this, m_div, pstring(this->name()), "m_div");
netlist().save(*this, m_old, pstring(this->name()), "m_old");
m_old = netlist::netlist_time_ext::zero();
m_rem = netlist::netlist_time_ext::zero();
save_state();
state_add(STATE_GENPC, "GENPC", m_genPC).noshow(); state_add(STATE_GENPC, "GENPC", m_genPC).noshow();
state_add(STATE_GENPCBASE, "CURPC", m_genPC).noshow(); state_add(STATE_GENPCBASE, "CURPC", m_genPC).noshow();
@ -1241,8 +1234,17 @@ void netlist_mame_cpu_device::device_start()
// set our instruction counter // set our instruction counter
set_icountptr(m_icount); set_icountptr(m_icount);
LOGDEVCALLS("device_start exit\n");
} }
void netlist_mame_cpu_device::device_clock_changed()
{
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());
}
void netlist_mame_cpu_device::nl_register_devices(netlist::nlparse_t &parser) const void netlist_mame_cpu_device::nl_register_devices(netlist::nlparse_t &parser) const
{ {
@ -1313,11 +1315,15 @@ offs_t netlist_disassembler::disassemble(std::ostream &stream, offs_t pc, const
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
netlist_mame_sound_device::netlist_mame_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) netlist_mame_sound_device::netlist_mame_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: netlist_mame_device(mconfig, NETLIST_SOUND, tag, owner, clock) : netlist_mame_device(mconfig, NETLIST_SOUND, tag, owner, 0)
, device_sound_interface(mconfig, *this) , device_sound_interface(mconfig, *this)
, m_in(nullptr) , m_in(nullptr)
, m_stream(nullptr) , m_stream(nullptr)
, m_cur_time(attotime::zero)
, m_sound_clock(clock)
, m_attotime_per_clock(attotime::zero)
, m_is_device_call(false) , m_is_device_call(false)
, m_last_update_to_current_time(attotime::zero)
{ {
} }
@ -1353,23 +1359,29 @@ void netlist_mame_sound_device::device_reset()
void netlist_mame_sound_device::device_start() void netlist_mame_sound_device::device_start()
{ {
netlist_mame_device::device_start();
LOGDEVCALLS("sound device_start\n"); LOGDEVCALLS("sound device_start\n");
m_attotime_per_clock = attotime::from_hz(m_sound_clock);
save_item(NAME(m_cur_time));
save_item(NAME(m_attotime_per_clock));
device_start_common();
save_state();
m_cur_time = attotime::zero;
// Configure outputs // Configure outputs
if (m_out.size() == 0) if (m_out.size() == 0)
fatalerror("No output devices"); fatalerror("No output devices");
//m_num_outputs = outdevs.size();
/* resort channels */ /* resort channels */
for (auto &outdev : m_out) for (auto &outdev : m_out)
{ {
if (outdev.first < 0 || outdev.first >= m_out.size()) if (outdev.first < 0 || outdev.first >= m_out.size())
fatalerror("illegal channel number %d", outdev.first); fatalerror("illegal channel number %d", outdev.first);
outdev.second->set_sample_time(netlist::netlist_time::from_hz(clock())); outdev.second->set_sample_time(netlist::netlist_time::from_hz(m_sound_clock));
outdev.second->buffer_reset(netlist::netlist_time_ext::zero()); outdev.second->buffer_reset(netlist::netlist_time_ext::zero());
} }
@ -1385,13 +1397,15 @@ void netlist_mame_sound_device::device_start()
if (indevs.size() == 1) if (indevs.size() == 1)
{ {
m_in = indevs[0]; m_in = indevs[0];
const auto sample_time = netlist::netlist_time::from_raw(static_cast<netlist::netlist_time::internal_type>(nltime_from_attotime(clocks_to_attotime(1)).as_raw())); const auto sample_time = netlist::netlist_time::from_raw(static_cast<netlist::netlist_time::internal_type>(nltime_from_attotime(m_attotime_per_clock).as_raw()));
m_in->resolve_params(sample_time); m_in->resolve_params(sample_time);
} }
/* initialize the stream(s) */ /* initialize the stream(s) */
m_is_device_call = false; m_is_device_call = false;
m_stream = machine().sound().stream_alloc(*this, m_in ? m_in->num_channels() : 0, m_out.size(), clock()); m_stream = machine().sound().stream_alloc(*this, m_in ? m_in->num_channels() : 0, m_out.size(), m_sound_clock);
LOGDEVCALLS("sound device_start exit\n");
} }
@ -1408,18 +1422,6 @@ void netlist_mame_sound_device::register_stream_output(int channel, netlist_mame
m_out[channel] = so; m_out[channel] = so;
} }
void netlist_mame_sound_device::device_clock_changed()
{
netlist_mame_device::device_clock_changed();
for (auto &e : m_out)
{
e.second->set_sample_time(nltime_from_clocks(1));
}
}
static attotime last;
void netlist_mame_sound_device::update_to_current_time() void netlist_mame_sound_device::update_to_current_time()
{ {
LOGDEBUG("before update\n"); LOGDEBUG("before update\n");
@ -1427,29 +1429,28 @@ void netlist_mame_sound_device::update_to_current_time()
get_stream()->update(); get_stream()->update();
m_is_device_call = false; m_is_device_call = false;
if (machine().time() < last) if (machine().time() < m_last_update_to_current_time)
LOGDEBUG("machine.time() decreased 2\n"); LOGTIMING("machine.time() decreased 2\n");
last = machine().time(); m_last_update_to_current_time = machine().time();
const auto mtime = nltime_from_attotime(machine().time()); const auto mtime = nltime_from_attotime(machine().time());
const auto cur(netlist().exec().time()); const auto cur(netlist().exec().time());
if (mtime > cur) if (mtime > cur)
{ {
if ((mtime - cur) >= nltime_from_clocks(1)) LOGTIMING("%f us\n", (mtime - cur).as_double() * 1000000.0);
LOGDEBUG("%f us\n", (mtime - cur).as_double() * 1000000.0);
netlist().exec().process_queue(mtime - cur); netlist().exec().process_queue(mtime - cur);
} }
else if (mtime < cur) else if (mtime < cur)
LOGDEBUG("%s : %f ns before machine time\n", this->name(), (cur - mtime).as_double() * 1000000000.0); LOGTIMING("%s : %f us before machine time\n", this->name(), (cur - mtime).as_double() * 1000000.0);
} }
void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{ {
if (machine().time() < last) if (machine().time() < m_last_update_to_current_time)
LOGDEBUG("machine.time() decreased 1\n"); LOGTIMING("machine.time() decreased 1\n");
last = machine().time(); m_last_update_to_current_time = machine().time();
LOGDEBUG("samples %d %d\n", (int) m_is_device_call, samples); LOGDEBUG("samples %d %d\n", (int) m_is_device_call, samples);
if (m_in) if (m_in)

View File

@ -75,25 +75,8 @@ public:
netlist::setup_t &setup(); netlist::setup_t &setup();
netlist_mame_t &netlist() noexcept { return *m_netlist; } netlist_mame_t &netlist() noexcept { return *m_netlist; }
void update_icount(netlist::netlist_time_ext time) noexcept;
void check_mame_abort_slice() noexcept;
static void register_memregion_source(netlist::nlparse_t &parser, device_t &dev, const char *name); static void register_memregion_source(netlist::nlparse_t &parser, device_t &dev, const char *name);
int m_icount;
static constexpr const unsigned MDIV_SHIFT = 16;
netlist::netlist_time_ext nltime_ext_from_clocks(unsigned c) const noexcept
{
return (m_div * c).shr(MDIV_SHIFT);
}
netlist::netlist_time nltime_from_clocks(unsigned c) const noexcept
{
return static_cast<netlist::netlist_time>((m_div * c).shr(MDIV_SHIFT));
}
protected: protected:
netlist_mame_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); netlist_mame_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@ -109,21 +92,16 @@ protected:
virtual void device_reset() override; virtual void device_reset() override;
virtual void device_post_load() override; virtual void device_post_load() override;
virtual void device_pre_save() override; virtual void device_pre_save() override;
virtual void device_clock_changed() override; //virtual void device_clock_changed() override;
void device_start_common();
void save_state();
std::unique_ptr<netlist::netlist_state_t> base_validity_check(validity_checker &valid) const; std::unique_ptr<netlist::netlist_state_t> base_validity_check(validity_checker &valid) const;
attotime m_cur_time;
attotime m_attotime_per_clock;
private: private:
void save_state();
void common_dev_start(netlist::netlist_state_t *lnetlist) const; void common_dev_start(netlist::netlist_state_t *lnetlist) const;
netlist::netlist_time_ext m_div;
netlist::netlist_time_ext m_rem;
netlist::netlist_time_ext m_old;
std::unique_ptr<netlist_mame_t> m_netlist; std::unique_ptr<netlist_mame_t> m_netlist;
func_type m_setup_func; func_type m_setup_func;
@ -156,6 +134,8 @@ class netlist_mame_cpu_device : public netlist_mame_device,
public device_memory_interface public device_memory_interface
{ {
public: public:
static constexpr const unsigned MDIV_SHIFT = 16;
// construction/destruction // construction/destruction
netlist_mame_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); netlist_mame_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -179,12 +159,26 @@ public:
return *this; return *this;
} }
void update_icount(netlist::netlist_time_ext time) noexcept;
void check_mame_abort_slice() noexcept;
netlist::netlist_time_ext nltime_ext_from_clocks(unsigned c) const noexcept
{
return (m_div * c).shr(MDIV_SHIFT);
}
netlist::netlist_time nltime_from_clocks(unsigned c) const noexcept
{
return static_cast<netlist::netlist_time>((m_div * c).shr(MDIV_SHIFT));
}
protected: protected:
// netlist_mame_device // netlist_mame_device
virtual void nl_register_devices(netlist::nlparse_t &parser) const override; virtual void nl_register_devices(netlist::nlparse_t &parser) const override;
// device_t overrides // device_t overrides
virtual void device_start() override; virtual void device_start() override;
virtual void device_clock_changed() override;
// device_execute_interface overrides // device_execute_interface overrides
virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override; virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override;
@ -204,6 +198,10 @@ protected:
address_space_config m_program_config; address_space_config m_program_config;
private: private:
int m_icount;
netlist::netlist_time_ext m_div;
netlist::netlist_time_ext m_rem;
netlist::netlist_time_ext m_old;
offs_t m_genPC; offs_t m_genPC;
}; };
@ -249,13 +247,16 @@ protected:
// device_t overrides // device_t overrides
virtual void device_start() override; virtual void device_start() override;
virtual void device_reset() override; virtual void device_reset() override;
virtual void device_clock_changed() override;
private: private:
std::map<int, netlist_mame_stream_output_device *> m_out; std::map<int, netlist_mame_stream_output_device *> m_out;
nld_sound_in *m_in; nld_sound_in *m_in;
sound_stream *m_stream; sound_stream *m_stream;
attotime m_cur_time;
uint32_t m_sound_clock;
attotime m_attotime_per_clock;
bool m_is_device_call; bool m_is_device_call;
attotime m_last_update_to_current_time;
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------