More truthtable rework and clean up. (nw)

This commit is contained in:
couriersud 2017-02-18 12:23:07 +01:00
parent 2ade578dc0
commit 65806114b0
7 changed files with 259 additions and 226 deletions

View File

@ -12,7 +12,7 @@ namespace netlist
{
namespace devices
{
#if (USE_TRUTHTABLE_7448 && USE_TRUTHTABLE)
#if (USE_TRUTHTABLE_7448)
NETLIB_TRUTHTABLE(7448, 7, 7);
@ -78,9 +78,9 @@ namespace netlist
#endif
#if (USE_TRUTHTABLE_7448 && USE_TRUTHTABLE)
#if (USE_TRUTHTABLE_7448)
nld_7448::truthtable_t nld_7448::m_ttbl;
const pstring nld_7448::m_desc[] = {
std::vector<pstring> nld_7448::m_desc = {
" LTQ,BIQ,RBIQ, A , B , C , D | a, b, c, d, e, f, g",
" 1, 1, 1, 0, 0, 0, 0 | 1, 1, 1, 1, 1, 1, 0|100,100,100,100,100,100,100",

View File

@ -26,14 +26,6 @@
#include "../nl_setup.h"
/*
* FIXME: Using truthtable is a lot slower than the explicit device
* in breakout. Performance drops by 20%. This can be fixed by
* setting param USE_DEACTIVATE for the device.
*/
#define USE_TRUTHTABLE_7448 (0)
#ifndef NL_AUTO_DEVICES
#define TTL_7448(name, cA0, cA1, cA2, cA3, cLTQ, cBIQ, cRBIQ) \

View File

@ -10,31 +10,101 @@
#include "../nl_setup.h"
#include "../plib/palloc.h"
#include <bitset>
namespace netlist
{
namespace devices
{
// ----------------------------------------------------------------------------------------
// Truthtable description ....
// int compatible bitset ....
// ----------------------------------------------------------------------------------------
template <typename T>
struct sbitset
{
typedef T type;
sbitset() : m_bs(0) { }
sbitset(T v) : m_bs(v) { }
sbitset &set() { *this = all_bits(); return *this; }
sbitset &set(const std::size_t bit) { m_bs |= (static_cast<T>(1) << bit); return *this; }
sbitset &reset() { *this = no_bits(); return *this; }
sbitset &reset(const std::size_t bit) { m_bs &= ~(static_cast<T>(1) << bit); return *this; }
sbitset invert() const { return sbitset(~m_bs); }
std::size_t count()
{
std::size_t ret = 0;
for (T v = m_bs; v != 0; v = v >> 1)
{
ret += (v & 1);
}
return ret;
}
constexpr bool test(const std::size_t bit) const { return ((m_bs >> bit) & 1) == 1; }
operator T&() { return m_bs; }
operator const T&() const { return m_bs; }
constexpr T as_uint() const { return m_bs; }
constexpr bool all() const { return *this == all_bits(); }
/*
* And all bits set with compressed bits from b
*
* Example: b = {b3,b2,b1,b0}
* v = {v7, 0, v5, 0, v3, v2, 0, 0}
* Returns {v7 & b3, 0, v5 & b2, 0, v3 & b1, v2 & b0, 0, 0}
*/
sbitset expand_and(sbitset b) const
{
sbitset ret;
T v( m_bs);
for (size_t i = 0; v != 0; v = v >> 1, ++i)
{
if (v & 1)
{
if (b.test(0))
ret.set(i);
b = b >> 1;
}
}
return ret;
}
static constexpr sbitset all_bits() { return sbitset(~static_cast<T>(0)); }
static constexpr sbitset no_bits() { return sbitset(static_cast<T>(0)); }
private:
T m_bs;
};
// ----------------------------------------------------------------------------------------
// Truthtable parsing ....
// ----------------------------------------------------------------------------------------
//static const uint_least64_t all_set = ~(static_cast<uint_least64_t>(0));
using tt_bitset = sbitset<uint_least64_t>;
struct packed_int
{
template<typename C>
packed_int(C *data)
packed_int(void *data, std::size_t bits)
: m_data(data)
, m_size(sizeof(C))
, m_size(bits)
{}
void set(const size_t pos, const uint_least64_t val)
{
switch (m_size)
{
case 1: static_cast<uint_least8_t *>(m_data)[pos] = static_cast<uint_least8_t>(val); break;
case 2: static_cast<uint_least16_t *>(m_data)[pos] = static_cast<uint_least16_t>(val); break;
case 4: static_cast<uint_least32_t *>(m_data)[pos] = static_cast<uint_least32_t>(val); break;
case 8: static_cast<uint_least64_t *>(m_data)[pos] = static_cast<uint_least64_t>(val); break;
case 8: static_cast<uint_least8_t *>(m_data)[pos] = static_cast<uint_least8_t>(val); break;
case 16: static_cast<uint_least16_t *>(m_data)[pos] = static_cast<uint_least16_t>(val); break;
case 32: static_cast<uint_least32_t *>(m_data)[pos] = static_cast<uint_least32_t>(val); break;
case 64: static_cast<uint_least64_t *>(m_data)[pos] = static_cast<uint_least64_t>(val); break;
default: { }
}
}
@ -43,37 +113,25 @@ namespace netlist
{
switch (m_size)
{
case 1: return static_cast<uint_least8_t *>(m_data)[pos];
case 2: return static_cast<uint_least16_t *>(m_data)[pos];
case 4: return static_cast<uint_least32_t *>(m_data)[pos];
case 8: return static_cast<uint_least64_t *>(m_data)[pos];
case 8: return static_cast<uint_least8_t *>(m_data)[pos];
case 16: return static_cast<uint_least16_t *>(m_data)[pos];
case 32: return static_cast<uint_least32_t *>(m_data)[pos];
case 64: return static_cast<uint_least64_t *>(m_data)[pos];
default:
return 0; //should never happen
}
}
uint_least64_t adjust(uint_least64_t val) const
{
switch (m_size)
{
case 1: return static_cast<uint_least8_t >(val);
case 2: return static_cast<uint_least16_t>(val);
case 4: return static_cast<uint_least32_t>(val);
case 8: return static_cast<uint_least64_t>(val);
default:
return 0; //should never happen
}
}
uint_least64_t mask() const { return (static_cast<uint_least64_t>(1) << m_size) - 1; }
private:
void *m_data;
size_t m_size;
};
static const uint_least64_t one64 = static_cast<uint_least64_t>(1);
struct truthtable_desc_t
struct truthtable_parser
{
truthtable_desc_t(unsigned NO, unsigned NI, bool *initialized,
truthtable_parser(unsigned NO, unsigned NI, bool *initialized,
packed_int outs, uint_least8_t *timing, netlist_time *timing_nt)
: m_NO(NO), m_NI(NI), m_initialized(initialized),
m_outs(outs), m_timing(timing), m_timing_nt(timing_nt),
@ -82,15 +140,13 @@ namespace netlist
{
}
void setup(const std::vector<pstring> &desc, uint_least64_t disabled_ignore);
void parse(const std::vector<pstring> &desc, uint_least64_t disabled_ignore);
private:
void help(unsigned cur, std::vector<pstring> list,
uint_least64_t state, uint_least64_t val, std::vector<uint_least8_t> &timing_index);
static unsigned count_bits(uint_least64_t v);
static uint_least64_t set_bits(uint_least64_t v, uint_least64_t b);
uint_least64_t get_ignored_simple(uint_least64_t i);
uint_least64_t get_ignored_extended(uint_least64_t i);
void parseline(unsigned cur, std::vector<pstring> list,
tt_bitset state, uint_least64_t val, std::vector<uint_least8_t> &timing_index);
tt_bitset calculate_ignored_inputs(tt_bitset i);
unsigned m_NO;
unsigned m_NI;
@ -106,30 +162,16 @@ namespace netlist
};
template<unsigned m_NI, unsigned m_NO>
template <class C>
nld_truthtable_t<m_NI, m_NO>::nld_truthtable_t(C &owner, const pstring &name, const logic_family_desc_t *fam,
truthtable_t *ttp, const pstring *desc)
: device_t(owner, name)
, m_fam(*this, fam)
, m_ign(*this, "m_ign", 0)
, m_active(*this, "m_active", 1)
, m_ttp(ttp)
{
while (*desc != "" )
{
m_desc.push_back(*desc);
desc++;
}
init();
}
// ----------------------------------------------------------------------------------------
// Truthtable class ....
// ----------------------------------------------------------------------------------------
template<unsigned m_NI, unsigned m_NO>
void NETLIB_NAME(truthtable_t)<m_NI, m_NO>::init()
template<std::size_t m_NI, std::size_t m_NO>
void NETLIB_NAME(truthtable_t)<m_NI, m_NO>::init(const std::vector<pstring> &desc)
{
set_hint_deactivate(true);
pstring header = m_desc[0];
pstring header = desc[0];
std::vector<pstring> io(plib::psplit(header,"|"));
// checks
@ -151,7 +193,7 @@ namespace netlist
}
// Connect output "Q" to input "_Q" if this exists
// This enables timed state without having explicit state ....
uint_least64_t disabled_ignore = 0;
tt_bitset disabled_ignore = 0;
for (std::size_t i=0; i < m_NO; i++)
{
pstring tmp = "_" + out[i];
@ -159,19 +201,19 @@ namespace netlist
if (idx != plib::container::npos)
{
connect(m_Q[i], m_I[idx]);
// disable ignore for this inputs altogether.
// disable ignore for theses inputs altogether.
// FIXME: This shouldn't be necessary
disabled_ignore |= (one64 << idx);
disabled_ignore.set(idx);
}
}
m_ign = 0;
truthtable_desc_t desc(m_NO, m_NI, &m_ttp->m_initialized,
packed_int(m_ttp->m_outs),
truthtable_parser desc_s(m_NO, m_NI, &m_ttp->m_initialized,
packed_int(m_ttp->m_outs, sizeof(m_ttp->m_outs[0]) * 8),
m_ttp->m_timing, m_ttp->m_timing_nt);
desc.setup(m_desc, disabled_ignore * 0);
desc_s.parse(desc, disabled_ignore * 0);
#if 0
printf("%s\n", name().c_str());
for (int j=0; j < m_size; j++)
@ -182,11 +224,6 @@ namespace netlist
#endif
}
// ----------------------------------------------------------------------------------------
// Truthtable class ....
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Truthtable factory ....
// ----------------------------------------------------------------------------------------
@ -209,96 +246,71 @@ namespace netlist
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)
tt_bitset truthtable_parser::calculate_ignored_inputs(tt_bitset state)
{
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)
// Determine all inputs which may be ignored ...
tt_bitset ignore = 0;
for (std::size_t j=0; j<m_NI; j++)
{
ret |= ((b&1)<<i);
b = b >> 1;
// if changing the input directly doesn't change outputs we can ignore
if (m_outs[state] == m_outs[tt_bitset(state).set(j)])
ignore.set(j);
}
}
return ret;
}
uint_least64_t truthtable_desc_t::get_ignored_simple(uint_least64_t i)
{
uint_least64_t m_enable = 0;
for (uint_least64_t j=0; j<m_size; j++)
{
if (m_outs[j] != m_outs[i])
/* Check all permutations of ign
* We have to remove those where the ignored inputs
* may change the output
*/
tt_bitset bits = tt_bitset().set(ignore.count());
std::vector<bool> t(bits);
// loop over all combinations of bits set in ignore
for (uint_least64_t j=1; j < bits; j++)
{
m_enable |= (i ^ j);
}
}
return m_enable ^ (m_size - 1);
}
tt_bitset tign = ignore.expand_and(j);
t[j] = false;
tt_bitset bitsk = tt_bitset().set(tign.count());
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 (std::size_t j=0; j<m_NI; j++)
{
if (m_outs[state] == m_outs[state ^ (one64 << j)])
ignore |= (one64 << j);
}
/* Check all permutations of ign
* We have to remove those where the ignored inputs
* may change the output
*/
uint_least64_t bits = (one64 << count_bits(ignore));
std::vector<bool> t(bits);
// now loop over all combinations of the bits set currently set
for (size_t j=1; j<bits; j++)
{
uint_least64_t tign = set_bits(ignore, j);
t[j] = 0;
uint_least64_t bitsk=(one64 << count_bits(tign));
for (uint_least64_t k=0; k<bitsk; k++)
{
uint_least64_t b=set_bits(tign, k);
if (m_outs[state] != m_outs[(state & ~tign) | b])
for (uint_least64_t k=0; k < bitsk; k++)
{
t[j] = 1;
break;
tt_bitset b = tign.expand_and(k);
// will any of the inputs ignored change the output if changed?
if (m_outs[state] != m_outs[(state & tign.invert()) | b])
{
t[j] = true;
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))
/* find the ignore mask without potential for change with the most bits */
size_t jb=0;
tt_bitset jm=0;
for (uint_least64_t j=1; j<bits; j++)
{
jb = nb;
jm = j;
tt_bitset bj(j);
size_t nb = bj.count();
if ((t[j] == false) && (nb>jb))
{
jb = nb;
jm = bj;
}
}
return ignore.expand_and(jm);
}
return set_bits(ignore, jm);
}
// ----------------------------------------------------------------------------------------
// desc
// parseline
// ----------------------------------------------------------------------------------------
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)
void truthtable_parser::parseline(unsigned cur, std::vector<pstring> list,
tt_bitset state, uint_least64_t val, std::vector<uint_least8_t> &timing_index)
{
pstring elem = list[cur].trim();
uint_least64_t start = 0;
@ -323,26 +335,28 @@ void truthtable_desc_t::help(unsigned cur, std::vector<pstring> list,
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);
tt_bitset nstate = state;
if (i==1)
nstate.set(cur);
if (cur < m_num_bits - 1)
{
help(cur + 1, list, nstate, val, timing_index);
parseline(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)
if (m_outs[nstate] != m_outs.mask() && 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) );
.x(nstate.as_uint(),"04")(m_outs[nstate])(val) );
m_outs.set(nstate, val);
for (unsigned j=0; j<m_NO; j++)
for (std::size_t 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)
void truthtable_parser::parse(const std::vector<pstring> &truthtable, uint_least64_t disabled_ignore)
{
unsigned line = 0;
@ -355,7 +369,7 @@ void truthtable_desc_t::setup(const std::vector<pstring> &truthtable, uint_least
line++;
for (unsigned j=0; j < m_size; j++)
m_outs.set(j, all_set);
m_outs.set(j, tt_bitset::all_bits());
for (int j=0; j < 16; j++)
m_timing_nt[j] = netlist_time::zero();
@ -372,14 +386,19 @@ void truthtable_desc_t::setup(const std::vector<pstring> &truthtable, uint_least
std::vector<pstring> times(plib::psplit(io[2], ","));
nl_assert_always(times.size() == m_NO, "timing count not matching");
uint_least64_t val = 0;
tt_bitset val = 0;
std::vector<uint_least8_t> tindex;
/*
* FIXME: evaluation of outputs should be done in parseline to
* enable the use of inputs for output values, i.e. "I1" or "~I1"
* in addition to "0" and "1".
*/
for (unsigned j=0; j<m_NO; j++)
{
pstring outs = out[j].trim();
if (outs.equals("1"))
val = val | (one64 << j);
val.set(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()));
@ -390,7 +409,7 @@ void truthtable_desc_t::setup(const std::vector<pstring> &truthtable, uint_least
tindex.push_back(k); //[j] = k;
}
help(0, inout, 0 , val, tindex);
parseline(0, inout, 0 , val, tindex);
if (line < truthtable.size())
ttline = truthtable[line];
else
@ -398,37 +417,34 @@ void truthtable_desc_t::setup(const std::vector<pstring> &truthtable, uint_least
line++;
}
// determine ignore
std::vector<uint_least64_t> ign(m_size, all_set);
// determine ignore mask by looping over all input combinations
std::vector<tt_bitset> ign(m_size);
for (tt_bitset &x : ign)
x.set();
for (uint_least64_t i=0; i<m_size; i++)
for (uint_least64_t i=0; i < m_size; i++)
{
if (ign[i] == all_set)
if (ign[i].all()) // not yet visited
{
uint_least64_t tign;
if ((0))
{
tign = get_ignored_simple(i);
ign[i] = tign;
}
else
{
tign = get_ignored_extended(i);
tt_bitset tign = calculate_ignored_inputs(i);
ign[i] = tign;
/* don't need to recalculate similar ones */
uint_least64_t bitsk=(one64 << 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;
}
ign[i] = tign;
/* don't need to recalculate similar ones */
tt_bitset bitsk;
bitsk.set(tign.count());
for (uint_least64_t k=0; k < bitsk; k++)
{
tt_bitset b = tign.expand_and(k);
ign[(i & tign.invert()) | b] = tign;
}
}
}
for (size_t i=0; i<m_size; i++)
{
if (m_outs[i] == m_outs.adjust(all_set))
if (m_outs[i] == m_outs.mask())
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));;
}
@ -452,7 +468,8 @@ netlist_base_factory_truthtable_t::~netlist_base_factory_truthtable_t()
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)
ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s); \
ENTRYY(n, 7, s); ENTRYY(n, 8, s)
void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile)
{

View File

@ -23,7 +23,7 @@
: nld_truthtable_t<nIN, nOUT>(owner, name, family_TTL(), &m_ttbl, m_desc) { } \
private: \
static truthtable_t m_ttbl; \
static const pstring m_desc[]; \
static std::vector<pstring> m_desc; \
}
@ -49,15 +49,18 @@ namespace netlist
template<> struct uint_for_size<4> { typedef uint_least32_t type; };
template<> struct uint_for_size<8> { typedef uint_least64_t type; };
template<unsigned m_NI, unsigned m_NO>
template<std::size_t m_NI, std::size_t m_NO>
NETLIB_OBJECT(truthtable_t)
{
private:
detail::family_setter_t m_fam;
public:
static constexpr int m_num_bits = m_NI;
static constexpr int m_size = (1 << (m_num_bits));
typedef typename uint_for_size<need_bytes_for_bits<m_NO + m_NI>::value>::type type_t;
static constexpr std::size_t m_num_bits = m_NI;
static constexpr std::size_t m_size = (1 << (m_num_bits));
static constexpr type_t m_outmask = ((1 << m_NO) - 1);
struct truthtable_t
{
@ -65,15 +68,11 @@ namespace netlist
: m_initialized(false)
{}
bool m_initialized;
typename uint_for_size<need_bytes_for_bits<m_NO + m_NI>::value>::type m_outs[m_size];
type_t m_outs[m_size];
uint_least8_t m_timing[m_size * m_NO];
netlist_time m_timing_nt[16];
};
template <class C>
nld_truthtable_t(C &owner, const pstring &name, const logic_family_desc_t *fam,
truthtable_t *ttp, const pstring *desc);
template <class C>
nld_truthtable_t(C &owner, const pstring &name, const logic_family_desc_t *fam,
truthtable_t *ttp, const std::vector<pstring> &desc)
@ -83,11 +82,10 @@ namespace netlist
, m_active(*this, "m_active", 1)
, m_ttp(ttp)
{
m_desc = desc;
init();
init(desc);
}
void init();
void init(const std::vector<pstring> &desc);
NETLIB_RESETI()
{
@ -105,7 +103,6 @@ namespace netlist
process<true>();
}
public:
void inc_active() NL_NOEXCEPT override
{
if (m_NI > 1)
@ -132,8 +129,6 @@ namespace netlist
}
}
//logic_input_t m_I[m_NI];
//logic_output_t m_Q[m_NO];
plib::uninitialised_array_t<logic_input_t, m_NI> m_I;
plib::uninitialised_array_t<logic_output_t, m_NO> m_Q;
@ -146,69 +141,78 @@ namespace netlist
{
netlist_time mt = netlist_time::zero();
uint_least64_t state = 0;
type_t nstate = 0;
if (m_NI > 1)
{
auto ign = m_ign;
type_t ign = m_ign;
if (!doOUT)
for (std::size_t i = 0; i < m_NI; i++)
{
m_I[i].activate();
state |= (m_I[i]() << i);
nstate |= (m_I[i]() << i);
mt = std::max(this->m_I[i].net().time(), mt);
}
else
for (std::size_t i = 0; i < m_NI; ign >>= 1, i++)
for (std::size_t i = 0; i < m_NI; i++)
{
if ((ign & 1))
m_I[i].activate();
state |= (m_I[i]() << i);
nstate |= (m_I[i]() << i);
ign >>= 1;
}
}
else
{
if (!doOUT)
for (std::size_t i = 0; i < m_NI; i++)
{
state |= (m_I[i]() << i);
mt = std::max(this->m_I[i].net().time(), mt);
}
{
nstate |= m_I[0]();
mt = std::max(this->m_I[0].net().time(), mt);
}
else
for (std::size_t i = 0; i < m_NI; i++)
state |= (m_I[i]() << i);
nstate |= m_I[0]();
}
auto nstate = state;
const auto outstate = m_ttp->m_outs[nstate];
const auto out = outstate & ((1 << m_NO) - 1);
const type_t outstate = m_ttp->m_outs[nstate];
type_t out = outstate & m_outmask;
m_ign = outstate >> m_NO;
const auto timebase = nstate * m_NO;
const std::size_t timebase = nstate * m_NO;
if (doOUT)
{
for (std::size_t i = 0; i < m_NO; i++)
m_Q[i].push((out >> i) & 1, m_ttp->m_timing_nt[m_ttp->m_timing[timebase + i]]);
auto *t = &m_ttp->m_timing[timebase];
for (std::size_t i = 0; i < m_NO; ++i)
{
m_Q[i].push(out & 1, m_ttp->m_timing_nt[*t]);
++t;
out >>= 1;
}
}
else
for (std::size_t i = 0; i < m_NO; i++)
m_Q[i].net().set_Q_time((out >> i) & 1, mt + m_ttp->m_timing_nt[m_ttp->m_timing[timebase + i]]);
{
auto *t = &m_ttp->m_timing[timebase];
for (std::size_t i = 0; i < m_NO; ++i)
{
m_Q[i].net().set_Q_time(out & 1, mt + m_ttp->m_timing_nt[*t]);
++t;
out >>= 1;
}
}
if (m_NI > 1)
{
auto ign(m_ign);
for (std::size_t i = 0; ign != 0; ign >>= 1, i++)
type_t ign(m_ign);
for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I)
if (ign & 1)
m_I[i].inactivate();
I->inactivate();
}
}
/* FIXME: check width */
state_var_u32 m_ign;
state_var<type_t> m_ign;
state_var_s32 m_active;
truthtable_t * m_ttp;
std::vector<pstring> m_desc;
};
class netlist_base_factory_truthtable_t : public factory::element_t

