summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/analog/nlid_twoterm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/analog/nlid_twoterm.cpp')
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.cpp361
1 files changed, 201 insertions, 160 deletions
diff --git a/src/lib/netlist/analog/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp
index aaddb65387a..1a3c79e713f 100644
--- a/src/lib/netlist/analog/nlid_twoterm.cpp
+++ b/src/lib/netlist/analog/nlid_twoterm.cpp
@@ -1,190 +1,231 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
-/*
- * nld_twoterm.c
- *
- */
-#include "netlist/solver/nld_solver.h"
-
-#include "netlist/nl_factory.h"
#include "nlid_twoterm.h"
-#include <cmath>
+#include "nl_factory.h"
-namespace netlist
-{
- namespace analog
- {
+#include "solver/nld_solver.h"
-// ----------------------------------------------------------------------------------------
-// nld_twoterm
-// ----------------------------------------------------------------------------------------
-
-void NETLIB_NAME(twoterm)::solve_now()
-{
- /* we only need to call the non-rail terminal */
- if (m_P.has_net() && !m_P.net().isRailNet())
- m_P.solve_now();
- else if (m_N.has_net() && !m_N.net().isRailNet())
- m_N.solve_now();
-}
-
-void NETLIB_NAME(twoterm)::solve_later(netlist_time delay)
+namespace netlist::analog
{
- /* we only need to call the non-rail terminal */
- if (m_P.has_net() && !m_P.net().isRailNet())
- m_P.schedule_solve_after(delay);
- else if (m_N.has_net() && !m_N.net().isRailNet())
- m_N.schedule_solve_after(delay);
-}
+ // -------------------------------------------------------------------------
+ // nld_twoterm
+ // -------------------------------------------------------------------------
-NETLIB_UPDATE(twoterm)
-{
- /* only called if connected to a rail net ==> notify the solver to recalculate */
- solve_now();
-}
-
-// ----------------------------------------------------------------------------------------
-// nld_R_base
-// ----------------------------------------------------------------------------------------
-
-NETLIB_RESET(R_base)
-{
- NETLIB_NAME(twoterm)::reset();
- set_R(1.0 / exec().gmin());
-}
+ solver::matrix_solver_t *nld_two_terminal::solver() const noexcept
+ {
+ auto *solv(m_P.solver());
+ if (solv != nullptr)
+ return solv;
+ return m_N.solver();
+ }
-// ----------------------------------------------------------------------------------------
-// nld_POT
-// ----------------------------------------------------------------------------------------
+ void nld_two_terminal::solve_now() const
+ {
+ auto *solv(solver());
+ if (solv != nullptr)
+ solv->solve_now();
+ }
-NETLIB_RESET(POT)
-{
- nl_double v = m_Dial();
- if (m_DialIsLog())
- v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
+ NETLIB_HANDLER(two_terminal, terminal_handler)
+ {
+ // only called if connected to a rail net ==> notify the solver to
+ // recalculate
+ // printf("%s update\n", this->name().c_str());
+ solve_now();
+ }
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
- m_R2.set_R(std::max(m_R() * (plib::constants<nl_double>::one() - v), exec().gmin()));
-}
+ // -------------------------------------------------------------------------
+ // nld_POT
+ // -------------------------------------------------------------------------
-NETLIB_UPDATE_PARAM(POT)
-{
- m_R1.solve_now();
- m_R2.solve_now();
+ NETLIB_RESET(POT)
+ {
+ nl_fptype v = m_Dial();
+ if (m_DialIsLog())
+ v = (plib::exp(v) - nlconst::one())
+ / (plib::exp(nlconst::one()) - nlconst::one());
- nl_double v = m_Dial();
- if (m_DialIsLog())
- v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
- if (m_Reverse())
- v = 1.0 - v;
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
- m_R2.set_R(std::max(m_R() * (plib::constants<nl_double>::one() - v), exec().gmin()));
+ m_R1().set_R(std::max(m_R() * v, exec().gmin()));
+ m_R2().set_R(std::max(m_R() * (nlconst::one() - v), exec().gmin()));
+ }
-}
+ NETLIB_UPDATE_PARAM(POT)
+ {
+ nl_fptype v = m_Dial();
+ if (m_DialIsLog())
+ v = (plib::exp(v) - nlconst::one())
+ / (plib::exp(nlconst::one()) - nlconst::one());
+ if (m_Reverse())
+ v = nlconst::one() - v;
+
+ nl_fptype r1(std::max(m_R() * v, exec().gmin()));
+ nl_fptype r2(std::max(m_R() * (nlconst::one() - v), exec().gmin()));
+
+ if (m_R1().solver() == m_R2().solver())
+ m_R1().change_state(
+ [this, &r1, &r2]()
+ {
+ m_R1().set_R(r1);
+ m_R2().set_R(r2);
+ });
+ else
+ {
+ m_R1().change_state([this, &r1]() { m_R1().set_R(r1); });
+ m_R2().change_state([this, &r2]() { m_R2().set_R(r2); });
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // nld_POT2
+ // -------------------------------------------------------------------------
+
+ NETLIB_RESET(POT2)
+ {
+ nl_fptype v = m_Dial();
-// ----------------------------------------------------------------------------------------
-// nld_POT2
-// ----------------------------------------------------------------------------------------
+ if (m_DialIsLog())
+ v = (plib::exp(v) - nlconst::one())
+ / (plib::exp(nlconst::one()) - nlconst::one());
+ if (m_Reverse())
+ v = nlconst::one() - v;
+ m_R1().set_R(std::max(m_R() * v, exec().gmin()));
+ }
-NETLIB_RESET(POT2)
-{
- nl_double v = m_Dial();
+ NETLIB_UPDATE_PARAM(POT2)
+ {
+ nl_fptype v = m_Dial();
- if (m_DialIsLog())
- v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
- if (m_Reverse())
- v = 1.0 - v;
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
-}
+ if (m_DialIsLog())
+ v = (plib::exp(v) - nlconst::one())
+ / (plib::exp(nlconst::one()) - nlconst::one());
+ if (m_Reverse())
+ v = nlconst::one() - v;
+ m_R1().change_state(
+ [this, &v]() { m_R1().set_R(std::max(m_R() * v, exec().gmin())); });
+ }
-NETLIB_UPDATE_PARAM(POT2)
-{
- m_R1.solve_now();
+ // -------------------------------------------------------------------------
+ // nld_L
+ // -------------------------------------------------------------------------
- nl_double v = m_Dial();
+ NETLIB_RESET(L)
+ {
+ m_gmin = exec().gmin();
+ m_I = nlconst::zero();
+ m_G = m_gmin;
+ set_mat(m_G, -m_G, -m_I, //
+ -m_G, m_G, m_I);
+ }
- if (m_DialIsLog())
- v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
- if (m_Reverse())
- v = 1.0 - v;
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
-}
+ NETLIB_UPDATE_PARAM(L) {}
-// ----------------------------------------------------------------------------------------
-// nld_L
-// ----------------------------------------------------------------------------------------
+ NETLIB_TIMESTEP(L)
+ {
+ if (ts_type == detail::time_step_type::FORWARD)
+ {
+ m_last_I = m_I;
+ m_last_G = m_G;
+ // Gpar should support convergence
+ m_I += m_G * deltaV();
+ m_G = step / m_L() + m_gmin;
+ set_mat(m_G, -m_G, -m_I, //
+ -m_G, m_G, m_I);
+ }
+ else
+ {
+ m_I = m_last_I;
+ m_G = m_last_G;
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // nld_D
+ // -------------------------------------------------------------------------
+
+ NETLIB_RESET(D)
+ {
+ nl_fptype Is = m_modacc.m_IS;
+ nl_fptype n = m_modacc.m_N;
-NETLIB_RESET(L)
-{
- m_gmin = exec().gmin();
- m_I = 0.0;
- m_G = m_gmin;
- set_mat( m_G, -m_G, -m_I,
- -m_G, m_G, m_I);
- //set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN);
-}
-
-NETLIB_UPDATE_PARAM(L)
-{
-}
+ m_D.set_param(Is, n, exec().gmin(), nlconst::T0());
+ set_G_V_I(m_D.G(), nlconst::zero(), m_D.Ieq());
+ }
-NETLIB_TIMESTEP(L)
-{
- /* Gpar should support convergence */
- m_I += m_I + m_G * deltaV();
- m_G = step / m_L() + m_gmin;
- set_mat( m_G, -m_G, -m_I,
- -m_G, m_G, m_I);
- //set(m_G, 0.0, m_I);
-}
-
-// ----------------------------------------------------------------------------------------
-// nld_D
-// ----------------------------------------------------------------------------------------
-
-NETLIB_RESET(D)
-{
- nl_double Is = m_model.m_IS;
- nl_double n = m_model.m_N;
+ NETLIB_UPDATE_PARAM(D)
+ {
+ nl_fptype Is = m_modacc.m_IS;
+ nl_fptype n = m_modacc.m_N;
- m_D.set_param(Is, n, exec().gmin(), constants::T0());
- set_G_V_I(m_D.G(), 0.0, m_D.Ieq());
-}
+ m_D.set_param(Is, n, exec().gmin(), nlconst::T0());
+ }
-NETLIB_UPDATE_PARAM(D)
-{
- nl_double Is = m_model.m_IS;
- nl_double n = m_model.m_N;
+ NETLIB_UPDATE_TERMINALS(D)
+ {
+ m_D.update_diode(deltaV());
+ const nl_fptype G(m_D.G());
+ const nl_fptype I(m_D.Ieq());
+ set_mat(G, -G, -I, //
+ -G, G, I);
+ // set(m_D.G(), 0.0, m_D.Ieq());
+ }
+
+ // -------------------------------------------------------------------------
+ // nld_Z
+ // -------------------------------------------------------------------------
+
+ NETLIB_RESET(Z)
+ {
+ nl_fptype IsBV = m_modacc.m_IBV
+ / (plib::exp(m_modacc.m_BV
+ / nlconst::np_VT(m_modacc.m_NBV))
+ - nlconst::one());
+
+ m_D.set_param(m_modacc.m_IS, m_modacc.m_N, exec().gmin(),
+ nlconst::T0());
+ m_R.set_param(IsBV, m_modacc.m_NBV, exec().gmin(), nlconst::T0());
+ set_G_V_I(m_D.G(), nlconst::zero(), m_D.Ieq());
+ }
+
+ NETLIB_UPDATE_PARAM(Z)
+ {
+ nl_fptype IsBV = m_modacc.m_IBV
+ / (plib::exp(m_modacc.m_BV
+ / nlconst::np_VT(m_modacc.m_NBV))
+ - nlconst::one());
+
+ m_D.set_param(m_modacc.m_IS, m_modacc.m_N, exec().gmin(),
+ nlconst::T0());
+ m_R.set_param(IsBV, m_modacc.m_NBV, exec().gmin(), nlconst::T0());
+ set_G_V_I(m_D.G(), nlconst::zero(), m_D.Ieq());
+ }
+
+ NETLIB_UPDATE_TERMINALS(Z)
+ {
+ m_D.update_diode(deltaV());
+ m_R.update_diode(-deltaV());
+ const nl_fptype G(m_D.G() + m_R.G());
+ const nl_fptype I(m_D.Ieq() - m_R.Ieq());
+ set_mat(G, -G, -I, //
+ -G, G, I);
+ }
- m_D.set_param(Is, n, exec().gmin(), constants::T0());
-}
+} // namespace netlist::analog
-NETLIB_UPDATE_TERMINALS(D)
+namespace netlist::devices
{
- m_D.update_diode(deltaV());
- const nl_double G = m_D.G();
- const nl_double I = m_D.Ieq();
- set_mat( G, -G, -I,
- -G, G, I);
- //set(m_D.G(), 0.0, m_D.Ieq());
-}
-
-
- } //namespace analog
-
- namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, R, "RES", "R")
- NETLIB_DEVICE_IMPL_NS(analog, POT, "POT", "R")
- NETLIB_DEVICE_IMPL_NS(analog, POT2, "POT2", "R")
- NETLIB_DEVICE_IMPL_NS(analog, C, "CAP", "C")
- NETLIB_DEVICE_IMPL_NS(analog, L, "IND", "L")
- NETLIB_DEVICE_IMPL_NS(analog, D, "DIODE", "MODEL")
- NETLIB_DEVICE_IMPL_NS(analog, VS, "VS", "V")
- NETLIB_DEVICE_IMPL_NS(analog, CS, "CS", "I")
- } // namespace devices
-
-} // namespace netlist
+ // clang-format off
+ NETLIB_DEVICE_IMPL_NS(analog, R, "RES", "R")
+ NETLIB_DEVICE_IMPL_NS(analog, POT, "POT", "R")
+ NETLIB_DEVICE_IMPL_NS(analog, POT2, "POT2", "R")
+ NETLIB_DEVICE_IMPL_NS(analog, C, "CAP", "C")
+ NETLIB_DEVICE_IMPL_NS(analog, L, "IND", "L")
+ NETLIB_DEVICE_IMPL_NS(analog, D, "DIODE", "MODEL")
+ NETLIB_DEVICE_IMPL_NS(analog, Z, "ZDIODE", "MODEL")
+ NETLIB_DEVICE_IMPL_NS(analog, VS, "VS", "V")
+ NETLIB_DEVICE_IMPL_NS(analog, CS, "CS", "I")
+ // clang-format on
+} // namespace netlist::devices