diff --git a/.gitattributes b/.gitattributes index 32a5c1a6bae..92ebd9fd1c6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2996,6 +2996,7 @@ src/emu/netlist/devices/nld_ne555.h svneol=native#text/plain src/emu/netlist/devices/nld_signal.h svneol=native#text/plain src/emu/netlist/devices/nld_system.c svneol=native#text/plain src/emu/netlist/devices/nld_system.h svneol=native#text/plain +src/emu/netlist/devices/nld_truthtable.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 diff --git a/src/emu/netlist/devices/nld_7400.c b/src/emu/netlist/devices/nld_7400.c index e6025c3bdcb..cb5d7f75faa 100644 --- a/src/emu/netlist/devices/nld_7400.c +++ b/src/emu/netlist/devices/nld_7400.c @@ -5,6 +5,10 @@ #include "nld_7400.h" +#if 0 +UINT32 nld_7400::m_outs[m_size]; +#endif + NETLIB_START(7400_dip) { register_sub(m_1, "1"); diff --git a/src/emu/netlist/devices/nld_7400.h b/src/emu/netlist/devices/nld_7400.h index 3e30bba7c58..0a86609e626 100644 --- a/src/emu/netlist/devices/nld_7400.h +++ b/src/emu/netlist/devices/nld_7400.h @@ -39,7 +39,33 @@ NET_CONNECT(_name, A, _A) \ NET_CONNECT(_name, B, _B) +#if 1 NETLIB_SIGNAL(7400, 2, 0, 0); +#else +#include "nld_truthtable.h" +class nld_7400 : public nld_truthtable_t<2,1> + { + public: + nld_7400 () + : nld_truthtable_t<2,1>() + { + } + void start() + { + static const char *tt[] = { + "A,B,PQ,PA,PB|Q", + "0,X,X,X,X|1", + "X,0,X,X,X|1", + "1,1,X,X,X|0", + "" + }; + setup_tt(tt, m_outs); + } + private: + static UINT32 m_outs[m_size]; +}; +#endif + #define TTL_7400_DIP(_name) \ NET_REGISTER_DEV(7400_dip, _name) diff --git a/src/emu/netlist/devices/nld_7490.c b/src/emu/netlist/devices/nld_7490.c index 623ee0bf982..16cb7d2d7b1 100644 --- a/src/emu/netlist/devices/nld_7490.c +++ b/src/emu/netlist/devices/nld_7490.c @@ -20,6 +20,8 @@ NETLIB_START(7490) register_output("QD", m_Q[3]); save(NAME(m_cnt)); + save(NAME(m_last_A)); + save(NAME(m_last_B)); } @@ -47,18 +49,20 @@ NETLIB_UPDATE(7490) m_cnt = 0; update_outputs(); } - else if (INP_HL(m_A)) + else if (m_last_A && !INPLOGIC(m_A)) // High - Low { m_cnt ^= 1; OUTLOGIC(m_Q[0], m_cnt & 1, delay[0]); } - else if (INP_HL(m_B)) + else if (m_last_B && !INPLOGIC(m_B)) // High - Low { m_cnt += 2; if (m_cnt >= 10) m_cnt = 0; update_outputs(); } + m_last_A = INPLOGIC(m_A); + m_last_B = INPLOGIC(m_B); } NETLIB_FUNC_VOID(7490, update_outputs, (void)) diff --git a/src/emu/netlist/devices/nld_7490.h b/src/emu/netlist/devices/nld_7490.h index 4263ec124da..6029b9837cf 100644 --- a/src/emu/netlist/devices/nld_7490.h +++ b/src/emu/netlist/devices/nld_7490.h @@ -81,6 +81,8 @@ NETLIB_DEVICE(7490, netlist_ttl_input_t m_B; netlist_state_t m_cnt; + netlist_state_t m_last_A; + netlist_state_t m_last_B; netlist_ttl_output_t m_Q[4]; ); diff --git a/src/emu/netlist/devices/nld_74ls629.c b/src/emu/netlist/devices/nld_74ls629.c index 9e177e6096e..e858995fffa 100644 --- a/src/emu/netlist/devices/nld_74ls629.c +++ b/src/emu/netlist/devices/nld_74ls629.c @@ -51,6 +51,7 @@ NETLIB_START(SN74LS629clk) save(NAME(m_enableq)); save(NAME(m_inc)); + save(NAME(m_out)); } NETLIB_RESET(SN74LS629clk) @@ -63,7 +64,8 @@ NETLIB_UPDATE(SN74LS629clk) { if (!m_enableq) { - OUTLOGIC(m_Y, !m_Y.net().as_logic().new_Q(), m_inc); + m_out = m_out ^ 1; + OUTLOGIC(m_Y, m_out, m_inc); } else { @@ -146,12 +148,14 @@ NETLIB_UPDATE(SN74LS629) if (!m_clock.m_enableq && INPLOGIC(m_ENQ)) { m_clock.m_enableq = 1; - OUTLOGIC(m_clock.m_Y, !m_clock.m_Y.net().as_logic().last_Q(), netlist_time::from_nsec(1)); + m_clock.m_out = m_clock.m_out ^ 1; + OUTLOGIC(m_clock.m_Y, m_clock.m_out, netlist_time::from_nsec(1)); } else if (m_clock.m_enableq && !INPLOGIC(m_ENQ)) { m_clock.m_enableq = 0; - OUTLOGIC(m_clock.m_Y, !m_clock.m_Y.net().as_logic().last_Q(), netlist_time::from_nsec(1)); + m_clock.m_out = m_clock.m_out ^ 1; + OUTLOGIC(m_clock.m_Y, m_clock.m_out, netlist_time::from_nsec(1)); } } diff --git a/src/emu/netlist/devices/nld_74ls629.h b/src/emu/netlist/devices/nld_74ls629.h index fd128113160..a3a7b8230e9 100644 --- a/src/emu/netlist/devices/nld_74ls629.h +++ b/src/emu/netlist/devices/nld_74ls629.h @@ -41,6 +41,7 @@ NETLIB_SUBDEVICE(SN74LS629clk, netlist_time m_inc; netlist_state_t m_enableq; + netlist_state_t m_out; ); NETLIB_DEVICE_WITH_PARAMS(SN74LS629, diff --git a/src/emu/netlist/devices/nld_signal.h b/src/emu/netlist/devices/nld_signal.h index 48e03f908d7..fc37aff6284 100644 --- a/src/emu/netlist/devices/nld_signal.h +++ b/src/emu/netlist/devices/nld_signal.h @@ -26,57 +26,6 @@ // net_signal_t // ---------------------------------------------------------------------------------------- -template -class net_signal_base_t : public netlist_device_t -{ -public: - net_signal_base_t() - : netlist_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], netlist_input_t::STATE_INP_ACTIVE); - } - save(NAME(m_active)); - } - - ATTR_COLD void reset() - { - m_Q.initial(1); - m_active = 1; - } - -#if (USE_DEACTIVE_DEVICE) - ATTR_HOT void inc_active() - { - if (++m_active == 1) - { - update(); - } - } - - ATTR_HOT void dec_active() - { - if (--m_active == 0) - { - for (int i = 0; i< _numdev; i++) - m_i[i].inactivate(); - } - } -#endif - -public: - netlist_ttl_input_t m_i[_numdev]; - netlist_ttl_output_t m_Q; - INT32 m_active; -}; - - template class net_signal_t : public netlist_device_t { @@ -207,22 +156,7 @@ public: m_i[0].activate(); m_i[1].activate(); -#if 0 - UINT8 res = _invert ^ 1 ^_check; - 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]);// ? 22000 : 15000); -#else + const UINT8 val = (INPLOGIC(m_i[0]) ^ _check) | ((INPLOGIC(m_i[1]) ^ _check) << 1); UINT8 res = _invert ^ 1 ^_check; switch (val) @@ -238,7 +172,6 @@ public: break; } OUTLOGIC(m_Q, res, times[res]);// ? 22000 : 15000); -#endif } public: @@ -248,71 +181,6 @@ public: }; -// The following did not improve performance -#if 0 - -template -class net_signal_t<3, _check, _invert> : public netlist_device_t -{ -public: - net_signal_t() : netlist_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], netlist_input_t::STATE_INP_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: - netlist_ttl_input_t m_i[3]; - netlist_ttl_output_t m_Q; - INT8 m_active; - -}; - -#endif - - template class net_signal_t<2, _check, _invert> : public net_signal_2inp_t<_check, _invert> { diff --git a/src/emu/netlist/devices/nld_truthtable.h b/src/emu/netlist/devices/nld_truthtable.h new file mode 100644 index 00000000000..1eb069d6612 --- /dev/null +++ b/src/emu/netlist/devices/nld_truthtable.h @@ -0,0 +1,187 @@ +/* + * nld_truthtable.h + * + * Created on: 19 Jun 2014 + * Author: andre + */ + +#ifndef NLD_TRUTHTABLE_H_ +#define NLD_TRUTHTABLE_H_ + +#include "../nl_base.h" + +template +class nld_truthtable_t : public netlist_device_t +{ +public: + + static const int m_size = (1 << (2 * m_NI + m_NO)); + + nld_truthtable_t() + : netlist_device_t(), m_active(1) + { + } + + ATTR_COLD virtual void start() + { + } + + ATTR_COLD void help(UINT32 outs[], int cur, nl_util::pstring_list list, UINT64 state, UINT64 ignore, UINT16 val) + { + pstring elem = list[cur]; + int start = 0; + int end = 0; + int ign = 0; + + if (elem.equals("0")) + { + start = 0; + end = 0; + } + else if (elem.equals("1")) + { + start = 1; + end = 1; + } + else if (elem.equals("X")) + { + start = 0; + end = 1; + ign = 1; + } + for (int i = start; i <= end; i++) + { + const UINT64 nstate = state | (i << cur); + const UINT64 nignore = ignore | (ign << cur); + + if (cur < list.count() - 1) + { + help(outs, cur + 1, list, nstate, nignore, val); + } + else + { + // cutoff previous inputs and outputs for ignore + outs[nstate] = val | ((nignore & ((1 << m_NI)-1)) << m_NO); + } + } + } + + ATTR_COLD void setup_tt(const char **truthtable, UINT32 outs[]) + { + pstring ttline = pstring(truthtable[0]); + truthtable++; + { + nl_util::pstring_list io = nl_util::split(ttline,"|"); + // checks + assert(io.count() == 2); + nl_util::pstring_list inout = nl_util::split(io[0], ","); + assert(inout.count() == 2 * m_NI + m_NO); + nl_util::pstring_list out = nl_util::split(io[1], ","); + assert(out.count() == m_NO); + + for (int i=0; i < m_NI; i++) + { + register_input(inout[i], m_i[i]); + } + for (int i=0; i < m_NO; i++) + { + register_output(out[i], m_Q[i]); + } + //save(NAME(m_active)); + ttline = pstring(truthtable[0]); + truthtable++; + } + + for (int j=0; j < m_size; j++) + outs[j] = -1; + + while (!ttline.equals("")) + { + nl_util::pstring_list io = nl_util::split(ttline,"|"); + // checks + assert(io.count() == 2); + nl_util::pstring_list inout = nl_util::split(io[0], ","); + assert(inout.count() == 2 * m_NI + m_NO); + nl_util::pstring_list out = nl_util::split(io[1], ","); + assert(out.count() == m_NO); + + UINT16 val = 0; + for (int j=0; j> m_NO); + m_ttp = outs; + } + + ATTR_COLD void reset() + { + //m_Q.initial(1); + m_active = 1; + m_last_state = 0; + } + + ATTR_HOT ATTR_ALIGN void update() + { + const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22)}; + + // FIXME: this check is needed because update is called during startup as well + if (UNEXPECTED(USE_DEACTIVE_DEVICE && m_active == 0)) + return; + + UINT32 state = 0; + for (int i=0; i< m_NI; i++) + { + m_i[i].activate(); + state = state | (INPLOGIC(m_i[i]) << i); + } + + const UINT32 nstate = state | (m_last_state << m_NI); + const UINT32 out = m_ttp[nstate] & ((1 << m_NO) - 1); + const UINT32 ign = m_ttp[nstate] >> m_NO; + + for (int i=0; i< m_NI; i++) + if (ign & (1 << i)) + m_i[i].inactivate(); + + for (int i=0; i> i) & 1, times[(out >> i) & 1]);// ? 22000 : 15000); + m_last_state = (state << m_NO) | out; + + } + + +#if (USE_DEACTIVE_DEVICE) + ATTR_HOT void inc_active() + { + if (++m_active == 1) + { + update(); + } + } + + ATTR_HOT void dec_active() + { + if (--m_active == 0) + { + for (int i = 0; i< m_NI; i++) + m_i[i].inactivate(); + } + } +#endif + +public: + netlist_ttl_input_t m_i[m_NI]; + netlist_ttl_output_t m_Q[m_NO]; + + UINT32 *m_ttp; + INT32 m_active; + UINT32 m_last_state; +}; + +#endif /* NLD_TRUTHTABLE_H_ */ diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c index 4b2bd420c16..99d3dd0ace0 100644 --- a/src/emu/netlist/nl_base.c +++ b/src/emu/netlist/nl_base.c @@ -455,7 +455,6 @@ ATTR_COLD netlist_net_t::netlist_net_t(const family_t afamily) : netlist_object_t(NET, afamily) , m_new_Q(0) , m_cur_Q (0) - , m_last_Q(0) , m_railterminal(NULL) , m_time(netlist_time::zero) , m_active(0) @@ -486,7 +485,6 @@ ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term) { if (m_active == 1 && m_in_queue > 0) { - m_last_Q = m_cur_Q; railterminal().netdev().inc_active(); m_cur_Q = m_new_Q; } @@ -501,7 +499,7 @@ ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term) } else { - m_cur_Q = m_last_Q = m_new_Q; + m_cur_Q = m_new_Q; m_in_queue = 2; } } @@ -541,7 +539,6 @@ ATTR_COLD void netlist_net_t::save_register() save(NAME(m_active)); save(NAME(m_in_queue)); save(NAME(m_cur_Analog)); - save(NAME(m_last_Q)); save(NAME(m_cur_Q)); save(NAME(m_new_Q)); netlist_object_t::save_register(); @@ -565,13 +562,13 @@ ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs() assert(this->isRailNet()); const UINT32 masks[4] = { 1, 5, 3, 1 }; - const UINT32 mask = masks[ (m_last_Q << 1) | m_new_Q ]; + const UINT32 mask = masks[ (m_cur_Q << 1) | m_new_Q ]; netlist_core_terminal_t *p = m_list_active.first(); m_in_queue = 2; /* mark as taken ... */ m_cur_Q = m_new_Q; - switch (m_active) + switch (m_active) { case 2: update_dev(p, mask); @@ -588,7 +585,7 @@ ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs() } break; } - m_last_Q = m_cur_Q; + } ATTR_COLD void netlist_net_t::reset() @@ -597,7 +594,6 @@ ATTR_COLD void netlist_net_t::reset() m_active = 0; m_in_queue = 2; - m_last_Q = 0; m_new_Q = 0; m_cur_Q = 0; m_cur_Analog = 0.0; diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h index cff28224f7c..6a937eb171d 100644 --- a/src/emu/netlist/nl_base.h +++ b/src/emu/netlist/nl_base.h @@ -629,7 +629,6 @@ protected: //FIXME: needed by current solver code netlist_sig_t m_new_Q; netlist_sig_t m_cur_Q; - netlist_sig_t m_last_Q; private: @@ -663,11 +662,6 @@ public: return m_cur_Q; } - 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; @@ -691,7 +685,6 @@ public: { m_cur_Q = val; m_new_Q = val; - m_last_Q = val; } /* internal state support @@ -986,21 +979,6 @@ public: out.set_Q(val, delay); } - ATTR_HOT inline bool INP_CHANGED(const netlist_logic_input_t &inp) const - { - return (inp.last_Q() != inp.Q()); - } - - ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const - { - return ((inp.last_Q() & !inp.Q()) == 1); - } - - ATTR_HOT inline bool INP_LH(const netlist_logic_input_t &inp) const - { - return ((!inp.last_Q() & inp.Q()) == 1); - } - ATTR_HOT inline const double INPANALOG(const netlist_analog_input_t &inp) const { return inp.Q_Analog(); } ATTR_HOT inline const double TERMANALOG(const netlist_terminal_t &term) const { return term.net().as_analog().Q_Analog(); } @@ -1358,11 +1336,6 @@ ATTR_HOT inline const netlist_sig_t netlist_logic_input_t::Q() const return net().as_logic().Q(); } -ATTR_HOT inline const netlist_sig_t netlist_logic_input_t::last_Q() const -{ - return net().as_logic().last_Q(); -} - ATTR_HOT inline const double netlist_analog_input_t::Q_Analog() const { return net().as_analog().Q_Analog(); diff --git a/src/emu/netlist/nl_config.h b/src/emu/netlist/nl_config.h index 20ce161dd62..972094ae324 100644 --- a/src/emu/netlist/nl_config.h +++ b/src/emu/netlist/nl_config.h @@ -23,8 +23,13 @@ */ #define USE_PMFDELEGATES (0) -// This increases performance in circuits with a lot of gates -// but is not guaranteed to be absolutely timing correct. +/* + * This increases performance in circuits with a lot of gates + * but is not guaranteed to be absolutely timing correct. + * + * Performance increase about 10% + * + */ #define USE_DEACTIVE_DEVICE (0)