netlist: first batch of explicit handlers.

* Currently devices use the "update" function if no handler is given for
an input.
* For this to work the update function has to be virtual. This will
cause issues on shared execution schemes like CPU/GPU using nvcc.
* This is the first batch of changes to ensure that handler resolution
is static.
This commit is contained in:
couriersud 2020-07-12 12:11:40 +02:00
parent a5fc819f50
commit 2683665665
11 changed files with 389 additions and 340 deletions

View File

@ -18,10 +18,10 @@ namespace netlist
NETLIB_OBJECT(2102A)
{
NETLIB_CONSTRUCTOR(2102A)
, m_A(*this, {"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9" })
, m_CEQ(*this, "CEQ")
, m_RWQ(*this, "RWQ")
, m_DI(*this, "DI")
, m_A(*this, {"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9" }, NETLIB_DELEGATE(inputs))
, m_CEQ(*this, "CEQ", NETLIB_DELEGATE(inputs))
, m_RWQ(*this, "RWQ", NETLIB_DELEGATE(inputs))
, m_DI(*this, "DI", NETLIB_DELEGATE(inputs))
, m_DO(*this, "DO")
, m_ram(*this, "m_ram", 0)
, m_RAM(*this, "m_RAM", &m_ram[0])
@ -29,8 +29,41 @@ namespace netlist
{
}
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_RESETI()
{
m_RAM.set(&m_ram[0]);
for (std::size_t i=0; i<128; i++)
m_ram[i] = 0;
}
NETLIB_HANDLERI(inputs)
{
netlist_time max_delay = NLTIME_FROM_NS(350);
if (!m_CEQ())
{
unsigned a = 0;
for (std::size_t i=0; i<10; i++)
{
a |= (m_A[i]() << i);
}
const unsigned byte = ADDR2BYTE(a);
const unsigned bit = ADDR2BIT(a);
if (!m_RWQ())
{
m_ram[byte] &= ~(static_cast<uint8_t>(1) << bit);
m_ram[byte] |= (static_cast<uint8_t>(m_DI()) << bit);
}
m_DO.push((m_ram[byte] >> bit) & 1, max_delay);
}
}
NETLIB_UPDATEI()
{
inputs();
}
friend class NETLIB_NAME(2102A_dip);
private:
@ -78,37 +111,6 @@ namespace netlist
NETLIB_SUB(2102A) A;
};
NETLIB_UPDATE(2102A)
{
netlist_time max_delay = NLTIME_FROM_NS(350);
if (!m_CEQ())
{
unsigned a = 0;
for (std::size_t i=0; i<10; i++)
{
a |= (m_A[i]() << i);
}
const unsigned byte = ADDR2BYTE(a);
const unsigned bit = ADDR2BIT(a);
if (!m_RWQ())
{
m_ram[byte] &= ~(static_cast<uint8_t>(1) << bit);
m_ram[byte] |= (static_cast<uint8_t>(m_DI()) << bit);
}
m_DO.push((m_ram[byte] >> bit) & 1, max_delay);
}
}
NETLIB_RESET(2102A)
{
m_RAM.set(&m_ram[0]);
for (std::size_t i=0; i<128; i++)
m_ram[i] = 0;
}
NETLIB_DEVICE_IMPL(2102A, "RAM_2102A", "+CEQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+RWQ,+DI,@VCC,@GND")
NETLIB_DEVICE_IMPL(2102A_dip,"RAM_2102A_DIP","")

View File

