summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2020-01-15 21:41:57 +0100
committer couriersud <couriersud@gmx.org>2020-01-15 21:41:57 +0100
commit83713b0b5d436a3674f5f82ae7a0179fb0603c80 (patch)
tree1b8f738849b3cc994bf7ab313a2fce6e2f810121
parentd070d8ebe6ec08059270b3fc39e3f2a01ab6b565 (diff)
netlist: Increase resolution to 100 pico seconds. [Couriersud]
Increase the time resolution from 1 nano second to 100 pico seconds. Make sure that icount and netlist internal time are better synched by tracking the remainder of the division. Fixed the netlist sound device. There is a one sample overflow every 13 seconds at 48000 Hz due to integer truncation which is now ignored. Added more doxygen documentation.
-rw-r--r--src/devices/machine/netlist.cpp68
-rw-r--r--src/devices/machine/netlist.h15
-rw-r--r--src/lib/netlist/nl_config.h35
-rw-r--r--src/lib/netlist/plib/ptime.h4
4 files changed, 81 insertions, 41 deletions
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index a6a8325d818..9edc5d1ba5f 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")
@@ -508,6 +506,7 @@ public:
, 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);
@@ -527,9 +526,11 @@ public:
elem.m_buffer = nullptr;
}
- ATTR_COLD void resolve()
+ ATTR_COLD void resolve(std::uint32_t clock)
{
m_pos = 0;
+ m_inc = netlist::netlist_time::from_hz(clock);
+
for (int i = 0; i < MAX_INPUT_CHANNELS; i++)
{
if ((*m_channels[i].m_param_name)() != pstring(""))
@@ -544,21 +545,38 @@ public:
NETLIB_UPDATEI()
{
- for (int i=0; i<m_num_channels; i++)
+ if (m_pos < m_samples)
{
- 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)());
+ 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_inc);
}
public:
- ATTR_HOT void buffer_reset()
+ template <typename S>
+ ATTR_HOT void buffer_reset(int num_samples, S **inputs)
{
+ m_samples = num_samples;
m_pos = 0;
+ for (int i=0; i < m_num_channels; i++)
+ {
+ m_channels[i].m_buffer = inputs[i];
+ }
}
struct channel
@@ -569,16 +587,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_inc;
+
netlist::logic_input_t m_feedback;
netlist::logic_output_t m_Q;
int m_pos;
+ int m_samples;
int m_num_channels;
};
@@ -1163,7 +1183,9 @@ void netlist_mame_device::device_start()
void netlist_mame_device::device_clock_changed()
{
- m_div = netlist::netlist_time::from_hz(clock());
+ m_div = static_cast<netlist::netlist_time>(
+ (netlist::netlist_time::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());
}
@@ -1199,10 +1221,11 @@ ATTR_COLD void netlist_mame_device::device_pre_save()
void netlist_mame_device::update_icount(netlist::netlist_time_ext time) noexcept
{
- const netlist::netlist_time_ext delta(time - m_old + m_rem);
- const auto d(delta / m_div);
+ const netlist::netlist_time_ext delta = (time - m_old).shl(MDIV_SHIFT) + m_rem;
+ const uint64_t d = delta / m_div;
m_old = time;
- m_rem = static_cast<netlist::netlist_time>(delta - (m_div * d));
+ m_rem = (delta - (m_div * d));
+ //printf("d %d m_rem %d\n", (int) d, (int) m_rem.as_raw());
m_icount -= d;
}
@@ -1320,13 +1343,13 @@ ATTR_HOT void netlist_mame_cpu_device::execute_run()
m_genPC++;
m_genPC &= 255;
debugger_instruction_hook(m_genPC);
- netlist().exec().process_queue(static_cast<netlist::netlist_time_ext>(nl_clock_period()));
+ netlist().exec().process_queue(nltime_from_clocks(1));
update_icount(netlist().exec().time());
}
}
else
{
- netlist().exec().process_queue(static_cast<netlist::netlist_time_ext>(nl_clock_period()) * m_icount);
+ netlist().exec().process_queue(nltime_from_clocks(m_icount));
update_icount(netlist().exec().time());
}
}
@@ -1440,8 +1463,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(clock());
}
/* initialize the stream(s) */
@@ -1467,15 +1489,11 @@ void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream
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(samples, inputs);
}
auto cur(netlist().exec().time());
- const auto delta(static_cast<netlist::netlist_time_ext>(nl_clock_period()) * samples);
+ const auto delta(nltime_from_clocks(samples));
netlist().exec().process_queue(delta);
cur += delta;
diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h
index 0be9fcac109..90ccc84493f 100644
--- a/src/devices/machine/netlist.h
+++ b/src/devices/machine/netlist.h
@@ -82,7 +82,16 @@ public:
int m_icount;
+ static constexpr const unsigned MDIV_SHIFT = 16;
+
+ netlist::netlist_time nltime_from_clocks(unsigned c) const noexcept
+ {
+ //return (m_div * c + netlist::netlist_time::from_raw((1 << MDIV_SHIFT) - 1)).shr(MDIV_SHIFT);
+ return (m_div * c).shr(MDIV_SHIFT);
+ }
+
protected:
+
netlist_mame_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// Custom to netlist ...
@@ -98,8 +107,6 @@ protected:
virtual void device_pre_save() override;
virtual void device_clock_changed() override;
- netlist::netlist_time nl_clock_period() const noexcept { return m_div; }
-
plib::unique_ptr<netlist::netlist_state_t> base_validity_check(validity_checker &valid) const;
private:
@@ -107,8 +114,8 @@ private:
void common_dev_start(netlist::netlist_state_t *lnetlist) const;
- netlist::netlist_time m_div;
- netlist::netlist_time m_rem;
+ 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;
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index 47707af7d22..a918db4d590 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -17,7 +17,7 @@
///
/// \brief Version - Minor.
///
-#define NL_VERSION_MINOR 5
+#define NL_VERSION_MINOR 6
///
/// \brief Version - Patch level.
///
@@ -135,19 +135,30 @@
/// \brief Resolution as clocks per second for timing
///
-/// Uses nano-second resolution - Sufficient for now
+/// Uses 100 pico second resolution. This is aligned to MAME's
+/// attotime resolution.
+///
+/// The table below shows the maximum run times depending on
+/// time type size and resolution.
+///
+/// | Bits | Res | Seconds | Days | Years |
+/// | ====-| ===-| =======-| ====-| =====-|
+/// | 63 | 1,000,000,000 | 9,223,372,037 | 106,752| 292.3 |
+/// | 63 | 10,000,000,000 | 922,337,204 | 10,675| 29.2 |
+/// | 63 | 100,000,000,000 | 92,233,720 | 1,068| 2.9 |
+/// | 63 | 1,000,000,000,000 | 9,223,372 | 107| 0.3 |
+///
-#if 1
-static constexpr const auto NETLIST_INTERNAL_RES = 1'000'000'000;
-static constexpr const auto NETLIST_CLOCK = NETLIST_INTERNAL_RES;
-#else
-//static constexpr const auto NETLIST_INTERNAL_RES = (1<<30); // 1,073,741,824
-//static constexpr const std::int64_t NETLIST_INTERNAL_RES = (static_cast<std::int64_t>(1)<<33); // 8,589,934,592
-static constexpr const std::int64_t NETLIST_INTERNAL_RES = (static_cast<std::int64_t>(1)<<37); // 137,438,953,472
-// FIXME: Belongs into MAME netlist.h
-static constexpr const std::int32_t NETLIST_CLOCK = (static_cast<std::int64_t>(1)<<30); // 1,073,741,824
-#endif
+static constexpr const auto NETLIST_INTERNAL_RES = 10'000'000'000ll;
+
+/// \brief Recommended clock to be used
+///
+/// This is the recommended clock to be used in fixed clock applications limited
+/// to 32 bit clock resolution. The MAME code (netlist.cpp) contains code
+/// illustrating how to deal with remainders if \ref NETLIST_INTERNAL_RES is
+/// bigger than NETLIST_CLOCK.
+static constexpr const int NETLIST_CLOCK = 1'000'000'000;
/// \brief Floating point types used
///
diff --git a/src/lib/netlist/plib/ptime.h b/src/lib/netlist/plib/ptime.h
index df0bac92477..5b23271d9ff 100644
--- a/src/lib/netlist/plib/ptime.h
+++ b/src/lib/netlist/plib/ptime.h
@@ -159,6 +159,10 @@ namespace plib
constexpr double as_float() const noexcept { return as_fp<float>(); }
constexpr double as_long_double() const noexcept { return as_fp<long double>(); }
+
+ constexpr ptime shl(unsigned shift) const noexcept { return ptime(m_time << shift); }
+ constexpr ptime shr(unsigned shift) const noexcept { return ptime(m_time >> shift); }
+
// for save states ....
C14CONSTEXPR internal_type *get_internaltype_ptr() noexcept { return &m_time; }