netlist: finished input handler refactoring.

* all inputs now explicitly specify a signal handler.
This commit is contained in:
couriersud 2020-07-12 20:28:52 +02:00
parent 54fe9d1678
commit 6328b0e995
23 changed files with 381 additions and 225 deletions

View File

@ -107,8 +107,8 @@ namespace netlist
NETLIB_CONSTRUCTOR(opamp)
, m_RP(*this, "RP1")
, m_G1(*this, "G1")
, m_VCC(*this, "VCC")
, m_GND(*this, "GND")
, m_VCC(*this, "VCC", NETLIB_DELEGATE(supply))
, m_GND(*this, "GND", NETLIB_DELEGATE(supply))
, m_model(*this, "MODEL", "LM324")
, m_modacc(m_model)
, m_VH(*this, "VH")
@ -183,10 +183,26 @@ namespace netlist
}
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
supply();
}
NETLIB_HANDLERI(supply)
{
const nl_fptype cVt = nlconst::np_VT(nlconst::one()); // * m_n;
const nl_fptype cId = m_modacc.m_DAB; // 3 mA
const nl_fptype cVd = cVt * plib::log(cId / nlconst::np_Is() + nlconst::one());
m_VH.push(m_VCC() - m_modacc.m_VLH - cVd);
m_VL.push(m_GND() + m_modacc.m_VLL + cVd);
m_VREF.push((m_VCC() + m_GND()) / nlconst::two());
}
NETLIB_RESETI()
{
}
NETLIB_UPDATE_PARAMI();
private:
@ -214,17 +230,6 @@ namespace netlist
int m_type;
};
NETLIB_UPDATE(opamp)
{
const nl_fptype cVt = nlconst::np_VT(nlconst::one()); // * m_n;
const nl_fptype cId = m_modacc.m_DAB; // 3 mA
const nl_fptype cVd = cVt * plib::log(cId / nlconst::np_Is() + nlconst::one());
m_VH.push(m_VCC() - m_modacc.m_VLH - cVd);
m_VL.push(m_GND() + m_modacc.m_VLL + cVd);
m_VREF.push((m_VCC() + m_GND()) / nlconst::two());
}
NETLIB_UPDATE_PARAM(opamp)
{
m_G1.m_RI.set(m_modacc.m_RI);

View File

@ -33,7 +33,7 @@ namespace netlist
NETLIB_CONSTRUCTOR_MODEL(CD4066_GATE, "CD4XXX")
, m_supply(*this, "VDD", "VSS")
, m_R(*this, "R")
, m_control(*this, "CTL")
, m_control(*this, "CTL", NETLIB_DELEGATE(control))
, m_base_r(*this, "BASER", nlconst::magic(270.0))
, m_last(*this, "m_last", false)
{
@ -47,6 +47,12 @@ namespace netlist
}
NETLIB_UPDATEI()
{
control();
}
private:
NETLIB_HANDLERI(control)
{
nl_fptype sup = (m_supply.VCC().Q_Analog() - m_supply.GND().Q_Analog());
nl_fptype in = m_control() - m_supply.GND().Q_Analog();
@ -71,7 +77,6 @@ namespace netlist
}
}
private:
nld_power_pins m_supply;
analog::NETLIB_SUB(R_base) m_R;
analog_input_t m_control;

View File

