More cleanup and some development:

- removed dead code from nld_signal.h
- removed m_last_Q and all callers; if a device depends on state let it maintain it.
- added development on a generic device based on truthtables.
This commit is contained in:
Couriersud 2014-06-20 18:16:40 +00:00
parent e4bbf24a5e
commit a3799cacd8
12 changed files with 246 additions and 175 deletions

1
.gitattributes vendored
View File

@ -2996,6 +2996,7 @@ src/emu/netlist/devices/nld_ne555.h svneol=native#text/plain
src/emu/netlist/devices/nld_signal.h svneol=native#text/plain
src/emu/netlist/devices/nld_system.c svneol=native#text/plain
src/emu/netlist/devices/nld_system.h svneol=native#text/plain
src/emu/netlist/devices/nld_truthtable.h svneol=native#text/plain
src/emu/netlist/netlist.mak svneol=native#text/plain
src/emu/netlist/nl_base.c svneol=native#text/plain
src/emu/netlist/nl_base.h svneol=native#text/plain

View File

@ -5,6 +5,10 @@
#include "nld_7400.h"
#if 0
UINT32 nld_7400::m_outs[m_size];
#endif
NETLIB_START(7400_dip)
{
register_sub(m_1, "1");

View File

@ -39,7 +39,33 @@
NET_CONNECT(_name, A, _A) \
NET_CONNECT(_name, B, _B)
#if 1
NETLIB_SIGNAL(7400, 2, 0, 0);
#else
#include "nld_truthtable.h"
class nld_7400 : public nld_truthtable_t<2,1>
{
public:
nld_7400 ()
: nld_truthtable_t<2,1>()
{
}
void start()
{
static const char *tt[] = {
"A,B,PQ,PA,PB|Q",
"0,X,X,X,X|1",
"X,0,X,X,X|1",
"1,1,X,X,X|0",
""
};
setup_tt(tt, m_outs);
}
private:
static UINT32 m_outs[m_size];
};
#endif
#define TTL_7400_DIP(_name) \
NET_REGISTER_DEV(7400_dip, _name)

View File

@ -20,6 +20,8 @@ NETLIB_START(7490)
register_output("QD", m_Q[3]);
save(NAME(m_cnt));
save(NAME(m_last_A));
save(NAME(m_last_B));
}
@ -47,18 +49,20 @@ NETLIB_UPDATE(7490)
m_cnt = 0;
update_outputs();
}
else if (INP_HL(m_A))
else if (m_last_A && !INPLOGIC(m_A)) // High - Low
{
m_cnt ^= 1;
OUTLOGIC(m_Q[0], m_cnt & 1, delay[0]);
}
else if (INP_HL(m_B))
else if (m_last_B && !INPLOGIC(m_B)) // High - Low
{
m_cnt += 2;
if (m_cnt >= 10)
m_cnt = 0;
update_outputs();
}
m_last_A = INPLOGIC(m_A);
m_last_B = INPLOGIC(m_B);
}
NETLIB_FUNC_VOID(7490, update_outputs, (void))

View File

@ -81,6 +81,8 @@ NETLIB_DEVICE(7490,
netlist_ttl_input_t m_B;
netlist_state_t<UINT8> m_cnt;
netlist_state_t<UINT8> m_last_A;
netlist_state_t<UINT8> m_last_B;
netlist_ttl_output_t m_Q[4];
);

View File

