Netlist: ongoing cleanup

- simplified classes
- separated logic and analog inputs/outputs.
This commit is contained in:
Couriersud 2013-10-26 19:58:49 +00:00
parent 1a4b917d7e
commit 708fd81c72
5 changed files with 483 additions and 410 deletions

View File

@ -72,7 +72,7 @@ NETLIB_CONSTRUCTOR(netdev_log)
NETLIB_UPDATE(netdev_log)
{
printf("%s: %d %d\n", name(), (UINT32) (netlist().time().as_raw() / 1000000), INPVAL(m_I));
printf("%s: %d %d\n", name(), (UINT32) (netlist().time().as_raw() / 1000000), INPLOGIC(m_I));
}
NETLIB_CONSTRUCTOR(netdev_clock)
@ -94,18 +94,8 @@ NETLIB_UPDATE_PARAM(netdev_clock)
NETLIB_UPDATE(netdev_clock)
{
m_Q.setToNoCheck(!m_Q.new_Q(), m_inc );
}
NETLIB_UPDATE_PARAM(netdev_mainclock)
{
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
NETLIB_UPDATE(netdev_mainclock)
{
*m_Q.new_Q_ptr() = !m_Q.new_Q();
m_Q.set_time(m_netlist.time() + m_inc);
//m_Q.setToNoCheck(!m_Q.new_Q(), m_inc );
OUTLOGIC(m_Q, !m_Q.new_Q(), m_inc );
}
NETLIB_CONSTRUCTOR(nicMultiSwitch)
@ -120,7 +110,7 @@ NETLIB_CONSTRUCTOR(nicMultiSwitch)
{
register_input(sIN[i], m_I[i]);
//register_link_internal(m_I[i], m_low);
m_I[i].set_output( GETINPPTR(m_low));
m_I[i].set_output(m_low);
}
register_param("POS", m_POS);
register_output("Q", m_Q);
@ -131,7 +121,7 @@ NETLIB_CONSTRUCTOR(nicMultiSwitch)
NETLIB_UPDATE(nicMultiSwitch)
{
assert(m_position<8);
m_Q.setTo(INPANALOG(m_I[m_position]), NLTIME_FROM_NS(1));
OUTANALOG(m_Q, INPANALOG(m_I[m_position]), NLTIME_FROM_NS(1));
}
NETLIB_UPDATE_PARAM(nicMultiSwitch)
@ -151,7 +141,7 @@ NETLIB_CONSTRUCTOR(nicMixer8)
for (i=0; i<8; i++)
{
register_input(sI[i], m_I[i]);
m_I[i].set_output(GETINPPTR(m_low));
m_I[i].set_output(m_low);
register_param(sR[i], m_R[i], 1e12);
}
register_output("Q", m_Q);
@ -168,7 +158,7 @@ NETLIB_UPDATE(nicMixer8)
{
r += m_w[i] * INPANALOG(m_I[i]);
}
m_Q.setTo(r, NLTIME_IMMEDIATE);
OUTANALOG(m_Q, r, NLTIME_IMMEDIATE);
}
NETLIB_UPDATE_PARAM(nicMixer8)
@ -198,15 +188,15 @@ NETLIB_CONSTRUCTOR(nicRSFF)
NETLIB_UPDATE(nicRSFF)
{
if (INPVAL(m_S))
if (INPLOGIC(m_S))
{
m_Q.set();
m_QQ.clear();
OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(10));
OUTLOGIC(m_QQ, 0, NLTIME_FROM_NS(10));
}
else if (INPVAL(m_R))
else if (INPLOGIC(m_R))
{
m_Q.clear();
m_QQ.set();
OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(10));
OUTLOGIC(m_QQ, 1, NLTIME_FROM_NS(10));
}
}
@ -222,7 +212,7 @@ NETLIB_CONSTRUCTOR(nicNE555N_MSTABLE)
register_param("VS", m_VS, 5.0);
register_param("VL", m_VL, 0.0 *5.0);
m_THRESHOLD_OUT.set_netdev(this);
m_THRESHOLD_OUT.init_terminal(this);
register_link_internal(m_THRESHOLD, m_THRESHOLD_OUT, net_input_t::INP_STATE_ACTIVE);
m_Q.initial(5.0 * 0.4);
@ -283,13 +273,13 @@ NETLIB_UPDATE(nicNE555N_MSTABLE)
time = 10.0;
}
m_Q.setToNoCheckPS(m_VS.Value() * 0.7, NLTIME_FROM_NS(100));
m_THRESHOLD_OUT.setTo(m_VS.Value(), NLTIME_FROM_US(time ));
OUTANALOG(m_Q, m_VS.Value() * 0.7, NLTIME_FROM_NS(100));
OUTANALOG(m_THRESHOLD_OUT, m_VS.Value(), NLTIME_FROM_US(time ));
}
else if (m_last && !out)
{
m_Q.setToNoCheckPS(0.25, NLTIME_FROM_NS(100));
m_THRESHOLD_OUT.setTo(0.0, NLTIME_FROM_NS(1));
OUTANALOG(m_Q, 0.25, NLTIME_FROM_NS(100));
OUTANALOG(m_THRESHOLD_OUT, 0.0, NLTIME_FROM_NS(1));
}
m_last = out;
}
@ -304,8 +294,8 @@ NETLIB_CONSTRUCTOR(nic7404)
NETLIB_UPDATE(nic7404)
{
static const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
UINT8 t = (INPVAL(m_I)) ^ 1;
m_Q.setTo(t, delay[t]);
UINT8 t = (INPLOGIC(m_I)) ^ 1;
OUTLOGIC(m_Q, t, delay[t]);
}
NETLIB_CONSTRUCTOR(nic7486)
@ -318,8 +308,8 @@ NETLIB_CONSTRUCTOR(nic7486)
NETLIB_UPDATE(nic7486)
{
static const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
UINT8 t = INPVAL(m_I0) ^ INPVAL(m_I1);
m_Q.setTo(t, delay[t]);
UINT8 t = INPLOGIC(m_I0) ^ INPLOGIC(m_I1);
OUTLOGIC(m_Q, t, delay[t]);
}
NETLIB_CONSTRUCTOR(nic7448)
@ -347,16 +337,16 @@ NETLIB_CONSTRUCTOR(nic7448)
NETLIB_UPDATE(nic7448)
{
if (INPVAL(m_BIQ) && !INPVAL(m_LTQ))
if (INPLOGIC(m_BIQ) && !INPLOGIC(m_LTQ))
{
sub.update_outputs(8);
}
else if (!INPVAL(m_BIQ))
else if (!INPLOGIC(m_BIQ))
{
sub.update_outputs(15);
}
if (!INPVAL(m_BIQ) || (INPVAL(m_BIQ) && !INPVAL(m_LTQ)))
if (!INPLOGIC(m_BIQ) || (INPLOGIC(m_BIQ) && !INPLOGIC(m_LTQ)))
{
sub.m_A0.inactivate();
sub.m_A1.inactivate();
@ -378,8 +368,8 @@ NETLIB_UPDATE(nic7448_sub)
{
UINT8 v;
v = (INPVAL(m_A0) << 0) | (INPVAL(m_A1) << 1) | (INPVAL(m_A2) << 2) | (INPVAL(m_A3) << 3);
if ((!INPVAL(m_RBIQ) && (v==0)))
v = (INPLOGIC(m_A0) << 0) | (INPLOGIC(m_A1) << 1) | (INPLOGIC(m_A2) << 2) | (INPLOGIC(m_A3) << 3);
if ((!INPLOGIC(m_RBIQ) && (v==0)))
v = 15;
update_outputs(v);
}
@ -389,13 +379,13 @@ NETLIB_FUNC_VOID(nic7448_sub, update_outputs, (UINT8 v))
assert(v<16);
if (v != m_state)
{
m_a.setTo(tab7448[v][0], NLTIME_FROM_NS(100));
m_b.setTo(tab7448[v][1], NLTIME_FROM_NS(100));
m_c.setTo(tab7448[v][2], NLTIME_FROM_NS(100));
m_d.setTo(tab7448[v][3], NLTIME_FROM_NS(100));
m_e.setTo(tab7448[v][4], NLTIME_FROM_NS(100));
m_f.setTo(tab7448[v][5], NLTIME_FROM_NS(100));
m_g.setTo(tab7448[v][6], NLTIME_FROM_NS(100));
OUTLOGIC(m_a, tab7448[v][0], NLTIME_FROM_NS(100));
OUTLOGIC(m_b, tab7448[v][1], NLTIME_FROM_NS(100));
OUTLOGIC(m_c, tab7448[v][2], NLTIME_FROM_NS(100));
OUTLOGIC(m_d, tab7448[v][3], NLTIME_FROM_NS(100));
OUTLOGIC(m_e, tab7448[v][4], NLTIME_FROM_NS(100));
OUTLOGIC(m_f, tab7448[v][5], NLTIME_FROM_NS(100));
OUTLOGIC(m_g, tab7448[v][6], NLTIME_FROM_NS(100));
m_state = v;
}
}
@ -431,11 +421,11 @@ NETLIB_CONSTRUCTOR(nic7450)
NETLIB_UPDATE(nic7450)
{
UINT8 t1 = INPVAL(m_I0) & INPVAL(m_I1);
UINT8 t2 = INPVAL(m_I2) & INPVAL(m_I3);
UINT8 t1 = INPLOGIC(m_I0) & INPLOGIC(m_I1);
UINT8 t2 = INPLOGIC(m_I2) & INPLOGIC(m_I3);
#if 0
UINT8 t = (t1 | t2) ^ 1;
m_Q.setTo(t, t ? NLTIME_FROM_NS(22) : NLTIME_FROM_NS(15));
OUTLOGIC(m_Q, t, t ? NLTIME_FROM_NS(22) : NLTIME_FROM_NS(15));
#else
const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
@ -464,46 +454,46 @@ NETLIB_UPDATE(nic7450)
m_I3.inactivate();
}
}
m_Q.setTo(res, times[1 - res]);// ? 22000 : 15000);
OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
#endif
}
INLINE void nic7474_newstate(const UINT8 state, ttl_output_t &Q, ttl_output_t &QQ)
ATTR_HOT inline void nic7474sub::newstate(const UINT8 state)
{
static const netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(40) };
//printf("%s %d %d %d\n", "7474", state, Q.Q(), QQ.Q());
Q.setTo(state, delay[state]);
QQ.setTo(!state, delay[!state]);
OUTLOGIC(m_Q, state, delay[state]);
OUTLOGIC(m_QQ, !state, delay[!state]);
}
NETLIB_UPDATE(nic7474sub)
{
//if (!INP_LAST(m_clk) & INP(m_clk))
{
nic7474_newstate(m_nextD, m_Q, m_QQ);
newstate(m_nextD);
m_clk.inactivate();
}
}
NETLIB_UPDATE(nic7474)
{
if (!INPVAL(m_preQ))
if (!INPLOGIC(m_preQ))
{
nic7474_newstate(1, sub.m_Q, sub.m_QQ);
sub.newstate(1);
sub.m_clk.inactivate();
m_D.inactivate();
}
else if (!INPVAL(m_clrQ))
else if (!INPLOGIC(m_clrQ))
{
nic7474_newstate(0, sub.m_Q, sub.m_QQ);
sub.newstate(0);
sub.m_clk.inactivate();
m_D.inactivate();
}
else
{
m_D.activate();
sub.m_nextD = INPVAL(m_D);
sub.m_nextD = INPLOGIC(m_D);
sub.m_clk.activate_lh();
}
}
@ -547,19 +537,19 @@ NETLIB_CONSTRUCTOR(nic7483)
NETLIB_UPDATE(nic7483)
{
UINT8 a = (INPVAL(m_A1) << 0) | (INPVAL(m_A2) << 1) | (INPVAL(m_A3) << 2) | (INPVAL(m_A4) << 3);
UINT8 b = (INPVAL(m_B1) << 0) | (INPVAL(m_B2) << 1) | (INPVAL(m_B3) << 2) | (INPVAL(m_B4) << 3);
UINT8 a = (INPLOGIC(m_A1) << 0) | (INPLOGIC(m_A2) << 1) | (INPLOGIC(m_A3) << 2) | (INPLOGIC(m_A4) << 3);
UINT8 b = (INPLOGIC(m_B1) << 0) | (INPLOGIC(m_B2) << 1) | (INPLOGIC(m_B3) << 2) | (INPLOGIC(m_B4) << 3);
UINT8 r = a + b + INPVAL(m_CI);
UINT8 r = a + b + INPLOGIC(m_CI);
if (r != m_lastr)
{
m_lastr = r;
m_SA.setTo((r >> 0) & 1, NLTIME_FROM_NS(23));
m_SB.setTo((r >> 1) & 1, NLTIME_FROM_NS(23));
m_SC.setTo((r >> 2) & 1, NLTIME_FROM_NS(23));
m_SD.setTo((r >> 3) & 1, NLTIME_FROM_NS(23));
m_CO.setTo((r >> 4) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SA, (r >> 0) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SB, (r >> 1) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SC, (r >> 2) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SD, (r >> 3) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_CO, (r >> 4) & 1, NLTIME_FROM_NS(23));
}
}
@ -581,17 +571,17 @@ NETLIB_CONSTRUCTOR(nic7490)
NETLIB_UPDATE(nic7490)
{
if (INPVAL(m_R91) & INPVAL(m_R92))
if (INPLOGIC(m_R91) & INPLOGIC(m_R92))
{
m_cnt = 9;
update_outputs();
}
else if (INPVAL(m_R1) & INPVAL(m_R2))
else if (INPLOGIC(m_R1) & INPLOGIC(m_R2))
{
m_cnt = 0;
update_outputs();
}
else if (INPVAL_LAST(m_clk) & !INPVAL(m_clk))
else if (INP_HL(m_clk))
{
m_cnt++;
if (m_cnt >= 10)
@ -602,22 +592,17 @@ NETLIB_UPDATE(nic7490)
#if 0
NETLIB_FUNC_VOID(nic7490, update_outputs)
{
m_QA.setTo((m_cnt >> 0) & 1, NLTIME_FROM_NS(18));
m_QB.setTo((m_cnt >> 1) & 1, NLTIME_FROM_NS(36));
m_QC.setTo((m_cnt >> 2) & 1, NLTIME_FROM_NS(54));
m_QD.setTo((m_cnt >> 3) & 1, NLTIME_FROM_NS(72));
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, NLTIME_FROM_NS(18));
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, NLTIME_FROM_NS(36));
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, NLTIME_FROM_NS(54));
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, NLTIME_FROM_NS(72));
}
#else
NETLIB_FUNC_VOID(nic7490, update_outputs, (void))
{
const netlist_time delay[4] = { NLTIME_FROM_NS(18), NLTIME_FROM_NS(36), NLTIME_FROM_NS(54), NLTIME_FROM_NS(72) };
for (int i=0; i<4; i++)
m_Q[i].setTo((m_cnt >> i) & 1, delay[i]);
//m_QA.setToPS((m_cnt >> 0) & 1, delay[0]);
//m_QB.setToPS((m_cnt >> 1) & 1, delay[1]);
//m_QC.setToPS((m_cnt >> 2) & 1, delay[2]);
//m_QD.setToPS((m_cnt >> 3) & 1, delay[3]);
OUTLOGIC(m_Q[i], (m_cnt >> i) & 1, delay[i]);
}
#endif
#if !USE_OLD7493
@ -646,12 +631,12 @@ NETLIB_CONSTRUCTOR(nic7493)
NETLIB_UPDATE(nic7493ff)
{
if (m_reset == 0)
m_Q.setTo(!m_Q.new_Q(), NLTIME_FROM_NS(18));
OUTLOGIC(m_Q, !m_Q.new_Q(), NLTIME_FROM_NS(18));
}
NETLIB_UPDATE(nic7493)
{
net_sig_t r = INPVAL(m_R1) & INPVAL(m_R2);
net_sig_t r = INPLOGIC(m_R1) & INPLOGIC(m_R2);
if (r)
{
@ -659,10 +644,10 @@ NETLIB_UPDATE(nic7493)
A.m_reset = B.m_reset = C.m_reset = D.m_reset = 1;
A.m_I.inactivate();
B.m_I.inactivate();
A.m_Q.setTo(0, NLTIME_FROM_NS(40));
B.m_Q.setTo(0, NLTIME_FROM_NS(40));
C.m_Q.setTo(0, NLTIME_FROM_NS(40));
D.m_Q.setTo(0, NLTIME_FROM_NS(40));
OUTLOGIC(A.m_Q, 0, NLTIME_FROM_NS(40));
OUTLOGIC(B.m_Q, 0, NLTIME_FROM_NS(40));
OUTLOGIC(C.m_Q, 0, NLTIME_FROM_NS(40));
OUTLOGIC(D.m_Q, 0, NLTIME_FROM_NS(40));
}
else
{
@ -692,25 +677,25 @@ NETLIB_CONSTRUCTOR(nic7493)
NETLIB_UPDATE(nic7493)
{
//UINT8 old_clk = m_lastclk;
//m_lastclk = INPVAL(m_clk);
//m_lastclk = INPLOGIC(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 (INPLOGIC(m_R1) & INPLOGIC(m_R2))
{
if (m_cnt > 0)
{
m_cnt = 0;
m_QA.setTo(0, NLTIME_FROM_NS(40));
m_QB.setTo(0, NLTIME_FROM_NS(40));
m_QC.setTo(0, NLTIME_FROM_NS(40));
m_QD.setTo(0, NLTIME_FROM_NS(40));
OUTLOGIC(m_QA, 0, NLTIME_FROM_NS(40));
OUTLOGIC(m_QB, 0, NLTIME_FROM_NS(40));
OUTLOGIC(m_QC, 0, NLTIME_FROM_NS(40));
OUTLOGIC(m_QD, 0, NLTIME_FROM_NS(40));
}
m_CLK.inactivate();
}
//else if (old_clk & !m_lastclk)
else {
m_CLK.activate_hl();
if (INPVAL_LAST(m_CLK) & !INPVAL(m_CLK))
if (INP_HL(m_CLK))
{
m_cnt++;
m_cnt &= 0x0f;
@ -722,32 +707,32 @@ NETLIB_UPDATE(nic7493)
NETLIB_FUNC_VOID(nic7493, update_outputs, (void))
{
if (m_cnt & 1)
m_QA.setToNoCheck(1, NLTIME_FROM_NS(16));
OUTLOGIC(m_QA, 1, NLTIME_FROM_NS(16));
else
{
m_QA.setToNoCheck(0, NLTIME_FROM_NS(16));
OUTLOGIC(m_QA, 0, NLTIME_FROM_NS(16));
switch (m_cnt)
{
case 0x00:
m_QD.setToNoCheck(0, NLTIME_FROM_NS(70));
m_QC.setToNoCheck(0, NLTIME_FROM_NS(48));
m_QB.setToNoCheck(0, NLTIME_FROM_NS(34));
OUTLOGIC(m_QD, 0, NLTIME_FROM_NS(70));
OUTLOGIC(m_QC, 0, NLTIME_FROM_NS(48));
OUTLOGIC(m_QB, 0, NLTIME_FROM_NS(34));
break;
case 0x02:
case 0x06:
case 0x0A:
case 0x0E:
m_QB.setToNoCheck(1, NLTIME_FROM_NS(34));
OUTLOGIC(m_QB, 1, NLTIME_FROM_NS(34));
break;
case 0x04:
case 0x0C:
m_QC.setToNoCheck(1, NLTIME_FROM_NS(48));
m_QB.setToNoCheck(0, NLTIME_FROM_NS(34));
OUTLOGIC(m_QC, 1, NLTIME_FROM_NS(48));
OUTLOGIC(m_QB, 0, NLTIME_FROM_NS(34));
break;
case 0x08:
m_QD.setToNoCheck(1, NLTIME_FROM_NS(70));
m_QC.setToNoCheck(0, NLTIME_FROM_NS(48));
m_QB.setToNoCheck(0, NLTIME_FROM_NS(34));
OUTLOGIC(m_QD, 1, NLTIME_FROM_NS(70));
OUTLOGIC(m_QC, 0, NLTIME_FROM_NS(48));
OUTLOGIC(m_QB, 0, NLTIME_FROM_NS(34));
break;
}
}
@ -768,12 +753,12 @@ NETLIB_CONSTRUCTOR(nic74107A)
sub.m_QQ.initial(1);
}
INLINE void nic74107A_newstate(UINT8 state, ttl_output_t &Q, ttl_output_t &QQ)
ATTR_HOT inline void nic74107Asub::newstate(const net_sig_t state)
{
const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
#if 1
Q.setTo(state, delay[1-state]);
QQ.setTo(1-state, delay[state]);
OUTLOGIC(m_Q, state, delay[state ^ 1]);
OUTLOGIC(m_QQ, state ^ 1, delay[state]);
#else
if (state != Q.new_Q())
{
@ -787,7 +772,7 @@ NETLIB_UPDATE(nic74107Asub)
{
{
net_sig_t t = m_Q.new_Q();
nic74107A_newstate((!t & m_Q1) | (t & m_Q2) | m_F, m_Q, m_QQ);
newstate((!t & m_Q1) | (t & m_Q2) | m_F);
if (!m_Q1)
m_clk.inactivate();
}
@ -795,19 +780,19 @@ NETLIB_UPDATE(nic74107Asub)
NETLIB_UPDATE(nic74107A)
{
if (INPVAL(m_J) & INPVAL(m_K))
if (INPLOGIC(m_J) & INPLOGIC(m_K))
{
sub.m_Q1 = 1;
sub.m_Q2 = 0;
sub.m_F = 0;
}
else if (!INPVAL(m_J) & INPVAL(m_K))
else if (!INPLOGIC(m_J) & INPLOGIC(m_K))
{
sub.m_Q1 = 0;
sub.m_Q2 = 0;
sub.m_F = 0;
}
else if (INPVAL(m_J) & !INPVAL(m_K))
else if (INPLOGIC(m_J) & !INPLOGIC(m_K))
{
sub.m_Q1 = 0;
sub.m_Q2 = 0;
@ -820,13 +805,15 @@ NETLIB_UPDATE(nic74107A)
sub.m_F = 0;
sub.m_clk.inactivate();
}
if (!INPVAL(m_clrQ))
if (!INPLOGIC(m_clrQ))
{
sub.m_clk.inactivate();
nic74107A_newstate(0, sub.m_Q, sub.m_QQ);
sub.newstate(0);
}
if (!sub.m_Q2 && INPVAL(m_clrQ))
else if (!sub.m_Q2)
sub.m_clk.activate_hl();
//if (!sub.m_Q2 & INPLOGIC(m_clrQ))
// sub.m_clk.activate_hl();
}
NETLIB_CONSTRUCTOR(nic74153)
@ -845,15 +832,15 @@ NETLIB_CONSTRUCTOR(nic74153)
NETLIB_UPDATE(nic74153)
{
const netlist_time delay[2] = { NLTIME_FROM_NS(23), NLTIME_FROM_NS(18) };
if (!INPVAL(m_GA))
if (!INPLOGIC(m_GA))
{
UINT8 chan = (INPVAL(m_A) | (INPVAL(m_B)<<1));
UINT8 t = INPVAL(m_I[chan]);
m_AY.setTo(t, delay[t] ); /* data to y only, FIXME */
UINT8 chan = (INPLOGIC(m_A) | (INPLOGIC(m_B)<<1));
UINT8 t = INPLOGIC(m_I[chan]);
OUTLOGIC(m_AY, t, delay[t] ); /* data to y only, FIXME */
}
else
{
m_AY.setTo(0, delay[0]);
OUTLOGIC(m_AY, 0, delay[0]);
}
}
@ -893,19 +880,19 @@ NETLIB_UPDATE(nic9316_sub)
}
else
{
m_cnt = (INPVAL_PASSIVE(m_D) << 3) | (INPVAL_PASSIVE(m_C) << 2) | (INPVAL_PASSIVE(m_B) << 1) | (INPVAL_PASSIVE(m_A) << 0);
m_cnt = (INPLOGIC_PASSIVE(m_D) << 3) | (INPLOGIC_PASSIVE(m_C) << 2) | (INPLOGIC_PASSIVE(m_B) << 1) | (INPLOGIC_PASSIVE(m_A) << 0);
update_outputs_all();
}
m_RC.setTo(m_ent & (m_cnt == 0x0f), NLTIME_FROM_NS(20));
OUTLOGIC(m_RC, m_ent & (m_cnt == 0x0f), NLTIME_FROM_NS(20));
}
NETLIB_UPDATE(nic9316)
{
sub.m_loadq = INPVAL(m_LOADQ);
sub.m_ent = INPVAL(m_ENT);
const net_sig_t clrq = INPVAL(m_CLRQ);
sub.m_loadq = INPLOGIC(m_LOADQ);
sub.m_ent = INPLOGIC(m_ENT);
const net_sig_t clrq = INPLOGIC(m_CLRQ);
if ((!sub.m_loadq || (sub.m_ent & INPVAL(m_ENP))) & clrq)
if ((!sub.m_loadq || (sub.m_ent & INPLOGIC(m_ENP))) & clrq)
{
sub.m_clk.activate_lh();
}
@ -916,58 +903,58 @@ NETLIB_UPDATE(nic9316)
{
sub.m_cnt = 0;
sub.update_outputs();
sub.m_RC.setTo(0, NLTIME_FROM_NS(20));
OUTLOGIC(sub.m_RC, 0, NLTIME_FROM_NS(20));
return;
}
}
sub.m_RC.setTo(sub.m_ent & (sub.m_cnt == 0x0f), NLTIME_FROM_NS(20));
OUTLOGIC(sub.m_RC, sub.m_ent & (sub.m_cnt == 0x0f), NLTIME_FROM_NS(20));
}
NETLIB_FUNC_VOID(nic9316_sub, update_outputs_all, (void))
{
const netlist_time out_delay = NLTIME_FROM_NS(20);
m_QA.setTo((m_cnt >> 0) & 1, out_delay);
m_QB.setTo((m_cnt >> 1) & 1, out_delay);
m_QC.setTo((m_cnt >> 2) & 1, out_delay);
m_QD.setTo((m_cnt >> 3) & 1, out_delay);
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, out_delay);
}
NETLIB_FUNC_VOID(nic9316_sub, update_outputs, (void))
{
const netlist_time out_delay = NLTIME_FROM_NS(20);
#if 0
m_QA.setTo((m_cnt >> 0) & 1, out_delay);
m_QB.setTo((m_cnt >> 1) & 1, out_delay);
m_QC.setTo((m_cnt >> 2) & 1, out_delay);
m_QD.setTo((m_cnt >> 3) & 1, out_delay);
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, out_delay);
#else
if ((m_cnt & 1) == 1)
m_QA.setToNoCheck(1, out_delay);
OUTLOGIC(m_QA, 1, out_delay);
else
{
m_QA.setToNoCheck(0, out_delay);
OUTLOGIC(m_QA, 0, out_delay);
switch (m_cnt)
{
case 0x00:
m_QB.setToNoCheck(0, out_delay);
m_QC.setToNoCheck(0, out_delay);
m_QD.setToNoCheck(0, out_delay);
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 0, out_delay);
OUTLOGIC(m_QD, 0, out_delay);
break;
case 0x02:
case 0x06:
case 0x0A:
case 0x0E:
m_QB.setToNoCheck(1, out_delay);
OUTLOGIC(m_QB, 1, out_delay);
break;
case 0x04:
case 0x0C:
m_QB.setToNoCheck(0, out_delay);
m_QC.setToNoCheck(1, out_delay);
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 1, out_delay);
break;
case 0x08:
m_QB.setToNoCheck(0, out_delay);
m_QC.setToNoCheck(0, out_delay);
m_QD.setToNoCheck(1, out_delay);
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 0, out_delay);
OUTLOGIC(m_QD, 1, out_delay);
break;
}
@ -986,7 +973,7 @@ static const net_device_t_base_factory *netregistry[] =
ENTRY(netdev_log, NETDEV_LOG)
ENTRY(netdev_clock, NETDEV_CLOCK)
ENTRY(netdev_mainclock, NETDEV_MAINCLOCK)
ENTRY(netdev_callback, NETDEV_CALLBACK)
ENTRY(netdev_analog_callback,NETDEV_CALLBACK)
ENTRY(nicMultiSwitch, NETDEV_SWITCH2)
ENTRY(nicRSFF, NETDEV_RSFF)
ENTRY(nicMixer8, NETDEV_MIXER)

View File

@ -66,7 +66,7 @@
#define NETDEV_ANALOG_INPUT(_name) \
NET_REGISTER_DEV(netdev_analog_input, _name)
#define NETDEV_CALLBACK(_name, _IN) \
NET_REGISTER_DEV(netdev_callback, _name) \
NET_REGISTER_DEV(netdev_analog_callback, _name) \
NET_CONNECT(_name, IN, _IN)
#define NETDEV_SWITCH2(_name, _i1, _i2) \
NET_REGISTER_DEV(nicMultiSwitch, _name) \
@ -333,6 +333,8 @@ NETLIB_SUBDEVICE(nic7474sub,
UINT8 m_nextD;
ttl_output_t m_Q;
ttl_output_t m_QQ;
ATTR_HOT inline void newstate(const UINT8 state);
);
NETLIB_DEVICE(nic7474,
@ -357,13 +359,16 @@ NETLIB_DEVICE(nic7486,
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;
net_sig_t m_Q1;
net_sig_t m_Q2;
net_sig_t m_F;
ATTR_HOT void newstate(const net_sig_t state);
);
NETLIB_DEVICE(nic74107A,

View File

@ -78,57 +78,8 @@
#define end_timing(v) do { } while (0)
#endif
// ----------------------------------------------------------------------------------------
// netlist_timed_queue
// ----------------------------------------------------------------------------------------
ATTR_HOT ATTR_ALIGN void netlist_timed_queue::push(const entry_t &e)
{
const netlist_time &t = e.time();
/* no real speedup */
#if 0
if (is_empty() || (t <= item(m_end - 1).time()))
{
set_item(m_end, e);
m_end++;
inc_stat(m_prof_end);
}
else
#endif
{
int i = m_end;
m_end++;
while ((i>0) && (t > item(i-1).time()) )
{
set_item(i, item(i-1));
inc_stat(m_prof_sortmove);
i--;
}
set_item(i, e);
inc_stat(m_prof_sort);
}
}
const netlist_time netlist_time::zero = netlist_time::from_raw(0);
ATTR_HOT ATTR_ALIGN const net_sig_t net_core_device_t::INPVAL_PASSIVE(logic_input_t &inp)
{
net_sig_t ret;
const net_input_t::net_input_state st = inp.state();
if (st == net_input_t::INP_STATE_PASSIVE)
{
inp.activate();
ret = inp.Q();
inp.inactivate();
}
else
ret = inp.Q();
return ret;
}
// ----------------------------------------------------------------------------------------
// A netlist parser
// ----------------------------------------------------------------------------------------
@ -342,6 +293,35 @@ private:
};
// ----------------------------------------------------------------------------------------
// netlist_timed_queue
// ----------------------------------------------------------------------------------------
ATTR_HOT ATTR_ALIGN void netlist_timed_queue::push(const entry_t &e)
{
const netlist_time &t = e.time();
if (is_empty() || (t <= item(m_end - 1).time()))
{
set_item(m_end, e);
m_end++;
inc_stat(m_prof_end);
}
else
{
int i = m_end;
m_end++;
while ((i>0) && (t > item(i-1).time()) )
{
set_item(i, item(i-1));
inc_stat(m_prof_sortmove);
i--;
}
set_item(i, e);
inc_stat(m_prof_sort);
}
}
// ----------------------------------------------------------------------------------------
// netdev_a_to_d
// ----------------------------------------------------------------------------------------
@ -355,24 +335,55 @@ public:
assert(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
m_I.m_high_thresh_V = in_proxied.m_high_thresh_V;
m_I.m_low_thresh_V = in_proxied.m_low_thresh_V;
m_I.init(this);
m_I.init_input(this);
m_Q.set_netdev(this);
m_Q.init_terminal(this);
m_Q.initial(1);
}
ATTR_HOT ATTR_ALIGN void update()
{
if (m_I.Q_Analog() > m_I.m_high_thresh_V)
m_Q.setTo(1, NLTIME_FROM_NS(1));
OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1));
else if (m_I.Q_Analog() < m_I.m_low_thresh_V)
m_Q.setTo(0, NLTIME_FROM_NS(1));
OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1));
}
analog_input_t m_I;
ttl_output_t m_Q;
};
// ----------------------------------------------------------------------------------------
// netdev_d_to_a
// ----------------------------------------------------------------------------------------
class netdev_d_to_a_proxy : public net_device_t
{
public:
netdev_d_to_a_proxy(netlist_setup_t &setup, const char *name, net_output_t &out_proxied)
: net_device_t(setup, name)
{
m_low_V = out_proxied.m_low_V;
m_high_V = out_proxied.m_high_V;
assert(out_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
m_I.init_input(this);
m_Q.init_terminal(this);
m_Q.initial(0);
}
ATTR_HOT ATTR_ALIGN void update()
{
OUTANALOG(m_Q, INPLOGIC(m_I) ? m_high_V : m_low_V, NLTIME_FROM_NS(1));
}
ttl_input_t m_I;
analog_output_t m_Q;
private:
double m_low_V;
double m_high_V;
};
// ----------------------------------------------------------------------------------------
// netdev_const
// ----------------------------------------------------------------------------------------
@ -389,7 +400,7 @@ NETLIB_UPDATE(netdev_ttl_const)
NETLIB_UPDATE_PARAM(netdev_ttl_const)
{
m_Q.setTo(m_const.ValueInt(), NLTIME_IMMEDIATE);
OUTLOGIC(m_Q, m_const.ValueInt(), NLTIME_IMMEDIATE);
}
NETLIB_CONSTRUCTOR(netdev_analog_const)
@ -412,6 +423,13 @@ NETLIB_UPDATE_PARAM(netdev_analog_const)
// ----------------------------------------------------------------------------------------
NETLIB_UPDATE(netdev_analog_callback)
{
// FIXME: Remove after device cleanup
if (!m_callback.isnull())
m_callback(INPANALOG(m_in));
}
netlist_base_t::netlist_base_t()
: m_mainclock(NULL),
m_time_ps(NLTIME_FROM_MS(0)),
@ -478,17 +496,16 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_list(INT32 &atime)
atime = 0;
}
} else {
net_output_t &mainclock_Q = m_mainclock->m_Q;
while (atime > 0)
{
if (m_queue.is_not_empty())
{
while (m_queue.peek().time() > mainclock_Q.time())
while (m_queue.peek().time() > m_mainclock->m_Q.time())
{
update_time(mainclock_Q.time(), atime);
update_time(m_mainclock->m_Q.time(), atime);
m_mainclock->update();
mainclock_Q.update_devs();
m_mainclock->m_Q.update_devs();
}
const queue_t::entry_t &e = m_queue.pop();
@ -498,10 +515,10 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_list(INT32 &atime)
e.object().update_devs();
} else {
update_time(mainclock_Q.time(), atime);
update_time(m_mainclock->m_Q.time(), atime);
m_mainclock->update();
mainclock_Q.update_devs();
m_mainclock->m_Q.update_devs();
}
if (FATAL_ERROR_AFTER_NS)
if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS))
@ -516,8 +533,6 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_list(INT32 &atime)
atime = 0;
}
}
//if (KEEP_STATISTICS)
// printf("%d\n", m_perf_out_processed);
}
// ----------------------------------------------------------------------------------------
@ -582,8 +597,8 @@ void netlist_setup_t::remove_dev(const char *name)
temp.cat(".");
remove_start_with<tagmap_input_t>(m_inputs, temp);
remove_start_with<tagmap_output_t>(m_outputs, temp);
//remove_start_with<tagmap_input_t>(m_inputs, temp);
remove_start_with<tagmap_terminal_t>(m_terminals, temp);
remove_start_with<tagmap_param_t>(m_params, temp);
remove_start_with<tagmap_astring_t>(m_links, temp);
m_devices.remove(name);
@ -591,7 +606,7 @@ void netlist_setup_t::remove_dev(const char *name)
void netlist_setup_t::register_callback(const char *devname, net_output_delegate delegate)
{
netdev_callback *dev = (netdev_callback *) m_devices.find(devname);
netdev_analog_callback *dev = (netdev_analog_callback *) m_devices.find(devname);
if (dev == NULL)
fatalerror("did not find device %s\n", devname);
dev->register_callback(delegate);
@ -609,8 +624,8 @@ void netlist_setup_t::register_output(net_core_device_t &dev, net_core_device_t
astring temp = dev.name();
temp.cat(".");
temp.cat(name);
out.set_netdev(&upd_dev);
if (!(m_outputs.add(temp, &out, false)==TMERR_NONE))
out.init_terminal(&upd_dev);
if (!(m_terminals.add(temp, &out, false)==TMERR_NONE))
fatalerror("Error adding output %s to output list\n", name);
}
@ -620,9 +635,9 @@ void netlist_setup_t::register_input(net_device_t &dev, net_core_device_t &upd_d
astring temp = dev.name();
temp.cat(".");
temp.cat(name);
inp.init(&upd_dev, type);
inp.init_input(&upd_dev, type);
dev.m_inputs.add(core_strdup(temp.cstr()));
if (!(m_inputs.add(temp, &inp, false) == TMERR_NONE))
if (!(m_terminals.add(temp, &inp, false) == TMERR_NONE))
fatalerror("Error adding input %s to input list\n", name);
}
@ -654,9 +669,8 @@ const char *netlist_setup_t::resolve_alias(const char *name) const
net_output_t *netlist_setup_t::find_output_exact(const char *outname_in)
{
net_output_t *ret = m_outputs.find(outname_in);
return ret;
net_terminal_t *term = m_terminals.find(outname_in);
return dynamic_cast<net_output_t *>(term);
}
net_output_t &netlist_setup_t::find_output(const char *outname_in)
@ -698,7 +712,7 @@ void netlist_setup_t::resolve_inputs(void)
{
const astring *sout = entry->object();
astring sin = entry->tag();
net_input_t *in = m_inputs.find(sin);
net_input_t *in = dynamic_cast<net_input_t *>(m_terminals.find(sin));
if (in == NULL)
fatalerror("Unable to find %s\n", sin.cstr());
@ -707,26 +721,33 @@ void netlist_setup_t::resolve_inputs(void)
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(*this, "abc", *in);
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);
in->set_output(proxy->m_Q);
proxy->m_Q.register_con(*in);
proxy->m_I.set_output(out);
out.register_con(proxy->m_I);
}
else if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL
&& in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG)
{
//printf("here 1\n");
netdev_d_to_a_proxy *proxy = new netdev_d_to_a_proxy(*this, "abc", out);
in->set_output(proxy->m_Q);
proxy->m_Q.register_con(*in);
proxy->m_I.set_output(out);
out.register_con(proxy->m_I);
//printf("here 2\n");
}
else
{
in->set_output(out.netdev()->GETINPPTR(out));
//Next check would not work with dynamic activation
//if (in->state() != net_input_t::INP_STATE_PASSIVE)
out.register_con(*in);
in->set_output(out);
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))
{
@ -747,12 +768,8 @@ void netlist_setup_t::resolve_inputs(void)
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
{
net_device_t *dev = entry->object();
dev->update_device();
//INT32 time = 10000;
//m_netlist.process_list(time);
dev->update();
}
//m_netlist.m_queue.clear();
#else
/* make sure all outputs are triggered once */
@ -770,10 +787,11 @@ void netlist_setup_t::resolve_inputs(void)
#endif
/* print all outputs */
for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
for (tagmap_terminal_t::entry_t *entry = m_terminals.first(); entry != NULL; entry = m_terminals.next(entry))
{
ATTR_UNUSED net_output_t *out = entry->object();
VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
ATTR_UNUSED net_output_t *out = dynamic_cast<net_output_t *>(entry->object());
if (out != NULL)
VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
}
@ -821,6 +839,20 @@ net_core_device_t::~net_core_device_t()
// net_device_t
// ----------------------------------------------------------------------------------------
ATTR_HOT ATTR_ALIGN const net_sig_t net_core_device_t::INPLOGIC_PASSIVE(logic_input_t &inp)
{
net_sig_t ret;
if (inp.state() == net_input_t::INP_STATE_PASSIVE)
{
inp.activate();
ret = inp.Q();
inp.inactivate();
}
else
ret = inp.Q();
return ret;
}
net_device_t::net_device_t(netlist_setup_t &setup, const char *name)
: net_core_device_t(setup, name),
@ -855,8 +887,8 @@ void net_device_t::register_input(const char *name, net_input_t &inp, net_input_
void net_device_t::register_link_internal(net_core_device_t &dev, net_input_t &in, net_output_t &out, net_input_t::net_input_state aState)
{
in.set_output(GETINPPTR(out));
in.init(&dev, aState);
in.set_output(out);
in.init_input(&dev, aState);
//if (in.state() != net_input_t::INP_STATE_PASSIVE)
out.register_con(in);
}
@ -878,13 +910,23 @@ void net_device_t::register_param(const char *name, net_param_t &param, double i
register_param(*this,name, param, initialVal);
}
// ----------------------------------------------------------------------------------------
// net_terminal_t
// ----------------------------------------------------------------------------------------
ATTR_COLD void net_terminal_t::init_terminal(net_core_device_t *dev)
{
m_netdev = dev;
m_netlist = &dev->netlist();
}
// ----------------------------------------------------------------------------------------
// net_input_t
// ----------------------------------------------------------------------------------------
ATTR_COLD void net_input_t::init(net_core_device_t *dev, net_input_state astate)
ATTR_COLD void net_input_t::init_input(net_core_device_t *dev, net_input_state astate)
{
m_netdev = dev;
init_terminal(dev);
m_state = astate;
#if USE_DELEGATES
h = net_update_delegate(&net_core_device_t::update, "update", dev);
@ -896,7 +938,7 @@ ATTR_COLD void net_input_t::init(net_core_device_t *dev, net_input_state astate)
// ----------------------------------------------------------------------------------------
net_output_t::net_output_t(int atype)
: net_object_t(atype)
: net_terminal_t(atype)
{
m_last_Q = 0;
m_Q = 0;
@ -906,23 +948,18 @@ net_output_t::net_output_t(int atype)
m_num_cons = 0;
m_Q_analog = 0.0;
m_new_Q_analog = 0.0;
//m_cons = global_alloc_array(net_input_t *, OUTPUT_MAX_CONNECTIONS);
}
ATTR_COLD void net_output_t::set_netdev(net_core_device_t *dev)
ATTR_HOT inline void net_output_t::update_dev(const net_input_t *inp, const UINT32 mask)
{
m_netdev = dev;
m_netlist = &dev->netlist();
}
ATTR_HOT ATTR_ALIGN inline void net_output_t::update_dev(const net_input_t &inp, const UINT8 mask)
{
if (((inp.state() & mask) != 0))
if ((inp->state() & mask) != 0)
{
ATTR_UNUSED net_core_device_t *netdev = inp.netdev();
ATTR_UNUSED net_core_device_t *netdev = inp->netdev();
begin_timing(netdev->total_time);
inc_stat(netdev->stat_count);
#if USE_DELEGATES
inp.h();
inp->h();
#else
netdev->update();
#endif
@ -930,45 +967,41 @@ ATTR_HOT ATTR_ALIGN inline void net_output_t::update_dev(const net_input_t &inp,
}
}
ATTR_HOT ATTR_ALIGN inline void net_output_t::update_devs()
ATTR_HOT inline void net_output_t::update_devs()
{
assert(m_num_cons != 0);
const UINT8 masks[4] = { 1, 5, 3, 1 };
const UINT32 masks[4] = { 1, 5, 3, 1 };
m_Q = m_new_Q;
m_Q_analog = m_new_Q_analog;
m_in_queue = 2; /* mark as taken ... */
//if (m_last_Q == m_Q)
//printf("%s\n", m_netdev->name());
//UINT32 mask = 1 | ((m_last_Q & (m_Q ^ 1)) << 1) | (((m_last_Q ^ 1) & m_Q) << 2);
const UINT8 mask = masks[ (m_last_Q << 1) | m_Q ];
const UINT32 mask = masks[ (m_last_Q << 1) | m_Q ];
switch (m_num_cons)
{
case 2:
update_dev(*m_cons[1], mask);
update_dev(m_cons[1], mask);
case 1:
update_dev(*m_cons[0], mask);
update_dev(m_cons[0], mask);
break;
default:
{
for (int i=0; i < m_num_cons; i++)
update_dev(*m_cons[i], mask);
update_dev(m_cons[i], mask);
}
break;
}
m_last_Q = m_Q;
}
ATTR_COLD void net_output_t::register_con(net_input_t &input)
{
int i;
if (m_num_cons >= ARRAY_LENGTH(m_cons))
fatalerror("Connections exceeded for %s\n", m_netdev->name());
if (m_num_cons >= OUTPUT_MAX_CONNECTIONS)
fatalerror("Connections exceeded for %s\n", netdev()->name());
/* keep similar devices together */
for (i = 0; i < m_num_cons; i++)
@ -984,19 +1017,10 @@ ATTR_COLD void net_output_t::register_con(net_input_t &input)
m_active++;
}
NETLIB_UPDATE(netdev_callback)
{
// FIXME: Remove after device cleanup
if (!m_callback.isnull())
m_callback(INPANALOG(m_in));
}
// ----------------------------------------------------------------------------------------
// netlist_mame_device
// ----------------------------------------------------------------------------------------
const device_type NETLIST = &device_creator<netlist_mame_device>;
netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
@ -1065,11 +1089,13 @@ void netlist_mame_device::device_timer(emu_timer &timer, device_timer_id id, int
void netlist_mame_device::save_state()
{
#if 0
for (netlist_setup_t::tagmap_output_t::entry_t *entry = m_setup->m_outputs.first(); entry != NULL; entry = m_setup->m_outputs.next(entry))
{
save_item(*entry->object()->Q_ptr(), entry->tag().cstr(), 0);
save_item(*entry->object()->new_Q_ptr(), entry->tag().cstr(), 1);
}
#endif
}
UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const

View File

@ -60,6 +60,8 @@
// Next if enabled adds 20% performance ... but is not guaranteed to be absolutely timing correct.
#define USE_DEACTIVE_DEVICE (0)
#define OUTPUT_MAX_CONNECTIONS (48)
// Use nano-second resolution - Sufficient for now
//#define NETLIST_INTERNAL_RES (U64(1000000000))
//#define NETLIST_DIV_BITS (0)
@ -194,6 +196,7 @@ typedef delegate<void ()> net_update_delegate;
typedef UINT8 net_sig_t;
typedef delegate<void (const double)> net_output_delegate;
// ----------------------------------------------------------------------------------------
@ -327,16 +330,18 @@ public:
static const int SIZE = ((1 << 11) - 1);
typedef net_output_t element_t;
struct entry_t
{
public:
inline entry_t() {}
inline entry_t(const netlist_time atime, net_output_t &elem) : m_time(atime), m_object(&elem) {}
inline entry_t(const netlist_time atime, element_t &elem) : m_time(atime), m_object(&elem) {}
ATTR_HOT inline const netlist_time &time() const { return m_time; }
ATTR_HOT inline net_output_t & object() const { return *m_object; }
ATTR_HOT inline element_t & object() const { return *m_object; }
private:
netlist_time m_time;
net_output_t *m_object;
element_t *m_object;
};
netlist_timed_queue()
@ -344,8 +349,8 @@ public:
clear();
}
ATTR_HOT inline bool is_empty() { return (m_end == 0); }
ATTR_HOT inline bool is_not_empty() { return (m_end != 0); }
ATTR_HOT inline bool is_empty() const { return (m_end == 0); }
ATTR_HOT inline bool is_not_empty() const { return (m_end != 0); }
ATTR_HOT ATTR_ALIGN void push(const entry_t &e);
@ -391,7 +396,10 @@ public:
OUTPUT = 1,
DEVICE = 2,
PARAM = 3,
TYPE_MASK = 0x03,
TERMINAL = 4,
NET_ANALOG = 5,
NET_DIGITAL = 6,
TYPE_MASK = 0x0f,
SIGNAL_DIGITAL = 0x00,
SIGNAL_ANALOG = 0x10,
SIGNAL_MASK = 0x10,
@ -400,6 +408,8 @@ public:
net_object_t(int atype)
: m_objtype(atype) {}
virtual ~net_object_t() {}
ATTR_HOT inline int object_type() const { return m_objtype; }
ATTR_HOT inline int object_type(const UINT32 mask) const { return m_objtype & mask; }
@ -407,13 +417,31 @@ private:
int m_objtype;
};
// ----------------------------------------------------------------------------------------
// net_terminal_t
// ----------------------------------------------------------------------------------------
class net_terminal_t : public net_object_t
{
public:
net_terminal_t(const int atype) : net_object_t(atype) {}
ATTR_COLD void init_terminal(net_core_device_t *dev);
ATTR_HOT inline net_core_device_t * RESTRICT netdev() const { return m_netdev; }
ATTR_HOT inline netlist_base_t * RESTRICT netlist() const { return m_netlist; }
private:
net_core_device_t * RESTRICT m_netdev;
netlist_base_t * RESTRICT m_netlist;
};
// ----------------------------------------------------------------------------------------
// net_input_t
// ----------------------------------------------------------------------------------------
class net_input_t : public net_object_t
class net_input_t : public net_terminal_t
{
public:
@ -424,21 +452,23 @@ public:
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, net_input_state astate = INP_STATE_ACTIVE);
ATTR_COLD net_input_t(const int atype)
: net_terminal_t(atype)
, m_state(INP_STATE_ACTIVE)
{}
ATTR_COLD void init_input(net_core_device_t *dev, net_input_state astate = INP_STATE_ACTIVE);
ATTR_HOT inline net_output_t * RESTRICT output() const { return m_output; }
ATTR_HOT inline const bool is_state(const net_input_state astate) { return (m_state == astate); }
ATTR_HOT inline const bool is_state(const net_input_state astate) const { return (m_state == astate); }
ATTR_HOT inline const net_input_state state() const { return m_state; }
ATTR_COLD void set_output(net_output_t *aout) { m_output = aout; }
ATTR_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;
@ -448,7 +478,6 @@ public:
private:
net_input_state m_state;
net_core_device_t * RESTRICT m_netdev;
net_output_t * RESTRICT m_output;
};
@ -492,46 +521,33 @@ public:
//#define INPVAL(_x) (_x).Q()
// ----------------------------------------------------------------------------------------
// net_output_t
// ----------------------------------------------------------------------------------------
class net_output_t : public net_object_t
class netdev_mainclock;
class net_output_t : public net_terminal_t
{
public:
net_output_t(int atype);
friend const net_sig_t logic_input_t::Q() const;
friend const double analog_input_t::Q_Analog() const;
friend const bool analog_input_t::is_highz() const;
friend class netdev_mainclock;
ATTR_HOT inline const net_sig_t last_Q() const { return m_last_Q; }
ATTR_HOT inline const net_sig_t new_Q() const { return m_new_Q; }
ATTR_HOT inline const double Q_Analog() const
{
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); break;
}
return 0;
}
inline net_sig_t *Q_ptr() { return &m_Q; }
inline net_sig_t *new_Q_ptr() { return &m_new_Q; }
//ATTR_HOT inline net_sig_t *Q_ptr() { return &m_Q; }
//ATTR_HOT inline net_sig_t *new_Q_ptr() { return &m_new_Q; }
ATTR_COLD void register_con(net_input_t &inp);
ATTR_HOT void update_dev(const net_input_t &inp, const UINT8 mask);
ATTR_HOT void update_devs();
ATTR_HOT inline const net_core_device_t *netdev() const { return m_netdev; }
ATTR_HOT inline void inc_active();
ATTR_HOT inline void dec_active();
@ -539,66 +555,48 @@ public:
ATTR_HOT inline const netlist_time time() const { return m_time; }
ATTR_HOT inline void set_time(const netlist_time ntime) { m_time = ntime; }
ATTR_COLD void set_netdev(net_core_device_t *dev);
double m_low_V;
double m_high_V;
protected:
/* prohibit use in device functions
* current (pending) state can be inquired using new_Q()
*/
ATTR_HOT inline const net_sig_t Q() const { return m_Q; }
ATTR_HOT inline const net_sig_t Q() const
{
assert(object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
return m_Q;
}
ATTR_HOT inline const double Q_Analog() const
{
assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG);
return m_Q_analog;
}
ATTR_HOT inline void push_to_queue(const netlist_time &delay);
ATTR_HOT inline void set_Q(const net_sig_t newQ, const netlist_time &delay)
{
if (newQ != m_new_Q)
{
m_new_Q = newQ;
push_to_queue(delay);
}
}
ATTR_HOT inline void set_Q_NoCheck(const net_sig_t val, const netlist_time &delay)
{
m_new_Q = val;
push_to_queue(delay);
}
ATTR_HOT inline void set_Q_Analog(const double newQ, const netlist_time &delay)
{
if (newQ != m_new_Q_analog)
{
m_new_Q_analog = newQ;
push_to_queue(delay);
}
}
ATTR_HOT inline void set_Q_NoCheck_Analog(const double val, const netlist_time &delay)
{
m_new_Q_analog = val;
push_to_queue(delay);
}
netlist_time m_time;
UINT8 m_in_queue;
int m_active;
net_sig_t m_last_Q;
net_sig_t m_Q;
net_sig_t m_new_Q;
double m_Q_analog;
double m_new_Q_analog;
int m_num_cons;
private:
ATTR_HOT void update_dev(const net_input_t *inp, const UINT32 mask);
net_input_t *m_cons[48];
netlist_time m_time;
double m_low_V;
double m_high_V;
INT32 m_active;
net_core_device_t *m_netdev;
netlist_base_t *m_netlist;
UINT32 m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */
UINT32 m_num_cons;
net_input_t *m_cons[OUTPUT_MAX_CONNECTIONS];
};
class logic_output_t : public net_output_t
{
public:
@ -612,10 +610,16 @@ public:
}
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(0, netlist_time::zero); }
ATTR_HOT inline void set() { set_Q(1, netlist_time::zero); }
ATTR_HOT inline void setTo(const UINT8 val, const netlist_time &delay) { set_Q(val, delay); }
ATTR_HOT inline void setToNoCheck(const UINT8 val, const netlist_time &delay) { set_Q_NoCheck(val, delay); }
ATTR_HOT inline void set_Q(const net_sig_t newQ, const netlist_time &delay)
{
if (EXPECTED(newQ != m_new_Q))
{
m_new_Q = newQ;
push_to_queue(delay);
}
}
ATTR_COLD inline void set_levels(const double low, const double high)
{
m_low_V = low;
@ -640,9 +644,17 @@ 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 setTo(const double val, const netlist_time &delay) { set_Q_Analog(val,delay); }
ATTR_HOT inline void setToNoCheckPS(const double val, const netlist_time &delay) { set_Q_NoCheck_Analog(val,delay); }
ATTR_COLD void initial(const double val) { m_Q_analog = val; m_new_Q_analog = val; }
ATTR_HOT inline void set_Q(const double newQ, const netlist_time &delay)
{
if (newQ != m_new_Q_analog)
{
m_new_Q_analog = newQ;
push_to_queue(delay);
}
}
};
// ----------------------------------------------------------------------------------------
@ -659,35 +671,49 @@ public:
ATTR_COLD const char *name() const { return m_name; }
ATTR_HOT inline void update_device() { update(); }
ATTR_HOT virtual void update_param() {}
ATTR_HOT virtual void update() { }
ATTR_HOT const net_sig_t INPVAL_PASSIVE(logic_input_t &inp);
ATTR_HOT const net_sig_t INPLOGIC_PASSIVE(logic_input_t &inp);
ATTR_HOT inline const net_sig_t INPVAL(const logic_input_t &inp)
ATTR_HOT inline const net_sig_t INPLOGIC(const logic_input_t &inp) const
{
assert(inp.state() != net_input_t::INP_STATE_PASSIVE);
return inp.Q();
}
ATTR_HOT inline const net_sig_t INPVAL_LAST(const logic_input_t &inp) { return inp.last_Q(); }
ATTR_HOT inline void OUTLOGIC(logic_output_t &out, const net_sig_t val, const netlist_time &delay)
{
out.set_Q(val, delay);
}
ATTR_HOT inline const double INPANALOG(const analog_input_t &inp) { return inp.Q_Analog(); }
ATTR_HOT inline bool INP_HL(const logic_input_t &inp) const
{
return ((inp.last_Q() & !inp.Q()) == 1);
}
ATTR_HOT inline bool INP_LH(const logic_input_t &inp) const
{
return ((!inp.last_Q() & inp.Q()) == 1);
}
ATTR_HOT inline const double INPANALOG(const analog_input_t &inp) const { return inp.Q_Analog(); }
ATTR_HOT inline void OUTANALOG(analog_output_t &out, const double val, const netlist_time &delay)
{
out.set_Q(val, delay);
}
ATTR_HOT inline netlist_base_t &netlist() const { return m_netlist; }
ATTR_COLD inline net_output_t * GETINPPTR(net_output_t &out) const { return &out; }
ATTR_HOT virtual void inc_active() { }
ATTR_HOT virtual void dec_active() { /*printf("DeActivate %s\n", m_name);*/ }
/* stats */
osd_ticks_t total_time;
volatile INT32 stat_count;
INT32 stat_count;
protected:
@ -855,9 +881,9 @@ public:
for (int i = 0; i< _numdev; i++)
{
this->m_i[i].activate();
if (INPVAL(this->m_i[i]) == _check)
if (INPLOGIC(this->m_i[i]) == _check)
{
this->m_Q.setTo(_check ^ (1 ^ _invert), times[_check]);// ? 15000 : 22000);
OUTLOGIC(this->m_Q, _check ^ (1 ^ _invert), times[_check]);// ? 15000 : 22000);
pos = i;
break;
}
@ -868,7 +894,7 @@ public:
if (i != pos)
this->m_i[i].inactivate();
} else
this->m_Q.setTo(_check ^ (_invert), times[1-_check]);// ? 22000 : 15000);
OUTLOGIC(this->m_Q,_check ^ (_invert), times[1-_check]);// ? 22000 : 15000);
}
public:
@ -923,10 +949,10 @@ public:
UINT8 res = _invert ^ 1 ^_check;
m_i[0].activate();
if (INPVAL(m_i[0]) ^ _check)
if (INPLOGIC(m_i[0]) ^ _check)
{
m_i[1].activate();
if (INPVAL(m_i[1]) ^ _check)
if (INPLOGIC(m_i[1]) ^ _check)
{
res = _invert ^ _check;
}
@ -934,10 +960,10 @@ public:
m_i[0].inactivate();
} else {
m_i[1].activate();
if (INPVAL(m_i[1]) ^ _check)
if (INPLOGIC(m_i[1]) ^ _check)
m_i[1].inactivate();
}
m_Q.setTo(res, times[1 - res]);// ? 22000 : 15000);
OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
}
public:
@ -975,13 +1001,13 @@ public:
UINT8 res = _invert ^ 1 ^_check;
m_i[0].activate();
if (INPVAL(m_i[0]) ^ _check)
if (INPLOGIC(m_i[0]) ^ _check)
{
m_i[1].activate();
if (INPVAL(m_i[1]) ^ _check)
if (INPLOGIC(m_i[1]) ^ _check)
{
m_i[2].activate();
if (INPVAL(m_i[2]) ^ _check)
if (INPLOGIC(m_i[2]) ^ _check)
{
res = _invert ^ _check;
}
@ -990,12 +1016,12 @@ public:
}
else
{
if (INPVAL(m_i[2]) ^ _check)
if (INPLOGIC(m_i[2]) ^ _check)
m_i[2].inactivate();
m_i[0].inactivate();
}
} else {
if (INPVAL(m_i[1]) ^ _check)
if (INPLOGIC(m_i[1]) ^ _check)
m_i[1].inactivate();
}
m_Q.setTo(res, times[1 - res]);// ? 22000 : 15000);
@ -1015,9 +1041,11 @@ public:
typedef tagmap_t<net_device_t *, 393> tagmap_devices_t;
typedef tagmap_t<astring *, 393> tagmap_astring_t;
typedef tagmap_t<net_output_t *, 393> tagmap_output_t;
typedef tagmap_t<net_input_t *, 393> tagmap_input_t;
typedef tagmap_t<net_param_t *, 393> tagmap_param_t;
typedef tagmap_t<net_terminal_t *, 393> tagmap_terminal_t;
//typedef tagmap_t<net_output_t *, 393> tagmap_output_t;
//typedef tagmap_t<net_input_t *, 393> tagmap_input_t;
netlist_setup_t(netlist_base_t &netlist);
~netlist_setup_t();
@ -1044,7 +1072,7 @@ public:
void resolve_inputs(void);
/* not ideal, but needed for save_state */
tagmap_output_t m_outputs;
tagmap_terminal_t m_terminals;
void print_stats();
@ -1056,7 +1084,7 @@ private:
tagmap_devices_t m_devices;
tagmap_astring_t m_alias;
tagmap_input_t m_inputs;
//tagmap_input_t m_inputs;
tagmap_param_t m_params;
tagmap_astring_t m_links;
@ -1088,7 +1116,7 @@ public:
ATTR_HOT void process_list(INT32 &atime);
ATTR_HOT inline const netlist_time &time() { return m_time_ps; }
ATTR_HOT inline const netlist_time &time() const { return m_time_ps; }
ATTR_COLD void set_mainclock_dev(netdev_mainclock *dev) { m_mainclock = dev; }
@ -1133,14 +1161,25 @@ inline NETLIB_CONSTRUCTOR(netdev_mainclock)
}
inline NETLIB_UPDATE_PARAM(netdev_mainclock)
{
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
inline NETLIB_UPDATE(netdev_mainclock)
{
m_Q.m_new_Q = !m_Q.m_new_Q;
m_Q.set_time(m_netlist.time() + m_inc);
}
// ----------------------------------------------------------------------------------------
// netdev_callback
// ----------------------------------------------------------------------------------------
class netdev_callback : public net_device_t
class netdev_analog_callback : public net_device_t
{
public:
netdev_callback(netlist_setup_t &setup, const char *name)
netdev_analog_callback(netlist_setup_t &setup, const char *name)
: net_device_t(setup, name)
{
register_input("IN", m_in);
@ -1223,12 +1262,12 @@ ATTR_HOT inline void net_input_t::activate_lh()
ATTR_HOT inline void net_output_t::push_to_queue(const netlist_time &delay)
{
m_time = m_netlist->time() + delay;
m_in_queue = 0; /* not queued */
if (m_active > 0)
m_time = netlist()->time() + delay;
m_in_queue = (m_active > 0) ? 1 : 0; /* queued ? */
if (m_in_queue)
{
m_in_queue = 1; /* pending */
m_netlist->push_to_queue(*this, m_time);
//m_in_queue = 1; /* pending */
netlist()->push_to_queue(*this, m_time);
}
}
@ -1240,17 +1279,17 @@ ATTR_HOT inline void net_output_t::inc_active()
if (m_active == 1 && m_in_queue > 0)
{
m_last_Q = m_Q;
m_netdev->inc_active();
netdev()->inc_active();
m_Q = m_new_Q;
}
#endif
if (m_active == 1 && m_in_queue == 0)
if (EXPECTED(m_active == 1 && m_in_queue == 0))
{
if (m_time > m_netlist->time())
if (EXPECTED(m_time > netlist()->time()))
{
m_in_queue = 1; /* pending */
m_netlist->push_to_queue(*this, m_time);
netlist()->push_to_queue(*this, m_time);
}
else
{
@ -1266,17 +1305,32 @@ ATTR_HOT inline void net_output_t::dec_active()
m_active--;
#if (USE_DEACTIVE_DEVICE)
if (m_active == 0)
m_netdev->dec_active();
netdev()->dec_active();
#endif
}
ATTR_HOT inline const net_sig_t logic_input_t::Q() const { return output()->Q(); }
ATTR_HOT inline const net_sig_t logic_input_t::last_Q() const { return output()->last_Q(); }
ATTR_HOT inline const double analog_input_t::Q_Analog() const { return output()->Q_Analog(); }
ATTR_HOT inline const bool analog_input_t::is_highz() const { return output()->Q_Analog() == NETLIST_HIGHIMP_V; }
ATTR_HOT inline const net_sig_t logic_input_t::Q() const
{
return output()->Q();
}
ATTR_HOT inline const net_sig_t logic_input_t::last_Q() const
{
return output()->last_Q();
}
ATTR_HOT inline const double analog_input_t::Q_Analog() const
{
return output()->Q_Analog();
}
ATTR_HOT inline const bool analog_input_t::is_highz() const
{
return output()->Q_Analog() == NETLIST_HIGHIMP_V;
}
// ----------------------------------------------------------------------------------------
// net_dev class factory
@ -1488,6 +1542,7 @@ public:
}
};
// device type definition
extern const device_type NETLIST;

View File

@ -96,7 +96,7 @@ static NETLIST_START(pong_schematics)
TTL_74107(ic_f6a, xclk, high, high, high)
NET_ALIAS(clk, ic_f6a.Q)
#else
/* abstracting this, performance increases by 80%
/* abstracting this, performance increases by 40%
* No surprise, the clock is extremely expensive */
NETDEV_MAINCLOCK(clk)
//NETDEV_CLOCK(clk)
@ -593,10 +593,10 @@ 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, NLTIME_FROM_NS(0)); break;
case IC_PADDLE2: m_p_V1->setTo(pad, NLTIME_FROM_NS(0)); break;
case IC_PADDLE1: m_p_V0->set_Q(pad, NLTIME_FROM_NS(0)); break;
case IC_PADDLE2: m_p_V1->set_Q(pad, NLTIME_FROM_NS(0)); break;
}
printf("%d %f\n", newval, (float) pad);
//printf("%d %f\n", newval, (float) pad);
break;
}
case IC_SWITCH:
@ -604,7 +604,7 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
m_sw1b->setTo(newval ? 1 : 0);
break;
case IC_COIN:
m_srst->setTo(newval & 1, NLTIME_FROM_US(500));
m_srst->set_Q(newval & 1, NLTIME_FROM_US(500));
break;
case IC_VR1:
case IC_VR2: