diff options
author | andreasnaive <andreasnaive@gmail.com> | 2019-03-25 23:13:40 +0100 |
---|---|---|
committer | andreasnaive <andreasnaive@gmail.com> | 2019-03-25 23:13:40 +0100 |
commit | b380514764cf857469bae61c11143a19f79a74c5 (patch) | |
tree | 63c8012e262618f08a332da31dd714281aa2c5ed /src/lib/netlist/analog/nlid_twoterm.cpp | |
parent | c24473ddff715ecec2e258a6eb38960cf8c8e98e (diff) |
Revert "conflict resolution (nw)"
This reverts commit c24473ddff715ecec2e258a6eb38960cf8c8e98e, reversing
changes made to 009cba4fb8102102168ef32870892438327f3705.
Diffstat (limited to 'src/lib/netlist/analog/nlid_twoterm.cpp')
-rw-r--r-- | src/lib/netlist/analog/nlid_twoterm.cpp | 233 |
1 files changed, 186 insertions, 47 deletions
diff --git a/src/lib/netlist/analog/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp index 5019c98c0e4..f54c2b3e68f 100644 --- a/src/lib/netlist/analog/nlid_twoterm.cpp +++ b/src/lib/netlist/analog/nlid_twoterm.cpp @@ -5,10 +5,10 @@ * */ -#include "netlist/solver/nld_solver.h" +#include "../solver/nld_solver.h" -#include "netlist/nl_factory.h" #include "nlid_twoterm.h" +#include "../nl_factory.h" #include <cmath> @@ -16,34 +16,81 @@ namespace netlist { namespace analog { - // ---------------------------------------------------------------------------------------- -// nld_twoterm +// generic_diode // ---------------------------------------------------------------------------------------- -void NETLIB_NAME(twoterm)::solve_now() +generic_diode::generic_diode(device_t &dev, pstring name) + : m_Vd(dev, name + ".m_Vd", 0.7) + , m_Id(dev, name + ".m_Id", 0.0) + , m_G(dev, name + ".m_G", 1e-15) + , m_Vt(0.0) + , m_Vmin(0.0) + , m_Is(0.0) + , m_logIs(0.0) + , m_n(0.0) + , m_gmin(1e-15) + , m_VtInv(0.0) + , m_Vcrit(0.0) { - /* 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(); + set_param(1e-15, 1, 1e-15); } -void NETLIB_NAME(twoterm)::solve_later(netlist_time delay) +void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double gmin) { - /* 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); + static constexpr double csqrt2 = 1.414213562373095048801688724209; //std::sqrt(2.0); + m_Is = Is; + m_logIs = std::log(Is); + m_n = n; + m_gmin = gmin; + + m_Vt = 0.0258 * m_n; + m_Vmin = -5.0 * m_Vt; + + m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2); + m_VtInv = 1.0 / m_Vt; +} + +void generic_diode::update_diode(const nl_double nVd) +{ + if (nVd < m_Vmin) + { + m_Vd = nVd; + m_G = m_gmin; + m_Id = - m_Is; + } + else if (nVd < m_Vcrit) + { + m_Vd = nVd; + //m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt); + //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv); + const double IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv); + m_Id = IseVDVt - m_Is; + m_G = IseVDVt * m_VtInv + m_gmin; + } + else + { + const double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99)); + m_Vd = m_Vd + std::log1p(a) * m_Vt; + //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv); + const double IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv); + m_Id = IseVDVt - m_Is; + m_G = IseVDVt * m_VtInv + m_gmin; + } } +// ---------------------------------------------------------------------------------------- +// nld_twoterm +// ---------------------------------------------------------------------------------------- NETLIB_UPDATE(twoterm) { /* only called if connected to a rail net ==> notify the solver to recalculate */ - 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(); } // ---------------------------------------------------------------------------------------- @@ -53,7 +100,12 @@ NETLIB_UPDATE(twoterm) NETLIB_RESET(R_base) { NETLIB_NAME(twoterm)::reset(); - set_R(1.0 / exec().gmin()); + set_R(1.0 / netlist().gmin()); +} + +NETLIB_UPDATE(R_base) +{ + NETLIB_NAME(twoterm)::update(); } // ---------------------------------------------------------------------------------------- @@ -62,14 +114,14 @@ NETLIB_RESET(R_base) NETLIB_UPDATE_PARAM(R) { - solve_now(); - set_R(std::max(m_R(), exec().gmin())); + update_dev(); + set_R(std::max(m_R(), netlist().gmin())); } NETLIB_RESET(R) { NETLIB_NAME(twoterm)::reset(); - set_R(std::max(m_R(), exec().gmin())); + set_R(std::max(m_R(), netlist().gmin())); } // ---------------------------------------------------------------------------------------- @@ -82,22 +134,21 @@ NETLIB_RESET(POT) if (m_DialIsLog()) v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0); - 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, netlist().gmin())); + m_R2.set_R(std::max(m_R() * (NL_FCONST(1.0) - v), netlist().gmin())); } NETLIB_UPDATE_PARAM(POT) { - m_R1.solve_now(); - m_R2.solve_now(); + m_R1.update_dev(); + m_R2.update_dev(); 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, netlist().gmin())); + m_R2.set_R(std::max(m_R() * (NL_FCONST(1.0) - v), netlist().gmin())); } @@ -113,13 +164,13 @@ NETLIB_RESET(POT2) 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_R1.set_R(std::max(m_R() * v, netlist().gmin())); } NETLIB_UPDATE_PARAM(POT2) { - m_R1.solve_now(); + m_R1.update_dev(); nl_double v = m_Dial(); @@ -127,7 +178,38 @@ NETLIB_UPDATE_PARAM(POT2) 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_R1.set_R(std::max(m_R() * v, netlist().gmin())); +} + +// ---------------------------------------------------------------------------------------- +// nld_C +// ---------------------------------------------------------------------------------------- + +NETLIB_RESET(C) +{ + // FIXME: Startup conditions + set(netlist().gmin(), 0.0, -5.0 / netlist().gmin()); + //set(netlist().gmin(), 0.0, 0.0); +} + +NETLIB_UPDATE_PARAM(C) +{ + m_GParallel = netlist().gmin(); +} + +NETLIB_UPDATE(C) +{ + NETLIB_NAME(twoterm)::update(); +} + +NETLIB_TIMESTEP(C) +{ + /* Gpar should support convergence */ + const nl_double G = m_C() / step + m_GParallel; + const nl_double I = -G * deltaV(); + set_mat( G, -G, -I, + -G, G, I); + //set(G, 0.0, I); } // ---------------------------------------------------------------------------------------- @@ -136,9 +218,9 @@ NETLIB_UPDATE_PARAM(POT2) NETLIB_RESET(L) { - m_gmin = exec().gmin(); + m_GParallel = netlist().gmin(); m_I = 0.0; - m_G = m_gmin; + m_G = m_GParallel; 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); @@ -148,11 +230,16 @@ NETLIB_UPDATE_PARAM(L) { } +NETLIB_UPDATE(L) +{ + NETLIB_NAME(twoterm)::update(); +} + NETLIB_TIMESTEP(L) { /* Gpar should support convergence */ m_I += m_I + m_G * deltaV(); - m_G = step / m_L() + m_gmin; + m_G = step / m_L() + m_GParallel; set_mat( m_G, -m_G, -m_I, -m_G, m_G, m_I); //set(m_G, 0.0, m_I); @@ -167,8 +254,8 @@ NETLIB_RESET(D) nl_double Is = m_model.m_IS; nl_double n = m_model.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, netlist().gmin()); + set(m_D.G(), 0.0, m_D.Ieq()); } NETLIB_UPDATE_PARAM(D) @@ -176,7 +263,12 @@ NETLIB_UPDATE_PARAM(D) nl_double Is = m_model.m_IS; nl_double n = m_model.m_N; - m_D.set_param(Is, n, exec().gmin(), constants::T0()); + m_D.set_param(Is, n, netlist().gmin()); +} + +NETLIB_UPDATE(D) +{ + NETLIB_NAME(twoterm)::update(); } NETLIB_UPDATE_TERMINALS(D) @@ -189,18 +281,65 @@ NETLIB_UPDATE_TERMINALS(D) //set(m_D.G(), 0.0, m_D.Ieq()); } +// ---------------------------------------------------------------------------------------- +// nld_VS +// ---------------------------------------------------------------------------------------- + +NETLIB_RESET(VS) +{ + NETLIB_NAME(twoterm)::reset(); + this->set(1.0 / m_R(), m_V(), 0.0); +} + +NETLIB_UPDATE(VS) +{ + NETLIB_NAME(twoterm)::update(); +} + +NETLIB_TIMESTEP(VS) +{ + this->set(1.0 / m_R(), + m_compiled.evaluate(std::vector<double>({netlist().time().as_double()})), + 0.0); +} + +// ---------------------------------------------------------------------------------------- +// nld_CS +// ---------------------------------------------------------------------------------------- + +NETLIB_RESET(CS) +{ + NETLIB_NAME(twoterm)::reset(); + const nl_double I = m_I(); + + set_mat(0.0, 0.0, -I, + 0.0, 0.0, I); + //this->set(0.0, 0.0, m_I()); +} + +NETLIB_UPDATE(CS) +{ + NETLIB_NAME(twoterm)::update(); +} + +NETLIB_TIMESTEP(CS) +{ + const double I = m_compiled.evaluate(std::vector<double>({netlist().time().as_double()})); + set_mat(0.0, 0.0, -I, + 0.0, 0.0, I); +} } //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 + NETLIB_DEVICE_IMPL_NS(analog, R) + NETLIB_DEVICE_IMPL_NS(analog, POT) + NETLIB_DEVICE_IMPL_NS(analog, POT2) + NETLIB_DEVICE_IMPL_NS(analog, C) + NETLIB_DEVICE_IMPL_NS(analog, L) + NETLIB_DEVICE_IMPL_NS(analog, D) + NETLIB_DEVICE_IMPL_NS(analog, VS) + NETLIB_DEVICE_IMPL_NS(analog, CS) + } } // namespace netlist |