@ -72,7 +72,7 @@ namespace netlist
, m_I(*this, D::names(), NETLIB_DELEGATE(ab_clear))
, m_Q(*this, "Q")
, m_QQ(*this, "QQ")
, m_CV(*this, "_CV") // internal
, m_CV(*this, "_CV", NETLIB_DELEGATE(cv)) // internal
, m_last_trig(*this, "m_last_trig", 0)
, m_state(*this, "m_state", 0)
, m_KP(plib::reciprocal(nlconst::one() + plib::exp(D::K())))
@ -128,6 +128,11 @@ namespace netlist
}
NETLIB_UPDATEI()
{
cv();
}
NETLIB_HANDLERI(cv)
{
if (m_state == 1)
{

View File

@ -16,10 +16,10 @@ namespace netlist
NETLIB_OBJECT(7477)
{
NETLIB_CONSTRUCTOR(7477)
, m_C1C2(*this, "C1C2")
, m_C3C4(*this, "C3C4")
, m_C1C2(*this, "C1C2", NETLIB_DELEGATE(inputs))
, m_C3C4(*this, "C3C4", NETLIB_DELEGATE(inputs))
, m_last_Q(*this, "m_last_Q", 0)
, m_D(*this, {"D1", "D2", "D3", "D4"})
, m_D(*this, {"D1", "D2", "D3", "D4"}, NETLIB_DELEGATE(inputs))
, m_Q(*this, {"Q1", "Q2", "Q3", "Q4"})
, m_power_pins(*this)
{
@ -30,9 +30,41 @@ namespace netlist
{
m_last_Q = 0;
}
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
inputs();
}
void update_outputs(std::size_t start, std::size_t end);
NETLIB_HANDLERI(inputs)
{
netlist_sig_t c1c2 = m_C1C2();
netlist_sig_t c3c4 = m_C3C4();
if (c1c2 && c3c4)
{
update_outputs(0, 4);
}
else if (c1c2)
{
update_outputs(0, 2);
}
else if (c3c4)
{
update_outputs(2, 4);
}
}
void update_outputs(std::size_t start, std::size_t end)
{
for (std::size_t i=start; i<end; i++)
{
netlist_sig_t d = m_D[i]();
if (d != ((m_last_Q >> i) & 1))
m_Q[i].push(d, d != 0 ? NLTIME_FROM_NS(30) : NLTIME_FROM_NS(25));
m_last_Q &= ~(1 << i);
m_last_Q |= d << i;
}
}
friend class NETLIB_NAME(7477_dip);
friend class NETLIB_NAME(7475_dip);
@ -47,19 +79,80 @@ namespace netlist
nld_power_pins m_power_pins;
};
NETLIB_OBJECT_DERIVED(7475, 7477)
NETLIB_OBJECT(7475)
{
NETLIB_CONSTRUCTOR(7475)
, m_C1C2(*this, "C1C2", NETLIB_DELEGATE(inputs))
, m_C3C4(*this, "C3C4", NETLIB_DELEGATE(inputs))
, m_last_Q(*this, "m_last_Q", 0)
, m_D(*this, {"D1", "D2", "D3", "D4"}, NETLIB_DELEGATE(inputs))
, m_Q(*this, {"Q1", "Q2", "Q3", "Q4"})
, m_QQ(*this, {"QQ1", "QQ2", "QQ3", "QQ4"})
, m_power_pins(*this)
{
register_subalias("Q1", m_Q[0]);
}
NETLIB_UPDATEI();
NETLIB_RESETI()
{
m_last_Q = 0;
}
NETLIB_UPDATEI()
{
inputs();
}
NETLIB_HANDLERI(inputs)
{
unsigned start_q = m_last_Q;
netlist_sig_t c1c2 = m_C1C2();
netlist_sig_t c3c4 = m_C3C4();
if (c1c2 && c3c4)
{
update_outputs(0, 4);
}
else if (c1c2)
{
update_outputs(0, 2);
}
else if (c3c4)
{
update_outputs(2, 4);
}
for (std::size_t i=0; i<4; i++)
{
unsigned last_bit = (m_last_Q >> i) & 1;
unsigned start_bit = (start_q >> i) & 1;
if (last_bit != start_bit)
m_QQ[i].push(last_bit ^ 1, last_bit != 0 ? NLTIME_FROM_NS(15) : NLTIME_FROM_NS(40));
}
}
void update_outputs(std::size_t start, std::size_t end)
{
for (std::size_t i=start; i<end; i++)
{
netlist_sig_t d = m_D[i]();
if (d != ((m_last_Q >> i) & 1))
m_Q[i].push(d, d != 0 ? NLTIME_FROM_NS(30) : NLTIME_FROM_NS(25));
m_last_Q &= ~(1 << i);
m_last_Q |= d << i;
}
}
friend class NETLIB_NAME(7477_dip);
friend class NETLIB_NAME(7475_dip);
private:
logic_input_t m_C1C2;
logic_input_t m_C3C4;
state_var<unsigned> m_last_Q;
object_array_t<logic_input_t, 4> m_D;
object_array_t<logic_output_t, 4> m_Q;
object_array_t<logic_output_t, 4> m_QQ;
nld_power_pins m_power_pins;
};
NETLIB_OBJECT(7475_dip)
@ -118,52 +211,6 @@ namespace netlist
NETLIB_SUB(7477) A;
};
NETLIB_UPDATE(7475)
{
unsigned start_q = m_last_Q;
NETLIB_NAME(7477)::update();
for (std::size_t i=0; i<4; i++)
{
unsigned last_bit = (m_last_Q >> i) & 1;
unsigned start_bit = (start_q >> i) & 1;
if (last_bit != start_bit)
m_QQ[i].push(last_bit ^ 1, last_bit != 0 ? NLTIME_FROM_NS(15) : NLTIME_FROM_NS(40));
}
}
void NETLIB_NAME(7477)::update_outputs(std::size_t start, std::size_t end)
{
for (std::size_t i=start; i<end; i++)
{
netlist_sig_t d = m_D[i]();
if (d != ((m_last_Q >> i) & 1))
m_Q[i].push(d, d != 0 ? NLTIME_FROM_NS(30) : NLTIME_FROM_NS(25));
m_last_Q &= ~(1 << i);
m_last_Q |= d << i;
}
}
NETLIB_UPDATE(7477)
{
netlist_sig_t c1c2 = m_C1C2();
netlist_sig_t c3c4 = m_C3C4();
if (c1c2 && c3c4)
{
update_outputs(0, 4);
}
else if (c1c2)
{
update_outputs(0, 2);
}
else if (c3c4)
{
update_outputs(2, 4);
}
}
NETLIB_DEVICE_IMPL(7475, "TTL_7475", "")
NETLIB_DEVICE_IMPL(7475_dip, "TTL_7475_DIP", "")
NETLIB_DEVICE_IMPL(7477, "TTL_7477", "")

View File

@ -65,13 +65,13 @@ namespace netlist
NETLIB_HANDLERI(upd_a)
{
m_a = static_cast<uint8_t>((m_A1() << 0) | (m_A2() << 1) | (m_A3() << 2) | (m_A4() << 3));
NETLIB_NAME(7483)::update();
c0();
}
NETLIB_HANDLERI(upd_b)
{
m_b = static_cast<uint8_t>((m_B1() << 0) | (m_B2() << 1) | (m_B3() << 2) | (m_B4() << 3));
NETLIB_NAME(7483)::update();
c0();
}

View File

@ -23,10 +23,10 @@ namespace netlist
NETLIB_OBJECT(7497)
{
NETLIB_CONSTRUCTOR(7497)
, m_B(*this, {"B5", "B4", "B3", "B2", "B1", "B0"})
, m_B(*this, {"B5", "B4", "B3", "B2", "B1", "B0"}, NETLIB_DELEGATE(inputs))
, m_CLK(*this, "CLK", NETLIB_DELEGATE(clk_strb))
, m_STRBQ(*this, "STRBQ", NETLIB_DELEGATE(clk_strb))
, m_ENQ(*this, "ENQ", NETLIB_DELEGATE(enq))
, m_ENQ(*this, "ENQ", NETLIB_DELEGATE(inputs))
, m_UNITYQ(*this, "UNITYQ", NETLIB_DELEGATE(unity))
, m_CLR(*this, "CLR", NETLIB_DELEGATE(clr))
, m_Y(*this, "Y")
@ -50,7 +50,7 @@ namespace netlist
NETLIB_UPDATEI()
{
enq();
inputs();
}
NETLIB_HANDLERI(noop) { }
@ -101,7 +101,7 @@ namespace netlist
}
NETLIB_HANDLERI(enq)
NETLIB_HANDLERI(inputs)
{
m_rate = rate();
clk_strb();
@ -146,9 +146,6 @@ namespace netlist
}
};
NETLIB_OBJECT(7497_dip)
{
NETLIB_CONSTRUCTOR(7497_dip)

View File

@ -184,7 +184,6 @@ namespace netlist
// FIXME: we need a possibility to remove entries from queue ...
// or an exact model ...
m_clock.m_inc = netlist_time::from_fp(nlconst::half() / freq);
//m_clock.update();
//NL_VERBOSE_OUT(("{1} {2} {3} {4}\n", name(), v_freq, v_rng, freq));
}