@ -22,9 +22,9 @@ namespace netlist
, m_clk(*this, "CLK", NETLIB_DELEGATE(clk))
, m_Q(*this, "Q")
, m_QQ(*this, "QQ")
, m_J(*this, "J")
, m_K(*this, "K")
, m_clrQ(*this, "CLRQ")
, m_J(*this, "J", NETLIB_DELEGATE(other))
, m_K(*this, "K", NETLIB_DELEGATE(other))
, m_clrQ(*this, "CLRQ", NETLIB_DELEGATE(other))
, m_power_pins(*this)
{
m_delay[0] = delay_107A[0];
@ -34,9 +34,47 @@ namespace netlist
friend class NETLIB_NAME(74107_dip);
friend class NETLIB_NAME(74107);
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_HANDLERI(clk);
NETLIB_RESETI()
{
m_clk.set_state(logic_t::STATE_INP_HL);
//m_Q.initial(0);
//m_QQ.initial(1);
}
NETLIB_UPDATEI()
{
other();
}
NETLIB_HANDLERI(other)
{
if (!m_clrQ())
{
m_clk.inactivate();
newstate(0);
}
else if (m_J() | m_K())
m_clk.activate_hl();
}
NETLIB_HANDLERI(clk)
{
const netlist_sig_t t(m_Q.net().Q());
/*
* J K Q1 Q2 F t Q
* 0 0 0 1 0 0 0
* 0 1 0 0 0 0 0
* 1 0 0 0 1 0 1
* 1 1 1 0 0 0 1
* 0 0 0 1 0 1 1
* 0 1 0 0 0 1 0
* 1 0 0 0 1 1 1
* 1 1 1 0 0 1 0
*/
if ((m_J() & m_K()) ^ 1)
m_clk.inactivate();
newstate(((t ^ 1) & m_J()) | (t & (m_K() ^ 1)));
}
private:
logic_input_t m_clk;
@ -106,43 +144,6 @@ namespace netlist
NETLIB_SUB(74107) m_B;
};
NETLIB_RESET(74107A)
{
m_clk.set_state(logic_t::STATE_INP_HL);
//m_Q.initial(0);
//m_QQ.initial(1);
}
NETLIB_HANDLER(74107A, clk)
{
const netlist_sig_t t(m_Q.net().Q());
/*
* J K Q1 Q2 F t Q
* 0 0 0 1 0 0 0
* 0 1 0 0 0 0 0
* 1 0 0 0 1 0 1
* 1 1 1 0 0 0 1
* 0 0 0 1 0 1 1
* 0 1 0 0 0 1 0
* 1 0 0 0 1 1 1
* 1 1 1 0 0 1 0
*/
if ((m_J() & m_K()) ^ 1)
m_clk.inactivate();
newstate(((t ^ 1) & m_J()) | (t & (m_K() ^ 1)));
}
NETLIB_UPDATE(74107A)
{
if (!m_clrQ())
{
m_clk.inactivate();
newstate(0);
}
else if (m_J() | m_K())
m_clk.activate_hl();
}
#if (!NL_USE_TRUTHTABLE_74107)
NETLIB_DEVICE_IMPL(74107, "TTL_74107", "+CLK,+J,+K,+CLRQ,@VCC,@GND")
NETLIB_DEVICE_IMPL(74107_dip, "TTL_74107_DIP", "")

View File

@ -17,10 +17,10 @@ namespace netlist
NETLIB_OBJECT(74113)
{
NETLIB_CONSTRUCTOR(74113)
, m_CLK(*this, "CLK")
, m_J(*this, "J")
, m_K(*this, "K")
, m_SETQ(*this, "SETQ")
, m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs))
, m_J(*this, "J", NETLIB_DELEGATE(inputs))
, m_K(*this, "K", NETLIB_DELEGATE(inputs))
, m_SETQ(*this, "SETQ", NETLIB_DELEGATE(inputs))
, m_last_CLK(*this, "m_last_CLK", 0)
, m_q(*this, "m_q", 0)
, m_Q(*this, "Q")
@ -29,8 +29,51 @@ namespace netlist
{
}
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_RESETI()
{
m_last_CLK = 0;
}
NETLIB_HANDLERI(inputs)
{
const auto JK = (m_J() << 1) | m_K();
if (m_SETQ())
{
if (!m_CLK() && m_last_CLK)
{
switch (JK)
{
case 1: // (!m_J) & m_K))
m_q = 0;
break;
case 2: // (m_J) & !m_K))
m_q = 1;
break;
case 3: // (m_J) & m_K))
m_q ^= 1;
break;
default:
case 0:
break;
}
}
}
else
{
m_q = 1;
}
m_last_CLK = m_CLK();
m_Q.push(m_q, NLTIME_FROM_NS(20)); // FIXME: timing
m_QQ.push(m_q ^ 1, NLTIME_FROM_NS(20)); // FIXME: timing
}
NETLIB_UPDATEI()
{
inputs();
}
public:
logic_input_t m_CLK;
@ -115,47 +158,6 @@ namespace netlist
NETLIB_SUB(74113A) m_B;
};
NETLIB_RESET(74113)
{
m_last_CLK = 0;
}
NETLIB_UPDATE(74113)
{
const auto JK = (m_J() << 1) | m_K();
if (m_SETQ())
{
if (!m_CLK() && m_last_CLK)
{
switch (JK)
{
case 1: // (!m_J) & m_K))
m_q = 0;
break;
case 2: // (m_J) & !m_K))
m_q = 1;
break;
case 3: // (m_J) & m_K))
m_q ^= 1;
break;
default:
case 0:
break;
}
}
}
else
{
m_q = 1;
}
m_last_CLK = m_CLK();
m_Q.push(m_q, NLTIME_FROM_NS(20)); // FIXME: timing
m_QQ.push(m_q ^ 1, NLTIME_FROM_NS(20)); // FIXME: timing
}
NETLIB_DEVICE_IMPL(74113, "TTL_74113", "+CLK,+J,+K,+CLRQ,@VCC,@GND")
NETLIB_DEVICE_IMPL(74113A, "TTL_74113A", "+CLK,+J,+K,+CLRQ,@VCC,@GND")
NETLIB_DEVICE_IMPL(74113_dip, "TTL_74113_DIP", "")

