summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/devices/nlid_system.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/devices/nlid_system.h')
-rw-r--r--src/lib/netlist/devices/nlid_system.h718
1 files changed, 422 insertions, 296 deletions
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index 89a525ef69f..fee4fad0333 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -1,86 +1,22 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
-/*
- * nlid_system.h
- *
- * netlist devices defined in the core
- *
- * This file contains internal headers
- */
-
#ifndef NLID_SYSTEM_H_
#define NLID_SYSTEM_H_
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/nl_base.h"
-#include "netlist/nl_setup.h"
-#include "plib/putil.h"
+///
+/// \file nlid_system.h
+///
-namespace netlist
-{
-namespace devices
-{
- // -----------------------------------------------------------------------------
- // netlistparams
- // -----------------------------------------------------------------------------
-
- NETLIB_OBJECT(netlistparams)
- {
- NETLIB_CONSTRUCTOR(netlistparams)
- , m_use_deactivate(*this, "USE_DEACTIVATE", false)
- , m_startup_strategy(*this, "STARTUP_STRATEGY", 1)
- , m_mos_capmodel(*this, "DEFAULT_MOS_CAPMODEL", 2)
- , m_max_link_loops(*this, "MAX_LINK_RESOLVE_LOOPS", 100)
- {
- }
- NETLIB_UPDATEI() { }
- //NETLIB_RESETI() { }
- //NETLIB_UPDATE_PARAMI() { }
- public:
- param_logic_t m_use_deactivate;
- param_num_t<unsigned> m_startup_strategy;
- param_num_t<unsigned> m_mos_capmodel;
- //! How many times do we try to resolve links (connections)
- param_num_t<unsigned> m_max_link_loops;
- };
-
- // -----------------------------------------------------------------------------
- // mainclock
- // -----------------------------------------------------------------------------
-
- NETLIB_OBJECT(mainclock)
- {
- NETLIB_CONSTRUCTOR(mainclock)
- , m_Q(*this, "Q")
- , m_freq(*this, "FREQ", 7159000.0 * 5)
- {
- m_inc = netlist_time::from_double(1.0 / (m_freq()*2.0));
- }
-
- NETLIB_RESETI()
- {
- m_Q.net().set_next_scheduled_time(netlist_time::zero());
- }
-
- NETLIB_UPDATE_PARAMI()
- {
- m_inc = netlist_time::from_double(1.0 / (m_freq()*2.0));
- }
+#include "analog/nlid_twoterm.h"
+#include "nl_base.h"
+#include "nl_factory.h"
+#include "plib/prandom.h"
+#include "plib/pstonum.h"
+#include "plib/putil.h"
- NETLIB_UPDATEI()
- {
- logic_net_t &net = m_Q.net();
- // this is only called during setup ...
- net.toggle_new_Q();
- net.set_next_scheduled_time(exec().time() + m_inc);
- }
+#include <random>
- public:
- logic_output_t m_Q;
- netlist_time m_inc;
- private:
- param_double_t m_freq;
- };
+namespace netlist::devices {
// -----------------------------------------------------------------------------
// clock
@@ -89,134 +25,99 @@ 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", 7159000.0 * 5.0)
+ , m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0))
+ , m_supply(*this)
{
- m_inc = netlist_time::from_double(1.0 / (m_freq()*2.0));
+ m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two()));
- connect(m_feedback, m_Q);
+ connect("FB", "Q");
}
- //NETLIB_RESETI();
NETLIB_UPDATE_PARAMI()
{
- m_inc = netlist_time::from_double(1.0 / (m_freq() * 2.0));
+ m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two()));
}
- NETLIB_UPDATEI()
+ NETLIB_HANDLERI(fb)
{
- m_Q.push(!m_feedback(), m_inc);
+ m_Q.push(m_feedback() ^ 1, m_inc);
}
private:
logic_input_t m_feedback;
logic_output_t m_Q;
- param_double_t m_freq;
+ param_fp_t m_freq;
netlist_time m_inc;
- };
+
+ NETLIB_NAME(power_pins) m_supply;
+};
// -----------------------------------------------------------------------------
- // varclock
+ // variable clock
// -----------------------------------------------------------------------------
NETLIB_OBJECT(varclock)
{
NETLIB_CONSTRUCTOR(varclock)
- , m_feedback(*this, "FB")
+ , m_N(*this, "N", 1)
+ , m_func(*this,"FUNC", "T")
+ , m_feedback(*this, "FB", NETLIB_DELEGATE(fb))
, m_Q(*this, "Q")
- , m_func(*this,"FUNC", "")
- , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
- , m_funcparam({0.0})
+ , m_compiled(*this, "m_compiled")
+ , m_supply(*this)
{
- if (m_func() != "")
- m_compiled.compile(std::vector<pstring>({{"T"}}), m_func());
- connect(m_feedback, m_Q);
+ if (!m_func().empty())
+ {
+ std::vector<pstring> inputs;
+
+ m_I.reserve(m_N());
+ inputs.reserve(m_N() + 1);
+ m_vals.reserve(m_N() + 1);
+
+ // add time parameter to the front
+ inputs.emplace_back("T");
+ m_vals.push_back(nlconst::zero());
+
+ for (std::uint64_t i=0; i < m_N(); i++)
+ {
+ pstring input_name = plib::pfmt("A{1}")(i);
+ m_I.push_back(state().make_pool_object<analog_input_t>(*this, input_name, NETLIB_DELEGATE(fb)));
+ inputs.push_back(input_name);
+ m_vals.push_back(nlconst::zero());
+ }
+ m_compiled->compile(m_func(), inputs);
+ }
+ connect("FB", "Q");
}
//NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI()
- NETLIB_UPDATEI()
- {
- m_funcparam[0] = exec().time().as_double();
- const netlist_time m_inc = netlist_time::from_double(m_compiled.evaluate(m_funcparam));
- m_Q.push(!m_feedback(), m_inc);
- }
-
private:
- logic_input_t m_feedback;
- logic_output_t m_Q;
-
- param_str_t m_func;
- plib::pfunction m_compiled;
- std::vector<double> m_funcparam;
- };
-
- // -----------------------------------------------------------------------------
- // extclock
- // -----------------------------------------------------------------------------
-
- NETLIB_OBJECT(extclock)
- {
- NETLIB_CONSTRUCTOR(extclock)
- , m_freq(*this, "FREQ", 7159000.0 * 5.0)
- , m_pattern(*this, "PATTERN", "1,1")
- , m_offset(*this, "OFFSET", 0.0)
- , m_feedback(*this, "FB")
- , m_Q(*this, "Q")
- , m_cnt(*this, "m_cnt", 0)
- , m_off(*this, "m_off", netlist_time::zero())
+ NETLIB_HANDLERI(fb)
{
- m_inc[0] = netlist_time::from_double(1.0 / (m_freq() * 2.0));
-
- connect(m_feedback, m_Q);
-
- netlist_time base = netlist_time::from_double(1.0 / (m_freq()*2.0));
- std::vector<pstring> pat(plib::psplit(m_pattern(),","));
- m_off = netlist_time::from_double(m_offset());
-
- std::array<std::int64_t, 32> pati = { 0 };
-
- m_size = static_cast<std::uint8_t>(pat.size());
- netlist_time::mult_type total = 0;
- for (unsigned i=0; i<m_size; i++)
- {
- // FIXME: use pstonum_ne
- //pati[i] = plib::pstonum<decltype(pati[i])>(pat[i]);
- pati[i] = plib::pstonum<std::int64_t>(pat[i]);
- total += pati[i];
- }
- netlist_time ttotal = netlist_time::zero();
- auto sm1 = static_cast<uint8_t>(m_size - 1);
- for (unsigned i=0; i < sm1; i++)
+ m_vals[0] = exec().time().as_fp<nl_fptype>();
+ for (std::size_t i = 0; i < static_cast<unsigned>(m_N()); i++)
{
- m_inc[i] = base * pati[i];
- ttotal += m_inc[i];
+ m_vals[i+1] = (*m_I[i])();
}
- m_inc[sm1] = base * total - ttotal;
-
+ const netlist_time m_inc = netlist_time::from_fp(m_compiled->evaluate(m_vals));
+ m_Q.push(m_feedback() ^ 1, m_inc);
}
- NETLIB_UPDATEI();
- NETLIB_RESETI();
- //NETLIB_UPDATE_PARAMI();
-
- NETLIB_HANDLERI(clk2);
- NETLIB_HANDLERI(clk2_pow2);
-
- private:
-
- param_double_t m_freq;
- param_str_t m_pattern;
- param_double_t m_offset;
-
+ using pf_type = plib::pfunction<nl_fptype>;
+ param_num_t<std::uint64_t> m_N;
+ param_str_t m_func;
logic_input_t m_feedback;
logic_output_t m_Q;
- state_var_u8 m_cnt;
- std::uint8_t m_size;
- state_var<netlist_time> m_off;
- std::array<netlist_time, 32> m_inc;
+ std::vector<device_arena::unique_ptr<analog_input_t>> m_I;
+
+ pf_type::values_container m_vals;
+ state_var<pf_type> m_compiled;
+
+ NETLIB_NAME(power_pins) m_supply;
};
// -----------------------------------------------------------------------------
@@ -228,241 +129,466 @@ namespace devices
NETLIB_CONSTRUCTOR(logic_input)
, m_Q(*this, "Q")
, m_IN(*this, "IN", false)
- /* make sure we get the family first */
- , m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)")
+ , m_supply(*this)
{
- set_logic_family(setup().family_from_model(m_FAMILY()));
- m_Q.set_logic_family(this->logic_family());
}
- NETLIB_UPDATEI() { }
NETLIB_RESETI() { m_Q.initial(0); }
- NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN() & 1, netlist_time::from_nsec(1)); }
+ NETLIB_UPDATE_PARAMI()
+ {
+ //printf("%s %d\n", name().c_str(), m_IN());
+ m_Q.push(m_IN() & 1, netlist_time::from_nsec(1));
+ }
private:
logic_output_t m_Q;
param_logic_t m_IN;
- param_model_t m_FAMILY;
+ NETLIB_NAME(power_pins) m_supply;
};
- NETLIB_OBJECT(analog_input)
+ template<std::size_t N>
+ NETLIB_OBJECT(logic_inputN)
{
- NETLIB_CONSTRUCTOR(analog_input)
- , m_Q(*this, "Q")
- , m_IN(*this, "IN", 0.0)
+ NETLIB_CONSTRUCTOR(logic_inputN)
+ , m_Q(*this, "Q{}")
+ , m_IN(*this, "IN", 0)
+ , m_supply(*this)
{
}
- NETLIB_UPDATEI() { }
- NETLIB_RESETI() { m_Q.initial(0.0); }
- NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); }
+ NETLIB_RESETI() { for (auto &q : m_Q) q.initial(0); }
+ NETLIB_UPDATE_PARAMI()
+ {
+ //printf("%s %d\n", name().c_str(), m_IN());
+ for (std::size_t i=0; i<N; i++)
+ m_Q[i].push((m_IN()>>i) & 1, netlist_time::from_nsec(1));
+ }
private:
- analog_output_t m_Q;
- param_double_t m_IN;
- };
+ object_array_t<logic_output_t, N> m_Q;
- // -----------------------------------------------------------------------------
- // nld_gnd
- // -----------------------------------------------------------------------------
-
- NETLIB_OBJECT(gnd)
- {
- NETLIB_CONSTRUCTOR(gnd)
- , m_Q(*this, "Q")
- {
- }
- NETLIB_UPDATEI()
- {
- m_Q.push(0.0);
- }
- NETLIB_RESETI() { }
- protected:
- analog_output_t m_Q;
+ param_int_t m_IN;
+ NETLIB_NAME(power_pins) m_supply;
};
- // -----------------------------------------------------------------------------
- // nld_dummy_input
- // -----------------------------------------------------------------------------
-
- NETLIB_OBJECT(dummy_input)
+ NETLIB_OBJECT(analog_input)
{
- public:
- NETLIB_CONSTRUCTOR(dummy_input)
- , m_I(*this, "I")
+ NETLIB_CONSTRUCTOR(analog_input)
+ , m_Q(*this, "Q")
+ , m_IN(*this, "IN", nlconst::zero())
{
}
- protected:
-
- NETLIB_RESETI() { }
- NETLIB_UPDATEI() { }
+ NETLIB_RESETI() { m_Q.initial(nlconst::zero()); }
+ NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); }
private:
- analog_input_t m_I;
-
+ analog_output_t m_Q;
+ param_fp_t m_IN;
};
+
// -----------------------------------------------------------------------------
// nld_frontier
// -----------------------------------------------------------------------------
+
+ /// \brief Frontiers divides a netlist into sub netlist
+ ///
+ /// Example:
+ ///
+ /// Consider the following mixing stage
+ ///
+ /// R1
+ /// I1 >-----1RRRR2---------+
+ /// |
+ /// R2 |
+ /// I2 >-----1RRRR2---------+----------> Out
+ /// |
+ /// R
+ /// R3 R
+ /// R
+ /// |
+ /// GND
+ ///
+ /// With OPTIMIZE_FRONTIER(R2.1, R2, RX) where RX is the impedance of the
+ /// output connected to I2 this becomes:
+ ///
+ /// R1
+ /// I1 >-----1RRRR2--------------------------------+
+ /// |
+ /// ########################## |
+ /// # RX # R2 |
+ /// I2 >----->--+-AnIn AnOut>--RRRR--->---1RRRR2---+----------> Out
+ /// # | # |
+ /// # R # R
+ /// # R R2 # R3 R
+ /// # R # R
+ /// # | # |
+ /// # GND Frontier # GND
+ /// # #
+ /// ##########################
+ ///
+ /// As a result, provided there are no other connections between the parts
+ /// generating S1 and S2 the "S2 part" will now have a separate solver.
+ ///
+ /// The size (aka number of nets) of the solver for I1 will be smaller.
+ /// The size of the solver for I2 and the rest of the circuit will be smaller
+ /// as well.
+ ///
+
NETLIB_OBJECT(frontier)
{
- public:
NETLIB_CONSTRUCTOR(frontier)
- , m_RIN(*this, "m_RIN", true)
- , m_ROUT(*this, "m_ROUT", true)
- , m_I(*this, "_I")
+ , m_RIN(*this, "m_RIN", NETLIB_DELEGATE(input)) // FIXME: does not look right
+ , m_ROUT(*this, "m_ROUT", NETLIB_DELEGATE(input)) // FIXME: does not look right
+ , m_I(*this, "_I", NETLIB_DELEGATE(input))
, m_Q(*this, "_Q")
- , m_p_RIN(*this, "RIN", 1.0e6)
- , m_p_ROUT(*this, "ROUT", 50.0)
+ , m_p_RIN(*this, "RIN", nlconst::magic(1.0e6))
+ , m_p_ROUT(*this, "ROUT", nlconst::magic(50.0))
{
- register_subalias("I", m_RIN.m_P);
- register_subalias("G", m_RIN.m_N);
- connect(m_I, m_RIN.m_P);
+ register_sub_alias("I", "m_RIN.1");
+ register_sub_alias("G", "m_RIN.2");
+ connect("_I", "m_RIN.1");
- register_subalias("_OP", m_ROUT.m_P);
- register_subalias("Q", m_ROUT.m_N);
- connect(m_Q, m_ROUT.m_P);
+ register_sub_alias("_OP", "m_ROUT.1");
+ register_sub_alias("Q", "m_ROUT.2");
+ connect("_Q", "m_ROUT.1");
}
+ private:
NETLIB_RESETI()
{
- m_RIN.set_G_V_I(1.0 / m_p_RIN(),0,0);
- m_ROUT.set_G_V_I(1.0 / m_p_ROUT(),0,0);
+ //printf("%s: in %f out %f\n", name().c_str(), m_p_RIN(), m_p_ROUT());
+ m_RIN.set_G_V_I(plib::reciprocal(m_p_RIN()),0,0);
+ m_ROUT.set_G_V_I(plib::reciprocal(m_p_ROUT()),0,0);
}
- NETLIB_UPDATEI()
+ NETLIB_HANDLERI(input)
{
m_Q.push(m_I());
}
- private:
- analog::NETLIB_NAME(twoterm) m_RIN;
- /* Fixme: only works if the device is time-stepped - need to rework */
- analog::NETLIB_NAME(twoterm) m_ROUT;
+ analog::NETLIB_NAME(two_terminal) m_RIN;
+ analog::NETLIB_NAME(two_terminal) m_ROUT;
analog_input_t m_I;
analog_output_t m_Q;
- param_double_t m_p_RIN;
- param_double_t m_p_ROUT;
+ param_fp_t m_p_RIN;
+ param_fp_t m_p_ROUT;
};
- /* -----------------------------------------------------------------------------
- * nld_function
- *
- * FIXME: Currently a proof of concept to get congo bongo working
- * ----------------------------------------------------------------------------- */
+ // -----------------------------------------------------------------------------
+ // nld_function
+ // ----------------------------------------------------------------------------- */
NETLIB_OBJECT(function)
{
NETLIB_CONSTRUCTOR(function)
, m_N(*this, "N", 1)
- , m_func(*this, "FUNC", "A0")
+ , m_function(*this, "FUNC", "A0")
+ , m_thresh(*this, "THRESH", nlconst::zero())
, m_Q(*this, "Q")
- , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
+ , m_compiled(*this, "m_compiled")
+ , m_last(*this, "m_last")
{
- std::vector<pstring> inps;
- for (int i=0; i < m_N(); i++)
+ std::vector<pstring> inputs;
+
+ m_I.reserve(m_N());
+ inputs.reserve(m_N());
+ m_values.reserve(m_N());
+
+ for (uint64_t i=0; i < m_N(); i++)
{
- pstring n = plib::pfmt("A{1}")(i);
- m_I.push_back(pool().make_poolptr<analog_input_t>(*this, n));
- inps.push_back(n);
- m_vals.push_back(0.0);
+ pstring input_name = plib::pfmt("A{1}")(i);
+ m_I.push_back(state().make_pool_object<analog_input_t>(*this, input_name, NETLIB_DELEGATE(inputs)));
+ inputs.push_back(input_name);
+ m_values.push_back(nlconst::zero());
}
- m_compiled.compile(inps, m_func());
+ m_compiled->compile(m_function(), inputs);
}
protected:
+ NETLIB_RESETI()
+ {
+ //m_Q.initial(0.0);
+ }
- NETLIB_RESETI();
- NETLIB_UPDATEI();
+ NETLIB_HANDLERI(inputs)
+ {
+ for (std::size_t i = 0; i < static_cast<unsigned>(m_N()); i++)
+ {
+ m_values[i] = (*m_I[i])();
+ }
+ auto result = m_compiled->evaluate(m_values);
+ if (plib::abs(m_last - result) >= m_thresh)
+ {
+ m_Q.push(result);
+ m_last = result;
+ }
+ }
private:
-
- param_int_t m_N;
- param_str_t m_func;
+ using pf_type = plib::pfunction<nl_fptype>;
+ param_num_t<std::uint64_t> m_N;
+ param_str_t m_function;
+ param_fp_t m_thresh;
analog_output_t m_Q;
- std::vector<pool_owned_ptr<analog_input_t>> m_I;
+ std::vector<device_arena::unique_ptr<analog_input_t>> m_I;
+
+ pf_type::values_container m_values;
+ state_var<pf_type> m_compiled;
+ state_var<nl_fptype> m_last;
- std::vector<double> m_vals;
- plib::pfunction m_compiled;
};
// -----------------------------------------------------------------------------
- // nld_res_sw
+ // nld_sys_dsw1
// -----------------------------------------------------------------------------
- NETLIB_OBJECT(res_sw)
+ NETLIB_OBJECT(sys_dsw1)
{
- public:
- NETLIB_CONSTRUCTOR(res_sw)
+ NETLIB_CONSTRUCTOR(sys_dsw1)
+ , m_RON(*this, "RON", nlconst::one())
+ , m_ROFF(*this, "ROFF", nlconst::magic(1.0E20))
, m_R(*this, "_R")
- , m_I(*this, "I")
- , m_RON(*this, "RON", 1.0)
- , m_ROFF(*this, "ROFF", 1.0E20)
+ , m_I(*this, "I", NETLIB_DELEGATE(input))
, m_last_state(*this, "m_last_state", 0)
{
- register_subalias("1", m_R.m_P);
- register_subalias("2", m_R.m_N);
+ register_sub_alias("1", "_R.1");
+ register_sub_alias("2", "_R.2");
+ }
+
+ NETLIB_RESETI()
+ {
+ m_last_state = 0;
+ m_R().set_R(m_ROFF());
}
- NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATEI();
- analog::NETLIB_SUB(R_base) m_R;
- logic_input_t m_I;
- param_double_t m_RON;
- param_double_t m_ROFF;
+ //FIXME: used by 74123
+
+ const terminal_t &P() const noexcept { return m_R().P(); }
+ const terminal_t &N() const noexcept { return m_R().N(); }
+ const logic_input_t &I() const noexcept { return m_I; }
+
+ param_fp_t m_RON;
+ param_fp_t m_ROFF;
private:
+ 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);
+ });
+ }
+ }
+
+ NETLIB_SUB_NS(analog, R_base) m_R;
+ logic_input_t m_I;
state_var<netlist_sig_t> m_last_state;
};
// -----------------------------------------------------------------------------
- // power pins - not a device, but a helper
+ // nld_sys_dsw2
// -----------------------------------------------------------------------------
- /**
- * Power Pins are passive inputs. Delegate noop will silently ignore any
- * updates.
- */
- class nld_power_pins
+ NETLIB_OBJECT(sys_dsw2)
{
- public:
- nld_power_pins(device_t &owner, const char *sVCC = "VCC", const char *sGND = "GND", bool force_analog_input = false)
+ NETLIB_CONSTRUCTOR(sys_dsw2)
+ , m_R1(*this, "_R1")
+ , m_R2(*this, "_R2")
+ , 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)
+ {
+ // connect and register pins
+ register_sub_alias("1", "_R1.1");
+ register_sub_alias("2", "_R1.2");
+ register_sub_alias("3", "_R2.2");
+ connect("_R1.2", "_R2.1");
+ }
+
+ private:
+ NETLIB_RESETI()
+ {
+ m_R1().set_G(m_GOFF());
+ m_R2().set_G(m_GON());
+ }
+
+ //NETLIB_UPDATE_PARAMI();
+
+ NETLIB_HANDLERI(input)
{
- if (owner.setup().is_validation() || force_analog_input)
+ const netlist_sig_t state = m_I();
+
+ //printf("Here %d\n", state);
+ const nl_fptype G1 = (state != 0) ? m_GON() : m_GOFF();
+ const nl_fptype G2 = (state != 0) ? m_GOFF() : m_GON();
+ if (m_R1().solver() == m_R2().solver())
{
- m_GND = plib::make_unique<analog_input_t>(owner, sGND, NETLIB_DELEGATE(power_pins, noop));
- m_VCC = plib::make_unique<analog_input_t>(owner, sVCC, NETLIB_DELEGATE(power_pins, noop));
+ m_R1().change_state([this, &G1, &G2]()
+ {
+ m_R1().set_G(G1);
+ m_R2().set_G(G2);
+ });
}
else
{
- owner.create_and_register_subdevice(sPowerDevRes, m_RVG);
- owner.register_subalias(sVCC, "_RVG.1");
- owner.register_subalias(sGND, "_RVG.2");
+ m_R1().change_state([this, &G1]()
+ {
+ m_R1().set_G(G1);
+ });
+ m_R2().change_state([this, &G2]()
+ {
+ m_R2().set_G(G2);
+ });
+ }
+ }
+
+ NETLIB_SUB_NS(analog, R_base) m_R1;
+ NETLIB_SUB_NS(analog, R_base) m_R2;
+ logic_input_t m_I;
+ param_fp_t m_GON;
+ param_fp_t m_GOFF;
+
+ nld_power_pins m_power_pins;
+ };
+
+
+ // -----------------------------------------------------------------------------
+ // nld_sys_comp
+ // -----------------------------------------------------------------------------
+
+ NETLIB_OBJECT(sys_compd)
+ {
+ NETLIB_CONSTRUCTOR(sys_compd)
+ , 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)
+ , m_last_state(*this, "m_last_state", 2) // ensure first execution
+ {
+ }
+
+ private:
+ NETLIB_RESETI()
+ {
+ m_last_state = 0;
+ }
+
+ //NETLIB_UPDATE_PARAMI();
+
+ NETLIB_HANDLERI(inputs)
+ {
+ const netlist_sig_t state = (m_IP() > m_IN());
+ if (state != m_last_state)
+ {
+ m_last_state = state;
+ // FIXME: make timing a parameter
+ m_Q.push(state, NLTIME_FROM_NS(10));
+ m_QQ.push(!state, NLTIME_FROM_NS(10));
}
}
- /* FIXME: this will seg-fault if force_analog_input = false */
- nl_double VCC() const NL_NOEXCEPT { return m_VCC->Q_Analog(); }
- nl_double GND() const NL_NOEXCEPT { return m_GND->Q_Analog(); }
+ analog_input_t m_IP;
+ analog_input_t m_IN;
+ logic_output_t m_Q;
+ logic_output_t m_QQ;
+ nld_power_pins m_power_pins;
- NETLIB_SUBXX(analog, R) m_RVG; // dummy resistor between VCC and GND
+ state_var<netlist_sig_t> m_last_state;
+ };
+
+ ///
+ /// \brief noise source
+ ///
+ /// 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
+ /// |
+ /// R
+ /// R
+ /// R
+ /// |
+ /// +-----> Output
+ /// |
+ /// +-------+
+ /// | 1 |
+ /// --->| I |
+ /// | 2 |
+ /// +-------+
+ /// |
+ /// R
+ /// R
+ /// R
+ /// |
+ /// GND
+ ///
+ // -----------------------------------------------------------------------------
+ template <typename E, template<class> class D>
+ NETLIB_OBJECT(sys_noise)
+ {
+ public:
+
+ using engine = E;
+ using distribution = D<nl_fptype>;
+
+ NETLIB_CONSTRUCTOR(sys_noise)
+ , m_T(*this, "m_T")
+ , 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")
+ , m_dis(*this, "m_dis",m_sigma())
+ {
+
+ register_sub_alias("1", "m_T.1");
+ register_sub_alias("2", "m_T.2");
+ }
private:
- void noop() { }
- plib::unique_ptr<analog_input_t> m_VCC; // only used during validation or force_analog_input
- plib::unique_ptr<analog_input_t> m_GND; // only used during validation or force_analog_input
+ NETLIB_HANDLERI(input)
+ {
+ nl_fptype val = m_dis()(m_mt());
+ m_T().change_state([this, val]()
+ {
+ m_T().set_G_V_I(plib::reciprocal(m_RI()), val, nlconst::zero());
+ });
+ }
+
+ NETLIB_RESETI()
+ {
+ m_T().set_G_V_I(plib::reciprocal(m_RI()), nlconst::zero(), nlconst::zero());
+ }
+
+ NETLIB_SUB_NS(analog, two_terminal) m_T;
+ logic_input_t m_I;
+ param_fp_t m_RI;
+ param_fp_t m_sigma;
+ state_var<engine> m_mt;
+ state_var<distribution> m_dis;
};
-} //namespace devices
-} // namespace netlist
+} // namespace netlist::devices
-#endif /* NLD_SYSTEM_H_ */
+#endif // NLD_SYSTEM_H_