View File

@ -71,7 +71,7 @@ namespace netlist
adr |= (m_A[i]() << i);
}
m_addr = adr;
NETLIB_NAME(82S16)::update();
inputs();
}
NETLIB_HANDLERI(enq)
{
@ -92,7 +92,7 @@ namespace netlist
m_A[i].activate();
m_WEQ.activate();
m_DIN.activate();
NETLIB_NAME(82S16)::update();
inputs();
}
}

View File

@ -26,7 +26,7 @@ namespace netlist
NETLIB_OBJECT(log)
{
NETLIB_CONSTRUCTOR(log)
, m_I(*this, "I")
, m_I(*this, "I", NETLIB_DELEGATE(input))
, m_strm(plib::filesystem::u8path(plib::pfmt("{1}.log")(this->name())))
, m_writer(&m_strm)
, m_reset(false)
@ -54,6 +54,16 @@ namespace netlist
}
NETLIB_UPDATEI()
{
input();
}
NETLIB_HANDLERI(input)
{
log_value(static_cast<nl_fptype>(m_I()));
}
void log_value(nl_fptype val)
{
if (m_buffers[m_w].size() == BUF_SIZE)
{
@ -64,7 +74,7 @@ namespace netlist
m_w = 0;
}
/* use pstring::sprintf, it is a LOT faster */
m_buffers[m_w].push_back({exec().time(), static_cast<nl_fptype>(m_I())});
m_buffers[m_w].push_back({exec().time(), val});
//m_writer.writeline(plib::pfmt("{1:.9} {2}").e(exec().time().as_fp<nl_fptype>()).e(static_cast<nl_fptype>(m_I())));
}
@ -117,13 +127,19 @@ namespace netlist
NETLIB_OBJECT_DERIVED(logD, log)
{
NETLIB_CONSTRUCTOR(logD)
, m_I2(*this, "I2")
, m_I2(*this, "I2", nldelegate(&NETLIB_NAME(logD)::input, this))
{
m_I.set_delegate(nldelegate(&NETLIB_NAME(logD)::input, this));
}
NETLIB_UPDATEI()
{
m_writer.writeline(plib::pfmt("{1:.9} {2}").e(exec().time().as_fp<nl_fptype>()).e(static_cast<nl_fptype>(m_I() - m_I2())));
input();
}
NETLIB_HANDLERI(input)
{
log_value(static_cast<nl_fptype>(m_I() - m_I2()));
}
NETLIB_RESETI() { }

View File

@ -60,7 +60,7 @@ namespace netlist
NETLIB_OBJECT(schmitt_trigger)
{
NETLIB_CONSTRUCTOR(schmitt_trigger)
, m_A(*this, "A")
, m_A(*this, "A", NETLIB_DELEGATE(input))
, m_supply(*this)
, m_RVI(*this, "RVI")
, m_RVO(*this, "RVO")
@ -86,6 +86,12 @@ namespace netlist
}
NETLIB_UPDATEI()
{
input();
}
private:
NETLIB_HANDLERI(input)
{
const auto va(m_A.Q_Analog() - m_supply.GND().Q_Analog());
if (m_last_state)
@ -112,7 +118,6 @@ namespace netlist
}
}
private:
analog_input_t m_A;
NETLIB_NAME(power_pins) m_supply;
analog::NETLIB_SUB(twoterm) m_RVI;

