summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/analog/nld_fourterm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/analog/nld_fourterm.c')
-rw-r--r--src/lib/netlist/analog/nld_fourterm.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/lib/netlist/analog/nld_fourterm.c b/src/lib/netlist/analog/nld_fourterm.c
new file mode 100644
index 00000000000..d7fd828e1f3
--- /dev/null
+++ b/src/lib/netlist/analog/nld_fourterm.c
@@ -0,0 +1,189 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_fourterm.c
+ *
+ */
+
+#include "solver/nld_solver.h"
+#include "nld_fourterm.h"
+#include "nl_setup.h"
+
+NETLIB_NAMESPACE_DEVICES_START()
+
+// ----------------------------------------------------------------------------------------
+// nld_VCCS
+// ----------------------------------------------------------------------------------------
+
+NETLIB_START(VCCS)
+{
+ start_internal(NL_FCONST(1.0) / netlist().gmin());
+ m_gfac = NL_FCONST(1.0);
+}
+
+void NETLIB_NAME(VCCS)::start_internal(const nl_double def_RI)
+{
+ register_param("G", m_G, 1.0);
+ register_param("RI", m_RI, def_RI);
+
+ register_terminal("IP", m_IP);
+ register_terminal("IN", m_IN);
+ register_terminal("OP", m_OP);
+ register_terminal("ON", m_ON);
+
+ register_terminal("_OP1", m_OP1);
+ register_terminal("_ON1", m_ON1);
+
+ m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
+ m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
+
+ m_OP.m_otherterm = &m_IP;
+ m_OP1.m_otherterm = &m_IN;
+
+ m_ON.m_otherterm = &m_IP;
+ m_ON1.m_otherterm = &m_IN;
+
+ connect_late(m_OP, m_OP1);
+ connect_late(m_ON, m_ON1);
+}
+
+NETLIB_RESET(VCCS)
+{
+ const nl_double m_mult = m_G.Value() * m_gfac; // 1.0 ==> 1V ==> 1A
+ const nl_double GI = NL_FCONST(1.0) / m_RI.Value();
+
+ m_IP.set(GI);
+ m_IN.set(GI);
+
+ m_OP.set(m_mult, NL_FCONST(0.0));
+ m_OP1.set(-m_mult, NL_FCONST(0.0));
+
+ m_ON.set(-m_mult, NL_FCONST(0.0));
+ m_ON1.set(m_mult, NL_FCONST(0.0));
+}
+
+NETLIB_UPDATE_PARAM(VCCS)
+{
+ NETLIB_NAME(VCCS)::reset();
+}
+
+NETLIB_UPDATE(VCCS)
+{
+ /* only called if connected to a rail net ==> notify the solver to recalculate */
+ if (!m_IP.net().isRailNet())
+ m_IP.schedule_solve();
+ else if (!m_IN.net().isRailNet())
+ m_IN.schedule_solve();
+ else if (!m_OP.net().isRailNet())
+ m_OP.schedule_solve();
+ else if (!m_ON.net().isRailNet())
+ m_ON.schedule_solve();
+}
+
+// ----------------------------------------------------------------------------------------
+// nld_LVCCS
+// ----------------------------------------------------------------------------------------
+
+NETLIB_START(LVCCS)
+{
+ NETLIB_NAME(VCCS)::start();
+ register_param("CURLIM", m_cur_limit, 1000.0);
+}
+
+NETLIB_RESET(LVCCS)
+{
+ NETLIB_NAME(VCCS)::reset();
+}
+
+NETLIB_UPDATE_PARAM(LVCCS)
+{
+ NETLIB_NAME(VCCS)::update_param();
+}
+
+NETLIB_UPDATE(LVCCS)
+{
+ NETLIB_NAME(VCCS)::update();
+}
+
+NETLIB_UPDATE_TERMINALS(LVCCS)
+{
+ const nl_double m_mult = m_G.Value() * m_gfac; // 1.0 ==> 1V ==> 1A
+ const nl_double vi = m_IP.net().m_cur_Analog - m_IN.net().m_cur_Analog;
+
+ if (std::abs(m_mult / m_cur_limit * vi) > 0.5)
+ m_vi = m_vi + 0.2*std::tanh((vi - m_vi)/0.2);
+ else
+ m_vi = vi;
+
+ const nl_double x = m_mult / m_cur_limit * m_vi;
+ const nl_double X = std::tanh(x);
+
+ const nl_double beta = m_mult * (1.0 - X*X);
+ const nl_double I = m_cur_limit * X - beta * m_vi;
+
+ m_OP.set(beta, NL_FCONST(0.0), I);
+ m_OP1.set(-beta, NL_FCONST(0.0));
+
+ m_ON.set(-beta, NL_FCONST(0.0), -I);
+ m_ON1.set(beta, NL_FCONST(0.0));
+}
+
+// ----------------------------------------------------------------------------------------
+// nld_CCCS
+// ----------------------------------------------------------------------------------------
+
+NETLIB_START(CCCS)
+{
+ start_internal(1.0);
+ m_gfac = NL_FCONST(1.0) / m_RI.Value();
+}
+
+NETLIB_RESET(CCCS)
+{
+ NETLIB_NAME(VCCS)::reset();
+}
+
+NETLIB_UPDATE_PARAM(CCCS)
+{
+ NETLIB_NAME(VCCS)::update_param();
+}
+
+NETLIB_UPDATE(CCCS)
+{
+ NETLIB_NAME(VCCS)::update();
+}
+
+// ----------------------------------------------------------------------------------------
+// nld_VCVS
+// ----------------------------------------------------------------------------------------
+
+NETLIB_START(VCVS)
+{
+ NETLIB_NAME(VCCS)::start();
+
+ register_param("RO", m_RO, 1.0);
+
+ register_terminal("_OP2", m_OP2);
+ register_terminal("_ON2", m_ON2);
+
+ m_OP2.m_otherterm = &m_ON2;
+ m_ON2.m_otherterm = &m_OP2;
+
+ connect_late(m_OP2, m_OP1);
+ connect_late(m_ON2, m_ON1);
+}
+
+NETLIB_RESET(VCVS)
+{
+ m_gfac = NL_FCONST(1.0) / m_RO.Value();
+ NETLIB_NAME(VCCS)::reset();
+
+ m_OP2.set(NL_FCONST(1.0) / m_RO.Value());
+ m_ON2.set(NL_FCONST(1.0) / m_RO.Value());
+}
+
+NETLIB_UPDATE_PARAM(VCVS)
+{
+}
+
+NETLIB_NAMESPACE_DEVICES_END()