@ -51,6 +51,7 @@ NETLIB_START(SN74LS629clk)
save(NAME(m_enableq));
save(NAME(m_inc));
save(NAME(m_out));
}
NETLIB_RESET(SN74LS629clk)
@ -63,7 +64,8 @@ NETLIB_UPDATE(SN74LS629clk)
{
if (!m_enableq)
{
OUTLOGIC(m_Y, !m_Y.net().as_logic().new_Q(), m_inc);
m_out = m_out ^ 1;
OUTLOGIC(m_Y, m_out, m_inc);
}
else
{
@ -146,12 +148,14 @@ NETLIB_UPDATE(SN74LS629)
if (!m_clock.m_enableq && INPLOGIC(m_ENQ))
{
m_clock.m_enableq = 1;
OUTLOGIC(m_clock.m_Y, !m_clock.m_Y.net().as_logic().last_Q(), netlist_time::from_nsec(1));
m_clock.m_out = m_clock.m_out ^ 1;
OUTLOGIC(m_clock.m_Y, m_clock.m_out, netlist_time::from_nsec(1));
}
else if (m_clock.m_enableq && !INPLOGIC(m_ENQ))
{
m_clock.m_enableq = 0;
OUTLOGIC(m_clock.m_Y, !m_clock.m_Y.net().as_logic().last_Q(), netlist_time::from_nsec(1));
m_clock.m_out = m_clock.m_out ^ 1;
OUTLOGIC(m_clock.m_Y, m_clock.m_out, netlist_time::from_nsec(1));
}
}

View File

@ -41,6 +41,7 @@ NETLIB_SUBDEVICE(SN74LS629clk,
netlist_time m_inc;
netlist_state_t<netlist_sig_t> m_enableq;
netlist_state_t<netlist_sig_t> m_out;
);
NETLIB_DEVICE_WITH_PARAMS(SN74LS629,

View File

@ -26,57 +26,6 @@
// net_signal_t
// ----------------------------------------------------------------------------------------
template <int _numdev>
class net_signal_base_t : public netlist_device_t
{
public:
net_signal_base_t()
: netlist_device_t(), m_active(1) { }
ATTR_COLD void start()
{
const char *sIN[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" };
register_output("Q", m_Q);
for (int i=0; i < _numdev; i++)
{
register_input(sIN[i], m_i[i], netlist_input_t::STATE_INP_ACTIVE);
}
save(NAME(m_active));
}
ATTR_COLD void reset()
{
m_Q.initial(1);
m_active = 1;
}
#if (USE_DEACTIVE_DEVICE)
ATTR_HOT void inc_active()
{
if (++m_active == 1)
{
update();
}
}
ATTR_HOT void dec_active()
{
if (--m_active == 0)
{
for (int i = 0; i< _numdev; i++)
m_i[i].inactivate();
}
}
#endif
public:
netlist_ttl_input_t m_i[_numdev];
netlist_ttl_output_t m_Q;
INT32 m_active;
};
template <int _numdev, int _check, int _invert>
class net_signal_t : public netlist_device_t
{
@ -207,22 +156,7 @@ public:
m_i[0].activate();
m_i[1].activate();
#if 0
UINT8 res = _invert ^ 1 ^_check;
if (INPLOGIC(m_i[0]) ^ _check)
{
if (INPLOGIC(m_i[1]) ^ _check)
{
res = _invert ^ _check;
}
else
m_i[0].inactivate();
} else {
if (INPLOGIC(m_i[1]) ^ _check)
m_i[1].inactivate();
}
OUTLOGIC(m_Q, res, times[res & 1]);// ? 22000 : 15000);
#else
const UINT8 val = (INPLOGIC(m_i[0]) ^ _check) | ((INPLOGIC(m_i[1]) ^ _check) << 1);
UINT8 res = _invert ^ 1 ^_check;
switch (val)
@ -238,7 +172,6 @@ public:
break;
}
OUTLOGIC(m_Q, res, times[res]);// ? 22000 : 15000);
#endif
}
public:
@ -248,71 +181,6 @@ public:
};
// The following did not improve performance
#if 0
template <UINT8 _check, UINT8 _invert>
class net_signal_t<3, _check, _invert> : public netlist_device_t
{
public:
net_signal_t() : netlist_device_t(), m_active(1) { }
ATTR_COLD void start()
{
const char *sIN[3] = { "I1", "I2", "I3" };
register_output("Q", m_Q);
for (int i=0; i < 3; i++)
{
register_input(sIN[i], m_i[i], netlist_input_t::STATE_INP_ACTIVE);
}
//m_Q.initial(1);
}
ATTR_HOT ATTR_ALIGN void update()
{
const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
//const UINT8 res_tab[4] = {1, 1, 1, 0 };
//const UINT8 ai1[4] = {0, 1, 0, 0 };
//const UINT8 ai2[4] = {1, 0, 1, 0 };
UINT8 res = _invert ^ 1 ^_check;
m_i[0].activate();
if (INPLOGIC(m_i[0]) ^ _check)
{
m_i[1].activate();
if (INPLOGIC(m_i[1]) ^ _check)
{
m_i[2].activate();
if (INPLOGIC(m_i[2]) ^ _check)
{
res = _invert ^ _check;
}
else
m_i[1].inactivate();
}
else
{
if (INPLOGIC(m_i[2]) ^ _check)
m_i[2].inactivate();
m_i[0].inactivate();
}
} else {
if (INPLOGIC(m_i[1]) ^ _check)
m_i[1].inactivate();
}
OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
}
public:
netlist_ttl_input_t m_i[3];
netlist_ttl_output_t m_Q;
INT8 m_active;
};
#endif
template <int _check, int _invert>
class net_signal_t<2, _check, _invert> : public net_signal_2inp_t<_check, _invert>
{

View File

@ -0,0 +1,187 @@
/*
* nld_truthtable.h
*
* Created on: 19 Jun 2014
* Author: andre
*/
#ifndef NLD_TRUTHTABLE_H_
#define NLD_TRUTHTABLE_H_
#include "../nl_base.h"
template<int m_NI, int m_NO>
class nld_truthtable_t : public netlist_device_t
{
public:
static const int m_size = (1 << (2 * m_NI + m_NO));
nld_truthtable_t()
: netlist_device_t(), m_active(1)
{
}
ATTR_COLD virtual void start()
{
}
ATTR_COLD void help(UINT32 outs[], int cur, nl_util::pstring_list list, UINT64 state, UINT64 ignore, UINT16 val)
{
pstring elem = list[cur];
int start = 0;
int end = 0;
int ign = 0;
if (elem.equals("0"))
{
start = 0;
end = 0;
}
else if (elem.equals("1"))
{
start = 1;
end = 1;
}
else if (elem.equals("X"))
{
start = 0;
end = 1;
ign = 1;
}
for (int i = start; i <= end; i++)
{
const UINT64 nstate = state | (i << cur);
const UINT64 nignore = ignore | (ign << cur);
if (cur < list.count() - 1)
{
help(outs, cur + 1, list, nstate, nignore, val);
}
else
{
// cutoff previous inputs and outputs for ignore
outs[nstate] = val | ((nignore & ((1 << m_NI)-1)) << m_NO);
}
}
}
ATTR_COLD void setup_tt(const char **truthtable, UINT32 outs[])
{
pstring ttline = pstring(truthtable[0]);
truthtable++;
{
nl_util::pstring_list io = nl_util::split(ttline,"|");
// checks
assert(io.count() == 2);
nl_util::pstring_list inout = nl_util::split(io[0], ",");
assert(inout.count() == 2 * m_NI + m_NO);
nl_util::pstring_list out = nl_util::split(io[1], ",");
assert(out.count() == m_NO);
for (int i=0; i < m_NI; i++)
{
register_input(inout[i], m_i[i]);
}
for (int i=0; i < m_NO; i++)
{
register_output(out[i], m_Q[i]);
}
//save(NAME(m_active));
ttline = pstring(truthtable[0]);
truthtable++;
}
for (int j=0; j < m_size; j++)
outs[j] = -1;
while (!ttline.equals(""))
{
nl_util::pstring_list io = nl_util::split(ttline,"|");
// checks
assert(io.count() == 2);
nl_util::pstring_list inout = nl_util::split(io[0], ",");
assert(inout.count() == 2 * m_NI + m_NO);
nl_util::pstring_list out = nl_util::split(io[1], ",");
assert(out.count() == m_NO);
UINT16 val = 0;
for (int j=0; j<m_NO; j++)
if (out[j].equals("1"))
val = val | (1 << j);
help(outs, 0, inout, 0 , 0 , val);
ttline = pstring(truthtable[0]);
truthtable++;
}
for (int j=0; j < m_size; j++)
printf("%05x %04x %04x\n", j, outs[j] & ((1 << m_NO)-1), outs[j] >> m_NO);
m_ttp = outs;
}
ATTR_COLD void reset()
{
//m_Q.initial(1);
m_active = 1;
m_last_state = 0;
}
ATTR_HOT ATTR_ALIGN void update()
{
const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22)};
// FIXME: this check is needed because update is called during startup as well
if (UNEXPECTED(USE_DEACTIVE_DEVICE && m_active == 0))
return;
UINT32 state = 0;
for (int i=0; i< m_NI; i++)
{
m_i[i].activate();
state = state | (INPLOGIC(m_i[i]) << i);
}
const UINT32 nstate = state | (m_last_state << m_NI);
const UINT32 out = m_ttp[nstate] & ((1 << m_NO) - 1);
const UINT32 ign = m_ttp[nstate] >> m_NO;
for (int i=0; i< m_NI; i++)
if (ign & (1 << i))
m_i[i].inactivate();
for (int i=0; i<m_NO; i++)
OUTLOGIC(m_Q[i], (out >> i) & 1, times[(out >> i) & 1]);// ? 22000 : 15000);
m_last_state = (state << m_NO) | out;
}
#if (USE_DEACTIVE_DEVICE)
ATTR_HOT void inc_active()
{
if (++m_active == 1)
{
update();
}
}
ATTR_HOT void dec_active()
{
if (--m_active == 0)
{
for (int i = 0; i< m_NI; i++)
m_i[i].inactivate();
}
}
#endif
public:
netlist_ttl_input_t m_i[m_NI];
netlist_ttl_output_t m_Q[m_NO];
UINT32 *m_ttp;
INT32 m_active;
UINT32 m_last_state;
};
#endif /* NLD_TRUTHTABLE_H_ */