View File

@ -18,46 +18,6 @@ namespace devices
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// extclock
// ----------------------------------------------------------------------------------------
NETLIB_RESET(extclock)
{
m_cnt = 0;
m_off = netlist_time::from_fp<decltype(m_offset())>(m_offset());
m_feedback.set_delegate(NETLIB_DELEGATE(update));
}
NETLIB_HANDLER(extclock, clk2)
{
m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]);
if (++m_cnt >= m_size)
m_cnt = 0;
}
NETLIB_HANDLER(extclock, clk2_pow2)
{
m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]);
m_cnt = (++m_cnt) & (m_size-1);
}
NETLIB_UPDATE(extclock)
{
m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off());
m_off = netlist_time::zero();
if (++m_cnt >= m_size)
m_cnt = 0;
// continue with optimized clock handlers ....
if ((m_size & (m_size-1)) == 0) // power of 2?
m_feedback.set_delegate(nldelegate(&NETLIB_NAME(extclock)::clk2_pow2, this));
else
m_feedback.set_delegate(nldelegate(&NETLIB_NAME(extclock)::clk2, this));
}
NETLIB_DEVICE_IMPL(nc_pin, "NC_PIN", "")
NETLIB_DEVICE_IMPL(frontier, "FRONTIER_DEV", "+I,+G,+Q")
NETLIB_DEVICE_IMPL(function, "AFUNC", "N,FUNC")

View File

@ -8,6 +8,9 @@
#include "nld_tristate.h"
#include "netlist/nl_base.h"
// FIXME: netlist now supports proper tristate outputs. All of this is legacy
// now and needs to be removed at some time.
namespace netlist
{
namespace devices
@ -15,61 +18,67 @@ namespace netlist
NETLIB_OBJECT(tristate)
{
NETLIB_CONSTRUCTOR(tristate)
, m_CEQ(*this, { "CEQ1", "CEQ2" })
, m_D(*this, { "D1", "D2" })
, m_CEQ(*this, { "CEQ1", "CEQ2" }, NETLIB_DELEGATE(inputs))
, m_D(*this, { "D1", "D2" }, NETLIB_DELEGATE(inputs))
, m_Q(*this, "Q")
{
}
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
inputs();
}
protected:
object_array_t<logic_input_t, 2> m_CEQ;
object_array_t<logic_input_t, 2> m_D;
logic_output_t m_Q;
private:
NETLIB_HANDLERI(inputs)
{
unsigned q = 0;
if (!m_CEQ[0]())
q |= m_D[0]();
if (!m_CEQ[1]())
q |= m_D[1]();
m_Q.push(q, NLTIME_FROM_NS(1));
}
};
NETLIB_OBJECT(tristate3)
{
NETLIB_CONSTRUCTOR(tristate3)
, m_CEQ(*this, { "CEQ1", "CEQ2", "CEQ3" } )
, m_D(*this, { "D1", "D2", "D3" } )
, m_CEQ(*this, { "CEQ1", "CEQ2", "CEQ3" }, NETLIB_DELEGATE(inputs) )
, m_D(*this, { "D1", "D2", "D3" }, NETLIB_DELEGATE(inputs) )
, m_Q(*this, "Q")
{
}
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
inputs();
}
protected:
object_array_t<logic_input_t, 3> m_CEQ;
object_array_t<logic_input_t, 3> m_D;
logic_output_t m_Q;
private:
NETLIB_HANDLERI(inputs)
{
unsigned q = 0;
if (!m_CEQ[0]())
q |= m_D[0]();
if (!m_CEQ[1]())
q |= m_D[1]();
if (!m_CEQ[2]())
q |= m_D[2]();
m_Q.push(q, NLTIME_FROM_NS(1));
}
};
NETLIB_UPDATE(tristate)
{
unsigned q = 0;
if (!m_CEQ[0]())
q |= m_D[0]();
if (!m_CEQ[1]())
q |= m_D[1]();
m_Q.push(q, NLTIME_FROM_NS(1));
}
NETLIB_UPDATE(tristate3)
{
unsigned q = 0;
if (!m_CEQ[0]())
q |= m_D[0]();
if (!m_CEQ[1]())
q |= m_D[1]();
if (!m_CEQ[2]())
q |= m_D[2]();
m_Q.push(q, NLTIME_FROM_NS(1));
}
NETLIB_DEVICE_IMPL(tristate, "TTL_TRISTATE", "+CEQ1,+D1,+CEQ2,+D2")
NETLIB_DEVICE_IMPL(tristate3, "TTL_TRISTATE3", "")