View File

@ -13,10 +13,9 @@ namespace netlist
namespace devices
{
/* FIXME: timing is not 100% accurate, Strobe and Select inputs have a
* slightly longer timing.
* Convert this to sub-devices at some time.
*/
// FIXME: timing is not 100% accurate, Strobe and Select inputs have a
// slightly longer timing .
// FIXME: Truthtable candidate
NETLIB_OBJECT(74153)
{
@ -25,8 +24,8 @@ namespace devices
, m_G(*this, "G", NETLIB_DELEGATE(sub))
, m_Y(*this, "AY") //FIXME: Change netlists
, m_chan(*this, "m_chan", 0)
, m_A(*this, "A")
, m_B(*this, "B")
, m_A(*this, "A", NETLIB_DELEGATE(other))
, m_B(*this, "B", NETLIB_DELEGATE(other))
, m_power_pins(*this)
{
}
@ -36,12 +35,17 @@ namespace devices
m_chan = 0;
}
NETLIB_UPDATEI()
NETLIB_HANDLERI(other)
{
m_chan = (m_A() | (m_B()<<1));
sub();
}
NETLIB_UPDATEI()
{
other();
}
NETLIB_HANDLERI(sub)
{
constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(23), NLTIME_FROM_NS(18) };

View File

@ -11,6 +11,8 @@
#include "nld_74164.h"
#include "netlist/nl_base.h"
// FIXME: clk input to be separated - only falling edge relevant
namespace netlist
{
namespace devices
@ -18,10 +20,10 @@ namespace netlist
NETLIB_OBJECT(74164)
{
NETLIB_CONSTRUCTOR(74164)
, m_A(*this, "A")
, m_B(*this, "B")
, m_CLRQ(*this, "CLRQ")
, m_CLK(*this, "CLK")
, m_A(*this, "A", NETLIB_DELEGATE(inputs))
, m_B(*this, "B", NETLIB_DELEGATE(inputs))
, m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(inputs))
, m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs))
, m_cnt(*this, "m_cnt", 0)
, m_last_CLK(*this, "m_last_CLK", 0)
, m_Q(*this, {"QA", "QB", "QC", "QD", "QE", "QF", "QG", "QH"})
@ -29,13 +31,43 @@ namespace netlist
{
}
NETLIB_HANDLERI(inputs)
{
if (!m_CLRQ())
{
m_cnt = 0;
}
else if (m_CLK() && !m_last_CLK)
{
m_cnt = (m_cnt << 1) & 0xfe;
if (m_A() && m_B())
{
m_cnt |= 0x01;
}
else
{
m_cnt &= 0xfe;
}
}
m_last_CLK = m_CLK();
for (std::size_t i=0; i<8; i++)
{
m_Q[i].push((m_cnt >> i) & 1, NLTIME_FROM_NS(30));
}
}
NETLIB_RESETI()
{
m_cnt = 0;
m_last_CLK = 0;
}
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
inputs();
}
friend class NETLIB_NAME(74164_dip);
private:
@ -77,33 +109,6 @@ namespace netlist
};
NETLIB_UPDATE(74164)
{
if (!m_CLRQ())
{
m_cnt = 0;
}
else if (m_CLK() && !m_last_CLK)
{
m_cnt = (m_cnt << 1) & 0xfe;
if (m_A() && m_B())
{
m_cnt |= 0x01;
}
else
{
m_cnt &= 0xfe;
}
}
m_last_CLK = m_CLK();
for (std::size_t i=0; i<8; i++)
{
m_Q[i].push((m_cnt >> i) & 1, NLTIME_FROM_NS(30));
}
}
NETLIB_DEVICE_IMPL(74164, "TTL_74164", "+A,+B,+CLRQ,+CLK,@VCC,@GND")
NETLIB_DEVICE_IMPL(74164_dip, "TTL_74164_DIP", "")

