summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/analog/nlid_twoterm.cpp
diff options
context:
space:
mode:
author andreasnaive <andreasnaive@gmail.com>2019-03-25 23:13:40 +0100
committer andreasnaive <andreasnaive@gmail.com>2019-03-25 23:13:40 +0100
commitb380514764cf857469bae61c11143a19f79a74c5 (patch)
tree63c8012e262618f08a332da31dd714281aa2c5ed /src/lib/netlist/analog/nlid_twoterm.cpp
parentc24473ddff715ecec2e258a6eb38960cf8c8e98e (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.cpp233
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