View File

@ -85,7 +85,7 @@ namespace netlist
nld_a_to_d_proxy::nld_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, const logic_input_t *in_proxied)
: nld_base_a_to_d_proxy(anetlist, name, in_proxied)
, m_Q(*this, "Q")
, m_I(*this, "I")
, m_I(*this, "I", nldelegate(&nld_a_to_d_proxy::input, this))
{
}
@ -93,7 +93,7 @@ namespace netlist
{
}
NETLIB_UPDATE(a_to_d_proxy)
NETLIB_HANDLER(a_to_d_proxy, input)
{
const auto v(m_I.Q_Analog());
const auto vn(m_tn->net().Q_Analog());
@ -121,7 +121,7 @@ namespace netlist
nld_d_to_a_proxy::nld_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, const logic_output_t *out_proxied)
: nld_base_d_to_a_proxy(anetlist, name, out_proxied)
, m_I(*this, "I")
, m_I(*this, "I", nldelegate(&nld_d_to_a_proxy :: input, this))
, m_RP(*this, "RP")
, m_RN(*this, "RN")
, m_last_state(*this, "m_last_var", terminal_t::OUT_TRISTATE())
@ -158,7 +158,7 @@ namespace netlist
nlconst::zero());
}
NETLIB_UPDATE(d_to_a_proxy)
NETLIB_HANDLER(d_to_a_proxy ,input)
{
const auto state = m_I();
if (state != m_last_state)

View File

@ -70,9 +70,14 @@ namespace devices
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
input();
}
private:
NETLIB_HANDLERI(input);
logic_output_t m_Q;
analog_input_t m_I;
};
@ -109,9 +114,13 @@ namespace devices
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
input();
}
private:
NETLIB_HANDLERI(input);
static constexpr const nl_fptype G_OFF = nlconst::cgmin();

View File

