summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Couriersud <couriersud@users.noreply.github.com>2013-11-04 20:47:32 +0000
committer Couriersud <couriersud@users.noreply.github.com>2013-11-04 20:47:32 +0000
commitbf1909932338a67c257f7eb613c78d65b5c74a73 (patch)
tree54f4d62d5cfddd946d1071b7e859bebc29c17498
parent39dc549a5f40b1495fb8a2bc5b1012db5e6b4e68 (diff)
Split the netlist code up into functional pieces like parser, setup and execution. This looks a lot more structured now and highlighted some issue already.
-rw-r--r--.gitattributes17
-rw-r--r--src/emu/emu.mak1
-rw-r--r--src/emu/machine/netlist.c1060
-rw-r--r--src/emu/machine/netlist.h1370
-rw-r--r--src/emu/netlist/devices/net_lib.c (renamed from src/emu/netlist/net_lib.c)30
-rw-r--r--src/emu/netlist/devices/net_lib.h (renamed from src/emu/netlist/net_lib.h)112
-rw-r--r--src/emu/netlist/devices/nld_7400.c6
-rw-r--r--src/emu/netlist/devices/nld_7400.h44
-rw-r--r--src/emu/netlist/devices/nld_signal.h296
-rw-r--r--src/emu/netlist/devices/nld_system.h82
-rw-r--r--src/emu/netlist/netlist.mak8
-rw-r--r--src/emu/netlist/nl_base.c435
-rw-r--r--src/emu/netlist/nl_base.h811
-rw-r--r--src/emu/netlist/nl_config.h103
-rw-r--r--src/emu/netlist/nl_lists.h134
-rw-r--r--src/emu/netlist/nl_parser.c207
-rw-r--r--src/emu/netlist/nl_parser.h39
-rw-r--r--src/emu/netlist/nl_setup.c318
-rw-r--r--src/emu/netlist/nl_setup.h113
-rw-r--r--src/emu/netlist/nl_time.h99
-rw-r--r--src/mame/drivers/pong.c6
21 files changed, 2800 insertions, 2491 deletions
diff --git a/.gitattributes b/.gitattributes
index 3e5b654e3d5..1d703b48d56 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2098,9 +2098,22 @@ src/emu/memarray.c svneol=native#text/plain
src/emu/memarray.h svneol=native#text/plain
src/emu/memory.c svneol=native#text/plain
src/emu/memory.h svneol=native#text/plain
-src/emu/netlist/net_lib.c svneol=native#text/plain
-src/emu/netlist/net_lib.h svneol=native#text/plain
+src/emu/netlist/devices/net_lib.c svneol=native#text/plain
+src/emu/netlist/devices/net_lib.h svneol=native#text/plain
+src/emu/netlist/devices/nld_7400.c svneol=native#text/plain
+src/emu/netlist/devices/nld_7400.h svneol=native#text/plain
+src/emu/netlist/devices/nld_signal.h svneol=native#text/plain
+src/emu/netlist/devices/nld_system.h svneol=native#text/plain
src/emu/netlist/netlist.mak svneol=native#text/plain
+src/emu/netlist/nl_base.c svneol=native#text/plain
+src/emu/netlist/nl_base.h svneol=native#text/plain
+src/emu/netlist/nl_config.h svneol=native#text/plain
+src/emu/netlist/nl_lists.h svneol=native#text/plain
+src/emu/netlist/nl_parser.c svneol=native#text/plain
+src/emu/netlist/nl_parser.h svneol=native#text/plain
+src/emu/netlist/nl_setup.c svneol=native#text/plain
+src/emu/netlist/nl_setup.h svneol=native#text/plain
+src/emu/netlist/nl_time.h svneol=native#text/plain
src/emu/network.c svneol=native#text/plain
src/emu/network.h svneol=native#text/plain
src/emu/output.c svneol=native#text/plain
diff --git a/src/emu/emu.mak b/src/emu/emu.mak
index 9abac43e3b1..c867a8d898d 100644
--- a/src/emu/emu.mak
+++ b/src/emu/emu.mak
@@ -60,6 +60,7 @@ OBJDIRS += \
$(EMUOBJ)/drivers \
$(EMUOBJ)/machine \
$(EMUOBJ)/netlist \
+ $(EMUOBJ)/netlist/devices \
$(EMUOBJ)/layout \
$(EMUOBJ)/imagedev \
$(EMUOBJ)/video \
diff --git a/src/emu/machine/netlist.c b/src/emu/machine/netlist.c
index 8dc6bfeeb03..d8fe4c0e7f5 100644
--- a/src/emu/machine/netlist.c
+++ b/src/emu/machine/netlist.c
@@ -45,1058 +45,13 @@
****************************************************************************/
#include "netlist.h"
-#include "netlist/net_lib.h"
-
-//============================================================
-// DEBUGGING
-//============================================================
-
-#define VERBOSE (0)
-#define KEEP_STATISTICS (0)
-#define FATAL_ERROR_AFTER_NS (0) //(1000)
-
-#if (VERBOSE)
- #define VERBOSE_OUT(x) printf x
-#else
- #define VERBOSE_OUT(x)
-#endif
-
-//============================================================
-// MACROS
-//============================================================
-
-#if KEEP_STATISTICS
-#define add_to_stat(v,x) do { v += (x); } while (0)
-#define inc_stat(v) add_to_stat(v, 1)
-#define begin_timing(v) do { (v) -= get_profile_ticks(); } while (0)
-#define end_timing(v) do { (v) += get_profile_ticks(); } while (0)
-#else
-#define add_to_stat(v,x) do { } while (0)
-#define inc_stat(v) add_to_stat(v, 1)
-#define begin_timing(v) do { } while (0)
-#define end_timing(v) do { } while (0)
-#endif
+#include "netlist/nl_base.h"
+#include "netlist/nl_setup.h"
+#include "netlist/devices/net_lib.h"
const netlist_time netlist_time::zero = netlist_time::from_raw(0);
// ----------------------------------------------------------------------------------------
-// A netlist parser
-// ----------------------------------------------------------------------------------------
-
-class netlist_parser
-{
-public:
- netlist_parser(netlist_setup_t &setup)
- : m_setup(setup) {}
-
- void parse(char *buf)
- {
- m_p = buf;
- while (*m_p)
- {
- astring n;
- skipws();
- if (!*m_p) break;
- n = getname('(');
- VERBOSE_OUT(("Parser: Device: %s\n", n.cstr()));
- if (n == "NET_ALIAS")
- net_alias();
- else if (n == "NETDEV_PARAM")
- netdev_param();
- else if ((n == "NETDEV_TTL_CONST") || (n == "NETDEV_ANALOG_CONST"))
- netdev_const(n);
- else
- netdev_device(n);
- }
- }
-
- void net_alias()
- {
- astring alias;
- astring out;
- skipws();
- alias = getname(',');
- skipws();
- out = getname(')');
- VERBOSE_OUT(("Parser: Alias: %s %s\n", alias.cstr(), out.cstr()));
- m_setup.register_alias(alias, out);
- }
-
- void netdev_param()
- {
- astring param;
- double val;
- skipws();
- param = getname(',');
- skipws();
- val = eval_param();
- VERBOSE_OUT(("Parser: Param: %s %f\n", param.cstr(), val));
- m_setup.find_param(param).initial(val);
- check_char(')');
- }
-
- void netdev_const(const astring &dev_name)
- {
- astring name;
- net_device_t *dev;
- astring paramfq;
- double val;
-
- skipws();
- name = getname(',');
- dev = net_create_device_by_name(dev_name, m_setup, name);
- m_setup.register_dev(dev);
- skipws();
- val = eval_param();
- check_char(')');
- paramfq = name;
- paramfq.cat(".CONST");
- VERBOSE_OUT(("Parser: Const: %s %f\n", name.cstr(), val));
- m_setup.find_param(paramfq).initial(val);
- }
-
- void netdev_device(const astring &dev_type)
- {
- astring devname;
- net_device_t *dev;
- int cnt;
-
- skipws();
- devname = getname2(',', ')');
- dev = net_create_device_by_name(dev_type, m_setup, devname);
- m_setup.register_dev(dev);
- skipws();
- VERBOSE_OUT(("Parser: IC: %s\n", devname.cstr()));
- cnt = 0;
- while (*m_p != ')')
- {
- m_p++;
- skipws();
- astring output_name = getname2(',', ')');
- VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), dev->m_inputs.item(cnt)->cstr()));
- m_setup.register_link(*dev->m_inputs.item(cnt), output_name);
- skipws();
- cnt++;
- }
- if (cnt != dev->m_inputs.count() && !dev->variable_input_count())
- fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname.cstr(), dev->m_inputs.count(), cnt);
- if (dev->variable_input_count())
- {
- VERBOSE_OUT(("variable inputs %s: %d\n", dev->name().cstr(), cnt));
- }
- check_char(')');
- }
-
-private:
-
- void skipeol()
- {
- while (*m_p)
- {
- if (*m_p == 10)
- {
- m_p++;
- if (*m_p && *m_p == 13)
- m_p++;
- return;
- }
- m_p++;
- }
- }
-
- void skipws()
- {
- while (*m_p)
- {
- switch (*m_p)
- {
- case ' ':
- case 9:
- case 10:
- case 13:
- m_p++;
- break;
- case '/':
- if (*(m_p+1) == '/')
- skipeol();
- break;
- default:
- return;
- }
- }
- }
-
- astring getname(char sep)
- {
- char buf[300];
- char *p1 = buf;
-
- while (*m_p != sep)
- *p1++ = *m_p++;
- *p1 = 0;
- m_p++;
- return astring(buf);
- }
-
- astring getname2(char sep1, char sep2)
- {
- char buf[300];
- char *p1 = buf;
-
- while ((*m_p != sep1) && (*m_p != sep2))
- *p1++ = *m_p++;
- *p1 = 0;
- return astring(buf);
- }
-
- void check_char(char ctocheck)
- {
- skipws();
- if (*m_p == ctocheck)
- {
- m_p++;
- return;
- }
- fatalerror("Parser: expected '%c' found '%c'\n", ctocheck, *m_p);
- }
-
- double eval_param()
- {
- static const char *macs[6] = {"", "RES_K(", "RES_M(", "CAP_U(", "CAP_N(", "CAP_P("};
- static double facs[6] = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
- int i;
- int f=0;
- char *e;
- double ret;
- char *s = m_p;
-
- for (i=1; i<6;i++)
- if (strncmp(s, macs[i], strlen(macs[i])) == 0)
- f = i;
- ret = strtod(s+strlen(macs[f]), &e);
- if ((f>0) && (*e != ')'))
- fatalerror("Parser: Error with parameter ...\n");
- if (f>0)
- e++;
- m_p = e;
- return ret * facs[f];
- }
-
- char * m_p;
- netlist_setup_t &m_setup;
-
-};
-
-
-// ----------------------------------------------------------------------------------------
-// netdev_mainclock
-// ----------------------------------------------------------------------------------------
-
-ATTR_HOT inline void netdev_mainclock::mc_update(net_output_t &Q, const netlist_time curtime)
-{
- Q.m_new_Q = !Q.m_new_Q;
- Q.set_time(curtime);
- Q.update_devs();
-}
-
-ATTR_COLD NETLIB_START(netdev_mainclock)
-{
- register_output("Q", m_Q);
-
- register_param("FREQ", m_freq, 7159000.0 * 5);
- m_inc = netlist_time::from_hz(m_freq.Value()*2);
-
-}
-
-ATTR_HOT NETLIB_UPDATE_PARAM(netdev_mainclock)
-{
- m_inc = netlist_time::from_hz(m_freq.Value()*2);
-}
-
-ATTR_HOT NETLIB_UPDATE(netdev_mainclock)
-{
- // this is only called during setup ...
- m_Q.m_new_Q = !m_Q.m_new_Q;
- m_Q.set_time(m_netlist->time() + m_inc);
-}
-
-
-// ----------------------------------------------------------------------------------------
-// netdev_a_to_d
-// ----------------------------------------------------------------------------------------
-
-class netdev_a_to_d_proxy : public net_device_t
-{
-public:
- netdev_a_to_d_proxy(net_input_t &in_proxied)
- : net_device_t()
- {
- assert(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
- m_I.m_high_thresh_V = in_proxied.m_high_thresh_V;
- m_I.m_low_thresh_V = in_proxied.m_low_thresh_V;
- }
-
- virtual ~netdev_a_to_d_proxy() {}
-
- analog_input_t m_I;
- ttl_output_t m_Q;
-
-protected:
- void start()
- {
- m_I.init_input(this);
-
- m_Q.init_terminal(this);
- m_Q.initial(1);
- }
-
- ATTR_HOT ATTR_ALIGN void update()
- {
- if (m_I.Q_Analog() > m_I.m_high_thresh_V)
- OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1));
- else if (m_I.Q_Analog() < m_I.m_low_thresh_V)
- OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1));
- }
-
-};
-
-// ----------------------------------------------------------------------------------------
-// netdev_d_to_a
-// ----------------------------------------------------------------------------------------
-
-class netdev_d_to_a_proxy : public net_device_t
-{
-public:
- netdev_d_to_a_proxy(net_output_t &out_proxied)
- : net_device_t()
- {
- assert(out_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
- m_low_V = out_proxied.m_low_V;
- m_high_V = out_proxied.m_high_V;
- }
-
- virtual ~netdev_d_to_a_proxy() {}
-
- ttl_input_t m_I;
- analog_output_t m_Q;
-
-protected:
- void start()
- {
- m_I.init_input(this);
- m_Q.init_terminal(this);
- m_Q.initial(0);
- }
-
- ATTR_HOT ATTR_ALIGN void update()
- {
- OUTANALOG(m_Q, INPLOGIC(m_I) ? m_high_V : m_low_V, NLTIME_FROM_NS(1));
- }
-
-private:
- double m_low_V;
- double m_high_V;
-};
-
-// ----------------------------------------------------------------------------------------
-// netdev_const
-// ----------------------------------------------------------------------------------------
-
-NETLIB_START(netdev_ttl_const)
-{
- register_output("Q", m_Q);
- register_param("CONST", m_const, 0.0);
-}
-
-NETLIB_UPDATE(netdev_ttl_const)
-{
-}
-
-NETLIB_UPDATE_PARAM(netdev_ttl_const)
-{
- OUTLOGIC(m_Q, m_const.ValueInt(), NLTIME_IMMEDIATE);
-}
-
-NETLIB_START(netdev_analog_const)
-{
- register_output("Q", m_Q);
- register_param("CONST", m_const, 0.0);
-}
-
-NETLIB_UPDATE(netdev_analog_const)
-{
-}
-
-NETLIB_UPDATE_PARAM(netdev_analog_const)
-{
- m_Q.initial(m_const.Value());
-}
-
-// ----------------------------------------------------------------------------------------
-// netlist_base_t
-// ----------------------------------------------------------------------------------------
-
-
-NETLIB_UPDATE(netdev_analog_callback)
-{
- // FIXME: Remove after device cleanup
- if (!m_callback.isnull())
- m_callback(INPANALOG(m_in));
-}
-
-netlist_base_t::netlist_base_t()
- : m_mainclock(NULL),
- m_time_ps(netlist_time::zero),
- m_rem(0),
- m_div(NETLIST_DIV)
-{
-}
-
-netlist_base_t::~netlist_base_t()
-{
-}
-
-ATTR_COLD void netlist_base_t::set_mainclock_dev(netdev_mainclock *dev)
-{
- m_mainclock = dev;
-}
-
-ATTR_COLD void netlist_base_t::reset()
-{
- m_time_ps = netlist_time::zero;
- m_rem = 0;
- m_queue.clear();
- if (m_mainclock != NULL)
- m_mainclock->m_Q.set_time(netlist_time::zero);
-}
-
-
-void netlist_base_t::set_clock_freq(UINT64 clockfreq)
-{
- m_div = netlist_time::from_hz(clockfreq).as_raw();
- m_rem = 0;
- assert_always(m_div == NETLIST_DIV, "netlist: illegal clock!");
- VERBOSE_OUT(("Setting clock %" I64FMT "d and divisor %d\n", clockfreq, m_div));
-}
-
-ATTR_HOT ATTR_ALIGN inline void netlist_base_t::update_time(const netlist_time t, INT32 &atime)
-{
- if (NETLIST_DIV_BITS == 0)
- {
- const netlist_time delta = t - m_time_ps;
- m_time_ps = t;
- atime -= delta.as_raw();
- } else {
- const netlist_time delta = t - m_time_ps + netlist_time::from_raw(m_rem);
- m_time_ps = t;
- m_rem = delta.as_raw() & NETLIST_MASK;
- atime -= (delta.as_raw() >> NETLIST_DIV_BITS);
-
- // The folling is suitable for non-power of 2 m_divs ...
- // atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
- }
-}
-
-ATTR_HOT ATTR_ALIGN void netlist_base_t::process_list(INT32 &atime)
-{
- if (m_mainclock == NULL)
- {
- while ( (atime > 0) && (m_queue.is_not_empty()))
- {
- const queue_t::entry_t e = m_queue.pop();
- update_time(e.time(), atime);
-
- if (FATAL_ERROR_AFTER_NS)
- printf("%s\n", e.object().netdev()->name().cstr());
-
- e.object().update_devs();
-
- add_to_stat(m_perf_out_processed, 1);
-
- if (FATAL_ERROR_AFTER_NS)
- if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS))
- fatalerror("Stopped");
- }
-
- if (atime > 0)
- {
- m_time_ps += netlist_time::from_raw(atime * m_div);
- atime = 0;
- }
- } else {
- net_output_t &mcQ = m_mainclock->m_Q;
- const netlist_time inc = m_mainclock->m_inc;
-
- while (atime > 0)
- {
- if (m_queue.is_not_empty())
- {
- while (m_queue.peek().time() > mcQ.time())
- {
- update_time(mcQ.time(), atime);
-
- netdev_mainclock::mc_update(mcQ, time() + inc);
-
- }
- const queue_t::entry_t e = m_queue.pop();
-
- update_time(e.time(), atime);
-
- e.object().update_devs();
-
- } else {
- update_time(mcQ.time(), atime);
-
- netdev_mainclock::mc_update(mcQ, time() + inc);
- }
- if (FATAL_ERROR_AFTER_NS)
- if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS))
- fatalerror("Stopped");
-
- add_to_stat(m_perf_out_processed, 1);
- }
-
- if (atime > 0)
- {
- m_time_ps += netlist_time::from_raw(atime * m_div);
- atime = 0;
- }
- }
-}
-
-// ----------------------------------------------------------------------------------------
-// Default netlist elements ...
-// ----------------------------------------------------------------------------------------
-
-
-static NETLIST_START(base)
- NETDEV_TTL_CONST(ttlhigh, 1)
- NETDEV_TTL_CONST(ttllow, 0)
- NETDEV_ANALOG_CONST(NC, NETLIST_HIGHIMP_V)
-NETLIST_END
-
-// ----------------------------------------------------------------------------------------
-// netlist_setup_t
-// ----------------------------------------------------------------------------------------
-
-netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
- : m_netlist(netlist)
-{
- NETLIST_NAME(base)(*this);
-}
-
-template <class T>
-static void tagmap_free_entries(T &tm)
-{
- for (typename T::entry_t *entry = tm.first(); entry != NULL; entry = tm.next(entry))
- {
- delete entry->object();
- }
- tm.reset();
-}
-
-netlist_setup_t::~netlist_setup_t()
-{
- tagmap_free_entries<tagmap_devices_t>(m_devices);
- tagmap_free_entries<tagmap_astring_t>(m_links);
- tagmap_free_entries<tagmap_astring_t>(m_alias);
- m_params.reset();
- m_terminals.reset();
-}
-
-net_device_t *netlist_setup_t::register_dev(net_device_t *dev)
-{
- if (!(m_devices.add(dev->name(), dev, false)==TMERR_NONE))
- fatalerror("Error adding %s to device list\n", dev->name().cstr());
- return dev;
-}
-
-template <class T>
-static void remove_start_with(T &hm, astring &sw)
-{
- typename T::entry_t *entry = hm.first();
- while (entry != NULL)
- {
- typename T::entry_t *next = hm.next(entry);
- if (sw.cmpsubstr(entry->tag(), 0, sw.len()) == 0)
- {
- VERBOSE_OUT(("removing %s\n", entry->tag().cstr()));
- hm.remove(entry->object());
- }
- entry = next;
- }
-}
-
-void netlist_setup_t::remove_dev(const astring &name)
-{
- net_device_t *dev = m_devices.find(name);
- astring temp = name;
- if (dev == NULL)
- fatalerror("Device %s does not exist\n", name.cstr());
-
- temp.cat(".");
-
- //remove_start_with<tagmap_input_t>(m_inputs, temp);
- remove_start_with<tagmap_terminal_t>(m_terminals, temp);
- remove_start_with<tagmap_param_t>(m_params, temp);
- remove_start_with<tagmap_astring_t>(m_links, temp);
- m_devices.remove(name);
-}
-
-void netlist_setup_t::register_callback(const astring &devname, net_output_delegate delegate)
-{
- netdev_analog_callback *dev = (netdev_analog_callback *) m_devices.find(devname);
- if (dev == NULL)
- fatalerror("did not find device %s\n", devname.cstr());
- dev->register_callback(delegate);
-}
-
-void netlist_setup_t::register_alias(const astring &alias, const astring &out)
-{
- if (!(m_alias.add(alias, new astring(out), false)==TMERR_NONE))
- fatalerror("Error adding alias %s to alias list\n", alias.cstr());
-}
-
-void netlist_setup_t::register_output(net_core_device_t &dev, net_core_device_t &upd_dev, const astring &name, net_output_t &out)
-{
- VERBOSE_OUT(("out %s\n", name.cstr()));
- astring temp = dev.name();
- temp.cat(".");
- temp.cat(name);
- out.init_terminal(&upd_dev);
- if (!(m_terminals.add(temp, &out, false)==TMERR_NONE))
- fatalerror("Error adding output %s to output list\n", name.cstr());
-}
-
-void netlist_setup_t::register_input(net_device_t &dev, net_core_device_t &upd_dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type)
-{
- VERBOSE_OUT(("input %s\n", name.cstr()));
- astring temp = dev.name();
- temp.cat(".");
- temp.cat(name);
- inp.init_input(&upd_dev, type);
- dev.m_inputs.add(temp);
- if (!(m_terminals.add(temp, &inp, false) == TMERR_NONE))
- fatalerror("Error adding input %s to input list\n", name.cstr());
-}
-
-void netlist_setup_t::register_link(const astring &sin, const astring &sout)
-{
- const astring *temp = new astring(sout);
- VERBOSE_OUT(("link %s <== %s\n", sin.cstr(), sout.cstr()));
- if (!(m_links.add(sin, temp, false)==TMERR_NONE))
- fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr());
-}
-
-
-void netlist_setup_t::register_param(const astring &name, net_param_t *param)
-{
- astring temp = param->netdev().name();
- temp.cat(".");
- temp.cat(name);
- if (!(m_params.add(temp, param, false)==TMERR_NONE))
- fatalerror("Error adding parameter %s to parameter list\n", name.cstr());
-}
-
-
-const astring &netlist_setup_t::resolve_alias(const astring &name) const
-{
- const astring *ret = m_alias.find(name);
- if (ret != NULL)
- return *ret;
- return name;
-}
-
-net_output_t *netlist_setup_t::find_output_exact(const astring &outname_in)
-{
- net_terminal_t *term = m_terminals.find(outname_in);
- return dynamic_cast<net_output_t *>(term);
-}
-
-net_output_t &netlist_setup_t::find_output(const astring &outname_in)
-{
- const astring &outname = resolve_alias(outname_in);
- net_output_t *ret;
-
- ret = find_output_exact(outname);
- /* look for default */
- if (ret == NULL)
- {
- /* look for ".Q" std output */
- astring s = outname;
- s.cat(".Q");
- ret = find_output_exact(s);
- }
- if (ret == NULL)
- fatalerror("output %s(%s) not found!\n", outname_in.cstr(), outname.cstr());
- VERBOSE_OUT(("Found input %s\n", outname.cstr()));
- return *ret;
-}
-
-net_param_t &netlist_setup_t::find_param(const astring &param_in)
-{
- const astring &outname = resolve_alias(param_in);
- net_param_t *ret;
-
- ret = m_params.find(outname);
- if (ret == NULL)
- fatalerror("parameter %s(%s) not found!\n", param_in.cstr(), outname.cstr());
- VERBOSE_OUT(("Found parameter %s\n", outname.cstr()));
- return *ret;
-}
-
-void netlist_setup_t::resolve_inputs(void)
-{
- VERBOSE_OUT(("Resolving ...\n"));
- int proxy_cnt = 0;
- for (tagmap_astring_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry))
- {
- const astring *sout = entry->object();
- astring sin = entry->tag();
- net_input_t *in = dynamic_cast<net_input_t *>(m_terminals.find(sin));
-
- if (in == NULL)
- fatalerror("Unable to find %s\n", sin.cstr());
-
- net_output_t &out = find_output(sout->cstr());
- if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG
- && in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL)
- {
- netdev_a_to_d_proxy *proxy = new netdev_a_to_d_proxy(*in);
- astring x = "";
- x.printf("proxy_ad_%d", proxy_cnt++);
-
- proxy->init(*this, x.cstr());
- register_dev(proxy);
-
- in->set_output(proxy->m_Q);
- proxy->m_Q.register_con(*in);
- proxy->m_I.set_output(out);
- out.register_con(proxy->m_I);
-
- }
- else if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL
- && in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG)
- {
- //printf("here 1\n");
- netdev_d_to_a_proxy *proxy = new netdev_d_to_a_proxy(out);
- astring x = "";
- x.printf("proxy_da_%d", proxy_cnt++);
- proxy->init(*this, x.cstr());
- register_dev(proxy);
-
- in->set_output(proxy->m_Q);
- proxy->m_Q.register_con(*in);
- proxy->m_I.set_output(out);
- out.register_con(proxy->m_I);
- //printf("here 2\n");
- }
- else
- {
- in->set_output(out);
- out.register_con(*in);
- }
- }
-
- /* find the main clock ... */
- for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
- {
- net_device_t *dev = entry->object();
- if (dynamic_cast<netdev_mainclock*>(dev) != NULL)
- {
- m_netlist.set_mainclock_dev(dynamic_cast<netdev_mainclock*>(dev));
- }
- }
-
-#if 1
-
-#else
- /* make sure all outputs are triggered once */
- for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
- {
- net_output_t *out = entry->object();
- //if (dynamic_cast<const netdev_clock *>(out->netdev()) == NULL )
- {
- out->update_devs_force();
- INT32 time = 10000;
- m_netlist.process_list(time);
- }
- }
- //m_netlist.m_queue.clear();
-#endif
-
- /* print all outputs */
- for (tagmap_terminal_t::entry_t *entry = m_terminals.first(); entry != NULL; entry = m_terminals.next(entry))
- {
- ATTR_UNUSED net_output_t *out = dynamic_cast<net_output_t *>(entry->object());
- //if (out != NULL)
- //VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
- }
-
-
-}
-
-void netlist_setup_t::step_devices_once(void)
-{
- /* make sure params are set now .. */
- for (tagmap_param_t::entry_t *entry = m_params.first(); entry != NULL; entry = m_params.next(entry))
- {
- entry->object()->netdev().update_param();
- }
-
- for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
- {
- net_device_t *dev = entry->object();
- dev->update_dev();
- }
-}
-
-
-void netlist_setup_t::parse(char *buf)
-{
- netlist_parser parser(*this);
- parser.parse(buf);
-}
-
-void netlist_setup_t::print_stats()
-{
- if (KEEP_STATISTICS)
- {
- for (netlist_setup_t::tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
- {
- //entry->object()->s
- printf("Device %20s : %12d %15ld\n", entry->object()->name().cstr(), entry->object()->stat_count, (long int) entry->object()->total_time / (entry->object()->stat_count + 1));
- }
- printf("Queue Start %15d\n", m_netlist.m_queue.m_prof_start);
- printf("Queue End %15d\n", m_netlist.m_queue.m_prof_end);
- printf("Queue Sort %15d\n", m_netlist.m_queue.m_prof_sort);
- printf("Queue Move %15d\n", m_netlist.m_queue.m_prof_sortmove);
- }
-}
-
-
-// ----------------------------------------------------------------------------------------
-// net_core_device_t
-// ----------------------------------------------------------------------------------------
-
-net_core_device_t::net_core_device_t()
-: net_object_t(DEVICE)
-{
-}
-
-ATTR_COLD void net_core_device_t::init(netlist_setup_t &setup, const astring &name)
-{
- m_netlist = &setup.netlist();
- m_name = name;
-
-#if USE_DELEGATES
-#if USE_PMFDELEGATES
- void (net_core_device_t::* pFunc)() = &net_core_device_t::update;
- static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
-#else
- static_update = net_update_delegate(&net_core_device_t::update, "update", this);
- // get the pointer to the member function
-#endif
-#endif
-
-}
-
-ATTR_COLD void net_device_t::init(netlist_setup_t &setup, const astring &name)
-{
- net_core_device_t::init(setup, name);
- m_setup = &setup;
- start();
-}
-
-
-net_core_device_t::~net_core_device_t()
-{
-}
-
-// ----------------------------------------------------------------------------------------
-// net_device_t
-// ----------------------------------------------------------------------------------------
-
-ATTR_HOT ATTR_ALIGN const net_sig_t net_core_device_t::INPLOGIC_PASSIVE(logic_input_t &inp)
-{
- if (inp.state() == net_input_t::INP_STATE_PASSIVE)
- {
- inp.activate();
- const net_sig_t ret = inp.Q();
- inp.inactivate();
- return ret;
- }
- else
- return inp.Q();
-
-}
-
-net_device_t::net_device_t()
- : net_core_device_t(),
- m_setup(NULL),
- m_variable_input_count(false)
-{
-}
-
-net_device_t::~net_device_t()
-{
- //printf("~net_device_t\n");
-}
-
-ATTR_COLD void net_device_t::register_sub(net_core_device_t &dev, const astring &name)
-{
- dev.init(*m_setup, name);
-}
-
-void net_device_t::register_output(net_core_device_t &dev, const astring &name, net_output_t &port)
-{
- m_setup->register_output(*this, dev, name, port);
-}
-
-void net_device_t::register_output(const astring &name, net_output_t &port)
-{
- m_setup->register_output(*this,*this,name, port);
-}
-
-void net_device_t::register_input(net_core_device_t &dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type)
-{
- m_setup->register_input(*this, dev, name, inp, type);
-}
-
-void net_device_t::register_input(const astring &name, net_input_t &inp, net_input_t::net_input_state type)
-{
- register_input(*this, name, inp, type);
-}
-
-void net_device_t::register_link_internal(net_core_device_t &dev, net_input_t &in, net_output_t &out, net_input_t::net_input_state aState)
-{
- in.set_output(out);
- in.init_input(&dev, aState);
- //if (in.state() != net_input_t::INP_STATE_PASSIVE)
- out.register_con(in);
-}
-
-void net_device_t::register_link_internal(net_input_t &in, net_output_t &out, net_input_t::net_input_state aState)
-{
- register_link_internal(*this, in, out, aState);
-}
-
-void net_device_t::register_param(net_core_device_t &dev, const astring &name, net_param_t &param, double initialVal)
-{
- param.set_netdev(dev);
- param.initial(initialVal);
- m_setup->register_param(name, &param);
-}
-
-void net_device_t::register_param(const astring &name, net_param_t &param, double initialVal)
-{
- register_param(*this,name, param, initialVal);
-}
-
-// ----------------------------------------------------------------------------------------
-// net_terminal_t
-// ----------------------------------------------------------------------------------------
-
-ATTR_COLD void net_terminal_t::init_terminal(net_core_device_t *dev)
-{
- m_netdev = dev;
- m_netlist = dev->netlist();
-}
-
-// ----------------------------------------------------------------------------------------
-// net_input_t
-// ----------------------------------------------------------------------------------------
-
-ATTR_COLD void net_input_t::init_input(net_core_device_t *dev, net_input_state astate)
-{
- init_terminal(dev);
- m_state = astate;
-}
-
-// ----------------------------------------------------------------------------------------
-// net_output_t
-// ----------------------------------------------------------------------------------------
-
-net_output_t::net_output_t(int atype)
- : net_terminal_t(atype)
- , m_low_V(0.0)
- , m_high_V(0.0)
- , m_last_Q(0)
- , m_Q(0)
- , m_new_Q(0)
- , m_Q_analog(0.0)
- , m_new_Q_analog(0.0)
- , m_num_cons(0)
- , m_time(netlist_time::zero)
- , m_active(0)
- , m_in_queue(2)
-{
- //m_cons = global_alloc_array(net_input_t *, OUTPUT_MAX_CONNECTIONS);
-}
-
-ATTR_HOT inline void net_output_t::update_dev(const net_input_t *inp, const UINT32 mask)
-{
- if ((inp->state() & mask) != 0)
- {
- ATTR_UNUSED net_core_device_t *netdev = inp->netdev();
- begin_timing(netdev->total_time);
- inc_stat(netdev->stat_count);
- netdev->update_dev();
- end_timing(netdev()->total_time);
- }
-}
-
-ATTR_HOT inline void net_output_t::update_devs()
-{
-
- assert(m_num_cons != 0);
-
- const UINT32 masks[4] = { 1, 5, 3, 1 };
- m_Q = m_new_Q;
- m_Q_analog = m_new_Q_analog;
- m_in_queue = 2; /* mark as taken ... */
-
- const UINT32 mask = masks[ (m_last_Q << 1) | m_Q ];
-
- switch (m_num_cons)
- {
- case 2:
- update_dev(m_cons[1], mask);
- case 1:
- update_dev(m_cons[0], mask);
- break;
- default:
- {
- for (int i=0; i < m_num_cons; i++)
- update_dev(m_cons[i], mask);
- }
- break;
- }
-
- m_last_Q = m_Q;
-}
-
-ATTR_COLD void net_output_t::register_con(net_input_t &input)
-{
- int i;
- if (m_num_cons >= OUTPUT_MAX_CONNECTIONS)
- fatalerror("Connections exceeded for %s\n", netdev()->name().cstr());
-
- /* keep similar devices together */
- for (i = 0; i < m_num_cons; i++)
- if (m_cons[i]->netdev() == input.netdev())
- break;
-
- for (int j = m_num_cons; j > i; j--)
- m_cons[j] = m_cons[j - 1];
-
- m_cons[i] = &input;
- m_num_cons++;
- if (input.state() != net_input_t::INP_STATE_PASSIVE)
- m_active++;
-}
-
-// ----------------------------------------------------------------------------------------
// netlist_mame_device
// ----------------------------------------------------------------------------------------
@@ -1104,7 +59,12 @@ const device_type NETLIST = &device_creator<netlist_mame_device>;
netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, NETLIST, "netlist", tag, owner, clock, "netlist_mame", __FILE__),
- device_execute_interface(mconfig, *this)
+ device_execute_interface(mconfig, *this),
+ m_device_start_list(100),
+ m_netlist(NULL),
+ m_setup(NULL),
+ m_setup_func(NULL),
+ m_icount(0)
{
}
@@ -1198,6 +158,6 @@ ATTR_HOT void netlist_mame_device::execute_run()
//if (check_debugger)
// debugger_instruction_hook(this, 0); //m_pc);
- m_netlist->process_list(m_icount);
+ m_netlist->process_queue(m_icount);
}
diff --git a/src/emu/machine/netlist.h b/src/emu/machine/netlist.h
index 70b788c8f5f..dde09639b5f 100644
--- a/src/emu/machine/netlist.h
+++ b/src/emu/machine/netlist.h
@@ -51,140 +51,9 @@
#include "emu.h"
#include "tagmap.h"
+#include "netlist/nl_base.h"
+#include "netlist/nl_setup.h"
-//============================================================
-// SETUP
-//============================================================
-
-#define USE_DELEGATES (0)
-/*
- * The next options needs -Wno-pmf-conversions to compile and gcc
- * This is intended for non-mame usage.
- *
- */
-#define USE_PMFDELEGATES (0)
-
-// Next if enabled adds 20% performance ... but is not guaranteed to be absolutely timing correct.
-#define USE_DEACTIVE_DEVICE (0)
-
-#define OUTPUT_MAX_CONNECTIONS (48)
-
-// Use nano-second resolution - Sufficient for now
-#define NETLIST_INTERNAL_RES (U64(1000000000))
-#define NETLIST_DIV_BITS (0)
-//#define NETLIST_INTERNAL_RES (U64(1000000000000))
-//#define NETLIST_DIV_BITS (10)
-#define NETLIST_DIV (U64(1) << NETLIST_DIV_BITS)
-#define NETLIST_MASK (NETLIST_DIV-1)
-#define NETLIST_CLOCK (NETLIST_INTERNAL_RES / NETLIST_DIV)
-
-#define NLTIME_FROM_NS(_t) netlist_time::from_nsec(_t)
-#define NLTIME_FROM_US(_t) netlist_time::from_usec(_t)
-#define NLTIME_FROM_MS(_t) netlist_time::from_msec(_t)
-#define NLTIME_IMMEDIATE netlist_time::from_nsec(0)
-
-#define NETLIST_HIGHIMP_V (1.23456e20) /* some voltage we should never see */
-
-
-//============================================================
-// MACROS / inline netlist definitions
-//============================================================
-
-#define NET_ALIAS(_alias, _name) \
- netlist.register_alias(# _alias, # _name);
-#define NET_NEW(_type , _name) net_create_device_by_classname(# _type, netlist, # _name)
-
-#define NET_REGISTER_DEV(_type, _name) \
- netlist.register_dev(NET_NEW(_type, _name));
-#define NET_REMOVE_DEV(_name) \
- netlist.remove_dev(# _name);
-#define NET_REGISTER_SIGNAL(_type, _name) \
- NET_REGISTER_DEV(_type ## _ ## sig, _name)
-#define NET_CONNECT(_name, _input, _output) \
- netlist.register_link(# _name "." # _input, # _output);
-#define NETDEV_PARAM(_name, _val) \
- netlist.find_param(# _name).initial(_val);
-
-#define NETLIST_NAME(_name) netlist ## _ ## _name
-
-#define NETLIST_START(_name) \
-ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \
-{
-
-#define NETLIST_END }
-
-#define NETLIST_INCLUDE(_name) \
- NETLIST_NAME(_name)(netlist);
-
-#define NETLIST_MEMREGION(_name) \
- netlist.parse((char *)downcast<netlist_t &>(netlist.netlist()).machine().root_device().memregion(_name)->base());
-
-#if defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
-#if !defined(__ppc__) && !defined (__PPC__) && !defined(__ppc64__) && !defined(__PPC64__)
-#define ATTR_ALIGN __attribute__ ((aligned(128)))
-#else
-#define ATTR_ALIGN
-#endif
-#else
-#define ATTR_ALIGN
-#endif
-
-//============================================================
-// MACROS / netlist devices
-//============================================================
-
-#define NETLIB_UPDATE(_chip) ATTR_HOT ATTR_ALIGN void _chip :: update(void)
-#define NETLIB_START(_chip) ATTR_COLD void _chip :: start(void)
-//#define NETLIB_CONSTRUCTOR(_chip) ATTR_COLD _chip :: _chip (netlist_setup_t &setup, const char *name)
-// : net_device_t(setup, name)
-
-#define NETLIB_UPDATE_PARAM(_chip) ATTR_HOT ATTR_ALIGN void _chip :: update_param(void)
-#define NETLIB_FUNC_VOID(_chip, _name, _params) ATTR_HOT ATTR_ALIGN inline void _chip :: _name _params
-
-#define NETLIB_SIGNAL(_name, _num_input, _check, _invert) \
- class _name : public net_signal_t<_num_input, _check, _invert> \
- { \
- public: \
- _name () \
- : net_signal_t<_num_input, _check, _invert>() { } \
- };
-
-#define NETLIB_DEVICE(_name, _priv) \
- class _name : public net_device_t \
- { \
- public: \
- _name () \
- : net_device_t() { } \
- protected: \
- ATTR_HOT void update(); \
- ATTR_HOT void start(); \
- _priv \
- }
-
-#define NETLIB_SUBDEVICE(_name, _priv) \
- class _name : public net_core_device_t \
- { \
- public: \
- _name () \
- : net_core_device_t() \
- { } \
- /*protected:*/ \
- ATTR_HOT void update(); \
- _priv \
- }
-
-#define NETLIB_DEVICE_WITH_PARAMS(_name, _priv) \
- class _name : public net_device_t \
- { \
- public: \
- _name () \
- : net_device_t() { } \
- ATTR_HOT void update_param(); \
- ATTR_HOT void update(); \
- ATTR_HOT void start(); \
- /* protected: */ \
- _priv \
- }
// MAME specific
#define MCFG_NETLIST_ADD(_tag, _setup ) \
@@ -196,1240 +65,9 @@ ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \
#define MCFG_NETLIST_SETUP(_setup) \
netlist_mame_device::static_set_constructor(*device, NETLIST_NAME(_setup));
-// ----------------------------------------------------------------------------------------
-// Type definitions
-// ----------------------------------------------------------------------------------------
-
-class net_core_device_t;
-
-#if USE_DELEGATES
-#if USE_PMFDELEGATES
-typedef void (*net_update_delegate)(net_core_device_t *);
-#else
-typedef delegate<void ()> net_update_delegate;
-#endif
-#endif
-
-typedef UINT8 net_sig_t;
-
-
-typedef delegate<void (const double)> net_output_delegate;
-
-// ----------------------------------------------------------------------------------------
-// Support classes
-// ----------------------------------------------------------------------------------------
-
-struct netlist_time
-{
-public:
-
- typedef UINT64 INTERNALTYPE;
-
- static const INTERNALTYPE RESOLUTION = NETLIST_INTERNAL_RES;
-
- inline netlist_time() : m_time(0) {}
-
- friend inline const netlist_time operator-(const netlist_time &left, const netlist_time &right);
- friend inline const netlist_time operator+(const netlist_time &left, const netlist_time &right);
- friend inline const netlist_time operator*(const netlist_time &left, const UINT32 factor);
- friend inline bool operator>(const netlist_time &left, const netlist_time &right);
- friend inline bool operator<(const netlist_time &left, const netlist_time &right);
- friend inline bool operator>=(const netlist_time &left, const netlist_time &right);
- friend inline bool operator<=(const netlist_time &left, const netlist_time &right);
-
- ATTR_HOT inline const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
- ATTR_HOT inline const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
-
- ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
-
- ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
- ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }
- ATTR_HOT static inline const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); }
- ATTR_HOT static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
- ATTR_HOT static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
-
- static const netlist_time zero;
-
-protected:
-
- ATTR_HOT inline netlist_time(const INTERNALTYPE val) : m_time(val) {}
-
- INTERNALTYPE m_time;
-};
-
-ATTR_HOT inline const netlist_time operator-(const netlist_time &left, const netlist_time &right)
-{
- return netlist_time::from_raw(left.m_time - right.m_time);
-}
-
-ATTR_HOT inline const netlist_time operator*(const netlist_time &left, const UINT32 factor)
-{
- return netlist_time::from_raw(left.m_time * factor);
-}
-
-ATTR_HOT inline const netlist_time operator+(const netlist_time &left, const netlist_time &right)
-{
- return netlist_time::from_raw(left.m_time + right.m_time);
-}
-
-ATTR_HOT inline bool operator<(const netlist_time &left, const netlist_time &right)
-{
- return (left.m_time < right.m_time);
-}
-
-ATTR_HOT inline bool operator>(const netlist_time &left, const netlist_time &right)
-{
- return (left.m_time > right.m_time);
-}
-
-ATTR_HOT inline bool operator<=(const netlist_time &left, const netlist_time &right)
-{
- return (left.m_time <= right.m_time);
-}
-
-ATTR_HOT inline bool operator>=(const netlist_time &left, const netlist_time &right)
-{
- return (left.m_time >= right.m_time);
-}
-
-template <class _ListClass, int _NumElements>
-struct net_list_t
-{
-public:
- net_list_t()
- {
- m_list = global_alloc_array(_ListClass, _NumElements);
- m_ptr = m_list;
- m_ptr--;
- }
- ~net_list_t()
- {
- global_free(m_list);
- }
- ATTR_HOT inline void add(const _ListClass elem)
- {
- assert(m_ptr-m_list <= _NumElements - 1);
-
- *(++m_ptr) = elem;
- }
- ATTR_HOT inline _ListClass *first() { return &m_list[0]; }
- ATTR_HOT inline _ListClass *last() { return m_ptr; }
- ATTR_HOT inline _ListClass *item(int i) { return &m_list[i]; }
- inline int count() const { return m_ptr - m_list + 1; }
- ATTR_HOT inline bool empty() { return (m_ptr < m_list); }
- ATTR_HOT inline void clear() { m_ptr = m_list - 1; }
-private:
- _ListClass * m_ptr;
- _ListClass * m_list;
- //_ListClass m_list[_NumElements];
-};
-
-// ----------------------------------------------------------------------------------------
-// forward definitions
-// ----------------------------------------------------------------------------------------
-
-class net_output_t;
-class net_core_device_t;
-class net_param_t;
-class netlist_setup_t;
-class netlist_base_t;
-
-// ----------------------------------------------------------------------------------------
-// timed queue
-// ----------------------------------------------------------------------------------------
-
-//#define SIZE ((1 << _Size) - 1)
-
-class netlist_timed_queue
-{
-public:
-
- static const int SIZE = ((1 << 11) - 1);
-
- typedef net_output_t element_t;
-
- struct entry_t
- {
- public:
- inline entry_t()
- : m_time(netlist_time::zero), m_object(NULL) {}
- inline entry_t(const netlist_time atime, element_t &elem) : m_time(atime), m_object(&elem) {}
- ATTR_HOT inline const netlist_time &time() const { return m_time; }
- ATTR_HOT inline element_t & object() const { return *m_object; }
- private:
- netlist_time m_time;
- element_t *m_object;
- };
-
- netlist_timed_queue()
- {
- //m_list = global_alloc_array(entry_t, SIZE);
- clear();
- }
-
- ATTR_HOT inline bool is_empty() const { return (m_end == &m_list[0]); }
- ATTR_HOT inline bool is_not_empty() const { return (m_end > &m_list[0]); }
-
- ATTR_HOT ATTR_ALIGN inline void push(const entry_t &e)
- {
- if (is_empty() || (e.time() <= (m_end - 1)->time()))
- {
- *m_end++ = e;
- //inc_stat(m_prof_end);
- }
- else
- {
- entry_t * RESTRICT i = m_end++;
- while ((i>&m_list[0]) && (e.time() > (i-1)->time()) )
- {
- i--;
- *(i+1) = *i;
- //inc_stat(m_prof_sortmove);
- }
- *i = e;
- //inc_stat(m_prof_sort);
- }
- assert(m_end - m_list < SIZE);
- }
-
- ATTR_HOT inline const entry_t pop()
- {
- return *--m_end;
- }
-
- ATTR_HOT inline const entry_t peek() const
- {
- return *(m_end-1);
- }
-
- ATTR_COLD void clear()
- {
- m_end = &m_list[0];
- }
- // profiling
-
- INT32 m_prof_start;
- INT32 m_prof_end;
- INT32 m_prof_sortmove;
- INT32 m_prof_sort;
-private:
-
- entry_t * RESTRICT m_end;
- //entry_t *m_list;
- entry_t m_list[SIZE + 1];
-
-};
-
-// ----------------------------------------------------------------------------------------
-// net_object_t
-// ----------------------------------------------------------------------------------------
-
-class net_object_t
-{
-public:
- enum type_t {
- INPUT = 0,
- OUTPUT = 1,
- DEVICE = 2,
- PARAM = 3,
- TERMINAL = 4,
- NET_ANALOG = 5,
- NET_DIGITAL = 6,
- TYPE_MASK = 0x0f,
- SIGNAL_DIGITAL = 0x00,
- SIGNAL_ANALOG = 0x10,
- SIGNAL_MASK = 0x10,
- };
-
- net_object_t(int atype)
- : m_objtype(atype) {}
-
- virtual ~net_object_t() {}
-
- ATTR_HOT inline int object_type() const { return m_objtype; }
- ATTR_HOT inline int object_type(const UINT32 mask) const { return m_objtype & mask; }
-
-private:
- int m_objtype;
-};
-
-// ----------------------------------------------------------------------------------------
-// net_terminal_t
-// ----------------------------------------------------------------------------------------
-
-class net_terminal_t : public net_object_t
-{
-public:
-
- net_terminal_t(const int atype)
- : net_object_t(atype)
- , m_netdev(NULL)
- , m_netlist(NULL)
- {}
-
- ATTR_COLD void init_terminal(net_core_device_t *dev);
- ATTR_HOT inline net_core_device_t * RESTRICT netdev() const { return m_netdev; }
- ATTR_HOT inline netlist_base_t * RESTRICT netlist() const { return m_netlist; }
-
-private:
- net_core_device_t * RESTRICT m_netdev;
- netlist_base_t * RESTRICT m_netlist;
-};
-
-
-// ----------------------------------------------------------------------------------------
-// net_input_t
-// ----------------------------------------------------------------------------------------
-
-class net_input_t : public net_terminal_t
-{
-public:
-
- enum net_input_state {
- INP_STATE_PASSIVE = 0,
- INP_STATE_ACTIVE = 1,
- INP_STATE_HL = 2,
- INP_STATE_LH = 4,
- };
-
- ATTR_COLD net_input_t(const int atype)
- : net_terminal_t(atype)
- , m_low_thresh_V(0)
- , m_high_thresh_V(0)
- , m_state(INP_STATE_ACTIVE)
- , m_output(NULL)
- {}
-
- ATTR_COLD void init_input(net_core_device_t *dev, net_input_state astate = INP_STATE_ACTIVE);
-
- ATTR_HOT inline net_output_t * RESTRICT output() const { return m_output; }
- ATTR_HOT inline const bool is_state(const net_input_state astate) const { return (m_state == astate); }
- ATTR_HOT inline const net_input_state state() const { return m_state; }
-
- ATTR_COLD void set_output(net_output_t &aout) { m_output = &aout; }
- ATTR_HOT inline void inactivate();
- ATTR_HOT inline void activate();
- ATTR_HOT inline void activate_hl();
- ATTR_HOT inline void activate_lh();
-
- double m_low_thresh_V;
- double m_high_thresh_V;
-
-private:
- net_input_state m_state;
- net_output_t * RESTRICT m_output;
-};
-
-class logic_input_t : public net_input_t
-{
-public:
- logic_input_t()
- : net_input_t(INPUT | SIGNAL_DIGITAL)
- {
- // default to TTL
- m_low_thresh_V = 0.8;
- m_high_thresh_V = 2.0;
- }
-
- ATTR_HOT inline const net_sig_t Q() const;
- ATTR_HOT inline const net_sig_t last_Q() const;
-
- ATTR_COLD inline void set_thresholds(const double low, const double high)
- {
- m_low_thresh_V = low;
- m_high_thresh_V = high;
- }
-};
-
-class ttl_input_t : public logic_input_t
-{
-public:
- ttl_input_t()
- : logic_input_t() { set_thresholds(0.8 , 2.0); }
-};
-
-class analog_input_t : public net_input_t
-{
-public:
- analog_input_t()
- : net_input_t(INPUT | SIGNAL_ANALOG) { }
-
- ATTR_HOT inline const bool is_highz() const;
- ATTR_HOT inline const double Q_Analog() const;
-};
-
-//#define INPVAL(_x) (_x).Q()
-
-// ----------------------------------------------------------------------------------------
-// net_output_t
-// ----------------------------------------------------------------------------------------
-
-class netdev_mainclock;
-
-class net_output_t : public net_terminal_t
-{
-public:
-
- net_output_t(int atype);
-
- friend const net_sig_t logic_input_t::Q() const;
- friend const double analog_input_t::Q_Analog() const;
- friend const bool analog_input_t::is_highz() const;
- friend class netdev_mainclock;
-
- ATTR_HOT inline const net_sig_t last_Q() const { return m_last_Q; }
- ATTR_HOT inline const net_sig_t new_Q() const { return m_new_Q; }
-
- ATTR_COLD void register_con(net_input_t &inp);
-
- ATTR_HOT inline void update_devs();
-
- ATTR_HOT inline void inc_active();
- ATTR_HOT inline void dec_active();
-
- ATTR_HOT inline const int active_count() const { return m_active; }
- ATTR_HOT inline const netlist_time time() const { return m_time; }
- ATTR_HOT inline void set_time(const netlist_time ntime) { m_time = ntime; }
-
- double m_low_V;
- double m_high_V;
-
-protected:
-
- /* prohibit use in device functions
- * current (pending) state can be inquired using new_Q()
- */
- ATTR_HOT inline const net_sig_t Q() const
- {
- assert(object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
- return m_Q;
- }
- ATTR_HOT inline const double Q_Analog() const
- {
- assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG);
- return m_Q_analog;
- }
-
- ATTR_HOT inline void push_to_queue(const netlist_time &delay);
-
- net_sig_t m_last_Q;
- net_sig_t m_Q;
- net_sig_t m_new_Q;
-
- double m_Q_analog;
- double m_new_Q_analog;
-
- UINT32 m_num_cons;
-private:
- ATTR_HOT void update_dev(const net_input_t *inp, const UINT32 mask);
-
- netlist_time m_time;
-
- INT32 m_active;
-
- UINT32 m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */
-
- net_input_t * RESTRICT m_cons[OUTPUT_MAX_CONNECTIONS];
-};
-
-
-class logic_output_t : public net_output_t
-{
-public:
-
- logic_output_t()
- : net_output_t(OUTPUT | SIGNAL_DIGITAL)
- {
- // Default to TTL
- m_low_V = 0.1; // these depend on sinked/sourced current. Values should be suitable for typical applications.
- m_high_V = 4.8;
- }
-
- ATTR_COLD void initial(const net_sig_t val) { m_Q = val; m_new_Q = val; m_last_Q = !val; }
-
- ATTR_HOT inline void set_Q(const net_sig_t newQ, const netlist_time &delay)
- {
- if (EXPECTED(newQ != m_new_Q))
- {
- m_new_Q = newQ;
- if (m_num_cons)
- push_to_queue(delay);
- }
- }
-
- ATTR_COLD inline void set_levels(const double low, const double high)
- {
- m_low_V = low;
- m_high_V = high;
- }
-};
-
-class ttl_output_t : public logic_output_t
-{
-public:
-
- ttl_output_t()
- : logic_output_t()
- { set_levels(0.3, 3.4); }
-
-};
-
-class analog_output_t : public net_output_t
-{
-public:
-
- analog_output_t()
- : net_output_t(OUTPUT | SIGNAL_ANALOG) { }
-
- ATTR_COLD void initial(const double val) { m_Q_analog = val; m_new_Q_analog = val; }
-
- ATTR_HOT inline void set_Q(const double newQ, const netlist_time &delay)
- {
- if (newQ != m_new_Q_analog)
- {
- m_new_Q_analog = newQ;
- push_to_queue(delay);
- }
- }
-
-};
-
-// ----------------------------------------------------------------------------------------
-// net_device_t
-// ----------------------------------------------------------------------------------------
-
-class net_core_device_t : public net_object_t
-{
-public:
-
- net_core_device_t();
-
- virtual ~net_core_device_t();
-
- ATTR_COLD virtual void init(netlist_setup_t &setup, const astring &name);
-
- ATTR_COLD const astring &name() const { return m_name; }
-
- ATTR_HOT virtual void update_param() {}
-
- ATTR_HOT const net_sig_t INPLOGIC_PASSIVE(logic_input_t &inp);
-
- ATTR_HOT inline void update_dev()
- {
-#if USE_DELEGATES
-#if USE_PMFDELEGATES
- static_update(this);
-#else
- static_update();
-#endif
-#else
- update();
-#endif
- }
-
- ATTR_HOT inline const net_sig_t INPLOGIC(const logic_input_t &inp) const
- {
- assert(inp.state() != net_input_t::INP_STATE_PASSIVE);
- return inp.Q();
- }
-
- ATTR_HOT inline void OUTLOGIC(logic_output_t &out, const net_sig_t val, const netlist_time &delay)
- {
- out.set_Q(val, delay);
- }
-
- ATTR_HOT inline bool INP_HL(const logic_input_t &inp) const
- {
- return ((inp.last_Q() & !inp.Q()) == 1);
- }
-
- ATTR_HOT inline bool INP_LH(const logic_input_t &inp) const
- {
- return ((!inp.last_Q() & inp.Q()) == 1);
- }
-
- ATTR_HOT inline const double INPANALOG(const analog_input_t &inp) const { return inp.Q_Analog(); }
-
- ATTR_HOT inline void OUTANALOG(analog_output_t &out, const double val, const netlist_time &delay)
- {
- out.set_Q(val, delay);
- }
-
- ATTR_HOT inline netlist_base_t *netlist() const { return m_netlist; }
-
- ATTR_HOT virtual void inc_active() { }
-
- ATTR_HOT virtual void dec_active() { /*printf("DeActivate %s\n", m_name);*/ }
-
- /* stats */
- osd_ticks_t total_time;
- INT32 stat_count;
-
-#if USE_DELEGATES
- net_update_delegate static_update;
-#endif
-
-protected:
-
- ATTR_HOT virtual void update() { }
- ATTR_HOT virtual void start() { }
-
- netlist_base_t * RESTRICT m_netlist;
-
-private:
-
- astring m_name;
-};
-
-
-class net_device_t : public net_core_device_t
-{
-public:
-
- net_device_t();
-
- virtual ~net_device_t();
-
- ATTR_COLD virtual void init(netlist_setup_t &setup, const astring &name);
-
- ATTR_COLD const netlist_setup_t *setup() const { return m_setup; }
-
- ATTR_COLD bool variable_input_count() { return m_variable_input_count; }
-
- ATTR_COLD void register_sub(net_core_device_t &dev, const astring &name);
-
- ATTR_COLD void register_output(const astring &name, net_output_t &out);
- ATTR_COLD void register_output(net_core_device_t &dev, const astring &name, net_output_t &out);
-
- ATTR_COLD void register_input(const astring &name, net_input_t &in, net_input_t::net_input_state state = net_input_t::INP_STATE_ACTIVE);
- ATTR_COLD void register_input(net_core_device_t &dev, const astring &name, net_input_t &in, net_input_t::net_input_state state = net_input_t::INP_STATE_ACTIVE);
-
- ATTR_COLD void register_link_internal(net_input_t &in, net_output_t &out, net_input_t::net_input_state aState);
- ATTR_COLD void register_link_internal(net_core_device_t &dev, net_input_t &in, net_output_t &out, net_input_t::net_input_state aState);
-
- net_list_t<astring, 20> m_inputs;
-
-protected:
-
- virtual void update() { }
- ATTR_HOT virtual void start() { }
-
- ATTR_COLD void register_param(const astring &sname, net_param_t &param, const double initialVal = 0.0);
- ATTR_COLD void register_param(net_core_device_t &dev, const astring &sname, net_param_t &param, const double initialVal = 0.0);
-
- netlist_setup_t *m_setup;
- bool m_variable_input_count;
-
-private:
-};
-
-class net_param_t
-{
-public:
- net_param_t()
- : m_param(0.0)
- , m_netdev(NULL)
- { }
-
- inline void setTo(const double param) { m_param = param; m_netdev->update_param(); }
- inline void setTo(const int param) { m_param = param; m_netdev->update_param(); }
- inline void initial(const double val) { m_param = val; }
- inline void initial(const int val) { m_param = val; }
-
- ATTR_HOT inline double Value() const { return m_param; }
- ATTR_HOT inline int ValueInt() const { return (int) m_param; }
-
- ATTR_HOT inline net_core_device_t &netdev() const { return *m_netdev; }
- void set_netdev(net_core_device_t &dev) { m_netdev = &dev; }
-
-private:
-
- double m_param;
- net_core_device_t *m_netdev;
-};
-
-// ----------------------------------------------------------------------------------------
-// net_signal_t
-// ----------------------------------------------------------------------------------------
-
-template <int _numdev>
-class net_signal_base_t : public net_device_t
-{
-public:
- net_signal_base_t()
- : net_device_t(), m_active(1) { }
-
- ATTR_COLD void start()
- {
- const char *sIN[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" };
-
- register_output("Q", m_Q);
- for (int i=0; i < _numdev; i++)
- {
- register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
- }
- m_Q.initial(1);
- }
-
-#if (USE_DEACTIVE_DEVICE)
- ATTR_HOT void inc_active()
- {
- if (m_active == 0)
- {
- update();
- }
- m_active++;
- }
-
- ATTR_HOT void dec_active()
- {
- m_active--;
- if (m_active == 0)
- {
- for (int i = 0; i< _numdev; i++)
- m_i[i].inactivate();
- }
- }
-#endif
-
-public:
- ttl_input_t m_i[_numdev];
- ttl_output_t m_Q;
- INT8 m_active;
-};
-
-
-template <int _numdev, int _check, int _invert>
-class net_signal_t : public net_device_t
-{
-public:
- net_signal_t()
- : net_device_t(), m_active(1) { }
-
- ATTR_COLD void start()
- {
- const char *sIN[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" };
-
- register_output("Q", m_Q);
- for (int i=0; i < _numdev; i++)
- {
- register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
- }
- m_Q.initial(1);
- }
-
- #if (USE_DEACTIVE_DEVICE)
- ATTR_HOT void inc_active()
- {
- if (m_active == 0)
- {
- update();
- }
- m_active++;
- }
-
- ATTR_HOT void dec_active()
- {
- m_active--;
- if (m_active == 0)
- {
- for (int i = 0; i< _numdev; i++)
- m_i[i].inactivate();
- }
- }
- #endif
-
- virtual void update()
- {
- static const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
- int pos = -1;
-
- for (int i = 0; i< _numdev; i++)
- {
- this->m_i[i].activate();
- if (INPLOGIC(this->m_i[i]) == _check)
- {
- OUTLOGIC(this->m_Q, _check ^ (1 ^ _invert), times[_check]);// ? 15000 : 22000);
- pos = i;
- break;
- }
- }
- if (pos >= 0)
- {
- for (int i = 0; i < _numdev; i++)
- if (i != pos)
- this->m_i[i].inactivate();
- } else
- OUTLOGIC(this->m_Q,_check ^ (_invert), times[1-_check]);// ? 22000 : 15000);
- }
-
-public:
- ttl_input_t m_i[_numdev];
- ttl_output_t m_Q;
- INT8 m_active;
-};
-
-#if 1
-template <int _check, int _invert>
-class xx_net_signal_t: public net_device_t
-{
-public:
- xx_net_signal_t()
- : net_device_t(), m_active(1) { }
-
- ATTR_COLD void start()
- {
- const char *sIN[2] = { "I1", "I2" };
-
- register_output("Q", m_Q);
- for (int i=0; i < 2; i++)
- {
- register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
- }
- m_Q.initial(1);
- }
-
- #if (USE_DEACTIVE_DEVICE)
- ATTR_HOT void inc_active()
- {
- if (m_active == 0)
- {
- update();
- }
- m_active++;
- }
-
- ATTR_HOT void dec_active()
- {
- m_active--;
- if (m_active == 0)
- {
- m_i[0].inactivate();
- m_i[1].inactivate();
- }
- }
- #endif
-
-
- ATTR_HOT ATTR_ALIGN void update()
- {
- const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
-
- int res = _invert ^ 1 ^_check;
- m_i[0].activate();
- m_i[1].activate();
- if (INPLOGIC(m_i[0]) ^ _check)
- {
- if (INPLOGIC(m_i[1]) ^ _check)
- {
- res = _invert ^ _check;
- }
- else
- m_i[0].inactivate();
- } else {
- if (INPLOGIC(m_i[1]) ^ _check)
- m_i[1].inactivate();
- }
- OUTLOGIC(m_Q, res, times[(res & 1) ^ 1]);// ? 22000 : 15000);
- }
-
-public:
- ttl_input_t m_i[2];
- ttl_output_t m_Q;
- INT8 m_active;
-
-};
-
-template <int _check, int _invert>
-class net_signal_t<2, _check, _invert> : public xx_net_signal_t<_check, _invert>
-{
-public:
- net_signal_t()
- : xx_net_signal_t<_check, _invert>() { }
-};
-
-// The following did not improve performance
-#if 0
-
-template <UINT8 _check, UINT8 _invert>
-class net_signal_t<3, _check, _invert> : public net_device_t
-{
-public:
- net_signal_t() : net_device_t(), m_active(1) { }
-
- ATTR_COLD void start()
- {
- const char *sIN[3] = { "I1", "I2", "I3" };
-
- register_output("Q", m_Q);
- for (int i=0; i < 3; i++)
- {
- register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
- }
- m_Q.initial(1);
- }
-
- ATTR_HOT ATTR_ALIGN void update()
- {
- const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
- //const UINT8 res_tab[4] = {1, 1, 1, 0 };
- //const UINT8 ai1[4] = {0, 1, 0, 0 };
- //const UINT8 ai2[4] = {1, 0, 1, 0 };
-
- UINT8 res = _invert ^ 1 ^_check;
- m_i[0].activate();
- if (INPLOGIC(m_i[0]) ^ _check)
- {
- m_i[1].activate();
- if (INPLOGIC(m_i[1]) ^ _check)
- {
- m_i[2].activate();
- if (INPLOGIC(m_i[2]) ^ _check)
- {
- res = _invert ^ _check;
- }
- else
- m_i[1].inactivate();
- }
- else
- {
- if (INPLOGIC(m_i[2]) ^ _check)
- m_i[2].inactivate();
- m_i[0].inactivate();
- }
- } else {
- if (INPLOGIC(m_i[1]) ^ _check)
- m_i[1].inactivate();
- }
- OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
- }
-public:
- ttl_input_t m_i[3];
- ttl_output_t m_Q;
- INT8 m_active;
-
-};
-
-#endif
-#endif
-
-// ----------------------------------------------------------------------------------------
-// netlist_setup_t
-// ----------------------------------------------------------------------------------------
-
-class netlist_setup_t
-{
-public:
- typedef tagmap_t<net_device_t *, 393> tagmap_devices_t;
- typedef tagmap_t<const astring *, 393> tagmap_astring_t;
- typedef tagmap_t<net_param_t *, 393> tagmap_param_t;
- typedef tagmap_t<net_terminal_t *, 393> tagmap_terminal_t;
- netlist_setup_t(netlist_base_t &netlist);
- ~netlist_setup_t();
-
- netlist_base_t &netlist() { return m_netlist; }
-
- net_device_t *register_dev(net_device_t *dev);
- void remove_dev(const astring &name);
-
- void register_output(net_core_device_t &dev, net_core_device_t &upd_dev, const astring &name, net_output_t &out);
- void register_input(net_device_t &dev, net_core_device_t &upd_dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type);
- void register_alias(const astring &alias, const astring &out);
- void register_param(const astring &sname, net_param_t *param);
-
- void register_link(const astring &sin, const astring &sout);
-
- net_output_t &find_output(const astring &outname_in);
- net_param_t &find_param(const astring &param_in);
-
- void register_callback(const astring &devname, net_output_delegate delegate);
-
- void parse(char *buf);
-
- void resolve_inputs(void);
- void step_devices_once(void);
-
- /* not ideal, but needed for save_state */
- tagmap_terminal_t m_terminals;
-
- void print_stats();
-
-protected:
-
-private:
-
- netlist_base_t &m_netlist;
-
- tagmap_devices_t m_devices;
- tagmap_astring_t m_alias;
- //tagmap_input_t m_inputs;
- tagmap_param_t m_params;
- tagmap_astring_t m_links;
-
- net_output_t *find_output_exact(const astring &outname_in);
- const astring &resolve_alias(const astring &name) const;
-};
-
-class netdev_mainclock;
-
-// ----------------------------------------------------------------------------------------
-// netlist_base_t
-// ----------------------------------------------------------------------------------------
-
-class netlist_base_t
-{
-public:
-
- typedef netlist_timed_queue queue_t;
-
- netlist_base_t();
- virtual ~netlist_base_t();
-
- void set_clock_freq(UINT64 clockfreq);
-
- ATTR_HOT inline void push_to_queue(net_output_t &out, const netlist_time &attime)
- {
- m_queue.push(queue_t::entry_t(attime, out));
- }
-
- ATTR_HOT void process_list(INT32 &atime);
-
- ATTR_HOT inline const netlist_time &time() const { return m_time_ps; }
-
- ATTR_COLD void set_mainclock_dev(netdev_mainclock *dev);
-
- ATTR_COLD void reset();
-
- // FIXME: should'nt be public
- queue_t m_queue;
-
-protected:
- // performance
- int m_perf_out_processed;
- int m_perf_inp_processed;
- int m_perf_inp_active;
-
-private:
- netdev_mainclock *m_mainclock;
- netlist_time m_time_ps;
- UINT32 m_rem;
- UINT32 m_div;
-
-
- ATTR_HOT void update_time(const netlist_time t, INT32 &atime);
-
-};
-
-// ----------------------------------------------------------------------------------------
-// netdev_mainclock
-// ----------------------------------------------------------------------------------------
-
-NETLIB_DEVICE_WITH_PARAMS(netdev_mainclock,
- ttl_output_t m_Q;
-
- net_param_t m_freq;
- netlist_time m_inc;
-
- ATTR_HOT inline static void mc_update(net_output_t &Q, const netlist_time curtime);
-);
-
-// ----------------------------------------------------------------------------------------
-// netdev_callback
-// ----------------------------------------------------------------------------------------
-
-class netdev_analog_callback : public net_device_t
-{
-public:
- netdev_analog_callback()
- : net_device_t() { }
-
- ATTR_COLD void start()
- {
- register_input("IN", m_in);
- }
-
- void register_callback(net_output_delegate callback)
- {
- m_callback = callback;
- }
-
- ATTR_HOT void update();
-
-
-private:
- analog_input_t m_in;
- net_output_delegate m_callback;
-};
-
-// ----------------------------------------------------------------------------------------
-// netdev_*_const
-// ----------------------------------------------------------------------------------------
-
-#define NETDEV_TTL_CONST(_name, _v) \
- NET_REGISTER_DEV(netdev_ttl_const, _name) \
- NETDEV_PARAM(_name.CONST, _v)
-#define NETDEV_ANALOG_CONST(_name, _v) \
- NET_REGISTER_DEV(netdev_analog_const, _name) \
- NETDEV_PARAM(_name.CONST, _v)
-
-NETLIB_DEVICE_WITH_PARAMS(netdev_ttl_const,
- ttl_output_t m_Q;
- net_param_t m_const;
-);
-
-NETLIB_DEVICE_WITH_PARAMS(netdev_analog_const,
- analog_output_t m_Q;
- net_param_t m_const;
-);
-
-// ----------------------------------------------------------------------------------------
-// Inline implementations
-// ----------------------------------------------------------------------------------------
-
-ATTR_HOT inline void net_input_t::inactivate()
-{
- if (m_state != INP_STATE_PASSIVE)
- {
- m_state = INP_STATE_PASSIVE;
- m_output->dec_active();
- }
-}
-
-ATTR_HOT inline void net_input_t::activate()
-{
- if (m_state == INP_STATE_PASSIVE)
- {
- m_output->inc_active();
- m_state = INP_STATE_ACTIVE;
- }
-}
-
-ATTR_HOT inline void net_input_t::activate_hl()
-{
- if (m_state == INP_STATE_PASSIVE)
- {
- m_output->inc_active();
- m_state = INP_STATE_HL;
- }
-}
-
-ATTR_HOT inline void net_input_t::activate_lh()
-{
- if (m_state == INP_STATE_PASSIVE)
- {
- m_output->inc_active();
- m_state = INP_STATE_LH;
- }
-}
-
-
-ATTR_HOT inline void net_output_t::push_to_queue(const netlist_time &delay)
-{
- // if (m_in_queue == 1) return; FIXME: check this at some time
- m_time = netlist()->time() + delay;
- m_in_queue = (m_active > 0) ? 1 : 0; /* queued ? */
- if (m_in_queue)
- {
- //m_in_queue = 1; /* pending */
- netlist()->push_to_queue(*this, m_time);
- }
-}
-
-ATTR_HOT inline void net_output_t::inc_active()
-{
- m_active++;
-
-#if USE_DEACTIVE_DEVICE
- if (m_active == 1 && m_in_queue > 0)
- {
- m_last_Q = m_Q;
- netdev()->inc_active();
- m_Q = m_new_Q;
- }
-#endif
-
- if (EXPECTED(m_active == 1 && m_in_queue == 0))
- {
- if (EXPECTED(m_time > netlist()->time()))
- {
- m_in_queue = 1; /* pending */
- netlist()->push_to_queue(*this, m_time);
- }
- else
- {
- m_Q = m_last_Q = m_new_Q;
- m_Q_analog = m_new_Q_analog;
- m_in_queue = 2;
- }
- }
-}
-
-ATTR_HOT inline void net_output_t::dec_active()
-{
- m_active--;
-#if (USE_DEACTIVE_DEVICE)
- if (m_active == 0)
- netdev()->dec_active();
-#endif
-}
-
-
-
-
-ATTR_HOT inline const net_sig_t logic_input_t::Q() const
-{
- return output()->Q();
-}
-
-ATTR_HOT inline const net_sig_t logic_input_t::last_Q() const
-{
- return output()->last_Q();
-}
-
-ATTR_HOT inline const double analog_input_t::Q_Analog() const
-{
- return output()->Q_Analog();
-}
-
-ATTR_HOT inline const bool analog_input_t::is_highz() const
-{
- return (output()->Q_Analog() == NETLIST_HIGHIMP_V);
-}
-
-// ----------------------------------------------------------------------------------------
-// net_dev class factory
-// ----------------------------------------------------------------------------------------
-
-class net_device_t_base_factory
-{
-public:
- virtual ~net_device_t_base_factory() {}
- virtual net_device_t *Create() const = 0;
-
- const astring &name() const { return m_name; }
- const astring &classname() const { return m_classname; }
-protected:
- astring m_name; /* device name */
- astring m_classname; /* device class name */
-};
-
-template <class C>
-class net_device_t_factory : public net_device_t_base_factory
-{
-public:
- net_device_t_factory(const astring &name, const astring &classname) { m_name = name; m_classname = classname; }
- net_device_t *Create() const
- {
- net_device_t *r = new C();
- //r->init(setup, name);
- return r;
- }
-};
-net_device_t *net_create_device_by_classname(const astring &classname, netlist_setup_t &setup, const astring &icname);
-net_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &setup, const astring &icname);
// ----------------------------------------------------------------------------------------
// MAME glue classes
@@ -1479,7 +117,7 @@ public:
netlist_setup_t &setup() { return *m_setup; }
netlist_t &netlist() { return *m_netlist; }
- net_list_t<on_device_start *, 393> m_device_start_list;
+ netlist_list_t<on_device_start *> m_device_start_list;
protected:
// device-level overrides
@@ -1526,7 +164,7 @@ class netlist_mame_device::output_finder : public object_finder_base<_NETClass>,
public:
// construction/destruction
output_finder(device_t &base, const char *tag, const char *output)
- : object_finder_base<_NETClass>(base, tag), m_output(output) { }
+ : object_finder_base<_NETClass>(base, tag), m_netlist(NULL), m_output(output) { }
// finder
virtual bool findit(bool isvalidation = false)
diff --git a/src/emu/netlist/net_lib.c b/src/emu/netlist/devices/net_lib.c
index 09015f90907..2c255469569 100644
--- a/src/emu/netlist/net_lib.c
+++ b/src/emu/netlist/devices/net_lib.c
@@ -1,3 +1,5 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
/***************************************************************************
netlib.c
@@ -46,6 +48,7 @@
****************************************************************************/
#include "net_lib.h"
+#include "nld_system.h"
NETLIB_START(netdev_logic_input)
{
@@ -219,12 +222,12 @@ NETLIB_START(nicNE555N_MSTABLE)
m_last = false;
}
-INLINE double nicNE555N_cv(nicNE555N_MSTABLE &dev)
+INLINE double nicNE555N_cv(NETLIB_NAME(nicNE555N_MSTABLE) &dev)
{
return (dev.m_CV.is_highz() ? 0.67 * dev.m_VS.Value() : dev.INPANALOG(dev.m_CV));
}
-INLINE double nicNE555N_clamp(nicNE555N_MSTABLE &dev, const double v, const double a, const double b)
+INLINE double nicNE555N_clamp(NETLIB_NAME(nicNE555N_MSTABLE) &dev, const double v, const double a, const double b)
{
double ret = v;
if (ret > dev.m_VS.Value() - a)
@@ -391,7 +394,7 @@ NETLIB_FUNC_VOID(nic7448_sub, update_outputs, (UINT8 v))
}
}
-const UINT8 nic7448_sub::tab7448[16][7] =
+const UINT8 NETLIB_NAME(nic7448_sub)::tab7448[16][7] =
{
{ 1, 1, 1, 1, 1, 1, 0 }, /* 00 - not blanked ! */
{ 0, 1, 1, 0, 0, 0, 0 }, /* 01 */
@@ -458,7 +461,7 @@ NETLIB_UPDATE(nic7450)
#endif
}
-ATTR_HOT inline void nic7474sub::newstate(const UINT8 state)
+ATTR_HOT inline void NETLIB_NAME(nic7474sub)::newstate(const UINT8 state)
{
static const netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(40) };
//printf("%s %d %d %d\n", "7474", state, Q.Q(), QQ.Q());
@@ -636,7 +639,7 @@ NETLIB_UPDATE(nic7493ff)
NETLIB_UPDATE(nic7493)
{
- net_sig_t r = INPLOGIC(m_R1) & INPLOGIC(m_R2);
+ netlist_sig_t r = INPLOGIC(m_R1) & INPLOGIC(m_R2);
if (r)
{
@@ -754,7 +757,7 @@ NETLIB_START(nic74107A)
sub.m_QQ.initial(1);
}
-ATTR_HOT inline void nic74107Asub::newstate(const net_sig_t state)
+ATTR_HOT inline void NETLIB_NAME(nic74107Asub)::newstate(const netlist_sig_t state)
{
const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
#if 1
@@ -772,7 +775,7 @@ ATTR_HOT inline void nic74107Asub::newstate(const net_sig_t state)
NETLIB_UPDATE(nic74107Asub)
{
{
- net_sig_t t = m_Q.new_Q();
+ netlist_sig_t t = m_Q.new_Q();
newstate((!t & m_Q1) | (t & m_Q2) | m_F);
if (!m_Q1)
m_clk.inactivate();
@@ -892,7 +895,7 @@ NETLIB_UPDATE(nic9316)
{
sub.m_loadq = INPLOGIC(m_LOADQ);
sub.m_ent = INPLOGIC(m_ENT);
- const net_sig_t clrq = INPLOGIC(m_CLRQ);
+ const netlist_sig_t clrq = INPLOGIC(m_CLRQ);
if ((!sub.m_loadq || (sub.m_ent & INPLOGIC(m_ENP))) & clrq)
{
@@ -964,7 +967,9 @@ NETLIB_FUNC_VOID(nic9316_sub, update_outputs, (void))
#endif
}
-#define ENTRY(_nic, _name) new net_device_t_factory< _nic >( # _name, # _nic ),
+#define xstr(s) # s
+#define ENTRY1(_nic, _name) new net_device_t_factory< _nic >( # _name, xstr(_nic) ),
+#define ENTRY(_nic, _name) ENTRY1(NETLIB_NAME(_nic), _name)
static const net_device_t_base_factory *netregistry[] =
{
@@ -979,7 +984,7 @@ static const net_device_t_base_factory *netregistry[] =
ENTRY(nicMultiSwitch, NETDEV_SWITCH2)
ENTRY(nicRSFF, NETDEV_RSFF)
ENTRY(nicMixer8, NETDEV_MIXER)
- ENTRY(nic7400, TTL_7400_NAND)
+ ENTRY(7400, TTL_7400_NAND)
ENTRY(nic7402, TTL_7402_NOR)
ENTRY(nic7404, TTL_7404_INVERT)
ENTRY(nic7410, TTL_7410_NAND)
@@ -1005,7 +1010,7 @@ static const net_device_t_base_factory *netregistry[] =
net_device_t *net_create_device_by_classname(const astring &classname, netlist_setup_t &setup, const astring &icname)
{
const net_device_t_base_factory **p = &netregistry[0];
- while (p != NULL)
+ while (*p != NULL)
{
if (strcmp((*p)->classname(), classname) == 0)
{
@@ -1022,7 +1027,7 @@ net_device_t *net_create_device_by_classname(const astring &classname, netlist_s
net_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &setup, const astring &icname)
{
const net_device_t_base_factory **p = &netregistry[0];
- while (p != NULL)
+ while (*p != NULL)
{
if (strcmp((*p)->name(), name) == 0)
{
@@ -1035,3 +1040,4 @@ net_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &se
fatalerror("Class %s required for IC %s not found!\n", name.cstr(), icname.cstr());
return NULL; // appease code analysis
}
+
diff --git a/src/emu/netlist/net_lib.h b/src/emu/netlist/devices/net_lib.h
index d48642a9bd1..2eb66ad2324 100644
--- a/src/emu/netlist/net_lib.h
+++ b/src/emu/netlist/devices/net_lib.h
@@ -1,3 +1,5 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
/***************************************************************************
net_lib.h
@@ -48,7 +50,11 @@
#ifndef NET_LIB_H
#define NET_LIB_H
-#include "machine/netlist.h"
+#include "../nl_base.h"
+#include "nld_signal.h"
+#include "nld_system.h"
+
+#include "nld_7400.h"
// this is a bad hack
#define USE_OLD7493 (0)
@@ -66,7 +72,7 @@
#define NETDEV_ANALOG_INPUT(_name) \
NET_REGISTER_DEV(netdev_analog_input, _name)
#define NETDEV_CALLBACK(_name, _IN) \
- NET_REGISTER_DEV(netdev_analog_callback, _name) \
+ NET_REGISTER_DEV(netdev_analog_callback, _name) \
NET_CONNECT(_name, IN, _IN)
#define NETDEV_SWITCH2(_name, _i1, _i2) \
NET_REGISTER_DEV(nicMultiSwitch, _name) \
@@ -90,15 +96,10 @@
// TTL Logic chips
// ----------------------------------------------------------------------------------------
-#define TTL_7400_NAND(_name, _I1, _I2) \
- NET_REGISTER_DEV(nic7400, _name) \
- NET_CONNECT(_name, I1, _I1) \
- NET_CONNECT(_name, I2, _I2)
-
#define TTL_7402_NOR(_name, _I1, _I2) \
NET_REGISTER_DEV(nic7402, _name) \
- NET_CONNECT(_name, I1, _I1) \
- NET_CONNECT(_name, I2, _I2)
+ NET_CONNECT(_name, A, _I1) \
+ NET_CONNECT(_name, B, _I2)
#define TTL_7404_INVERT(_name, _I1) \
NET_REGISTER_DEV(nic7404, _name) \
@@ -106,40 +107,40 @@
#define TTL_7410_NAND(_name, _I1, _I2, _I3) \
NET_REGISTER_DEV(nic7410, _name) \
- NET_CONNECT(_name, I1, _I1) \
- NET_CONNECT(_name, I2, _I2) \
- NET_CONNECT(_name, I3, _I3)
+ NET_CONNECT(_name, A, _I1) \
+ NET_CONNECT(_name, B, _I2) \
+ NET_CONNECT(_name, C, _I3)
#define TTL_7420_NAND(_name, _I1, _I2, _I3, _I4) \
NET_REGISTER_DEV(nic7420, _name) \
- NET_CONNECT(_name, I1, _I1) \
- NET_CONNECT(_name, I2, _I2) \
- NET_CONNECT(_name, I3, _I3) \
- NET_CONNECT(_name, I4, _I4)
+ NET_CONNECT(_name, A, _I1) \
+ NET_CONNECT(_name, B, _I2) \
+ NET_CONNECT(_name, C, _I3) \
+ NET_CONNECT(_name, D, _I4)
#define TTL_7425_NOR(_name, _I1, _I2, _I3, _I4) \
NET_REGISTER_DEV(nic7425, _name) \
- NET_CONNECT(_name, I1, _I1) \
- NET_CONNECT(_name, I2, _I2) \
- NET_CONNECT(_name, I3, _I3) \
- NET_CONNECT(_name, I4, _I4)
+ NET_CONNECT(_name, A, _I1) \
+ NET_CONNECT(_name, B, _I2) \
+ NET_CONNECT(_name, C, _I3) \
+ NET_CONNECT(_name, D, _I4)
#define TTL_7427_NOR(_name, _I1, _I2, _I3) \
NET_REGISTER_DEV(nic7427, _name) \
- NET_CONNECT(_name, I1, _I1) \
- NET_CONNECT(_name, I2, _I2) \
- NET_CONNECT(_name, I3, _I3)
+ NET_CONNECT(_name, A, _I1) \
+ NET_CONNECT(_name, B, _I2) \
+ NET_CONNECT(_name, C, _I3)
#define TTL_7430_NAND(_name, _I1, _I2, _I3, _I4, _I5, _I6, _I7, _I8) \
NET_REGISTER_DEV(nic7430, _name) \
- NET_CONNECT(_name, I1, _I1) \
- NET_CONNECT(_name, I2, _I2) \
- NET_CONNECT(_name, I3, _I3) \
- NET_CONNECT(_name, I4, _I4) \
- NET_CONNECT(_name, I5, _I5) \
- NET_CONNECT(_name, I6, _I6) \
- NET_CONNECT(_name, I7, _I7) \
- NET_CONNECT(_name, I8, _I8)
+ NET_CONNECT(_name, A, _I1) \
+ NET_CONNECT(_name, B, _I2) \
+ NET_CONNECT(_name, C, _I3) \
+ NET_CONNECT(_name, D, _I4) \
+ NET_CONNECT(_name, E, _I5) \
+ NET_CONNECT(_name, F, _I6) \
+ NET_CONNECT(_name, G, _I7) \
+ NET_CONNECT(_name, H, _I8)
#define TTL_7450_ANDORINVERT(_name, _I1, _I2, _I3, _I4) \
NET_REGISTER_DEV(nic7450, _name) \
@@ -324,13 +325,12 @@ NETLIB_DEVICE_WITH_PARAMS(nicNE555N_MSTABLE,
net_param_t m_VL;
);
-NETLIB_SIGNAL(nic7400, 2, 0, 0)
-NETLIB_SIGNAL(nic7402, 2, 1, 0)
-NETLIB_SIGNAL(nic7410, 3, 0, 0)
-NETLIB_SIGNAL(nic7420, 4, 0, 0)
-NETLIB_SIGNAL(nic7425, 4, 1, 0)
-NETLIB_SIGNAL(nic7427, 3, 1, 0)
-NETLIB_SIGNAL(nic7430, 8, 0, 0)
+NETLIB_SIGNAL(nic7402, 2, 1, 0);
+NETLIB_SIGNAL(nic7410, 3, 0, 0);
+NETLIB_SIGNAL(nic7420, 4, 0, 0);
+NETLIB_SIGNAL(nic7425, 4, 1, 0);
+NETLIB_SIGNAL(nic7427, 3, 1, 0);
+NETLIB_SIGNAL(nic7430, 8, 0, 0);
NETLIB_DEVICE(nic7404,
ttl_input_t m_I;
@@ -356,7 +356,7 @@ NETLIB_SUBDEVICE(nic7474sub,
);
NETLIB_DEVICE(nic7474,
- nic7474sub sub;
+ NETLIB_NAME(nic7474sub) sub;
ttl_input_t m_D;
ttl_input_t m_clrQ;
@@ -380,17 +380,16 @@ NETLIB_SUBDEVICE(nic74107Asub,
ttl_output_t m_Q;
ttl_output_t m_QQ;
+ netlist_sig_t m_Q1;
+ netlist_sig_t m_Q2;
+ netlist_sig_t m_F;
- net_sig_t m_Q1;
- net_sig_t m_Q2;
- net_sig_t m_F;
-
- ATTR_HOT void newstate(const net_sig_t state);
+ ATTR_HOT void newstate(const netlist_sig_t state);
);
NETLIB_DEVICE(nic74107A,
- nic74107Asub sub;
+ NETLIB_NAME(nic74107Asub) sub;
ttl_input_t m_J;
ttl_input_t m_K;
@@ -398,11 +397,11 @@ NETLIB_DEVICE(nic74107A,
);
-class nic74107 : public nic74107A
+class NETLIB_NAME(nic74107) : public NETLIB_NAME(nic74107A)
{
public:
- nic74107()
- : nic74107A() {}
+ NETLIB_NAME(nic74107) ()
+ : NETLIB_NAME(nic74107A) () {}
};
@@ -419,11 +418,12 @@ NETLIB_DEVICE(nic7493,
ttl_input_t m_R1;
ttl_input_t m_R2;
- nic7493ff A;
- nic7493ff B;
- nic7493ff C;
- nic7493ff D;
+ NETLIB_NAME(nic7493ff) A;
+ NETLIB_NAME(nic7493ff) B;
+ NETLIB_NAME(nic7493ff) C;
+ NETLIB_NAME(nic7493ff) D;
);
+
#else
NETLIB_DEVICE(nic7493,
ttl_input_t m_CLK;
@@ -469,8 +469,8 @@ NETLIB_SUBDEVICE(nic9316_sub,
ttl_input_t m_D;
UINT8 m_cnt;
- net_sig_t m_loadq;
- net_sig_t m_ent;
+ netlist_sig_t m_loadq;
+ netlist_sig_t m_ent;
ttl_output_t m_QA;
ttl_output_t m_QB;
@@ -480,7 +480,7 @@ NETLIB_SUBDEVICE(nic9316_sub,
);
NETLIB_DEVICE(nic9316,
- nic9316_sub sub;
+ NETLIB_NAME(nic9316_sub) sub;
ttl_input_t m_ENP;
ttl_input_t m_ENT;
ttl_input_t m_CLRQ;
@@ -543,7 +543,7 @@ NETLIB_SUBDEVICE(nic7448_sub,
NETLIB_DEVICE(nic7448,
- nic7448_sub sub;
+ NETLIB_NAME(nic7448_sub) sub;
ttl_input_t m_LTQ;
ttl_input_t m_BIQ;
diff --git a/src/emu/netlist/devices/nld_7400.c b/src/emu/netlist/devices/nld_7400.c
new file mode 100644
index 00000000000..977bd991dbc
--- /dev/null
+++ b/src/emu/netlist/devices/nld_7400.c
@@ -0,0 +1,6 @@
+/*
+ * nld_7400.c
+ *
+ */
+
+
diff --git a/src/emu/netlist/devices/nld_7400.h b/src/emu/netlist/devices/nld_7400.h
new file mode 100644
index 00000000000..078ceafd54b
--- /dev/null
+++ b/src/emu/netlist/devices/nld_7400.h
@@ -0,0 +1,44 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_7400.h
+ *
+ * DM7400: Quad 2-Input NAND Gates
+ *
+ * +--------------+
+ * A1 |1 ++ 14| VCC
+ * B1 |2 13| B4
+ * Y1 |3 12| A4
+ * A2 |4 7400 11| Y4
+ * B2 |5 10| B3
+ * Y2 |6 9| A3
+ * GND |7 8| Y3
+ * +--------------+
+ * __
+ * Y = AB
+ * +---+---++---+
+ * | A | B || Y |
+ * +===+===++===+
+ * | 0 | 0 || 1 |
+ * | 0 | 1 || 1 |
+ * | 1 | 0 || 1 |
+ * | 1 | 1 || 0 |
+ * +---+---++---+
+ *
+ * Naming conventions follow National Semiconductor datasheet
+ *
+ */
+
+#include "nld_signal.h"
+
+#ifndef NLD_7400_H_
+#define NLD_7400_H_
+
+#define TTL_7400_NAND(_name, _A, _B) \
+ NET_REGISTER_DEV(7400, _name) \
+ NET_CONNECT(_name, A, _A) \
+ NET_CONNECT(_name, B, _B)
+
+NETLIB_SIGNAL(7400, 2, 0, 0);
+
+#endif /* NLD_7400_H_ */
diff --git a/src/emu/netlist/devices/nld_signal.h b/src/emu/netlist/devices/nld_signal.h
new file mode 100644
index 00000000000..9119c0253a7
--- /dev/null
+++ b/src/emu/netlist/devices/nld_signal.h
@@ -0,0 +1,296 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_signal.h
+ *
+ */
+
+#ifndef NLD_SIGNAL_H_
+#define NLD_SIGNAL_H_
+
+#include "../nl_base.h"
+
+// ----------------------------------------------------------------------------------------
+// MACROS
+// ----------------------------------------------------------------------------------------
+
+#define NETLIB_SIGNAL(_name, _num_input, _check, _invert) \
+ class NETLIB_NAME(_name) : public net_signal_t<_num_input, _check, _invert> \
+ { \
+ public: \
+ ATTR_COLD NETLIB_NAME(_name) () \
+ : net_signal_t<_num_input, _check, _invert>() { } \
+ }
+
+// ----------------------------------------------------------------------------------------
+// net_signal_t
+// ----------------------------------------------------------------------------------------
+
+template <int _numdev>
+class net_signal_base_t : public net_device_t
+{
+public:
+ net_signal_base_t()
+ : net_device_t(), m_active(1) { }
+
+ ATTR_COLD void start()
+ {
+ const char *sIN[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" };
+
+ register_output("Q", m_Q);
+ for (int i=0; i < _numdev; i++)
+ {
+ register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
+ }
+ m_Q.initial(1);
+ }
+
+#if (USE_DEACTIVE_DEVICE)
+ ATTR_HOT void inc_active()
+ {
+ if (m_active == 0)
+ {
+ update();
+ }
+ m_active++;
+ }
+
+ ATTR_HOT void dec_active()
+ {
+ m_active--;
+ if (m_active == 0)
+ {
+ for (int i = 0; i< _numdev; i++)
+ m_i[i].inactivate();
+ }
+ }
+#endif
+
+public:
+ ttl_input_t m_i[_numdev];
+ ttl_output_t m_Q;
+ INT8 m_active;
+};
+
+
+template <int _numdev, int _check, int _invert>
+class net_signal_t : public net_device_t
+{
+public:
+ net_signal_t()
+ : net_device_t(), m_active(1)
+ {
+ m_Q.initial(1);
+ }
+
+ ATTR_COLD void start()
+ {
+ const char *sIN[8] = { "A", "B", "C", "D", "E", "F", "G", "H" };
+
+ register_output("Q", m_Q);
+ for (int i=0; i < _numdev; i++)
+ {
+ register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
+ }
+ }
+
+ #if (USE_DEACTIVE_DEVICE)
+ ATTR_HOT void inc_active()
+ {
+ if (m_active == 0)
+ {
+ update();
+ }
+ m_active++;
+ }
+
+ ATTR_HOT void dec_active()
+ {
+ m_active--;
+ if (m_active == 0)
+ {
+ for (int i = 0; i< _numdev; i++)
+ m_i[i].inactivate();
+ }
+ }
+ #endif
+
+ virtual void update()
+ {
+ static const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
+ int pos = -1;
+
+ for (int i = 0; i< _numdev; i++)
+ {
+ this->m_i[i].activate();
+ if (INPLOGIC(this->m_i[i]) == _check)
+ {
+ OUTLOGIC(this->m_Q, _check ^ (1 ^ _invert), times[_check]);// ? 15000 : 22000);
+ pos = i;
+ break;
+ }
+ }
+ if (pos >= 0)
+ {
+ for (int i = 0; i < _numdev; i++)
+ if (i != pos)
+ this->m_i[i].inactivate();
+ } else
+ OUTLOGIC(this->m_Q,_check ^ (_invert), times[1-_check]);// ? 22000 : 15000);
+ }
+
+public:
+ ttl_input_t m_i[_numdev];
+ ttl_output_t m_Q;
+ INT8 m_active;
+};
+
+#if 1
+template <int _check, int _invert>
+class xx_net_signal_t: public net_device_t
+{
+public:
+ xx_net_signal_t()
+ : net_device_t(), m_active(1)
+ {
+ m_Q.initial(1);
+ }
+
+ ATTR_COLD void start()
+ {
+ const char *sIN[2] = { "A", "B" };
+
+ register_output("Q", m_Q);
+ for (int i=0; i < 2; i++)
+ {
+ register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
+ }
+ }
+
+ #if (USE_DEACTIVE_DEVICE)
+ ATTR_HOT void inc_active()
+ {
+ if (m_active == 0)
+ {
+ update();
+ }
+ m_active++;
+ }
+
+ ATTR_HOT void dec_active()
+ {
+ m_active--;
+ if (m_active == 0)
+ {
+ m_i[0].inactivate();
+ m_i[1].inactivate();
+ }
+ }
+ #endif
+
+
+ ATTR_HOT ATTR_ALIGN void update()
+ {
+ const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
+
+ int res = _invert ^ 1 ^_check;
+ m_i[0].activate();
+ m_i[1].activate();
+ if (INPLOGIC(m_i[0]) ^ _check)
+ {
+ if (INPLOGIC(m_i[1]) ^ _check)
+ {
+ res = _invert ^ _check;
+ }
+ else
+ m_i[0].inactivate();
+ } else {
+ if (INPLOGIC(m_i[1]) ^ _check)
+ m_i[1].inactivate();
+ }
+ OUTLOGIC(m_Q, res, times[(res & 1) ^ 1]);// ? 22000 : 15000);
+ }
+
+public:
+ ttl_input_t m_i[2];
+ ttl_output_t m_Q;
+ INT8 m_active;
+
+};
+#endif
+
+// The following did not improve performance
+#if 0
+
+template <UINT8 _check, UINT8 _invert>
+class net_signal_t<3, _check, _invert> : public net_device_t
+{
+public:
+ net_signal_t() : net_device_t(), m_active(1) { }
+
+ ATTR_COLD void start()
+ {
+ const char *sIN[3] = { "I1", "I2", "I3" };
+
+ register_output("Q", m_Q);
+ for (int i=0; i < 3; i++)
+ {
+ register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
+ }
+ m_Q.initial(1);
+ }
+
+ ATTR_HOT ATTR_ALIGN void update()
+ {
+ const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
+ //const UINT8 res_tab[4] = {1, 1, 1, 0 };
+ //const UINT8 ai1[4] = {0, 1, 0, 0 };
+ //const UINT8 ai2[4] = {1, 0, 1, 0 };
+
+ UINT8 res = _invert ^ 1 ^_check;
+ m_i[0].activate();
+ if (INPLOGIC(m_i[0]) ^ _check)
+ {
+ m_i[1].activate();
+ if (INPLOGIC(m_i[1]) ^ _check)
+ {
+ m_i[2].activate();
+ if (INPLOGIC(m_i[2]) ^ _check)
+ {
+ res = _invert ^ _check;
+ }
+ else
+ m_i[1].inactivate();
+ }
+ else
+ {
+ if (INPLOGIC(m_i[2]) ^ _check)
+ m_i[2].inactivate();
+ m_i[0].inactivate();
+ }
+ } else {
+ if (INPLOGIC(m_i[1]) ^ _check)
+ m_i[1].inactivate();
+ }
+ OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
+ }
+public:
+ ttl_input_t m_i[3];
+ ttl_output_t m_Q;
+ INT8 m_active;
+
+};
+
+#endif
+
+
+template <int _check, int _invert>
+class net_signal_t<2, _check, _invert> : public xx_net_signal_t<_check, _invert>
+{
+public:
+ net_signal_t()
+ : xx_net_signal_t<_check, _invert>() { }
+};
+
+
+#endif /* NLD_SIGNAL_H_ */
diff --git a/src/emu/netlist/devices/nld_system.h b/src/emu/netlist/devices/nld_system.h
new file mode 100644
index 00000000000..34cc4d99bc4
--- /dev/null
+++ b/src/emu/netlist/devices/nld_system.h
@@ -0,0 +1,82 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_system.h
+ *
+ * netlist devices defined in the core
+ */
+
+#ifndef NLD_SYSTEM_H_
+#define NLD_SYSTEM_H_
+
+#include "../nl_setup.h"
+#include "../nl_base.h"
+
+// ----------------------------------------------------------------------------------------
+// Macros
+// ----------------------------------------------------------------------------------------
+
+#define NETDEV_TTL_CONST(_name, _v) \
+ NET_REGISTER_DEV(netdev_ttl_const, _name) \
+ NETDEV_PARAM(_name.CONST, _v)
+
+#define NETDEV_ANALOG_CONST(_name, _v) \
+ NET_REGISTER_DEV(netdev_analog_const, _name) \
+ NETDEV_PARAM(_name.CONST, _v)
+
+// ----------------------------------------------------------------------------------------
+// netdev_*_const
+// ----------------------------------------------------------------------------------------
+
+NETLIB_DEVICE_WITH_PARAMS(netdev_ttl_const,
+ ttl_output_t m_Q;
+ net_param_t m_const;
+);
+
+NETLIB_DEVICE_WITH_PARAMS(netdev_analog_const,
+ analog_output_t m_Q;
+ net_param_t m_const;
+);
+
+// ----------------------------------------------------------------------------------------
+// netdev_mainclock
+// ----------------------------------------------------------------------------------------
+
+NETLIB_DEVICE_WITH_PARAMS(netdev_mainclock,
+ ttl_output_t m_Q;
+
+ net_param_t m_freq;
+ netlist_time m_inc;
+
+ ATTR_HOT inline static void mc_update(net_output_t &Q, const netlist_time curtime);
+);
+
+// ----------------------------------------------------------------------------------------
+// netdev_callback
+// ----------------------------------------------------------------------------------------
+
+class NETLIB_NAME(netdev_analog_callback) : public net_device_t
+{
+public:
+ NETLIB_NAME(netdev_analog_callback)()
+ : net_device_t() { }
+
+ ATTR_COLD void start()
+ {
+ register_input("IN", m_in);
+ }
+
+ ATTR_COLD void register_callback(netlist_output_delegate callback)
+ {
+ m_callback = callback;
+ }
+
+ ATTR_HOT void update();
+
+
+private:
+ analog_input_t m_in;
+ netlist_output_delegate m_callback;
+};
+
+#endif /* NLD_SYSTEM_H_ */
diff --git a/src/emu/netlist/netlist.mak b/src/emu/netlist/netlist.mak
index afe61c3b97b..76aa56236d4 100644
--- a/src/emu/netlist/netlist.mak
+++ b/src/emu/netlist/netlist.mak
@@ -17,5 +17,9 @@ NETLISTOBJ = $(EMUOBJ)/netlist
# Core files
#-------------------------------------------------
-NETLISTOBJS+= $(NETLISTOBJ)/net_lib.o
-
+NETLISTOBJS+= \
+ $(NETLISTOBJ)/nl_setup.o \
+ $(NETLISTOBJ)/nl_base.o \
+ $(NETLISTOBJ)/nl_parser.o \
+ $(NETLISTOBJ)/devices/net_lib.o \
+
diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c
new file mode 100644
index 00000000000..a784c64e3b7
--- /dev/null
+++ b/src/emu/netlist/nl_base.c
@@ -0,0 +1,435 @@
+/*
+ * nlbase.c
+ *
+ */
+
+#include "nl_base.h"
+#include "devices/nld_system.h"
+
+
+// ----------------------------------------------------------------------------------------
+// netlist_base_t
+// ----------------------------------------------------------------------------------------
+
+netlist_base_t::netlist_base_t()
+ : m_mainclock(NULL),
+ m_time_ps(netlist_time::zero),
+ m_rem(0),
+ m_div(NETLIST_DIV)
+{
+}
+
+netlist_base_t::~netlist_base_t()
+{
+}
+
+ATTR_COLD void netlist_base_t::set_mainclock_dev(NETLIB_NAME(netdev_mainclock) *dev)
+{
+ m_mainclock = dev;
+}
+
+ATTR_COLD void netlist_base_t::reset()
+{
+ m_time_ps = netlist_time::zero;
+ m_rem = 0;
+ m_queue.clear();
+ if (m_mainclock != NULL)
+ m_mainclock->m_Q.set_time(netlist_time::zero);
+}
+
+
+void netlist_base_t::set_clock_freq(UINT64 clockfreq)
+{
+ m_div = netlist_time::from_hz(clockfreq).as_raw();
+ m_rem = 0;
+ assert_always(m_div == NETLIST_DIV, "netlist: illegal clock!");
+ NL_VERBOSE_OUT(("Setting clock %" I64FMT "d and divisor %d\n", clockfreq, m_div));
+}
+
+ATTR_HOT ATTR_ALIGN inline void netlist_base_t::update_time(const netlist_time t, INT32 &atime)
+{
+ if (NETLIST_DIV_BITS == 0)
+ {
+ const netlist_time delta = t - m_time_ps;
+ m_time_ps = t;
+ atime -= delta.as_raw();
+ } else {
+ const netlist_time delta = t - m_time_ps + netlist_time::from_raw(m_rem);
+ m_time_ps = t;
+ m_rem = delta.as_raw() & NETLIST_MASK;
+ atime -= (delta.as_raw() >> NETLIST_DIV_BITS);
+
+ // The folling is suitable for non-power of 2 m_divs ...
+ // atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
+ }
+}
+
+ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(INT32 &atime)
+{
+ if (m_mainclock == NULL)
+ {
+ while ( (atime > 0) && (m_queue.is_not_empty()))
+ {
+ const queue_t::entry_t e = m_queue.pop();
+ update_time(e.time(), atime);
+
+ if (FATAL_ERROR_AFTER_NS)
+ printf("%s\n", e.object().netdev()->name().cstr());
+
+ e.object().update_devs();
+
+ add_to_stat(m_perf_out_processed, 1);
+
+ if (FATAL_ERROR_AFTER_NS)
+ if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS))
+ fatalerror("Stopped");
+ }
+
+ if (atime > 0)
+ {
+ m_time_ps += netlist_time::from_raw(atime * m_div);
+ atime = 0;
+ }
+ } else {
+ net_output_t &mcQ = m_mainclock->m_Q;
+ const netlist_time inc = m_mainclock->m_inc;
+
+ while (atime > 0)
+ {
+ if (m_queue.is_not_empty())
+ {
+ while (m_queue.peek().time() > mcQ.time())
+ {
+ update_time(mcQ.time(), atime);
+
+ NETLIB_NAME(netdev_mainclock)::mc_update(mcQ, time() + inc);
+
+ }
+ const queue_t::entry_t e = m_queue.pop();
+
+ update_time(e.time(), atime);
+
+ e.object().update_devs();
+
+ } else {
+ update_time(mcQ.time(), atime);
+
+ NETLIB_NAME(netdev_mainclock)::mc_update(mcQ, time() + inc);
+ }
+ if (FATAL_ERROR_AFTER_NS)
+ if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS))
+ fatalerror("Stopped");
+
+ add_to_stat(m_perf_out_processed, 1);
+ }
+
+ if (atime > 0)
+ {
+ m_time_ps += netlist_time::from_raw(atime * m_div);
+ atime = 0;
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------------------
+// Default netlist elements ...
+// ----------------------------------------------------------------------------------------
+
+
+
+// ----------------------------------------------------------------------------------------
+// net_core_device_t
+// ----------------------------------------------------------------------------------------
+
+netlist_core_device_t::netlist_core_device_t()
+: net_object_t(DEVICE)
+{
+}
+
+ATTR_COLD void netlist_core_device_t::init(netlist_setup_t &setup, const astring &name)
+{
+ m_netlist = &setup.netlist();
+ m_name = name;
+
+#if USE_DELEGATES
+#if USE_PMFDELEGATES
+ void (netlist_core_device_t::* pFunc)() = &netlist_core_device_t::update;
+ static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
+#else
+ static_update = net_update_delegate(&netlist_core_device_t::update, "update", this);
+ // get the pointer to the member function
+#endif
+#endif
+
+}
+
+ATTR_COLD void net_device_t::init(netlist_setup_t &setup, const astring &name)
+{
+ netlist_core_device_t::init(setup, name);
+ m_setup = &setup;
+ start();
+}
+
+
+netlist_core_device_t::~netlist_core_device_t()
+{
+}
+
+// ----------------------------------------------------------------------------------------
+// net_device_t
+// ----------------------------------------------------------------------------------------
+
+ATTR_HOT ATTR_ALIGN const netlist_sig_t netlist_core_device_t::INPLOGIC_PASSIVE(logic_input_t &inp)
+{
+ if (inp.state() == net_input_t::INP_STATE_PASSIVE)
+ {
+ inp.activate();
+ const netlist_sig_t ret = inp.Q();
+ inp.inactivate();
+ return ret;
+ }
+ else
+ return inp.Q();
+
+}
+
+net_device_t::net_device_t()
+ : netlist_core_device_t(),
+ m_inputs(20),
+ m_setup(NULL),
+ m_variable_input_count(false)
+{
+}
+
+net_device_t::~net_device_t()
+{
+ //printf("~net_device_t\n");
+}
+
+ATTR_COLD void net_device_t::register_sub(netlist_core_device_t &dev, const astring &name)
+{
+ dev.init(*m_setup, name);
+}
+
+void net_device_t::register_output(netlist_core_device_t &dev, const astring &name, net_output_t &port)
+{
+ m_setup->register_output(*this, dev, name, port);
+}
+
+void net_device_t::register_output(const astring &name, net_output_t &port)
+{
+ m_setup->register_output(*this,*this,name, port);
+}
+
+void net_device_t::register_input(netlist_core_device_t &dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type)
+{
+ m_setup->register_input(*this, dev, name, inp, type);
+}
+
+void net_device_t::register_input(const astring &name, net_input_t &inp, net_input_t::net_input_state type)
+{
+ register_input(*this, name, inp, type);
+}
+
+void net_device_t::register_link_internal(netlist_core_device_t &dev, net_input_t &in, net_output_t &out, net_input_t::net_input_state aState)
+{
+ in.set_output(out);
+ in.init_input(&dev, aState);
+ //if (in.state() != net_input_t::INP_STATE_PASSIVE)
+ out.register_con(in);
+}
+
+void net_device_t::register_link_internal(net_input_t &in, net_output_t &out, net_input_t::net_input_state aState)
+{
+ register_link_internal(*this, in, out, aState);
+}
+
+void net_device_t::register_param(netlist_core_device_t &dev, const astring &name, net_param_t &param, double initialVal)
+{
+ param.set_netdev(dev);
+ param.initial(initialVal);
+ m_setup->register_param(name, &param);
+}
+
+void net_device_t::register_param(const astring &name, net_param_t &param, double initialVal)
+{
+ register_param(*this,name, param, initialVal);
+}
+
+// ----------------------------------------------------------------------------------------
+// net_terminal_t
+// ----------------------------------------------------------------------------------------
+
+ATTR_COLD void net_terminal_t::init_terminal(netlist_core_device_t *dev)
+{
+ m_netdev = dev;
+ m_netlist = dev->netlist();
+}
+
+// ----------------------------------------------------------------------------------------
+// net_input_t
+// ----------------------------------------------------------------------------------------
+
+ATTR_COLD void net_input_t::init_input(netlist_core_device_t *dev, net_input_state astate)
+{
+ init_terminal(dev);
+ m_state = astate;
+}
+
+// ----------------------------------------------------------------------------------------
+// net_output_t
+// ----------------------------------------------------------------------------------------
+
+net_output_t::net_output_t(int atype)
+ : net_terminal_t(atype)
+ , m_low_V(0.0)
+ , m_high_V(0.0)
+ , m_last_Q(0)
+ , m_Q(0)
+ , m_new_Q(0)
+ , m_Q_analog(0.0)
+ , m_new_Q_analog(0.0)
+ , m_num_cons(0)
+ , m_time(netlist_time::zero)
+ , m_active(0)
+ , m_in_queue(2)
+{
+ //m_cons = global_alloc_array(net_input_t *, OUTPUT_MAX_CONNECTIONS);
+}
+
+ATTR_HOT inline void net_output_t::update_dev(const net_input_t *inp, const UINT32 mask)
+{
+ if ((inp->state() & mask) != 0)
+ {
+ ATTR_UNUSED netlist_core_device_t *netdev = inp->netdev();
+ begin_timing(netdev->total_time);
+ inc_stat(netdev->stat_count);
+ netdev->update_dev();
+ end_timing(netdev()->total_time);
+ }
+}
+
+ATTR_HOT inline void net_output_t::update_devs()
+{
+
+ assert(m_num_cons != 0);
+
+ const UINT32 masks[4] = { 1, 5, 3, 1 };
+ m_Q = m_new_Q;
+ m_Q_analog = m_new_Q_analog;
+ m_in_queue = 2; /* mark as taken ... */
+
+ const UINT32 mask = masks[ (m_last_Q << 1) | m_Q ];
+
+ switch (m_num_cons)
+ {
+ case 2:
+ update_dev(m_cons[1], mask);
+ case 1:
+ update_dev(m_cons[0], mask);
+ break;
+ default:
+ {
+ for (int i=0; i < m_num_cons; i++)
+ update_dev(m_cons[i], mask);
+ }
+ break;
+ }
+
+ m_last_Q = m_Q;
+}
+
+ATTR_COLD void net_output_t::register_con(net_input_t &input)
+{
+ int i;
+ if (m_num_cons >= OUTPUT_MAX_CONNECTIONS)
+ fatalerror("Connections exceeded for %s\n", netdev()->name().cstr());
+
+ /* keep similar devices together */
+ for (i = 0; i < m_num_cons; i++)
+ if (m_cons[i]->netdev() == input.netdev())
+ break;
+
+ for (int j = m_num_cons; j > i; j--)
+ m_cons[j] = m_cons[j - 1];
+
+ m_cons[i] = &input;
+ m_num_cons++;
+ if (input.state() != net_input_t::INP_STATE_PASSIVE)
+ m_active++;
+}
+
+// ----------------------------------------------------------------------------------------
+// netdev_const
+// ----------------------------------------------------------------------------------------
+
+NETLIB_START(netdev_ttl_const)
+{
+ register_output("Q", m_Q);
+ register_param("CONST", m_const, 0.0);
+}
+
+NETLIB_UPDATE(netdev_ttl_const)
+{
+}
+
+NETLIB_UPDATE_PARAM(netdev_ttl_const)
+{
+ OUTLOGIC(m_Q, m_const.ValueInt(), NLTIME_IMMEDIATE);
+}
+
+NETLIB_START(netdev_analog_const)
+{
+ register_output("Q", m_Q);
+ register_param("CONST", m_const, 0.0);
+}
+
+NETLIB_UPDATE(netdev_analog_const)
+{
+}
+
+NETLIB_UPDATE_PARAM(netdev_analog_const)
+{
+ m_Q.initial(m_const.Value());
+}
+
+NETLIB_UPDATE(netdev_analog_callback)
+{
+ // FIXME: Remove after device cleanup
+ if (!m_callback.isnull())
+ m_callback(INPANALOG(m_in));
+}
+
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+// ----------------------------------------------------------------------------------------
+// netdev_mainclock
+// ----------------------------------------------------------------------------------------
+
+ATTR_HOT inline void NETLIB_NAME(netdev_mainclock)::mc_update(net_output_t &Q, const netlist_time curtime)
+{
+ Q.m_new_Q = !Q.m_new_Q;
+ Q.set_time(curtime);
+ Q.update_devs();
+}
+
+ATTR_COLD NETLIB_START(netdev_mainclock)
+{
+ register_output("Q", m_Q);
+
+ register_param("FREQ", m_freq, 7159000.0 * 5);
+ m_inc = netlist_time::from_hz(m_freq.Value()*2);
+
+}
+
+ATTR_HOT NETLIB_UPDATE_PARAM(netdev_mainclock)
+{
+ m_inc = netlist_time::from_hz(m_freq.Value()*2);
+}
+
+ATTR_HOT NETLIB_UPDATE(netdev_mainclock)
+{
+ // this is only called during setup ...
+ m_Q.m_new_Q = !m_Q.m_new_Q;
+ m_Q.set_time(m_netlist->time() + m_inc);
+}
diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h
new file mode 100644
index 00000000000..713e94572e2
--- /dev/null
+++ b/src/emu/netlist/nl_base.h
@@ -0,0 +1,811 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nlbase.h
+ *
+ */
+
+#ifndef NLBASE_H_
+#define NLBASE_H_
+
+#include "nl_config.h"
+#include "nl_lists.h"
+#include "nl_time.h"
+
+// ----------------------------------------------------------------------------------------
+// Type definitions
+// ----------------------------------------------------------------------------------------
+
+class netlist_core_device_t;
+
+#if USE_DELEGATES
+#if USE_PMFDELEGATES
+typedef void (*net_update_delegate)(netlist_core_device_t *);
+#else
+typedef delegate<void ()> net_update_delegate;
+#endif
+#endif
+
+//============================================================
+// MACROS / netlist devices
+//============================================================
+
+#define NETLIB_NAME(_chip) nld_ ## _chip
+
+#define NETLIB_NAME_STR_S(_s) # _s
+#define NETLIB_NAME_STR(_chip) NETLIB_NAME_STR_S(nld_ ## _chip)
+
+#define NETLIB_UPDATE(_chip) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: update(void)
+#define NETLIB_START(_chip) ATTR_COLD void NETLIB_NAME(_chip) :: start(void)
+//#define NETLIB_CONSTRUCTOR(_chip) ATTR_COLD _chip :: _chip (netlist_setup_t &setup, const char *name)
+// : net_device_t(setup, name)
+
+#define NETLIB_UPDATE_PARAM(_chip) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: update_param(void)
+#define NETLIB_FUNC_VOID(_chip, _name, _params) ATTR_HOT ATTR_ALIGN inline void NETLIB_NAME(_chip) :: _name _params
+
+#define NETLIB_DEVICE(_name, _priv) \
+ class NETLIB_NAME(_name) : public net_device_t \
+ { \
+ public: \
+ NETLIB_NAME(_name) () \
+ : net_device_t() { } \
+ protected: \
+ ATTR_HOT void update(); \
+ ATTR_HOT void start(); \
+ _priv \
+ }
+
+#define NETLIB_SUBDEVICE(_name, _priv) \
+ class NETLIB_NAME(_name) : public netlist_core_device_t \
+ { \
+ public: \
+ NETLIB_NAME(_name) () \
+ : netlist_core_device_t() \
+ { } \
+ /*protected:*/ \
+ ATTR_HOT void update(); \
+ _priv \
+ }
+
+#define NETLIB_DEVICE_WITH_PARAMS(_name, _priv) \
+ class NETLIB_NAME(_name) : public net_device_t \
+ { \
+ public: \
+ NETLIB_NAME(_name) () \
+ : net_device_t() { } \
+ ATTR_HOT void update_param(); \
+ ATTR_HOT void update(); \
+ ATTR_HOT void start(); \
+ /* protected: */ \
+ _priv \
+ }
+
+// ----------------------------------------------------------------------------------------
+// forward definitions
+// ----------------------------------------------------------------------------------------
+
+class net_output_t;
+class net_param_t;
+class netlist_setup_t;
+class netlist_base_t;
+
+
+// ----------------------------------------------------------------------------------------
+// net_object_t
+// ----------------------------------------------------------------------------------------
+
+class net_object_t
+{
+public:
+ enum type_t {
+ INPUT = 0,
+ OUTPUT = 1,
+ DEVICE = 2,
+ PARAM = 3,
+ TERMINAL = 4,
+ NET_ANALOG = 5,
+ NET_DIGITAL = 6,
+ TYPE_MASK = 0x0f,
+ SIGNAL_DIGITAL = 0x00,
+ SIGNAL_ANALOG = 0x10,
+ SIGNAL_MASK = 0x10,
+ };
+
+ net_object_t(int atype)
+ : m_objtype(atype) {}
+
+ virtual ~net_object_t() {}
+
+ ATTR_HOT inline int object_type() const { return m_objtype; }
+ ATTR_HOT inline int object_type(const UINT32 mask) const { return m_objtype & mask; }
+
+private:
+ int m_objtype;
+};
+
+// ----------------------------------------------------------------------------------------
+// net_terminal_t
+// ----------------------------------------------------------------------------------------
+
+class net_terminal_t : public net_object_t
+{
+public:
+
+ net_terminal_t(const int atype)
+ : net_object_t(atype)
+ , m_netdev(NULL)
+ , m_netlist(NULL)
+ {}
+
+ ATTR_COLD void init_terminal(netlist_core_device_t *dev);
+ ATTR_HOT inline netlist_core_device_t * RESTRICT netdev() const { return m_netdev; }
+ ATTR_HOT inline netlist_base_t * RESTRICT netlist() const { return m_netlist; }
+
+private:
+ netlist_core_device_t * RESTRICT m_netdev;
+ netlist_base_t * RESTRICT m_netlist;
+};
+
+
+// ----------------------------------------------------------------------------------------
+// net_input_t
+// ----------------------------------------------------------------------------------------
+
+class net_input_t : public net_terminal_t
+{
+public:
+
+ enum net_input_state {
+ INP_STATE_PASSIVE = 0,
+ INP_STATE_ACTIVE = 1,
+ INP_STATE_HL = 2,
+ INP_STATE_LH = 4,
+ };
+
+ ATTR_COLD net_input_t(const int atype)
+ : net_terminal_t(atype)
+ , m_low_thresh_V(0)
+ , m_high_thresh_V(0)
+ , m_state(INP_STATE_ACTIVE)
+ , m_output(NULL)
+ {}
+
+ ATTR_COLD void init_input(netlist_core_device_t *dev, net_input_state astate = INP_STATE_ACTIVE);
+
+ ATTR_HOT inline net_output_t * RESTRICT output() const { return m_output; }
+ ATTR_HOT inline const bool is_state(const net_input_state astate) const { return (m_state == astate); }
+ ATTR_HOT inline const net_input_state state() const { return m_state; }
+
+ ATTR_COLD void set_output(net_output_t &aout) { m_output = &aout; }
+ ATTR_HOT inline void inactivate();
+ ATTR_HOT inline void activate();
+ ATTR_HOT inline void activate_hl();
+ ATTR_HOT inline void activate_lh();
+
+ double m_low_thresh_V;
+ double m_high_thresh_V;
+
+private:
+ net_input_state m_state;
+ net_output_t * RESTRICT m_output;
+};
+
+// ----------------------------------------------------------------------------------------
+// logic_input_t
+// ----------------------------------------------------------------------------------------
+
+class logic_input_t : public net_input_t
+{
+public:
+ logic_input_t()
+ : net_input_t(INPUT | SIGNAL_DIGITAL)
+ {
+ // default to TTL
+ m_low_thresh_V = 0.8;
+ m_high_thresh_V = 2.0;
+ }
+
+ ATTR_HOT inline const netlist_sig_t Q() const;
+ ATTR_HOT inline const netlist_sig_t last_Q() const;
+
+ ATTR_COLD inline void set_thresholds(const double low, const double high)
+ {
+ m_low_thresh_V = low;
+ m_high_thresh_V = high;
+ }
+};
+
+// ----------------------------------------------------------------------------------------
+// ttl_input_t
+// ----------------------------------------------------------------------------------------
+
+class ttl_input_t : public logic_input_t
+{
+public:
+ ttl_input_t()
+ : logic_input_t() { set_thresholds(0.8 , 2.0); }
+};
+
+class analog_input_t : public net_input_t
+{
+public:
+ analog_input_t()
+ : net_input_t(INPUT | SIGNAL_ANALOG) { }
+
+ ATTR_HOT inline const bool is_highz() const;
+ ATTR_HOT inline const double Q_Analog() const;
+};
+
+//#define INPVAL(_x) (_x).Q()
+
+// ----------------------------------------------------------------------------------------
+// net_output_t
+// ----------------------------------------------------------------------------------------
+
+class NETLIB_NAME(netdev_mainclock);
+
+class net_output_t : public net_terminal_t
+{
+public:
+
+ net_output_t(int atype);
+
+ friend const netlist_sig_t logic_input_t::Q() const;
+ friend const double analog_input_t::Q_Analog() const;
+ friend const bool analog_input_t::is_highz() const;
+ friend class NETLIB_NAME(netdev_mainclock);
+
+ ATTR_HOT inline const netlist_sig_t last_Q() const { return m_last_Q; }
+ ATTR_HOT inline const netlist_sig_t new_Q() const { return m_new_Q; }
+
+ ATTR_COLD void register_con(net_input_t &inp);
+
+ ATTR_HOT inline void update_devs();
+
+ ATTR_HOT inline void inc_active();
+ ATTR_HOT inline void dec_active();
+
+ ATTR_HOT inline const int active_count() const { return m_active; }
+ ATTR_HOT inline const netlist_time time() const { return m_time; }
+ ATTR_HOT inline void set_time(const netlist_time ntime) { m_time = ntime; }
+
+ double m_low_V;
+ double m_high_V;
+
+protected:
+
+ /* prohibit use in device functions
+ * current (pending) state can be inquired using new_Q()
+ */
+ ATTR_HOT inline const netlist_sig_t Q() const
+ {
+ assert(object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
+ return m_Q;
+ }
+ ATTR_HOT inline const double Q_Analog() const
+ {
+ assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG);
+ return m_Q_analog;
+ }
+
+ ATTR_HOT inline void push_to_queue(const netlist_time &delay);
+
+ netlist_sig_t m_last_Q;
+ netlist_sig_t m_Q;
+ netlist_sig_t m_new_Q;
+
+ double m_Q_analog;
+ double m_new_Q_analog;
+
+ UINT32 m_num_cons;
+private:
+ ATTR_HOT void update_dev(const net_input_t *inp, const UINT32 mask);
+
+ netlist_time m_time;
+
+ INT32 m_active;
+
+ UINT32 m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */
+
+ net_input_t * RESTRICT m_cons[OUTPUT_MAX_CONNECTIONS];
+};
+
+
+class logic_output_t : public net_output_t
+{
+public:
+
+ logic_output_t()
+ : net_output_t(OUTPUT | SIGNAL_DIGITAL)
+ {
+ // Default to TTL
+ m_low_V = 0.1; // these depend on sinked/sourced current. Values should be suitable for typical applications.
+ m_high_V = 4.8;
+ }
+
+ ATTR_COLD void initial(const netlist_sig_t val) { m_Q = val; m_new_Q = val; m_last_Q = !val; }
+
+ ATTR_HOT inline void set_Q(const netlist_sig_t newQ, const netlist_time &delay)
+ {
+ if (EXPECTED(newQ != m_new_Q))
+ {
+ m_new_Q = newQ;
+ if (m_num_cons)
+ push_to_queue(delay);
+ }
+ }
+
+ ATTR_COLD inline void set_levels(const double low, const double high)
+ {
+ m_low_V = low;
+ m_high_V = high;
+ }
+};
+
+class ttl_output_t : public logic_output_t
+{
+public:
+
+ ttl_output_t()
+ : logic_output_t()
+ { set_levels(0.3, 3.4); }
+
+};
+
+class analog_output_t : public net_output_t
+{
+public:
+
+ analog_output_t()
+ : net_output_t(OUTPUT | SIGNAL_ANALOG) { }
+
+ ATTR_COLD void initial(const double val) { m_Q_analog = val; m_new_Q_analog = val; }
+
+ ATTR_HOT inline void set_Q(const double newQ, const netlist_time &delay)
+ {
+ if (newQ != m_new_Q_analog)
+ {
+ m_new_Q_analog = newQ;
+ push_to_queue(delay);
+ }
+ }
+
+};
+
+// ----------------------------------------------------------------------------------------
+// net_device_t
+// ----------------------------------------------------------------------------------------
+
+class netlist_core_device_t : public net_object_t
+{
+public:
+
+ netlist_core_device_t();
+
+ virtual ~netlist_core_device_t();
+
+ ATTR_COLD virtual void init(netlist_setup_t &setup, const astring &name);
+
+ ATTR_COLD const astring &name() const { return m_name; }
+
+ ATTR_HOT virtual void update_param() {}
+
+ ATTR_HOT const netlist_sig_t INPLOGIC_PASSIVE(logic_input_t &inp);
+
+ ATTR_HOT inline void update_dev()
+ {
+#if USE_DELEGATES
+#if USE_PMFDELEGATES
+ static_update(this);
+#else
+ static_update();
+#endif
+#else
+ update();
+#endif
+ }
+
+ ATTR_HOT inline const netlist_sig_t INPLOGIC(const logic_input_t &inp) const
+ {
+ assert(inp.state() != net_input_t::INP_STATE_PASSIVE);
+ return inp.Q();
+ }
+
+ ATTR_HOT inline void OUTLOGIC(logic_output_t &out, const netlist_sig_t val, const netlist_time &delay)
+ {
+ out.set_Q(val, delay);
+ }
+
+ ATTR_HOT inline bool INP_HL(const logic_input_t &inp) const
+ {
+ return ((inp.last_Q() & !inp.Q()) == 1);
+ }
+
+ ATTR_HOT inline bool INP_LH(const logic_input_t &inp) const
+ {
+ return ((!inp.last_Q() & inp.Q()) == 1);
+ }
+
+ ATTR_HOT inline const double INPANALOG(const analog_input_t &inp) const { return inp.Q_Analog(); }
+
+ ATTR_HOT inline void OUTANALOG(analog_output_t &out, const double val, const netlist_time &delay)
+ {
+ out.set_Q(val, delay);
+ }
+
+ ATTR_HOT inline netlist_base_t *netlist() const { return m_netlist; }
+
+ ATTR_HOT virtual void inc_active() { }
+
+ ATTR_HOT virtual void dec_active() { /*printf("DeActivate %s\n", m_name);*/ }
+
+ /* stats */
+ osd_ticks_t total_time;
+ INT32 stat_count;
+
+#if USE_DELEGATES
+ net_update_delegate static_update;
+#endif
+
+protected:
+
+ ATTR_HOT virtual void update() { }
+ ATTR_HOT virtual void start() { }
+
+ netlist_base_t * RESTRICT m_netlist;
+
+private:
+
+ astring m_name;
+};
+
+
+class net_device_t : public netlist_core_device_t
+{
+public:
+
+ net_device_t();
+
+ virtual ~net_device_t();
+
+ ATTR_COLD virtual void init(netlist_setup_t &setup, const astring &name);
+
+ ATTR_COLD const netlist_setup_t *setup() const { return m_setup; }
+
+ ATTR_COLD bool variable_input_count() { return m_variable_input_count; }
+
+ ATTR_COLD void register_sub(netlist_core_device_t &dev, const astring &name);
+
+ ATTR_COLD void register_output(const astring &name, net_output_t &out);
+ ATTR_COLD void register_output(netlist_core_device_t &dev, const astring &name, net_output_t &out);
+
+ ATTR_COLD void register_input(const astring &name, net_input_t &in, net_input_t::net_input_state state = net_input_t::INP_STATE_ACTIVE);
+ ATTR_COLD void register_input(netlist_core_device_t &dev, const astring &name, net_input_t &in, net_input_t::net_input_state state = net_input_t::INP_STATE_ACTIVE);
+
+ ATTR_COLD void register_link_internal(net_input_t &in, net_output_t &out, net_input_t::net_input_state aState);
+ ATTR_COLD void register_link_internal(netlist_core_device_t &dev, net_input_t &in, net_output_t &out, net_input_t::net_input_state aState);
+
+ netlist_list_t<astring> m_inputs;
+
+protected:
+
+ virtual void update() { }
+ ATTR_HOT virtual void start() { }
+
+ ATTR_COLD void register_param(const astring &sname, net_param_t &param, const double initialVal = 0.0);
+ ATTR_COLD void register_param(netlist_core_device_t &dev, const astring &sname, net_param_t &param, const double initialVal = 0.0);
+
+ netlist_setup_t *m_setup;
+ bool m_variable_input_count;
+
+private:
+};
+
+class net_param_t
+{
+public:
+ net_param_t()
+ : m_param(0.0)
+ , m_netdev(NULL)
+ { }
+
+ inline void setTo(const double param) { m_param = param; m_netdev->update_param(); }
+ inline void setTo(const int param) { m_param = param; m_netdev->update_param(); }
+ inline void initial(const double val) { m_param = val; }
+ inline void initial(const int val) { m_param = val; }
+
+ ATTR_HOT inline double Value() const { return m_param; }
+ ATTR_HOT inline int ValueInt() const { return (int) m_param; }
+
+ ATTR_HOT inline netlist_core_device_t &netdev() const { return *m_netdev; }
+ void set_netdev(netlist_core_device_t &dev) { m_netdev = &dev; }
+
+private:
+
+ double m_param;
+ netlist_core_device_t *m_netdev;
+};
+
+
+
+class netdev_mainclock;
+
+// ----------------------------------------------------------------------------------------
+// netlist_base_t
+// ----------------------------------------------------------------------------------------
+
+class netlist_base_t
+{
+public:
+
+ typedef netlist_timed_queue1<net_output_t, netlist_time, 512> queue_t;
+
+ netlist_base_t();
+ virtual ~netlist_base_t();
+
+ void set_clock_freq(UINT64 clockfreq);
+
+ ATTR_HOT inline void push_to_queue(net_output_t &out, const netlist_time &attime)
+ {
+ m_queue.push(queue_t::entry_t(attime, out));
+ }
+
+ ATTR_HOT void process_queue(INT32 &atime);
+
+ ATTR_HOT inline const netlist_time &time() const { return m_time_ps; }
+
+ ATTR_COLD void set_mainclock_dev(NETLIB_NAME(netdev_mainclock) *dev);
+
+ ATTR_COLD void reset();
+
+ // FIXME: should'nt be public
+ queue_t m_queue;
+
+protected:
+ // performance
+ int m_perf_out_processed;
+ int m_perf_inp_processed;
+ int m_perf_inp_active;
+
+private:
+ NETLIB_NAME(netdev_mainclock) *m_mainclock;
+ netlist_time m_time_ps;
+ UINT32 m_rem;
+ UINT32 m_div;
+
+
+ ATTR_HOT void update_time(const netlist_time t, INT32 &atime);
+
+};
+
+// ----------------------------------------------------------------------------------------
+// netdev_a_to_d
+// ----------------------------------------------------------------------------------------
+
+class netdev_a_to_d_proxy : public net_device_t
+{
+public:
+ netdev_a_to_d_proxy(net_input_t &in_proxied)
+ : net_device_t()
+ {
+ assert(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
+ m_I.m_high_thresh_V = in_proxied.m_high_thresh_V;
+ m_I.m_low_thresh_V = in_proxied.m_low_thresh_V;
+ }
+
+ virtual ~netdev_a_to_d_proxy() {}
+
+ analog_input_t m_I;
+ ttl_output_t m_Q;
+
+protected:
+ void start()
+ {
+ m_I.init_input(this);
+
+ m_Q.init_terminal(this);
+ m_Q.initial(1);
+ }
+
+ ATTR_HOT ATTR_ALIGN void update()
+ {
+ if (m_I.Q_Analog() > m_I.m_high_thresh_V)
+ OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1));
+ else if (m_I.Q_Analog() < m_I.m_low_thresh_V)
+ OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1));
+ }
+
+};
+
+// ----------------------------------------------------------------------------------------
+// netdev_d_to_a
+// ----------------------------------------------------------------------------------------
+
+class netdev_d_to_a_proxy : public net_device_t
+{
+public:
+ netdev_d_to_a_proxy(net_output_t &out_proxied)
+ : net_device_t()
+ {
+ assert(out_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
+ m_low_V = out_proxied.m_low_V;
+ m_high_V = out_proxied.m_high_V;
+ }
+
+ virtual ~netdev_d_to_a_proxy() {}
+
+ ttl_input_t m_I;
+ analog_output_t m_Q;
+
+protected:
+ void start()
+ {
+ m_I.init_input(this);
+ m_Q.init_terminal(this);
+ m_Q.initial(0);
+ }
+
+ ATTR_HOT ATTR_ALIGN void update()
+ {
+ OUTANALOG(m_Q, INPLOGIC(m_I) ? m_high_V : m_low_V, NLTIME_FROM_NS(1));
+ }
+
+private:
+ double m_low_V;
+ double m_high_V;
+};
+
+
+// ----------------------------------------------------------------------------------------
+// Inline implementations
+// ----------------------------------------------------------------------------------------
+
+ATTR_HOT inline void net_input_t::inactivate()
+{
+ if (m_state != INP_STATE_PASSIVE)
+ {
+ m_state = INP_STATE_PASSIVE;
+ m_output->dec_active();
+ }
+}
+
+ATTR_HOT inline void net_input_t::activate()
+{
+ if (m_state == INP_STATE_PASSIVE)
+ {
+ m_output->inc_active();
+ m_state = INP_STATE_ACTIVE;
+ }
+}
+
+ATTR_HOT inline void net_input_t::activate_hl()
+{
+ if (m_state == INP_STATE_PASSIVE)
+ {
+ m_output->inc_active();
+ m_state = INP_STATE_HL;
+ }
+}
+
+ATTR_HOT inline void net_input_t::activate_lh()
+{
+ if (m_state == INP_STATE_PASSIVE)
+ {
+ m_output->inc_active();
+ m_state = INP_STATE_LH;
+ }
+}
+
+
+ATTR_HOT inline void net_output_t::push_to_queue(const netlist_time &delay)
+{
+ // if (m_in_queue == 1) return; FIXME: check this at some time
+ m_time = netlist()->time() + delay;
+ m_in_queue = (m_active > 0) ? 1 : 0; /* queued ? */
+ if (m_in_queue)
+ {
+ //m_in_queue = 1; /* pending */
+ netlist()->push_to_queue(*this, m_time);
+ }
+}
+
+ATTR_HOT inline void net_output_t::inc_active()
+{
+ m_active++;
+
+#if USE_DEACTIVE_DEVICE
+ if (m_active == 1 && m_in_queue > 0)
+ {
+ m_last_Q = m_Q;
+ netdev()->inc_active();
+ m_Q = m_new_Q;
+ }
+#endif
+
+ if (EXPECTED(m_active == 1 && m_in_queue == 0))
+ {
+ if (EXPECTED(m_time > netlist()->time()))
+ {
+ m_in_queue = 1; /* pending */
+ netlist()->push_to_queue(*this, m_time);
+ }
+ else
+ {
+ m_Q = m_last_Q = m_new_Q;
+ m_Q_analog = m_new_Q_analog;
+ m_in_queue = 2;
+ }
+ }
+}
+
+ATTR_HOT inline void net_output_t::dec_active()
+{
+ m_active--;
+#if (USE_DEACTIVE_DEVICE)
+ if (m_active == 0)
+ netdev()->dec_active();
+#endif
+}
+
+ATTR_HOT inline const netlist_sig_t logic_input_t::Q() const
+{
+ return output()->Q();
+}
+
+ATTR_HOT inline const netlist_sig_t logic_input_t::last_Q() const
+{
+ return output()->last_Q();
+}
+
+ATTR_HOT inline const double analog_input_t::Q_Analog() const
+{
+ return output()->Q_Analog();
+}
+
+ATTR_HOT inline const bool analog_input_t::is_highz() const
+{
+ return (output()->Q_Analog() == NETLIST_HIGHIMP_V);
+}
+
+// ----------------------------------------------------------------------------------------
+// net_dev class factory
+// ----------------------------------------------------------------------------------------
+
+class net_device_t_base_factory
+{
+public:
+ net_device_t_base_factory(const astring &name, const astring &classname)
+ : m_name(name), m_classname(classname)
+ {}
+
+ virtual ~net_device_t_base_factory() {}
+
+ virtual net_device_t *Create() const = 0;
+
+ const astring &name() const { return m_name; }
+ const astring &classname() const { return m_classname; }
+protected:
+ astring m_name; /* device name */
+ astring m_classname; /* device class name */
+};
+
+template <class C>
+class net_device_t_factory : public net_device_t_base_factory
+{
+public:
+ net_device_t_factory(const astring &name, const astring &classname)
+ : net_device_t_base_factory(name, classname) { }
+
+ net_device_t *Create() const
+ {
+ net_device_t *r = new C();
+ //r->init(setup, name);
+ return r;
+ }
+};
+
+net_device_t *net_create_device_by_classname(const astring &classname, netlist_setup_t &setup, const astring &icname);
+net_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &setup, const astring &icname);
+
+
+#endif /* NLBASE_H_ */
diff --git a/src/emu/netlist/nl_config.h b/src/emu/netlist/nl_config.h
new file mode 100644
index 00000000000..91bc758193c
--- /dev/null
+++ b/src/emu/netlist/nl_config.h
@@ -0,0 +1,103 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nlconfig.h
+ *
+ */
+
+#ifndef NLCONFIG_H_
+#define NLCONFIG_H_
+
+/* FIXME: at some time, make it compile on it's own */
+
+#include "emu.h"
+
+//============================================================
+// SETUP
+//============================================================
+
+#define USE_DELEGATES (0)
+/*
+ * The next options needs -Wno-pmf-conversions to compile and gcc
+ * This is intended for non-mame usage.
+ *
+ */
+#define USE_PMFDELEGATES (0)
+
+// Next if enabled adds 20% performance ... but is not guaranteed to be absolutely timing correct.
+#define USE_DEACTIVE_DEVICE (0)
+
+#define OUTPUT_MAX_CONNECTIONS (48)
+
+// Use nano-second resolution - Sufficient for now
+#define NETLIST_INTERNAL_RES (U64(1000000000))
+#define NETLIST_DIV_BITS (0)
+//#define NETLIST_INTERNAL_RES (U64(1000000000000))
+//#define NETLIST_DIV_BITS (10)
+#define NETLIST_DIV (U64(1) << NETLIST_DIV_BITS)
+#define NETLIST_MASK (NETLIST_DIV-1)
+#define NETLIST_CLOCK (NETLIST_INTERNAL_RES / NETLIST_DIV)
+
+#define NETLIST_HIGHIMP_V (1.23456e20) /* some voltage we should never see */
+
+typedef UINT8 netlist_sig_t;
+
+/* FIXME: We need a different solution to output delegates !
+ * More something like a callback object
+ */
+
+typedef delegate<void (const double)> netlist_output_delegate;
+
+//============================================================
+// DEBUGGING
+//============================================================
+
+#define NL_VERBOSE (0)
+#define NL_KEEP_STATISTICS (0)
+#define FATAL_ERROR_AFTER_NS (0) //(1000)
+
+#if (NL_VERBOSE)
+ #define NL_VERBOSE_OUT(x) printf x
+#else
+ #define NL_VERBOSE_OUT(x)
+#endif
+
+//============================================================
+// MACROS
+//============================================================
+
+#if NL_KEEP_STATISTICS
+#define add_to_stat(v,x) do { v += (x); } while (0)
+#define inc_stat(v) add_to_stat(v, 1)
+#define begin_timing(v) do { (v) -= get_profile_ticks(); } while (0)
+#define end_timing(v) do { (v) += get_profile_ticks(); } while (0)
+#else
+#define add_to_stat(v,x) do { } while (0)
+#define inc_stat(v) add_to_stat(v, 1)
+#define begin_timing(v) do { } while (0)
+#define end_timing(v) do { } while (0)
+#endif
+
+// Compiling without mame ?
+
+#ifndef ATTR_HOT
+#warning ATTR_HOT not defined
+#define ATTR_HOT
+#endif
+
+#ifndef ATTR_COLD
+#define ATTR_COLD
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
+#if !defined(__ppc__) && !defined (__PPC__) && !defined(__ppc64__) && !defined(__PPC64__)
+#define ATTR_ALIGN __attribute__ ((aligned(128)))
+#else
+#define ATTR_ALIGN
+#endif
+#else
+#define ATTR_ALIGN
+#endif
+
+
+#endif /* NLCONFIG_H_ */
diff --git a/src/emu/netlist/nl_lists.h b/src/emu/netlist/nl_lists.h
new file mode 100644
index 00000000000..cb437df14c2
--- /dev/null
+++ b/src/emu/netlist/nl_lists.h
@@ -0,0 +1,134 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nllists.h
+ *
+ */
+
+#ifndef NLLISTS_H_
+#define NLLISTS_H_
+
+#include "nl_config.h"
+
+// ----------------------------------------------------------------------------------------
+// netlist_list_t: a simple list
+// ----------------------------------------------------------------------------------------
+
+
+template <class _ListClass>
+struct netlist_list_t
+{
+public:
+ ATTR_COLD netlist_list_t(int numElements)
+ {
+ m_num_elements = numElements;
+ m_list = new _ListClass[m_num_elements];
+ m_ptr = m_list;
+ m_ptr--;
+ }
+ ATTR_COLD ~netlist_list_t()
+ {
+ delete[] m_list;
+ }
+ ATTR_HOT inline void add(const _ListClass elem)
+ {
+ assert(m_ptr-m_list <= m_num_elements - 1);
+
+ *(++m_ptr) = elem;
+ }
+ ATTR_HOT inline _ListClass *first() { return &m_list[0]; }
+ ATTR_HOT inline _ListClass *last() { return m_ptr; }
+ ATTR_HOT inline _ListClass *item(int i) { return &m_list[i]; }
+ ATTR_HOT inline int count() const { return m_ptr - m_list + 1; }
+ ATTR_HOT inline bool empty() { return (m_ptr < m_list); }
+ ATTR_HOT inline void clear() { m_ptr = m_list - 1; }
+private:
+ _ListClass * m_ptr;
+ _ListClass * m_list;
+ int m_num_elements;
+ //_ListClass m_list[_NumElements];
+};
+
+// ----------------------------------------------------------------------------------------
+// timed queue
+// ----------------------------------------------------------------------------------------
+
+template <class _Element, class _Time, int _Size>
+class netlist_timed_queue1
+{
+public:
+
+ struct entry_t
+ {
+ public:
+ inline entry_t()
+ : m_time(), m_object(NULL) {}
+ inline entry_t(const _Time atime, _Element &elem) : m_time(atime), m_object(&elem) {}
+ ATTR_HOT inline const _Time &time() const { return m_time; }
+ ATTR_HOT inline _Element & object() const { return *m_object; }
+ private:
+ _Time m_time;
+ _Element *m_object;
+ };
+
+ netlist_timed_queue1()
+ {
+ //m_list = global_alloc_array(entry_t, SIZE);
+ clear();
+ }
+
+ ATTR_HOT inline bool is_empty() const { return (m_end == &m_list[0]); }
+ ATTR_HOT inline bool is_not_empty() const { return (m_end > &m_list[0]); }
+
+ ATTR_HOT ATTR_ALIGN inline void push(const entry_t &e)
+ {
+ if (is_empty() || (e.time() <= (m_end - 1)->time()))
+ {
+ *m_end++ = e;
+ //inc_stat(m_prof_end);
+ }
+ else
+ {
+ entry_t * RESTRICT i = m_end++;
+ while ((i>&m_list[0]) && (e.time() > (i-1)->time()) )
+ {
+ i--;
+ *(i+1) = *i;
+ //inc_stat(m_prof_sortmove);
+ }
+ *i = e;
+ //inc_stat(m_prof_sort);
+ }
+ assert(m_end - m_list < _Size);
+ }
+
+ ATTR_HOT inline const entry_t pop()
+ {
+ return *--m_end;
+ }
+
+ ATTR_HOT inline const entry_t peek() const
+ {
+ return *(m_end-1);
+ }
+
+ ATTR_COLD void clear()
+ {
+ m_end = &m_list[0];
+ }
+ // profiling
+
+ INT32 m_prof_start;
+ INT32 m_prof_end;
+ INT32 m_prof_sortmove;
+ INT32 m_prof_sort;
+private:
+
+ entry_t * RESTRICT m_end;
+ //entry_t *m_list;
+ entry_t m_list[_Size];
+
+};
+
+
+#endif /* NLLISTS_H_ */
diff --git a/src/emu/netlist/nl_parser.c b/src/emu/netlist/nl_parser.c
new file mode 100644
index 00000000000..3116ef81061
--- /dev/null
+++ b/src/emu/netlist/nl_parser.c
@@ -0,0 +1,207 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nl_parser.c
+ *
+ */
+
+#include "nl_parser.h"
+
+// ----------------------------------------------------------------------------------------
+// A netlist parser
+// ----------------------------------------------------------------------------------------
+
+void netlist_parser::parse(char *buf)
+{
+ m_p = buf;
+ while (*m_p)
+ {
+ astring n;
+ skipws();
+ if (!*m_p) break;
+ n = getname('(');
+ NL_VERBOSE_OUT(("Parser: Device: %s\n", n.cstr()));
+ if (n == "NET_ALIAS")
+ net_alias();
+ else if (n == "NETDEV_PARAM")
+ netdev_param();
+ else if ((n == "NETDEV_TTL_CONST") || (n == "NETDEV_ANALOG_CONST"))
+ netdev_const(n);
+ else
+ netdev_device(n);
+ }
+}
+
+void netlist_parser::net_alias()
+{
+ astring alias;
+ astring out;
+ skipws();
+ alias = getname(',');
+ skipws();
+ out = getname(')');
+ NL_VERBOSE_OUT(("Parser: Alias: %s %s\n", alias.cstr(), out.cstr()));
+ m_setup.register_alias(alias, out);
+}
+
+void netlist_parser::netdev_param()
+{
+ astring param;
+ double val;
+ skipws();
+ param = getname(',');
+ skipws();
+ val = eval_param();
+ NL_VERBOSE_OUT(("Parser: Param: %s %f\n", param.cstr(), val));
+ m_setup.find_param(param).initial(val);
+ check_char(')');
+}
+
+void netlist_parser::netdev_const(const astring &dev_name)
+{
+ astring name;
+ net_device_t *dev;
+ astring paramfq;
+ double val;
+
+ skipws();
+ name = getname(',');
+ dev = net_create_device_by_name(dev_name, m_setup, name);
+ m_setup.register_dev(dev);
+ skipws();
+ val = eval_param();
+ check_char(')');
+ paramfq = name;
+ paramfq.cat(".CONST");
+ NL_VERBOSE_OUT(("Parser: Const: %s %f\n", name.cstr(), val));
+ m_setup.find_param(paramfq).initial(val);
+}
+
+void netlist_parser::netdev_device(const astring &dev_type)
+{
+ astring devname;
+ net_device_t *dev;
+ int cnt;
+
+ skipws();
+ devname = getname2(',', ')');
+ dev = net_create_device_by_name(dev_type, m_setup, devname);
+ m_setup.register_dev(dev);
+ skipws();
+ NL_VERBOSE_OUT(("Parser: IC: %s\n", devname.cstr()));
+ cnt = 0;
+ while (*m_p != ')')
+ {
+ m_p++;
+ skipws();
+ astring output_name = getname2(',', ')');
+ NL_VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), dev->m_inputs.item(cnt)->cstr()));
+ m_setup.register_link(*dev->m_inputs.item(cnt), output_name);
+ skipws();
+ cnt++;
+ }
+ if (cnt != dev->m_inputs.count() && !dev->variable_input_count())
+ fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname.cstr(), dev->m_inputs.count(), cnt);
+ if (dev->variable_input_count())
+ {
+ NL_VERBOSE_OUT(("variable inputs %s: %d\n", dev->name().cstr(), cnt));
+ }
+ check_char(')');
+}
+
+// ----------------------------------------------------------------------------------------
+// private
+// ----------------------------------------------------------------------------------------
+
+void netlist_parser::skipeol()
+{
+ while (*m_p)
+ {
+ if (*m_p == 10)
+ {
+ m_p++;
+ if (*m_p && *m_p == 13)
+ m_p++;
+ return;
+ }
+ m_p++;
+ }
+}
+
+void netlist_parser::skipws()
+{
+ while (*m_p)
+ {
+ switch (*m_p)
+ {
+ case ' ':
+ case 9:
+ case 10:
+ case 13:
+ m_p++;
+ break;
+ case '/':
+ if (*(m_p+1) == '/')
+ skipeol();
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+astring netlist_parser::getname(char sep)
+{
+ char buf[300];
+ char *p1 = buf;
+
+ while (*m_p != sep)
+ *p1++ = *m_p++;
+ *p1 = 0;
+ m_p++;
+ return astring(buf);
+}
+
+astring netlist_parser::getname2(char sep1, char sep2)
+{
+ char buf[300];
+ char *p1 = buf;
+
+ while ((*m_p != sep1) && (*m_p != sep2))
+ *p1++ = *m_p++;
+ *p1 = 0;
+ return astring(buf);
+}
+
+void netlist_parser::check_char(char ctocheck)
+{
+ skipws();
+ if (*m_p == ctocheck)
+ {
+ m_p++;
+ return;
+ }
+ fatalerror("Parser: expected '%c' found '%c'\n", ctocheck, *m_p);
+}
+
+double netlist_parser::eval_param()
+{
+ static const char *macs[6] = {"", "RES_K(", "RES_M(", "CAP_U(", "CAP_N(", "CAP_P("};
+ static double facs[6] = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
+ int i;
+ int f=0;
+ char *e;
+ double ret;
+ char *s = m_p;
+
+ for (i=1; i<6;i++)
+ if (strncmp(s, macs[i], strlen(macs[i])) == 0)
+ f = i;
+ ret = strtod(s+strlen(macs[f]), &e);
+ if ((f>0) && (*e != ')'))
+ fatalerror("Parser: Error with parameter ...\n");
+ if (f>0)
+ e++;
+ m_p = e;
+ return ret * facs[f];
+}
diff --git a/src/emu/netlist/nl_parser.h b/src/emu/netlist/nl_parser.h
new file mode 100644
index 00000000000..79b3882ac37
--- /dev/null
+++ b/src/emu/netlist/nl_parser.h
@@ -0,0 +1,39 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nl_parser.c
+ *
+ */
+
+#ifndef NL_PARSER_H_
+#define NL_PARSER_H_
+
+#include "nl_setup.h"
+
+class netlist_parser
+{
+public:
+ netlist_parser(netlist_setup_t &setup)
+ : m_setup(setup) {}
+
+ void parse(char *buf);
+ void net_alias();
+ void netdev_param();
+ void netdev_const(const astring &dev_name);
+ void netdev_device(const astring &dev_type);
+
+private:
+
+ void skipeol();
+ void skipws();
+ astring getname(char sep);
+ astring getname2(char sep1, char sep2);
+ void check_char(char ctocheck);
+ double eval_param();
+
+ char * m_p;
+ netlist_setup_t &m_setup;
+};
+
+
+#endif /* NL_PARSER_H_ */
diff --git a/src/emu/netlist/nl_setup.c b/src/emu/netlist/nl_setup.c
new file mode 100644
index 00000000000..3cf1795c488
--- /dev/null
+++ b/src/emu/netlist/nl_setup.c
@@ -0,0 +1,318 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nlsetup.c
+ *
+ */
+
+#include "nl_base.h"
+#include "nl_setup.h"
+#include "nl_parser.h"
+#include "devices/nld_system.h"
+
+static NETLIST_START(base)
+ NETDEV_TTL_CONST(ttlhigh, 1)
+ NETDEV_TTL_CONST(ttllow, 0)
+ NETDEV_ANALOG_CONST(NC, NETLIST_HIGHIMP_V)
+NETLIST_END
+
+
+// ----------------------------------------------------------------------------------------
+// netlist_setup_t
+// ----------------------------------------------------------------------------------------
+
+netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
+ : m_netlist(netlist)
+{
+ NETLIST_NAME(base)(*this);
+}
+
+template <class T>
+static void tagmap_free_entries(T &tm)
+{
+ for (typename T::entry_t *entry = tm.first(); entry != NULL; entry = tm.next(entry))
+ {
+ delete entry->object();
+ }
+ tm.reset();
+}
+
+netlist_setup_t::~netlist_setup_t()
+{
+ tagmap_free_entries<tagmap_devices_t>(m_devices);
+ tagmap_free_entries<tagmap_astring_t>(m_links);
+ tagmap_free_entries<tagmap_astring_t>(m_alias);
+ m_params.reset();
+ m_terminals.reset();
+}
+
+net_device_t *netlist_setup_t::register_dev(net_device_t *dev)
+{
+ if (!(m_devices.add(dev->name(), dev, false)==TMERR_NONE))
+ fatalerror("Error adding %s to device list\n", dev->name().cstr());
+ return dev;
+}
+
+template <class T>
+static void remove_start_with(T &hm, astring &sw)
+{
+ typename T::entry_t *entry = hm.first();
+ while (entry != NULL)
+ {
+ typename T::entry_t *next = hm.next(entry);
+ if (sw.cmpsubstr(entry->tag(), 0, sw.len()) == 0)
+ {
+ NL_VERBOSE_OUT(("removing %s\n", entry->tag().cstr()));
+ hm.remove(entry->object());
+ }
+ entry = next;
+ }
+}
+
+void netlist_setup_t::remove_dev(const astring &name)
+{
+ net_device_t *dev = m_devices.find(name);
+ astring temp = name;
+ if (dev == NULL)
+ fatalerror("Device %s does not exist\n", name.cstr());
+
+ temp.cat(".");
+
+ //remove_start_with<tagmap_input_t>(m_inputs, temp);
+ remove_start_with<tagmap_terminal_t>(m_terminals, temp);
+ remove_start_with<tagmap_param_t>(m_params, temp);
+ remove_start_with<tagmap_astring_t>(m_links, temp);
+ m_devices.remove(name);
+}
+
+void netlist_setup_t::register_callback(const astring &devname, netlist_output_delegate delegate)
+{
+ NETLIB_NAME(netdev_analog_callback) *dev = (NETLIB_NAME(netdev_analog_callback) *) m_devices.find(devname);
+ if (dev == NULL)
+ fatalerror("did not find device %s\n", devname.cstr());
+ dev->register_callback(delegate);
+}
+
+void netlist_setup_t::register_alias(const astring &alias, const astring &out)
+{
+ if (!(m_alias.add(alias, new astring(out), false)==TMERR_NONE))
+ fatalerror("Error adding alias %s to alias list\n", alias.cstr());
+}
+
+void netlist_setup_t::register_output(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, net_output_t &out)
+{
+ NL_VERBOSE_OUT(("out %s\n", name.cstr()));
+ astring temp = dev.name();
+ temp.cat(".");
+ temp.cat(name);
+ out.init_terminal(&upd_dev);
+ if (!(m_terminals.add(temp, &out, false)==TMERR_NONE))
+ fatalerror("Error adding output %s to output list\n", name.cstr());
+}
+
+void netlist_setup_t::register_input(net_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type)
+{
+ NL_VERBOSE_OUT(("input %s\n", name.cstr()));
+ astring temp = dev.name();
+ temp.cat(".");
+ temp.cat(name);
+ inp.init_input(&upd_dev, type);
+ dev.m_inputs.add(temp);
+ if (!(m_terminals.add(temp, &inp, false) == TMERR_NONE))
+ fatalerror("Error adding input %s to input list\n", name.cstr());
+}
+
+void netlist_setup_t::register_link(const astring &sin, const astring &sout)
+{
+ const astring *temp = new astring(sout);
+ NL_VERBOSE_OUT(("link %s <== %s\n", sin.cstr(), sout.cstr()));
+ if (!(m_links.add(sin, temp, false)==TMERR_NONE))
+ fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr());
+}
+
+
+void netlist_setup_t::register_param(const astring &name, net_param_t *param)
+{
+ astring temp = param->netdev().name();
+ temp.cat(".");
+ temp.cat(name);
+ if (!(m_params.add(temp, param, false)==TMERR_NONE))
+ fatalerror("Error adding parameter %s to parameter list\n", name.cstr());
+}
+
+
+const astring &netlist_setup_t::resolve_alias(const astring &name) const
+{
+ const astring *ret = m_alias.find(name);
+ if (ret != NULL)
+ return *ret;
+ return name;
+}
+
+net_output_t *netlist_setup_t::find_output_exact(const astring &outname_in)
+{
+ net_terminal_t *term = m_terminals.find(outname_in);
+ return dynamic_cast<net_output_t *>(term);
+}
+
+net_output_t &netlist_setup_t::find_output(const astring &outname_in)
+{
+ const astring &outname = resolve_alias(outname_in);
+ net_output_t *ret;
+
+ ret = find_output_exact(outname);
+ /* look for default */
+ if (ret == NULL)
+ {
+ /* look for ".Q" std output */
+ astring s = outname;
+ s.cat(".Q");
+ ret = find_output_exact(s);
+ }
+ if (ret == NULL)
+ fatalerror("output %s(%s) not found!\n", outname_in.cstr(), outname.cstr());
+ NL_VERBOSE_OUT(("Found input %s\n", outname.cstr()));
+ return *ret;
+}
+
+net_param_t &netlist_setup_t::find_param(const astring &param_in)
+{
+ const astring &outname = resolve_alias(param_in);
+ net_param_t *ret;
+
+ ret = m_params.find(outname);
+ if (ret == NULL)
+ fatalerror("parameter %s(%s) not found!\n", param_in.cstr(), outname.cstr());
+ NL_VERBOSE_OUT(("Found parameter %s\n", outname.cstr()));
+ return *ret;
+}
+
+void netlist_setup_t::resolve_inputs(void)
+{
+ NL_VERBOSE_OUT(("Resolving ...\n"));
+ int proxy_cnt = 0;
+ for (tagmap_astring_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry))
+ {
+ const astring *sout = entry->object();
+ astring sin = entry->tag();
+ net_input_t *in = dynamic_cast<net_input_t *>(m_terminals.find(sin));
+
+ if (in == NULL)
+ fatalerror("Unable to find %s\n", sin.cstr());
+
+ net_output_t &out = find_output(sout->cstr());
+ if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG
+ && in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL)
+ {
+ netdev_a_to_d_proxy *proxy = new netdev_a_to_d_proxy(*in);
+ astring x = "";
+ x.printf("proxy_ad_%d", proxy_cnt++);
+
+ proxy->init(*this, x.cstr());
+ register_dev(proxy);
+
+ in->set_output(proxy->m_Q);
+ proxy->m_Q.register_con(*in);
+ proxy->m_I.set_output(out);
+ out.register_con(proxy->m_I);
+
+ }
+ else if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL
+ && in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG)
+ {
+ //printf("here 1\n");
+ netdev_d_to_a_proxy *proxy = new netdev_d_to_a_proxy(out);
+ astring x = "";
+ x.printf("proxy_da_%d", proxy_cnt++);
+ proxy->init(*this, x.cstr());
+ register_dev(proxy);
+
+ in->set_output(proxy->m_Q);
+ proxy->m_Q.register_con(*in);
+ proxy->m_I.set_output(out);
+ out.register_con(proxy->m_I);
+ //printf("here 2\n");
+ }
+ else
+ {
+ in->set_output(out);
+ out.register_con(*in);
+ }
+ }
+
+ /* find the main clock ... */
+ for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
+ {
+ net_device_t *dev = entry->object();
+ if (dynamic_cast<NETLIB_NAME(netdev_mainclock)*>(dev) != NULL)
+ {
+ m_netlist.set_mainclock_dev(dynamic_cast<NETLIB_NAME(netdev_mainclock)*>(dev));
+ }
+ }
+
+#if 1
+
+#else
+ /* make sure all outputs are triggered once */
+ for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
+ {
+ net_output_t *out = entry->object();
+ //if (dynamic_cast<const netdev_clock *>(out->netdev()) == NULL )
+ {
+ out->update_devs_force();
+ INT32 time = 10000;
+ m_netlist.process_list(time);
+ }
+ }
+ //m_netlist.m_queue.clear();
+#endif
+
+ /* print all outputs */
+ for (tagmap_terminal_t::entry_t *entry = m_terminals.first(); entry != NULL; entry = m_terminals.next(entry))
+ {
+ ATTR_UNUSED net_output_t *out = dynamic_cast<net_output_t *>(entry->object());
+ //if (out != NULL)
+ //VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
+ }
+
+
+}
+
+void netlist_setup_t::step_devices_once(void)
+{
+ /* make sure params are set now .. */
+ for (tagmap_param_t::entry_t *entry = m_params.first(); entry != NULL; entry = m_params.next(entry))
+ {
+ entry->object()->netdev().update_param();
+ }
+
+ for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
+ {
+ net_device_t *dev = entry->object();
+ dev->update_dev();
+ }
+}
+
+
+void netlist_setup_t::parse(char *buf)
+{
+ netlist_parser parser(*this);
+ parser.parse(buf);
+}
+
+void netlist_setup_t::print_stats()
+{
+ if (NL_KEEP_STATISTICS)
+ {
+ for (netlist_setup_t::tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
+ {
+ //entry->object()->s
+ printf("Device %20s : %12d %15ld\n", entry->object()->name().cstr(), entry->object()->stat_count, (long int) entry->object()->total_time / (entry->object()->stat_count + 1));
+ }
+ printf("Queue Start %15d\n", m_netlist.m_queue.m_prof_start);
+ printf("Queue End %15d\n", m_netlist.m_queue.m_prof_end);
+ printf("Queue Sort %15d\n", m_netlist.m_queue.m_prof_sort);
+ printf("Queue Move %15d\n", m_netlist.m_queue.m_prof_sortmove);
+ }
+}
+
diff --git a/src/emu/netlist/nl_setup.h b/src/emu/netlist/nl_setup.h
new file mode 100644
index 00000000000..ffc07c9b17d
--- /dev/null
+++ b/src/emu/netlist/nl_setup.h
@@ -0,0 +1,113 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nlsetup.h
+ *
+ * Created on: 3 Nov 2013
+ * Author: andre
+ */
+
+#ifndef NLSETUP_H_
+#define NLSETUP_H_
+
+#include "nl_base.h"
+
+//============================================================
+// MACROS / inline netlist definitions
+//============================================================
+
+#define NET_ALIAS(_alias, _name) \
+ netlist.register_alias(# _alias, # _name);
+#define NET_NEW(_type , _name) net_create_device_by_classname(NETLIB_NAME_STR(_type), netlist, # _name)
+
+#define NET_REGISTER_DEV(_type, _name) \
+ netlist.register_dev(NET_NEW(_type, _name));
+#define NET_REMOVE_DEV(_name) \
+ netlist.remove_dev(# _name);
+#define NET_REGISTER_SIGNAL(_type, _name) \
+ NET_REGISTER_DEV(_type ## _ ## sig, _name)
+#define NET_CONNECT(_name, _input, _output) \
+ netlist.register_link(# _name "." # _input, # _output);
+#define NETDEV_PARAM(_name, _val) \
+ netlist.find_param(# _name).initial(_val);
+
+#define NETLIST_NAME(_name) netlist ## _ ## _name
+
+#define NETLIST_START(_name) \
+ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \
+{
+
+#define NETLIST_END }
+
+#define NETLIST_INCLUDE(_name) \
+ NETLIST_NAME(_name)(netlist);
+
+#define NETLIST_MEMREGION(_name) \
+ netlist.parse((char *)downcast<netlist_t &>(netlist.netlist()).machine().root_device().memregion(_name)->base());
+
+// ----------------------------------------------------------------------------------------
+// FIXME: Clean this up
+// ----------------------------------------------------------------------------------------
+
+class NETLIB_NAME(netdev_analog_callback);
+
+// ----------------------------------------------------------------------------------------
+// netlist_setup_t
+// ----------------------------------------------------------------------------------------
+
+class netlist_setup_t
+{
+public:
+
+ typedef tagmap_t<net_device_t *, 393> tagmap_devices_t;
+ typedef tagmap_t<const astring *, 393> tagmap_astring_t;
+ typedef tagmap_t<net_param_t *, 393> tagmap_param_t;
+ typedef tagmap_t<net_terminal_t *, 393> tagmap_terminal_t;
+
+ netlist_setup_t(netlist_base_t &netlist);
+ ~netlist_setup_t();
+
+ netlist_base_t &netlist() { return m_netlist; }
+
+ net_device_t *register_dev(net_device_t *dev);
+ void remove_dev(const astring &name);
+
+ void register_output(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, net_output_t &out);
+ void register_input(net_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type);
+ void register_alias(const astring &alias, const astring &out);
+ void register_param(const astring &sname, net_param_t *param);
+
+ void register_link(const astring &sin, const astring &sout);
+
+ net_output_t &find_output(const astring &outname_in);
+ net_param_t &find_param(const astring &param_in);
+
+ void register_callback(const astring &devname, netlist_output_delegate delegate);
+
+ void parse(char *buf);
+
+ void resolve_inputs(void);
+ void step_devices_once(void);
+
+ /* not ideal, but needed for save_state */
+ tagmap_terminal_t m_terminals;
+
+ void print_stats();
+
+protected:
+
+private:
+
+ netlist_base_t &m_netlist;
+
+ tagmap_devices_t m_devices;
+ tagmap_astring_t m_alias;
+ //tagmap_input_t m_inputs;
+ tagmap_param_t m_params;
+ tagmap_astring_t m_links;
+
+ net_output_t *find_output_exact(const astring &outname_in);
+ const astring &resolve_alias(const astring &name) const;
+};
+
+#endif /* NLSETUP_H_ */
diff --git a/src/emu/netlist/nl_time.h b/src/emu/netlist/nl_time.h
new file mode 100644
index 00000000000..740e10d8572
--- /dev/null
+++ b/src/emu/netlist/nl_time.h
@@ -0,0 +1,99 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nltime.h
+ */
+
+#ifndef NLTIME_H_
+#define NLTIME_H_
+
+#include "nl_config.h"
+
+//============================================================
+// MACROS
+//============================================================
+
+#define NLTIME_FROM_NS(_t) netlist_time::from_nsec(_t)
+#define NLTIME_FROM_US(_t) netlist_time::from_usec(_t)
+#define NLTIME_FROM_MS(_t) netlist_time::from_msec(_t)
+#define NLTIME_IMMEDIATE netlist_time::from_nsec(0)
+
+// ----------------------------------------------------------------------------------------
+// net_list_time
+// ----------------------------------------------------------------------------------------
+
+struct netlist_time
+{
+public:
+
+ typedef UINT64 INTERNALTYPE;
+
+ static const INTERNALTYPE RESOLUTION = NETLIST_INTERNAL_RES;
+
+ ATTR_HOT inline netlist_time() : m_time(0) {}
+
+ ATTR_HOT friend inline const netlist_time operator-(const netlist_time &left, const netlist_time &right);
+ ATTR_HOT friend inline const netlist_time operator+(const netlist_time &left, const netlist_time &right);
+ ATTR_HOT friend inline const netlist_time operator*(const netlist_time &left, const UINT32 factor);
+ ATTR_HOT friend inline bool operator>(const netlist_time &left, const netlist_time &right);
+ ATTR_HOT friend inline bool operator<(const netlist_time &left, const netlist_time &right);
+ ATTR_HOT friend inline bool operator>=(const netlist_time &left, const netlist_time &right);
+ ATTR_HOT friend inline bool operator<=(const netlist_time &left, const netlist_time &right);
+
+ ATTR_HOT inline const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
+ ATTR_HOT inline const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
+
+ ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
+
+ ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
+ ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }
+ ATTR_HOT static inline const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); }
+ ATTR_HOT static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
+ ATTR_HOT static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
+
+ static const netlist_time zero;
+
+protected:
+
+ ATTR_HOT inline netlist_time(const INTERNALTYPE val) : m_time(val) {}
+
+ INTERNALTYPE m_time;
+};
+
+ATTR_HOT inline const netlist_time operator-(const netlist_time &left, const netlist_time &right)
+{
+ return netlist_time::from_raw(left.m_time - right.m_time);
+}
+
+ATTR_HOT inline const netlist_time operator*(const netlist_time &left, const UINT32 factor)
+{
+ return netlist_time::from_raw(left.m_time * factor);
+}
+
+ATTR_HOT inline const netlist_time operator+(const netlist_time &left, const netlist_time &right)
+{
+ return netlist_time::from_raw(left.m_time + right.m_time);
+}
+
+ATTR_HOT inline bool operator<(const netlist_time &left, const netlist_time &right)
+{
+ return (left.m_time < right.m_time);
+}
+
+ATTR_HOT inline bool operator>(const netlist_time &left, const netlist_time &right)
+{
+ return (left.m_time > right.m_time);
+}
+
+ATTR_HOT inline bool operator<=(const netlist_time &left, const netlist_time &right)
+{
+ return (left.m_time <= right.m_time);
+}
+
+ATTR_HOT inline bool operator>=(const netlist_time &left, const netlist_time &right)
+{
+ return (left.m_time >= right.m_time);
+}
+
+
+#endif /* NLTIME_H_ */
diff --git a/src/mame/drivers/pong.c b/src/mame/drivers/pong.c
index 9ec2c4b8e08..49c475da5e3 100644
--- a/src/mame/drivers/pong.c
+++ b/src/mame/drivers/pong.c
@@ -18,7 +18,7 @@ TODO:
#include "machine/rescap.h"
#include "machine/netlist.h"
-#include "netlist/net_lib.h"
+#include "netlist/devices/net_lib.h"
#include "sound/dac.h"
#include "video/fixfreq.h"
#include "astring.h"
@@ -562,8 +562,8 @@ void pong_state::machine_reset()
void pong_state::video_start()
{
- m_maincpu->setup().register_callback("sound_cb", net_output_delegate(&pong_state::sound_cb, "pong_state::sound_cb", this));
- m_maincpu->setup().register_callback("video_cb", net_output_delegate(&pong_state::video_cb, "pong_state::video_cb", this));
+ m_maincpu->setup().register_callback("sound_cb", netlist_output_delegate(&pong_state::sound_cb, "pong_state::sound_cb", this));
+ m_maincpu->setup().register_callback("video_cb", netlist_output_delegate(&pong_state::video_cb, "pong_state::video_cb", this));
}