From 12ae4ea7480d080d4fa5548f193891df326a99b2 Mon Sep 17 00:00:00 2001 From: Couriersud Date: Fri, 15 Nov 2013 19:57:34 +0000 Subject: [PATCH] Netlist: Need a checkpoint before I continue. --- src/emu/netlist/devices/net_lib.c | 38 +---- src/emu/netlist/devices/net_lib.h | 22 ++- src/emu/netlist/devices/nld_signal.h | 2 +- src/emu/netlist/devices/nld_system.c | 30 ++++ src/emu/netlist/devices/nld_system.h | 23 ++- src/emu/netlist/nl_base.c | 113 ++++++++++--- src/emu/netlist/nl_base.h | 147 ++++++++++++---- src/emu/netlist/nl_config.h | 2 + src/emu/netlist/nl_parser.c | 2 +- src/emu/netlist/nl_setup.c | 242 ++++++++++++++++++++------- src/emu/netlist/nl_setup.h | 13 ++ src/mame/drivers/pong.c | 10 ++ 12 files changed, 497 insertions(+), 147 deletions(-) diff --git a/src/emu/netlist/devices/net_lib.c b/src/emu/netlist/devices/net_lib.c index 5b7884458be..5a61a6e0540 100644 --- a/src/emu/netlist/devices/net_lib.c +++ b/src/emu/netlist/devices/net_lib.c @@ -78,28 +78,6 @@ NETLIB_UPDATE(log) printf("%s: %d %d\n", name().cstr(), (UINT32) (netlist().time().as_raw() / 1000000), INPLOGIC(m_I)); } -NETLIB_START(clock) -{ - register_output("Q", m_Q); - //register_input("FB", m_feedback); - - register_param("FREQ", m_freq, 7159000.0 * 5); - m_inc = netlist_time::from_hz(m_freq.Value()*2); - - register_link_internal(m_feedback, m_Q, netlist_input_t::INP_STATE_ACTIVE); - -} - -NETLIB_UPDATE_PARAM(clock) -{ - m_inc = netlist_time::from_hz(m_freq.Value()*2); -} - -NETLIB_UPDATE(clock) -{ - //m_Q.setToNoCheck(!m_Q.new_Q(), m_inc ); - OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc ); -} NETLIB_START(nicMultiSwitch) { @@ -223,16 +201,16 @@ NETLIB_START(nicNE555N_MSTABLE) m_last = false; } -INLINE double nicNE555N_cv(NETLIB_NAME(nicNE555N_MSTABLE) &dev) +inline double NETLIB_NAME(nicNE555N_MSTABLE)::nicNE555N_cv() { - return (dev.m_CV.is_highz() ? 0.67 * dev.m_VS.Value() : dev.INPANALOG(dev.m_CV)); + return (m_CV.is_highz() ? 0.67 * m_VS.Value() : INPANALOG(m_CV)); } -INLINE double nicNE555N_clamp(NETLIB_NAME(nicNE555N_MSTABLE) &dev, const double v, const double a, const double b) +inline double NETLIB_NAME(nicNE555N_MSTABLE)::nicNE555N_clamp(const double v, const double a, const double b) { double ret = v; - if (ret > dev.m_VS.Value() - a) - ret = dev.m_VS.Value() - a; + if (ret > m_VS.Value() - a) + ret = m_VS.Value() - a; if (ret < b) ret = b; return ret; @@ -246,9 +224,9 @@ NETLIB_UPDATE(nicNE555N_MSTABLE) { update_param(); // FIXME : m_CV should be on a sub device ... - double vt = nicNE555N_clamp(*this, nicNE555N_cv(*this), 0.7, 1.4); + double vt = nicNE555N_clamp(nicNE555N_cv(), 0.7, 1.4); bool bthresh = (INPANALOG(m_THRESHOLD) > vt); - bool btrig = (INPANALOG(m_trigger) > nicNE555N_clamp(*this, nicNE555N_cv(*this) * 0.5, 0.7, 1.4)); + bool btrig = (INPANALOG(m_trigger) > nicNE555N_clamp(nicNE555N_cv() * 0.5, 0.7, 1.4)); bool out = m_last; if (!btrig) @@ -624,7 +602,6 @@ NETLIB_START(nic7493) register_output(C, "QC", C.m_Q); register_output(D, "QD", D.m_Q); - //B.register_link_internal(B.m_I, A.m_Q); register_link_internal(C, C.m_I, B.m_Q, netlist_input_t::INP_STATE_HL); register_link_internal(D, D.m_I, C.m_Q, netlist_input_t::INP_STATE_HL); @@ -972,6 +949,7 @@ NETLIB_FUNC_VOID(nic9316_sub, update_outputs, (void)) static const net_device_t_base_factory *netregistry[] = { + ENTRY(R, NETDEV_R) ENTRY(ttl_const, NETDEV_TTL_CONST) ENTRY(analog_const, NETDEV_ANALOG_CONST) ENTRY(logic_input, NETDEV_LOGIC_INPUT) diff --git a/src/emu/netlist/devices/net_lib.h b/src/emu/netlist/devices/net_lib.h index 8b58df399ec..455f16335ba 100644 --- a/src/emu/netlist/devices/net_lib.h +++ b/src/emu/netlist/devices/net_lib.h @@ -64,6 +64,16 @@ // this is a bad hack #define USE_OLD7493 (0) + +// ---------------------------------------------------------------------------------------- +// 2 terminal devices +// ---------------------------------------------------------------------------------------- + +#define NETDEV_R(_name, _R) \ + NET_REGISTER_DEV(R, _name) \ + NETDEV_PARAMI(_name, R, _R) \ + + // ---------------------------------------------------------------------------------------- // Special chips // ---------------------------------------------------------------------------------------- @@ -77,7 +87,7 @@ #define NETDEV_ANALOG_INPUT(_name) \ NET_REGISTER_DEV(analog_input, _name) #define NETDEV_CALLBACK(_name, _IN) \ - NET_REGISTER_DEV(analog_callback, _name) \ + NET_REGISTER_DEV(analog_callback, _name) \ NET_CONNECT(_name, IN, _IN) #define NETDEV_SWITCH2(_name, _i1, _i2) \ NET_REGISTER_DEV(nicMultiSwitch, _name) \ @@ -241,13 +251,7 @@ NETLIB_DEVICE(log, // ---------------------------------------------------------------------------------------- -NETLIB_DEVICE_WITH_PARAMS(clock, - netlist_ttl_input_t m_feedback; - netlist_ttl_output_t m_Q; - netlist_param_t m_freq; - netlist_time m_inc; -); NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch, netlist_analog_input_t m_I[8]; @@ -301,6 +305,10 @@ NETLIB_DEVICE_WITH_PARAMS(nicNE555N_MSTABLE, netlist_param_t m_C; netlist_param_t m_VS; netlist_param_t m_VL; + + double nicNE555N_cv(); + double nicNE555N_clamp(const double v, const double a, const double b); + ); NETLIB_SIGNAL(nic7430, 8, 0, 0); diff --git a/src/emu/netlist/devices/nld_signal.h b/src/emu/netlist/devices/nld_signal.h index b8f658d1f81..50ac975d303 100644 --- a/src/emu/netlist/devices/nld_signal.h +++ b/src/emu/netlist/devices/nld_signal.h @@ -90,7 +90,7 @@ public: register_output("Q", m_Q); for (int i=0; i < _numdev; i++) { - register_input(sIN[i], m_i[i], netlist_input_t::INP_STATE_ACTIVE); + register_input(sIN[i], m_i[i]); } } diff --git a/src/emu/netlist/devices/nld_system.c b/src/emu/netlist/devices/nld_system.c index 9718a9d4709..5c1bf6f14c4 100644 --- a/src/emu/netlist/devices/nld_system.c +++ b/src/emu/netlist/devices/nld_system.c @@ -39,6 +39,10 @@ NETLIB_UPDATE_PARAM(analog_const) m_Q.initial(m_const.Value()); } +// ---------------------------------------------------------------------------------------- +// analog_callback +// ---------------------------------------------------------------------------------------- + NETLIB_UPDATE(analog_callback) { // FIXME: Remove after device cleanup @@ -46,3 +50,29 @@ NETLIB_UPDATE(analog_callback) m_callback(INPANALOG(m_in)); } +// ---------------------------------------------------------------------------------------- +// clock +// ---------------------------------------------------------------------------------------- + +NETLIB_START(clock) +{ + register_output("Q", m_Q); + //register_input("FB", m_feedback); + + register_param("FREQ", m_freq, 7159000.0 * 5); + m_inc = netlist_time::from_hz(m_freq.Value()*2); + + register_link_internal(m_feedback, m_Q, netlist_input_t::INP_STATE_ACTIVE); + +} + +NETLIB_UPDATE_PARAM(clock) +{ + m_inc = netlist_time::from_hz(m_freq.Value()*2); +} + +NETLIB_UPDATE(clock) +{ + //m_Q.setToNoCheck(!m_Q.new_Q(), m_inc ); + OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc ); +} diff --git a/src/emu/netlist/devices/nld_system.h b/src/emu/netlist/devices/nld_system.h index 4dfaf465aa2..16d254573fd 100644 --- a/src/emu/netlist/devices/nld_system.h +++ b/src/emu/netlist/devices/nld_system.h @@ -43,7 +43,8 @@ NETLIB_DEVICE_WITH_PARAMS(analog_const, // ---------------------------------------------------------------------------------------- NETLIB_DEVICE_WITH_PARAMS(mainclock, - netlist_ttl_output_t m_Q; +public: + netlist_ttl_output_t m_Q; netlist_param_t m_freq; netlist_time m_inc; @@ -51,6 +52,26 @@ NETLIB_DEVICE_WITH_PARAMS(mainclock, ATTR_HOT inline static void mc_update(netlist_net_t &net, const netlist_time curtime); ); +// ---------------------------------------------------------------------------------------- +// clock +// ---------------------------------------------------------------------------------------- + +NETLIB_DEVICE_WITH_PARAMS(clock, + netlist_ttl_input_t m_feedback; + netlist_ttl_output_t m_Q; + + netlist_param_t m_freq; + netlist_time m_inc; +); + +// ---------------------------------------------------------------------------------------- +// solver_clock +// ---------------------------------------------------------------------------------------- + +NETLIB_DEVICE_WITH_PARAMS_DERIVED(solver_clock, clock, +public: +); + // ---------------------------------------------------------------------------------------- // netdev_callback // ---------------------------------------------------------------------------------------- diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c index dcd43412659..bba9780d263 100644 --- a/src/emu/netlist/nl_base.c +++ b/src/emu/netlist/nl_base.c @@ -216,6 +216,11 @@ void netlist_device_t::register_output(netlist_core_device_t &dev, const astring m_setup->register_output(*this, dev, name, port); } +void netlist_device_t::register_terminal(const astring &name, netlist_terminal_t &port) +{ + m_setup->register_terminal(*this,*this,name, port); +} + void netlist_device_t::register_output(const astring &name, netlist_output_t &port) { m_setup->register_output(*this,*this,name, port); @@ -234,7 +239,9 @@ void netlist_device_t::register_input(const astring &name, netlist_input_t &inp, void netlist_device_t::register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, netlist_input_t::net_input_state aState) { in.init_input(dev, aState); - out.init_terminal(dev); + // ensure we are not yet initialized ... + if (!out.net().isRailNet()) + out.init_terminal(dev); //if (in.state() != net_input_t::INP_STATE_PASSIVE) out.net().register_con(in); } @@ -274,6 +281,39 @@ ATTR_COLD netlist_net_t::netlist_net_t(const type_t atype, const family_t afamil m_last.Q = 0; }; +ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet) +{ + if (othernet == NULL) + return; // Nothing to do + + if (this->isRailNet() && othernet->isRailNet()) + fatalerror("Trying to merge to rail nets\n"); + + if (othernet->isRailNet()) + othernet->merge_net(this); + else + { + netlist_terminal_t *p = othernet->m_head; + if (p == NULL) + return; + if (m_head == NULL) + { + m_head = p; + m_head->set_net(*this); + p = p->m_update_list_next; + } + while (p != NULL) + { + netlist_terminal_t *pn = p->m_update_list_next; + p->m_update_list_next = m_head; + p->set_net(*this); + m_head = p; + p = pn; + } + othernet->m_head = NULL; // FIXME: othernet needs to be free'd from memory + } +} + ATTR_COLD void netlist_net_t::register_con(netlist_terminal_t &terminal) { terminal.set_net(*this); @@ -306,30 +346,61 @@ ATTR_HOT inline void netlist_net_t::update_devs() { assert(m_num_cons != 0); - const UINT32 masks[4] = { 1, 5, 3, 1 }; - m_cur = m_new; - m_in_queue = 2; /* mark as taken ... */ - - const UINT32 mask = masks[ (m_last.Q << 1) | m_cur.Q ]; - - netlist_terminal_t *p = m_head; - switch (m_num_cons) - { - case 2: - update_dev(p, mask); - p = p->m_update_list_next; - case 1: - update_dev(p, mask); - break; - default: + //assert(this->isRailNet()); + if (UNEXPECTED(!this->isRailNet())) + { + /* only inputs and terminals connected + * approach: + * + * a) Update voltage on this net + * b) Update devices + * c) If difference old - new > trigger schedule immediate update + * of number of updates < max_update_count + * else clear number of updates + */ + m_in_queue = 2; /* mark as taken ... */ + double gtot = 0; + double iIdr = 0; + netlist_terminal_t *p = m_head; do { - update_dev(p, mask); + p->netdev().update_dev(); + gtot += p->m_g; + iIdr += p->m_Idr; + p = p->m_update_list_next; } while (p != NULL); - break; - } - m_last = m_cur; + m_new.Analog = iIdr / gtot; + printf("New: %f\n", m_new.Analog); + } + else + { + + const UINT32 masks[4] = { 1, 5, 3, 1 }; + m_cur = m_new; + m_in_queue = 2; /* mark as taken ... */ + + const UINT32 mask = masks[ (m_last.Q << 1) | m_cur.Q ]; + + netlist_terminal_t *p = m_head; + switch (m_num_cons) + { + case 2: + update_dev(p, mask); + p = p->m_update_list_next; + case 1: + update_dev(p, mask); + break; + default: + do + { + update_dev(p, mask); + p = p->m_update_list_next; + } while (p != NULL); + break; + } + m_last = m_cur; + } } // ---------------------------------------------------------------------------------------- diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h index be92d32cc70..d4c0cb7383a 100644 --- a/src/emu/netlist/nl_base.h +++ b/src/emu/netlist/nl_base.h @@ -170,17 +170,24 @@ typedef delegate net_update_delegate; #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_BASE(_name, _pclass, _extra, _priv) \ + class _name : public _pclass \ + { \ + public: \ + _name() \ + : _pclass() { } \ + protected: \ + _extra \ + ATTR_HOT void update(); \ + ATTR_HOT void start(); \ + _priv \ + } + +#define NETLIB_DEVICE_DERIVED(_name, _pclass, _priv) \ + NETLIB_DEVICE_BASE(NETLIB_NAME(_name), NETLIB_NAME(_pclass), , _priv) + #define NETLIB_DEVICE(_name, _priv) \ - class NETLIB_NAME(_name) : public netlist_device_t \ - { \ - public: \ - NETLIB_NAME(_name) () \ - : netlist_device_t() { } \ - protected: \ - ATTR_HOT void update(); \ - ATTR_HOT void start(); \ - _priv \ - } + NETLIB_DEVICE_BASE(NETLIB_NAME(_name), netlist_device_t, , _priv) #define NETLIB_SUBDEVICE(_name, _priv) \ class NETLIB_NAME(_name) : public netlist_core_device_t \ @@ -195,17 +202,14 @@ typedef delegate net_update_delegate; } #define NETLIB_DEVICE_WITH_PARAMS(_name, _priv) \ - class NETLIB_NAME(_name) : public netlist_device_t \ - { \ - public: \ - NETLIB_NAME(_name) () \ - : netlist_device_t() { } \ - ATTR_HOT void update_param(); \ - ATTR_HOT void update(); \ - ATTR_HOT void start(); \ - /* protected: */ \ - _priv \ - } + NETLIB_DEVICE_BASE(NETLIB_NAME(_name), netlist_device_t, \ + ATTR_HOT void update_param(); \ + , _priv) + +#define NETLIB_DEVICE_WITH_PARAMS_DERIVED(_name, _pclass, _priv) \ + NETLIB_DEVICE_BASE(NETLIB_NAME(_name), NETLIB_NAME(_pclass), \ + ATTR_HOT void update_param(); \ + , _priv) // ---------------------------------------------------------------------------------------- // forward definitions @@ -287,15 +291,27 @@ public: ATTR_COLD netlist_terminal_t(const type_t atype, const family_t afamily) : netlist_object_t(atype, afamily) + , m_Idr(0.0) + , m_g(NETLIST_GMIN) , m_update_list_next(NULL) , m_netdev(NULL) , m_net(NULL) , m_state(INP_STATE_ACTIVE) {} + ATTR_COLD netlist_terminal_t() + : netlist_object_t(TERMINAL, ANALOG) + , m_Idr(0.0) + , m_update_list_next(NULL) + , m_netdev(NULL) + , m_net(NULL) + , m_state(INP_STATE_ACTIVE) + {} + ATTR_COLD virtual void init_terminal(netlist_core_device_t &dev); ATTR_COLD void set_net(netlist_net_t &anet) { m_net = &anet; } + ATTR_COLD bool has_net() { return (m_net != NULL); } ATTR_HOT inline const netlist_net_t & RESTRICT net() const { return *m_net;} ATTR_HOT inline netlist_net_t & RESTRICT net() { return *m_net;} @@ -306,6 +322,9 @@ public: ATTR_HOT inline netlist_core_device_t & RESTRICT netdev() const { return *m_netdev; } + double m_Idr; // drive current + double m_g; // conductance + netlist_terminal_t *m_update_list_next; private: @@ -421,6 +440,7 @@ public: ATTR_COLD netlist_net_t(const type_t atype, const family_t afamily); ATTR_COLD void register_con(netlist_terminal_t &terminal); + ATTR_COLD void merge_net(netlist_net_t *othernet); ATTR_COLD void register_railterminal(netlist_terminal_t &mr) { assert(m_railterminal == NULL); @@ -447,6 +467,16 @@ public: 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_HOT inline const double Q_Analog() const + { + //assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG); + assert(family() == ANALOG); + return m_cur.Analog; + } + + ATTR_HOT inline void push_to_queue(const netlist_time &delay); + ATTR_HOT bool is_queued() { return m_in_queue == 1; } + protected: /* prohibit use in device functions @@ -458,14 +488,6 @@ protected: assert(family() == LOGIC); return m_cur.Q; } - ATTR_HOT inline const double Q_Analog() const - { - //assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG); - assert(family() == ANALOG); - return m_cur.Analog; - } - - ATTR_HOT inline void push_to_queue(const netlist_time &delay); hybrid_t m_last; hybrid_t m_cur; @@ -670,6 +692,8 @@ public: ATTR_COLD void register_sub(netlist_core_device_t &dev, const astring &name); + ATTR_COLD void register_terminal(const astring &name, netlist_terminal_t &port); + ATTR_COLD void register_output(const astring &name, netlist_output_t &out); ATTR_COLD void register_output(netlist_core_device_t &dev, const astring &name, netlist_output_t &out); @@ -850,6 +874,71 @@ private: double m_high_V; }; +// ---------------------------------------------------------------------------------------- +// nld_twoterm +// ---------------------------------------------------------------------------------------- + +class nld_twoterm : public netlist_device_t +{ +public: + nld_twoterm() + : netlist_device_t(), m_g(0.0), m_V(0.0), m_I(0.0) + { + } + + netlist_terminal_t m_P; + netlist_terminal_t m_N; + +protected: + virtual void start() + { + } + + ATTR_HOT ATTR_ALIGN virtual void update() + { + m_N.m_Idr = (m_P.net().Q_Analog() - m_V) * m_g + m_I; + m_P.m_Idr = (m_N.net().Q_Analog() + m_V) * m_g - m_I; + printf("%f %f %f %f\n", m_N.m_Idr, m_P.m_Idr, m_N.net().Q_Analog(), m_P.net().Q_Analog()); + if (!m_N.net().is_queued() && !m_N.net().isRailNet()) + m_N.net().push_to_queue(NLTIME_FROM_NS(10)); + if (!m_P.net().is_queued() && !m_P.net().isRailNet() ) + m_P.net().push_to_queue(NLTIME_FROM_NS(10)); + } + + double m_g; // conductance + double m_V; // internal voltage source + double m_I; // internal current source +private: +}; + +class nld_R : public nld_twoterm +{ +public: + nld_R() + : nld_twoterm() + { + } + + netlist_param_t m_R; + +protected: + void start() + { + register_terminal("1", m_P); + register_terminal("2", m_N); + + register_param("R", m_R, NETLIST_GMIN); + } + + virtual void update_param() + { + m_g = 1.0 / m_R.Value(); + m_P.m_g = m_g; + m_N.m_g = m_g; + } + +private: +}; // ---------------------------------------------------------------------------------------- // Inline implementations diff --git a/src/emu/netlist/nl_config.h b/src/emu/netlist/nl_config.h index 96af378c357..e68fdf35a27 100644 --- a/src/emu/netlist/nl_config.h +++ b/src/emu/netlist/nl_config.h @@ -38,6 +38,8 @@ #define NETLIST_HIGHIMP_V (1.23456e20) /* some voltage we should never see */ +#define NETLIST_GMIN (1e-9) + typedef UINT8 netlist_sig_t; /* FIXME: We need a different solution to output delegates ! diff --git a/src/emu/netlist/nl_parser.c b/src/emu/netlist/nl_parser.c index 4d08156ade7..a6c05b0cd27 100644 --- a/src/emu/netlist/nl_parser.c +++ b/src/emu/netlist/nl_parser.c @@ -95,7 +95,7 @@ void netlist_parser::netdev_device(const astring &dev_type) m_p++; skipws(); astring output_name = getname2(',', ')'); - NL_VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), dev->m_inputs.item(cnt)->cstr())); + NL_VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), dev->m_terminals.item(cnt)->cstr())); m_setup.register_link(*dev->m_terminals.item(cnt), output_name); skipws(); cnt++; diff --git a/src/emu/netlist/nl_setup.c b/src/emu/netlist/nl_setup.c index 835db508604..a43b9275230 100644 --- a/src/emu/netlist/nl_setup.c +++ b/src/emu/netlist/nl_setup.c @@ -23,6 +23,7 @@ NETLIST_END netlist_setup_t::netlist_setup_t(netlist_base_t &netlist) : m_netlist(netlist) + , m_proxy_cnt(0) { NETLIST_NAME(base)(*this); } @@ -110,6 +111,18 @@ void netlist_setup_t::register_output(netlist_core_device_t &dev, netlist_core_d fatalerror("Error adding output %s to terminal list\n", name.cstr()); } +void netlist_setup_t::register_terminal(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_terminal_t &out) +{ + NL_VERBOSE_OUT(("output %s\n", name.cstr())); + assert(out.isType(netlist_terminal_t::TERMINAL)); + 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 terminal list\n", name.cstr()); +} + void netlist_setup_t::register_input(netlist_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_input_t &inp, netlist_input_t::net_input_state type) { NL_VERBOSE_OUT(("input %s\n", name.cstr())); @@ -176,6 +189,26 @@ netlist_output_t &netlist_setup_t::find_output(const astring &outname_in) return *ret; } +netlist_terminal_t &netlist_setup_t::find_terminal(const astring &terminal_in) +{ + const astring &tname = resolve_alias(terminal_in); + netlist_terminal_t *ret; + + ret = dynamic_cast(m_terminals.find(tname)); + /* look for default */ + if (ret == NULL) + { + /* look for ".Q" std output */ + astring s = tname; + s.cat(".Q"); + ret = dynamic_cast(m_terminals.find(s)); + } + if (ret == NULL) + fatalerror("terminal %s(%s) not found!\n", terminal_in.cstr(), tname.cstr()); + NL_VERBOSE_OUT(("Found input %s\n", tname.cstr())); + return *ret; +} + netlist_param_t &netlist_setup_t::find_param(const astring ¶m_in) { const astring &outname = resolve_alias(param_in); @@ -188,68 +221,163 @@ netlist_param_t &netlist_setup_t::find_param(const astring ¶m_in) return *ret; } + +void netlist_setup_t::connect_input_output(netlist_input_t &in, netlist_output_t &out) +{ + if (out.isFamily(netlist_terminal_t::ANALOG) && in.isFamily(netlist_terminal_t::LOGIC)) + { + nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(in); + astring x = ""; + x.printf("proxy_ad_%d", m_proxy_cnt++); + + proxy->init(*this, x.cstr()); + register_dev(proxy); + + proxy->m_Q.net().register_con(in); + out.net().register_con(proxy->m_I); + + } + else if (out.isFamily(netlist_terminal_t::LOGIC) && in.isFamily(netlist_terminal_t::ANALOG)) + { + //printf("here 1\n"); + nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out); + astring x = ""; + x.printf("proxy_da_%d", m_proxy_cnt++); + proxy->init(*this, x.cstr()); + register_dev(proxy); + + proxy->m_Q.net().register_con(in); + out.net().register_con(proxy->m_I); + } + else + { + out.net().register_con(in); + } +} + +// FIXME: optimize code ... +void netlist_setup_t::connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out) +{ + if (out.isFamily(netlist_terminal_t::ANALOG)) + { + /* no proxy needed, just merge existing terminal net */ + if (in.has_net()) + out.net().merge_net(&in.net()); + else + out.net().register_con(in); + + } + else if (out.isFamily(netlist_terminal_t::LOGIC)) + { + //printf("here 1\n"); + nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out); + astring x = ""; + x.printf("proxy_da_%d", m_proxy_cnt++); + proxy->init(*this, x.cstr()); + register_dev(proxy); + + out.net().register_con(proxy->m_I); + + if (in.has_net()) + proxy->m_Q.net().merge_net(&in.net()); + else + proxy->m_Q.net().register_con(in); + } + else + { + fatalerror("Netlist: Severe Error"); + } +} + +void netlist_setup_t::connect_terminals(netlist_terminal_t &in, netlist_terminal_t &out) +{ + assert(in.isType(netlist_terminal_t::TERMINAL)); + assert(out.isType(netlist_terminal_t::TERMINAL)); + + if (in.has_net() && out.has_net()) + { + in.net().merge_net(&out.net()); + //in.net().register_con(out); + //in.net().register_con(in); + } + else if (out.has_net()) + { + out.net().register_con(in); + //out.net().register_con(out); + } + else if (in.has_net()) + { + in.net().register_con(out); + //in.net().register_con(in); + } + else + { + NL_VERBOSE_OUT(("adding net ...\n")); + in.set_net(*(new netlist_net_t(netlist_object_t::NET, netlist_object_t::ANALOG))); + in.net().init_object(netlist()); + in.net().register_con(out); + in.net().register_con(in); + } +} + 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(); - netlist_input_t *in = dynamic_cast(m_terminals.find(sin)); + NL_VERBOSE_OUT(("Searching for clocks ...\n")); + /* find the main clock ... */ + for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry)) + { + netlist_device_t *dev = entry->object(); + if (dynamic_cast(dev) != NULL) + { + m_netlist.set_mainclock_dev(dynamic_cast(dev)); + } + } - if (in == NULL) - fatalerror("Unable to find %s\n", sin.cstr()); + NL_VERBOSE_OUT(("Resolving ...\n")); + for (tagmap_astring_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry)) + { + const astring t1s = *entry->object(); + const astring t2s = entry->tag(); + netlist_terminal_t &t1 = find_terminal(t1s); + netlist_terminal_t &t2 = find_terminal(t2s); - netlist_output_t &out = find_output(sout->cstr()); - if (out.isFamily(netlist_terminal_t::ANALOG) && in->isFamily(netlist_terminal_t::LOGIC)) - { - nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(*in); - astring x = ""; - x.printf("proxy_ad_%d", proxy_cnt++); + // FIXME: amend device design so that warnings can be turned into errors + // Only variable inputs have this issue + if (t1.isType(netlist_terminal_t::OUTPUT) && t2.isType(netlist_terminal_t::INPUT)) + { + if (t2.has_net()) + mame_printf_warning("Input %s already connected\n", t2s.cstr()); + connect_input_output(dynamic_cast(t2), dynamic_cast(t1)); + } + else if (t1.isType(netlist_terminal_t::INPUT) && t2.isType(netlist_terminal_t::OUTPUT)) + { + if (t1.has_net()) + mame_printf_warning("Input %s already connected\n", t1s.cstr()); + connect_input_output(dynamic_cast(t1), dynamic_cast(t2)); + } + else if (t1.isType(netlist_terminal_t::OUTPUT) && t2.isType(netlist_terminal_t::TERMINAL)) + { + connect_terminal_output(dynamic_cast(t2), dynamic_cast(t1)); + } + else if (t1.isType(netlist_terminal_t::TERMINAL) && t2.isType(netlist_terminal_t::OUTPUT)) + { + connect_terminal_output(dynamic_cast(t1), dynamic_cast(t2)); + } + else if (t1.isType(netlist_terminal_t::TERMINAL) && t2.isType(netlist_terminal_t::TERMINAL)) + { + connect_terminals(dynamic_cast(t1), dynamic_cast(t2)); + } + else + fatalerror("Connecting %s to %s not supported!\n", t1s.cstr(), t2s.cstr()); + } - proxy->init(*this, x.cstr()); - register_dev(proxy); - - proxy->m_Q.net().register_con(*in); - out.net().register_con(proxy->m_I); - - } - else if (out.isFamily(netlist_terminal_t::LOGIC) && in->isFamily(netlist_terminal_t::ANALOG)) - { - //printf("here 1\n"); - nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out); - astring x = ""; - x.printf("proxy_da_%d", proxy_cnt++); - proxy->init(*this, x.cstr()); - register_dev(proxy); - - proxy->m_Q.net().register_con(*in); - out.net().register_con(proxy->m_I); - } - else - { - out.net().register_con(*in); - } - } - - /* find the main clock ... */ - for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry)) - { - netlist_device_t *dev = entry->object(); - if (dynamic_cast(dev) != NULL) - { - m_netlist.set_mainclock_dev(dynamic_cast(dev)); - } - } - - /* print all outputs */ - for (tagmap_terminal_t::entry_t *entry = m_terminals.first(); entry != NULL; entry = m_terminals.next(entry)) - { - ATTR_UNUSED netlist_output_t *out = dynamic_cast(entry->object()); - //if (out != NULL) - //VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr())); - } + /* print all outputs */ + for (tagmap_terminal_t::entry_t *entry = m_terminals.first(); entry != NULL; entry = m_terminals.next(entry)) + { + ATTR_UNUSED netlist_output_t *out = dynamic_cast(entry->object()); + //if (out != NULL) + //VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr())); + } } diff --git a/src/emu/netlist/nl_setup.h b/src/emu/netlist/nl_setup.h index da2796c7fd2..468cb205fdd 100644 --- a/src/emu/netlist/nl_setup.h +++ b/src/emu/netlist/nl_setup.h @@ -28,8 +28,13 @@ NET_REGISTER_DEV(_type ## _ ## sig, _name) #define NET_CONNECT(_name, _input, _output) \ netlist.register_link(# _name "." # _input, # _output); +#define NET_C(_input, _output) \ + netlist.register_link(# _input , # _output); #define NETDEV_PARAM(_name, _val) \ netlist.find_param(# _name).initial(_val); +#define NETDEV_PARAMI(_name, _param, _val) \ + netlist.find_param(# _name "." # _param).initial(_val); + #define NETLIST_NAME(_name) netlist ## _ ## _name @@ -71,6 +76,7 @@ public: netlist_device_t *register_dev(netlist_device_t *dev); void remove_dev(const astring &name); + void register_terminal(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_terminal_t &out); void register_output(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_output_t &out); void register_input(netlist_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_input_t &inp, netlist_input_t::net_input_state type); void register_alias(const astring &alias, const astring &out); @@ -79,6 +85,7 @@ public: void register_link(const astring &sin, const astring &sout); netlist_output_t &find_output(const astring &outname_in); + netlist_terminal_t &find_terminal(const astring &outname_in); netlist_param_t &find_param(const astring ¶m_in); void register_callback(const astring &devname, netlist_output_delegate delegate); @@ -105,6 +112,12 @@ private: tagmap_param_t m_params; tagmap_astring_t m_links; + int m_proxy_cnt; + + void connect_terminals(netlist_terminal_t &in, netlist_terminal_t &out); + void connect_input_output(netlist_input_t &in, netlist_output_t &out); + void connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out); + netlist_output_t *find_output_exact(const astring &outname_in); const astring &resolve_alias(const astring &name) const; }; diff --git a/src/mame/drivers/pong.c b/src/mame/drivers/pong.c index 110d93b421f..ec450f81533 100644 --- a/src/mame/drivers/pong.c +++ b/src/mame/drivers/pong.c @@ -464,6 +464,16 @@ static NETLIST_START(pong_schematics) NETDEV_PARAM(videomix.R1, RES_K(1)) NETDEV_PARAM(videomix.R2, RES_K(1.2)) NETDEV_PARAM(videomix.R3, RES_K(22)) + +#if 0 + NETDEV_ANALOG_CONST(V5, 5) + NETDEV_ANALOG_CONST(V0, 0) + NETDEV_R(R1, 10) + NETDEV_R(R2, 10) + NET_C(V5,R1.1) + NET_C(R1.2, R2.1) + NET_C(R2.2, V0) +#endif NETLIST_END static NETLIST_START(pong)