// license:GPL-2.0+ // copyright-holders:Couriersud /* * nld_truthtable.h * * Created on: 19 Jun 2014 * Author: andre */ #ifndef NLID_TRUTHTABLE_H_ #define NLID_TRUTHTABLE_H_ #include "../nl_setup.h" #include "../nl_base.h" #include "../plib/putil.h" #define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \ class NETLIB_NAME(cname) : public nld_truthtable_t \ { \ public: \ template \ NETLIB_NAME(cname)(C &owner, const pstring &name) \ : nld_truthtable_t(owner, name, family_TTL(), &m_ttbl, m_desc) { } \ private: \ static truthtable_t m_ttbl; \ static std::vector m_desc; \ } namespace netlist { namespace devices { #if 0 template struct uint_for_size { typedef uint_least32_t type; }; template struct need_bytes_for_bits { enum { value = 4 }; }; #else template struct need_bytes_for_bits { enum { value = bits <= 8 ? 1 : bits <= 16 ? 2 : bits <= 32 ? 4 : 8 }; }; template struct uint_for_size; template<> struct uint_for_size<1> { typedef uint_least8_t type; }; template<> struct uint_for_size<2> { typedef uint_least16_t type; }; template<> struct uint_for_size<4> { typedef uint_least32_t type; }; template<> struct uint_for_size<8> { typedef uint_least64_t type; }; #endif template NETLIB_OBJECT(truthtable_t) { private: detail::family_setter_t m_fam; public: typedef typename uint_for_size::value>::type type_t; static constexpr const std::size_t m_num_bits = m_NI; static constexpr const std::size_t m_size = (1 << (m_num_bits)); static constexpr const type_t m_outmask = ((1 << m_NO) - 1); static constexpr const std::size_t m_min_devices_for_deactivate = 2; struct truthtable_t { truthtable_t() : m_initialized(false) {} bool m_initialized; type_t m_outs[m_size]; uint_least8_t m_timing[m_size * m_NO]; netlist_time m_timing_nt[16]; }; template nld_truthtable_t(C &owner, const pstring &name, const logic_family_desc_t *fam, truthtable_t &ttp, const std::vector &desc) : device_t(owner, name) , m_fam(*this, fam) , m_ign(*this, "m_ign", 0) , m_active(*this, "m_active", 1) , m_ttp(ttp) { init(desc); } void init(const std::vector &desc); NETLIB_RESETI() { m_active = 0; m_ign = 0; for (auto &i : m_I) i.activate(); for (auto &q : m_Q) if (q.has_net() && q.net().num_cons() > 0) m_active++; } NETLIB_UPDATEI() { process(); } void inc_active() NL_NOEXCEPT override { if (m_NI >= m_min_devices_for_deactivate) if (++m_active == 1) { process(); } } void dec_active() NL_NOEXCEPT override { /* FIXME: * Based on current measurements there is no point to disable * 1 input devices. This should actually be a parameter so that we * can decide for each individual gate whether it is beneficial to * ignore deactivation. */ if (m_NI >= m_min_devices_for_deactivate) if (--m_active == 0) { for (std::size_t i = 0; i< m_NI; i++) m_I[i].inactivate(); m_ign = (1< m_I; plib::uninitialised_array_t m_Q; protected: private: template void process() { netlist_time mt(netlist_time::zero()); type_t nstate(0); if (m_NI >= m_min_devices_for_deactivate) { type_t ign(m_ign); if (!doOUT) for (std::size_t i = 0; i < m_NI; i++) { m_I[i].activate(); nstate |= (m_I[i]() ? (1 << i) : 0); mt = std::max(this->m_I[i].net().time(), mt); } else for (std::size_t i = 0; i < m_NI; i++) { if ((ign & 1)) m_I[i].activate(); nstate |= (m_I[i]() ? (1 << i) : 0); ign >>= 1; } } else { if (!doOUT) for (std::size_t i = 0; i < m_NI; i++) { nstate |= (m_I[i]() ? (1 << i) : 0); mt = std::max(this->m_I[i].net().time(), mt); } else for (std::size_t i = 0; i < m_NI; i++) nstate |= (m_I[i]() ? (1 << i) : 0); } const type_t outstate(m_ttp.m_outs[nstate]); type_t out(outstate & m_outmask); m_ign = outstate >> m_NO; const std::size_t timebase(nstate * m_NO); const auto *t(&m_ttp.m_timing[timebase]); const auto *tim = m_ttp.m_timing_nt; if (doOUT) for (std::size_t i = 0; i < m_NO; out >>= 1, ++i) m_Q[i].push(out & 1, tim[t[i]]); else for (std::size_t i = 0; i < m_NO; out >>= 1, ++i) m_Q[i].set_Q_time(out & 1, mt + tim[t[i]]); if (m_NI >= m_min_devices_for_deactivate) { type_t ign(m_ign); for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I) if (ign & 1) I->inactivate(); } } /* FIXME: check width */ state_var m_ign; state_var_s32 m_active; const truthtable_t &m_ttp; }; class netlist_base_factory_truthtable_t : public factory::element_t { public: netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname, const pstring &def_param, const pstring &sourcefile); virtual ~netlist_base_factory_truthtable_t(); std::vector m_desc; const logic_family_desc_t *m_family; }; void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile); } //namespace devices } // namespace netlist #endif /* NLID_TRUTHTABLE_H_ */