View File

@ -15,11 +15,11 @@ namespace netlist
NETLIB_OBJECT(74165)
{
NETLIB_CONSTRUCTOR(74165)
, m_DATA(*this, { "H", "G", "F", "E", "D", "C", "B", "A" })
, m_SER(*this, "SER")
, m_SH_LDQ(*this, "SH_LDQ")
, m_CLK(*this, "CLK")
, m_CLKINH(*this, "CLKINH")
, m_DATA(*this, { "H", "G", "F", "E", "D", "C", "B", "A" }, NETLIB_DELEGATE(inputs))
, m_SER(*this, "SER", NETLIB_DELEGATE(inputs))
, m_SH_LDQ(*this, "SH_LDQ", NETLIB_DELEGATE(inputs))
, m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs))
, m_CLKINH(*this, "CLKINH", NETLIB_DELEGATE(inputs))
, m_QH(*this, "QH")
, m_QHQ(*this, "QHQ")
, m_shifter(*this, "m_shifter", 0)
@ -33,7 +33,43 @@ namespace netlist
m_shifter = 0;
m_last_CLK = 0;
}
NETLIB_UPDATEI();
NETLIB_HANDLERI(inputs)
{
{
netlist_sig_t old_qh = m_QH.net().Q();
netlist_sig_t qh = 0;
if (!m_SH_LDQ())
{
m_shifter = 0;
for (std::size_t i=0; i<8; i++)
m_shifter |= (m_DATA[i]() << i);
}
else if (!m_CLK() || m_CLKINH())
{
// FIXME: qh is overwritten below?
qh = old_qh;
}
else if (!m_last_CLK)
{
unsigned high_bit = m_SER() ? 0x80 : 0;
m_shifter = high_bit | (m_shifter >> 1);
}
qh = m_shifter & 1;
m_last_CLK = m_CLK();
m_QH.push(qh, NLTIME_FROM_NS(20)); // FIXME: Timing
}
}
NETLIB_UPDATEI()
{
inputs();
}
friend class NETLIB_NAME(74165_dip);
private:
@ -80,35 +116,6 @@ namespace netlist
};
// FIXME: Timing
NETLIB_UPDATE(74165)
{
netlist_sig_t old_qh = m_QH.net().Q();
netlist_sig_t qh = 0;
if (!m_SH_LDQ())
{
m_shifter = 0;
for (std::size_t i=0; i<8; i++)
m_shifter |= (m_DATA[i]() << i);
}
else if (!m_CLK() || m_CLKINH())
{
// FIXME: qh is overwritten below?
qh = old_qh;
}
else if (!m_last_CLK)
{
unsigned high_bit = m_SER() ? 0x80 : 0;
m_shifter = high_bit | (m_shifter >> 1);
}
qh = m_shifter & 1;
m_last_CLK = m_CLK();
m_QH.push(qh, NLTIME_FROM_NS(20)); // FIXME: Timing
}
NETLIB_DEVICE_IMPL(74165, "TTL_74165", "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,@VCC,@GND")
NETLIB_DEVICE_IMPL(74165_dip, "TTL_74165_DIP", "")

View File

