summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2020-04-25 18:08:04 +0200
committer couriersud <couriersud@gmx.org>2020-04-25 18:08:04 +0200
commitd3ee7e21c6f52a794e67beda0d3bffa32179d03c (patch)
tree145711c33db8106a7c347014fbe390caaae98ff8
parent14f92c9786572699754473eecb9d47e8f95db0bb (diff)
netlist: unify solver calls. (nw)
Calls to the solver used different paths. These changes unify these calls and provide a common call for discontinuous state changes on analog components (change_state).
-rw-r--r--src/lib/netlist/analog/nld_switches.cpp35
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.cpp52
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.h30
-rw-r--r--src/lib/netlist/devices/nld_4066.cpp4
-rw-r--r--src/lib/netlist/devices/nld_4316.cpp14
-rw-r--r--src/lib/netlist/devices/nld_mm5837.cpp14
-rw-r--r--src/lib/netlist/devices/nld_r2r_dac.cpp10
-rw-r--r--src/lib/netlist/devices/nld_schmitt.cpp19
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp43
-rw-r--r--src/lib/netlist/devices/nlid_proxy.h1
-rw-r--r--src/lib/netlist/devices/nlid_system.h7
-rw-r--r--src/lib/netlist/nl_base.cpp14
-rw-r--r--src/lib/netlist/nl_base.h15
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp32
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h47
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp15
16 files changed, 183 insertions, 169 deletions
diff --git a/src/lib/netlist/analog/nld_switches.cpp b/src/lib/netlist/analog/nld_switches.cpp
index a5d68228af1..9dbd50c94e9 100644
--- a/src/lib/netlist/analog/nld_switches.cpp
+++ b/src/lib/netlist/analog/nld_switches.cpp
@@ -49,17 +49,10 @@ namespace netlist
NETLIB_UPDATE_PARAM(switch1)
{
- m_R.solve_now();
- if (!m_POS())
- {
- m_R.set_R(R_OFF);
- }
- else
+ m_R.change_state([this]()
{
- m_R.set_R(R_ON);
- }
- m_R.solve_later();
-
+ m_R.set_R(m_POS() ? R_ON : R_OFF);
+ });
}
// ----------------------------------------------------------------------------------------
@@ -112,21 +105,19 @@ namespace netlist
NETLIB_UPDATE_PARAM(switch2)
{
- // FIXME: We only need to update the net first if this is a time stepping net
- m_R1.solve_now();
- m_R2.solve_now();
- if (!m_POS())
- {
- m_R1.set_R(R_ON);
- m_R2.set_R(R_OFF);
- }
+ // R1 and R2 are connected. However this net may be a rail net.
+ // The code here thus is a bit more complex.
+
+ nl_fptype r1 = m_POS() ? R_OFF : R_ON;
+ nl_fptype r2 = m_POS() ? R_ON : R_OFF;
+
+ 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.set_R(R_OFF);
- m_R2.set_R(R_ON);
+ m_R1.change_state([this, &r1]() { m_R1.set_R(r1); });
+ m_R2.change_state([this, &r2]() { m_R2.set_R(r2); });
}
- m_R1.solve_later();
- m_R2.solve_later();
}
} //namespace analog
diff --git a/src/lib/netlist/analog/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp
index 2573103d06b..c57d76c821e 100644
--- a/src/lib/netlist/analog/nlid_twoterm.cpp
+++ b/src/lib/netlist/analog/nlid_twoterm.cpp
@@ -15,25 +15,22 @@ namespace analog
// nld_twoterm
// ----------------------------------------------------------------------------------------
- void NETLIB_NAME(twoterm)::solve_now()
+ solver::matrix_solver_t * NETLIB_NAME(twoterm)::solver() const noexcept
{
- // we only need to call the non-rail terminal
- if (m_P.has_net() && !m_P.net().is_rail_net())
- m_P.solve_now();
- else if (m_N.has_net() && !m_N.net().is_rail_net())
- m_N.solve_now();
+ auto *solv(m_P.solver());
+ if (solv)
+ return solv;
+ return m_N.solver();
}
- void NETLIB_NAME(twoterm)::solve_later(netlist_time delay) noexcept
+
+ void NETLIB_NAME(twoterm)::solve_now() const
{
- // we only need to call the non-rail terminal
- if (m_P.has_net() && !m_P.net().is_rail_net())
- m_P.schedule_solve_after(delay);
- else if (m_N.has_net() && !m_N.net().is_rail_net())
- m_N.schedule_solve_after(delay);
+ auto *solv(solver());
+ if (solv)
+ solv->solve_now();
}
-
NETLIB_UPDATE(twoterm)
{
// only called if connected to a rail net ==> notify the solver to recalculate
@@ -66,19 +63,22 @@ namespace analog
NETLIB_UPDATE_PARAM(POT)
{
- // FIXME: We only need to update the net first if this is a time stepping net
- m_R1.solve_now();
- m_R2.solve_now();
-
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;
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
- m_R2.set_R(std::max(m_R() * (nlconst::one() - v), exec().gmin()));
- m_R1.solve_later();
- m_R2.solve_later();
+
+ 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); });
+ }
}
@@ -100,17 +100,17 @@ namespace analog
NETLIB_UPDATE_PARAM(POT2)
{
- // FIXME: We only need to update the net first if this is a time stepping net
- m_R1.solve_now();
-
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;
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
- m_R1.solve_later();
+
+ m_R1.change_state([this, &v]()
+ {
+ m_R1.set_R(std::max(m_R() * v, exec().gmin()));
+ });
}
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h
index ffeb75e215c..cb816847bf1 100644
--- a/src/lib/netlist/analog/nlid_twoterm.h
+++ b/src/lib/netlist/analog/nlid_twoterm.h
@@ -86,9 +86,17 @@ namespace analog
NETLIB_UPDATEI();
- void solve_now();
+ solver::matrix_solver_t *solver() const noexcept;
- void solve_later(netlist_time delay = netlist_time::quantum()) noexcept;
+ void solve_now() const;
+
+ template <typename F>
+ void change_state(F f, netlist_time delay = netlist_time::quantum())
+ {
+ auto *solv(solver());
+ if (solv)
+ solv->change_state(f, delay);
+ }
void set_G_V_I(nl_fptype G, nl_fptype V, nl_fptype I) const noexcept
{
@@ -168,9 +176,10 @@ namespace analog
NETLIB_UPDATE_PARAMI()
{
// FIXME: We only need to update the net first if this is a time stepping net
- solve_now();
- set_R(std::max(m_R(), exec().gmin()));
- solve_later();
+ change_state([this]()
+ {
+ set_R(std::max(m_R(), exec().gmin()));
+ });
}
private:
@@ -524,11 +533,12 @@ namespace analog
{
// FIXME: We only need to update the net first if this is a time stepping net
//FIXME: works only for CS without function
- solve_now();
- const auto zero(nlconst::zero());
- set_mat(zero, zero, -m_I(),
- zero, zero, m_I());
- solve_later();
+ change_state([this]()
+ {
+ const auto zero(nlconst::zero());
+ set_mat(zero, zero, -m_I(),
+ zero, zero, m_I());
+ });
}
private:
diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp
index 8ccd01156cd..7200e5a3962 100644
--- a/src/lib/netlist/devices/nld_4066.cpp
+++ b/src/lib/netlist/devices/nld_4066.cpp
@@ -69,9 +69,7 @@ namespace netlist
if (R > nlconst::zero() && (m_last != new_state))
{
m_last = new_state;
- m_R.solve_now();
- m_R.set_R(R);
- m_R.solve_later();
+ m_R.change_state([this, &R]() -> void { this->m_R.set_R(R);});
}
}
diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp
index 7667772bb91..f8085092178 100644
--- a/src/lib/netlist/devices/nld_4316.cpp
+++ b/src/lib/netlist/devices/nld_4316.cpp
@@ -43,12 +43,14 @@ namespace netlist { namespace devices {
NETLIB_UPDATE(CD4316_GATE)
{
- m_R.solve_now();
- if (m_S() && !m_E())
- m_R.set_R(m_base_r());
- else
- m_R.set_R(plib::reciprocal(exec().gmin()));
- m_R.solve_later(NLTIME_FROM_NS(1));
+ m_R.change_state([this]()
+ {
+ if (m_S() && !m_E())
+ m_R.set_R(m_base_r());
+ else
+ m_R.set_R(plib::reciprocal(exec().gmin()));
+ }
+ , NLTIME_FROM_NS(1));
}
NETLIB_DEVICE_IMPL(CD4316_GATE, "CD4316_GATE", "")
diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp
index 75e0d9635c8..771b64e0ab6 100644
--- a/src/lib/netlist/devices/nld_mm5837.cpp
+++ b/src/lib/netlist/devices/nld_mm5837.cpp
@@ -28,7 +28,6 @@ namespace netlist
, m_Q(*this, "_Q")
, m_inc(netlist_time::from_hz(24000 * 2))
, m_shift(*this, "m_shift", 0)
- , m_is_timestep(false)
{
connect(m_feedback, m_Q);
@@ -57,9 +56,6 @@ namespace netlist
/* state */
state_var_u32 m_shift;
-
- /* cache */
- bool m_is_timestep;
};
NETLIB_RESET(MM5837_dip)
@@ -74,7 +70,6 @@ namespace netlist
log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ()));
m_shift = 0x1ffff;
- m_is_timestep = (m_RV.m_P.net().solver()->timestep_device_count() > 0);
}
NETLIB_UPDATE_PARAM(MM5837_dip)
@@ -104,11 +99,10 @@ namespace netlist
const nl_fptype R = state ? m_R_HIGH : m_R_LOW;
const nl_fptype V = state ? m_VDD() : m_VSS();
- // We only need to update the net first if this is a time stepping net
- if (m_is_timestep)
- m_RV.solve_now();
- m_RV.set_G_V_I(plib::reciprocal(R), V, nlconst::zero());
- m_RV.solve_later(NLTIME_FROM_NS(1));
+ m_RV.change_state([this, &R, &V]()
+ {
+ m_RV.set_G_V_I(plib::reciprocal(R), V, nlconst::zero());
+ });
}
}
diff --git a/src/lib/netlist/devices/nld_r2r_dac.cpp b/src/lib/netlist/devices/nld_r2r_dac.cpp
index 361652a373a..946050c1951 100644
--- a/src/lib/netlist/devices/nld_r2r_dac.cpp
+++ b/src/lib/netlist/devices/nld_r2r_dac.cpp
@@ -39,13 +39,13 @@ namespace netlist
NETLIB_UPDATE_PARAM(r2r_dac)
{
- // FIXME: We only need to update the net first if this is a time stepping net
- solve_now();
nl_fptype V = m_VIN() / static_cast<nl_fptype>(1 << m_num())
* static_cast<nl_fptype>(m_val());
-
- this->set_G_V_I(plib::reciprocal(m_R()), V, nlconst::zero());
- solve_later();
+ change_state([this, &V]()
+ {
+ this->set_G_V_I(plib::reciprocal(m_R()), V, nlconst::zero());
+ }
+ );
}
} //namespace analog
diff --git a/src/lib/netlist/devices/nld_schmitt.cpp b/src/lib/netlist/devices/nld_schmitt.cpp
index 6c59b2a3192..877c32bf3d7 100644
--- a/src/lib/netlist/devices/nld_schmitt.cpp
+++ b/src/lib/netlist/devices/nld_schmitt.cpp
@@ -67,7 +67,6 @@ namespace netlist
, m_RVO(*this, "RVO")
, m_model(*this, "MODEL", "TTL_7414_GATE")
, m_last_state(*this, "m_last_var", 1)
- , m_is_timestep(false)
{
register_subalias("Q", m_RVO.m_P);
@@ -82,7 +81,6 @@ namespace netlist
m_last_state = 1;
m_RVI.reset();
m_RVO.reset();
- m_is_timestep = (m_RVO.m_P.net().solver()->timestep_device_count() > 0);
m_RVI.set_G_V_I(plib::reciprocal(m_model.m_RI()), m_model.m_VI, nlconst::zero());
m_RVO.set_G_V_I(plib::reciprocal(m_model.m_ROL()), m_model.m_VOL, nlconst::zero());
}
@@ -95,10 +93,10 @@ namespace netlist
if (va < m_model.m_VTM)
{
m_last_state = 0;
- if (m_is_timestep)
- m_RVO.solve_now();
- m_RVO.set_G_V_I(plib::reciprocal(m_model.m_ROH()), m_model.m_VOH, nlconst::zero());
- m_RVO.solve_later();
+ m_RVO.change_state([this]()
+ {
+ m_RVO.set_G_V_I(plib::reciprocal(m_model.m_ROH()), m_model.m_VOH, nlconst::zero());
+ });
}
}
else
@@ -106,10 +104,10 @@ namespace netlist
if (va > m_model.m_VTP)
{
m_last_state = 1;
- if (m_is_timestep)
- m_RVO.solve_now();
- m_RVO.set_G_V_I(plib::reciprocal(m_model.m_ROL()), m_model.m_VOL, nlconst::zero());
- m_RVO.solve_later();
+ m_RVO.change_state([this]()
+ {
+ m_RVO.set_G_V_I(plib::reciprocal(m_model.m_ROL()), m_model.m_VOL, nlconst::zero());
+ });
}
}
}
@@ -121,7 +119,6 @@ namespace netlist
analog::NETLIB_SUB(twoterm) m_RVO;
schmitt_trigger_model_t m_model;
state_var<int> m_last_state;
- bool m_is_timestep;
};
NETLIB_DEVICE_IMPL(schmitt_trigger, "SCHMITT_TRIGGER", "MODEL")
diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp
index 74dbf2d3cc7..f2cf50e7b91 100644
--- a/src/lib/netlist/devices/nlid_proxy.cpp
+++ b/src/lib/netlist/devices/nlid_proxy.cpp
@@ -117,7 +117,6 @@ namespace netlist
, m_RP(*this, "RP")
, m_RN(*this, "RN")
, m_last_state(*this, "m_last_var", -1)
- , m_is_timestep(false)
{
register_subalias("Q", m_RN.m_P);
@@ -145,7 +144,6 @@ namespace netlist
m_last_state = -1;
m_RN.reset();
m_RP.reset();
- m_is_timestep = (m_RN.m_P.net().solver()->timestep_device_count() > 0);
m_RN.set_G_V_I(plib::reciprocal(logic_family()->R_low()),
logic_family()->low_offset_V(), nlconst::zero());
m_RP.set_G_V_I(G_OFF,
@@ -158,28 +156,27 @@ namespace netlist
const auto state = static_cast<int>(m_I());
if (state != m_last_state)
{
- // We only need to update the net first if this is a time stepping net
- if (m_is_timestep)
+ // RN, RP are connected ...
+ m_RN.change_state([this, &state]()
{
- m_RN.solve_now(); // RN, RP are connected ...
- }
- if (state)
- {
- m_RN.set_G_V_I(G_OFF,
- nlconst::zero(),
- nlconst::zero());
- m_RP.set_G_V_I(plib::reciprocal(logic_family()->R_high()),
- logic_family()->high_offset_V(), nlconst::zero());
- }
- else
- {
- m_RN.set_G_V_I(plib::reciprocal(logic_family()->R_low()),
- logic_family()->low_offset_V(), nlconst::zero());
- m_RP.set_G_V_I(G_OFF,
- nlconst::zero(),
- nlconst::zero());
- }
- m_RN.solve_later(); // RN, RP are connected ...
+ if (state)
+ {
+
+ m_RN.set_G_V_I(G_OFF,
+ nlconst::zero(),
+ nlconst::zero());
+ m_RP.set_G_V_I(plib::reciprocal(logic_family()->R_high()),
+ logic_family()->high_offset_V(), nlconst::zero());
+ }
+ else
+ {
+ m_RN.set_G_V_I(plib::reciprocal(logic_family()->R_low()),
+ logic_family()->low_offset_V(), nlconst::zero());
+ m_RP.set_G_V_I(G_OFF,
+ nlconst::zero(),
+ nlconst::zero());
+ }
+ });
m_last_state = state;
}
}
diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h
index 936d03f8fb6..b1639631a0e 100644
--- a/src/lib/netlist/devices/nlid_proxy.h
+++ b/src/lib/netlist/devices/nlid_proxy.h
@@ -119,7 +119,6 @@ namespace devices
analog::NETLIB_NAME(twoterm) m_RP;
analog::NETLIB_NAME(twoterm) m_RN;
state_var<int> m_last_state;
- bool m_is_timestep;
};
} // namespace devices
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index 34a8c599b3f..386b4f4b709 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -463,9 +463,10 @@ namespace devices
const nl_fptype R = state ? m_RON() : m_ROFF();
// FIXME: We only need to update the net first if this is a time stepping net
- m_R.solve_now();
- m_R.set_R(R);
- m_R.solve_later();
+ m_R.change_state([this, &R]()
+ {
+ m_R.set_R(R);
+ });
}
}
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index facd3f68bd0..e01bd8496a8 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -813,18 +813,10 @@ namespace netlist
void terminal_t::solve_now()
{
+ const auto *solv(solver());
// Nets may belong to railnets which do not have a solver attached
- if (this->has_net())
- if (net().solver() != nullptr)
- net().solver()->solve_now();
- }
-
- void terminal_t::schedule_solve_after(netlist_time after) noexcept
- {
- // Nets may belong to railnets which do not have a solver attached
- if (this->has_net())
- if (net().solver() != nullptr)
- net().solver()->update_after(after);
+ if (solv)
+ solver()->solve_now();
}
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index ba18104b2e4..53706060783 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -798,6 +798,8 @@ namespace netlist
const analog_net_t & net() const noexcept;
analog_net_t & net() noexcept;
+
+ solver::matrix_solver_t *solver() const noexcept;
};
// -----------------------------------------------------------------------------
@@ -834,7 +836,6 @@ namespace netlist
}
void solve_now();
- void schedule_solve_after(netlist_time after) noexcept;
void set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(false);
@@ -945,6 +946,11 @@ namespace netlist
solver::matrix_solver_t *solver() const noexcept { return m_solver; }
void set_solver(solver::matrix_solver_t *solver) noexcept { m_solver = solver; }
+ friend constexpr bool operator==(const analog_net_t &lhs, const analog_net_t &rhs) noexcept
+ {
+ return &lhs == &rhs;
+ }
+
private:
state_var<nl_fptype> m_cur_Analog;
solver::matrix_solver_t *m_solver;
@@ -1940,6 +1946,13 @@ namespace netlist
return static_cast<analog_net_t &>(core_terminal_t::net());
}
+ inline solver::matrix_solver_t *analog_t::solver() const noexcept
+ {
+ if (this->has_net())
+ return net().solver();
+ return nullptr;
+ }
+
inline nl_fptype terminal_t::operator ()() const noexcept { return net().Q_Analog(); }
inline void terminal_t::set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(false)
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
index 2ea4a85d7cd..a84e958cca5 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.cpp
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -389,6 +389,20 @@ namespace solver
inp->push(inp->proxied_net()->Q_Analog());
}
+ bool matrix_solver_t::updates_net(const analog_net_t *net) const noexcept
+ {
+ if (net != nullptr)
+ {
+ for (const auto &t : m_terms )
+ if (t.is_net(net))
+ return true;
+ for (const auto &inp : m_inps)
+ if (&inp->net() == net)
+ return true;
+ }
+ return false;
+ }
+
void matrix_solver_t::update_dynamic() noexcept
{
// update all non-linear devices
@@ -412,22 +426,6 @@ namespace solver
}
}
- void matrix_solver_t::solve_now()
- {
- // this should only occur outside of execution and thus
- // using time should be safe.
-
- const netlist_time new_timestep = solve(exec().time());
- plib::unused_var(new_timestep);
-
- update_inputs();
-
- if (m_params.m_dynamic_ts && (timestep_device_count() != 0))
- {
- m_Q_sync.net().toggle_and_push_to_queue(netlist_time::from_fp(m_params.m_min_timestep));
- }
- }
-
void matrix_solver_t::step(netlist_time delta) noexcept
{
const auto dd(delta.as_fp<nl_fptype>());
@@ -495,7 +493,7 @@ namespace solver
int matrix_solver_t::get_net_idx(const analog_net_t *net) const noexcept
{
for (std::size_t k = 0; k < m_terms.size(); k++)
- if (m_terms[k].isNet(net))
+ if (m_terms[k].is_net(net))
return static_cast<int>(k);
return -1;
}
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index 7bfcc0944c8..ec7bf9f9727 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -143,13 +143,11 @@ namespace solver
terminal_t **terms() noexcept { return m_terms.data(); }
- template <typename FT, typename = std::enable_if<plib::is_floating_point<FT>::value, void>>
- FT getV() const noexcept { return static_cast<FT>(m_net->Q_Analog()); }
+ nl_fptype getV() const noexcept { return m_net->Q_Analog(); }
- template <typename FT, typename = std::enable_if<plib::is_floating_point<FT>::value, void>>
- void setV(FT v) noexcept { m_net->set_Q_Analog(static_cast<nl_fptype>(v)); }
+ void setV(nl_fptype v) noexcept { m_net->set_Q_Analog(v); }
- bool isNet(const analog_net_t * net) const noexcept { return net == m_net; }
+ bool is_net(const analog_net_t * net) const noexcept { return net == m_net; }
void set_railstart(std::size_t val) noexcept { m_railstart = val; }
@@ -191,6 +189,14 @@ namespace solver
netlist_time solve(netlist_time_ext now);
void update_inputs();
+ /// \brief Checks if solver may alter a net
+ ///
+ /// This checks if a solver will alter a net. Returns true if the
+ /// net is either part of the voltage vector or if it belongs to
+ /// the analog input nets connected to the solver.
+
+ bool updates_net(const analog_net_t *net) const noexcept;
+
std::size_t dynamic_device_count() const noexcept { return m_dynamic_funcs.size(); }
std::size_t timestep_device_count() const noexcept { return m_step_funcs.size(); }
@@ -199,11 +205,30 @@ namespace solver
/// This should only be called from update and update_param events.
/// It's purpose is to bring voltage values to the current timestep.
/// This will be called BEFORE updating object properties.
- void solve_now();
+ void solve_now()
+ {
+ // this should only occur outside of execution and thus
+ // using time should be safe.
+
+ const netlist_time new_timestep = solve(exec().time());
+ plib::unused_var(new_timestep);
+
+ update_inputs();
+
+ if (m_params.m_dynamic_ts && (timestep_device_count() != 0))
+ {
+ m_Q_sync.net().toggle_and_push_to_queue(netlist_time::from_fp(m_params.m_min_timestep));
+ }
+ }
- void update_after(netlist_time after) noexcept
+ template <typename F>
+ void change_state(F f, netlist_time delay = netlist_time::quantum())
{
- m_Q_sync.net().toggle_and_push_to_queue(after);
+ // We only need to update the net first if this is a time stepping net
+ if (timestep_device_count() > 0)
+ solve_now();
+ f();
+ m_Q_sync.net().toggle_and_push_to_queue(delay);
}
// netdevice functions
@@ -413,7 +438,7 @@ namespace solver
{
const std::size_t iN = size();
for (std::size_t i = 0; i < iN; i++)
- this->m_terms[i].setV(m_new_V[i]);
+ this->m_terms[i].setV(static_cast<nl_fptype>(m_new_V[i]));
}
#else
// global tanh damping (4.197)
@@ -439,7 +464,7 @@ namespace solver
const auto vntol(static_cast<float_type>(m_params.m_vntol));
for (std::size_t i = 0; i < iN; i++)
{
- const auto vold(this->m_terms[i].template getV<float_type>());
+ const auto vold(static_cast<float_type>(this->m_terms[i].getV()));
const auto vnew(m_new_V[i]);
const auto tol(vntol + reltol * std::max(plib::abs(vnew),plib::abs(vold)));
if (plib::abs(vnew - vold) > tol)
@@ -455,7 +480,7 @@ namespace solver
for (std::size_t k = 0; k < size(); k++)
{
const auto &t = m_terms[k];
- const auto v(t.template getV<nl_fptype>());
+ const auto v(static_cast<nl_fptype>(t.getV()));
// avoid floating point exceptions
const nl_fptype DD_n = std::max(-fp_constants<nl_fptype>::TIMESTEP_MAXDIFF(),
std::min(+fp_constants<nl_fptype>::TIMESTEP_MAXDIFF(),(v - m_last_V[k])));
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 35a5afd961d..f9870bf68d5 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -183,30 +183,27 @@ namespace devices
{
return create_solver<FT, -16>(net_count, sname, nets);
}
- else if (net_count <= 32)
+ if (net_count <= 32)
{
return create_solver<FT, -32>(net_count, sname, nets);
}
- else if (net_count <= 64)
+ if (net_count <= 64)
{
return create_solver<FT, -64>(net_count, sname, nets);
}
- else if (net_count <= 128)
+ if (net_count <= 128)
{
return create_solver<FT, -128>(net_count, sname, nets);
}
- else if (net_count <= 256)
+ if (net_count <= 256)
{
return create_solver<FT, -256>(net_count, sname, nets);
}
- else if (net_count <= 512)
+ if (net_count <= 512)
{
return create_solver<FT, -512>(net_count, sname, nets);
}
- else
- {
- return create_solver<FT, 0>(net_count, sname, nets);
- }
+ return create_solver<FT, 0>(net_count, sname, nets);
break;
}
}