netlist: next batch of explicit handlers.

This commit is contained in:
couriersud 2020-07-12 15:53:16 +02:00
parent 4fdb3edcfe
commit 985c0225d1
6 changed files with 228 additions and 192 deletions

View File

@ -12,11 +12,14 @@ namespace netlist
{
namespace devices
{
// FIXME: optimize clock input
NETLIB_OBJECT(CD4006)
{
NETLIB_CONSTRUCTOR_MODEL(CD4006, "CD4XXX")
, m_CLOCK(*this, "CLOCK")
, m_I(*this, {"D1", "D2", "D3", "D4"})
, m_CLOCK(*this, "CLOCK", NETLIB_DELEGATE(inputs))
, m_I(*this, {"D1", "D2", "D3", "D4"}, NETLIB_DELEGATE(inputs))
, m_Q(*this, {"D1P4", "D1P4S", "D2P4", "D2P5", "D3P4", "D4P4", "D3P5"})
, m_d(*this, "m_d", 0)
, m_last_clock(*this, "m_last_clock", 0)
@ -24,7 +27,7 @@ namespace netlist
{
}
NETLIB_UPDATEI()
NETLIB_HANDLERI(inputs)
{
if (m_last_clock && !m_CLOCK())
{
@ -56,6 +59,10 @@ namespace netlist
}
}
NETLIB_UPDATEI()
{
inputs();
}
friend class NETLIB_NAME(CD4006_dip);
private:
logic_input_t m_CLOCK;

View File

@ -16,9 +16,9 @@ namespace netlist
NETLIB_OBJECT(CD4013)
{
NETLIB_CONSTRUCTOR_MODEL(CD4013, "CD4XXX")
, m_D(*this, "DATA")
, m_RESET(*this, "RESET")
, m_SET(*this, "SET")
, m_D(*this, "DATA", NETLIB_DELEGATE(inputs))
, m_RESET(*this, "RESET", NETLIB_DELEGATE(inputs))
, m_SET(*this, "SET", NETLIB_DELEGATE(inputs))
, m_CLK(*this, "CLOCK", NETLIB_DELEGATE(clk))
, m_Q(*this, "Q")
, m_QQ(*this, "QQ")
@ -28,9 +28,41 @@ namespace netlist
}
private:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_HANDLERI(clk);
NETLIB_RESETI()
{
m_CLK.set_state(logic_t::STATE_INP_LH);
m_D.set_state(logic_t::STATE_INP_ACTIVE);
m_nextD = 0;
}
NETLIB_UPDATEI()
{
inputs();
}
NETLIB_HANDLERI(inputs)
{
const auto set(m_SET());
const auto reset(m_RESET());
if ((set ^ 1) & (reset ^ 1))
{
m_D.activate();
m_nextD = m_D();
m_CLK.activate_lh();
}
else
{
newstate_setreset(set, reset);
m_CLK.inactivate();
m_D.inactivate();
}
}
NETLIB_HANDLERI(clk)
{
newstate_clk(m_nextD);
m_CLK.inactivate();
}
logic_input_t m_D;
logic_input_t m_RESET;
@ -92,37 +124,6 @@ namespace netlist
NETLIB_SUB(CD4013) m_B;
};
NETLIB_HANDLER(CD4013, clk)
{
newstate_clk(m_nextD);
m_CLK.inactivate();
}
NETLIB_UPDATE(CD4013)
{
const auto set(m_SET());
const auto reset(m_RESET());
if ((set ^ 1) & (reset ^ 1))
{
m_D.activate();
m_nextD = m_D();
m_CLK.activate_lh();
}
else
{
newstate_setreset(set, reset);
m_CLK.inactivate();
m_D.inactivate();
}
}
NETLIB_RESET(CD4013)
{
m_CLK.set_state(logic_t::STATE_INP_LH);
m_D.set_state(logic_t::STATE_INP_ACTIVE);
m_nextD = 0;
}
NETLIB_RESET(CD4013_dip)
{
}

View File

@ -16,7 +16,7 @@ namespace netlist
NETLIB_OBJECT(CD4020_sub)
{
NETLIB_CONSTRUCTOR_MODEL(CD4020_sub, "CD4XXX")
, m_IP(*this, "IP")
, m_IP(*this, "IP", NETLIB_DELEGATE(ip))
, m_Q(*this, {"Q1", "_Q2", "_Q3", "Q4", "Q5", "Q6", "Q7", "Q8", "Q9",
"Q10", "Q11", "Q12", "Q13", "Q14"})
, m_cnt(*this, "m_cnt", 0)
@ -30,7 +30,17 @@ namespace netlist
m_cnt = 0;
}
NETLIB_UPDATEI();
NETLIB_HANDLERI(ip)
{
++m_cnt;
m_cnt &= 0x3fff;
update_outputs(m_cnt);
}
NETLIB_UPDATEI()
{
ip();
}
public:
void update_outputs(const unsigned cnt) noexcept
@ -60,7 +70,7 @@ namespace netlist
{
NETLIB_CONSTRUCTOR_MODEL(CD4020, "CD4XXX")
, m_sub(*this, "sub")
, m_RESET(*this, "RESET")
, m_RESET(*this, "RESET", NETLIB_DELEGATE(inputs))
{
register_subalias("IP", m_sub.m_IP);
register_subalias("Q1", m_sub.m_Q[0]);
@ -78,35 +88,35 @@ namespace netlist
register_subalias("VDD", "sub.VDD");
register_subalias("VSS", "sub.VSS");
}
NETLIB_RESETI() { }
NETLIB_UPDATEI();
NETLIB_HANDLERI(inputs)
{
if (m_RESET())
{
m_sub.m_cnt = 0;
m_sub.m_IP.inactivate();
/* static */ const netlist_time reset_time = netlist_time::from_nsec(140);
m_sub.m_Q[0].push(0, reset_time);
for (std::size_t i=3; i<14; i++)
m_sub.m_Q[i].push(0, reset_time);
}
else
m_sub.m_IP.activate_hl();
}
NETLIB_UPDATEI()
{
inputs();
}
private:
NETLIB_SUB(CD4020_sub) m_sub;
logic_input_t m_RESET;
};
NETLIB_UPDATE(CD4020_sub)
{
++m_cnt;
m_cnt &= 0x3fff;
update_outputs(m_cnt);
}
NETLIB_UPDATE(CD4020)
{
if (m_RESET())
{
m_sub.m_cnt = 0;
m_sub.m_IP.inactivate();
/* static */ const netlist_time reset_time = netlist_time::from_nsec(140);
m_sub.m_Q[0].push(0, reset_time);
for (std::size_t i=3; i<14; i++)
m_sub.m_Q[i].push(0, reset_time);
}
else
m_sub.m_IP.activate_hl();
}
NETLIB_DEVICE_IMPL(CD4020, "CD4020", "")
NETLIB_DEVICE_IMPL_ALIAS(CD4020_WI, CD4020, "CD4020_WI", "+IP,+RESET,+VDD,+VSS")

View File

@ -11,13 +11,15 @@
namespace netlist { namespace devices {
// FIXME: tristate outputs?
NETLIB_OBJECT(CD4316_GATE)
{
NETLIB_CONSTRUCTOR_MODEL(CD4316_GATE, "CD4XXX")
, m_supply(*this, "VDD", "VSS")
, m_R(*this, "_R")
, m_S(*this, "S")
, m_E(*this, "E")
, m_S(*this, "S", NETLIB_DELEGATE(inputs))
, m_E(*this, "E", NETLIB_DELEGATE(inputs))
, m_base_r(*this, "BASER", nlconst::magic(45.0))
{
}
@ -27,18 +29,23 @@ namespace netlist { namespace devices {
m_R.set_R(plib::reciprocal(exec().gmin()));
}
NETLIB_UPDATEI()
NETLIB_HANDLERI(inputs)
{
m_R.change_state([this]()
{
if (m_S() && !m_E())
m_R.set_R(m_base_r());
else
m_R.set_R(plib::reciprocal(exec().gmin()));
if (m_S() && !m_E())
m_R.set_R(m_base_r());
else
m_R.set_R(plib::reciprocal(exec().gmin()));
}
, NLTIME_FROM_NS(1));
}
NETLIB_UPDATEI()
{
inputs();
}
private:
nld_power_pins m_supply;
analog::NETLIB_SUB(R_base) m_R;

View File

@ -15,13 +15,24 @@ namespace netlist
static constexpr const unsigned MAXCNT = 9;
// FIXME: Optimize
// FIXME: Timing
static constexpr const std::array<netlist_time, 4> delay =
{
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40)
};
NETLIB_OBJECT(74192)
{
NETLIB_CONSTRUCTOR(74192)
, m_CLEAR(*this, "CLEAR")
, m_LOADQ(*this, "LOADQ")
, m_CU(*this, "CU")
, m_CD(*this, "CD")
, m_CLEAR(*this, "CLEAR", NETLIB_DELEGATE(inputs))
, m_LOADQ(*this, "LOADQ", NETLIB_DELEGATE(inputs))
, m_CU(*this, "CU", NETLIB_DELEGATE(inputs))
, m_CD(*this, "CD", NETLIB_DELEGATE(inputs))
, m_cnt(*this, "m_cnt", 0)
, m_last_CU(*this, "m_last_CU", 0)
, m_last_CD(*this, "m_last_CD", 0)
@ -43,7 +54,10 @@ namespace netlist
m_last_CD = 0;
}
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
inputs();
}
friend class NETLIB_NAME(74192_dip);
private:
@ -66,6 +80,50 @@ namespace netlist
logic_input_t m_D;
nld_power_pins m_power_pins;
NETLIB_HANDLERI(inputs)
{
netlist_sig_t tCarry = 1;
netlist_sig_t tBorrow = 1;
if (m_CLEAR())
{
m_cnt = 0;
}
else if (!m_LOADQ())
{
m_cnt = read_ABCD();
}
else
{
if (m_CD() && !m_last_CU && m_CU())
{
if (++m_cnt > MAXCNT)
m_cnt = 0;
}
if (m_CU() && !m_last_CD && m_CD())
{
if (m_cnt > 0)
--m_cnt;
else
m_cnt = MAXCNT;
}
}
if (!m_CU() && (m_cnt == MAXCNT))
tCarry = 0;
if (!m_CD() && (m_cnt == 0))
tBorrow = 0;
m_last_CD = m_CD();
m_last_CU = m_CU();
for (std::size_t i=0; i<4; i++)
m_Q[i].push((m_cnt >> i) & 1, delay[i]);
m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME
m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME
}
NETLIB_HANDLERI(sub)
{
// FIXME: can use more optimization
@ -107,59 +165,6 @@ namespace netlist
NETLIB_SUB(74192) A;
};
// FIXME: Timing
static constexpr const std::array<netlist_time, 4> delay =
{
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40)
};
NETLIB_UPDATE(74192)
{
netlist_sig_t tCarry = 1;
netlist_sig_t tBorrow = 1;
if (m_CLEAR())
{
m_cnt = 0;
}
else if (!m_LOADQ())
{
m_cnt = read_ABCD();
}
else
{
if (m_CD() && !m_last_CU && m_CU())
{
if (++m_cnt > MAXCNT)
m_cnt = 0;
}
if (m_CU() && !m_last_CD && m_CD())
{
if (m_cnt > 0)
--m_cnt;
else
m_cnt = MAXCNT;
}
}
if (!m_CU() && (m_cnt == MAXCNT))
tCarry = 0;
if (!m_CD() && (m_cnt == 0))
tBorrow = 0;
m_last_CD = m_CD();
m_last_CU = m_CU();
for (std::size_t i=0; i<4; i++)
m_Q[i].push((m_cnt >> i) & 1, delay[i]);
m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME
m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME
}
NETLIB_DEVICE_IMPL(74192, "TTL_74192", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD,@VCC,@GND")
NETLIB_DEVICE_IMPL(74192_dip,"TTL_74192_DIP", "")

View File

@ -12,19 +12,31 @@ namespace netlist
{
namespace devices
{
static constexpr const unsigned MAXCNT = 15;
// FIXME: Timing
static constexpr const std::array<netlist_time, 4> delay =
{
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40)
};
// FIXME: Optimize!
NETLIB_OBJECT(74193)
{
NETLIB_CONSTRUCTOR(74193)
, m_A(*this, "A")
, m_B(*this, "B")
, m_C(*this, "C")
, m_D(*this, "D")
, m_CLEAR(*this, "CLEAR")
, m_LOADQ(*this, "LOADQ")
, m_CU(*this, "CU")
, m_CD(*this, "CD")
, m_A(*this, "A", NETLIB_DELEGATE(inputs))
, m_B(*this, "B", NETLIB_DELEGATE(inputs))
, m_C(*this, "C", NETLIB_DELEGATE(inputs))
, m_D(*this, "D", NETLIB_DELEGATE(inputs))
, m_CLEAR(*this, "CLEAR", NETLIB_DELEGATE(inputs))
, m_LOADQ(*this, "LOADQ", NETLIB_DELEGATE(inputs))
, m_CU(*this, "CU", NETLIB_DELEGATE(inputs))
, m_CD(*this, "CD", NETLIB_DELEGATE(inputs))
, m_cnt(*this, "m_cnt", 0)
, m_last_CU(*this, "m_last_CU", 0)
, m_last_CD(*this, "m_last_CD", 0)
@ -41,10 +53,58 @@ namespace netlist
m_last_CU = 0;
m_last_CD = 0;
}
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
inputs();
}
friend class NETLIB_NAME(74193_dip);
private:
NETLIB_HANDLERI(inputs)
{
netlist_sig_t tCarry = 1;
netlist_sig_t tBorrow = 1;
if (m_CLEAR())
{
m_cnt = 0;
}
else if (!m_LOADQ())
{
m_cnt = (m_D() << 3) | (m_C() << 2)
| (m_B() << 1) | (m_A() << 0);
}
else
{
if (m_CD() && !m_last_CU && m_CU())
{
++m_cnt &= MAXCNT;
}
if (m_CU() && !m_last_CD && m_CD())
{
if (m_cnt > 0)
--m_cnt;
else
m_cnt = MAXCNT;
}
}
if (!m_CU() && (m_cnt == MAXCNT))
tCarry = 0;
if (!m_CD() && (m_cnt == 0))
tBorrow = 0;
m_last_CD = m_CD();
m_last_CU = m_CU();
for (std::size_t i=0; i<4; i++)
m_Q[i].push((m_cnt >> i) & 1, delay[i]);
m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME timing
m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME timing
}
logic_input_t m_A;
logic_input_t m_B;
logic_input_t m_C;
@ -93,60 +153,6 @@ namespace netlist
NETLIB_SUB(74193) A;
};
// FIXME: Timing
static constexpr const std::array<netlist_time, 4> delay =
{
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40)
};
NETLIB_UPDATE(74193)
{
netlist_sig_t tCarry = 1;
netlist_sig_t tBorrow = 1;
if (m_CLEAR())
{
m_cnt = 0;
}
else if (!m_LOADQ())
{
m_cnt = (m_D() << 3) | (m_C() << 2)
| (m_B() << 1) | (m_A() << 0);
}
else
{
if (m_CD() && !m_last_CU && m_CU())
{
++m_cnt &= MAXCNT;
}
if (m_CU() && !m_last_CD && m_CD())
{
if (m_cnt > 0)
--m_cnt;
else
m_cnt = MAXCNT;
}
}
if (!m_CU() && (m_cnt == MAXCNT))
tCarry = 0;
if (!m_CD() && (m_cnt == 0))
tBorrow = 0;
m_last_CD = m_CD();
m_last_CU = m_CU();
for (std::size_t i=0; i<4; i++)
m_Q[i].push((m_cnt >> i) & 1, delay[i]);
m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME timing
m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME timing
}
NETLIB_DEVICE_IMPL(74193, "TTL_74193", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD,@VCC,@GND")
NETLIB_DEVICE_IMPL(74193_dip, "TTL_74193_DIP", "")