View File

@ -455,7 +455,6 @@ ATTR_COLD netlist_net_t::netlist_net_t(const family_t afamily)
: netlist_object_t(NET, afamily)
, m_new_Q(0)
, m_cur_Q (0)
, m_last_Q(0)
, m_railterminal(NULL)
, m_time(netlist_time::zero)
, m_active(0)
@ -486,7 +485,6 @@ ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term)
{
if (m_active == 1 && m_in_queue > 0)
{
m_last_Q = m_cur_Q;
railterminal().netdev().inc_active();
m_cur_Q = m_new_Q;
}
@ -501,7 +499,7 @@ ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term)
}
else
{
m_cur_Q = m_last_Q = m_new_Q;
m_cur_Q = m_new_Q;
m_in_queue = 2;
}
}
@ -541,7 +539,6 @@ ATTR_COLD void netlist_net_t::save_register()
save(NAME(m_active));
save(NAME(m_in_queue));
save(NAME(m_cur_Analog));
save(NAME(m_last_Q));
save(NAME(m_cur_Q));
save(NAME(m_new_Q));
netlist_object_t::save_register();
@ -565,13 +562,13 @@ ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs()
assert(this->isRailNet());
const UINT32 masks[4] = { 1, 5, 3, 1 };
const UINT32 mask = masks[ (m_last_Q << 1) | m_new_Q ];
const UINT32 mask = masks[ (m_cur_Q << 1) | m_new_Q ];
netlist_core_terminal_t *p = m_list_active.first();
m_in_queue = 2; /* mark as taken ... */
m_cur_Q = m_new_Q;
switch (m_active)
switch (m_active)
{
case 2:
update_dev(p, mask);
@ -588,7 +585,7 @@ ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs()
}
break;
}
m_last_Q = m_cur_Q;
}
ATTR_COLD void netlist_net_t::reset()
@ -597,7 +594,6 @@ ATTR_COLD void netlist_net_t::reset()
m_active = 0;
m_in_queue = 2;
m_last_Q = 0;
m_new_Q = 0;
m_cur_Q = 0;
m_cur_Analog = 0.0;