@ -51,7 +51,7 @@ namespace devices
NETLIB_OBJECT(clock)
{
NETLIB_CONSTRUCTOR(clock)
, m_feedback(*this, "FB")
, m_feedback(*this, "FB", NETLIB_DELEGATE(fb))
, m_Q(*this, "Q")
, m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0))
, m_supply(*this)
@ -67,6 +67,11 @@ namespace devices
}
NETLIB_UPDATEI()
{
fb();
}
NETLIB_HANDLERI(fb)
{
m_Q.push(m_feedback() ^ 1, m_inc);
}
@ -90,7 +95,7 @@ namespace devices
NETLIB_CONSTRUCTOR(varclock)
, m_N(*this, "N", 1)
, m_func(*this,"FUNC", "T")
, m_feedback(*this, "FB")
, m_feedback(*this, "FB", NETLIB_DELEGATE(fb))
, m_Q(*this, "Q")
, m_compiled(*this, "m_compiled")
, m_supply(*this)
@ -103,7 +108,7 @@ namespace devices
for (int i=0; i < m_N(); i++)
{
pstring inpname = plib::pfmt("A{1}")(i);
m_I.push_back(state().make_pool_object<analog_input_t>(*this, inpname));
m_I.push_back(state().make_pool_object<analog_input_t>(*this, inpname, NETLIB_DELEGATE(fb)));
inps.push_back(inpname);
m_vals.push_back(nlconst::zero());
}
@ -115,6 +120,12 @@ namespace devices
//NETLIB_UPDATE_PARAMI()
NETLIB_UPDATEI()
{
fb();
}
private:
NETLIB_HANDLERI(fb)
{
m_vals[0] = exec().time().as_fp<nl_fptype>();
for (std::size_t i = 0; i < static_cast<unsigned>(m_N()); i++)
@ -125,7 +136,6 @@ namespace devices
m_Q.push(m_feedback() ^ 1, m_inc);
}
private:
using pf_type = plib::pfunction<nl_fptype>;
param_int_t m_N;
param_str_t m_func;
@ -149,7 +159,7 @@ namespace devices
, m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0))
, m_pattern(*this, "PATTERN", "1,1")
, m_offset(*this, "OFFSET", nlconst::zero())
, m_feedback(*this, "FB")
, m_feedback(*this, "FB", NETLIB_DELEGATE(first))
, m_Q(*this, "Q")
, m_cnt(*this, "m_cnt", 0)
, m_off(*this, "m_off", netlist_time::zero())
@ -182,15 +192,50 @@ namespace devices
}
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATEI()
{
first();
}
NETLIB_RESETI()
{
m_cnt = 0;
m_off = netlist_time::from_fp<decltype(m_offset())>(m_offset());
m_feedback.set_delegate(NETLIB_DELEGATE(first));
}
//NETLIB_UPDATE_PARAMI();
NETLIB_HANDLERI(clk2);
NETLIB_HANDLERI(clk2_pow2);
private:
NETLIB_HANDLERI(clk2)
{
m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]);
if (++m_cnt >= m_size)
m_cnt = 0;
}
NETLIB_HANDLERI(clk2_pow2)
{
m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]);
m_cnt = (++m_cnt) & (m_size-1);
}
NETLIB_HANDLERI(first)
{
m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off());
m_off = netlist_time::zero();
if (++m_cnt >= m_size)
m_cnt = 0;
// continue with optimized clock handlers ....
if ((m_size & (m_size-1)) == 0) // power of 2?
m_feedback.set_delegate(nldelegate(&NETLIB_NAME(extclock)::clk2_pow2, this));
else
m_feedback.set_delegate(nldelegate(&NETLIB_NAME(extclock)::clk2, this));
}
param_fp_t m_freq;
param_str_t m_pattern;
param_fp_t m_offset;
@ -301,7 +346,7 @@ namespace devices
{
public:
NETLIB_CONSTRUCTOR(nc_pin)
, m_I(*this, "I")
, m_I(*this, "I", NETLIB_DELEGATE(noop))
{
}
@ -310,6 +355,10 @@ namespace devices
NETLIB_UPDATEI() { }
private:
NETLIB_HANDLERI(noop)
{
}
analog_input_t m_I;
};
@ -324,7 +373,7 @@ namespace devices
NETLIB_CONSTRUCTOR(frontier)
, m_RIN(*this, "m_RIN", true)
, m_ROUT(*this, "m_ROUT", true)
, m_I(*this, "_I")
, m_I(*this, "_I", NETLIB_DELEGATE(input))
, m_Q(*this, "_Q")
, m_p_RIN(*this, "RIN", nlconst::magic(1.0e6))
, m_p_ROUT(*this, "ROUT", nlconst::magic(50.0))
@ -347,10 +396,15 @@ namespace devices
NETLIB_UPDATEI()
{
m_Q.push(m_I());
input();
}
private:
NETLIB_HANDLERI(input)
{
m_Q.push(m_I());
}
analog::NETLIB_NAME(twoterm) m_RIN;
analog::NETLIB_NAME(twoterm) m_ROUT;
analog_input_t m_I;
@ -376,7 +430,7 @@ namespace devices
for (int i=0; i < m_N(); i++)
{
pstring inpname = plib::pfmt("A{1}")(i);
m_I.push_back(state().make_pool_object<analog_input_t>(*this, inpname));
m_I.push_back(state().make_pool_object<analog_input_t>(*this, inpname, NETLIB_DELEGATE(inputs)));
inps.push_back(inpname);
m_vals.push_back(nlconst::zero());
}
@ -390,6 +444,11 @@ namespace devices
}
NETLIB_UPDATEI()
{
inputs();
}
NETLIB_HANDLERI(inputs)
{
for (std::size_t i = 0; i < static_cast<unsigned>(m_N()); i++)
{
@ -421,7 +480,7 @@ namespace devices
, m_RON(*this, "RON", nlconst::one())
, m_ROFF(*this, "ROFF", nlconst::magic(1.0E20))
, m_R(*this, "_R")
, m_I(*this, "I")
, m_I(*this, "I", NETLIB_DELEGATE(input))
, m_last_state(*this, "m_last_state", 0)
{
register_subalias("1", m_R.P());
@ -434,21 +493,6 @@ namespace devices
m_R.set_R(m_ROFF());
}
NETLIB_UPDATEI()
{
const netlist_sig_t state = m_I();
if (state != m_last_state)
{
m_last_state = state;
const nl_fptype R = (state != 0) ? m_RON() : m_ROFF();
m_R.change_state([this, &R]()
{
m_R.set_R(R);
});
}
}
//NETLIB_UPDATE_PARAMI();
//FIXME: used by 74123
@ -461,6 +505,26 @@ namespace devices
param_fp_t m_ROFF;
private:
NETLIB_UPDATEI()
{
input();
}
NETLIB_HANDLERI(input)
{
const netlist_sig_t state = m_I();
if (state != m_last_state)
{
m_last_state = state;
const nl_fptype R = (state != 0) ? m_RON() : m_ROFF();
m_R.change_state([this, &R]()
{
m_R.set_R(R);
});
}
}
analog::NETLIB_SUB(R_base) m_R;
logic_input_t m_I;
@ -477,7 +541,7 @@ namespace devices
NETLIB_CONSTRUCTOR(sys_dsw2)
, m_R1(*this, "_R1")
, m_R2(*this, "_R2")
, m_I(*this, "I")
, m_I(*this, "I", NETLIB_DELEGATE(input))
, m_GON(*this, "GON", nlconst::magic(1e9)) // FIXME: all switches should have some on value
, m_GOFF(*this, "GOFF", nlconst::cgmin())
, m_power_pins(*this)
@ -495,7 +559,15 @@ namespace devices
m_R2.set_G(m_GON());
}
//NETLIB_UPDATE_PARAMI();
private:
NETLIB_UPDATEI()
{
input();
}
NETLIB_HANDLERI(input)
{
const netlist_sig_t state = m_I();
@ -523,9 +595,6 @@ namespace devices
}
}
//NETLIB_UPDATE_PARAMI();
private:
analog::NETLIB_SUB(R_base) m_R1;
analog::NETLIB_SUB(R_base) m_R2;
logic_input_t m_I;
@ -544,8 +613,8 @@ namespace devices
{
public:
NETLIB_CONSTRUCTOR(sys_compd)
, m_IP(*this, "IP")
, m_IN(*this, "IN")
, m_IP(*this, "IP", NETLIB_DELEGATE(inputs))
, m_IN(*this, "IN", NETLIB_DELEGATE(inputs))
, m_Q(*this, "Q")
, m_QQ(*this, "QQ")
, m_power_pins(*this)
@ -559,6 +628,14 @@ namespace devices
}
NETLIB_UPDATEI()
{
inputs();
}
//NETLIB_UPDATE_PARAMI();
private:
NETLIB_HANDLERI(inputs)
{
const netlist_sig_t state = (m_IP() > m_IN());
if (state != m_last_state)
@ -570,9 +647,6 @@ namespace devices
}
}
//NETLIB_UPDATE_PARAMI();
private:
analog_input_t m_IP;
analog_input_t m_IN;
logic_output_t m_Q;
@ -588,6 +662,9 @@ namespace devices
/// An externally clocked noise source. The noise acts as a voltage source
/// with internal resistance RI.
///
/// Since a new random value is used on each state change on I the effective
/// frequency is clock source frequency times two!
///
/// Typical application:
///
/// VCC
@ -621,7 +698,7 @@ namespace devices
NETLIB_CONSTRUCTOR(sys_noise)
, m_T(*this, "m_T")
, m_I(*this, "I")
, m_I(*this, "I", NETLIB_DELEGATE(input))
, m_RI(*this, "RI", nlconst::magic(0.1))
, m_sigma(*this, "SIGMA", nlconst::zero())
, m_mt(*this, "m_mt")
@ -632,9 +709,13 @@ namespace devices
register_subalias("2", m_T.N());
}
protected:
private:
NETLIB_UPDATEI()
{
input();
}
NETLIB_HANDLERI(input)
{
nl_fptype val = m_dis.var()(m_mt.var());
m_T.change_state([this, val]()
@ -648,7 +729,6 @@ namespace devices
m_T.set_G_V_I(plib::reciprocal(m_RI()), nlconst::zero(), nlconst::zero());
}
private:
analog::NETLIB_SUB(twoterm) m_T;
logic_input_t m_I;
param_fp_t m_RI;

View File

@ -81,6 +81,11 @@ namespace devices
// update is only called during startup here ...
NETLIB_UPDATEI()
{
inputs();
}
NETLIB_HANDLERI(inputs)
{
#if USE_TT_ALTERNATIVE
m_state = 0;
for (std::size_t i = 0; i < m_NI; ++i)
@ -390,7 +395,7 @@ namespace devices
for (std::size_t i=0; i < m_NI; i++)
{
inout[i] = plib::trim(inout[i]);
m_I.emplace(i, *this, inout[i]);
m_I.emplace(i, *this, inout[i], nldelegate(&NETLIB_NAME(truthtable_t)<m_NI, m_NO> :: inputs, this));
}
#else
for (std::size_t i=0; i < m_NI; i++)

View File

@ -717,7 +717,7 @@ namespace netlist
// ----------------------------------------------------------------------------------------
terminal_t::terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm)
: analog_t(dev, aname, STATE_BIDIR)
: analog_t(dev, aname, STATE_BIDIR, nldelegate())
, m_Idr(nullptr)
, m_go(nullptr)
, m_gt(nullptr)
@ -782,7 +782,7 @@ namespace netlist
// ----------------------------------------------------------------------------------------
logic_output_t::logic_output_t(device_t &dev, const pstring &aname, bool dummy)
: logic_t(dev, aname, STATE_OUT)
: logic_t(dev, aname, STATE_OUT, nldelegate())
, m_my_net(dev.state(), name() + ".net", this)
{
plib::unused_var(dummy);
@ -813,7 +813,7 @@ namespace netlist
// ----------------------------------------------------------------------------------------
analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname)
: analog_t(dev, aname, STATE_OUT)
: analog_t(dev, aname, STATE_OUT, nldelegate())
, m_my_net(dev.state(), name() + ".net", this)
{
state().register_net(device_arena::owned_ptr<analog_net_t>(&m_my_net, false));

View File

@ -627,7 +627,7 @@ namespace netlist
};
core_terminal_t(core_device_t &dev, const pstring &aname,
state_e state, nldelegate delegate = nldelegate());
state_e state, nldelegate delegate);
virtual ~core_terminal_t() noexcept = default;
PCOPYASSIGNMOVE(core_terminal_t, delete)
@ -813,7 +813,7 @@ namespace netlist
public:
analog_t(core_device_t &dev, const pstring &aname, state_e state,
nldelegate delegate = nldelegate());
nldelegate delegate);
const analog_net_t & net() const noexcept;
analog_net_t & net() noexcept;
@ -890,7 +890,7 @@ namespace netlist
{
public:
logic_t(device_t &dev, const pstring &aname,
state_e terminal_state, nldelegate delegate = nldelegate());
state_e terminal_state, nldelegate delegate);
logic_net_t & net() noexcept;
const logic_net_t & net() const noexcept;
@ -904,7 +904,7 @@ namespace netlist
{
public:
logic_input_t(device_t &dev, const pstring &aname,
nldelegate delegate = nldelegate());
nldelegate delegate);
#if 0
template <class D>
@ -933,7 +933,7 @@ namespace netlist
/// \brief Constructor
analog_input_t(core_device_t &dev, ///< owning device
const pstring &aname, ///< name of terminal
nldelegate delegate = nldelegate() ///< delegate
nldelegate delegate ///< delegate
);
/// \brief returns voltage at terminal.

