mirror of
https://github.com/holub/mame
synced 2025-04-21 16:01:56 +03:00
Removed dead code and simplified matrix solvers. No Wn
This commit is contained in:
parent
61f3de3165
commit
bcbd00db40
@ -58,64 +58,6 @@ NETLIB_UPDATE(Q)
|
||||
// nld_QBJT_switch
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#if USE_OLD_S
|
||||
NETLIB_START(QBJT_switch)
|
||||
{
|
||||
NETLIB_NAME(Q)::start();
|
||||
|
||||
register_sub(m_RB, "RB");
|
||||
register_sub(m_RC, "RC");
|
||||
register_input("BV", m_BV);
|
||||
register_input("EV", m_EV);
|
||||
|
||||
register_subalias("B", m_RB.m_P);
|
||||
register_subalias("E", m_RB.m_N);
|
||||
register_subalias("C", m_RC.m_P);
|
||||
|
||||
connect(m_RB.m_N, m_RC.m_N);
|
||||
connect(m_RB.m_P, m_BV);
|
||||
connect(m_RB.m_N, m_EV);
|
||||
|
||||
save(NAME(m_state_on));
|
||||
|
||||
m_RB.set(NETLIST_GMIN, 0.0, 0.0);
|
||||
m_RC.set(NETLIST_GMIN, 0.0, 0.0);
|
||||
|
||||
m_state_on = 0;
|
||||
|
||||
{
|
||||
double IS = m_model.model_value("IS", 1e-15);
|
||||
double BF = m_model.model_value("BF", 100);
|
||||
double NF = m_model.model_value("NF", 1);
|
||||
//double VJE = m_model.dValue("VJE", 0.75);
|
||||
|
||||
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
||||
|
||||
double alpha = BF / (1.0 + BF);
|
||||
|
||||
diode d(IS, NF);
|
||||
|
||||
// Assume 5mA Collector current for switch operation
|
||||
|
||||
m_V = d.V(0.005 / alpha);
|
||||
|
||||
/* Base current is 0.005 / beta
|
||||
* as a rough estimate, we just scale the conductance down */
|
||||
|
||||
m_gB = d.gI(0.005 / alpha) / BF;
|
||||
|
||||
if (m_gB < NETLIST_GMIN)
|
||||
m_gB = NETLIST_GMIN;
|
||||
m_gC = BF * m_gB; // very rough estimate
|
||||
//printf("%f %f \n", m_V, m_gB);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(QBJT_switch)
|
||||
{
|
||||
}
|
||||
#else
|
||||
NETLIB_START(QBJT_switch)
|
||||
{
|
||||
NETLIB_NAME(Q)::start();
|
||||
@ -175,77 +117,12 @@ NETLIB_UPDATE_PARAM(QBJT_switch)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// nld_Q - Ebers Moll
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#define USE_OLD_B (0)
|
||||
|
||||
#if USE_OLD_B
|
||||
NETLIB_START(QBJT_EB)
|
||||
{
|
||||
NETLIB_NAME(Q)::start();
|
||||
|
||||
register_terminal("B", m_D_BE.m_P); // Anode
|
||||
register_terminal("E", m_D_BE.m_N); // Cathode
|
||||
|
||||
register_terminal("_B1", m_D_BC.m_P); // Anode
|
||||
register_terminal("C", m_D_BC.m_N); // Cathode
|
||||
|
||||
register_terminal("_B2", m_I_BE.m_P);
|
||||
register_terminal("_E2", m_I_BE.m_N);
|
||||
|
||||
register_terminal("_B3", m_I_BC.m_P);
|
||||
register_terminal("_C1", m_I_BC.m_N);
|
||||
|
||||
connect(m_D_BE.m_P, m_D_BC.m_P);
|
||||
connect(m_D_BE.m_P, m_I_BE.m_P);
|
||||
connect(m_D_BE.m_P, m_I_BC.m_P);
|
||||
|
||||
connect(m_D_BE.m_N, m_I_BE.m_N);
|
||||
connect(m_D_BC.m_N, m_I_BC.m_N);
|
||||
|
||||
m_gD_BE.save("m_D_BE", *this);
|
||||
m_gD_BC.save("m_D_BC", *this);
|
||||
|
||||
{
|
||||
double IS = m_model.model_value("IS", 1e-15);
|
||||
double BF = m_model.model_value("BF", 100);
|
||||
double NF = m_model.model_value("NF", 1);
|
||||
double BR = m_model.model_value("BR", 1);
|
||||
double NR = m_model.model_value("NR", 1);
|
||||
//double VJE = m_model.dValue("VJE", 0.75);
|
||||
|
||||
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
||||
//printf("type %s\n", m_model.model_type().cstr());
|
||||
|
||||
m_alpha_f = BF / (1.0 + BF);
|
||||
m_alpha_r = BR / (1.0 + BR);
|
||||
|
||||
m_gD_BE.set_param(IS / m_alpha_f, NF);
|
||||
m_gD_BC.set_param(IS / m_alpha_r, NR);
|
||||
}
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(QBJT_EB)
|
||||
{
|
||||
#if !(USE_ALTERNATE_SCHEDULING)
|
||||
netlist().solver()->schedule1();
|
||||
#else
|
||||
if (!m_D_BE.m_P.net().isRailNet())
|
||||
m_D_BE.m_P.net().solve(); // Basis
|
||||
else if (!m_D_BE.m_N.net().isRailNet())
|
||||
m_D_BE.m_N.net().solve(); // Emitter
|
||||
else
|
||||
m_D_BC.m_N.net().solve(); // Collector
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
NETLIB_START(QBJT_EB)
|
||||
{
|
||||
NETLIB_NAME(Q)::start();
|
||||
@ -287,18 +164,13 @@ NETLIB_START(QBJT_EB)
|
||||
|
||||
NETLIB_UPDATE(QBJT_EB)
|
||||
{
|
||||
#if !(USE_ALTERNATE_SCHEDULING)
|
||||
netlist().solver()->schedule1();
|
||||
#else
|
||||
if (!m_D_EB.m_P.net().isRailNet())
|
||||
m_D_EB.m_P.net().solve(); // Basis
|
||||
else if (!m_D_EB.m_N.net().isRailNet())
|
||||
m_D_EB.m_N.net().solve(); // Emitter
|
||||
else
|
||||
m_D_CB.m_N.net().solve(); // Collector
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
NETLIB_RESET(QBJT_EB)
|
||||
{
|
||||
|
@ -86,64 +86,6 @@ private:
|
||||
* E
|
||||
*/
|
||||
|
||||
#define USE_OLD_S (0)
|
||||
|
||||
#if USE_OLD_S
|
||||
class NETLIB_NAME(QBJT_switch) : public NETLIB_NAME(QBJT)
|
||||
{
|
||||
public:
|
||||
ATTR_COLD NETLIB_NAME(QBJT_switch)()
|
||||
: NETLIB_NAME(QBJT)(BJT_SWITCH), m_gB(NETLIST_GMIN), m_gC(NETLIST_GMIN), m_V(0.0), m_state_on(0) { }
|
||||
|
||||
|
||||
NETLIB_UPDATEI()
|
||||
{
|
||||
double vE = INPANALOG(m_EV);
|
||||
double vB = INPANALOG(m_BV);
|
||||
double m = (is_qtype( BJT_NPN) ? 1 : -1);
|
||||
|
||||
int new_state = ((vB - vE) * m > m_V ) ? 1 : 0;
|
||||
if (m_state_on ^ new_state)
|
||||
{
|
||||
double gb = m_gB;
|
||||
double gc = m_gC;
|
||||
double v = m_V * m;
|
||||
if (!new_state )
|
||||
{
|
||||
// not conducting
|
||||
gb = NETLIST_GMIN;
|
||||
v = 0;
|
||||
gc = NETLIST_GMIN;
|
||||
}
|
||||
m_RB.set(gb, v, 0.0);
|
||||
m_RC.set(gc, 0.0, 0.0);
|
||||
m_state_on = new_state;
|
||||
// Don't update m_RB - could cause an infinite loop
|
||||
m_RB.update_dev();
|
||||
m_RC.update_dev();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NETLIB_NAME(R) m_RB;
|
||||
NETLIB_NAME(R) m_RC;
|
||||
|
||||
netlist_analog_input_t m_BV;
|
||||
netlist_analog_input_t m_EV;
|
||||
|
||||
protected:
|
||||
|
||||
ATTR_COLD virtual void start();
|
||||
ATTR_HOT void update_param();
|
||||
|
||||
double m_gB; // base conductance / switch on
|
||||
double m_gC; // collector conductance / switch on
|
||||
double m_V; // internal voltage source
|
||||
UINT8 m_state_on;
|
||||
|
||||
private:
|
||||
};
|
||||
#else
|
||||
class NETLIB_NAME(QBJT_switch) : public NETLIB_NAME(QBJT)
|
||||
{
|
||||
public:
|
||||
@ -207,60 +149,12 @@ protected:
|
||||
|
||||
private:
|
||||
};
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// nld_QBJT_EB
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#define USE_OLD_B (0)
|
||||
|
||||
#if USE_OLD_B
|
||||
class NETLIB_NAME(QBJT_EB) : public NETLIB_NAME(QBJT)
|
||||
{
|
||||
public:
|
||||
ATTR_COLD NETLIB_NAME(QBJT_EB)()
|
||||
: NETLIB_NAME(QBJT)(BJT_EB),
|
||||
m_D_BC(netlist_object_t::ANALOG),
|
||||
m_D_BE(netlist_object_t::ANALOG),
|
||||
m_I_BC(netlist_object_t::ANALOG),
|
||||
m_I_BE(netlist_object_t::ANALOG)
|
||||
{ }
|
||||
|
||||
NETLIB_UPDATE_TERMINALS()
|
||||
{
|
||||
m_gD_BE.update_diode(m_D_BE.deltaV());
|
||||
m_gD_BC.update_diode(m_D_BC.deltaV());
|
||||
|
||||
m_D_BE.set(m_gD_BE.G(), 0.0, m_gD_BE.Ieq());
|
||||
m_D_BC.set(m_gD_BC.G(), 0.0, m_gD_BC.Ieq());
|
||||
|
||||
m_I_BE.set(0.0, 0.0, - m_alpha_r * m_gD_BC.I());
|
||||
m_I_BC.set(0.0, 0.0, - m_alpha_f * m_gD_BE.I());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
ATTR_COLD virtual void start();
|
||||
ATTR_COLD virtual void reset();
|
||||
ATTR_HOT void update_param();
|
||||
ATTR_HOT ATTR_ALIGN void virtual update();
|
||||
|
||||
netlist_generic_diode m_gD_BC;
|
||||
netlist_generic_diode m_gD_BE;
|
||||
|
||||
nld_twoterm m_D_BC;
|
||||
nld_twoterm m_D_BE;
|
||||
|
||||
nld_twoterm m_I_BC;
|
||||
nld_twoterm m_I_BE;
|
||||
|
||||
double m_alpha_f;
|
||||
double m_alpha_r;
|
||||
|
||||
private:
|
||||
};
|
||||
#else
|
||||
class NETLIB_NAME(QBJT_EB) : public NETLIB_NAME(QBJT)
|
||||
{
|
||||
public:
|
||||
@ -312,5 +206,5 @@ protected:
|
||||
|
||||
private:
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* NLD_BJT_H_ */
|
||||
|
@ -59,14 +59,11 @@ NETLIB_UPDATE_PARAM(VCCS)
|
||||
NETLIB_UPDATE(VCCS)
|
||||
{
|
||||
/* only called if connected to a rail net ==> notify the solver to recalculate */
|
||||
#if !(USE_ALTERNATE_SCHEDULING)
|
||||
netlist().solver()->schedule1();
|
||||
#else
|
||||
/* Big FIXME ... */
|
||||
m_IP.net().solve();
|
||||
m_IN.net().solve();
|
||||
m_OP.net().solve();
|
||||
m_ON.net().solve();
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -140,13 +140,44 @@ ATTR_HOT inline void netlist_matrix_solver_t::step(const netlist_time delta)
|
||||
m_steps[k]->step_time(dd);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool netlist_matrix_solver_t::solve()
|
||||
{
|
||||
int resched_cnt = 0;
|
||||
|
||||
netlist_time now = owner().netlist().time();
|
||||
netlist_time delta = now - m_last_step;
|
||||
if (delta >= netlist_time::from_nsec(1)) // always update capacitors
|
||||
{
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
m_last_step = now;
|
||||
step(delta);
|
||||
}
|
||||
|
||||
if (is_dynamic())
|
||||
{
|
||||
int this_resched;
|
||||
do
|
||||
{
|
||||
update_dynamic();
|
||||
this_resched = solve_non_dynamic();
|
||||
resched_cnt += this_resched;
|
||||
} while (this_resched > 1 && resched_cnt < m_resched_loops);
|
||||
}
|
||||
else
|
||||
{
|
||||
resched_cnt = solve_non_dynamic();
|
||||
}
|
||||
return (resched_cnt >= m_resched_loops);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_matrix_solver - Direct base
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
ATTR_COLD int netlist_matrix_solver_directb_t<m_N, _storage_N>::get_net_idx(netlist_net_t *net)
|
||||
ATTR_COLD int netlist_matrix_solver_direct_t<m_N, _storage_N>::get_net_idx(netlist_net_t *net)
|
||||
{
|
||||
for (int k = 0; k < N(); k++)
|
||||
if (m_nets[k] == net)
|
||||
@ -155,7 +186,7 @@ ATTR_COLD int netlist_matrix_solver_directb_t<m_N, _storage_N>::get_net_idx(netl
|
||||
}
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
ATTR_COLD void netlist_matrix_solver_directb_t<m_N, _storage_N>::setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner)
|
||||
ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner)
|
||||
{
|
||||
netlist_matrix_solver_t::setup(nets, owner);
|
||||
|
||||
@ -201,7 +232,9 @@ ATTR_COLD void netlist_matrix_solver_directb_t<m_N, _storage_N>::setup(netlist_n
|
||||
}
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
ATTR_HOT inline void netlist_matrix_solver_directb_t<m_N, _storage_N>::build_LE(double (* RESTRICT m_A)[_storage_N], double (* RESTRICT m_RHS))
|
||||
ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE(
|
||||
double (* RESTRICT A)[_storage_N],
|
||||
double (* RESTRICT RHS))
|
||||
{
|
||||
|
||||
#if 0
|
||||
@ -223,22 +256,117 @@ ATTR_HOT inline void netlist_matrix_solver_directb_t<m_N, _storage_N>::build_LE
|
||||
for (int i = 0; i < m_rail_start; i++)
|
||||
{
|
||||
terms_t &t = m_terms[i];
|
||||
m_RHS[t.net_this] += t.term->m_Idr;
|
||||
m_A[t.net_this][t.net_this] += t.term->m_gt;
|
||||
RHS[t.net_this] += t.term->m_Idr;
|
||||
A[t.net_this][t.net_this] += t.term->m_gt;
|
||||
|
||||
m_A[t.net_this][t.net_other] += -t.term->m_go;
|
||||
A[t.net_this][t.net_other] += -t.term->m_go;
|
||||
}
|
||||
for (int i = m_rail_start; i < m_term_num; i++)
|
||||
{
|
||||
terms_t &t = m_terms[i];
|
||||
m_RHS[t.net_this] += t.term->m_Idr;
|
||||
m_A[t.net_this][t.net_this] += t.term->m_gt;
|
||||
RHS[t.net_this] += t.term->m_Idr;
|
||||
A[t.net_this][t.net_this] += t.term->m_gt;
|
||||
|
||||
m_RHS[t.net_this] += t.term->m_go * t.term->m_otherterm->net().Q_Analog();
|
||||
RHS[t.net_this] += t.term->m_go * t.term->m_otherterm->net().Q_Analog();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
|
||||
double (* RESTRICT A)[_storage_N],
|
||||
double (* RESTRICT RHS),
|
||||
double (* RESTRICT x))
|
||||
{
|
||||
for (int i = 0; i < N(); i++) {
|
||||
|
||||
#if 0
|
||||
/* Find the row with the largest first value */
|
||||
maxrow = i;
|
||||
for (j=i+1;j<n;j++) {
|
||||
if (ABS(a[i][j]) > ABS(a[i][maxrow]))
|
||||
maxrow = j;
|
||||
}
|
||||
|
||||
/* Swap the maxrow and ith row */
|
||||
for (k=i;k<n+1;k++) {
|
||||
tmp = a[k][i];
|
||||
a[k][i] = a[k][maxrow];
|
||||
a[k][maxrow] = tmp;
|
||||
}
|
||||
#endif
|
||||
/* Singular matrix? */
|
||||
double f = A[i][i];
|
||||
//if (fabs(A[i][i]) < 1e-20) printf("Singular!");
|
||||
f = 1.0 / f;
|
||||
|
||||
/* Eliminate column i from row j */
|
||||
for (int j = i + 1; j < N(); j++)
|
||||
{
|
||||
double f1 = A[j][i] * f;
|
||||
|
||||
for (int k = i; k < N(); k++)
|
||||
{
|
||||
A[j][k] -= A[i][k] * f1;
|
||||
}
|
||||
RHS[j] -= RHS[i] * f1;
|
||||
}
|
||||
}
|
||||
|
||||
/* back substitution */
|
||||
for (int j = N() - 1; j >= 0; j--)
|
||||
{
|
||||
double tmp = 0;
|
||||
for (int k = j + 1; k < N(); k++)
|
||||
tmp += A[j][k] * x[k];
|
||||
x[j] = (RHS[j] - tmp) / A[j][j];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
ATTR_HOT inline double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta_and_store(
|
||||
double (* RESTRICT RHS),
|
||||
double (* RESTRICT V))
|
||||
{
|
||||
double cerr = 0;
|
||||
double cerr2 = 0;
|
||||
for (int i = 0; i < this->N(); i++)
|
||||
{
|
||||
double e = (V[i] - this->m_nets[i]->m_cur.Analog);
|
||||
double e2 = (RHS[i] - this->m_RHS[i]);
|
||||
cerr += e * e;
|
||||
cerr2 += e2 * e2;
|
||||
this->m_nets[i]->m_cur.Analog = this->m_nets[i]->m_new.Analog = V[i];
|
||||
this->m_RHS[i] = RHS[i];
|
||||
}
|
||||
return (cerr + cerr2*(100000.0 * 100000.0)) / this->N();
|
||||
}
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic()
|
||||
{
|
||||
double A[_storage_N][_storage_N] = { { 0.0 } };
|
||||
double RHS[_storage_N] = { 0.0 };
|
||||
double new_v[_storage_N] = { 0.0 };
|
||||
|
||||
this->build_LE(A, RHS);
|
||||
|
||||
this->gauss_LE(A, RHS, new_v);
|
||||
|
||||
if (this->is_dynamic())
|
||||
{
|
||||
double err = delta_and_store(RHS, new_v);
|
||||
|
||||
if (err > this->m_accuracy * this->m_accuracy)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_matrix_solver - Direct1
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -246,12 +374,6 @@ ATTR_HOT inline void netlist_matrix_solver_directb_t<m_N, _storage_N>::build_LE
|
||||
ATTR_HOT inline int netlist_matrix_solver_direct1_t::solve_non_dynamic()
|
||||
{
|
||||
#if 1
|
||||
ATTR_UNUSED netlist_net_t *last_resched_net = NULL;
|
||||
|
||||
/* over-relaxation not really works on these matrices */
|
||||
//const double w = 1.0; //2.0 / (1.0 + sin(3.14159 / (m_nets.count()+1)));
|
||||
//const double w1 = 1.0 - w;
|
||||
//NL_VERBOSE_OUT(("%d %d\n", N(), 1);
|
||||
|
||||
double gtot_t = 0.0;
|
||||
double RHS_t = 0.0;
|
||||
@ -294,40 +416,6 @@ ATTR_HOT inline int netlist_matrix_solver_direct1_t::solve_non_dynamic()
|
||||
}
|
||||
|
||||
|
||||
ATTR_HOT inline bool netlist_matrix_solver_direct1_t::solve()
|
||||
{
|
||||
int resched_cnt = 0;
|
||||
ATTR_UNUSED netlist_net_t *last_resched_net = NULL;
|
||||
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
{
|
||||
netlist_time now = owner().netlist().time();
|
||||
netlist_time delta = now - m_last_step;
|
||||
if (delta >= netlist_time::from_nsec(5)) // always update capacitors
|
||||
{
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
m_last_step = now;
|
||||
step(delta);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dynamic())
|
||||
{
|
||||
int this_resched;
|
||||
do
|
||||
{
|
||||
update_dynamic();
|
||||
this_resched = solve_non_dynamic();
|
||||
resched_cnt += this_resched;
|
||||
} while (this_resched > 1 && resched_cnt < m_resched_loops);
|
||||
}
|
||||
else
|
||||
{
|
||||
resched_cnt = solve_non_dynamic();
|
||||
}
|
||||
return (resched_cnt >= m_resched_loops);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_matrix_solver - Direct2
|
||||
@ -335,74 +423,30 @@ ATTR_HOT inline bool netlist_matrix_solver_direct1_t::solve()
|
||||
|
||||
ATTR_HOT int netlist_matrix_solver_direct2_t::solve_non_dynamic()
|
||||
{
|
||||
double m_A[2][2] = { { 0.0 } };
|
||||
double m_RHS[2] = { 0.0 };
|
||||
double A[2][2] = { { 0.0 } };
|
||||
double RHS[2] = { 0.0 };
|
||||
|
||||
build_LE(A, RHS);
|
||||
|
||||
build_LE(m_A, m_RHS);
|
||||
//NL_VERBOSE_OUT(("%f %f\n", new_val, m_RHS[0] / m_A[0][0]);
|
||||
|
||||
const double a = m_A[0][0];
|
||||
const double b = m_A[0][1];
|
||||
const double c = m_A[1][0];
|
||||
const double d = m_A[1][1];
|
||||
const double a = A[0][0];
|
||||
const double b = A[0][1];
|
||||
const double c = A[1][0];
|
||||
const double d = A[1][1];
|
||||
|
||||
const double new_val1 = a / (a*d - b*c) * (m_RHS[1] - c / a * m_RHS[0]);
|
||||
const double new_val0 = (m_RHS[0] - b * new_val1) / a;
|
||||
double new_val[2];
|
||||
new_val[1] = a / (a*d - b*c) * (RHS[1] - c / a * RHS[0]);
|
||||
new_val[0] = (RHS[0] - b * new_val[1]) / a;
|
||||
|
||||
double e = (new_val0 - m_nets[0]->m_cur.Analog);
|
||||
double cerr = e * e;
|
||||
m_nets[0]->m_cur.Analog = m_nets[0]->m_new.Analog = new_val0;
|
||||
|
||||
e = (new_val1 - m_nets[1]->m_cur.Analog);
|
||||
cerr += e * e;
|
||||
m_nets[1]->m_cur.Analog = m_nets[1]->m_new.Analog = new_val1;
|
||||
|
||||
if (is_dynamic() && (cerr / N() > m_accuracy * m_accuracy))
|
||||
if (is_dynamic() && (delta_and_store(RHS, new_val) > m_accuracy * m_accuracy))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ATTR_HOT inline bool netlist_matrix_solver_direct2_t::solve()
|
||||
{
|
||||
int resched_cnt = 0;
|
||||
ATTR_UNUSED netlist_net_t *last_resched_net = NULL;
|
||||
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
{
|
||||
netlist_time now = owner().netlist().time();
|
||||
netlist_time delta = now - m_last_step;
|
||||
if (delta >= netlist_time::from_nsec(5)) // always update capacitors
|
||||
{
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
m_last_step = now;
|
||||
step(delta);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dynamic())
|
||||
{
|
||||
int this_resched;
|
||||
do
|
||||
{
|
||||
update_dynamic();
|
||||
this_resched = solve_non_dynamic();
|
||||
resched_cnt += this_resched;
|
||||
} while (this_resched > 1 && resched_cnt < m_resched_loops);
|
||||
}
|
||||
else
|
||||
{
|
||||
resched_cnt = solve_non_dynamic();
|
||||
}
|
||||
return (resched_cnt >= m_resched_loops);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_matrix_solver - Gauss - Seidel
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -503,51 +547,6 @@ ATTR_HOT inline int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::solve
|
||||
return resched_cnt;
|
||||
}
|
||||
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
ATTR_HOT inline bool netlist_matrix_solver_gauss_seidel_t< m_N, _storage_N>::solve()
|
||||
{
|
||||
int resched_cnt = 0;
|
||||
ATTR_UNUSED netlist_net_t *last_resched_net = NULL;
|
||||
|
||||
m_resched = false;
|
||||
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
{
|
||||
netlist_time now = owner().netlist().time();
|
||||
netlist_time delta = now - m_last_step;
|
||||
if (delta >= netlist_time::from_nsec(5)) // always update capacitors
|
||||
{
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
m_last_step = now;
|
||||
step(delta);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dynamic())
|
||||
{
|
||||
int this_resched;
|
||||
do
|
||||
{
|
||||
update_dynamic();
|
||||
this_resched = solve_non_dynamic();
|
||||
resched_cnt += this_resched;
|
||||
} while (this_resched > 1 && resched_cnt < m_resched_loops);
|
||||
}
|
||||
else
|
||||
{
|
||||
resched_cnt = solve_non_dynamic();
|
||||
}
|
||||
if (resched_cnt >= m_resched_loops)
|
||||
m_resched = true;
|
||||
|
||||
//if (resched)
|
||||
//NL_VERBOSE_OUT(("Resched on net %s first term %s\n", last_resched_net->name().cstr(), last_resched_net->m_terms[0]->name().cstr());
|
||||
|
||||
return m_resched;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// solver
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -594,14 +593,14 @@ NETLIB_START(solver)
|
||||
register_output("Q_step", m_Q_step);
|
||||
//register_input("FB", m_feedback);
|
||||
|
||||
register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(10).as_double());
|
||||
register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(5).as_double());
|
||||
m_nt_sync_delay = m_sync_delay.Value();
|
||||
|
||||
register_param("FREQ", m_freq, 48000.0);
|
||||
m_inc = netlist_time::from_hz(m_freq.Value());
|
||||
|
||||
//register_param("ACCURACY", m_accuracy, 1e-3);
|
||||
register_param("ACCURACY", m_accuracy, 1e-6);
|
||||
register_param("ACCURACY", m_accuracy, 1e-7);
|
||||
register_param("CONVERG", m_convergence, 0.3);
|
||||
register_param("RESCHED_LOOPS", m_resched_loops, 35);
|
||||
|
||||
@ -646,26 +645,15 @@ NETLIB_UPDATE(solver)
|
||||
{
|
||||
netlist_time now = netlist().time();
|
||||
netlist_time delta = now - m_last_step;
|
||||
bool do_full = (USE_ALTERNATE_SCHEDULING ? false : true);
|
||||
bool do_full = false;
|
||||
bool global_resched = false;
|
||||
bool this_resched[100];
|
||||
|
||||
if (delta < m_inc)
|
||||
do_full = true; // we have been called between updates
|
||||
|
||||
//FIXME: make this a parameter
|
||||
if (!USE_ALTERNATE_SCHEDULING && delta >= netlist_time::from_nsec(5)) // always update capacitors
|
||||
{
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
for (netlist_matrix_solver_t * const *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
|
||||
{
|
||||
(*e)->step(delta);
|
||||
}
|
||||
}
|
||||
m_last_step = now;
|
||||
|
||||
|
||||
#if HAS_OPENMP && USE_OPENMP
|
||||
int t_cnt = m_mat_solvers.count();
|
||||
omp_set_num_threads(3);
|
||||
@ -739,20 +727,25 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start()
|
||||
ms = new netlist_matrix_solver_direct1_t();
|
||||
break;
|
||||
case 2:
|
||||
//ms = new netlist_matrix_solver_gauss_seidel_t<2,2>();
|
||||
// Below is only half as fast as gauss_seidel ....
|
||||
ms = new netlist_matrix_solver_direct2_t();
|
||||
break;
|
||||
/* FIXME: There is an issue (singularity during gaussian elemination
|
||||
* with the direct solver - use gauss_seidel
|
||||
*/
|
||||
case 3:
|
||||
//ms = new netlist_matrix_solver_direct_t<3,3>();
|
||||
ms = new netlist_matrix_solver_gauss_seidel_t<3,3>();
|
||||
break;
|
||||
case 4:
|
||||
//ms = new netlist_matrix_solver_direct_t<4,4>();
|
||||
ms = new netlist_matrix_solver_gauss_seidel_t<4,4>();
|
||||
break;
|
||||
case 5:
|
||||
//ms = new netlist_matrix_solver_direct_t<5,5>();
|
||||
ms = new netlist_matrix_solver_gauss_seidel_t<5,5>();
|
||||
break;
|
||||
default:
|
||||
//ms = new netlist_matrix_solver_direct_t<0,16>();
|
||||
ms = new netlist_matrix_solver_gauss_seidel_t<0,16>();
|
||||
break;
|
||||
}
|
||||
|
@ -36,10 +36,11 @@ public:
|
||||
ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner);
|
||||
|
||||
// return true if a reschedule is needed ...
|
||||
ATTR_HOT virtual bool solve() = 0;
|
||||
ATTR_HOT virtual int solve_non_dynamic() = 0;
|
||||
ATTR_HOT virtual void step(const netlist_time delta);
|
||||
|
||||
ATTR_HOT bool solve();
|
||||
|
||||
ATTR_HOT void update_inputs();
|
||||
ATTR_HOT void update_dynamic();
|
||||
|
||||
@ -66,21 +67,30 @@ protected:
|
||||
};
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
class netlist_matrix_solver_directb_t: public netlist_matrix_solver_t
|
||||
class netlist_matrix_solver_direct_t: public netlist_matrix_solver_t
|
||||
{
|
||||
public:
|
||||
|
||||
netlist_matrix_solver_directb_t() : netlist_matrix_solver_t() {}
|
||||
netlist_matrix_solver_direct_t() : netlist_matrix_solver_t() {}
|
||||
|
||||
virtual ~netlist_matrix_solver_directb_t() {}
|
||||
virtual ~netlist_matrix_solver_direct_t() {}
|
||||
|
||||
ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner);
|
||||
ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); }
|
||||
ATTR_HOT virtual int solve_non_dynamic();
|
||||
|
||||
ATTR_HOT inline const int N() const { return (m_N == 0) ? m_nets.count() : m_N; }
|
||||
ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); }
|
||||
|
||||
protected:
|
||||
ATTR_HOT inline void build_LE(double (* RESTRICT m_A)[_storage_N], double (* RESTRICT m_RHS));
|
||||
ATTR_HOT inline void build_LE(double (* RESTRICT A)[_storage_N], double (* RESTRICT RHS));
|
||||
ATTR_HOT inline void gauss_LE(double (* RESTRICT A)[_storage_N],
|
||||
double (* RESTRICT RHS),
|
||||
double (* RESTRICT x));
|
||||
ATTR_HOT inline double delta_and_store(
|
||||
double (* RESTRICT RHS),
|
||||
double (* RESTRICT V));
|
||||
|
||||
double m_RHS[_storage_N]; // right hand side - contains currents
|
||||
|
||||
private:
|
||||
|
||||
@ -101,68 +111,35 @@ class netlist_matrix_solver_gauss_seidel_t: public netlist_matrix_solver_t
|
||||
{
|
||||
public:
|
||||
|
||||
netlist_matrix_solver_gauss_seidel_t() : netlist_matrix_solver_t(), m_resched(false) {}
|
||||
netlist_matrix_solver_gauss_seidel_t() : netlist_matrix_solver_t() {}
|
||||
|
||||
virtual ~netlist_matrix_solver_gauss_seidel_t() {}
|
||||
|
||||
ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner)
|
||||
{
|
||||
m_resched = true;
|
||||
netlist_matrix_solver_t::setup(nets, owner);
|
||||
}
|
||||
|
||||
// return true if a reschedule is needed ...
|
||||
ATTR_HOT bool solve();
|
||||
ATTR_HOT int solve_non_dynamic();
|
||||
|
||||
ATTR_HOT inline const int N() const { if (m_N == 0) return m_nets.count(); else return m_N; }
|
||||
|
||||
ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); }
|
||||
|
||||
private:
|
||||
bool m_resched;
|
||||
};
|
||||
|
||||
class netlist_matrix_solver_direct1_t: public netlist_matrix_solver_directb_t<1,1>
|
||||
class netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1>
|
||||
{
|
||||
public:
|
||||
|
||||
netlist_matrix_solver_direct1_t() : netlist_matrix_solver_directb_t() {}
|
||||
|
||||
virtual ~netlist_matrix_solver_direct1_t() {}
|
||||
|
||||
ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner)
|
||||
{
|
||||
netlist_matrix_solver_directb_t::setup(nets, owner);
|
||||
}
|
||||
|
||||
// return true if a reschedule is needed ...
|
||||
ATTR_HOT bool solve();
|
||||
ATTR_HOT int solve_non_dynamic();
|
||||
|
||||
//ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); }
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class netlist_matrix_solver_direct2_t: public netlist_matrix_solver_directb_t<2,2>
|
||||
class netlist_matrix_solver_direct2_t: public netlist_matrix_solver_direct_t<2,2>
|
||||
{
|
||||
public:
|
||||
|
||||
netlist_matrix_solver_direct2_t() : netlist_matrix_solver_directb_t() {}
|
||||
|
||||
virtual ~netlist_matrix_solver_direct2_t() {}
|
||||
|
||||
ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner)
|
||||
{
|
||||
netlist_matrix_solver_directb_t::setup(nets, owner);
|
||||
}
|
||||
|
||||
// return true if a reschedule is needed ...
|
||||
ATTR_HOT bool solve();
|
||||
ATTR_HOT int solve_non_dynamic();
|
||||
|
||||
//ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); }
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
@ -49,9 +49,7 @@ NETLIB_UPDATE_PARAM(switch2)
|
||||
m_R[0].set_R(R_OFF);
|
||||
m_R[1].set_R(R_ON);
|
||||
}
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
{
|
||||
m_R[0].update_dev();
|
||||
m_R[1].update_dev();
|
||||
}
|
||||
|
||||
m_R[0].update_dev();
|
||||
m_R[1].update_dev();
|
||||
}
|
||||
|
@ -29,15 +29,11 @@ NETLIB_RESET(twoterm)
|
||||
NETLIB_UPDATE(twoterm)
|
||||
{
|
||||
/* only called if connected to a rail net ==> notify the solver to recalculate */
|
||||
#if !(USE_ALTERNATE_SCHEDULING)
|
||||
netlist().solver()->schedule1();
|
||||
#else
|
||||
/* we only need to call the non-rail terminal */
|
||||
if (!m_P.net().isRailNet())
|
||||
m_P.net().solve();
|
||||
else
|
||||
m_N.net().solve();
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -81,8 +77,7 @@ NETLIB_UPDATE_PARAM(R)
|
||||
{
|
||||
//printf("updating %s to %f\n", name().cstr(), m_R.Value());
|
||||
set_R(m_R.Value());
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
update_dev();
|
||||
update_dev();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -126,11 +121,8 @@ NETLIB_UPDATE_PARAM(POT)
|
||||
m_R1.set_R(MAX(m_R.Value() * v, NETLIST_GMIN));
|
||||
m_R2.set_R(MAX(m_R.Value() * (1.0 - v), NETLIST_GMIN));
|
||||
// force a schedule all
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
{
|
||||
m_R1.update_dev();
|
||||
m_R2.update_dev();
|
||||
}
|
||||
m_R1.update_dev();
|
||||
m_R2.update_dev();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -199,10 +199,7 @@ NETLIB_UPDATE(nic7450)
|
||||
m_I3.activate();
|
||||
UINT8 t1 = INPLOGIC(m_I0) & INPLOGIC(m_I1);
|
||||
UINT8 t2 = INPLOGIC(m_I2) & INPLOGIC(m_I3);
|
||||
#if 0
|
||||
UINT8 t = (t1 | t2) ^ 1;
|
||||
OUTLOGIC(m_Q, t, t ? NLTIME_FROM_NS(22) : NLTIME_FROM_NS(15));
|
||||
#else
|
||||
|
||||
const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
|
||||
|
||||
UINT8 res = 0;
|
||||
@ -225,8 +222,6 @@ NETLIB_UPDATE(nic7450)
|
||||
}
|
||||
}
|
||||
OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -153,26 +153,22 @@ public:
|
||||
INT32 m_active;
|
||||
};
|
||||
|
||||
#if 1
|
||||
template <int _check, int _invert>
|
||||
class xx_net_signal_t: public netlist_device_t
|
||||
class net_signal_2inp_t: public netlist_device_t
|
||||
{
|
||||
public:
|
||||
xx_net_signal_t()
|
||||
net_signal_2inp_t()
|
||||
: netlist_device_t(), m_active(1)
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
const char *sIN[2] = { "A", "B" };
|
||||
|
||||
register_output("Q", m_Q);
|
||||
for (int i=0; i < 2; i++)
|
||||
{
|
||||
register_input(sIN[i], m_i[i]);
|
||||
}
|
||||
save(NAME(m_active));
|
||||
register_input("A", m_i[0]);
|
||||
register_input("B", m_i[1]);
|
||||
|
||||
save(NAME(m_active));
|
||||
}
|
||||
|
||||
ATTR_COLD void reset()
|
||||
@ -229,7 +225,6 @@ public:
|
||||
INT32 m_active;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
// The following did not improve performance
|
||||
#if 0
|
||||
@ -297,11 +292,11 @@ public:
|
||||
|
||||
|
||||
template <int _check, int _invert>
|
||||
class net_signal_t<2, _check, _invert> : public xx_net_signal_t<_check, _invert>
|
||||
class net_signal_t<2, _check, _invert> : public net_signal_2inp_t<_check, _invert>
|
||||
{
|
||||
public:
|
||||
net_signal_t()
|
||||
: xx_net_signal_t<_check, _invert>() { }
|
||||
: net_signal_2inp_t<_check, _invert>() { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -286,13 +286,6 @@ ATTR_COLD void netlist_base_t::error(const char *format, ...) const
|
||||
// net_core_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
ATTR_COLD netlist_core_device_t::netlist_core_device_t()
|
||||
: netlist_object_t(DEVICE, GENERIC), m_family_desc(NULL)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
ATTR_COLD netlist_core_device_t::netlist_core_device_t(const family_t afamily)
|
||||
: netlist_object_t(DEVICE, afamily), m_family_desc(NULL)
|
||||
{
|
||||
@ -535,13 +528,20 @@ ATTR_HOT inline void netlist_net_t::update_devs()
|
||||
|
||||
assert(this->isRailNet());
|
||||
|
||||
const UINT32 masks[4] = { 1, 5, 3, 1 };
|
||||
static const UINT32 masks[4] = { 1, 5, 3, 1 };
|
||||
const UINT32 mask = masks[ (m_last.Q << 1) | m_new.Q ];
|
||||
|
||||
m_cur = m_new;
|
||||
m_in_queue = 2; /* mark as taken ... */
|
||||
|
||||
const UINT32 mask = masks[ (m_last.Q << 1) | m_cur.Q ];
|
||||
|
||||
netlist_core_terminal_t *p = m_head;
|
||||
#if 0
|
||||
do
|
||||
{
|
||||
update_dev(p, mask);
|
||||
p = p->m_update_list_next;
|
||||
} while (p != NULL);
|
||||
#else
|
||||
switch (m_num_cons)
|
||||
{
|
||||
case 2:
|
||||
@ -558,6 +558,7 @@ ATTR_HOT inline void netlist_net_t::update_devs()
|
||||
} while (p != NULL);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
m_last = m_cur;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#define NETLIST_INTERNAL_RES (U64(1000000000))
|
||||
//#define NETLIST_INTERNAL_RES (U64(1000000000000))
|
||||
|
||||
#define USE_ALTERNATE_SCHEDULING (1)
|
||||
//#define USE_ALTERNATE_SCHEDULING (1)
|
||||
|
||||
#define NETLIST_CLOCK (NETLIST_INTERNAL_RES)
|
||||
|
||||
|
@ -165,26 +165,15 @@ public:
|
||||
|
||||
ATTR_HOT ATTR_ALIGN void push(const entry_t &e)
|
||||
{
|
||||
#if 0
|
||||
// less is more
|
||||
if (is_empty() || (e.time() <= (m_end - 1)->time()))
|
||||
{
|
||||
*m_end++ = e;
|
||||
inc_stat(m_prof_end);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
entry_t * RESTRICT i = m_end++;
|
||||
while ((i > &m_list[0]) && (e.time() > (i - 1)->time()) )
|
||||
{
|
||||
i--;
|
||||
*(i+1) = *i;
|
||||
inc_stat(m_prof_sortmove);
|
||||
}
|
||||
*i = e;
|
||||
inc_stat(m_prof_sort);
|
||||
}
|
||||
entry_t * RESTRICT i = m_end++;
|
||||
while ((i > &m_list[0]) && (e.time() > (i - 1)->time()) )
|
||||
{
|
||||
i--;
|
||||
*(i+1) = *i;
|
||||
inc_stat(m_prof_sortmove);
|
||||
}
|
||||
*i = e;
|
||||
inc_stat(m_prof_sort);
|
||||
assert(m_end - m_list < _Size);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user