summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/netlist
diff options
context:
space:
mode:
author Couriersud <couriersud@users.noreply.github.com>2014-05-25 21:45:51 +0000
committer Couriersud <couriersud@users.noreply.github.com>2014-05-25 21:45:51 +0000
commitc37566ab080a6d19828d6eae38cc86cf390d7c5d (patch)
tree9c68663eaa0e75dc6c1994f9539aa90eb4e676ed /src/emu/netlist
parent4febea390ff1c68989d19099f794a08a91b528c6 (diff)
Further simplification and clean up around the linear system solvers.
Diffstat (limited to 'src/emu/netlist')
-rw-r--r--src/emu/netlist/analog/nld_solver.c249
-rw-r--r--src/emu/netlist/analog/nld_solver.h75
-rw-r--r--src/emu/netlist/nl_base.c2
-rw-r--r--src/emu/netlist/nl_base.h8
-rw-r--r--src/emu/netlist/plists.h1
5 files changed, 175 insertions, 160 deletions
diff --git a/src/emu/netlist/analog/nld_solver.c b/src/emu/netlist/analog/nld_solver.c
index 1e4a4336ca2..ed14c3df774 100644
--- a/src/emu/netlist/analog/nld_solver.c
+++ b/src/emu/netlist/analog/nld_solver.c
@@ -25,8 +25,6 @@
ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t()
: m_owner(NULL)
, m_calculations(0)
-, m_gs_fail(0)
-, m_gs_total(0)
{
}
@@ -36,24 +34,27 @@ ATTR_COLD netlist_matrix_solver_t::~netlist_matrix_solver_t()
delete m_inps[i];
}
-ATTR_COLD void netlist_matrix_solver_t::vsetup(netlist_analog_net_t::list_t &nets, NETLIB_NAME(solver) &aowner)
+ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets, NETLIB_NAME(solver) &aowner, net_entry *list)
{
m_owner = &aowner;
NL_VERBOSE_OUT(("New solver setup\n"));
- for (netlist_analog_net_t * const * pn = nets.first(); pn != NULL; pn = nets.next(pn))
+ for (int k = 0; k < nets.count(); k++)
+ list[k].m_net = nets[k];
+
+ for (int k = 0; k < nets.count(); k++)
{
NL_VERBOSE_OUT(("setting up net\n"));
- m_nets.add(*pn);
+ netlist_analog_net_t *net = list[k].m_net;
- (*pn)->m_solver = this;
+ net->m_solver = this;
- for (int i = 0; i < (*pn)->m_core_terms.count(); i++)
+ for (int i = 0; i < net->m_core_terms.count(); i++)
{
- netlist_core_terminal_t *p = (*pn)->m_core_terms[i];
- NL_VERBOSE_OUT(("%s %s %d\n", p->name().cstr(), (*pn)->name().cstr(), (int) (*pn)->isRailNet()));
+ netlist_core_terminal_t *p = net->m_core_terms[i];
+ NL_VERBOSE_OUT(("%s %s %d\n", p->name().cstr(), net->name().cstr(), (int) net->isRailNet()));
switch (p->type())
{
case netlist_terminal_t::TERMINAL:
@@ -77,12 +78,12 @@ ATTR_COLD void netlist_matrix_solver_t::vsetup(netlist_analog_net_t::list_t &net
{
netlist_terminal_t *pterm = dynamic_cast<netlist_terminal_t *>(p);
// for gauss seidel
- pterm->m_otherterm_ptr = &pterm->m_otherterm->net().as_analog().m_new_Analog;
+ pterm->m_new_analog_ptr = &pterm->m_otherterm->net().as_analog().m_new_Analog;
if (pterm->m_otherterm->net().isRailNet())
- (*pn)->m_rails.add(pterm);
+ list[k].m_rails.add(pterm);
else
- (*pn)->m_terms.add(pterm);
+ list[k].m_terms.add(pterm);
}
NL_VERBOSE_OUT(("Added terminal\n"));
break;
@@ -114,7 +115,7 @@ ATTR_COLD void netlist_matrix_solver_t::vsetup(netlist_analog_net_t::list_t &net
break;
}
}
- NL_VERBOSE_OUT(("added net with %d populated connections (%d railnets)\n", (*pn)->m_terms.count(), (*pn)->m_rails.count()));
+ NL_VERBOSE_OUT(("added net with %d populated connections (%d railnets)\n", net->m_terms.count(), (*pn)->m_rails.count()));
}
}
@@ -268,20 +269,21 @@ ATTR_HOT double netlist_matrix_solver_t::solve()
return next_time_step;
}
-void netlist_matrix_solver_t::log_stats()
+template <int m_N, int _storage_N>
+void netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::log_stats()
{
#if 0
printf("==============================================\n");
- printf("Solver %s\n", name().cstr());
- printf(" ==> %d nets\n", m_nets.count()); //, (*(*groups[i].first())->m_core_terms.first())->name().cstr());
- printf(" has %s elements\n", is_dynamic() ? "dynamic" : "no dynamic");
- printf(" has %s elements\n", is_timestep() ? "timestep" : "no timestep");
+ printf("Solver %s\n", this->name().cstr());
+ printf(" ==> %d nets\n", this->N()); //, (*(*groups[i].first())->m_core_terms.first())->name().cstr());
+ printf(" has %s elements\n", this->is_dynamic() ? "dynamic" : "no dynamic");
+ printf(" has %s elements\n", this->is_timestep() ? "timestep" : "no timestep");
printf(" %10d invocations (%6d Hz) %10d gs fails (%6.2f%%) %4.1f average\n",
- m_calculations,
- m_calculations * 10 / (int) (netlist().time().as_double() * 10.0),
- m_gs_fail,
- 100.0 * (double) m_gs_fail / (double) m_calculations,
- (double) m_gs_total / (double) m_calculations);
+ this->m_calculations,
+ this->m_calculations * 10 / (int) (this->netlist().time().as_double() * 10.0),
+ this->m_gs_fail,
+ 100.0 * (double) this->m_gs_fail / (double) this->m_calculations,
+ (double) this->m_gs_total / (double) this->m_calculations);
#endif
}
@@ -294,7 +296,7 @@ template <int m_N, int _storage_N>
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)
+ if (m_nets[k].m_net == net)
return k;
return -1;
}
@@ -302,75 +304,70 @@ ATTR_COLD int netlist_matrix_solver_direct_t<m_N, _storage_N>::get_net_idx(netli
template <int m_N, int _storage_N>
ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_analog_net_t::list_t &nets, NETLIB_NAME(solver) &owner)
{
- netlist_matrix_solver_t::vsetup(nets, owner);
+ m_dim = nets.count();
+ netlist_matrix_solver_t::setup(nets, owner, m_nets);
- m_term_num = 0;
+ m_terms.clear();
m_rail_start = 0;
for (int k = 0; k < N(); k++)
{
- netlist_analog_net_t *net = m_nets[k];
- const netlist_terminal_t::list_t &terms = net->m_terms;
+ const netlist_terminal_t::list_t &terms = m_nets[k].m_terms;
for (int i = 0; i < terms.count(); i++)
{
- m_terms[m_term_num].net_this = k;
int ot = get_net_idx(&terms[i]->m_otherterm->net());
- m_terms[m_term_num].net_other = ot;
- m_terms[m_term_num].term = terms[i];
if (ot>=0)
{
- m_term_num++;
+ m_terms.add(terms_t(terms[i], k, ot));
SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go));
}
}
}
- m_rail_start = m_term_num;
+ m_rail_start = m_terms.count();
for (int k = 0; k < N(); k++)
{
- netlist_analog_net_t *net = m_nets[k];
- const netlist_terminal_t::list_t &terms = net->m_terms;
- const netlist_terminal_t::list_t &rails = net->m_rails;
+ const netlist_terminal_t::list_t &terms = m_nets[k].m_terms;
+ const netlist_terminal_t::list_t &rails = m_nets[k].m_rails;
for (int i = 0; i < terms.count(); i++)
{
- m_terms[m_term_num].net_this = k;
- int ot = get_net_idx(&terms[i]->m_otherterm->net());
- m_terms[m_term_num].net_other = ot;
- m_terms[m_term_num].term = terms[i];
+ int ot = get_net_idx(&terms[i]->m_otherterm->net());
if (ot<0)
{
- m_term_num++;
- SOLVER_VERBOSE_OUT(("found term with missing othernet %s\n", terms[i]->name().cstr()));
+ m_terms.add(terms_t(terms[i], k, ot));
+ netlist().warning("found term with missing othernet %s\n", terms[i]->name().cstr());
}
}
for (int i = 0; i < rails.count(); i++)
{
- m_terms[m_term_num].net_this = k;
- m_terms[m_term_num].net_other = -1; //get_net_idx(&rails[i]->m_otherterm->net());
- m_terms[m_term_num].term = rails[i];
- m_term_num++;
+ m_terms.add(terms_t(rails[i], k, -1));
SOLVER_VERBOSE_OUT(("Net %d Rail %s %f %f\n", k, rails[i]->name().cstr(), rails[i]->m_gt, rails[i]->m_go));
}
}
}
template <int m_N, int _storage_N>
-ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE(
- double (* RESTRICT A)[_storage_N],
- double (* RESTRICT RHS))
+ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE()
{
+ for (int k=0; k < _storage_N; k++)
+ for (int i=0; i < _storage_N; i++)
+ m_A[k][i] = 0.0;
+
+ for (int k=0; k < _storage_N; k++)
+ m_RHS[k] = 0.0;
#if 0
+
for (int i = 0; i < m_term_num; i++)
{
terms_t &t = m_terms[i];
- RHS[t.net_this] += t.term->m_Idr;
- A[t.net_this][t.net_this] += t.term->m_gt;
- if (t.net_other >= 0)
+ m_RHS[t.m_net_this] += t.m_term->m_Idr;
+ m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt;
+ if (t.m_net_other >= 0)
{
//m_A[t.net_other][t.net_other] += t.term->m_otherterm->m_gt;
- A[t.net_this][t.net_other] += -t.term->m_go;
+ m_A[t.m_net_this][t.m_net_other] += -t.m_term->m_go;
//m_A[t.net_other][t.net_this] += -t.term->m_otherterm->m_go;
}
else
- RHS[t.net_this] += t.term->m_go * t.term->m_otherterm->net().as_analog().Q_Analog();
+ m_RHS[t.m_net_this] += t.m_term->m_go * t.m_term->m_otherterm->net().as_analog().Q_Analog();
}
#else
for (int i = 0; i < m_rail_start; i++)
@@ -378,33 +375,31 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE(
const terms_t &t = m_terms[i];
//printf("A %d %d %s %f %f\n",t.net_this, t.net_other, t.term->name().cstr(), t.term->m_gt, t.term->m_go);
- RHS[t.net_this] += t.term->m_Idr;
- A[t.net_this][t.net_this] += t.term->m_gt;
- A[t.net_this][t.net_other] += -t.term->m_go;
+ m_RHS[t.m_net_this] += t.m_term->m_Idr;
+ m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt;
+ m_A[t.m_net_this][t.m_net_other] += -t.m_term->m_go;
}
- for (int i = m_rail_start; i < m_term_num; i++)
+ for (int i = m_rail_start; i < m_terms.count(); i++)
{
const terms_t &t = m_terms[i];
- RHS[t.net_this] += t.term->m_Idr;
- A[t.net_this][t.net_this] += t.term->m_gt;
- RHS[t.net_this] += t.term->m_go * t.term->m_otherterm->net().as_analog().Q_Analog();
+ m_RHS[t.m_net_this] += t.m_term->m_Idr;
+ m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt;
+ m_RHS[t.m_net_this] += t.m_term->m_go * t.m_term->m_otherterm->net().as_analog().Q_Analog();
}
#endif
}
template <int m_N, int _storage_N>
ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
- double (* RESTRICT A)[_storage_N],
- double (* RESTRICT RHS),
double (* RESTRICT x))
{
#if 0
for (int i = 0; i < N(); i++)
{
for (int k = 0; k < N(); k++)
- printf("%f ", A[i][k]);
- printf("| %f = %f \n", x[i], RHS[i]);
+ printf("%f ", m_A[i][k]);
+ printf("| %f = %f \n", x[i], m_RHS[i]);
}
printf("\n");
#endif
@@ -419,7 +414,7 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
int maxrow = i;
for (int j = i + 1; j < kN; j++)
{
- if (fabs(A[j][i]) > fabs(A[maxrow][i]))
+ if (fabs(m_A[j][i]) > fabs(m_A[maxrow][i]))
maxrow = j;
}
@@ -427,14 +422,14 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
{
/* Swap the maxrow and ith row */
for (int k = i; k < kN; k++) {
- std::swap(A[i][k], A[maxrow][k]);
+ std::swap(m_A[i][k], m_A[maxrow][k]);
}
- std::swap(RHS[i], RHS[maxrow]);
+ std::swap(m_RHS[i], m_RHS[maxrow]);
}
}
/* Singular matrix? */
- double f = A[i][i];
+ double f = m_A[i][i];
//if (fabs(f) < 1e-20) printf("Singular!");
f = 1.0 / f;
@@ -443,12 +438,12 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
for (int j = i + 1; j < kN; j++)
{
//__builtin_prefetch(&A[j+1][i], 1);
- const double f1 = A[j][i] * f;
+ const double f1 = m_A[j][i] * f;
if (f1 != 0.0)
{
for (int k = i; k < kN; k++)
- A[j][k] -= A[i][k] * f1;
- RHS[j] -= RHS[i] * f1;
+ m_A[j][k] -= m_A[i][k] * f1;
+ m_RHS[j] -= m_RHS[i] * f1;
}
}
}
@@ -458,16 +453,16 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
//__builtin_prefetch(&A[j-1][j], 0);
double tmp = 0;
for (int k = j + 1; k < kN; k++)
- tmp += A[j][k] * x[k];
- x[j] = (RHS[j] - tmp) / A[j][j];
+ tmp += m_A[j][k] * x[k];
+ x[j] = (m_RHS[j] - tmp) / m_A[j][j];
}
#if 0
printf("Solution:\n");
for (int i = 0; i < N(); i++)
{
for (int k = 0; k < N(); k++)
- printf("%f ", A[i][k]);
- printf("| %f = %f \n", x[i], RHS[i]);
+ printf("%f ", m_A[i][k]);
+ printf("| %f = %f \n", x[i], m_RHS[i]);
}
printf("\n");
#endif
@@ -476,15 +471,14 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
template <int m_N, int _storage_N>
ATTR_HOT double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta(
- const double (* RESTRICT RHS),
const 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_last_RHS[i]);
+ double e = (V[i] - this->m_nets[i].m_net->m_cur_Analog);
+ double e2 = (m_RHS[i] - this->m_last_RHS[i]);
cerr += e * e;
cerr2 += e2 * e2;
}
@@ -493,34 +487,33 @@ ATTR_HOT double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta(
template <int m_N, int _storage_N>
ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::store(
- const double (* RESTRICT RHS),
- const double (* RESTRICT V))
+ const double (* RESTRICT V), bool store_RHS)
{
for (int i = 0; i < this->N(); i++)
{
- this->m_nets[i]->m_cur_Analog = this->m_nets[i]->m_new_Analog = V[i];
+ this->m_nets[i].m_net->m_cur_Analog = this->m_nets[i].m_net->m_new_Analog = V[i];
}
- if (RHS != NULL)
+ if (store_RHS)
{
for (int i = 0; i < this->N(); i++)
{
- this->m_last_RHS[i] = RHS[i];
+ this->m_last_RHS[i] = m_RHS[i];
}
}
}
template <int m_N, int _storage_N>
-ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(double (* RESTRICT A)[_storage_N], double (* RESTRICT RHS))
+ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic()
{
double new_v[_storage_N] = { 0.0 };
- this->gauss_LE(A, RHS, new_v);
+ this->gauss_LE(new_v);
if (this->is_dynamic())
{
- double err = delta(RHS, new_v);
+ double err = delta(new_v);
- store(RHS, new_v);
+ store(new_v, true);
if (err > this->m_params.m_accuracy * this->m_params.m_accuracy)
{
@@ -528,19 +521,16 @@ ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(
}
return 1;
}
- store(NULL, new_v); // ==> No need to store RHS
+ store(new_v, false); // ==> No need to store RHS
return 1;
}
template <int m_N, int _storage_N>
ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic()
{
- double A[_storage_N][_storage_N] = { { 0.0 } };
- double RHS[_storage_N] = { 0.0 };
-
- this->build_LE(A, RHS);
+ this->build_LE();
- return this->solve_non_dynamic(A, RHS);
+ return this->solve_non_dynamic();
}
@@ -551,10 +541,8 @@ ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic
ATTR_HOT int netlist_matrix_solver_direct1_t::vsolve_non_dynamic()
{
- netlist_analog_net_t *net = m_nets[0];
- double m_A[1][1] = { {0.0} };
- double m_RHS[1] = { 0.0 };
- build_LE(m_A, m_RHS);
+ netlist_analog_net_t *net = m_nets[0].m_net;
+ this->build_LE();
//NL_VERBOSE_OUT(("%f %f\n", new_val, m_RHS[0] / m_A[0][0]);
double new_val = m_RHS[0] / m_A[0][0];
@@ -581,30 +569,28 @@ ATTR_HOT int netlist_matrix_solver_direct1_t::vsolve_non_dynamic()
ATTR_HOT int netlist_matrix_solver_direct2_t::vsolve_non_dynamic()
{
- double A[2][2] = { { 0.0 } };
- double RHS[2] = { 0.0 };
- build_LE(A, RHS);
+ build_LE();
- 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 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];
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;
+ new_val[1] = a / (a * d - b * c) * (m_RHS[1] - c / a * m_RHS[0]);
+ new_val[0] = (m_RHS[0] - b * new_val[1]) / a;
if (is_dynamic())
{
- double err = delta(RHS, new_val);
- store(RHS, new_val);
+ double err = delta(new_val);
+ store(new_val, true);
if (err > m_params.m_accuracy * m_params.m_accuracy)
return 2;
else
return 1;
}
- store(NULL, new_val);
+ store(new_val, false);
return 1;
}
@@ -621,8 +607,6 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
*/
#if 0
- double A[_storage_N][_storage_N] = { { 0.0 } };
- double RHS[_storage_N] = { 0.0 };
double new_v[_storage_N] = { 0.0 };
const int iN = this->N();
@@ -630,11 +614,11 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
int resched_cnt = 0;
- this->build_LE(A, RHS);
+ this->build_LE();
for (int k = 0; k < iN; k++)
{
- new_v[k] = this->m_nets[k]->m_cur_Analog;
+ new_v[k] = this->m_nets[k].m_net->m_cur_Analog;
}
do {
resched = false;
@@ -647,9 +631,9 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
// loop auto-vectorized
for (int i = 0; i < iN; i++)
- Idrive -= A[pk][i] * new_v[i];
+ Idrive -= this->m_A[pk][i] * new_v[i];
- const double new_val = (RHS[pk] + Idrive + A[pk][pk] * new_v[pk]) / A[pk][pk];
+ const double new_val = (this->m_RHS[pk] + Idrive + this->m_A[pk][pk] * new_v[pk]) / this->m_A[pk][pk];
const double e = (new_val - new_v[k]);
cerr += e * e;
@@ -668,14 +652,14 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
{
//this->netlist().warning("Falling back to direct solver .. Consider increasing RESCHED_LOOPS");
this->m_gs_fail++;
- int tmp = netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(A, RHS);
+ int tmp = netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic();
this->m_calculations++;
return tmp;
}
else {
this->m_calculations++;
- this->store(NULL, new_v);
+ this->store(new_v, false);
return resched_cnt;
}
@@ -697,7 +681,7 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
for (int k = 0; k < iN; k++)
{
- this->m_nets[k]->m_new_Analog = this->m_nets[k]->m_cur_Analog;
+ this->m_nets[k].m_net->m_new_Analog = this->m_nets[k].m_net->m_cur_Analog;
}
for (int k = 0; k < iN; k++)
@@ -706,9 +690,9 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
double gabs_t = 0.0;
double RHS_t = 0.0;
- const netlist_analog_net_t &net = *this->m_nets[k];
- const netlist_terminal_t::list_t &terms = net.m_terms;
- const netlist_terminal_t::list_t &rails = net.m_rails;
+ //const netlist_analog_net_t &net = *this->m_nets[k];
+ const netlist_terminal_t::list_t &terms = this->m_nets[k].m_terms;
+ const netlist_terminal_t::list_t &rails = this->m_nets[k].m_rails;
const int term_count = terms.count();
const int rail_count = rails.count();
@@ -717,8 +701,7 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
gtot_t += rails[i]->m_gt;
gabs_t += fabs(rails[i]->m_go);
RHS_t += rails[i]->m_Idr;
- //RHS_t += rails[i]->m_go * rails[i]->m_otherterm->net().as_analog().Q_Analog();
- RHS_t += rails[i]->m_go * *rails[i]->m_otherterm_ptr;
+ RHS_t += rails[i]->m_go * rails[i]->m_otherterm->net().as_analog().Q_Analog();
}
for (int i = 0; i < term_count; i++)
@@ -731,14 +714,14 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
gabs_t *= 1.0;
if (gabs_t > gtot_t)
{
- //this->netlist().warning("Falling back to direct solver .. Consider increasing RESCHED_LOOPS");
w[k] = 1.0 / (gtot_t + gabs_t);
one_m_w[k] = 1.0 - 1.0 * gtot_t / (gtot_t + gabs_t);
}
else
{
- w[k] = 1.0/ gtot_t;
- one_m_w[k] = 1.0 - 1.0;
+ const double ws = 1.0;
+ w[k] = ws / gtot_t;
+ one_m_w[k] = 1.0 - ws;
}
RHS[k] = RHS_t;
@@ -750,15 +733,15 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
for (int k = 0; k < iN; k++)
{
- netlist_analog_net_t &net = *this->m_nets[k];
- const netlist_terminal_t::list_t &terms = net.m_terms;
+ netlist_analog_net_t & RESTRICT net = *this->m_nets[k].m_net;
+ const netlist_terminal_t::list_t &terms = this->m_nets[k].m_terms;
const int term_count = terms.count();
double Idrive = 0;
- for (int i = 0; i < term_count; i++)
- Idrive += terms[i]->m_go * *(terms[i]->m_otherterm_ptr);
+ for (int i = 0; i < term_count; i++)
+ Idrive += terms[i]->m_go * *(terms[i]->m_new_analog_ptr);
- //double new_val = (net->m_cur_Analog * gabs[k] + iIdr) / (gtot[k]);
+ //double new_val = (net->m_cur_Analog * gabs[k] + iIdr) / (gtot[k]);
const double new_val = net.m_new_Analog * one_m_w[k] + (Idrive + RHS[k]) * w[k];
const double e = (new_val - net.m_new_Analog);
@@ -786,7 +769,7 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
this->m_calculations++;
for (int k = 0; k < this->N(); k++)
- this->m_nets[k]->m_cur_Analog = this->m_nets[k]->m_new_Analog;
+ this->m_nets[k].m_net->m_cur_Analog = this->m_nets[k].m_net->m_new_Analog;
return resched_cnt;
}
diff --git a/src/emu/netlist/analog/nld_solver.h b/src/emu/netlist/analog/nld_solver.h
index c4ee0be8571..f308d790897 100644
--- a/src/emu/netlist/analog/nld_solver.h
+++ b/src/emu/netlist/analog/nld_solver.h
@@ -46,7 +46,8 @@ public:
ATTR_COLD netlist_matrix_solver_t();
ATTR_COLD virtual ~netlist_matrix_solver_t();
- ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets, NETLIB_NAME(solver) &owner);
+ ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets,
+ NETLIB_NAME(solver) &owner) = 0;
ATTR_HOT double solve();
@@ -64,12 +65,25 @@ public:
netlist_solver_parameters_t m_params;
- ATTR_COLD void log_stats();
+ ATTR_COLD virtual void log_stats() {};
protected:
- netlist_analog_net_t::list_t m_nets;
+ class net_entry
+ {
+ NETLIST_PREVENT_COPYING(net_entry)
+
+ public:
+ net_entry(netlist_analog_net_t *net) : m_net(net) {}
+ net_entry() : m_net(NULL) {}
+
+ netlist_analog_net_t * RESTRICT m_net;
+ netlist_terminal_t::list_t m_terms;
+ netlist_terminal_t::list_t m_rails;
+ };
+ ATTR_COLD virtual void setup(netlist_analog_net_t::list_t &nets,
+ NETLIB_NAME(solver) &owner, net_entry *list);
NETLIB_NAME(solver) *m_owner;
@@ -77,8 +91,6 @@ protected:
ATTR_HOT virtual int vsolve_non_dynamic() = 0;
int m_calculations;
- int m_gs_fail;
- int m_gs_total;
private:
@@ -110,7 +122,7 @@ public:
netlist_matrix_solver_direct_t()
: netlist_matrix_solver_t()
- , m_term_num(0)
+ , m_dim(0)
, m_rail_start(0)
{}
@@ -119,34 +131,43 @@ public:
ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets, NETLIB_NAME(solver) &owner);
ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); }
- ATTR_HOT inline const int N() const { if (m_N == 0) return m_nets.count(); else return m_N; }
+ ATTR_HOT inline const int N() const { if (m_N == 0) return m_dim; else return m_N; }
protected:
ATTR_HOT virtual int vsolve_non_dynamic();
- ATTR_HOT int solve_non_dynamic(double (* RESTRICT A)[_storage_N], double (* RESTRICT 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 int solve_non_dynamic();
+ ATTR_HOT inline void build_LE();
+ ATTR_HOT inline void gauss_LE(double (* RESTRICT x));
ATTR_HOT inline double delta(
- const double (* RESTRICT RHS),
const double (* RESTRICT V));
- ATTR_HOT inline void store(const double (* RESTRICT RHS), const double (* RESTRICT V));
+ ATTR_HOT inline void store(const double (* RESTRICT V), bool store_RHS);
- double m_last_RHS[_storage_N]; // right hand side - contains currents
+ net_entry m_nets[_storage_N];
-private:
+ double m_A[_storage_N][_storage_N];
+ double m_RHS[_storage_N];
+ double m_last_RHS[_storage_N]; // right hand side - contains currents
+private:
ATTR_COLD int get_net_idx(netlist_net_t *net);
struct terms_t{
- int net_this;
- int net_other;
- netlist_terminal_t *term;
+
+ terms_t(netlist_terminal_t *term, int net_this, int net_other)
+ : m_term(term), m_net_this(net_this), m_net_other(net_other)
+ {}
+ terms_t()
+ : m_term(NULL), m_net_this(-1), m_net_other(-1)
+ {}
+
+ netlist_terminal_t *m_term;
+ int m_net_this;
+ int m_net_other;
};
- int m_term_num;
+
+ int m_dim;
int m_rail_start;
- terms_t m_terms[_storage_N * _storage_N];
+ plinearlist_t<terms_t> m_terms;
};
template <int m_N, int _storage_N>
@@ -154,13 +175,23 @@ class netlist_matrix_solver_gauss_seidel_t: public netlist_matrix_solver_direct_
{
public:
- netlist_matrix_solver_gauss_seidel_t() : netlist_matrix_solver_direct_t<m_N, _storage_N>() {}
+ netlist_matrix_solver_gauss_seidel_t()
+ : netlist_matrix_solver_direct_t<m_N, _storage_N>()
+ , m_gs_fail(0)
+ , m_gs_total(0)
+ {}
virtual ~netlist_matrix_solver_gauss_seidel_t() {}
+ ATTR_COLD virtual void log_stats();
+
protected:
ATTR_HOT int vsolve_non_dynamic();
+private:
+ int m_gs_fail;
+ int m_gs_total;
+
};
class netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1>
diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c
index 215c4717d61..2a6e545838a 100644
--- a/src/emu/netlist/nl_base.c
+++ b/src/emu/netlist/nl_base.c
@@ -771,7 +771,7 @@ ATTR_COLD netlist_terminal_t::netlist_terminal_t()
, m_go(NETLIST_GMIN_DEFAULT)
, m_gt(NETLIST_GMIN_DEFAULT)
, m_otherterm(NULL)
-, m_otherterm_ptr(NULL)
+, m_new_analog_ptr(NULL)
{
}
diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h
index cbbc7534681..0d66d5a6985 100644
--- a/src/emu/netlist/nl_base.h
+++ b/src/emu/netlist/nl_base.h
@@ -429,7 +429,7 @@ class netlist_terminal_t : public netlist_core_terminal_t
NETLIST_PREVENT_COPYING(netlist_terminal_t)
public:
- typedef plinearlist_t<netlist_terminal_t *> list_t;
+ typedef plinearlist_t<netlist_terminal_t * RESTRICT> list_t;
ATTR_COLD netlist_terminal_t();
@@ -462,7 +462,7 @@ public:
// used by gauss-seidel-solver
- double * RESTRICT m_otherterm_ptr;
+ double * RESTRICT m_new_analog_ptr;
protected:
ATTR_COLD virtual void save_register();
@@ -732,8 +732,8 @@ public:
//FIXME: needed by current solver code
netlist_matrix_solver_t *m_solver;
- netlist_terminal_t::list_t m_terms;
- netlist_terminal_t::list_t m_rails;
+// netlist_terminal_t::list_t m_terms;
+// netlist_terminal_t::list_t m_rails;
};
// ----------------------------------------------------------------------------------------
diff --git a/src/emu/netlist/plists.h b/src/emu/netlist/plists.h
index 3981c310b19..b690f0dfa17 100644
--- a/src/emu/netlist/plists.h
+++ b/src/emu/netlist/plists.h
@@ -61,6 +61,7 @@ public:
{
if (m_list != NULL)
delete[] m_list;
+ m_list = NULL;
}
ATTR_HOT inline void add(const _ListClass &elem)