summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/devices/nlid_truthtable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/devices/nlid_truthtable.cpp')
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.cpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp
new file mode 100644
index 00000000000..824061fdc30
--- /dev/null
+++ b/src/lib/netlist/devices/nlid_truthtable.cpp
@@ -0,0 +1,307 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_truthtable.c
+ *
+ */
+
+#include "nlid_truthtable.h"
+#include "plib/plists.h"
+#include "nl_setup.h"
+#include "plib/palloc.h"
+
+namespace netlist
+{
+ namespace devices
+ {
+ template<unsigned m_NI, unsigned m_NO>
+ class netlist_factory_truthtable_t : public netlist_base_factory_truthtable_t
+ {
+ public:
+ netlist_factory_truthtable_t(const pstring &name, const pstring &classname,
+ const pstring &def_param, const pstring &sourcefile)
+ : netlist_base_factory_truthtable_t(name, classname, def_param, sourcefile)
+ { }
+
+ plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
+ {
+ typedef nld_truthtable_t<m_NI, m_NO> tt_type;
+ return plib::owned_ptr<device_t>::Create<tt_type>(anetlist, name, m_family, &m_ttbl, m_desc);
+ }
+ private:
+ typename nld_truthtable_t<m_NI, m_NO>::truthtable_t m_ttbl;
+ };
+
+ static const uint_least64_t all_set = ~(static_cast<uint_least64_t>(0));
+
+unsigned truthtable_desc_t::count_bits(uint_least64_t v)
+{
+ unsigned ret = 0;
+ for (; v != 0; v = v >> 1)
+ {
+ ret += (v & 1);
+ }
+ return ret;
+}
+
+uint_least64_t truthtable_desc_t::set_bits(uint_least64_t v, uint_least64_t b)
+{
+ uint_least64_t ret = 0;
+ for (size_t i = 0; v != 0; v = v >> 1, ++i)
+ {
+ if (v & 1)
+ {
+ ret |= ((b&1)<<i);
+ b = b >> 1;
+ }
+ }
+ return ret;
+}
+
+uint_least64_t truthtable_desc_t::get_ignored_simple(uint_least64_t i)
+{
+ uint_least64_t m_enable = 0;
+ for (size_t j=0; j<m_size; j++)
+ {
+ if (m_outs[j] != m_outs[i])
+ {
+ m_enable |= (i ^ j);
+ }
+ }
+ return m_enable ^ (m_size - 1);
+}
+
+uint_least64_t truthtable_desc_t::get_ignored_extended(uint_least64_t state)
+{
+ // Determine all inputs which may be ignored ...
+ uint_least64_t ignore = 0;
+ for (unsigned j=0; j<m_NI; j++)
+ {
+ if (m_outs[state] == m_outs[state ^ (1 << j)])
+ ignore |= (1<<j);
+ }
+ /* Check all permutations of ign
+ * We have to remove those where the ignored inputs
+ * may change the output
+ */
+ uint_least64_t bits = (1<<count_bits(ignore));
+ std::vector<bool> t(bits);
+
+ for (size_t j=1; j<bits; j++)
+ {
+ uint_least64_t tign = set_bits(ignore, j);
+ t[j] = 0;
+ uint_least64_t bitsk=(1<<count_bits(tign));
+ for (size_t k=0; k<bitsk; k++)
+ {
+ uint_least64_t b=set_bits(tign, k);
+ if (m_outs[state] != m_outs[(state & ~tign) | b])
+ {
+ t[j] = 1;
+ break;
+ }
+ }
+ }
+ size_t jb=0;
+ size_t jm=0;
+ for (size_t j=1; j<bits; j++)
+ {
+ size_t nb = count_bits(j);
+ if ((t[j] == 0) && (nb>jb))
+ {
+ jb = nb;
+ jm = j;
+ }
+ }
+ return set_bits(ignore, jm);
+}
+
+// ----------------------------------------------------------------------------------------
+// desc
+// ----------------------------------------------------------------------------------------
+
+void truthtable_desc_t::help(unsigned cur, std::vector<pstring> list,
+ uint_least64_t state, uint_least64_t val, std::vector<uint_least8_t> &timing_index)
+{
+ pstring elem = list[cur].trim();
+ uint_least64_t start = 0;
+ uint_least64_t 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 (uint_least64_t i = start; i <= end; i++)
+ {
+ const uint_least64_t 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
+ if (m_outs[nstate] != m_outs.adjust(all_set) && m_outs[nstate] != val)
+ nl_exception(plib::pfmt("Error in truthtable: State {1} already set, {2} != {3}\n")
+ .x(nstate,"04")(m_outs[nstate])(val) );
+ m_outs.set(nstate, val);
+ for (unsigned j=0; j<m_NO; j++)
+ m_timing[nstate * m_NO + j] = timing_index[j];
+ }
+ }
+}
+
+void truthtable_desc_t::setup(const std::vector<pstring> &truthtable, uint_least64_t disabled_ignore)
+{
+ unsigned line = 0;
+
+ if (*m_initialized)
+ return;
+
+ pstring ttline = truthtable[line];
+ line++;
+ ttline = truthtable[line];
+ line++;
+
+ for (unsigned j=0; j < m_size; j++)
+ m_outs.set(j, all_set);
+
+ for (int j=0; j < 16; j++)
+ m_timing_nt[j] = netlist_time::zero();
+
+ while (!ttline.equals(""))
+ {
+ std::vector<pstring> io(plib::psplit(ttline,"|"));
+ // checks
+ nl_assert_always(io.size() == 3, "io.count mismatch");
+ std::vector<pstring> inout(plib::psplit(io[0], ","));
+ nl_assert_always(inout.size() == m_num_bits, "number of bits not matching");
+ std::vector<pstring> out(plib::psplit(io[1], ","));
+ nl_assert_always(out.size() == m_NO, "output count not matching");
+ std::vector<pstring> times(plib::psplit(io[2], ","));
+ nl_assert_always(times.size() == m_NO, "timing count not matching");
+
+ uint_least64_t val = 0;
+ std::vector<uint_least8_t> tindex;
+
+ for (unsigned 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(static_cast<unsigned long>(times[j].trim().as_long()));
+ uint_least8_t k=0;
+ while (m_timing_nt[k] != netlist_time::zero() && m_timing_nt[k] != t)
+ k++;
+ m_timing_nt[k] = t;
+ tindex.push_back(k); //[j] = k;
+ }
+
+ help(0, inout, 0 , val, tindex);
+ if (line < truthtable.size())
+ ttline = truthtable[line];
+ else
+ ttline = "";
+ line++;
+ }
+
+ // determine ignore
+ std::vector<uint_least64_t> ign(m_size, all_set);
+
+ for (size_t i=0; i<m_size; i++)
+ {
+ if (ign[i] == all_set)
+ {
+ uint_least64_t tign;
+ if ((0))
+ {
+ tign = get_ignored_simple(i);
+ ign[i] = tign;
+ }
+ else
+ {
+ tign = get_ignored_extended(i);
+
+ ign[i] = tign;
+ /* don't need to recalculate similar ones */
+ uint_least64_t bitsk=(1<<count_bits(tign));
+ for (uint_least64_t k=0; k<bitsk; k++)
+ {
+ uint_least64_t b=set_bits(tign, k);
+ ign[(i & ~tign) | b] = tign;
+ }
+ }
+ }
+ }
+ for (size_t i=0; i<m_size; i++)
+ {
+ if (m_outs[i] == m_outs.adjust(all_set))
+ throw nl_exception(plib::pfmt("truthtable: found element not set {1}\n").x(i) );
+ m_outs.set(i, m_outs[i] | ((ign[i] & ~disabled_ignore) << m_NO));;
+ }
+ *m_initialized = true;
+
+}
+
+netlist_base_factory_truthtable_t::netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname,
+ const pstring &def_param, const pstring &sourcefile)
+: factory::element_t(name, classname, def_param, sourcefile), m_family(family_TTL())
+{
+}
+
+netlist_base_factory_truthtable_t::~netlist_base_factory_truthtable_t()
+{
+}
+
+
+#define ENTRYY(n, m, s) case (n * 100 + m): \
+ { using xtype = netlist_factory_truthtable_t<n, m>; \
+ ret = plib::palloc<xtype>(desc.name, desc.classname, desc.def_param, s); } break
+
+#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \
+ ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s)
+
+void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile)
+{
+ netlist_base_factory_truthtable_t *ret;
+
+ switch (desc.ni * 100 + desc.no)
+ {
+ ENTRY(1, sourcefile);
+ ENTRY(2, sourcefile);
+ ENTRY(3, sourcefile);
+ ENTRY(4, sourcefile);
+ ENTRY(5, sourcefile);
+ ENTRY(6, sourcefile);
+ ENTRY(7, sourcefile);
+ ENTRY(8, sourcefile);
+ ENTRY(9, sourcefile);
+ ENTRY(10, sourcefile);
+ default:
+ pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no);
+ nl_assert_always(false, msg);
+ }
+ ret->m_desc = desc.desc;
+ if (desc.family != "")
+ ret->m_family = setup.family_from_model(desc.family);
+ setup.factory().register_device(std::unique_ptr<netlist_base_factory_truthtable_t>(ret));
+}
+
+ } //namespace devices
+} // namespace netlist