mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
netlist: improve readability. (nw)
The purpose here is to make clear what is actually done and to reduce usage of calls to update.
This commit is contained in:
parent
9c756b09d8
commit
f5fad035de
@ -463,7 +463,6 @@ namespace analog
|
||||
}
|
||||
|
||||
protected:
|
||||
// NETLIB_UPDATEI() { NETLIB_NAME(twoterm)::update(time); }
|
||||
|
||||
NETLIB_RESETI()
|
||||
{
|
||||
@ -513,7 +512,6 @@ namespace analog
|
||||
|
||||
protected:
|
||||
|
||||
//NETLIB_UPDATEI() { NETLIB_NAME(twoterm)::update(time); }
|
||||
NETLIB_RESETI()
|
||||
{
|
||||
NETLIB_NAME(twoterm)::reset();
|
||||
|
@ -69,7 +69,7 @@ namespace netlist
|
||||
if (R > nlconst::zero() && (m_last != new_state))
|
||||
{
|
||||
m_last = new_state;
|
||||
m_R.update();
|
||||
m_R.solve_now();
|
||||
m_R.set_R(R);
|
||||
m_R.solve_later();
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ namespace netlist { namespace devices {
|
||||
|
||||
NETLIB_UPDATE(CD4316_GATE)
|
||||
{
|
||||
m_R.update();
|
||||
m_R.solve_now();
|
||||
if (m_S() && !m_E())
|
||||
m_R.set_R(m_base_r());
|
||||
else
|
||||
|
@ -106,7 +106,7 @@ namespace netlist
|
||||
|
||||
// We only need to update the net first if this is a time stepping net
|
||||
if (m_is_timestep)
|
||||
m_RV.update();
|
||||
m_RV.solve_now();
|
||||
m_RV.set_G_V_I(plib::reciprocal(R), V, nlconst::zero());
|
||||
m_RV.solve_later(NLTIME_FROM_NS(1));
|
||||
}
|
||||
|
@ -196,13 +196,13 @@ namespace netlist
|
||||
|
||||
if (m_last_out && !out)
|
||||
{
|
||||
m_RDIS.update();
|
||||
m_RDIS.solve_now();
|
||||
m_OUT.push(m_R3.m_N());
|
||||
m_RDIS.set_R(nlconst::magic(R_ON));
|
||||
}
|
||||
else if (!m_last_out && out)
|
||||
{
|
||||
m_RDIS.update();
|
||||
m_RDIS.solve_now();
|
||||
// FIXME: Should be delayed by 100ns
|
||||
m_OUT.push(m_R1.m_P());
|
||||
m_RDIS.set_R(nlconst::magic(R_OFF));
|
||||
|
@ -96,7 +96,7 @@ namespace netlist
|
||||
{
|
||||
m_last_state = 0;
|
||||
if (m_is_timestep)
|
||||
m_RVO.update();
|
||||
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();
|
||||
}
|
||||
@ -107,7 +107,7 @@ namespace netlist
|
||||
{
|
||||
m_last_state = 1;
|
||||
if (m_is_timestep)
|
||||
m_RVO.update();
|
||||
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();
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ namespace netlist
|
||||
// We only need to update the net first if this is a time stepping net
|
||||
if (m_is_timestep)
|
||||
{
|
||||
m_RN.update(); // RN, RP are connected ...
|
||||
m_RN.solve_now(); // RN, RP are connected ...
|
||||
}
|
||||
if (state)
|
||||
{
|
||||
|
@ -816,7 +816,7 @@ namespace netlist
|
||||
// Nets may belong to railnets which do not have a solver attached
|
||||
if (this->has_net())
|
||||
if (net().solver() != nullptr)
|
||||
net().solver()->update_forced();
|
||||
net().solver()->solve_now();
|
||||
}
|
||||
|
||||
void terminal_t::schedule_solve_after(netlist_time after) noexcept
|
||||
|
@ -118,8 +118,8 @@
|
||||
/// Defaults to NL_USE_ACADEMIC_SOLVERS to provide faster build times
|
||||
|
||||
#ifndef NL_USE_FLOAT_MATRIX
|
||||
#define NL_USE_FLOAT_MATRIX (NL_USE_ACADEMIC_SOLVERS)
|
||||
//#define NL_USE_FLOAT_MATRIX 1
|
||||
//#define NL_USE_FLOAT_MATRIX (NL_USE_ACADEMIC_SOLVERS)
|
||||
#define NL_USE_FLOAT_MATRIX 1
|
||||
#endif
|
||||
|
||||
/// \brief Support long double type for matrix calculations.
|
||||
@ -127,8 +127,8 @@
|
||||
/// Defaults to NL_USE_ACADEMIC_SOLVERS to provide faster build times
|
||||
|
||||
#ifndef NL_USE_LONG_DOUBLE_MATRIX
|
||||
#define NL_USE_LONG_DOUBLE_MATRIX (NL_USE_ACADEMIC_SOLVERS)
|
||||
//#define NL_USE_LONG_DOUBLE_MATRIX 1
|
||||
//#define NL_USE_LONG_DOUBLE_MATRIX (NL_USE_ACADEMIC_SOLVERS)
|
||||
#define NL_USE_LONG_DOUBLE_MATRIX 1
|
||||
#endif
|
||||
|
||||
//============================================================
|
||||
|
@ -947,7 +947,7 @@ void setup_t::resolve_inputs()
|
||||
detail::core_terminal_t *t1 = find_terminal(t1s);
|
||||
detail::core_terminal_t *t2 = find_terminal(t2s);
|
||||
if (connect(*t1, *t2))
|
||||
m_links.erase(m_links.begin() + i);
|
||||
m_links.erase(m_links.begin() + static_cast<std::ptrdiff_t>(i));
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
@ -412,13 +412,11 @@ namespace solver
|
||||
}
|
||||
}
|
||||
|
||||
// update_forced is called from within param_update
|
||||
//
|
||||
// this should only occur outside of execution and thus
|
||||
// using time should be safe.
|
||||
|
||||
void matrix_solver_t::update_forced()
|
||||
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);
|
||||
|
||||
@ -487,7 +485,11 @@ namespace solver
|
||||
this->store();
|
||||
}
|
||||
|
||||
return compute_next_timestep(delta.as_fp<nl_fptype>());
|
||||
|
||||
if (m_params.m_dynamic_ts)
|
||||
return compute_next_timestep(delta.as_fp<nl_fptype>(), m_params.m_max_timestep);
|
||||
|
||||
return netlist_time::from_fp(m_params.m_max_timestep);
|
||||
}
|
||||
|
||||
int matrix_solver_t::get_net_idx(const analog_net_t *net) const noexcept
|
||||
|
@ -194,7 +194,13 @@ namespace solver
|
||||
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(); }
|
||||
|
||||
void update_forced();
|
||||
/// \brief Immediately solve system at current time
|
||||
///
|
||||
/// 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 update_after(netlist_time after) noexcept
|
||||
{
|
||||
m_Q_sync.net().toggle_and_push_to_queue(after);
|
||||
@ -224,7 +230,7 @@ namespace solver
|
||||
const solver_parameters_t *params);
|
||||
|
||||
virtual void vsolve_non_dynamic() = 0;
|
||||
virtual netlist_time compute_next_timestep(nl_fptype cur_ts) = 0;
|
||||
virtual netlist_time compute_next_timestep(nl_fptype cur_ts, nl_fptype max_ts) = 0;
|
||||
virtual bool check_err() = 0;
|
||||
virtual void store() = 0;
|
||||
|
||||
@ -402,13 +408,26 @@ namespace solver
|
||||
return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim;
|
||||
}
|
||||
|
||||
#if 1
|
||||
void store() override
|
||||
{
|
||||
const std::size_t iN = size();
|
||||
for (std::size_t i = 0; i < iN; i++)
|
||||
this->m_terms[i].setV(m_new_V[i]);
|
||||
}
|
||||
|
||||
#else
|
||||
// global tanh damping (4.197)
|
||||
// partially cures the symptoms but not the cause
|
||||
void store() override
|
||||
{
|
||||
const std::size_t iN = size();
|
||||
for (std::size_t i = 0; i < iN; i++)
|
||||
{
|
||||
auto oldV = this->m_terms[i].template getV<nl_fptype>();
|
||||
this->m_terms[i].setV(oldV + 0.02 * plib::tanh((m_new_V[i]-oldV)*50.0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bool check_err() override
|
||||
{
|
||||
// NOTE: Ideally we should also include currents (RHS) here. This would
|
||||
@ -429,38 +448,35 @@ namespace solver
|
||||
return false;
|
||||
}
|
||||
|
||||
netlist_time compute_next_timestep(const nl_fptype cur_ts) override
|
||||
netlist_time compute_next_timestep(nl_fptype cur_ts, nl_fptype max_ts) override
|
||||
{
|
||||
nl_fptype new_solver_timestep = m_params.m_max_timestep;
|
||||
nl_fptype new_solver_timestep(max_ts);
|
||||
|
||||
if (m_params.m_dynamic_ts)
|
||||
for (std::size_t k = 0; k < size(); k++)
|
||||
{
|
||||
for (std::size_t k = 0; k < size(); k++)
|
||||
{
|
||||
const auto &t = m_terms[k];
|
||||
const auto v(t.template getV<nl_fptype>());
|
||||
// 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])));
|
||||
const auto &t = m_terms[k];
|
||||
const auto v(t.template getV<nl_fptype>());
|
||||
// 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])));
|
||||
|
||||
m_last_V[k] = v;
|
||||
const nl_fptype hn = cur_ts;
|
||||
m_last_V[k] = v;
|
||||
const nl_fptype hn = cur_ts;
|
||||
|
||||
//printf("%g %g %g %g\n", DD_n, hn, t.m_DD_n_m_1, t.m_h_n_m_1);
|
||||
nl_fptype DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]);
|
||||
nl_fptype new_net_timestep(0);
|
||||
//printf("%g %g %g %g\n", DD_n, hn, t.m_DD_n_m_1, t.m_h_n_m_1);
|
||||
nl_fptype DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]);
|
||||
nl_fptype new_net_timestep(0);
|
||||
|
||||
m_h_n_m_1[k] = hn;
|
||||
m_DD_n_m_1[k] = DD_n;
|
||||
if (plib::abs(DD2) > fp_constants<nl_fptype>::TIMESTEP_MINDIV()) // avoid div-by-zero
|
||||
new_net_timestep = plib::sqrt(m_params.m_dynamic_lte / plib::abs(nlconst::magic(0.5)*DD2));
|
||||
else
|
||||
new_net_timestep = m_params.m_max_timestep;
|
||||
m_h_n_m_1[k] = hn;
|
||||
m_DD_n_m_1[k] = DD_n;
|
||||
if (plib::abs(DD2) > fp_constants<nl_fptype>::TIMESTEP_MINDIV()) // avoid div-by-zero
|
||||
new_net_timestep = plib::sqrt(m_params.m_dynamic_lte / plib::abs(nlconst::magic(0.5)*DD2));
|
||||
else
|
||||
new_net_timestep = m_params.m_max_timestep;
|
||||
|
||||
new_solver_timestep = std::min(new_net_timestep, new_solver_timestep);
|
||||
}
|
||||
new_solver_timestep = std::max(new_solver_timestep, m_params.m_min_timestep);
|
||||
new_solver_timestep = std::min(new_net_timestep, new_solver_timestep);
|
||||
}
|
||||
new_solver_timestep = std::max(new_solver_timestep, m_params.m_min_timestep);
|
||||
|
||||
// FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere.
|
||||
return std::max(netlist_time::from_fp(new_solver_timestep), netlist_time::quantum() * 2);
|
||||
|
@ -106,7 +106,7 @@ namespace solver
|
||||
|
||||
for (std::size_t k = 0; k < iN; k++)
|
||||
{
|
||||
this->m_new_V[k] = this->m_terms[k].template getV<float_type>();
|
||||
this->m_new_V[k] = static_cast<float_type>(this->m_terms[k].getV());
|
||||
}
|
||||
|
||||
const auto accuracy(static_cast<float_type>(this->m_params.m_accuracy));
|
||||
|
@ -80,7 +80,7 @@ namespace solver
|
||||
const nl_fptype * const Idr = this->m_Idrn[k];
|
||||
auto other_cur_analog = this->m_connected_net_Vn[k];
|
||||
|
||||
this->m_new_V[k] = this->m_terms[k].template getV<float_type>();
|
||||
this->m_new_V[k] = static_cast<float_type>(this->m_terms[k].getV());
|
||||
|
||||
for (std::size_t i = 0; i < term_count; i++)
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ namespace solver
|
||||
#endif
|
||||
|
||||
for (std::size_t k = 0; k < iN; k++)
|
||||
this->m_new_V[k] = this->m_terms[k].template getV<FT>();
|
||||
this->m_new_V[k] = static_cast<float_type>(this->m_terms[k].getV());
|
||||
|
||||
do {
|
||||
resched = false;
|
||||
|
Loading…
Reference in New Issue
Block a user