diff options
-rw-r--r-- | scripts/src/netlist.lua | 1 | ||||
-rw-r--r-- | src/emu/netlist/devices/nld_truthtable.c | 189 | ||||
-rw-r--r-- | src/emu/netlist/devices/nld_truthtable.h | 218 |
3 files changed, 229 insertions, 179 deletions
diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index 3c0ded1383e..6c79eb1b463 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -116,5 +116,6 @@ files { MAME_DIR .. "src/emu/netlist/devices/nld_system.h", MAME_DIR .. "src/emu/netlist/devices/nld_cmos.h", MAME_DIR .. "src/emu/netlist/devices/nld_signal.h", + MAME_DIR .. "src/emu/netlist/devices/nld_truthtable.c", MAME_DIR .. "src/emu/netlist/devices/nld_truthtable.h", } diff --git a/src/emu/netlist/devices/nld_truthtable.c b/src/emu/netlist/devices/nld_truthtable.c new file mode 100644 index 00000000000..54733eb160f --- /dev/null +++ b/src/emu/netlist/devices/nld_truthtable.c @@ -0,0 +1,189 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * nld_truthtable.c + * + */ + +#include "nld_truthtable.h" + +static inline int count_bits(UINT32 v) +{ + int ret = 0; + for (int i=0; i<32; i++) + if (v & (1<<i)) + ret++; + return ret; +} + +static inline UINT32 set_bits(UINT32 v, UINT32 b) +{ + UINT32 ret = 0; + for (int i=0; i<32; i++) + if (v & (1<<i)) + { + ret |= ((b&1)<<i); + b = b >> 1; + } + return ret; +} + + +// ---------------------------------------------------------------------------------------- +// desc +// ---------------------------------------------------------------------------------------- + +ATTR_COLD void truthtable_desc_t::help(int cur, nl_util::pstring_list list, + UINT64 state,UINT16 val, UINT8 *timing_index) +{ + pstring elem = list[cur].trim(); + int start = 0; + int end = 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; + } + else + nl_assert_always(false, "unknown input value (not 0, 1, or X)"); + for (int i = start; i <= end; i++) + { + const UINT64 nstate = state | (i << cur); + + if (cur < m_num_bits - 1) + { + help(cur + 1, list, nstate, val, timing_index); + } + else + { + // cutoff previous inputs and outputs for ignore + m_outs[nstate] = val; + for (int j=0; j<m_NO; j++) + m_timing[nstate * m_NO + j] = timing_index[j]; + } + } +} + +ATTR_COLD void truthtable_desc_t::setup(const char **truthtable) +{ + if (*m_initialized) + return; + + pstring ttline = pstring(truthtable[0]); + truthtable++; + ttline = pstring(truthtable[0]); + truthtable++; + + for (int j=0; j < m_size; j++) + m_outs[j] = -1; + + for (int j=0; j < 16; j++) + m_timing_nt[j] = netlist_time::zero; + + while (!ttline.equals("")) + { + nl_util::pstring_list io = nl_util::split(ttline,"|"); + // checks + nl_assert_always(io.count() == 3, "io.count mismatch"); + nl_util::pstring_list inout = nl_util::split(io[0], ","); + nl_assert_always(inout.count() == m_num_bits, "number of bits not matching"); + nl_util::pstring_list out = nl_util::split(io[1], ","); + nl_assert_always(out.count() == m_NO, "output count not matching"); + nl_util::pstring_list times = nl_util::split(io[2], ","); + nl_assert_always(times.count() == m_NO, "timing count not matching"); + + UINT16 val = 0; + UINT8 tindex[m_NO]; + for (int j=0; j<m_NO; j++) + { + pstring outs = out[j].trim(); + if (outs.equals("1")) + val = val | (1 << j); + else + nl_assert_always(outs.equals("0"), "Unknown value (not 0 or 1"); + netlist_time t = netlist_time::from_nsec(times[j].trim().as_long()); + int k=0; + while (m_timing_nt[k] != netlist_time::zero && m_timing_nt[k] != t) + k++; + m_timing_nt[k] = t; + tindex[j] = k; + } + + help(0, inout, 0 , val, tindex); + ttline = pstring(truthtable[0]); + truthtable++; + } + + // determine ignore + UINT32 ign[m_size]; + + for (int i=0; i<m_size; i++) + { +#if 1 + UINT32 m_enable = 0; + for (int j=0; j<m_size; j++) + { + if (m_outs[j] != m_outs[i]) + { + m_enable |= (i ^ j); + } + } + ign[i] = m_enable ^ (m_size - 1); +#else + // this doesn't work in all cases and is dog slow + UINT32 nign = 0; + for (int j=0; j<m_NI; j++) + { + if (m_outs[i] == m_outs[i ^ (1 << j)]) + nign |= (1<<j); + } + /* Check all permutations of ign + */ + int t[1<<count_bits(nign)]; + + for (UINT32 j=0; j<(1<<count_bits(nign)); j++) + { + UINT32 tign = set_bits(nign, j); + t[j] = 0; + for (UINT32 k=0; k<(1<<count_bits(tign)); k++) + { + UINT32 b=set_bits(tign, k); + if (m_outs[i] != m_outs[(i & ~tign) | b]) + t[j] = 1; + } + //printf("x %d %d\n", j, tign); + } + UINT32 jb=0; + UINT32 jm=0; + for (UINT32 j=0; j<(1<<count_bits(nign)); j++) + { + int nb = count_bits(j); + if ((t[j] == 0)&& (nb>jb)) + { + jb = nb; + jm = j; + } + } + ign[i] = set_bits(nign, jm); +#endif + } + for (int i=0; i<m_size; i++) + { + m_outs[i] |= (ign[i] << m_NO); + } + *m_initialized = true; + +} + + diff --git a/src/emu/netlist/devices/nld_truthtable.h b/src/emu/netlist/devices/nld_truthtable.h index 2ab64bc8b42..ad2683f4f74 100644 --- a/src/emu/netlist/devices/nld_truthtable.h +++ b/src/emu/netlist/devices/nld_truthtable.h @@ -32,26 +32,37 @@ static inline UINT32 remove_first_bit(UINT32 v) return v; } -static inline int count_bits(UINT32 v) +struct truthtable_desc_t { - int ret = 0; - for (int i=0; i<32; i++) - if (v & (1<<i)) - ret++; - return ret; -} + truthtable_desc_t(int NO, int NI, int has_state, bool *initialized, + UINT32 *outs, UINT8 *timing, netlist_time *timing_nt) + : m_NO(NO), m_NI(NI), m_has_state(has_state), m_initialized(initialized), + m_outs(outs), m_timing(timing), m_timing_nt(timing_nt), + m_num_bits(m_NI + has_state * (m_NI + m_NO)), + m_size(1 << (m_num_bits)) + { + } -static inline UINT32 set_bits(UINT32 v, UINT32 b) -{ - UINT32 ret = 0; - for (int i=0; i<32; i++) - if (v & (1<<i)) - { - ret |= ((b&1)<<i); - b = b >> 1; - } - return ret; -} + ATTR_COLD void setup(const char **truthtable); + +private: + ATTR_COLD void help(int cur, nl_util::pstring_list list, + UINT64 state,UINT16 val, UINT8 *timing_index); + + int m_NO; + int m_NI; + int m_has_state; + bool *m_initialized; + UINT32 *m_outs; + UINT8 *m_timing; + netlist_time *m_timing_nt; + + /* additional values */ + + const int m_num_bits; + const int m_size; + +}; template<int m_NI, int m_NO, int has_state> class nld_truthtable_t : public netlist_device_t @@ -63,11 +74,13 @@ public: struct truthtable_t { - truthtable_t() : m_initialized(false) {} + truthtable_t() : m_initialized(false), + m_desc(m_NO, m_NI, has_state, &m_initialized, m_outs, m_timing, m_timing_nt) {} + bool m_initialized; UINT32 m_outs[m_size]; UINT8 m_timing[m_size * m_NO]; netlist_time m_timing_nt[16]; - bool m_initialized; + truthtable_desc_t m_desc; }; nld_truthtable_t(truthtable_t *ttbl, const char *desc[]) @@ -112,172 +125,16 @@ public: } } m_ign = 0; - setup_tt(); - // FIXME: save state - } - - ATTR_COLD void help(int cur, nl_util::pstring_list list, - UINT64 state,UINT16 val, UINT8 timing_index[m_NO]) - { - pstring elem = list[cur].trim(); - int start = 0; - int end = 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; - } - else - nl_assert_always(false, "unknown input value (not 0, 1, or X)"); - for (int i = start; i <= end; i++) - { - const UINT64 nstate = state | (i << cur); - - if (cur < m_num_bits - 1) - { - help(cur + 1, list, nstate, val, timing_index); - } - else - { - // cutoff previous inputs and outputs for ignore - m_ttp->m_outs[nstate] = val; - for (int j=0; j<m_NO; j++) - m_ttp->m_timing[nstate * m_NO + j] = timing_index[j]; - } - } - } - - ATTR_COLD void setup_tt() - { - if (m_ttp->m_initialized) - return; - - const char **truthtable = m_desc; - pstring ttline = pstring(truthtable[0]); - truthtable++; - ttline = pstring(truthtable[0]); - truthtable++; - - for (int j=0; j < m_size; j++) - m_ttp->m_outs[j] = -1; - - for (int j=0; j < 16; j++) - m_ttp->m_timing_nt[j] = netlist_time::zero; - - while (!ttline.equals("")) - { - nl_util::pstring_list io = nl_util::split(ttline,"|"); - // checks - nl_assert_always(io.count() == 3, "io.count mismatch"); - nl_util::pstring_list inout = nl_util::split(io[0], ","); - nl_assert_always(inout.count() == m_num_bits, "number of bits not matching"); - nl_util::pstring_list out = nl_util::split(io[1], ","); - nl_assert_always(out.count() == m_NO, "output count not matching"); - nl_util::pstring_list times = nl_util::split(io[2], ","); - nl_assert_always(times.count() == m_NO, "timing count not matching"); - - UINT16 val = 0; - UINT8 tindex[m_NO]; - for (int j=0; j<m_NO; j++) - { - pstring outs = out[j].trim(); - if (outs.equals("1")) - val = val | (1 << j); - else - nl_assert_always(outs.equals("0"), "Unknown value (not 0 or 1"); - netlist_time t = netlist_time::from_nsec(times[j].trim().as_long()); - int k=0; - while (m_ttp->m_timing_nt[k] != netlist_time::zero && m_ttp->m_timing_nt[k] != t) - k++; - m_ttp->m_timing_nt[k] = t; - tindex[j] = k; - } - - help(0, inout, 0 , val, tindex); - ttline = pstring(truthtable[0]); - truthtable++; - } - - // ((nignore & ((1 << m_NI)-1)) << m_NO) - - // determine ignore - UINT32 ign[m_size]; - - for (int i=0; i<m_size; i++) - { -#if 1 - UINT32 m_enable = 0; - for (int j=0; j<m_size; j++) - { - if (m_ttp->m_outs[j] != m_ttp->m_outs[i]) - { - m_enable |= (i ^ j); - } - } - ign[i] = m_enable ^ (m_size - 1); -#else - // this doesn't work in all cases and is dog slow - UINT32 nign = 0; - for (int j=0; j<m_NI; j++) - { - if (m_ttp->m_outs[i] == m_ttp->m_outs[i ^ (1 << j)]) - nign |= (1<<j); - } - /* Check all permutations of ign - */ - int t[1<<count_bits(nign)]; - - for (UINT32 j=0; j<(1<<count_bits(nign)); j++) - { - UINT32 tign = set_bits(nign, j); - t[j] = 0; - for (UINT32 k=0; k<(1<<count_bits(tign)); k++) - { - UINT32 b=set_bits(tign, k); - if (m_ttp->m_outs[i] != m_ttp->m_outs[(i & ~tign) | b]) - t[j] = 1; - } - //printf("x %d %d\n", j, tign); - } - UINT32 jb=0; - UINT32 jm=0; - for (UINT32 j=0; j<(1<<count_bits(nign)); j++) - { - int nb = count_bits(j); - if ((t[j] == 0)&& (nb>jb)) - { - jb = nb; - jm = j; - } - } - ign[i] = set_bits(nign, jm); -#endif - } - for (int i=0; i<m_size; i++) - { - m_ttp->m_outs[i] |= (ign[i] << m_NO); - } + m_ttp->m_desc.setup(m_desc); #if 0 printf("%s\n", name().cstr()); for (int j=0; j < m_size; j++) printf("%05x %04x %04x %04x\n", j, m_ttp->m_outs[j] & ((1 << m_NO)-1), - m_ttp->m_outs[j] >> m_NO, m_ttp->m_timing[j][0]); + m_ttp->m_outs[j] >> m_NO, m_ttp->m_timing[j * m_NO + 0]); for (int k=0; m_ttp->m_timing_nt[k] != netlist_time::zero; k++) printf("%d %f\n", k, m_ttp->m_timing_nt[k].as_double() * 1000000.0); #endif - m_ttp->m_initialized = true; - + // FIXME: save state } ATTR_COLD void reset() @@ -366,4 +223,7 @@ private: const char **m_desc; }; + + + #endif /* NLD_TRUTHTABLE_H_ */ |