diff --git a/src/emu/machine/net_lib.c b/src/emu/machine/net_lib.c index e1b452d69f0..e7754edadfd 100644 --- a/src/emu/machine/net_lib.c +++ b/src/emu/machine/net_lib.c @@ -47,47 +47,44 @@ #include "net_lib.h" - -NETLIB_START(netdev_const) +NETLIB_START(netdev_logic_input) { - register_output("Q", &m_Q); - register_param("CONST", &m_const, 0.0); + register_output("Q", m_Q); } -NETLIB_UPDATE(netdev_const) +NETLIB_UPDATE(netdev_logic_input) { } -NETLIB_UPDATE_PARAM(netdev_const) +NETLIB_START(netdev_analog_input) { - m_Q.setTo(m_const.ValueInt()); + register_output("Q", m_Q); } -NETLIB_START(netdev_input) -{ - register_output("Q", &m_Q); -} - -NETLIB_UPDATE(netdev_input) +NETLIB_UPDATE(netdev_analog_input) { } -NETLIB_START(netdev_delay_lh) +NETLIB_START(netdev_clock) { - register_input("CLK", &m_clk); - register_input("D", &m_D, NET_INP_TYPE_PASSIVE); - register_output("Q", &m_Q); + 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); - m_lastclk = nst_LOW; - m_Q.initial(1); } -NETLIB_UPDATE(netdev_delay_lh) +NETLIB_UPDATE_PARAM(netdev_clock) { - UINT8 oclk = m_lastclk; - m_lastclk = INPVAL(m_clk); - if (!oclk && m_lastclk) - m_Q.setTo(INPVAL(m_D)); + m_inc = netlist_time::from_hz(m_freq.Value()*2); +} + +NETLIB_UPDATE(netdev_clock) +{ + m_Q.setToPS(!m_Q.new_Q(), m_inc ); } NETLIB_START(nicMultiSwitch) @@ -100,18 +97,20 @@ NETLIB_START(nicMultiSwitch) for (i=0; i<8; i++) { - register_input(sIN[i], &m_I[i]); - m_I[i].o = GETINPPTR(m_low); + register_input(sIN[i], m_I[i]); + //register_link_internal(m_I[i], m_low); + m_I[i].set_output( GETINPPTR(m_low)); } - register_param("POS", &m_POS); - register_output("Q", &m_Q); + register_param("POS", m_POS); + register_output("Q", m_Q); m_variable_input_count = true; } NETLIB_UPDATE(nicMultiSwitch) { - m_Q.setTo(INPVAL(m_I[m_position])); + assert(m_position<8); + m_Q.setToPS(INPANALOG(m_I[m_position]), NLTIME_FROM_NS(1)); } NETLIB_UPDATE_PARAM(nicMultiSwitch) @@ -120,12 +119,60 @@ NETLIB_UPDATE_PARAM(nicMultiSwitch) update(); } +NETLIB_START(nicMixer8) +{ + static const char *sI[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" }; + static const char *sR[8] = { "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8" }; + int i; + + m_low.initial(0); + + for (i=0; i<8; i++) + { + register_input(sI[i], m_I[i]); + m_I[i].set_output(GETINPPTR(m_low)); + register_param(sR[i], m_R[i], 1e12); + } + register_output("Q", m_Q); + + m_variable_input_count = true; +} + +NETLIB_UPDATE(nicMixer8) +{ + int i; + double r = 0; + + for (i=0; i<8; i++) + { + r += m_w[i] * INPANALOG(m_I[i]); + } + m_Q.setToPS(r, NLTIME_IMMEDIATE); +} + +NETLIB_UPDATE_PARAM(nicMixer8) +{ + double t = 0; + int i; + + for (i=0; i<8; i++) + t += 1.0 / m_R[i].Value(); + t = 1.0 / t; + + for (i=0; i<8; i++) + m_w[i] = t / m_R[i].Value(); +} + + + NETLIB_START(nicRSFF) { - register_input("S", &m_S); - register_input("R", &m_R); - register_output("Q", &m_Q); - register_output("QQ", &m_QQ); + register_input("S", m_S); + register_input("R", m_R); + register_output("Q", m_Q); + register_output("QQ", m_QQ); + m_Q.initial(0); + m_QQ.initial(1); } NETLIB_UPDATE(nicRSFF) @@ -145,134 +192,137 @@ NETLIB_UPDATE(nicRSFF) NETLIB_START(nicNE555N_MSTABLE) { - register_input("TRIG", &m_trigger); - register_output("Q", &m_Q); - register_param("R", &m_R); - register_param("C", &m_C); - register_param("VS", &m_VS, 5.0); - register_param("VL", &m_VL, 0.0 *5.0); - register_param("VT", &m_VT, 0.67*5.0); + register_input("TRIG", m_trigger); + register_input("CV", m_CV); - m_Q.initial(0); + register_output("Q", m_Q); + register_param("R", m_R); + register_param("C", m_C); + register_param("VS", m_VS, 5.0); + register_param("VL", m_VL, 0.0 *5.0); - m_timer = m_setup->netlist().alloc_timer(this, 0); + m_THRESHOLD_OUT.set_netdev(this); + register_link_internal(m_THRESHOLD, m_THRESHOLD_OUT); + + m_Q.initial(5.0 * 0.4); + m_last = false; +} + +INLINE double nicNE555N_cv(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) +{ + double ret = v; + if (ret > dev.m_VS.Value() - a) + ret = dev.m_VS.Value() - a; + if (ret < b) + ret = b; + return ret; } NETLIB_UPDATE_PARAM(nicNE555N_MSTABLE) { - double vt = m_VT.Value(); - double vl = m_VL.Value(); - - if (vt > m_VS.Value()-0.7) - vt = m_VS.Value()-0.7; - - if (vt < 1.4) - vt = 1.4; - - if (vt nicNE555N_cv(*this)); + bool btrig = (INPANALOG(m_trigger) > nicNE555N_cv(*this) * 0.5); + bool out = m_last; + + if (!btrig) { - if (m_last && !INPVAL(m_trigger)) - { - m_fired = 0; - m_timer->adjust_timer(m_time); - m_Q.set(); - } + out = true; } - else if (m_fired) + else if (bthresh) { - if (INPVAL(m_trigger)) - m_Q.clear(); + out = false; } - m_last = INPVAL(m_trigger); + + if (!m_last && out) + { + double vt = nicNE555N_cv(*this); + double vl = m_VL.Value(); + double time; + + vt = nicNE555N_clamp(*this, vt, 0.7, 1.4); + // FIXME : m_CV should be on a sub device ... + + if (vt> 0) & 1); - m_SB.setTo((r >> 1) & 1); - m_SC.setTo((r >> 2) & 1); - m_SD.setTo((r >> 3) & 1); - m_CO.setTo((r >> 4) & 1); + m_SA.setToPS((r >> 0) & 1, NLTIME_FROM_NS(23)); + m_SB.setToPS((r >> 1) & 1, NLTIME_FROM_NS(23)); + m_SC.setToPS((r >> 2) & 1, NLTIME_FROM_NS(23)); + m_SD.setToPS((r >> 3) & 1, NLTIME_FROM_NS(23)); + m_CO.setToPS((r >> 4) & 1, NLTIME_FROM_NS(23)); } } NETLIB_START(nic7490) { - m_lastclk = 0; m_cnt = 0; - register_input("CLK", &m_clk); - register_input("R1", &m_R1); - register_input("R2", &m_R2); - register_input("R91", &m_R91); - register_input("R92", &m_R92); + register_input("CLK", m_clk); + register_input("R1", m_R1); + register_input("R2", m_R2); + register_input("R91", m_R91); + register_input("R92", m_R92); - register_output("QA", &m_QA); - register_output("QB", &m_QB); - register_output("QC", &m_QC); - register_output("QD", &m_QD); + register_output("QA", m_QA); + register_output("QB", m_QB); + register_output("QC", m_QC); + register_output("QD", m_QD); } NETLIB_UPDATE(nic7490) { - UINT8 old_clk = m_lastclk; - m_lastclk = INPVAL(m_clk); - - if (UNEXPECTED(INPVAL(m_R91) & INPVAL(m_R92))) + if (INPVAL(m_R91) & INPVAL(m_R92)) { m_cnt = 9; update_outputs(); } - else if (UNEXPECTED(INPVAL(m_R1) & INPVAL(m_R2))) + else if (INPVAL(m_R1) & INPVAL(m_R2)) { m_cnt = 0; update_outputs(); } - else if (old_clk & !m_lastclk) + else if (INPVAL_LAST(m_clk) & !INPVAL(m_clk)) { m_cnt++; if (m_cnt >= 10) @@ -449,44 +551,102 @@ NETLIB_UPDATE(nic7490) NETLIB_FUNC_VOID(nic7490, update_outputs) { - m_QA.setTo((m_cnt >> 0) & 1); - m_QB.setTo((m_cnt >> 1) & 1); - m_QC.setTo((m_cnt >> 2) & 1); - m_QD.setTo((m_cnt >> 3) & 1); + m_QA.setToPS((m_cnt >> 0) & 1, NLTIME_FROM_NS(18)); + m_QB.setToPS((m_cnt >> 1) & 1, NLTIME_FROM_NS(36)); + m_QC.setToPS((m_cnt >> 2) & 1, NLTIME_FROM_NS(54)); + m_QD.setToPS((m_cnt >> 3) & 1, NLTIME_FROM_NS(72)); } +#if 1 NETLIB_START(nic7493) { - m_lastclk = 0; - m_cnt = 0; + register_subdevice(A); + register_subdevice(B); + register_subdevice(C); + register_subdevice(D); - register_input("CLK", &m_clk); - register_input("R1", &m_R1); - register_input("R2", &m_R2); + register_input(A, "CLKA", A.m_I, net_input_t::INP_STATE_HL); + register_input(B, "CLKB", B.m_I, net_input_t::INP_STATE_HL); + register_input("R1", m_R1); + register_input("R2", m_R2); - register_output("QA", &m_QA); - register_output("QB", &m_QB); - register_output("QC", &m_QC); - register_output("QD", &m_QD); + register_output(A, "QA", A.m_Q); + register_output(B, "QB", B.m_Q); + 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); + register_link_internal(D, D.m_I, C.m_Q); + +} + +NETLIB_UPDATE(nic7493ff) +{ + //if INP_LAST(m_I) && !INP(m_I)) + m_Q.setToNoCheckPS(!m_Q.new_Q(), NLTIME_FROM_NS(18)); } NETLIB_UPDATE(nic7493) { - UINT8 old_clk = m_lastclk; - m_lastclk = INPVAL(m_clk); + net_sig_t r = INPVAL(m_R1) & INPVAL(m_R2); - if (UNEXPECTED(INPVAL(m_R1) & INPVAL(m_R2))) + if (r) { - if (EXPECTED(m_cnt > 0)) + //printf("%s reset\n", name()); + A.m_I.inactivate(); + A.m_Q.setToPS(0, NLTIME_FROM_NS(40)); + B.m_I.inactivate(); + B.m_Q.setToPS(0, NLTIME_FROM_NS(40)); + C.m_I.inactivate(); + C.m_Q.setToPS(0, NLTIME_FROM_NS(40)); + D.m_I.inactivate(); + D.m_Q.setToPS(0, NLTIME_FROM_NS(40)); + } + else + { + A.m_I.activate_hl(); + B.m_I.activate_hl(); + C.m_I.activate_hl(); + D.m_I.activate_hl(); + //printf("%s enable\n", name()); + } +} +#else + +NETLIB_START(nic7493) +{ + m_cnt = 0; + + register_input("CLK", m_clk, net_input_t::INP_STATE_HL); + register_input("R1", m_R1); + register_input("R2", m_R2); + + register_output("QA", m_QA); + register_output("QB", m_QB); + register_output("QC", m_QC); + register_output("QD", m_QD); +} + +NETLIB_UPDATE(nic7493) +{ + //UINT8 old_clk = m_lastclk; + //m_lastclk = INPVAL(m_clk); + + //printf("%s %d %d %d %d %d %d\n", name(), m_cnt, old_clk, m_QA.Q(), m_QB.Q(), m_QC.Q(), m_QD.Q()); + if (INPVAL(m_R1) & INPVAL(m_R2)) + { + if (m_cnt > 0) { m_cnt = 0; - m_QA.setTo(0, 40); - m_QB.setTo(0, 40); - m_QC.setTo(0, 40); - m_QD.setTo(0, 40); + m_QA.setToPS(0, 40000); + m_QB.setToPS(0, 40000); + m_QC.setToPS(0, 40000); + m_QD.setToPS(0, 40000); } } - else if (EXPECTED(old_clk & !m_lastclk)) + //else if (old_clk & !m_lastclk) + else if (INPVAL_LAST(m_clk) & !INPVAL(m_clk)) { m_cnt++; m_cnt &= 0x0f; @@ -497,90 +657,127 @@ NETLIB_UPDATE(nic7493) NETLIB_FUNC_VOID(nic7493, update_outputs) { if (m_cnt & 1) - m_QA.setToNoCheck(1, 16); + m_QA.setToNoCheckPS(1, 16000); else { - m_QA.setToNoCheck(0, 16); + m_QA.setToNoCheckPS(0, 16000); switch (m_cnt) { case 0x00: - m_QB.setToNoCheck(0, 34); - m_QC.setToNoCheck(0, 48); - m_QD.setToNoCheck(0, 70); + m_QB.setToNoCheckPS(0, 34000); + m_QC.setToNoCheckPS(0, 48000); + m_QD.setToNoCheckPS(0, 70000); break; case 0x02: case 0x06: case 0x0A: case 0x0E: - m_QB.setToNoCheck(1, 34); + m_QB.setToNoCheckPS(1, 34000); break; case 0x04: case 0x0C: - m_QB.setToNoCheck(0, 34); - m_QC.setToNoCheck(1, 48); + m_QB.setToNoCheckPS(0, 34000); + m_QC.setToNoCheckPS(1, 48000); break; case 0x08: - m_QB.setToNoCheck(0, 34); - m_QC.setToNoCheck(0, 48); - m_QD.setToNoCheck(1, 70); + m_QB.setToNoCheckPS(0, 34000); + m_QC.setToNoCheckPS(0, 48000); + m_QD.setToNoCheckPS(1, 70000); break; } } } - +#endif NETLIB_START(nic74107A) { - register_input("CLK", &m_clk); - register_input("J", &m_J, NET_INP_TYPE_PASSIVE); - register_input("K", &m_K, NET_INP_TYPE_PASSIVE); - register_input("CLRQ", &m_clrQ); - register_output("Q", &m_Q); - register_output("QQ", &m_QQ); + register_subdevice(sub); - m_lastclk = 0; - m_Q.initial(0); - m_QQ.initial(1); + register_input(sub, "CLK", sub.m_clk, net_input_t::INP_STATE_HL); + register_input("J", m_J); + register_input("K", m_K); + register_input("CLRQ", m_clrQ); + register_output(sub, "Q", sub.m_Q); + register_output(sub, "QQ", sub.m_QQ); + + sub.m_Q.initial(0); + sub.m_QQ.initial(1); } -INLINE void nic74107A_newstate(UINT8 state, net_output_t &Q, net_output_t &QQ) +INLINE void nic74107A_newstate(UINT8 state, ttl_output_t &Q, ttl_output_t &QQ) { - if (state != Q.Q()) + if (state != Q.new_Q()) { - Q.setToNoCheck(state, state ? 40 : 25); - QQ.setToNoCheck(!state, state ? 25 : 40); + if (state) + { + Q.setToNoCheckPS(1, NLTIME_FROM_NS(40)); + QQ.setToNoCheckPS(0, NLTIME_FROM_NS(25)); + } + else + { + Q.setToNoCheckPS(0, NLTIME_FROM_NS(25)); + QQ.setToNoCheckPS(1, NLTIME_FROM_NS(40)); + } + } +} + +NETLIB_UPDATE(nic74107Asub) +{ + //if (INPVAL_LAST(m_clk) & !INPVAL(m_clk)) + { + nic74107A_newstate((!m_Q.new_Q() & m_Q1) | (m_Q.new_Q() & m_Q2) | m_F, m_Q, m_QQ); + if (!m_Q1) + m_clk.inactivate(); } } NETLIB_UPDATE(nic74107A) { - UINT8 oclk = m_lastclk; - m_lastclk = INPVAL(m_clk); - - if (!INPVAL(m_clrQ)) - nic74107A_newstate(0, m_Q, m_QQ); - else if (oclk & !m_lastclk) + if (INPVAL(m_J) & INPVAL(m_K)) { - if (EXPECTED(INPVAL(m_J) & INPVAL(m_K))) - nic74107A_newstate(!m_Q.Q(), m_Q, m_QQ); - else if (!INPVAL(m_J) & INPVAL(m_K)) - nic74107A_newstate(0, m_Q, m_QQ); - else if (INPVAL(m_J) & !INPVAL(m_K)) - nic74107A_newstate(1, m_Q, m_QQ); + sub.m_Q1 = 1; + sub.m_Q2 = 0; + sub.m_F = 0; } + else if (!INPVAL(m_J) & INPVAL(m_K)) + { + sub.m_Q1 = 0; + sub.m_Q2 = 0; + sub.m_F = 0; + } + else if (INPVAL(m_J) & !INPVAL(m_K)) + { + sub.m_Q1 = 0; + sub.m_Q2 = 0; + sub.m_F = 1; + } + else + { + sub.m_Q1 = 0; + sub.m_Q2 = 1; + sub.m_F = 0; + sub.m_clk.inactivate(); + } + if (!INPVAL(m_clrQ)) + { + sub.m_clk.inactivate(); + nic74107A_newstate(0, sub.m_Q, sub.m_QQ); + } + if (!sub.m_Q2 && INPVAL(m_clrQ)) + sub.m_clk.activate_hl(); } NETLIB_START(nic74153) { - register_input("A1", &m_I[0]); - register_input("A2", &m_I[1]); - register_input("A3", &m_I[2]); - register_input("A4", &m_I[3]); - register_input("A", &m_A); - register_input("B", &m_B); - register_input("GA", &m_GA); + register_input("A1", m_I[0]); + register_input("A2", m_I[1]); + register_input("A3", m_I[2]); + register_input("A4", m_I[3]); + register_input("A", m_A); + register_input("B", m_B); + register_input("GA", m_GA); - register_output("AY", &m_AY); + register_output("AY", m_AY); } NETLIB_UPDATE(nic74153) @@ -588,76 +785,84 @@ NETLIB_UPDATE(nic74153) if (!INPVAL(m_GA)) { UINT8 chan = (INPVAL(m_A) | (INPVAL(m_B)<<1)); - m_AY.setTo(INPVAL(m_I[chan])); + UINT8 t = INPVAL(m_I[chan]); + m_AY.setToPS(t, t ? NLTIME_FROM_NS(18) : NLTIME_FROM_NS(23)); /* data to y only, FIXME */ } else - m_AY.clear(); + { + m_AY.setToPS(0, NLTIME_FROM_NS(23)); + } } NETLIB_START(nic9316) { - m_lastclk = 0; - m_cnt = 0; + register_subdevice(sub); + sub.m_cnt = 0; - register_input("CLK", &m_clk); - register_input("ENP", &m_ENP, NET_INP_TYPE_PASSIVE); - register_input("ENT", &m_ENT); - register_input("CLRQ", &m_CLRQ); - register_input("LOADQ", &m_LOADQ, NET_INP_TYPE_PASSIVE); - register_input("A", &m_A, NET_INP_TYPE_PASSIVE); - register_input("B", &m_B, NET_INP_TYPE_PASSIVE); - register_input("C", &m_C, NET_INP_TYPE_PASSIVE); - register_input("D", &m_D, NET_INP_TYPE_PASSIVE); + register_input(sub, "CLK", sub.m_clk, net_input_t::INP_STATE_LH); + register_input("ENP", m_ENP); + register_input("ENT", sub.m_ENT); + register_input("CLRQ", m_CLRQ); + register_input("LOADQ", sub.m_LOADQ, net_input_t::INP_STATE_ACTIVE); - register_output("QA", &m_QA); - register_output("QB", &m_QB); - register_output("QC", &m_QC); - register_output("QD", &m_QD); - register_output("RC", &m_RC); + register_input(sub, "A", sub.m_A, net_input_t::INP_STATE_PASSIVE); + register_input(sub, "B", sub.m_B, net_input_t::INP_STATE_PASSIVE); + register_input(sub, "C", sub.m_C, net_input_t::INP_STATE_PASSIVE); + register_input(sub, "D", sub.m_D, net_input_t::INP_STATE_PASSIVE); + + register_output(sub, "QA", sub.m_QA); + register_output(sub, "QB", sub.m_QB); + register_output(sub, "QC", sub.m_QC); + register_output(sub, "QD", sub.m_QD); + register_output(sub, "RC", sub.m_RC); + +} + +NETLIB_UPDATE(nic9316sub) +{ + //if (!INP_LAST(m_clk) & INP(m_clk)) + { + if (INPVAL(m_LOADQ)) + { + m_cnt = ( m_cnt + 1) & 0x0f; + update_outputs(); + m_RC.setToPS(m_cnt == 0x0f, NLTIME_FROM_NS(20)); + } + else + { + m_cnt = (INPVAL_PASSIVE(m_D) << 3) | (INPVAL_PASSIVE(m_C) << 2) | (INPVAL_PASSIVE(m_B) << 1) | (INPVAL_PASSIVE(m_A) << 0); + update_outputs_all(); + m_RC.setToPS(INPVAL(m_ENT) & (m_cnt == 0x0f), NLTIME_FROM_NS(20)); + } + } } NETLIB_UPDATE(nic9316) { - UINT8 old_clk = m_lastclk; - m_lastclk = INPVAL(m_clk); - - if (EXPECTED(INPVAL(m_CLRQ))) + if ((!INPVAL(sub.m_LOADQ) | (INPVAL(sub.m_ENT) & INPVAL(m_ENP))) & INPVAL(m_CLRQ)) + sub.m_clk.activate_lh(); + else { - if (EXPECTED(!old_clk & m_lastclk)) + sub.m_clk.inactivate(); + if (!INPVAL(m_CLRQ) & (sub.m_cnt>0)) { - if (EXPECTED(INPVAL(m_LOADQ))) - { - if (EXPECTED(INPVAL(m_ENP) & INPVAL(m_ENT))) - { - m_cnt = ( m_cnt + 1) & 0x0f; - update_outputs(); - } - } - else - { - m_cnt = (INPVAL(m_D) << 3) | (INPVAL(m_C) << 2) | (INPVAL(m_B) << 1) | (INPVAL(m_A) << 0); - update_outputs_all(); - } + sub.m_cnt = 0; + sub.update_outputs(); + sub.m_RC.setToPS(0, NLTIME_FROM_NS(20)); } - m_RC.setTo((INPVAL(m_ENT) & (m_cnt == 0x0f)), 20); - } - else if (m_cnt>0) - { - m_cnt = 0; - update_outputs(); - m_RC.setTo(0, 20); } + sub.m_RC.setToPS(INPVAL(sub.m_ENT) & (sub.m_cnt == 0x0f), NLTIME_FROM_NS(20)); } -NETLIB_FUNC_VOID(nic9316, update_outputs_all) +NETLIB_FUNC_VOID(nic9316sub, update_outputs_all) { - m_QA.setTo((m_cnt >> 0) & 1, 20); - m_QB.setTo((m_cnt >> 1) & 1, 20); - m_QC.setTo((m_cnt >> 2) & 1, 20); - m_QD.setTo((m_cnt >> 3) & 1, 20); + m_QA.setToPS((m_cnt >> 0) & 1, NLTIME_FROM_NS(20)); + m_QB.setToPS((m_cnt >> 1) & 1, NLTIME_FROM_NS(20)); + m_QC.setToPS((m_cnt >> 2) & 1, NLTIME_FROM_NS(20)); + m_QD.setToPS((m_cnt >> 3) & 1, NLTIME_FROM_NS(20)); } -NETLIB_FUNC_VOID(nic9316, update_outputs) +NETLIB_FUNC_VOID(nic9316sub, update_outputs) { #if 0 m_QA.setTo((m_cnt >> 0) & 1, 20); @@ -665,33 +870,33 @@ NETLIB_FUNC_VOID(nic9316, update_outputs) m_QC.setTo((m_cnt >> 2) & 1, 20); m_QD.setTo((m_cnt >> 3) & 1, 20); #else - if (m_cnt & 1) - m_QA.setToNoCheck(1, 20); + if ((m_cnt & 1) == 1) + m_QA.setToNoCheckPS(1, NLTIME_FROM_NS(20)); else { - m_QA.setToNoCheck(0, 20); + m_QA.setToNoCheckPS(0, NLTIME_FROM_NS(20)); switch (m_cnt) { case 0x00: - m_QB.setToNoCheck(0, 20); - m_QC.setToNoCheck(0, 20); - m_QD.setToNoCheck(0, 20); + m_QB.setToNoCheckPS(0, NLTIME_FROM_NS(20)); + m_QC.setToNoCheckPS(0, NLTIME_FROM_NS(20)); + m_QD.setToNoCheckPS(0, NLTIME_FROM_NS(20)); break; case 0x02: case 0x06: case 0x0A: case 0x0E: - m_QB.setToNoCheck(1, 20); + m_QB.setToNoCheckPS(1, NLTIME_FROM_NS(20)); break; case 0x04: case 0x0C: - m_QB.setToNoCheck(0, 20); - m_QC.setToNoCheck(1, 20); + m_QB.setToNoCheckPS(0, NLTIME_FROM_NS(20)); + m_QC.setToNoCheckPS(1, NLTIME_FROM_NS(20)); break; case 0x08: - m_QB.setToNoCheck(0, 20); - m_QC.setToNoCheck(0, 20); - m_QD.setToNoCheck(1, 20); + m_QB.setToNoCheckPS(0, NLTIME_FROM_NS(20)); + m_QC.setToNoCheckPS(0, NLTIME_FROM_NS(20)); + m_QD.setToNoCheckPS(1, NLTIME_FROM_NS(20)); break; } @@ -699,16 +904,19 @@ NETLIB_FUNC_VOID(nic9316, update_outputs) #endif } -#define ENTRY(_nic, _name) new net_dev_t_factory< _nic >( # _name, # _nic ), +#define ENTRY(_nic, _name) new net_device_t_factory< _nic >( # _name, # _nic ), -static net_dev_t_base_factory *netregistry[] = +static net_device_t_base_factory *netregistry[] = { - ENTRY(netdev_const, NETDEV_CONST) - ENTRY(netdev_input, NETDEV_INPUT) - ENTRY(netdev_callback, NETDEV_CALLBACK) - ENTRY(nicMultiSwitch, NETDEV_SWITCH2) - ENTRY(netdev_delay_lh, NETDEV_DELAY_RAISE) + ENTRY(netdev_ttl_const, NETDEV_TTL_CONST) + ENTRY(netdev_analog_const, NETDEV_ANALOG_CONST) + ENTRY(netdev_logic_input, NETDEV_LOGIC_INPUT) + ENTRY(netdev_analog_input, NETDEV_ANALOG_INPUT) + ENTRY(netdev_clock, NETDEV_CLOCK) + ENTRY(netdev_callback, NETDEV_CALLBACK) + ENTRY(nicMultiSwitch, NETDEV_SWITCH2) ENTRY(nicRSFF, NETDEV_RSFF) + ENTRY(nicMixer8, NETDEV_MIXER) ENTRY(nic7400, TTL_7400_NAND) ENTRY(nic7402, TTL_7402_NOR) ENTRY(nic7404, TTL_7404_INVERT) @@ -732,9 +940,9 @@ static net_dev_t_base_factory *netregistry[] = NULL }; -net_dev_t *net_create_device_by_classname(const char *classname, netlist_setup_t *setup, const char *icname) +net_device_t *net_create_device_by_classname(const char *classname, netlist_setup_t *setup, const char *icname) { - net_dev_t_base_factory **p = &netregistry[0]; + net_device_t_base_factory **p = &netregistry[0]; while (p != NULL) { if (strcmp((*p)->classname(), classname) == 0) @@ -744,9 +952,9 @@ net_dev_t *net_create_device_by_classname(const char *classname, netlist_setup_t fatalerror("Class %s required for IC %s not found!", classname, icname); } -net_dev_t *net_create_device_by_name(const char *name, netlist_setup_t *setup, const char *icname) +net_device_t *net_create_device_by_name(const char *name, netlist_setup_t *setup, const char *icname) { - net_dev_t_base_factory **p = &netregistry[0]; + net_device_t_base_factory **p = &netregistry[0]; while (p != NULL) { if (strcmp((*p)->name(), name) == 0) diff --git a/src/emu/machine/net_lib.h b/src/emu/machine/net_lib.h index 6c8e957ccbb..e99ec2ac05d 100644 --- a/src/emu/machine/net_lib.h +++ b/src/emu/machine/net_lib.h @@ -54,12 +54,14 @@ // Special chips // ---------------------------------------------------------------------------------------- -#define NETDEV_CONST(_name, _v) \ - NET_REGISTER_DEV(netdev_const, _name) \ - NETDEV_PARAM(_name.CONST, _v) \ +#define NETDEV_CLOCK(_name) \ + NET_REGISTER_DEV(netdev_clock, _name) \ -#define NETDEV_INPUT(_name) \ - NET_REGISTER_DEV(netdev_input, _name) \ +#define NETDEV_LOGIC_INPUT(_name) \ + NET_REGISTER_DEV(netdev_logic_input, _name) \ + +#define NETDEV_ANALOG_INPUT(_name) \ + NET_REGISTER_DEV(netdev_analog_input, _name) \ #define NETDEV_CALLBACK(_name, _IN) \ NET_REGISTER_DEV(netdev_callback, _name) \ @@ -92,7 +94,7 @@ #define TTL_7402_NOR(_name, _I1, _I2) \ NET_REGISTER_DEV(nic7402, _name) \ - NET_CONNECT(_name, I1, _I1) \ + NET_CONNECT(_name, I1, _I1) \ NET_CONNECT(_name, I2, _I2) \ #define TTL_7404_INVERT(_name, _I1) \ @@ -145,7 +147,7 @@ #define TTL_7486_XOR(_name, _I1, _I2) \ NET_REGISTER_DEV(nic7486, _name) \ - NET_CONNECT(_name, I1, _I1) \ + NET_CONNECT(_name, I1, _I1) \ NET_CONNECT(_name, I2, _I2) \ #define TTL_7448(_name, _A0, _A1, _A2, _A3, _LTQ, _BIQ, _RBIQ) \ @@ -185,9 +187,10 @@ NET_CONNECT(_name, R91, _R91) \ NET_CONNECT(_name, R92, _R92) \ -#define TTL_7493(_name, _CLK, _R1, _R2) \ +#define TTL_7493(_name, _CLKA, _CLKB, _R1, _R2) \ NET_REGISTER_DEV(nic7493, _name) \ - NET_CONNECT(_name, CLK, _CLK) \ + NET_CONNECT(_name, CLKA, _CLKA) \ + NET_CONNECT(_name, CLKB, _CLKB) \ NET_CONNECT(_name, R1, _R1) \ NET_CONNECT(_name, R2, _R2) \ @@ -198,7 +201,7 @@ NET_CONNECT(_name, K, _K) \ NET_CONNECT(_name, CLRQ, _CLRQ) \ -#define TTL_74107(_name, _CLK, _J, _K, _CLRQ) \ +#define TTL_74107(_name, _CLK, _J, _K, _CLRQ) \ TTL_74107A(_name, _CLK, _J, _K, _CLRQ) #define TTL_74153(_name, _A1, _A2, _A3, _A4, _A, _B, _GA) \ @@ -224,46 +227,50 @@ NET_CONNECT(_name, D, _D) \ -#define NE555N_MSTABLE(_name, _TRIG) \ +#define NE555N_MSTABLE(_name, _TRIG, _CV) \ NET_REGISTER_DEV(nicNE555N_MSTABLE, _name) \ NET_CONNECT(_name, TRIG, _TRIG) \ + NET_CONNECT(_name, CV, _CV) \ + +#define NETDEV_MIXER3(_name, _I1, _I2, _I3) \ + NET_REGISTER_DEV(nicMixer8, _name) \ + NET_CONNECT(_name, I1, _I1) \ + NET_CONNECT(_name, I2, _I2) \ + NET_CONNECT(_name, I3, _I3) \ // ---------------------------------------------------------------------------------------- // Special support devices ... // ---------------------------------------------------------------------------------------- -NETLIB_DEVICE_WITH_PARAMS(netdev_const, - net_output_t m_Q; - net_param_t m_const; +NETLIB_DEVICE(netdev_logic_input, + ttl_output_t m_Q; ); -NETLIB_DEVICE(netdev_input, - net_output_t m_Q; +NETLIB_DEVICE(netdev_analog_input, + analog_output_t m_Q; ); + + // ---------------------------------------------------------------------------------------- // Special devices ... // ---------------------------------------------------------------------------------------- -/* This class is an artificial delay circuit delaying a signal until the next low to high transition - * this is needed by pong to model delays in the hblank circuit - */ -NETLIB_DEVICE(netdev_delay_lh, - net_input_t m_clk; - net_input_t m_D; +NETLIB_DEVICE_WITH_PARAMS(netdev_clock, + ttl_input_t m_feedback; + ttl_output_t m_Q; - net_sig_t m_lastclk; - - net_output_t m_Q; + net_param_t m_freq; + netlist_time m_inc; ); NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch, - net_input_t m_I[8]; + analog_input_t m_I[8]; - net_output_t m_Q; - net_output_t m_low; + analog_output_t m_Q; + analog_output_t m_low; net_param_t m_POS; @@ -271,11 +278,22 @@ NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch, ); NETLIB_DEVICE(nicRSFF, - net_input_t m_S; - net_input_t m_R; + ttl_input_t m_S; + ttl_input_t m_R; - net_output_t m_Q; - net_output_t m_QQ; + ttl_output_t m_Q; + ttl_output_t m_QQ; +); + +NETLIB_DEVICE_WITH_PARAMS(nicMixer8, + analog_input_t m_I[8]; + + analog_output_t m_Q; + analog_output_t m_low; + + net_param_t m_R[8]; + + double m_w[8]; ); // ---------------------------------------------------------------------------------------- @@ -284,186 +302,252 @@ NETLIB_DEVICE(nicRSFF, NETLIB_DEVICE_WITH_PARAMS(nicNE555N_MSTABLE, - ATTR_HOT void timer_cb(INT32 timer_id); + //ATTR_HOT void timer_cb(INT32 timer_id); - net_input_t m_trigger; + analog_input_t m_trigger; + analog_input_t m_CV; + analog_input_t m_THRESHOLD; /* internal */ - UINT8 m_last; - UINT8 m_fired; - double m_time; + bool m_last; - net_output_t m_Q; + analog_output_t m_Q; + analog_output_t m_THRESHOLD_OUT; /* internal */ - netlist_base_timer_t *m_timer; + //netlist_base_timer_t *m_timer; net_param_t m_R; net_param_t m_C; net_param_t m_VS; net_param_t m_VL; - net_param_t m_VT; ); -NETLIB_SIGNAL(nic7400, 2) -NETLIB_SIGNAL(nic7402, 2) -NETLIB_SIGNAL(nic7404, 1) -NETLIB_SIGNAL(nic7410, 3) -NETLIB_SIGNAL(nic7420, 4) -NETLIB_SIGNAL(nic7425, 4) -NETLIB_SIGNAL(nic7427, 3) -NETLIB_SIGNAL(nic7430, 8) -NETLIB_SIGNAL(nic7450, 4) +NETLIB_SIGNAL(nic7400, 2, 0) +NETLIB_SIGNAL(nic7402, 2, 1) +NETLIB_SIGNAL(nic7410, 3, 0) +NETLIB_SIGNAL(nic7420, 4, 0) +NETLIB_SIGNAL(nic7425, 4, 1) +NETLIB_SIGNAL(nic7427, 3, 1) +NETLIB_SIGNAL(nic7430, 8, 0) +NETLIB_DEVICE(nic7404, + ttl_input_t m_I; + ttl_output_t m_Q; +); + +NETLIB_DEVICE(nic7450, + ttl_input_t m_I0; + ttl_input_t m_I1; + ttl_input_t m_I2; + ttl_input_t m_I3; + ttl_output_t m_Q; +); + +#if 0 NETLIB_DEVICE(nic7474, - net_input_t m_clk; - net_input_t m_D; - net_input_t m_clrQ; - net_input_t m_preQ; + ttl_input_t m_clk; + ttl_input_t m_D; + ttl_input_t m_clrQ; + ttl_input_t m_preQ; net_sig_t m_lastclk; - net_output_t m_Q; - net_output_t m_QQ; + ttl_output_t m_Q; + ttl_output_t m_QQ; ); -NETLIB_SIGNAL(nic7486, 2) +#else +NETLIB_SUBDEVICE(nic7474sub, + ttl_input_t m_clk; + + UINT8 m_nextD; + ttl_output_t m_Q; + ttl_output_t m_QQ; +); + +NETLIB_DEVICE(nic7474, + nic7474sub sub; + + ttl_input_t m_D; + ttl_input_t m_clrQ; + ttl_input_t m_preQ; +); +#endif + +NETLIB_DEVICE(nic7486, + ttl_input_t m_I0; + ttl_input_t m_I1; + ttl_output_t m_Q; +); /* 74107 does latch data during high ! * For modelling purposes, we assume 74107 and 74107A are the same */ +NETLIB_SUBDEVICE(nic74107Asub, + ttl_input_t m_clk; + + UINT8 m_Q1; + UINT8 m_Q2; + UINT8 m_F; + + ttl_output_t m_Q; + ttl_output_t m_QQ; + +); + NETLIB_DEVICE(nic74107A, - net_input_t m_clk; - net_input_t m_J; - net_input_t m_K; - net_input_t m_clrQ; + nic74107Asub sub; - net_sig_t m_lastclk; + ttl_input_t m_J; + ttl_input_t m_K; + ttl_input_t m_clrQ; - net_output_t m_Q; - net_output_t m_QQ; ); class nic74107 : public nic74107A { public: - nic74107(netlist_setup_t *parent, const char *name) - : nic74107A(parent, name) {} + nic74107() + : nic74107A() {} }; +NETLIB_SUBDEVICE(nic7493ff, + ttl_input_t m_I; + ttl_output_t m_Q; + UINT8 m_active; +); + +#if 1 +NETLIB_DEVICE(nic7493, + ttl_input_t m_R1; + ttl_input_t m_R2; + + nic7493ff A; + nic7493ff B; + nic7493ff C; + nic7493ff D; + +); +#else + NETLIB_DEVICE(nic7493, ATTR_HOT void update_outputs(); - net_input_t m_R1; - net_input_t m_R2; - net_input_t m_clk; + ttl_input_t m_clk; + ttl_input_t m_R1; + ttl_input_t m_R2; + + ttl_output_t m_QA; + ttl_output_t m_QB; + ttl_output_t m_QC; + ttl_output_t m_QD; - UINT8 m_lastclk; UINT8 m_cnt; - - net_output_t m_QA; - net_output_t m_QB; - net_output_t m_QC; - net_output_t m_QD; ); +#endif NETLIB_DEVICE(nic7490, ATTR_HOT void update_outputs(); - net_input_t m_R1; - net_input_t m_R2; - net_input_t m_R91; - net_input_t m_R92; - net_input_t m_clk; + ttl_input_t m_R1; + ttl_input_t m_R2; + ttl_input_t m_R91; + ttl_input_t m_R92; + ttl_input_t m_clk; - net_sig_t m_lastclk; UINT8 m_cnt; - net_output_t m_QA; - net_output_t m_QB; - net_output_t m_QC; - net_output_t m_QD; + ttl_output_t m_QA; + ttl_output_t m_QB; + ttl_output_t m_QC; + ttl_output_t m_QD; ); /* ripple-carry counter on low-high clock transition */ -NETLIB_DEVICE(nic9316, + +NETLIB_SUBDEVICE(nic9316sub, ATTR_HOT void update_outputs_all(); ATTR_HOT void update_outputs(); - net_input_t m_clk; - net_input_t m_ENP; - net_input_t m_ENT; - net_input_t m_CLRQ; - net_input_t m_LOADQ; - net_input_t m_A; - net_input_t m_B; - net_input_t m_C; - net_input_t m_D; + ttl_input_t m_clk; + + ttl_input_t m_LOADQ; + ttl_input_t m_ENT; + ttl_input_t m_A; + ttl_input_t m_B; + ttl_input_t m_C; + ttl_input_t m_D; - UINT8 m_lastclk; UINT8 m_cnt; - net_output_t m_QA; - net_output_t m_QB; - net_output_t m_QC; - net_output_t m_QD; - net_output_t m_RC; + ttl_output_t m_QA; + ttl_output_t m_QB; + ttl_output_t m_QC; + ttl_output_t m_QD; + ttl_output_t m_RC; +); + +NETLIB_DEVICE(nic9316, + nic9316sub sub; + ttl_input_t m_ENP; + ttl_input_t m_CLRQ; ); NETLIB_DEVICE(nic7483, - net_input_t m_CI; - net_input_t m_A1; - net_input_t m_A2; - net_input_t m_A3; - net_input_t m_A4; - net_input_t m_B1; - net_input_t m_B2; - net_input_t m_B3; - net_input_t m_B4; - net_input_t m_clk; + ttl_input_t m_CI; + ttl_input_t m_A1; + ttl_input_t m_A2; + ttl_input_t m_A3; + ttl_input_t m_A4; + ttl_input_t m_B1; + ttl_input_t m_B2; + ttl_input_t m_B3; + ttl_input_t m_B4; + ttl_input_t m_clk; UINT8 m_lastr; - net_output_t m_SA; - net_output_t m_SB; - net_output_t m_SC; - net_output_t m_SD; - net_output_t m_CO; + ttl_output_t m_SA; + ttl_output_t m_SB; + ttl_output_t m_SC; + ttl_output_t m_SD; + ttl_output_t m_CO; ); /* one half of a nic74153 */ NETLIB_DEVICE(nic74153, - net_input_t m_I[4]; - net_input_t m_A; - net_input_t m_B; - net_input_t m_GA; + ttl_input_t m_I[4]; + ttl_input_t m_A; + ttl_input_t m_B; + ttl_input_t m_GA; - net_output_t m_AY; + ttl_output_t m_AY; ); NETLIB_DEVICE(nic7448, static const UINT8 tab7448[16][7]; - net_input_t m_A0; - net_input_t m_A1; - net_input_t m_A2; - net_input_t m_A3; - net_input_t m_LTQ; - net_input_t m_RBIQ; - net_input_t m_BIQ; + ttl_input_t m_A0; + ttl_input_t m_A1; + ttl_input_t m_A2; + ttl_input_t m_A3; + ttl_input_t m_LTQ; + ttl_input_t m_RBIQ; + ttl_input_t m_BIQ; UINT8 m_state; - net_output_t m_a; - net_output_t m_b; - net_output_t m_c; - net_output_t m_d; - net_output_t m_e; - net_output_t m_f; - net_output_t m_g; + ttl_output_t m_a; + ttl_output_t m_b; + ttl_output_t m_c; + ttl_output_t m_d; + ttl_output_t m_e; + ttl_output_t m_f; + ttl_output_t m_g; ); diff --git a/src/emu/machine/netlist.c b/src/emu/machine/netlist.c index ba634fbdb04..e631a6b7d29 100644 --- a/src/emu/machine/netlist.c +++ b/src/emu/machine/netlist.c @@ -42,10 +42,10 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ****************************************************************************/ #include "netlist.h" +#include "net_lib.h" //============================================================ // DEBUGGING @@ -54,11 +54,6 @@ #define VERBOSE (0) #define KEEP_STATISTICS (0) - -#if KEEP_STATISTICS && USE_DELEGATES -#error "Statistics only work without delegates!" -#endif - #if (VERBOSE) #define VERBOSE_OUT(x) printf x @@ -71,9 +66,9 @@ //============================================================ #if KEEP_STATISTICS -#define add_to_stat(v,x) do { atomic_add32((v), (x)); } while (0) +#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 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) @@ -82,6 +77,9 @@ #define end_timing(v) do { } while (0) #endif + +const netlist_time netlist_time::zero = netlist_time::from_raw(0); + // ---------------------------------------------------------------------------------------- // A netlist parser // ---------------------------------------------------------------------------------------- @@ -103,86 +101,96 @@ public: n = getname('('); VERBOSE_OUT(("Parser: Device: %s\n", n)); if (strcmp(n,"NET_ALIAS") == 0) - { - char *alias; - char *out; - m_p++; - skipws(); - alias = getname(','); - m_p++; - skipws(); - out = getname(')'); - m_p++; - VERBOSE_OUT(("Parser: Alias: %s %s\n", alias, out)); - m_setup.register_alias(alias, out); - } + net_alias(); else if (strcmp(n,"NETDEV_PARAM") == 0) - { - char *param; - double val; - m_p++; - skipws(); - param = getname(','); - m_p++; - skipws(); - val = eval_param(); - m_p++; - VERBOSE_OUT(("Parser: Param: %s %f\n", param, val)); - m_setup.find_param(param)->setTo(val); - } - else if (strcmp(n,"NETDEV_CONST") == 0) - { - char *devname; - net_dev_t *dev; - char paramfq[30]; - double val; - m_p++; - skipws(); - devname = getname(','); - dev = net_create_device_by_name(n, &m_setup, devname); - m_setup.register_dev(dev); - m_p++; - skipws(); - val = eval_param(); - m_p++; - strcpy(paramfq, devname); - strcat(paramfq, ".CONST"); - VERBOSE_OUT(("Parser: Const: %s %f\n", devname, val)); - m_setup.find_param(paramfq)->setTo(val); - } + netdev_param(); + else if ((strcmp(n,"NETDEV_TTL_CONST") == 0) || (strcmp(n,"NETDEV_ANALOG_CONST") == 0)) + netdev_const(n); else - { - char *devname; - net_dev_t *dev; - int cnt; - - m_p++; - skipws(); - devname = getname2(',', ')'); - dev = net_create_device_by_name(n, &m_setup, devname); - m_setup.register_dev(dev); - skipws(); - VERBOSE_OUT(("Parser: IC: %s\n", n)); - cnt = 0; - while (*m_p != ')') - { - m_p++; - skipws(); - n = getname2(',', ')'); - VERBOSE_OUT(("Parser: ID: %s %s\n", n, dev->m_inputs.item(cnt))); - m_setup.register_link(dev->m_inputs.item(cnt), n); - skipws(); - cnt++; - //return 0; - } - if (cnt != dev->m_inputs.count() && !dev->variable_input_count()) - fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname, dev->m_inputs.count(), cnt); - m_p++; - } + netdev_device(n); } } + void net_alias() + { + char *alias; + char *out; + skipws(); + alias = getname(','); + skipws(); + out = getname(')'); + VERBOSE_OUT(("Parser: Alias: %s %s\n", alias, out)); + m_setup.register_alias(alias, out); + } + + void netdev_param() + { + char *param; + double val; + skipws(); + param = getname(','); + skipws(); + val = eval_param(); + VERBOSE_OUT(("Parser: Param: %s %f\n", param, val)); + m_setup.find_param(param).initial(val); + check_char(')'); + } + + void netdev_const(const char *dev_name) + { + char *devname; + net_device_t *dev; + char paramfq[30]; + double val; + + skipws(); + devname = getname(','); + dev = net_create_device_by_name(dev_name, &m_setup, devname); + m_setup.register_dev(dev); + skipws(); + val = eval_param(); + check_char(')'); + strcpy(paramfq, devname); + strcat(paramfq, ".CONST"); + VERBOSE_OUT(("Parser: Const: %s %f\n", devname, val)); + m_setup.find_param(paramfq).setTo(val); + } + + void netdev_device(const char *dev_type) + { + char *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", n)); + cnt = 0; + while (*m_p != ')') + { + m_p++; + skipws(); + char *output_name = getname2(',', ')'); + VERBOSE_OUT(("Parser: ID: %s %s\n", output_name, dev->m_inputs.item(cnt))); + 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, dev->m_inputs.count(), cnt); + check_char(')'); + } + private: + + char *cdup(const char *s) + { + return core_strdup(s); + } + void skipeol() { while (*m_p) @@ -190,6 +198,8 @@ private: if (*m_p == 10) { m_p++; + if (*m_p && *m_p == 13) + m_p++; return; } m_p++; @@ -226,7 +236,8 @@ private: while (*m_p != sep) *p1++ = *m_p++; *p1 = 0; - return core_strdup(buf); + m_p++; + return cdup(buf); } char *getname2(char sep1, char sep2) @@ -237,7 +248,18 @@ private: while ((*m_p != sep1) && (*m_p != sep2)) *p1++ = *m_p++; *p1 = 0; - return core_strdup(buf); + return cdup(buf); + } + + void check_char(char ctocheck) + { + skipws(); + if (*m_p == ctocheck) + { + m_p++; + return; + } + fatalerror("Parser: expected '%c' found '%c'", ctocheck, *m_p); } double eval_param() @@ -255,7 +277,7 @@ private: f = i; ret = strtod(s+strlen(macs[f]), &e); if ((f>0) && (*e != ')')) - exit(0); + fatalerror("Parser: Error with parameter ..."); if (f>0) e++; m_p = e; @@ -268,83 +290,142 @@ private: }; +// ---------------------------------------------------------------------------------------- +// 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_always(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL, "Digital signal expected"); + m_I.m_high_thresh_V = in_proxied.m_high_thresh_V; + m_I.m_low_thresh_V = in_proxied.m_low_thresh_V; + } + + ATTR_HOT void update() + { + if (m_I.Q_Analog() > m_I.m_high_thresh_V) + m_Q.setToPS(1, NLTIME_FROM_NS(1)); + else if (m_I.Q_Analog() < m_I.m_low_thresh_V) + m_Q.setToPS(0, NLTIME_FROM_NS(1)); + } + + ATTR_COLD void start() + { + m_I.init(this); + m_Q.set_netdev(this); + + m_Q.initial(1); + } + + analog_input_t m_I; + ttl_output_t m_Q; +}; + +// ---------------------------------------------------------------------------------------- +// 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) +{ + m_Q.setToPS(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 // ---------------------------------------------------------------------------------------- -netlist_base_t::netlist_base_t(bool sub_cycle_exact) +netlist_base_t::netlist_base_t() //m_output_list(ttl_list_t(2048)), - : m_current(0), m_divisor(32), m_sub_cycle_exact(sub_cycle_exact), m_gatedelay(100), m_clockfreq(1000000) + //: m_divisor(32), m_gatedelay(100), m_clockfreq(1000000) + : m_div(1024) { - m_netlist_mask = NET_LIST_MASK; - reset_lists(); } netlist_base_t::~netlist_base_t() { } -void netlist_base_t::set_clock_freq(int clockfreq) +void netlist_base_t::set_clock_freq(UINT64 clockfreq) { - m_clockfreq = clockfreq; - m_divisor = U64(100000000000) / m_clockfreq / m_gatedelay; - VERBOSE_OUT(("Divisor %d\n", m_divisor)); + m_div = netlist_time::from_hz(clockfreq).as_raw(); + VERBOSE_OUT(("Setting clock %lld and divisor %d\n", clockfreq, m_div)); } -void netlist_base_t::set_gatedelay(int gatedelay) +ATTR_HOT ATTR_ALIGN void netlist_base_t::process_list(INT32 &atime) { - m_gatedelay = gatedelay; - m_divisor = U64(100000000000) / m_clockfreq / m_gatedelay; - VERBOSE_OUT(("Divisor %d\n", m_divisor)); -} -ATTR_HOT inline void netlist_base_t::process_list(void) -{ - net_list_t &list = m_output_list[m_sub_cycle_exact ? m_current : 0]; -#if 0 - net_output_t * RESTRICT * RESTRICT first; - net_output_t * RESTRICT * RESTRICT last; - - first = list.first(); - last = list.last(); - while (first <= last) + while ( (atime > 0) && (m_queue.is_not_empty())) { - net_output_t * RESTRICT * RESTRICT out = first; - while (out <= last) - { - (*out)->update_out(); - (*out)->update_devs(); - out++; - } - first = last + 1; - last = list.last(); - } -#else - net_output_t * RESTRICT * RESTRICT out; + queue_t::entry_t e = m_queue.pop(); + netlist_time delta = e.time() - m_time_ps + netlist_time::from_raw(m_rem); - out = list.first(); - while (out <= list.last()) + atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem); + m_time_ps = e.time(); + + e.object()->update_devs(); + + add_to_stat(m_perf_out_processed, 1); + add_to_stat(m_perf_list_len, m_end); + } + + if (atime > 0) { - (*out)->update_out(); - (*out)->update_devs(); - out++; + m_time_ps += netlist_time::from_raw(atime * m_div); + atime = 0; } -#endif - reset_list(); - if (m_sub_cycle_exact) - m_current = (m_current + 1) & m_netlist_mask; + if (KEEP_STATISTICS) + printf("%f\n", (double) m_perf_list_len / (double) m_perf_out_processed); } +// ---------------------------------------------------------------------------------------- +// 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_output_list(ttl_list_t(2048)), : m_netlist(netlist) { + NETLIST_NAME(base)(*this); } netlist_setup_t::~netlist_setup_t() @@ -352,7 +433,7 @@ netlist_setup_t::~netlist_setup_t() } -net_dev_t *netlist_setup_t::register_dev(net_dev_t *dev) +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()); @@ -378,7 +459,7 @@ static void remove_start_with(T &hm, astring &sw) void netlist_setup_t::remove_dev(const char *name) { - net_dev_t *dev = m_devices.find(name); + net_device_t *dev = m_devices.find(name); astring temp = name; if (dev == NULL) fatalerror("Device %s does not exist\n", name); @@ -413,11 +494,10 @@ void netlist_setup_t::register_output(const char *name, net_output_t *out) fatalerror("Error adding output %s to output list\n", name); } -void netlist_setup_t::register_input(const char *name, net_input_t *inp, net_input_type type) +void netlist_setup_t::register_input(const char *name, net_input_t *inp) { - net_input_setup_t *setup_inp = new net_input_setup_t(inp, type); VERBOSE_OUT(("input %s\n", name)); - if (!(m_inputs.add(name, setup_inp, false) == TMERR_NONE)) + if (!(m_inputs.add(name, inp, false) == TMERR_NONE)) fatalerror("Error adding input %s to input list\n", name); } @@ -431,7 +511,7 @@ void netlist_setup_t::register_link(const char *sin, const char *sout) void netlist_setup_t::register_param(const char *sname, net_param_t *param) { - astring temp = param->ttl_dev()->name(); + astring temp = param->netdev().name(); temp.cat("."); temp.cat(sname); if (!(m_params.add(temp, param, false)==TMERR_NONE)) @@ -454,7 +534,7 @@ net_output_t *netlist_setup_t::find_output_exact(const char *outname_in) return ret; } -net_output_t *netlist_setup_t::find_output(const char *outname_in) +net_output_t &netlist_setup_t::find_output(const char *outname_in) { const char *outname = resolve_alias(outname_in); net_output_t *ret; @@ -471,10 +551,10 @@ net_output_t *netlist_setup_t::find_output(const char *outname_in) if (ret == NULL) fatalerror("output %s(%s) not found!", outname_in, outname); VERBOSE_OUT(("Found input %s\n", outname)); - return ret; + return *ret; } -net_param_t *netlist_setup_t::find_param(const char *param_in) +net_param_t &netlist_setup_t::find_param(const char *param_in) { const char *outname = resolve_alias(param_in); net_param_t *ret; @@ -483,7 +563,7 @@ net_param_t *netlist_setup_t::find_param(const char *param_in) if (ret == NULL) fatalerror("parameter %s(%s) not found!", param_in, outname); VERBOSE_OUT(("Found parameter %s\n", outname)); - return ret; + return *ret; } void netlist_setup_t::resolve_inputs(void) @@ -493,39 +573,47 @@ void netlist_setup_t::resolve_inputs(void) { const astring *sout = entry->object(); astring sin = entry->tag(); - net_input_setup_t *in = m_inputs.find(sin); - int p = sin.find("."); - const char *devname = sin.substr(0, p); - net_dev_t *dev = m_devices.find(devname); - net_output_t *out = find_output(sout->cstr() ); + net_input_t *in = m_inputs.find(sin); - (*in->inp()).o = GETINPPTR(*out); - //in->inp()->v = out->Q_ptr(); - if (in->type() == NET_INP_TYPE_ACTIVE) - out->register_con(dev); + 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) + { + // fatalerror("connecting analog output %s with %s\n", out.netdev()->name(), in->netdev()->name()); + // fatalerror("connecting analog output %s with %s\n", out.netdev()->name(), in->netdev()->name()); + netdev_a_to_d_proxy *proxy = new netdev_a_to_d_proxy(*in); + proxy->init(this, "abc"); + proxy->start(); + in->set_output(proxy->GETINPPTR(proxy->m_Q)); + //Next check would not work with dynamic activation + //if (in->state() != net_input_t::INP_STATE_PASSIVE) + proxy->m_Q.register_con(*in); + proxy->m_I.set_output(&out); + //if (proxy->m_I.state() != net_input_t::INP_STATE_PASSIVE) + out.register_con(proxy->m_I); + } + else + { + in->set_output(out.netdev()->GETINPPTR(out)); + + //Next check would not work with dynamic activation + //if (in->state() != net_input_t::INP_STATE_PASSIVE) + out.register_con(*in); + } + } + /* 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(); } - step_all_devices(); - //reset_list(); - //process_list(); -} - -void netlist_setup_t::step_all_devices() -{ - m_netlist.reset_list(); - - for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry)) + /* 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_dev_t &dev = *entry->object(); - dev.update_param(); - dev.update(); - - for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry)) - { - net_output_t &out = *entry->object(); - out.update_out(); - } - m_netlist.reset_lists(); + net_output_t *out = entry->object(); + out->update_devs_force(); + INT32 time = 1000; + m_netlist.process_list(time); } } @@ -547,119 +635,238 @@ void netlist_setup_t::print_stats() } +// ---------------------------------------------------------------------------------------- +// net_core_device_t +// ---------------------------------------------------------------------------------------- + +net_core_device_t::net_core_device_t() +: net_object_t(DEVICE) +{ +} + +net_core_device_t::~net_core_device_t() +{ +} + + +ATTR_COLD void net_core_device_t::init_core(netlist_base_t *anetlist, const char *name) +{ + m_netlist = anetlist; + m_name = name; +#if USE_DELEGATES_A + h = net_update_delegate(&net_core_device_t::update, "update", this); +#endif +} + + +ATTR_COLD void net_core_device_t::register_subdevice(net_core_device_t &subdev) +{ + m_subdevs.add(&subdev); + subdev.init_core(m_netlist, this->name()); + //subdev.start(); +} + // ---------------------------------------------------------------------------------------- // net_dev_t // ---------------------------------------------------------------------------------------- -net_dev_t::~net_dev_t() + +net_device_t::net_device_t() +: net_core_device_t(), m_variable_input_count(false) { } -ATTR_HOT void net_dev_t::update_timed() +net_device_t::~net_device_t() { - inc_stat(&stat_count); - begin_timing(total_time); - update(); - end_timing(total_time); } -void net_dev_t::register_output(const char *name, net_output_t *port) +ATTR_COLD void net_device_t::init(netlist_setup_t *setup, const char *name) { - astring temp = this->name(); + m_setup = setup; + init_core(&setup->netlist(), name); +} + +void net_device_t::register_output(const net_core_device_t &dev, const char *name, net_output_t &port) +{ + astring temp = dev.name(); temp.cat("."); temp.cat(name); - port->set_ttl_dev(this); - m_setup->register_output(temp, port); + port.set_netdev(&dev); + m_setup->register_output(temp, &port); } -void net_dev_t::register_input(const char *name, net_input_t *inp, net_input_type type) +void net_device_t::register_output(const char *name, net_output_t &port) { - astring temp = this->name(); + register_output(*this, name, port); +} + +void net_device_t::register_input(net_core_device_t &dev, const char *name, net_input_t &inp, int type) +{ + astring temp = dev.name(); temp.cat("."); temp.cat(name); + inp.init(&dev, type); m_inputs.add(core_strdup(temp.cstr())); - m_setup->register_input(temp, inp, type); + m_setup->register_input(temp, &inp); } -void net_dev_t::register_param(const char *name, net_param_t *param, double initialVal) +void net_device_t::register_input(const char *name, net_input_t &inp, int type) { - param->set_ttl_dev(this); - param->initial(initialVal); - m_setup->register_param(name, param); + 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) +{ + in.set_output(GETINPPTR(out)); + in.init(&dev); + //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) +{ + register_link_internal(*this, in, out); +} + +void net_device_t::register_param(net_core_device_t &dev, const char *name, net_param_t ¶m, double initialVal) +{ + param.set_netdev(dev); + param.initial(initialVal); + m_setup->register_param(name, ¶m); +} + +void net_device_t::register_param(const char *name, net_param_t ¶m, double initialVal) +{ + register_param(*this,name, param, initialVal); +} + +// ---------------------------------------------------------------------------------------- +// net_input_t +// ---------------------------------------------------------------------------------------- + +ATTR_COLD void net_input_t::init(net_core_device_t *dev, int astate) +{ + m_netdev = dev; + m_state = astate; +#if USE_DELEGATES + h = net_update_delegate(&net_core_device_t::update, "update", dev); +#endif } // ---------------------------------------------------------------------------------------- // net_output_t // ---------------------------------------------------------------------------------------- -net_output_t::net_output_t() +net_output_t::net_output_t(int atype) + : net_object_t(atype) { -#if USE_DELEGATES - //m_cons = global_alloc_array_clear(net_update_delegate, 32); -#else - // m_cons = global_alloc_array_clear(net_dev_t *, 32); -#endif - //m_Q = parent.alloc_sig(); - //m_new_Q = parent.alloc_sig(); - m_num_cons = 0; + m_last_Q = 1; m_Q = 0; m_new_Q = m_Q; + m_active = 0; + m_in_queue = 2; } -ATTR_COLD void net_output_t::set_ttl_dev(net_dev_t *dev) +ATTR_COLD void net_output_t::set_netdev(const net_core_device_t *dev) { - m_ttldev = dev; - m_netlist = &dev->setup()->netlist(); + m_netdev = dev; + m_netlist = dev->netlist(); } - -ATTR_COLD void net_output_t::register_con(net_dev_t *dev) +static inline void update_dev(const net_input_t *inp, const UINT32 mask) { - assert(m_num_cons<32); + if ((inp->state() & mask) != 0) + { + begin_timing(inp->netdev()->total_time); + inc_stat(inp->netdev()->stat_count); #if USE_DELEGATES - net_update_delegate aDelegate = net_update_delegate(&net_dev_t::update, "update", dev); - for (int i=0; i < m_num_cons; i++) - if (m_cons[i] == aDelegate) - return; - m_cons[m_num_cons++] = aDelegate; + inp->h(); #else - for (int i=0; i < m_num_cons; i++) - if (m_cons[i] == dev) - return; - m_cons[m_num_cons++] = dev; + inp->netdev()->update_device(); #endif + end_timing(inp->netdev()->total_time); + } } ATTR_HOT inline void net_output_t::update_devs() { -#if USE_DELEGATES - net_update_delegate *s = m_cons; - net_update_delegate *e = s + m_num_cons; + const UINT32 masks[4] = { 1, 5, 3, 1 }; + m_Q = m_new_Q; + m_Q_analog = m_new_Q_analog; - while (supdate_timed(); + m_in_queue = 2; /* mark as taken ... */ + m_last_Q = m_Q; +} + +ATTR_COLD void net_output_t::update_devs_force() +{ + net_input_t **s = m_cons; + int i = m_num_cons; + + m_Q = m_new_Q; + m_Q_analog = m_new_Q_analog; + while (i-- > 0) + { + if (((*s)->state() & net_input_t::INP_STATE_ACTIVE) != 0) +#if USE_DELEGATES + (*s)->h(); #else - while (supdate(); + (*s)->netdev()->update_device(); #endif + s++; + } + + m_last_Q = m_Q; +} + +ATTR_COLD void net_output_t::register_con(net_input_t &input) +{ + int i; + if (m_num_cons >= ARRAY_LENGTH(m_cons)) + fatalerror("Connections exceeded for %s\n", m_netdev->name()); + + /* keep similar devices together */ + for (i = 0; i < m_num_cons; i++) +#if USE_DELEGATES + if (m_cons[i]->h == input.h) + break; +#else + if (m_cons[i]->netdev() == input.netdev()) + break; #endif + 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++; } NETLIB_UPDATE(netdev_callback) { // FIXME: Remove after device cleanup if (!m_callback.isnull()) - m_callback(INPVAL(m_in)); + m_callback(INPANALOG(m_in)); } // ---------------------------------------------------------------------------------------- @@ -674,17 +881,6 @@ netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const ch : device_t(mconfig, NETLIST, "netlist", tag, owner, clock), device_execute_interface(mconfig, *this) { - m_clock = clock; -} - -void netlist_mame_device::static_set_subcycles(device_t &device, int subcycles) -{ - netlist_mame_device &netlist = downcast(device); - - assert((subcycles & 1) == 0); - assert( subcycles > 0); - - netlist.m_subcycles = subcycles; } void netlist_mame_device::static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &)) @@ -701,8 +897,8 @@ void netlist_mame_device::device_start() { //double dt = clocks_to_attotime(1).as_double(); - m_netlist = global_alloc_clear(netlist_t(*this, m_subcycles > 2)); - m_netlist->set_clock_freq(m_clock * m_subcycles); + m_netlist = global_alloc_clear(netlist_t(*this)); + m_netlist->set_clock_freq(this->clock()); m_setup = global_alloc_clear(netlist_setup_t(*m_netlist)); @@ -717,18 +913,12 @@ void netlist_mame_device::device_start() m_setup->resolve_inputs(); - //m_clockcnt = 0; - - m_clock_input = m_setup->find_output("clk"); - //save_item(NAME(m_clockcnt)); save_state(); /* TODO: we have to save the round robin queue as well */ // set our instruction counter m_icountptr = &m_icount; - m_ss = SubCycles() / 2; - m_clk = 0; } void netlist_mame_device::device_reset() @@ -761,37 +951,25 @@ void netlist_mame_device::save_state() UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const { - return clocks * SubCycles(); + return clocks; } UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const { - return cycles / SubCycles(); + return cycles; } ATTR_HOT void netlist_mame_device::execute_run() { //bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0); - osd_ticks_t a = -osd_ticks(); - UINT8 ssdiv2 = (SubCycles() / 2); - //int p = m_icount; - do - { - // debugging - //m_ppc = m_pc; // copy PC to previous PC - //if (check_debugger) - // debugger_instruction_hook(this, 0); //m_pc); - if (--m_ss == 0) - { - m_ss = ssdiv2; - m_clk = !m_clk; - m_clock_input->setTo(m_clk); - } - m_netlist->process_list(); - m_icount--; - } while (m_icount > 0); - a+=osd_ticks(); - //printf("%ld %d %ld\n", (long) a, p, (long) (a * 1000 / p)); + + // debugging + //m_ppc = m_pc; // copy PC to previous PC + //if (check_debugger) + // debugger_instruction_hook(this, 0); //m_pc); + + m_netlist->process_list(m_icount); + } diff --git a/src/emu/machine/netlist.h b/src/emu/machine/netlist.h index 524e6b83f72..740d3072084 100644 --- a/src/emu/machine/netlist.h +++ b/src/emu/machine/netlist.h @@ -56,10 +56,17 @@ //============================================================ #define USE_DELEGATES (1) -#define USE_DOUBLE (0) +#define USE_DELEGATES_A (0) + +#define NETLIST_CLOCK (U64(1000000000)) + +#define NLTIME_FROM_NS(_t) netlist_time::from_ns(_t) +#define NLTIME_FROM_US(_t) netlist_time::from_us(_t) +#define NLTIME_FROM_MS(_t) netlist_time::from_ms(_t) +#define NLTIME_IMMEDIATE netlist_time::from_ns(0) + +#define NETLIST_HIGHIMP_V (1.23456e20) /* some voltage we should never see */ -#define NET_LIST_SIZE (32) -#define NET_LIST_MASK (0x1f) //============================================================ // MACROS / inline netlist definitions @@ -83,7 +90,7 @@ netlist.register_link(# _name "." # _input, # _output); \ #define NETDEV_PARAM(_name, _val) \ - netlist.find_param(# _name)->setTo(_val); + netlist.find_param(# _name).initial(_val); #define NETLIST_NAME(_name) netlist ## _ ## _name @@ -93,15 +100,15 @@ ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \ #define NETLIST_END } -#define NETLIST_INCLUDE(_name) \ +#define NETLIST_INCLUDE(_name) \ NETLIST_NAME(_name)(netlist); \ -#define NETLIST_MEMREGION(_name) \ +#define NETLIST_MEMREGION(_name) \ netlist.parse((char *)downcast(netlist.netlist()).machine().root_device().memregion(_name)->base()); \ #if defined(__GNUC__) && (__GNUC__ >= 3) -#define ATTR_ALIGN __attribute__ ((aligned(64))) +#define ATTR_ALIGN __attribute__ ((aligned(128))) #else #define ATTR_ALIGN #endif @@ -115,58 +122,57 @@ ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \ #define NETLIB_UPDATE_PARAM(_chip) ATTR_HOT ATTR_ALIGN void _chip :: update_param(void) #define NETLIB_FUNC_VOID(_chip, _name) ATTR_HOT ATTR_ALIGN inline void _chip :: _name (void) -#define NETLIB_TIMER_CALLBACK(_chip) ATTR_HOT void _chip :: timer_cb(INT32 timer_id) - -#define NETLIB_SIGNAL(_name, _num_input) \ - class _name : public net_signal_t< _num_input > \ +#define NETLIB_SIGNAL(_name, _num_input, _check) \ + class _name : public net_signal_t<_num_input, _check> \ { \ - public: \ - _name (netlist_setup_t *parent, const char *name) \ - : net_signal_t<_num_input>(parent, name) { } \ - ATTR_HOT void update(); \ + public: \ + _name () : net_signal_t<_num_input, _check>() { } \ }; \ #define NETLIB_DEVICE(_name, _priv) \ - class _name : public net_dev_t \ + class _name : public net_device_t \ { \ public: \ - _name (netlist_setup_t *parent, const char *name) \ - : net_dev_t(parent, name) { } \ + _name () : net_device_t() { } \ ATTR_HOT void update(); \ ATTR_COLD void start(); \ - private: \ + protected: \ + _priv \ + } \ + +#define NETLIB_SUBDEVICE(_name, _priv) \ + class _name : public net_core_device_t \ + { \ + public: \ + _name () : net_core_device_t() { } \ + ATTR_HOT void update(); \ + /*protected:*/ \ _priv \ } \ #define NETLIB_DEVICE_WITH_PARAMS(_name, _priv) \ - class _name : public net_dev_t \ + class _name : public net_device_t \ { \ public: \ - _name (netlist_setup_t *parent, const char *name) \ - : net_dev_t(parent, name) { } \ + _name () : net_device_t() { } \ ATTR_HOT void update_param(); \ ATTR_HOT void update(); \ ATTR_COLD void start(); \ - private: \ + /* protected: */ \ _priv \ } \ // MAME specific -#define MCFG_NETLIST_ADD(_tag, _clock, _setup, _subcycles) \ - MCFG_DEVICE_ADD(_tag, NETLIST, _clock) \ - MCFG_NETLIST_SUBCYCLES(_subcycles) \ - MCFG_NETLIST_SETUP(_setup) \ +#define MCFG_NETLIST_ADD(_tag, _setup ) \ + MCFG_DEVICE_ADD(_tag, NETLIST, NETLIST_CLOCK) \ + MCFG_NETLIST_SETUP(_setup) \ -#define MCFG_NETLIST_REPLACE(_tag, _clock, _setup, _subcycles) \ - MCFG_DEVICE_REPLACE(_tag, NETLIST, _clock) \ - MCFG_NETLIST_SUBCYCLES(_subcycles) \ - MCFG_NETLIST_SETUP(_setup) \ +#define MCFG_NETLIST_REPLACE(_tag, _setup) \ + MCFG_DEVICE_REPLACE(_tag, NETLIST, NETLIST_CLOCK) \ + MCFG_NETLIST_SETUP(_setup) \ -#define MCFG_NETLIST_SUBCYCLES(_subcycles) \ - netlist_mame_device::static_set_subcycles(*device, _subcycles); \ - -#define MCFG_NETLIST_SETUP(_setup) \ +#define MCFG_NETLIST_SETUP(_setup) \ netlist_mame_device::static_set_constructor(*device, NETLIST_NAME(_setup)); \ @@ -175,69 +181,98 @@ ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \ // ---------------------------------------------------------------------------------------- -enum net_input_type { - NET_INP_TYPE_PASSIVE, - NET_INP_TYPE_ACTIVE -}; - -enum { nst_LOW = 0, nst_HIGH = 1}; -//typedef double net_sig_t; -//enum net_sig_t { nst_LOW = 0, nst_HIGH = 1}; - -// ---------------------------------------------------------------------------------------- -// net_input_t -// ---------------------------------------------------------------------------------------- - -class net_output_t; - -#if !USE_DOUBLE -#if 0 -typedef UINT8 net_sig_t; -#define INPVAL(_x) (*(_x)) -#define GETINPPTR(_x) (_x).Q_ptr() -typedef net_sig_t * RESTRICT net_input_t; -#else -typedef UINT8 net_sig_t; -//#define INPVAL(_x) ((_x)->Q()) -#define INPVAL(_x) INP(_x) -#define GETINPPTR(_x) (&(_x)) -class net_input_t { -public: - net_output_t * RESTRICT o; -}; -#endif -#else -typedef double net_sig_t; -#define INPVAL(_x) ((int)*(_x)) -#define GETINPPTR(_x) (_x).Q_ptr() -typedef net_sig_t * RESTRICT net_input_t; -#endif - - - -typedef delegate net_output_delegate; - -#if USE_DELEGATES +#if USE_DELEGATES || USE_DELEGATES_A typedef delegate net_update_delegate; -typedef delegate net_register_delegate; #endif -class net_dev_t; -class net_param_t; -class netlist_setup_t; -class netlist_base_t; +typedef UINT8 net_sig_t; + +typedef delegate net_output_delegate; // ---------------------------------------------------------------------------------------- -// net_list_t +// Support classes // ---------------------------------------------------------------------------------------- +struct netlist_time +{ +public: + + typedef UINT64 INTERNALTYPE; + + static const INTERNALTYPE RESOLUTION = U64(1024000000000); + + inline netlist_time() : m_time(0) {} + + friend netlist_time operator-(const netlist_time &left, const netlist_time &right); + friend netlist_time operator+(const netlist_time &left, const netlist_time &right); + friend netlist_time operator*(const netlist_time &left, const UINT64 factor); + friend bool operator>(const netlist_time &left, const netlist_time &right); + friend bool operator<(const netlist_time &left, const netlist_time &right); + friend bool operator>=(const netlist_time &left, const netlist_time &right); + friend bool operator<=(const netlist_time &left, const netlist_time &right); + + inline netlist_time &operator=(const netlist_time right) { m_time = right.m_time; return *this; } + inline netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; } + + inline const INTERNALTYPE as_raw() const { return m_time; } + + static inline const netlist_time from_ns(const int ns) { return netlist_time((UINT64) ns * RESOLUTION / U64(1000000000)); } + static inline const netlist_time from_us(const int us) { return netlist_time((UINT64) us * RESOLUTION / U64(1000000)); } + static inline const netlist_time from_ms(const int ms) { return netlist_time((UINT64) ms * RESOLUTION / U64(1000)); } + static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); } + static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); } + + static const netlist_time zero; + +protected: + + inline netlist_time(const INTERNALTYPE val) : m_time(val) {} + + INTERNALTYPE m_time; +}; + +inline netlist_time operator-(const netlist_time &left, const netlist_time &right) +{ + return netlist_time::from_raw(left.m_time - right.m_time); +} + +inline netlist_time operator*(const netlist_time &left, const UINT64 factor) +{ + return netlist_time::from_raw(left.m_time * factor); +} + +inline netlist_time operator+(const netlist_time &left, const netlist_time &right) +{ + return netlist_time::from_raw(left.m_time + right.m_time); +} + +inline bool operator<(const netlist_time &left, const netlist_time &right) +{ + return (left.m_time < right.m_time); +} + +inline bool operator>(const netlist_time &left, const netlist_time &right) +{ + return (left.m_time > right.m_time); +} + +inline bool operator<=(const netlist_time &left, const netlist_time &right) +{ + return (left.m_time <= right.m_time); +} + +inline bool operator>=(const netlist_time &left, const netlist_time &right) +{ + return (left.m_time >= right.m_time); +} + template struct net_list_t { public: - net_list_t() //(int max_elements = 64) + net_list_t() { - //m_list = global_alloc_array_clear(_ListClass, max_elements); + m_list = global_alloc_array(_ListClass, _NumElements); m_ptr = m_list; m_ptr--; } @@ -247,135 +282,416 @@ public: *(++m_ptr) = elem; } - ATTR_HOT inline _ListClass *first() { return m_list; } - ATTR_HOT inline _ListClass *last() { return m_ptr; } - ATTR_HOT inline _ListClass item(int i) { return m_list[i]; } - inline int count() { return m_ptr - m_list + 1; } - ATTR_HOT inline bool empty() { return (m_ptr < m_list); } + ATTR_HOT inline _ListClass *first() const { return m_list; } + ATTR_HOT inline _ListClass *last() const { return m_ptr; } + ATTR_HOT inline _ListClass item(int i) const { return m_list[i]; } + inline int count() const { return m_ptr - m_list + 1; } + ATTR_HOT inline bool empty() const { return (m_ptr < m_list); } ATTR_HOT inline void clear() { m_ptr = m_list - 1; } private: _ListClass * m_ptr; - _ListClass m_list[_NumElements]; + //_ListClass m_list[_NumElements]; + _ListClass *m_list; }; +#define SIZE ((1 << _Size) - 1) + +template +class netlist_timed_queue +{ +public: + struct entry_t + { + public: + inline entry_t() {} + inline entry_t(netlist_time atime, _QC elem) : m_time(atime), m_object(elem) {} + ATTR_HOT inline const netlist_time &time() const { return m_time; } + ATTR_HOT inline _QC object() const { return m_object; } + private: + netlist_time m_time; + _QC m_object; + }; + + + netlist_timed_queue() + { + clear(); + } + + ATTR_HOT inline bool is_empty() { return ((m_start & SIZE) == (m_end & SIZE)); } + ATTR_HOT inline bool is_not_empty() { return ((m_start & SIZE) != (m_end & SIZE)); } + + ATTR_HOT void push(const entry_t &e); + + ATTR_HOT inline entry_t &pop() + { + m_end--; + return item(m_end); + } + + ATTR_COLD void clear() + { + m_end = m_start = (1 << _Size) >> 1; + } +private: + ATTR_HOT inline entry_t &item(UINT32 x) { return m_list[x & SIZE]; } + ATTR_HOT inline void set_item(UINT32 x, const entry_t &aitem) { m_list[x & SIZE] = aitem; } + + UINT32 m_start; + UINT32 m_end; + entry_t m_list[SIZE + 1]; +}; + +template +ATTR_HOT ATTR_ALIGN void netlist_timed_queue<_QC, _Size>::push(const entry_t &e) +{ + if (is_empty() || (e.time() <= item(m_end - 1).time())) + { + set_item(m_end, e); + m_end++; + } + else if (e.time() >= item(m_start).time()) + { + m_start--; + set_item(m_start, e); + } + else + { + register UINT32 i = m_end; + register UINT32 j = i - 1; + m_end++; + while ((e.time() > item(j).time())) + { + set_item(i, item(j)); + i = j; + j--; + } + set_item(i, e); + } +} +// ---------------------------------------------------------------------------------------- +// forward definitions +// ---------------------------------------------------------------------------------------- + +class net_output_t; +class net_core_device_t; +class net_param_t; +class netlist_setup_t; +class netlist_base_t; + +// ---------------------------------------------------------------------------------------- +// net_input_t +// ---------------------------------------------------------------------------------------- + +class net_object_t +{ +public: + enum type_t { + INPUT = 0, + OUTPUT = 1, + DEVICE = 2, + PARAM = 3, + TYPE_MASK = 0x03, + SIGNAL_DIGITAL = 0x00, + SIGNAL_ANALOG = 0x10, + SIGNAL_MASK = 0x10, + }; + + net_object_t(int atype) + : m_objtype(atype) {} + + ATTR_HOT inline int object_type() const { return m_objtype; } + ATTR_HOT inline int object_type(int mask) const { return m_objtype & mask; } + +private: + int m_objtype; +}; + + +class net_input_t : public net_object_t +{ +public: + + enum net_input_state { + INP_STATE_PASSIVE = 0, + INP_STATE_ACTIVE = 1, + INP_STATE_HL = 2, + INP_STATE_LH = 4, + }; + + net_input_t(const int atype) : net_object_t(atype), m_state(INP_STATE_ACTIVE) {} + ATTR_COLD void init(net_core_device_t *dev,int astate = INP_STATE_ACTIVE); + + ATTR_HOT inline net_output_t * RESTRICT output() const { return m_output; } + ATTR_HOT inline bool is_state(const net_input_state astate) { return (m_state & astate); } + ATTR_HOT inline UINT32 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(); + + ATTR_HOT inline net_core_device_t * RESTRICT netdev() const { return m_netdev; } + + double m_low_thresh_V; + double m_high_thresh_V; + +#if USE_DELEGATES + net_update_delegate h; +#endif + +private: + UINT32 m_state; + net_core_device_t * RESTRICT m_netdev; + 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 net_sig_t Q() const; + ATTR_HOT inline net_sig_t last_Q() const; + + ATTR_COLD inline void set_thresholds(double low, 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 bool is_highz() const; + ATTR_HOT inline double Q_Analog() const; +}; + +//#define INPVAL(_x) (_x).Q() + + + + // ---------------------------------------------------------------------------------------- // net_output_t // ---------------------------------------------------------------------------------------- -class net_output_t +class net_output_t : public net_object_t { public: - net_output_t(); - ATTR_HOT inline void clear() { set_Q(nst_LOW); } - ATTR_HOT inline void set() { set_Q(nst_HIGH); } - ATTR_HOT inline void setTo(const net_sig_t val) { set_Q(val); } - ATTR_HOT inline void setTo(const net_sig_t val, const UINT8 delay_ns) { set_Q(val,delay_ns); } - ATTR_HOT inline void setToNoCheck(const net_sig_t val) + net_output_t(int atype); + + friend net_sig_t logic_input_t::Q() const; + + 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_HOT inline const double Q_Analog() const { - m_new_Q = val; - register_in_list(); + switch (object_type(SIGNAL_MASK)) + { + case SIGNAL_DIGITAL: return m_Q ? m_high_V : m_low_V; + case SIGNAL_ANALOG: return m_Q_analog; + default: assert(true); + } + + return 0; } - ATTR_HOT inline void setToNoCheck(const net_sig_t val, const UINT8 delay_ns) - { - m_new_Q = val; - register_in_list(delay_ns); - } - - ATTR_COLD void initial(const net_sig_t val) { m_Q = val; m_new_Q = val; } - - ATTR_HOT inline const net_sig_t Q() const { return m_Q; } - inline net_sig_t *Q_ptr() { return &m_Q; } - inline net_sig_t *new_Q_ptr() { return &m_new_Q; } + inline net_sig_t *new_Q_ptr() { return &m_new_Q; } - ATTR_COLD void register_con(net_dev_t *dev); + ATTR_COLD void register_con(net_input_t &inp); ATTR_HOT void update_devs(); + ATTR_COLD void update_devs_force(); - ATTR_HOT inline void update_out() { - m_Q = m_new_Q; - //m_QD = m_new_QD; - } + ATTR_HOT inline const net_core_device_t *netdev() const { return m_netdev; } - ATTR_HOT inline const net_dev_t *ttl_dev() { return m_ttldev; } + ATTR_HOT inline void inc_active(); + ATTR_HOT inline void dec_active() { m_active--; } + ATTR_HOT inline int active_count() { return m_active; } - ATTR_COLD void set_ttl_dev(net_dev_t *dev); + ATTR_COLD void set_netdev(const net_core_device_t *dev); -private: +protected: - ATTR_HOT inline void register_in_list(const UINT8 delay_ns); - ATTR_HOT inline void register_in_list(); + /* prohibit use in device functions + * current (pending) state can be inquired using new_Q() + */ + ATTR_HOT inline const net_sig_t Q() const { return m_Q; } - ATTR_HOT inline void set_Q(const net_sig_t newQ) + ATTR_HOT inline void register_in_listPS(const netlist_time delay_ps); + + ATTR_HOT inline void set_Q_PS(const net_sig_t newQ, const netlist_time delay_ps) { if (newQ != m_new_Q) { m_new_Q = newQ; - //m_new_QD = newQ ? 1.0 : 0.0; - register_in_list(); + register_in_listPS(delay_ps); } } + ATTR_HOT inline void set_Q_NoCheckPS(const net_sig_t val, const netlist_time delay_ps) + { + m_new_Q = val; + register_in_listPS(delay_ps); + } - ATTR_HOT inline void set_Q(const net_sig_t newQ, const UINT8 delay_ns) + ATTR_HOT inline void set_Q_PS_Analog(const double newQ, const netlist_time delay_ps) { - if (newQ != m_new_Q) + if (newQ != m_new_Q_analog) { - m_new_Q = newQ; - //m_new_QD = newQ ? 1.0 : 0.0; - register_in_list(delay_ns); + m_new_Q_analog = newQ; + register_in_listPS(delay_ps); } } + ATTR_HOT inline void set_Q_NoCheckPS_Analog(const double val, const netlist_time delay_ps) + { + m_new_Q_analog = val; + register_in_listPS(delay_ps); + } + + netlist_time m_time; + int m_in_queue; net_sig_t m_Q; net_sig_t m_new_Q; - double m_QD; - double m_new_QD; + net_sig_t m_last_Q; + double m_Q_analog; + double m_new_Q_analog; + netlist_base_t *m_netlist; + + int m_active; int m_num_cons; -#if USE_DELEGATES - net_update_delegate m_cons[32]; -#else - //net_dev_t **m_cons; - net_dev_t *m_cons[32]; -#endif - net_dev_t *m_ttldev; + net_input_t *m_cons[48]; + + const net_core_device_t *m_netdev; + double m_low_V; + double m_high_V; + +}; + +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.3; + m_high_V = 3.4; + } + + ATTR_COLD void initial(const net_sig_t val) { m_Q = val; m_new_Q = val; m_last_Q = !val; } + ATTR_HOT inline void clear() { set_Q_PS(0, netlist_time::zero); } + ATTR_HOT inline void set() { set_Q_PS(1, netlist_time::zero); } + ATTR_HOT inline void setToPS(const UINT8 val, const netlist_time delay_ps) { set_Q_PS(val, delay_ps); } + ATTR_HOT inline void setToNoCheckPS(const UINT8 val, const netlist_time delay_ps) { set_Q_NoCheckPS(val, delay_ps); } + 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(double val) { m_Q_analog = val; m_new_Q_analog = val; } + ATTR_HOT inline void setToPS(const double val, const netlist_time delay_ps) { set_Q_PS_Analog(val,delay_ps); } + ATTR_HOT inline void setToNoCheckPS(const double val, const netlist_time delay_ps) { set_Q_NoCheckPS_Analog(val,delay_ps); } }; // ---------------------------------------------------------------------------------------- -// net_dev_t +// net_device_t // ---------------------------------------------------------------------------------------- -class net_dev_t +class net_core_device_t : public net_object_t { public: - net_dev_t(netlist_setup_t *setup, const char *name) - : m_setup(setup), m_variable_input_count(false), m_name(name) + +#if USE_DELEGATES + friend class net_input_t; // for access to update +#endif + + net_core_device_t(); + + virtual ~net_core_device_t(); + + ATTR_COLD void init_core(netlist_base_t *anetlist, const char *name); + + ATTR_COLD const char *name() const { return m_name; } + + ATTR_HOT inline void update_device() { - assert(name != NULL); +#if USE_DELEGATES_A + h(); +#else + update(); +#endif } - virtual ~net_dev_t(); - - ATTR_HOT virtual void timer_cb(INT32 timer_id) {} - - const char *name() const { return m_name; } - inline netlist_setup_t *setup() { return m_setup; } - - ATTR_HOT void update_timed(); - ATTR_HOT virtual void update_param() {} - ATTR_HOT virtual void update() { } + ATTR_HOT inline net_sig_t INPVAL_PASSIVE(logic_input_t &inp) + { + net_sig_t ret; + inp.activate(); + ret = inp.Q(); + inp.inactivate(); + return ret; + } - ATTR_HOT inline net_sig_t INP(net_input_t &v) { return v.o->Q(); } + ATTR_HOT inline net_sig_t INPVAL(const logic_input_t &inp) + { + assert(inp.state() != net_input_t::INP_STATE_PASSIVE); + return inp.Q(); + } - ATTR_COLD virtual void start() {} + ATTR_HOT inline net_sig_t INPVAL_LAST(const logic_input_t &inp) { return inp.last_Q(); } - net_list_t m_inputs; + ATTR_HOT inline double INPANALOG(const analog_input_t &inp) { return inp.Q_Analog(); } - ATTR_COLD bool variable_input_count() { return m_variable_input_count; } + ATTR_HOT inline netlist_base_t *netlist() const { return m_netlist; } + + ATTR_COLD inline net_output_t * GETINPPTR(net_output_t &out) const { return &out; } + + net_list_t m_subdevs; /* stats */ osd_ticks_t total_time; @@ -383,77 +699,125 @@ public: protected: - void register_output(const char *name, net_output_t *out); - void register_input(const char *name, net_input_t *in, net_input_type type = NET_INP_TYPE_ACTIVE); - void register_param(const char *sname, net_param_t *param, double initialVal = 0.0); + ATTR_HOT virtual void update() { } + + ATTR_COLD void register_subdevice(net_core_device_t &subdev); + + netlist_base_t *m_netlist; + +private: + + net_update_delegate h; + const char *m_name; +}; + + +class net_device_t : public net_core_device_t +{ +public: + + net_device_t(); + + virtual ~net_device_t(); + + ATTR_COLD void init(netlist_setup_t *setup, const char *name); + + ATTR_COLD netlist_setup_t *setup() const { return m_setup; } + + ATTR_COLD virtual void start() {} + + ATTR_COLD bool variable_input_count() { return m_variable_input_count; } + + ATTR_COLD void register_output(const char *name, net_output_t &out); + ATTR_COLD void register_output(const net_core_device_t &dev, const char *name, net_output_t &out); + + ATTR_COLD void register_input(const char *name, net_input_t &in, int state = net_input_t::INP_STATE_ACTIVE); + ATTR_COLD void register_input(net_core_device_t &dev, const char *name, net_input_t &in, int state = net_input_t::INP_STATE_ACTIVE); + + ATTR_COLD void register_link_internal(net_input_t &in, net_output_t &out); + ATTR_COLD void register_link_internal(net_core_device_t &dev, net_input_t &in, net_output_t &out); + + net_list_t m_inputs; + +protected: + + ATTR_COLD void register_param(const char *sname, net_param_t ¶m, const double initialVal = 0.0); + ATTR_COLD void register_param(net_core_device_t &dev, const char *sname, net_param_t ¶m, const double initialVal = 0.0); netlist_setup_t *m_setup; bool m_variable_input_count; private: - - const char *m_name; }; - - class net_param_t { public: net_param_t() { } - inline void setTo(const double param) { m_param = param; m_ttldev->update_param(); } - inline void setTo(const int param) { m_param = param; m_ttldev->update_param(); } + 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; } - inline double Value() { return m_param; } - inline int ValueInt() { return m_param; } + ATTR_HOT inline double Value() const { return m_param; } + ATTR_HOT inline int ValueInt() const { return (int) m_param; } - ATTR_HOT inline const net_dev_t *ttl_dev() { return m_ttldev; } - void set_ttl_dev(net_dev_t *dev) { m_ttldev = dev; } + 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_dev_t *m_ttldev; + net_core_device_t *m_netdev; }; // ---------------------------------------------------------------------------------------- // net_signal_t // ---------------------------------------------------------------------------------------- -template -class net_signal_t : public net_dev_t +template +class net_signal_t : public net_device_t { public: - net_signal_t(netlist_setup_t *parent, const char *name) - : net_dev_t(parent, name) { } + net_signal_t() + : net_device_t() { } - //ATTR_HOT virtual void update() = 0; ATTR_COLD void start() { const char *sIN[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" }; - register_output("Q", &m_Q); + register_output("Q", m_Q); for (int i=0; i < _numdev; i++) - register_input(sIN[i], &m_i[i]); + { + register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE); + } + m_Q.initial(1); + } + + ATTR_HOT inline void update() + { + static netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) }; + for (int i=0; i< _numdev; i++) + { + m_i[i].activate(); + if (INPVAL(m_i[i]) == _check) + { + m_Q.setToPS(!_check, times[_check]);// ? 15000 : 22000); + for (int j = i + 1; j < _numdev; j++) + m_i[j].inactivate(); + return; + } + m_i[i].inactivate(); + } + m_Q.setToPS(_check, times[1-_check]);// ? 22000 : 15000); + for (int i = 0; i < _numdev; i++) + m_i[i].activate(); } protected: - net_input_t m_i[_numdev]; - net_output_t m_Q; -}; - -// ---------------------------------------------------------------------------------------- -// netlist_base_timer_t -// ---------------------------------------------------------------------------------------- - -class netlist_base_timer_t -{ -public: - netlist_base_timer_t() {} - virtual void adjust_timer(double delay) = 0; + ttl_input_t m_i[8]; + ttl_output_t m_Q; }; // ---------------------------------------------------------------------------------------- @@ -464,21 +828,10 @@ class netlist_setup_t { public: - struct net_input_setup_t { - public: - net_input_setup_t(net_input_t *inp, net_input_type type = NET_INP_TYPE_ACTIVE) - : m_inp(inp), m_type(type) {} - net_input_t *inp() { return m_inp; } - net_input_type type() { return m_type; } - private: - net_input_t *m_inp; - net_input_type m_type; - }; - - typedef tagmap_t tagmap_devices_t; + typedef tagmap_t tagmap_devices_t; typedef tagmap_t tagmap_astring_t; typedef tagmap_t tagmap_output_t; - typedef tagmap_t tagmap_input_t; + typedef tagmap_t tagmap_input_t; typedef tagmap_t tagmap_param_t; netlist_setup_t(netlist_base_t &netlist); @@ -486,18 +839,18 @@ public: netlist_base_t &netlist() { return m_netlist; } - net_dev_t *register_dev(net_dev_t *dev); + net_device_t *register_dev(net_device_t *dev); void remove_dev(const char *name); void register_output(const char *name, net_output_t *out); - void register_input(const char *name, net_input_t *inp, net_input_type type = NET_INP_TYPE_ACTIVE); + void register_input(const char *name, net_input_t *inp); void register_alias(const char *alias, const char *out); void register_param(const char *sname, net_param_t *param); void register_link(const char *sin, const char *sout); - net_output_t *find_output(const char *outname_in); - net_param_t *find_param(const char *param_in); + net_output_t &find_output(const char *outname_in); + net_param_t &find_param(const char *param_in); void register_callback(const char *devname, net_output_delegate delegate); @@ -522,7 +875,6 @@ private: tagmap_param_t m_params; tagmap_astring_t m_links; - void step_all_devices(); net_output_t *find_output_exact(const char *outname_in); const char *resolve_alias(const char *name) const; }; @@ -535,45 +887,43 @@ class netlist_base_t { public: - netlist_base_t(bool sub_cycle_exact); + struct entry_t + { + public: + entry_t() {} + entry_t(netlist_time atime, net_output_t *aout) : time(atime), out(aout) {} + netlist_time time; + net_output_t *out; + }; + typedef netlist_timed_queue queue_t; + + netlist_base_t(); virtual ~netlist_base_t(); - virtual netlist_base_timer_t *alloc_timer(net_dev_t *dev, INT32 timer_id) = 0; + void set_clock_freq(UINT64 clockfreq); - void set_clock_freq(int clockfreq); - void set_gatedelay(int gatedelay); - - ATTR_HOT inline void register_in_list(net_output_t *out, const UINT8 delay_ns) + ATTR_HOT inline void register_in_listPS1(net_output_t *out, const netlist_time attime) { - m_output_list[m_sub_cycle_exact ? ((m_current + delay_ns / m_divisor) & m_netlist_mask) : 0].add(out); + m_queue.push(queue_t::entry_t(attime, out)); } - ATTR_HOT inline void register_in_list(net_output_t *out) - { - m_output_list[m_sub_cycle_exact ? (m_current & m_netlist_mask) : 0].add(out); - } + ATTR_HOT void process_list(INT32 &atime); - ATTR_HOT inline void reset_list() - { - m_output_list[m_sub_cycle_exact ? m_current : 0].clear(); - } - - ATTR_COLD void reset_lists() - { - for (int i = 0; i <= m_netlist_mask; i++) - m_output_list[i].clear(); - } - - ATTR_HOT void process_list(void); + ATTR_HOT inline netlist_time &time() { return m_time_ps; } protected: - UINT8 m_current; - UINT8 m_divisor; - UINT8 m_netlist_mask; - bool m_sub_cycle_exact; - net_list_t m_output_list[NET_LIST_SIZE]; - int m_gatedelay; - int m_clockfreq; + netlist_time m_time_ps; + UINT32 m_rem; + UINT32 m_div; + + queue_t m_queue; + + // performance + int m_perf_out_processed; + int m_perf_inp_processed; + int m_perf_inp_active; + UINT64 m_perf_list_len; + private: @@ -581,17 +931,14 @@ private: // ---------------------------------------------------------------------------------------- -// dev_callback +// netdev_callback // ---------------------------------------------------------------------------------------- -class netdev_callback : public net_dev_t +class netdev_callback : public net_device_t { public: - netdev_callback(netlist_setup_t *parent, const char *name) - : net_dev_t(parent, name) - { - register_input("IN", &m_in); - } + netdev_callback() + : net_device_t() {} void register_callback(net_output_delegate callback) { @@ -599,35 +946,120 @@ public: } ATTR_HOT void update(); + ATTR_COLD void start() + { + register_input("IN", m_in); + } + private: - net_input_t m_in; + 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_output_t::register_in_list(const UINT8 delay_ns) +ATTR_HOT inline void net_input_t::inactivate() { - m_netlist->register_in_list(this, delay_ns); + if (m_state != INP_STATE_PASSIVE) + { + m_state = INP_STATE_PASSIVE; + m_output->dec_active(); + } } -ATTR_HOT inline void net_output_t::register_in_list() +ATTR_HOT inline void net_input_t::activate() { - m_netlist->register_in_list(this); + 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::register_in_listPS(const netlist_time delay_ps) +{ + m_time = m_netlist->time() + delay_ps; + m_in_queue = 0; /* not queued */ + if (m_active > 0) + { + m_in_queue = 1; /* pending */ + m_netlist->register_in_listPS1(this, m_time); + } +} + +ATTR_HOT inline void net_output_t::inc_active() +{ + m_active++; + if (m_active == 1 && m_in_queue == 0) + { + if (m_time >= m_netlist->time()) + { + m_in_queue = 1; /* pending */ + m_netlist->register_in_listPS1(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 net_sig_t logic_input_t::Q() const { return output()->Q(); } +ATTR_HOT inline net_sig_t logic_input_t::last_Q() const { return output()->last_Q(); } +ATTR_HOT inline double analog_input_t::Q_Analog() const { return output()->Q_Analog(); } +ATTR_HOT inline bool analog_input_t::is_highz() const { return output()->Q_Analog() == NETLIST_HIGHIMP_V; } + // ---------------------------------------------------------------------------------------- // net_dev class factory // ---------------------------------------------------------------------------------------- -class net_dev_t_base_factory +class net_device_t_base_factory { public: - virtual ~net_dev_t_base_factory() {} - virtual net_dev_t *Create(netlist_setup_t *setup, const char *name) = 0; + virtual ~net_device_t_base_factory() {} + virtual net_device_t *Create(netlist_setup_t *setup, const char *name) = 0; const char *name() { return m_name; } const char *classname() { return m_classname; } @@ -637,68 +1069,38 @@ protected: }; template -class net_dev_t_factory : public net_dev_t_base_factory +class net_device_t_factory : public net_device_t_base_factory { public: - net_dev_t_factory(const char *name, const char *classname) { m_name = name; m_classname = classname; } - net_dev_t *Create(netlist_setup_t *setup, const char *name) + net_device_t_factory(const char *name, const char *classname) { m_name = name; m_classname = classname; } + net_device_t *Create(netlist_setup_t *setup, const char *name) { - net_dev_t *r = global_alloc_clear(C(setup, name)); + net_device_t *r = global_alloc_clear(C()); + r->init(setup, name); return r; } }; -net_dev_t *net_create_device_by_classname(const char *classname, netlist_setup_t *setup, const char *icname); -net_dev_t *net_create_device_by_name(const char *name, netlist_setup_t *setup, const char *icname); +net_device_t *net_create_device_by_classname(const char *classname, netlist_setup_t *setup, const char *icname); +net_device_t *net_create_device_by_name(const char *name, netlist_setup_t *setup, const char *icname); // ---------------------------------------------------------------------------------------- // MAME glue classes // ---------------------------------------------------------------------------------------- -class netlist_timer_t : public netlist_base_timer_t -{ -public: - netlist_timer_t(device_t &parent, net_dev_t *dev, INT32 timer_id) - : netlist_base_timer_t() - { - m_param = timer_id; - m_timer = parent.machine().scheduler().timer_alloc(timer_expired_delegate(&netlist_timer_t::timer_cb, "netlist_timer_t::timer_cb", this), dev); - } - - virtual void adjust_timer(double delay) - { - m_timer->adjust(attotime::from_double(delay) ,m_param, attotime::never); - } - - void timer_cb(void *ptr, INT32 param) - { - net_dev_t *dev = (net_dev_t *) ptr; - dev->timer_cb(param); - } -private: - - INT32 m_param; - emu_timer *m_timer; -}; class netlist_t : public netlist_base_t { public: - netlist_t(device_t &parent, bool sub_cycle_exact) - : netlist_base_t(sub_cycle_exact), + netlist_t(device_t &parent) + : netlist_base_t(), m_parent(parent) {} virtual ~netlist_t() { }; inline running_machine &machine() { return m_parent.machine(); } - virtual netlist_base_timer_t *alloc_timer(net_dev_t *dev, INT32 timer_id) - { - netlist_timer_t *ret = new netlist_timer_t(m_parent, dev, timer_id); - return ret; - } - device_t &parent() { return m_parent; } private: @@ -707,7 +1109,6 @@ private: // ======================> netlist_mame_device - class netlist_mame_device : public device_t, public device_execute_interface { @@ -716,6 +1117,7 @@ public: template class output_finder; class optional_output; + template class required_output; class optional_param; class required_param; @@ -724,15 +1126,11 @@ public: // construction/destruction netlist_mame_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - static void static_set_subcycles(device_t &device, int subcycles); static void static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &)); netlist_setup_t &setup() { return *m_setup; } netlist_t &netlist() { return *m_netlist; } - //ATTR_HOT inline UINT64 Clocks() { return m_clockcnt; } - ATTR_HOT inline int SubCycles() const { return m_subcycles; } - net_list_t m_device_start_list; protected: @@ -749,7 +1147,6 @@ protected: ATTR_HOT virtual void execute_run(); netlist_t *m_netlist; - net_output_t *m_clock_input; netlist_setup_t *m_setup; @@ -758,16 +1155,9 @@ private: void step_one_clock(); void save_state(); - int m_clock; - int m_subcycles; - void (*m_setup_func)(netlist_setup_t &); - UINT32 dummy[8]; - int m_icount; - int m_ss; - int m_clk; }; @@ -817,21 +1207,22 @@ public: virtual bool OnDeviceStart() { - this->m_target = m_netlist->setup().find_output(m_output); + this->m_target = &m_netlist->setup().find_output(m_output); return this->report_missing(this->m_target != NULL, "output", false); } }; // required devices are similar but throw an error if they are not found -class netlist_mame_device::required_output : public netlist_mame_device::output_finder +template +class netlist_mame_device::required_output : public netlist_mame_device::output_finder { public: - required_output(device_t &base, const char *tag, const char *output) : output_finder(base, tag, output) { } + required_output(device_t &base, const char *tag, const char *output) : output_finder(base, tag, output) { } virtual bool OnDeviceStart() { - this->m_target = m_netlist->setup().find_output(m_output); + this->m_target = (_C *) &(this->m_netlist->setup().find_output(this->m_output)); return this->report_missing(this->m_target != NULL, "output", true); } @@ -845,7 +1236,7 @@ public: virtual bool OnDeviceStart() { - this->m_target = m_netlist->setup().find_param(m_output); + this->m_target = &m_netlist->setup().find_param(m_output); return this->report_missing(this->m_target != NULL, "parameter", false); } @@ -859,7 +1250,7 @@ public: virtual bool OnDeviceStart() { - this->m_target = m_netlist->setup().find_param(m_output); + this->m_target = &m_netlist->setup().find_param(m_output); return this->report_missing(this->m_target != NULL, "output", true); } }; @@ -867,4 +1258,5 @@ public: // device type definition extern const device_type NETLIST; + #endif diff --git a/src/mame/drivers/pong.c b/src/mame/drivers/pong.c index 44dbe9ad0e2..9e2c75ebb47 100644 --- a/src/mame/drivers/pong.c +++ b/src/mame/drivers/pong.c @@ -46,7 +46,7 @@ TODO: * http://www.youtube.com/watch?v=pDrRnJOCKZc */ -#define MASTER_CLOCK 7139000 +#define MASTER_CLOCK 7159000 #define V_TOTAL (0x105+1) #define H_TOTAL (0x1C6+1) // 454 @@ -55,7 +55,7 @@ TODO: #define VBSTART (V_TOTAL) #define VBEND (16) -#define HRES_MULT (2) +#define HRES_MULT (1) enum input_changed_enum { @@ -64,15 +64,17 @@ enum input_changed_enum IC_COIN, IC_SWITCH, IC_VR1, - IC_VR2, - IC_GATEDELAY + IC_VR2 }; static NETLIST_START(pong_schematics) - NETDEV_CONST(high, 1) - NETDEV_CONST(low, 0) - NETDEV_INPUT(clk) - NETDEV_INPUT(SRST) + NETDEV_TTL_CONST(high, 1) + NETDEV_TTL_CONST(low, 0) + NETDEV_CLOCK(clk) + NETDEV_PARAM(clk.FREQ, 7159000.0) + NETDEV_LOGIC_INPUT(SRST) + NETDEV_ANALOG_INPUT(P1) + NETDEV_ANALOG_INPUT(P2) TTL_7404_INVERT(hitQ, hit) TTL_7400_NAND(hit, hit1Q, hit2Q) @@ -111,9 +113,9 @@ static NETLIST_START(pong_schematics) TTL_7427_NOR(ic_g2a, ic_g3c.Q, 256HQ, vpad2Q) NET_ALIAS(pad2, ic_g2a.Q) - /* horizontal counter */ - TTL_7493(ic_f8, clk, ic_e7b.QQ, ic_e7b.QQ) /* f8, f9, f6b */ - TTL_7493(ic_f9, ic_f8.QD, ic_e7b.QQ, ic_e7b.QQ) /* f8, f9, f6b */ + // horizontal counter + TTL_7493(ic_f8, clk, ic_f8.QA, ic_e7b.QQ, ic_e7b.QQ) // f8, f9, f6b + TTL_7493(ic_f9, ic_f8.QD, ic_f9.QA, ic_e7b.QQ, ic_e7b.QQ) // f8, f9, f6b TTL_74107(ic_f6b, ic_f9.QD, high, high, ic_e7b.Q) TTL_7430_NAND(ic_f7, ic_f8.QB, ic_f8.QC, ic_f9.QC, ic_f9.QD, ic_f6b.Q, high, high, high) TTL_7474(ic_e7b, clk, ic_f7, high, high) @@ -129,9 +131,9 @@ static NETLIST_START(pong_schematics) NET_ALIAS(256H, ic_f6b.Q) NET_ALIAS(256HQ, ic_f6b.QQ) - /* vertical counter */ - TTL_7493(ic_e8, hreset, ic_e7a.QQ, ic_e7a.QQ) /* e8, e9, d9b */ - TTL_7493(ic_e9, ic_e8.QD, ic_e7a.QQ, ic_e7a.QQ) /* e8, e9, d9b */ + // vertical counter + TTL_7493(ic_e8, hreset, ic_e8.QA, ic_e7a.QQ, ic_e7a.QQ) // e8, e9, d9b + TTL_7493(ic_e9, ic_e8.QD,ic_e9.QA, ic_e7a.QQ, ic_e7a.QQ) // e8, e9, d9b TTL_74107(ic_d9b, ic_e9.QD, high, high, ic_e7a.Q) TTL_7474(ic_e7a, hreset, e7a_data, high, high) TTL_7410_NAND(e7a_data, ic_e8.QA, ic_e8.QC, ic_d9b.Q) @@ -147,11 +149,11 @@ static NETLIST_START(pong_schematics) NET_ALIAS(256VQ, ic_d9b.QQ) - /* hblank flip flop */ + // hblank flip flop TTL_7400_NAND(ic_g5b, 16H, 64H) - /* the time critical one */ + // the time critical one TTL_7400_NAND(ic_h5c, ic_h5b.Q, hresetQ) TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b.Q) @@ -159,7 +161,7 @@ static NETLIST_START(pong_schematics) NET_ALIAS(hblankQ, ic_h5b.Q) TTL_7400_NAND(hsyncQ, hblank, 32H) - /* vblank flip flop */ + // vblank flip flop TTL_7402_NOR(ic_f5c, ic_f5d.Q, vreset) TTL_7402_NOR(ic_f5d, ic_f5c.Q, 16V) @@ -170,11 +172,11 @@ static NETLIST_START(pong_schematics) TTL_7410_NAND(ic_g5a, vblank, 4V, ic_h5a.Q) NET_ALIAS(vsyncQ, ic_g5a.Q) - /* move logic */ + // move logic TTL_7400_NAND(ic_e1d, hit_sound, ic_e1c.Q) TTL_7400_NAND(ic_e1c, ic_f1.QC, ic_f1.QD) - TTL_7493(ic_f1, ic_e1d.Q, rstspeed, rstspeed) + TTL_7493(ic_f1, ic_e1d.Q, ic_f1.QA, rstspeed, rstspeed) TTL_7402_NOR(ic_g1d, ic_f1.QC, ic_f1.QD) TTL_7400_NAND(ic_h1a, ic_g1d.Q, ic_g1d.Q) @@ -199,7 +201,7 @@ static NETLIST_START(pong_schematics) NET_ALIAS(Aa, ic_h4c.Q) NET_ALIAS(Ba, ic_h4b.Q) - /* hvid circuit */ + // hvid circuit TTL_7400_NAND(hball_resetQ, Serve, attractQ) @@ -210,19 +212,19 @@ static NETLIST_START(pong_schematics) TTL_7420_NAND(ic_h6b, ic_g6b.Q, ic_h7.RC, ic_g7.QC, ic_g7.QD) NET_ALIAS(hvidQ, ic_h6b.Q) - /* vvid circuit */ + // vvid circuit TTL_9316(ic_b3, hsyncQ, high, vblankQ, high, ic_b2b.Q, a6, b6, c6, d6) TTL_9316(ic_a3, hsyncQ, ic_b3.RC, high, high, ic_b2b.Q, low, low, low, low) TTL_7400_NAND(ic_b2b, ic_a3.RC, ic_b3.RC) TTL_7410_NAND(ic_e2b, ic_a3.RC, ic_b3.QC, ic_b3.QD) NET_ALIAS(vvidQ, ic_e2b.Q) - TTL_7404_INVERT(vvid, vvidQ) /* D2D */ + TTL_7404_INVERT(vvid, vvidQ) // D2D NET_ALIAS(vpos256, ic_a3.RC) NET_ALIAS(vpos32, ic_a3.QB) NET_ALIAS(vpos16, ic_a3.QA) - /* vball ctrl circuit */ + // vball ctrl circuit TTL_7450_ANDORINVERT(ic_a6a, b1, 256HQ, b2, 256H) TTL_7450_ANDORINVERT(ic_a6b, c1, 256HQ, c2, 256H) @@ -231,7 +233,7 @@ static NETLIST_START(pong_schematics) TTL_7474(ic_a5b, hit, ic_a6a, attractQ, high) TTL_7474(ic_a5a, hit, ic_a6b, attractQ, high) TTL_7474(ic_b5a, hit, ic_b6b, attractQ, high) - TTL_74107(ic_h2x, vblank, vvid, vvid, hitQ) /* two marked at position h2a ==> this h2x */ + TTL_74107(ic_h2x, vblank, vvid, vvid, hitQ) // two marked at position h2a ==> this h2x TTL_7486_XOR(ic_a4c, ic_a5b.Q, ic_h2x.Q) TTL_7486_XOR(ic_a4b, ic_a5a.Q, ic_h2x.Q) @@ -246,9 +248,9 @@ static NETLIST_START(pong_schematics) NET_ALIAS(c6, ic_b4.SC) NET_ALIAS(d6, ic_b4.SD) - /* serve monoflop */ + // serve monoflop TTL_7404_INVERT(f4_trig, rstspeed) - NE555N_MSTABLE(ic_f4_serve, f4_trig) + NE555N_MSTABLE(ic_f4_serve, f4_trig, NC) NETDEV_PARAM(ic_f4_serve.R, RES_K(330)) NETDEV_PARAM(ic_f4_serve.C, CAP_U(4.7)) @@ -258,15 +260,15 @@ static NETLIST_START(pong_schematics) NET_ALIAS(Serve, ic_b5b_serve.QQ) NET_ALIAS(ServeQ, ic_b5b_serve.Q) - /* score logic */ + // score logic TTL_7474(ic_h3a, 4H, 128H, high, attractQ) - /* sound logic */ + // sound logic TTL_7474(ic_c2a, vpos256, high, hitQ, high) TTL_74107(ic_f3_topbot, vblank, vvid, vvidQ, ServeQ) - NE555N_MSTABLE(ic_g4_sc, MissQ) - NET_ALIAS(SC, ic_g4_sc.Q) /* monoflop with NE555 determines score sound */ + NE555N_MSTABLE(ic_g4_sc, MissQ, NC) + NET_ALIAS(SC, ic_g4_sc.Q) // monoflop with NE555 determines score sound NETDEV_PARAM(ic_g4_sc.R, RES_K(220)) NETDEV_PARAM(ic_g4_sc.C, CAP_U(1)) @@ -280,15 +282,15 @@ static NETLIST_START(pong_schematics) NET_ALIAS(sound, ic_c1b.Q) - /* paddle1 logic 1 */ + // paddle1 logic 1 - NE555N_MSTABLE(ic_b9, 256VQ) + NE555N_MSTABLE(ic_b9, 256VQ, P1) NETDEV_PARAM(ic_b9.R, RES_K(90)) NETDEV_PARAM(ic_b9.C, CAP_U(.1)) NETDEV_PARAM(ic_b9.VL, 0.7) TTL_7404_INVERT(ic_c9b, ic_b9.Q) TTL_7400_NAND(ic_b7b, ic_a7b.Q, hsyncQ) - TTL_7493(ic_b8, ic_b7b.Q, ic_b9.Q, ic_b9.Q) + TTL_7493(ic_b8, ic_b7b.Q, ic_b8.QA, ic_b9.Q, ic_b9.Q) TTL_7400_NAND(ic_b7a, ic_c9b.Q, ic_a7b.Q) TTL_7420_NAND(ic_a7b, ic_b8.QA, ic_b8.QB, ic_b8.QC, ic_b8.QD) NET_ALIAS(vpad1Q, ic_b7a.Q) @@ -297,15 +299,15 @@ static NETLIST_START(pong_schematics) NET_ALIAS(c1, ic_b8.QC) NET_ALIAS(d1, ic_b8.QD) - /* paddle1 logic 2 */ + // paddle1 logic 2 - NE555N_MSTABLE(ic_a9, 256VQ) + NE555N_MSTABLE(ic_a9, 256VQ, P2) NETDEV_PARAM(ic_a9.R, RES_K(90)) NETDEV_PARAM(ic_a9.C, CAP_U(.1)) NETDEV_PARAM(ic_a9.VL, 0.7) TTL_7404_INVERT(ic_c9a, ic_a9.Q) TTL_7400_NAND(ic_b7c, ic_a7a.Q, hsyncQ) - TTL_7493(ic_a8, ic_b7c.Q, ic_a9.Q, ic_a9.Q) + TTL_7493(ic_a8, ic_b7c.Q, ic_a8.QA, ic_a9.Q, ic_a9.Q) TTL_7400_NAND(ic_b7d, ic_c9a.Q, ic_a7a.Q) TTL_7420_NAND(ic_a7a, ic_a8.QA, ic_a8.QB, ic_a8.QC, ic_a8.QD) NET_ALIAS(vpad2Q, ic_b7d.Q) @@ -314,7 +316,7 @@ static NETLIST_START(pong_schematics) NET_ALIAS(c2, ic_a8.QC) NET_ALIAS(d2, ic_a8.QD) - /* C5-EN Logic */ + // C5-EN Logic TTL_7404_INVERT(ic_e3a, 128H) TTL_7427_NOR( ic_e3b, 256H, 64H, ic_e3a.Q) @@ -325,14 +327,14 @@ static NETLIST_START(pong_schematics) TTL_7425_NOR(ic_f2a, ic_g1a.Q, 64V, 128V, ic_d2c.Q) NET_ALIAS(c5-en, ic_f2a.Q) - /* Score logic ... */ + // Score logic ... TTL_7402_NOR(ic_f5b, L, Missed) TTL_7490(ic_c7, ic_f5b, SRST, SRST, low, low) TTL_74107(ic_c8a, ic_c7.QD, high, high, SRSTQ) NETDEV_SWITCH2(sw1a, high, ic_c7.QC) NETDEV_PARAM(sw1a.POS, 0) - TTL_7410_NAND(ic_d8a, ic_c7.QA, sw1a.Q, ic_c8a.Q) /* would be nand2 for 11 instead of 15 points, need a switch dev! */ + TTL_7410_NAND(ic_d8a, ic_c7.QA, sw1a.Q, ic_c8a.Q) // would be nand2 for 11 instead of 15 points, need a switch dev! NET_ALIAS(StopG1Q, ic_d8a.Q) NET_ALIAS(score1_1, ic_c7.QA) @@ -347,7 +349,7 @@ static NETLIST_START(pong_schematics) TTL_74107(ic_c8b, ic_d7.QD, high, high, SRSTQ) NETDEV_SWITCH2(sw1b, high, ic_d7.QC) NETDEV_PARAM(sw1b.POS, 0) - TTL_7410_NAND(ic_d8b, ic_d7.QA, sw1b.Q, ic_c8b.Q) /* would be nand2 for 11 instead of 15 points, need a switch dev! */ + TTL_7410_NAND(ic_d8b, ic_d7.QA, sw1b.Q, ic_c8b.Q) // would be nand2 for 11 instead of 15 points, need a switch dev! NET_ALIAS(StopG2Q, ic_d8b.Q) NET_ALIAS(score2_1, ic_d7.QA) @@ -357,7 +359,7 @@ static NETLIST_START(pong_schematics) NET_ALIAS(score2_10, ic_c8b.Q) NET_ALIAS(score2_10Q, ic_c8b.QQ) - /* Score display */ + // Score display TTL_74153(ic_d6a, score1_10Q, score1_4, score2_10Q, score2_4, 32H, 64H, low) TTL_74153(ic_d6b, score1_10Q, score1_8, score2_10Q, score2_8, 32H, 64H, low) @@ -395,18 +397,26 @@ static NETLIST_START(pong_schematics) TTL_7430_NAND(ic_d3, ic_d4a, ic_d5c, ic_c4c, ic_d5a, ic_d4c, ic_d4b, ic_d5b, high) NET_ALIAS(score, ic_d3.Q) //FIXME - /* net */ + // net TTL_74107(ic_f3b, clk, 256H, 256HQ, high) TTL_7400_NAND(ic_g3b, ic_f3b.QQ, 256H) TTL_7427_NOR(ic_g2b, ic_g3b.Q, vblank, 4V) NET_ALIAS(net, ic_g2b.Q) - /* video */ + // video TTL_7402_NOR(ic_g1b, hvidQ, vvidQ) TTL_7425_NOR(ic_f2b, ic_g1b.Q, pad1, pad2, net) TTL_7404_INVERT(ic_e4e, ic_f2b.Q) NET_ALIAS(video, ic_e4e.Q) + TTL_7486_XOR(ic_a4d, hsyncQ, vsyncQ) + TTL_7404_INVERT(ic_e4f, ic_a4d.Q) + + NETDEV_MIXER3(videomix, video, score, ic_e4f.Q) + NETDEV_PARAM(videomix.R1, RES_K(1)) + NETDEV_PARAM(videomix.R2, RES_K(1.2)) + NETDEV_PARAM(videomix.R3, RES_K(22)) + NETLIST_END static NETLIST_START(pong) @@ -414,8 +424,7 @@ static NETLIST_START(pong) //NETLIST_INCLUDE(pong_schematics) NETLIST_MEMREGION("maincpu") NETDEV_CALLBACK(sound_cb, sound) - NETDEV_CALLBACK(video_cb, video) - NETDEV_CALLBACK(score_cb, score) + NETDEV_CALLBACK(video_cb, videomix) NETLIST_END @@ -425,13 +434,12 @@ static NETLIST_START(pong_fast) /* the signal above is delayed on pong due to counter at gate delays. * This is approximated by the following circuit ... */ - NET_REMOVE_DEV(ic_h5b) - NETDEV_DELAY_RISE(ic_g5b_D, clk, ic_g5b.Q) - TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b_D.Q) + //NET_REMOVE_DEV(ic_h5b) + //NETDEV_DELAY_RISE(ic_g5b_D, clk, ic_g5b.Q) + //TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b_D.Q) NETDEV_CALLBACK(sound_cb, sound) - NETDEV_CALLBACK(video_cb, video) - NETDEV_CALLBACK(score_cb, score) + NETDEV_CALLBACK(video_cb, videomix) NETLIST_END @@ -443,10 +451,10 @@ public: m_maincpu(*this, "maincpu"), m_dac(*this, "dac"), /* just to have a sound device */ m_srst(*this, "maincpu", "SRST"), + m_p_V0(*this, "maincpu", "P1"), + m_p_V1(*this, "maincpu", "P2"), m_sw1a(*this, "maincpu", "sw1a.POS"), m_sw1b(*this, "maincpu", "sw1b.POS"), - m_p_V0(*this, "maincpu", "ic_a9.VT"), - m_p_V1(*this, "maincpu", "ic_b9.VT"), m_p_R0(*this, "maincpu", "ic_a9.R"), m_p_R1(*this, "maincpu", "ic_b9.R") { @@ -457,11 +465,11 @@ public: required_device m_dac; /* just to have a sound device */ // sub devices - netlist_mame_device::required_output m_srst; + netlist_mame_device::required_output m_srst; + netlist_mame_device::required_output m_p_V0; + netlist_mame_device::required_output m_p_V1; netlist_mame_device::required_param m_sw1a; netlist_mame_device::required_param m_sw1b; - netlist_mame_device::required_param m_p_V0; - netlist_mame_device::required_param m_p_V1; netlist_mame_device::required_param m_p_R0; netlist_mame_device::required_param m_p_R1; @@ -469,21 +477,21 @@ public: DECLARE_INPUT_CHANGED_MEMBER(input_changed); - void sound_cb(net_sig_t newval) + void sound_cb(double newval) { - m_dac->write_unsigned8(128*(!newval)); + //printf("snd %f\n", newval); + //dac_w(m_dac, 0, newval*64); + m_dac->write_unsigned8(64*newval); } - void video_cb(net_sig_t newval) + void video_cb(double newval) { - update_vid(); - m_vid = (m_vid & 2) | (UINT8) newval; - } - - void score_cb(net_sig_t newval) - { - update_vid(); - m_vid = (m_vid & 1) | ((UINT8) newval<<1); + //printf("%f\n", newval); + if (newval != m_vid) + { + update_vid(); + m_vid = newval; + } } protected: @@ -498,29 +506,75 @@ private: void update_vid() { + const netlist_time clock_period = netlist_time::from_hz(NETLIST_CLOCK); + const netlist_time hsync_min_time = netlist_time::from_us(4); + const netlist_time vsync_min_time = netlist_time::from_us(50); /* usec */ + const int vsync_min_pulses = 4; + UINT64 clocks = m_maincpu->total_cycles(); // m_maincpu->attotime_to_cycles(m_maincpu->local_time()); - int new_x = clocks % ( m_maincpu->SubCycles() * H_TOTAL); - int new_y = (clocks / (m_maincpu->SubCycles() * H_TOTAL)) % V_TOTAL; - if (m_vid > 0) + int pw = NETLIST_CLOCK / ((UINT64)MASTER_CLOCK) / HRES_MULT; + netlist_time time = clock_period * (clocks - m_last_clock); + + //UINT64 clocks = m_maincpu->netlist().time().as_raw() >> 10; // m_maincpu->attotime_to_cycles(m_maincpu->local_time()); + //int pw = (NETLIST_INTERNAL_CLOCK / ((UINT64)MASTER_CLOCK) / HRES_MULT) >> 8; + + if (m_last_y < m_bitmap->height()) { - rgb_t col = MAKE_RGB(255,255,255); - if (new_y > m_last_y) - new_x = m_maincpu->SubCycles() * H_TOTAL-1; - int delta = (new_x - m_last_x); - if (delta < m_maincpu->SubCycles()) - col = MAKE_RGB(255 * delta /( m_maincpu->SubCycles()),255 * delta /( m_maincpu->SubCycles()),255 * delta /( m_maincpu->SubCycles())); - for (int i = m_last_x / ( m_maincpu->SubCycles() / HRES_MULT); i < new_x / ( m_maincpu->SubCycles()/HRES_MULT); i++) + int colv = (int) (m_vid / 3.5 * 255.0); + rgb_t col = MAKE_RGB(colv, colv, colv); + int pixels = (clocks - m_line_clock) / pw; + + while (pixels >= m_bitmap->width()) + { + for (int i = m_last_x ; i < m_bitmap->width() - 1; i++) + m_bitmap->pix(m_last_y, i) = col; + pixels -= m_bitmap->width(); + m_last_x = 0; + } + for (int i = m_last_x ; i < pixels; i++) m_bitmap->pix(m_last_y, i) = col; + m_last_x = pixels; } - m_last_x = new_x; - m_last_y = new_y; + if (m_vid <= 0.34) + { + if (time >= vsync_min_time) + { + m_vsync_cnt++; + if (m_vsync_cnt >= vsync_min_pulses) + { + m_vsync_cnt = 0; + m_last_y = 0; + attoseconds_t new_refresh = DOUBLE_TO_ATTOSECONDS((double) (clocks - m_vsync_clock) / (double) NETLIST_CLOCK); + if (new_refresh != m_refresh) + { + m_refresh = new_refresh; + rectangle visarea(0, H_TOTAL * HRES_MULT - 1, 0, V_TOTAL-1); + this->mconfig().first_screen()->configure(H_TOTAL * HRES_MULT, V_TOTAL, visarea, m_refresh); + m_vsync_clock = clocks; + } + } + m_last_y++; + m_last_x = 0; + } + else if (time >= hsync_min_time) + { + m_last_x = 0; // hsync + m_last_y++; + m_line_clock = clocks; + } + } + m_last_clock = clocks; } - UINT8 m_vid; + double m_vid; int m_last_x; int m_last_y; + UINT64 m_last_clock; + UINT64 m_line_clock; + UINT64 m_vsync_clock; + attoseconds_t m_refresh; + int m_vsync_cnt; bitmap_rgb32 *m_bitmap; - }; void pong_state::machine_start() @@ -530,13 +584,10 @@ void pong_state::machine_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("score_cb", net_output_delegate(&pong_state::score_cb, "pong_state::score_cb", this)); } void pong_state::machine_reset() { -// m_sound_nmi_enabled = FALSE; -// m_nmi_enable = 0; } @@ -549,7 +600,7 @@ void pong_state::video_start() UINT32 pong_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect ) { copybitmap(bitmap, *m_bitmap, 0, 0, 0, 0, cliprect); - m_bitmap->fill(MAKE_RGB(0,0,0)); + //m_bitmap->fill(MAKE_RGB(0,0,0)); return 0; } @@ -579,8 +630,8 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed) double pad = vA + (vB - vA)*PRE_R / (Req + PRE_R); switch (numpad) { - case IC_PADDLE1: m_p_V0->setTo(pad); break; - case IC_PADDLE2: m_p_V1->setTo(pad); break; + case IC_PADDLE1: m_p_V0->setToPS(pad, NLTIME_FROM_NS(0)); break; + case IC_PADDLE2: m_p_V1->setToPS(pad, NLTIME_FROM_NS(0)); break; } break; } @@ -589,7 +640,7 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed) m_sw1b->setTo(newval ? 1 : 0); break; case IC_COIN: - m_srst->setTo(newval & 1); + m_srst->setToPS(newval & 1, NLTIME_FROM_US(500)); break; case IC_VR1: case IC_VR2: @@ -600,9 +651,6 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed) case IC_VR2: m_p_R1->setTo(pad); break; } break; - case IC_GATEDELAY: - m_maincpu->netlist().set_gatedelay(newval); - break; } @@ -626,15 +674,15 @@ static INPUT_PORTS_START( pong ) PORT_ADJUSTER( 63, "VR1 - 50k, Paddle 1 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR1) PORT_START("VR2") PORT_ADJUSTER( 63, "VR2 - 50k, Paddle 2 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR2) - PORT_START("GATESPEED") - PORT_ADJUSTER( 100, "Logic Gate Delay" ) PORT_MINMAX(10, 200) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_GATEDELAY) + //PORT_START("GATESPEED") + //PORT_ADJUSTER( 100, "Logic Gate Delay" ) PORT_MINMAX(10, 200) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_GATEDELAY) INPUT_PORTS_END static MACHINE_CONFIG_START( pong, pong_state ) /* basic machine hardware */ - MCFG_NETLIST_ADD("maincpu", MASTER_CLOCK, pong, 10) + MCFG_NETLIST_ADD("maincpu", pong) /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) @@ -651,7 +699,8 @@ MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( pongf, pong ) /* basic machine hardware */ - MCFG_NETLIST_REPLACE("maincpu", MASTER_CLOCK, pong_fast, 2) + //MCFG_NETLIST_REPLACE("maincpu", MASTER_CLOCK, pong_fast, 100) + MCFG_NETLIST_REPLACE("maincpu", pong_fast) MACHINE_CONFIG_END @@ -663,7 +712,7 @@ MACHINE_CONFIG_END ROM_START( pong ) /* dummy to satisfy game entry*/ ROM_REGION( 0x10000, "maincpu", 0 ) /* enough for netlist */ - ROM_LOAD( "pong.netlist", 0x00000, 10306, CRC(bb92b267) SHA1(0dd6b3209ac1335a97cfe159502d24556f531007) ) + ROM_LOAD( "pong.netlist", 0x000000, 0x0029e4, CRC(e9c409a1) SHA1(1dc99437f49261c3cb3f46153c6258043bc720a0) ) ROM_END ROM_START( pongf ) /* dummy to satisfy game entry*/