@ -8,6 +8,8 @@
#include "nld_74166.h"
#include "netlist/nl_base.h"
// FIXME: separate handlers for inputs
namespace netlist
{
namespace devices
@ -15,12 +17,12 @@ namespace netlist
NETLIB_OBJECT(74166)
{
NETLIB_CONSTRUCTOR(74166)
, m_DATA(*this, { "H", "G", "F", "E", "D", "C", "B", "A" })
, m_SER(*this, "SER")
, m_CLRQ(*this, "CLRQ")
, m_SH_LDQ(*this, "SH_LDQ")
, m_CLK(*this, "CLK")
, m_CLKINH(*this, "CLKINH")
, m_DATA(*this, { "H", "G", "F", "E", "D", "C", "B", "A" }, NETLIB_DELEGATE(inputs))
, m_SER(*this, "SER", NETLIB_DELEGATE(inputs))
, m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(inputs))
, m_SH_LDQ(*this, "SH_LDQ", NETLIB_DELEGATE(inputs))
, m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs))
, m_CLKINH(*this, "CLKINH", NETLIB_DELEGATE(inputs))
, m_QH(*this, "QH")
, m_shifter(*this, "m_shifter", 0)
, m_last_CLRQ(*this, "m_last_CLRQ", 0)
@ -35,7 +37,57 @@ namespace netlist
m_last_CLRQ = 0;
m_last_CLK = 0;
}
NETLIB_UPDATEI();
NETLIB_HANDLERI(inputs)
{
netlist_sig_t old_qh = m_QH.net().Q();
netlist_sig_t qh = 0;
netlist_time delay = NLTIME_FROM_NS(26);
if (m_CLRQ())
{
bool clear_unset = !m_last_CLRQ;
if (clear_unset)
{
delay = NLTIME_FROM_NS(35);
}
if (!m_CLK() || m_CLKINH())
{
qh = old_qh;
}
else if (!m_last_CLK)
{
if (!m_SH_LDQ())
{
m_shifter = 0;
for (std::size_t i=0; i<8; i++)
m_shifter |= (m_DATA[i]() << i);
}
else
{
unsigned high_bit = m_SER() ? 0x80 : 0;
m_shifter = high_bit | (m_shifter >> 1);
}
qh = m_shifter & 1;
if (!qh && !clear_unset)
{
delay = NLTIME_FROM_NS(30);
}
}
}
m_last_CLRQ = m_CLRQ();
m_last_CLK = m_CLK();
m_QH.push(qh, delay); //FIXME
}
NETLIB_UPDATEI()
{
inputs();
}
friend class NETLIB_NAME(74166_dip);
private:
@ -82,52 +134,6 @@ namespace netlist
NETLIB_SUB(74166) A;
};
NETLIB_UPDATE(74166)
{
netlist_sig_t old_qh = m_QH.net().Q();
netlist_sig_t qh = 0;
netlist_time delay = NLTIME_FROM_NS(26);
if (m_CLRQ())
{
bool clear_unset = !m_last_CLRQ;
if (clear_unset)
{
delay = NLTIME_FROM_NS(35);
}
if (!m_CLK() || m_CLKINH())
{
qh = old_qh;
}
else if (!m_last_CLK)
{
if (!m_SH_LDQ())
{
m_shifter = 0;
for (std::size_t i=0; i<8; i++)
m_shifter |= (m_DATA[i]() << i);
}
else
{
unsigned high_bit = m_SER() ? 0x80 : 0;
m_shifter = high_bit | (m_shifter >> 1);
}
qh = m_shifter & 1;
if (!qh && !clear_unset)
{
delay = NLTIME_FROM_NS(30);
}
}
}
m_last_CLRQ = m_CLRQ();
m_last_CLK = m_CLK();
m_QH.push(qh, delay); //FIXME
}
NETLIB_DEVICE_IMPL(74166, "TTL_74166", "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,+CLRQ,@VCC,@GND")
NETLIB_DEVICE_IMPL(74166_dip,"TTL_74166_DIP", "")

View File