View File

@ -51,13 +51,11 @@ namespace netlist
///
template <typename FUNC>
class NETLIB_NAME(analog_callback) : public device_t
NETLIB_OBJECT(analog_callback)
{
public:
NETLIB_NAME(analog_callback)(netlist_state_t &anetlist,
const pstring &name, nl_fptype threshold, FUNC &&func)
: device_t(anetlist, name)
, m_in(*this, "IN")
NETLIB_CONSTRUCTOR_EX(analog_callback, nl_fptype threshold, FUNC &&func)
, m_in(*this, "IN", NETLIB_DELEGATE(in))
, m_threshold(threshold)
, m_last(*this, "m_last", 0)
, m_func(func)
@ -70,6 +68,11 @@ namespace netlist
}
NETLIB_UPDATEI()
{
in();
}
NETLIB_HANDLERI(in)
{
const nl_fptype cur = m_in();
if (plib::abs(cur - m_last) > m_threshold)

View File

@ -49,7 +49,7 @@ namespace solver
, m_stat_newton_raphson_fail(*this, "m_stat_newton_raphson_fail", 0)
, m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0)
, m_last_step(*this, "m_last_step", netlist_time_ext::zero())
, m_fb_sync(*this, "FB_sync")
, m_fb_sync(*this, "FB_sync", nldelegate(&matrix_solver_t::fb_sync, this))
, m_Q_sync(*this, "Q_sync")
, m_ops(0)
{

View File

@ -254,6 +254,11 @@ namespace solver
// netdevice functions
NETLIB_UPDATEI()
{
fb_sync();
}
NETLIB_HANDLERI(fb_sync)
{
PFDEBUG(printf("update\n");)
const netlist_time new_timestep = solve(exec().time());

View File

@ -42,7 +42,7 @@ namespace devices
s->log_stats();
}
NETLIB_UPDATE(solver)
NETLIB_HANDLER(solver, fb_step)
{
if (m_params.m_dynamic_ts)
return;

View File

@ -27,7 +27,7 @@ namespace devices
NETLIB_OBJECT(solver)
{
NETLIB_CONSTRUCTOR(solver)
, m_fb_step(*this, "FB_step")
, m_fb_step(*this, "FB_step", NETLIB_DELEGATE(fb_step))
, m_Q_step(*this, "Q_step")
, m_params(*this)
{
@ -43,7 +43,11 @@ namespace devices
solver::static_compile_container create_solver_code(solver::static_compile_target target);
NETLIB_UPDATEI();
NETLIB_UPDATEI()
{
fb_step();
}
NETLIB_RESETI();
// NETLIB_UPDATE_PARAMI();
@ -52,6 +56,8 @@ namespace devices
using net_list_t = solver::matrix_solver_t::net_list_t;
private:
NETLIB_HANDLERI(fb_step);
logic_input_t m_fb_step;
logic_output_t m_Q_step;