View File

@ -629,7 +629,6 @@ protected: //FIXME: needed by current solver code
netlist_sig_t m_new_Q;
netlist_sig_t m_cur_Q;
netlist_sig_t m_last_Q;
private:
@ -663,11 +662,6 @@ public:
return m_cur_Q;
}
ATTR_HOT inline const netlist_sig_t last_Q() const
{
return m_last_Q;
}
ATTR_HOT inline const netlist_sig_t new_Q() const
{
return m_new_Q;
@ -691,7 +685,6 @@ public:
{
m_cur_Q = val;
m_new_Q = val;
m_last_Q = val;
}
/* internal state support
@ -986,21 +979,6 @@ public:
out.set_Q(val, delay);
}
ATTR_HOT inline bool INP_CHANGED(const netlist_logic_input_t &inp) const
{
return (inp.last_Q() != inp.Q());
}
ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const
{
return ((inp.last_Q() & !inp.Q()) == 1);
}
ATTR_HOT inline bool INP_LH(const netlist_logic_input_t &inp) const
{
return ((!inp.last_Q() & inp.Q()) == 1);
}
ATTR_HOT inline const double INPANALOG(const netlist_analog_input_t &inp) const { return inp.Q_Analog(); }
ATTR_HOT inline const double TERMANALOG(const netlist_terminal_t &term) const { return term.net().as_analog().Q_Analog(); }
@ -1358,11 +1336,6 @@ ATTR_HOT inline const netlist_sig_t netlist_logic_input_t::Q() const
return net().as_logic().Q();
}
ATTR_HOT inline const netlist_sig_t netlist_logic_input_t::last_Q() const
{
return net().as_logic().last_Q();
}
ATTR_HOT inline const double netlist_analog_input_t::Q_Analog() const
{
return net().as_analog().Q_Analog();

View File

@ -23,8 +23,13 @@
*/
#define USE_PMFDELEGATES (0)
// This increases performance in circuits with a lot of gates
// but is not guaranteed to be absolutely timing correct.
/*
* This increases performance in circuits with a lot of gates
* but is not guaranteed to be absolutely timing correct.
*
* Performance increase about 10%
*
*/
#define USE_DEACTIVE_DEVICE (0)