View File

@ -29,7 +29,8 @@
// ----------------------------------------------------------------------------------------
/*! netlist_sig_t is the type used for logic signals. */
using netlist_sig_t = std::uint32_t;
//using netlist_sig_t = std::uint32_t;
using netlist_sig_t = std::uint8_t;
//============================================================
// MACROS / New Syntax

View File

@ -31,7 +31,13 @@
*/
#define USE_MEMPOOL (0)
#define USE_TRUTHTABLE (1)
/*
* FIXME: Using truthtable is a lot slower than the explicit device
* in breakout. Performance drops by 20%. This can be fixed by
* setting param USE_DEACTIVATE for the device.
*/
#define USE_TRUTHTABLE_7448 (1)
// How many times do we try to resolve links (connections)
#define NL_MAX_LINK_RESOLVE_LOOPS (100)

View File

@ -28,6 +28,10 @@ template <class C, std::size_t N>
class uninitialised_array_t
{
public:
typedef C* iterator;
typedef const C* const_iterator;
uninitialised_array_t()
{
}
@ -38,7 +42,7 @@ public:
(*this)[i].~C();
}
size_t size() { return N; }
size_t size() const { return N; }
C& operator[](const std::size_t &index) noexcept
{
@ -57,6 +61,15 @@ public:
new (&m_buf[index]) C(std::forward<Args>(args)...);
}
iterator begin() const noexcept { return reinterpret_cast<iterator>(&m_buf[0]); }
iterator end() const noexcept { return reinterpret_cast<iterator>(&m_buf[N]); }
iterator begin() noexcept { return reinterpret_cast<iterator>(&m_buf[0]); }
iterator end() noexcept { return reinterpret_cast<iterator>(&m_buf[N]); }
const_iterator cbegin() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[0]); }
const_iterator cend() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[N]); }
protected:
private: