Refactoring and bug fixes. (nw)

This commit is contained in:
couriersud 2019-01-10 20:55:59 +01:00
parent 2416e7933c
commit e8fed7f532
10 changed files with 147 additions and 91 deletions

View File

@ -98,10 +98,14 @@ namespace netlist
ENTRYX(74123_dip, TTL_74123_DIP, "")
ENTRYX_N(74153)
ENTRYX_N(74153_dip)
ENTRYX(74161, TTL_74161, "+A,+B,+C,+D,+CLRQ,+LOADQ,+CLK,+ENABLEP,+ENABLET")
ENTRYX_N(74161)
ENTRYX_N(74161_dip)
ENTRYX(74164, TTL_74164, "+A,+B,+CLRQ,+CLK")
ENTRYX(74164_dip, TTL_74164_DIP, "")
ENTRYX(74165, TTL_74165, "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H")
ENTRYX(74165_dip, TTL_74165_DIP, "")
ENTRYX(74166, TTL_74166, "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,+CLRQ")
ENTRYX(74166_dip, TTL_74166_DIP, "")
ENTRYX(74174, TTL_74174, "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ")
ENTRYX(74175, TTL_74175, "+CLK,+D1,+D2,+D3,+D4,+CLRQ")
ENTRYX(74192, TTL_74192, "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
@ -134,10 +138,6 @@ namespace netlist
ENTRYX(r2r_dac, R2R_DAC, "VIN,R,N")
ENTRYX(tristate, TTL_TRISTATE, "+CEQ1,+D1,+CEQ2,+D2")
ENTRYX(tristate3, TTL_TRISTATE3, "")
ENTRYX(74161_dip, TTL_74161_DIP, "")
ENTRYX(74164_dip, TTL_74164_DIP, "")
ENTRYX(74165_dip, TTL_74165_DIP, "")
ENTRYX(74166_dip, TTL_74166_DIP, "")
ENTRYX(74174_dip, TTL_74174_DIP, "")
ENTRYX(74175_dip, TTL_74175_DIP, "")
ENTRYX(74192_dip, TTL_74192_DIP, "")

View File

@ -126,8 +126,8 @@ namespace netlist
m_RCO.push(tRippleCarryOut, NLTIME_FROM_NS(20)); //FIXME
}
NETLIB_DEVICE_IMPL_DEPRECATED(74161)
NETLIB_DEVICE_IMPL_DEPRECATED(74161_dip)
NETLIB_DEVICE_IMPL(74161, "TTL_74161", "+A,+B,+C,+D,+CLRQ,+LOADQ,+CLK,+ENABLEP,+ENABLET")
NETLIB_DEVICE_IMPL(74161_dip, "TTL_74161_DIP", "")
} //namespace devices
} // namespace netlist

View File

@ -12,6 +12,14 @@ namespace netlist
{
namespace devices
{
/* FIXME: This should be a single device, i.e. one tristate buffer only.
*
* FIXME: Implement tristate output.
*
*/
NETLIB_OBJECT(74365)
{
NETLIB_CONSTRUCTOR(74365)

View File

@ -16,14 +16,16 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(7483)
, m_C0(*this, "C0")
, m_A1(*this, "A1")
, m_A2(*this, "A2")
, m_A3(*this, "A3")
, m_A4(*this, "A4")
, m_B1(*this, "B1")
, m_B2(*this, "B2")
, m_B3(*this, "B3")
, m_B4(*this, "B4")
, m_A1(*this, "A1", NETLIB_DELEGATE(7483, upd_a))
, m_A2(*this, "A2", NETLIB_DELEGATE(7483, upd_a))
, m_A3(*this, "A3", NETLIB_DELEGATE(7483, upd_a))
, m_A4(*this, "A4", NETLIB_DELEGATE(7483, upd_a))
, m_B1(*this, "B1", NETLIB_DELEGATE(7483, upd_b))
, m_B2(*this, "B2", NETLIB_DELEGATE(7483, upd_b))
, m_B3(*this, "B3", NETLIB_DELEGATE(7483, upd_b))
, m_B4(*this, "B4", NETLIB_DELEGATE(7483, upd_b))
, m_a(*this, "m_a", 0)
, m_b(*this, "m_b", 0)
, m_lastr(*this, "m_lastr", 0)
, m_S1(*this, "S1")
, m_S2(*this, "S2")
@ -34,6 +36,8 @@ namespace netlist
}
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_HANDLERI(upd_a);
NETLIB_HANDLERI(upd_b);
protected:
logic_input_t m_C0;
@ -46,7 +50,9 @@ namespace netlist
logic_input_t m_B3;
logic_input_t m_B4;
state_var<unsigned> m_lastr;
state_var_u8 m_a;
state_var_u8 m_b;
state_var_u8 m_lastr;
logic_output_t m_S1;
logic_output_t m_S2;
@ -87,12 +93,21 @@ namespace netlist
m_lastr = 0;
}
NETLIB_UPDATE(7483)
NETLIB_HANDLER(7483, upd_a)
{
unsigned a = (m_A1() << 0) | (m_A2() << 1) | (m_A3() << 2) | (m_A4() << 3);
unsigned b = (m_B1() << 0) | (m_B2() << 1) | (m_B3() << 2) | (m_B4() << 3);
m_a = (m_A1() << 0) | (m_A2() << 1) | (m_A3() << 2) | (m_A4() << 3);
NETLIB_NAME(7483)::update();
}
unsigned r = a + b + m_C0();
NETLIB_HANDLER(7483, upd_b)
{
m_b = (m_B1() << 0) | (m_B2() << 1) | (m_B3() << 2) | (m_B4() << 3);
NETLIB_NAME(7483)::update();
}
inline NETLIB_UPDATE(7483)
{
uint8_t r = m_a + m_b + m_C0();
if (r != m_lastr)
{

View File

@ -13,9 +13,9 @@ namespace netlist
namespace devices
{
static constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
static constexpr netlist_time out_delay2 = NLTIME_FROM_NS(36);
static constexpr netlist_time out_delay3 = NLTIME_FROM_NS(54);
static constexpr const netlist_time out_delay = NLTIME_FROM_NS(18);
static constexpr const netlist_time out_delay2 = NLTIME_FROM_NS(36);
static constexpr const netlist_time out_delay3 = NLTIME_FROM_NS(54);
NETLIB_OBJECT(7493)
{
@ -51,10 +51,11 @@ namespace netlist
{
//if (m_reset)
{
++m_bcd &= static_cast<std::uint8_t>(0x07);
m_QD.push((m_bcd >> 2) & 1, out_delay3);
m_QC.push((m_bcd >> 1) & 1, out_delay2);
m_QB.push(m_bcd & 1, out_delay);
//++m_bcd &= 0x07;
auto cnt = (++m_bcd &= 0x07);
m_QD.push((cnt >> 2) & 1, out_delay3);
m_QC.push((cnt >> 1) & 1, out_delay2);
m_QB.push(cnt & 1, out_delay);
}
}

View File

@ -122,8 +122,18 @@ namespace netlist
}
}
uint_least64_t mask() const { return static_cast<uint_least64_t>(-1); }
uint_least64_t mask() const
{
switch (m_size)
{
case 8: return static_cast<uint_least8_t>(-1);
case 16: return static_cast<uint_least16_t>(-1);
case 32: return static_cast<uint_least32_t>(-1);
case 64: return static_cast<uint_least64_t>(-1);
default:
return 0; //should never happen
}
}
private:
void *m_data;
size_t m_size;
@ -134,7 +144,7 @@ namespace netlist
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),
m_out_state(outs), m_timing(timing), m_timing_nt(timing_nt),
m_num_bits(m_NI),
m_size(1 << (m_num_bits))
{
@ -151,7 +161,7 @@ namespace netlist
unsigned m_NO;
unsigned m_NI;
bool *m_initialized;
packed_int m_outs;
packed_int m_out_state;
uint_least8_t *m_timing;
netlist_time *m_timing_nt;
@ -178,8 +188,8 @@ namespace netlist
nl_assert_always(io.size() == 2, "too many '|'");
std::vector<pstring> inout(plib::psplit(io[0], ","));
nl_assert_always(inout.size() == m_num_bits, "bitcount wrong");
std::vector<pstring> out(plib::psplit(io[1], ","));
nl_assert_always(out.size() == m_NO, "output count wrong");
std::vector<pstring> outputs(plib::psplit(io[1], ","));
nl_assert_always(outputs.size() == m_NO, "output count wrong");
for (std::size_t i=0; i < m_NI; i++)
{
@ -188,38 +198,23 @@ namespace netlist
}
for (std::size_t i=0; i < m_NO; i++)
{
out[i] = plib::trim(out[i]);
m_Q.emplace(i, *this, out[i]);
}
// Connect output "Q" to input "_Q" if this exists
// This enables timed state without having explicit state ....
tt_bitset disabled_ignore = 0;
for (std::size_t i=0; i < m_NO; i++)
{
pstring tmp = "_" + out[i];
outputs[i] = plib::trim(outputs[i]);
m_Q.emplace(i, *this, outputs[i]);
// Connect output "Q" to input "_Q" if this exists
// This enables timed state without having explicit state ....
pstring tmp = "_" + outputs[i];
const std::size_t idx = plib::container::indexof(inout, tmp);
if (idx != plib::container::npos)
{
connect(m_Q[i], m_I[idx]);
// disable ignore for theses inputs altogether.
// FIXME: This shouldn't be necessary
disabled_ignore.set(idx);
}
}
m_ign = 0;
#if 0
for (size_t i=0; i<m_size; i++)
{
m_ttp.m_outs[i] &= ~(disabled_ignore << m_NO);
}
#endif
#if 0
printf("%s\n", name().c_str());
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 * m_NO + 0]);
printf("%05x %04x %04x %04x\n", j, m_ttp->m_out_state[j] & ((1 << m_NO)-1),
m_ttp->m_out_state[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
@ -242,8 +237,8 @@ namespace netlist
{
typedef nld_truthtable_t<m_NI, m_NO> tt_type;
truthtable_parser desc_s(m_NO, m_NI, &m_ttbl.m_initialized,
packed_int(m_ttbl.m_outs, sizeof(m_ttbl.m_outs[0]) * 8),
m_ttbl.m_timing, m_ttbl.m_timing_nt);
packed_int(m_ttbl.m_out_state, sizeof(m_ttbl.m_out_state[0]) * 8),
m_ttbl.m_timing_index, m_ttbl.m_timing_nt);
desc_s.parse(m_desc);
return plib::owned_ptr<device_t>::Create<tt_type>(anetlist, name, m_family, m_ttbl, m_desc);
@ -259,7 +254,7 @@ namespace netlist
for (std::size_t j=0; j<m_NI; j++)
{
// if changing the input directly doesn't change outputs we can ignore
if (m_outs[state] == m_outs[tt_bitset(state).set(j)])
if (m_out_state[state] == m_out_state[tt_bitset(state).set(j)])
ignore.set(j);
}
@ -285,7 +280,7 @@ namespace netlist
{
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])
if (m_out_state[state] != m_out_state[(state & tign.invert()) | b])
{
t[j] = true;
break;
@ -352,10 +347,10 @@ void truthtable_parser::parseline(unsigned cur, std::vector<pstring> list,
else
{
// cutoff previous inputs and outputs for ignore
if (m_outs[nstate] != m_outs.mask() && m_outs[nstate] != val)
nl_exception(plib::pfmt("Error in truthtable: State {1:04} already set, {2} != {3}\n")
.x(nstate.as_uint())(m_outs[nstate])(val) );
m_outs.set(nstate, val);
if (m_out_state[nstate] != m_out_state.mask() && m_out_state[nstate] != val)
throw nl_exception(plib::pfmt("Error in truthtable: State {1:04} already set, {2} != {3}\n")
.x(nstate.as_uint())(m_out_state[nstate])(val) );
m_out_state.set(nstate, val);
for (std::size_t j=0; j<m_NO; j++)
m_timing[nstate * m_NO + j] = timing_index[j];
}
@ -375,7 +370,7 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
line++;
for (unsigned j=0; j < m_size; j++)
m_outs.set(j, tt_bitset::all_bits());
m_out_state.set(j, tt_bitset::all_bits());
for (int j=0; j < 16; j++)
m_timing_nt[j] = netlist_time::zero();
@ -451,9 +446,9 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
}
for (size_t i=0; i<m_size; i++)
{
if (m_outs[i] == m_outs.mask())
if (m_out_state[i] == m_out_state.mask())
throw nl_exception(plib::pfmt("truthtable: found element not set {1}\n").x(i) );
m_outs.set(i, m_outs[i] | (ign[i] << m_NO));;
m_out_state.set(i, m_out_state[i] | (ign[i] << m_NO));;
}
*m_initialized = true;

View File

@ -58,6 +58,32 @@ namespace netlist
template<> struct uint_for_size<8> { typedef uint_least64_t type; };
#endif
template<std::size_t NUM, typename R>
struct aa
{
template<typename T>
R f(T &arr, const R ign)
{
R r = aa<NUM-1, R>().f(arr, ign);
if (ign & (1 << (NUM-1)))
arr[NUM-1].activate();
return r | (arr[NUM-1]() << (NUM-1));
}
};
template<>
template<typename R>
struct aa<1, R>
{
template<typename T>
R f(T &arr, const R ign)
{
if ((ign & 1))
arr[0].activate();
return arr[0]();
}
};
template<std::size_t m_NI, std::size_t m_NO>
NETLIB_OBJECT(truthtable_t)
{
@ -70,17 +96,17 @@ namespace netlist
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;
static constexpr const std::size_t m_min_inputs_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];
type_t m_out_state[m_size];
uint_least8_t m_timing_index[m_size * m_NO];
netlist_time m_timing_nt[16];
bool m_initialized;
};
template <class C>
@ -90,7 +116,7 @@ namespace netlist
: device_t(owner, name)
, m_fam(*this, fam)
, m_ign(*this, "m_ign", 0)
, m_active(*this, "m_active", 1)
, m_active_outputs(*this, "m_active_outputs", 1)
, m_ttp(ttp)
{
init(desc);
@ -100,13 +126,13 @@ namespace netlist
NETLIB_RESETI()
{
m_active = 0;
m_active_outputs = 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++;
m_active_outputs++;
}
NETLIB_UPDATEI()
@ -116,8 +142,8 @@ namespace netlist
void inc_active() NL_NOEXCEPT override
{
if (m_NI >= m_min_devices_for_deactivate)
if (++m_active == 1)
if (m_NI >= m_min_inputs_for_deactivate)
if (++m_active_outputs == 1)
{
process<false>();
}
@ -131,8 +157,8 @@ namespace netlist
* 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)
if (m_NI >= m_min_inputs_for_deactivate)
if (--m_active_outputs == 0)
{
for (std::size_t i = 0; i< m_NI; i++)
m_I[i].inactivate();
@ -153,9 +179,10 @@ namespace netlist
netlist_time mt(netlist_time::zero());
type_t nstate(0);
if (m_NI >= m_min_devices_for_deactivate)
if (m_NI >= m_min_inputs_for_deactivate)
{
type_t ign(m_ign);
#if 1
if (!doOUT)
for (std::size_t i = 0; i < m_NI; i++)
{
@ -173,6 +200,16 @@ namespace netlist
nstate |= (m_I[i]() << i);
ign >>= 1;
}
#else
if (!doOUT)
{
nstate = aa<m_NI, type_t>().f(m_I, ~0);
for (std::size_t i = 0; i < m_NI; i++)
mt = std::max(this->m_I[i].net().time(), mt);
}
else
nstate = aa<m_NI, type_t>().f(m_I, ign);
#endif
}
else
{
@ -189,13 +226,13 @@ namespace netlist
nstate |= (m_I[i]() << i);
}
const type_t outstate(m_ttp.m_outs[nstate]);
const type_t outstate(m_ttp.m_out_state[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 *t(&m_ttp.m_timing_index[timebase]);
const auto *tim = m_ttp.m_timing_nt;
if (doOUT)
@ -205,7 +242,7 @@ namespace netlist
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)
if (m_NI >= m_min_inputs_for_deactivate)
{
type_t ign(m_ign);
for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I)
@ -216,7 +253,7 @@ namespace netlist
/* FIXME: check width */
state_var<type_t> m_ign;
state_var_s32 m_active;
state_var_s32 m_active_outputs;
const truthtable_t &m_ttp;
};

View File

@ -796,7 +796,7 @@ detail::net_t::~net_t()
netlist().state().remove_save_items(this);
}
void detail::net_t::inc_active(core_terminal_t &term) NL_NOEXCEPT
void detail::net_t::add_to_active_list(core_terminal_t &term) NL_NOEXCEPT
{
const bool was_empty = m_list_active.empty();
m_list_active.push_front(&term);
@ -819,7 +819,7 @@ void detail::net_t::inc_active(core_terminal_t &term) NL_NOEXCEPT
}
}
void detail::net_t::dec_active(core_terminal_t &term) NL_NOEXCEPT
void detail::net_t::remove_from_active_list(core_terminal_t &term) NL_NOEXCEPT
{
m_list_active.remove(&term);
if (m_list_active.empty())

View File

@ -741,8 +741,8 @@ namespace netlist
std::size_t num_cons() const NL_NOEXCEPT { return m_core_terms.size(); }
void inc_active(core_terminal_t &term) NL_NOEXCEPT;
void dec_active(core_terminal_t &term) NL_NOEXCEPT;
void add_to_active_list(core_terminal_t &term) NL_NOEXCEPT;
void remove_from_active_list(core_terminal_t &term) NL_NOEXCEPT;
/* setup stuff */
@ -1396,7 +1396,7 @@ namespace netlist
if (!is_state(STATE_INP_PASSIVE))
{
set_state(STATE_INP_PASSIVE);
net().dec_active(*this);
net().remove_from_active_list(*this);
}
}
@ -1404,7 +1404,7 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
net().inc_active(*this);
net().add_to_active_list(*this);
set_state(STATE_INP_ACTIVE);
}
}
@ -1413,7 +1413,7 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
net().inc_active(*this);
net().add_to_active_list(*this);
set_state(STATE_INP_HL);
}
}
@ -1422,7 +1422,7 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
net().inc_active(*this);
net().add_to_active_list(*this);
set_state(STATE_INP_LH);
}
}

View File

@ -51,7 +51,7 @@ public:
const C& operator[](const std::size_t &index) const noexcept
{
return *reinterpret_cast<C *>(&m_buf[index]);
return *reinterpret_cast<const C *>(&m_buf[index]);
}
template<typename... Args>