@ -15,12 +15,12 @@ namespace devices
NETLIB_OBJECT(74174)
{
NETLIB_CONSTRUCTOR(74174)
, m_CLK(*this, "CLK", NETLIB_DELEGATE(sub))
, m_CLK(*this, "CLK", NETLIB_DELEGATE(clk))
, m_Q(*this, {"Q1", "Q2", "Q3", "Q4", "Q5", "Q6"})
, m_clrq(*this, "m_clr", 0)
, m_data(*this, "m_data", 0)
, m_D(*this, {"D1", "D2", "D3", "D4", "D5", "D6"})
, m_CLRQ(*this, "CLRQ")
, m_D(*this, {"D1", "D2", "D3", "D4", "D5", "D6"}, NETLIB_DELEGATE(other))
, m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(other))
, m_power_pins(*this)
{
}
@ -31,9 +31,35 @@ namespace devices
m_clrq = 0;
m_data = 0xFF;
}
NETLIB_UPDATEI();
NETLIB_HANDLERI(sub)
NETLIB_HANDLERI(other)
{
uint_fast8_t d = 0;
for (std::size_t i=0; i<6; i++)
{
d |= (m_D[i]() << i);
}
m_clrq = m_CLRQ();
if (!m_clrq)
{
for (std::size_t i=0; i<6; i++)
{
m_Q[i].push(0, NLTIME_FROM_NS(40));
}
m_data = 0;
} else if (d != m_data)
{
m_data = d;
m_CLK.activate_lh();
}
}
NETLIB_UPDATEI()
{
other();
}
NETLIB_HANDLERI(clk)
{
if (m_clrq)
{
@ -94,28 +120,6 @@ namespace devices
NETLIB_SUB(74174) A;
};
NETLIB_UPDATE(74174)
{
uint_fast8_t d = 0;
for (std::size_t i=0; i<6; i++)
{
d |= (m_D[i]() << i);
}
m_clrq = m_CLRQ();
if (!m_clrq)
{
for (std::size_t i=0; i<6; i++)
{
m_Q[i].push(0, NLTIME_FROM_NS(40));
}
m_data = 0;
} else if (d != m_data)
{
m_data = d;
m_CLK.activate_lh();
}
}
NETLIB_DEVICE_IMPL(74174, "TTL_74174", "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ,@VCC,@GND")
NETLIB_DEVICE_IMPL(74174_dip,"TTL_74174_DIP", "")

View File

@ -8,16 +8,22 @@
#include "nld_74175.h"
#include "netlist/nl_base.h"
// FIXME: optimize
namespace netlist
{
namespace devices
{
static constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(25) };
static constexpr const std::array<netlist_time, 2> delay_clear = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
NETLIB_OBJECT(74175)
{
NETLIB_CONSTRUCTOR(74175)
, m_D(*this, {"D1", "D2", "D3", "D4"})
, m_CLRQ(*this, "CLRQ")
, m_D(*this, {"D1", "D2", "D3", "D4"}, NETLIB_DELEGATE(other))
, m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(other))
, m_CLK(*this, "CLK", NETLIB_DELEGATE(clk))
, m_Q(*this, {"Q1", "Q2", "Q3", "Q4"})
, m_QQ(*this, {"Q1Q", "Q2Q", "Q3Q", "Q4Q"})
@ -31,8 +37,47 @@ namespace netlist
m_CLK.set_state(logic_t::STATE_INP_LH);
m_data = 0xFF;
}
NETLIB_UPDATEI();
NETLIB_HANDLERI(clk);
NETLIB_HANDLERI(other)
{
uint_fast8_t d = 0;
for (std::size_t i=0; i<4; i++)
{
d |= (m_D[i]() << i);
}
if (!m_CLRQ())
{
for (std::size_t i=0; i<4; i++)
{
m_Q[i].push(0, delay_clear[0]);
m_QQ[i].push(1, delay_clear[1]);
}
m_data = 0;
} else if (d != m_data)
{
m_data = d;
m_CLK.activate_lh();
}
}
NETLIB_UPDATEI()
{
other();
}
NETLIB_HANDLERI(clk)
{
if (m_CLRQ())
{
for (std::size_t i=0; i<4; i++)
{
netlist_sig_t d = (m_data >> i) & 1;
m_Q[i].push(d, delay[d]);
m_QQ[i].push(d ^ 1, delay[d ^ 1]);
}
m_CLK.inactivate();
}
}
friend class NETLIB_NAME(74175_dip);
private:
@ -80,46 +125,6 @@ namespace netlist
NETLIB_SUB(74175) A;
};
constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(25) };
constexpr const std::array<netlist_time, 2> delay_clear = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
NETLIB_HANDLER(74175, clk)
{
if (m_CLRQ())
{
for (std::size_t i=0; i<4; i++)
{
netlist_sig_t d = (m_data >> i) & 1;
m_Q[i].push(d, delay[d]);
m_QQ[i].push(d ^ 1, delay[d ^ 1]);
}
m_CLK.inactivate();
}
}
NETLIB_UPDATE(74175)
{
uint_fast8_t d = 0;
for (std::size_t i=0; i<4; i++)
{
d |= (m_D[i]() << i);
}
if (!m_CLRQ())
{
for (std::size_t i=0; i<4; i++)
{
m_Q[i].push(0, delay_clear[0]);
m_QQ[i].push(1, delay_clear[1]);
}
m_data = 0;
} else if (d != m_data)
{
m_data = d;
m_CLK.activate_lh();
}
}
NETLIB_DEVICE_IMPL(74175, "TTL_74175", "+CLK,+D1,+D2,+D3,+D4,+CLRQ,@VCC,@GND")
NETLIB_DEVICE_IMPL(74175_dip,"TTL_74175_DIP", "")

View File

@ -24,11 +24,11 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(9316_base)
, m_CLK(*this, "CLK", NETLIB_DELEGATE(clk))
, m_ENT(*this, "ENT")
, m_ENT(*this, "ENT", NETLIB_DELEGATE(other))
, m_RC(*this, "RC")
, m_LOADQ(*this, "LOADQ")
, m_ENP(*this, "ENP")
, m_CLRQ(*this, "CLRQ")
, m_LOADQ(*this, "LOADQ", NETLIB_DELEGATE(other))
, m_ENP(*this, "ENP", NETLIB_DELEGATE(other))
, m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(other))
, m_ABCD(*this, {"A", "B", "C", "D"}, NETLIB_DELEGATE(abcd))
, m_Q(*this, { "QA", "QB", "QC", "QD" })
, m_cnt(*this, "m_cnt", 0)
@ -47,7 +47,7 @@ namespace netlist
m_abcd = 0;
}
NETLIB_UPDATEI()
NETLIB_HANDLERI(other)
{
const auto CLRQ(m_CLRQ());
m_ent = m_ENT();
@ -69,6 +69,11 @@ namespace netlist
m_RC.push(m_ent && (m_cnt == D::MAXCNT::value), D::tRC::value(0));
}
NETLIB_UPDATEI()
{
other();
}
NETLIB_HANDLERI(clk)
{
if (!D::ASYNC::value && !m_CLRQ())

View File

@ -99,22 +99,26 @@ namespace netlist
/// analog callback device instead.
template <typename FUNC>
class NETLIB_NAME(logic_callback) : public device_t
NETLIB_OBJECT(logic_callback)
{
public:
NETLIB_NAME(logic_callback)(netlist_state_t &anetlist, const pstring &name, FUNC &&func)
: device_t(anetlist, name)
, m_in(*this, "IN")
NETLIB_CONSTRUCTOR_EX(logic_callback, FUNC &&func)
, m_in(*this, "IN", NETLIB_DELEGATE(in))
, m_func(func)
{
}
NETLIB_UPDATEI()
NETLIB_HANDLERI(in)
{
const netlist_sig_t cur = m_in();
m_func(*this, cur);
}
NETLIB_UPDATEI()
{
in();
}
private:
logic_input_t m_in;
FUNC m_func;
@ -130,16 +134,15 @@ namespace netlist
/// \tparam N Maximum number of supported buffers
///
template <typename T, std::size_t N>
class NETLIB_NAME(buffered_param_setter) : public device_t
NETLIB_OBJECT(buffered_param_setter)
{
public:
static const int MAX_INPUT_CHANNELS = N;
NETLIB_NAME(buffered_param_setter)(netlist_state_t &anetlist, const pstring &name)
: device_t(anetlist, name)
NETLIB_CONSTRUCTOR(buffered_param_setter)
, m_sample_time(netlist_time::zero())
, m_feedback(*this, "FB") // clock part
, m_feedback(*this, "FB", NETLIB_DELEGATE(feedback)) // clock part
, m_Q(*this, "Q")
, m_pos(0)
, m_samples(0)
@ -158,7 +161,7 @@ namespace netlist
{
}
NETLIB_UPDATEI()
NETLIB_HANDLERI(feedback)
{
if (m_pos < m_samples)
{
@ -182,6 +185,11 @@ namespace netlist
m_Q.net().toggle_and_push_to_queue(m_sample_time);
}
NETLIB_UPDATEI()
{
feedback();
}
public:
/// \brief resolve parameter names to pointers
///