mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
Netlist changes:
- Reworked the analog storage model to better support the compiler. This will most likely only pay off on larger matrices than currently used. Investment for future platforms with larger vectors - Added parameter "GS_THRESHOLD" to select the minimum matrix size for Gauss-Seidel solver - pstate: pointer will be resolved late, i.e. after all initialization is finished. State is registered during start, but some pointers are only set during post_load in the solver.
This commit is contained in:
parent
ac79d15878
commit
f4f871ada4
@ -439,7 +439,10 @@ ATTR_COLD void netlist_mame_device_t::save_state()
|
||||
switch (s->m_dt)
|
||||
{
|
||||
case DT_DOUBLE:
|
||||
save_pointer((double *) s->m_ptr, s->m_name, s->m_count);
|
||||
{
|
||||
double *td = s->resolved<double>();
|
||||
if (td != NULL) save_pointer(td, s->m_name, s->m_count);
|
||||
}
|
||||
break;
|
||||
case DT_INT64:
|
||||
save_pointer((INT64 *) s->m_ptr, s->m_name, s->m_count);
|
||||
|
@ -18,6 +18,12 @@
|
||||
#define SOLVER_VERBOSE_OUT(x) do {} while (0)
|
||||
//#define SOLVER_VERBOSE_OUT(x) printf x
|
||||
|
||||
/* Commented out for now. Relatively low number of terminals / net makes
|
||||
* the vectorizations this enables pretty expensive
|
||||
*/
|
||||
|
||||
//#pragma GCC optimize "-ffast-math"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_matrix_solver
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -122,9 +128,8 @@ ATTR_HOT double netlist_matrix_solver_direct_t<m_N, _storage_N>::compute_next_ti
|
||||
if (m_params.m_dynamic)
|
||||
{
|
||||
/*
|
||||
* FIXME: this is a reduced LTE focusing on the nets which drive other nets
|
||||
* The academically correct version using all nets is the one commented out
|
||||
* This causes really bad performance due to rounding errors.
|
||||
* FIXME: We should extend the logic to use either all nets or
|
||||
* only output nets.
|
||||
*/
|
||||
#if 0
|
||||
for (netlist_analog_output_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p))
|
||||
@ -140,7 +145,7 @@ ATTR_HOT double netlist_matrix_solver_direct_t<m_N, _storage_N>::compute_next_ti
|
||||
if (fabs(DD_n) < 2.0 * m_params.m_accuracy)
|
||||
DD_n = 0.0;
|
||||
else
|
||||
DD_n = DD_n / hn;
|
||||
DD_n = copysign(fabs(DD_n) - 2.0 * m_params.m_accuracy, DD_n) / hn;
|
||||
|
||||
double h_n_m_1 = n->m_h_n_m_1;
|
||||
// limit last timestep in equation.
|
||||
@ -361,47 +366,12 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_a
|
||||
|
||||
netlist_matrix_solver_t::setup(nets);
|
||||
|
||||
#if 0
|
||||
for (int k = 0; k < N(); k++)
|
||||
{
|
||||
const netlist_terminal_t::list_t &terms = m_nets[k].m_terms;
|
||||
for (int i = 0; i < terms.count(); i++)
|
||||
{
|
||||
int ot = get_net_idx(&terms[i]->m_otherterm->net());
|
||||
if (ot>=0)
|
||||
{
|
||||
m_terms[k].add(terms_t(terms[i], ot));
|
||||
SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Should this be allowed ? */
|
||||
for (int k = 0; k < N(); k++)
|
||||
{
|
||||
const netlist_terminal_t::list_t &terms = m_nets[k].m_terms;
|
||||
for (int i = 0; i < terms.count(); i++)
|
||||
{
|
||||
int ot = get_net_idx(&terms[i]->m_otherterm->net());
|
||||
if (ot<0)
|
||||
{
|
||||
m_rails[k].add(terms_t(terms[i], ot));
|
||||
netlist().warning("found term with missing othernet %s\n", terms[i]->name().cstr());
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < N(); k++)
|
||||
{
|
||||
m_terms[k].set_pointers();
|
||||
m_rails[k].set_pointers();
|
||||
}
|
||||
|
||||
|
||||
for (int k = 0; k < N(); k++)
|
||||
{
|
||||
const netlist_terminal_t::list_t &rails = m_nets[k].m_rails;
|
||||
for (int i = 0; i < rails.count(); i++)
|
||||
{
|
||||
m_rails[k].add(terms_t(rails[i], -1));
|
||||
SOLVER_VERBOSE_OUT(("Net %d Rail %s %f %f\n", k, rails[i]->name().cstr(), rails[i]->m_gt, rails[i]->m_go));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
@ -415,26 +385,36 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE()
|
||||
{
|
||||
double rhsk = 0.0;
|
||||
double akk = 0.0;
|
||||
const int terms_count = m_terms[k].count();
|
||||
const netlist_terminal_t * const *terms = m_terms[k].terms();
|
||||
const int *net_other = m_terms[k].net_other();
|
||||
|
||||
for (int i = 0; i < terms_count; 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);
|
||||
|
||||
rhsk = rhsk + terms[i]->m_Idr;
|
||||
akk = akk + terms[i]->m_gt;
|
||||
m_A[k][net_other[i]] += -terms[i]->m_go;
|
||||
}
|
||||
|
||||
const int rails_count = m_rails[k].count();
|
||||
const netlist_terminal_t * const *rails = m_rails[k].terms();
|
||||
|
||||
for (int i = 0; i < rails_count; i++)
|
||||
{
|
||||
rhsk = rhsk + rails[i]->m_Idr + rails[i]->m_go * rails[i]->m_otherterm->net().as_analog().Q_Analog();
|
||||
akk = akk + rails[i]->m_gt;
|
||||
const int terms_count = m_terms[k].count();
|
||||
//const netlist_terminal_t * const *terms = m_terms[k].terms();
|
||||
const int *net_other = m_terms[k].net_other();
|
||||
const double *gt = m_terms[k].gt();
|
||||
const double *go = m_terms[k].go();
|
||||
const double *Idr = m_terms[k].Idr();
|
||||
|
||||
for (int i = 0; i < terms_count; 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);
|
||||
|
||||
rhsk = rhsk + Idr[i];
|
||||
akk = akk + gt[i];
|
||||
m_A[k][net_other[i]] += -go[i];
|
||||
}
|
||||
}
|
||||
{
|
||||
const int rails_count = m_rails[k].count();
|
||||
const netlist_terminal_t * const *rails = m_rails[k].terms();
|
||||
const double *gt = m_rails[k].gt();
|
||||
const double *go = m_rails[k].go();
|
||||
const double *Idr = m_rails[k].Idr();
|
||||
|
||||
for (int i = 0; i < rails_count; i++)
|
||||
{
|
||||
rhsk = rhsk + Idr[i];
|
||||
akk = akk + gt[i];
|
||||
rhsk = rhsk + go[i] * rails[i]->m_otherterm->net().as_analog().Q_Analog();
|
||||
}
|
||||
}
|
||||
m_RHS[k] = rhsk;
|
||||
m_A[k][k] += akk;
|
||||
@ -479,20 +459,17 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
|
||||
}
|
||||
}
|
||||
|
||||
/* Singular matrix? */
|
||||
double f = m_A[i][i];
|
||||
//if (fabs(f) < 1e-20) printf("Singular!");
|
||||
f = 1.0 / f;
|
||||
/* FIXME: Singular matrix? */
|
||||
const double f = 1.0 / m_A[i][i];
|
||||
|
||||
/* Eliminate column i from row j */
|
||||
|
||||
for (int j = i + 1; j < kN; j++)
|
||||
{
|
||||
//__builtin_prefetch(&A[j+1][i], 1);
|
||||
const double f1 = m_A[j][i] * f;
|
||||
if (f1 != 0.0)
|
||||
{
|
||||
for (int k = i; k < kN; k++)
|
||||
for (int k = i + 1; k < kN; k++)
|
||||
m_A[j][k] -= m_A[i][k] * f1;
|
||||
m_RHS[j] -= m_RHS[i] * f1;
|
||||
}
|
||||
@ -501,7 +478,7 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
|
||||
/* back substitution */
|
||||
for (int j = kN - 1; j >= 0; j--)
|
||||
{
|
||||
//__builtin_prefetch(&A[j-1][j], 0);
|
||||
//__builtin_prefetch(&m_A[j-1][j], 0);
|
||||
double tmp = 0;
|
||||
for (int k = j + 1; k < kN; k++)
|
||||
tmp += m_A[j][k] * x[k];
|
||||
@ -650,6 +627,24 @@ ATTR_HOT int netlist_matrix_solver_direct2_t::vsolve_non_dynamic()
|
||||
// netlist_matrix_solver - Gauss - Seidel
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<int _N>
|
||||
static inline const double sum(const double *v)
|
||||
{
|
||||
double tmp = 0.0;
|
||||
for (int i=0; i < _N; i++)
|
||||
tmp += v[i];
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<int _N>
|
||||
static inline const double sumabs(const double *v)
|
||||
{
|
||||
double tmp = 0.0;
|
||||
for (int i=0; i < _N; i++)
|
||||
tmp += fabs(v[i]);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <int m_N, int _storage_N>
|
||||
ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_dynamic()
|
||||
{
|
||||
@ -659,7 +654,7 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
|
||||
*/
|
||||
|
||||
#if 0
|
||||
double new_v[_storage_N] = { 0.0 };
|
||||
ATTR_ALIGN double new_v[_storage_N] = { 0.0 };
|
||||
const int iN = this->N();
|
||||
|
||||
bool resched = false;
|
||||
@ -680,7 +675,7 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
|
||||
{
|
||||
double Idrive = 0;
|
||||
|
||||
// loop auto-vectorized
|
||||
// Reduction loops need -ffast-math
|
||||
for (int i = 0; i < iN; i++)
|
||||
Idrive -= this->m_A[k][i] * new_v[i];
|
||||
|
||||
@ -726,10 +721,10 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
|
||||
//const double w = 1.0; //2.0 / (1.0 + sin(3.14159 / (m_nets.count()+1)));
|
||||
//const double w1 = 1.0 - w;
|
||||
|
||||
double w[_storage_N];
|
||||
double one_m_w[_storage_N];
|
||||
double RHS[_storage_N];
|
||||
double new_V[_storage_N];
|
||||
ATTR_ALIGN double w[_storage_N];
|
||||
ATTR_ALIGN double one_m_w[_storage_N];
|
||||
ATTR_ALIGN double RHS[_storage_N];
|
||||
ATTR_ALIGN double new_V[_storage_N];
|
||||
|
||||
for (int k = 0; k < iN; k++)
|
||||
{
|
||||
@ -746,27 +741,30 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
|
||||
const netlist_terminal_t * const * rails = this->m_rails[k].terms();
|
||||
//const int * othernet = this->m_rails[k].m_othernet;
|
||||
const int rail_count = this->m_rails[k].count();
|
||||
const double *gt = this->m_rails[k].gt();
|
||||
const double *go = this->m_rails[k].go();
|
||||
const double *Idr = this->m_rails[k].Idr();
|
||||
|
||||
for (int i = 0; i < rail_count; i++)
|
||||
{
|
||||
const netlist_terminal_t *rail = rails[i];
|
||||
gtot_t += rail->m_gt;
|
||||
gabs_t += fabs(rail->m_go);
|
||||
RHS_t += rail->m_Idr;
|
||||
// this may point to a rail net ...
|
||||
RHS_t += rail->m_go * rail->m_otherterm->net().as_analog().Q_Analog();
|
||||
}
|
||||
for (int i = 0; i < rail_count; i++)
|
||||
{
|
||||
RHS_t += go[i] * rails[i]->m_otherterm->net().as_analog().Q_Analog();
|
||||
gtot_t += gt[i];
|
||||
gabs_t += fabs(go[i]);
|
||||
RHS_t += Idr[i];
|
||||
// this may point to a rail net ...
|
||||
}
|
||||
}
|
||||
{
|
||||
const netlist_terminal_t * const * terms = this->m_terms[k].terms();
|
||||
const int term_count = this->m_terms[k].count();
|
||||
const double *gt = this->m_terms[k].gt();
|
||||
const double *go = this->m_terms[k].go();
|
||||
const double *Idr = this->m_terms[k].Idr();
|
||||
|
||||
for (int i = 0; i < term_count; i++)
|
||||
{
|
||||
const netlist_terminal_t *term = terms[i];
|
||||
gtot_t += term->m_gt;
|
||||
gabs_t += fabs(term->m_go);
|
||||
RHS_t += term->m_Idr;
|
||||
gtot_t += gt[i];
|
||||
gabs_t += fabs(go[i]);
|
||||
RHS_t += Idr[i];
|
||||
}
|
||||
}
|
||||
gabs_t *= 1.0;
|
||||
@ -791,15 +789,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 & RESTRICT net = *this->m_nets[k];
|
||||
const netlist_terminal_t * const * terms = this->m_terms[k].terms();
|
||||
const int * net_other = this->m_terms[k].net_other();
|
||||
const int term_count = this->m_terms[k].count();
|
||||
const double *go = this->m_terms[k].go();
|
||||
// -msse2 -msse3 -msse4.1 -msse4.2 -mfpmath=sse -ftree-vectorizer-verbose=3 -fprefetch-loop-arrays -ffast-math
|
||||
|
||||
double Idrive = 0;
|
||||
|
||||
for (int i = 0; i < term_count; i++)
|
||||
Idrive += terms[i]->m_go * new_V[net_other[i]];
|
||||
Idrive = Idrive + go[i] * new_V[net_other[i]];
|
||||
|
||||
//double new_val = (net->m_cur_Analog * gabs[k] + iIdr) / (gtot[k]);
|
||||
const double new_val = new_V[k] * one_m_w[k] + (Idrive + RHS[k]) * w[k];
|
||||
@ -856,14 +854,15 @@ NETLIB_START(solver)
|
||||
|
||||
register_param("FREQ", m_freq, 48000.0);
|
||||
|
||||
register_param("ACCURACY", m_accuracy, 1e-4);
|
||||
register_param("GS_LOOPS", m_gs_loops, 5); // Gauss-Seidel loops
|
||||
register_param("ACCURACY", m_accuracy, 1e-7);
|
||||
register_param("GS_LOOPS", m_gs_loops, 9); // Gauss-Seidel loops
|
||||
register_param("GS_THRESHOLD", m_gs_threshold, 5); // below this value, gaussian elimination is used
|
||||
register_param("NR_LOOPS", m_nr_loops, 25); // Newton-Raphson loops
|
||||
register_param("PARALLEL", m_parallel, 0);
|
||||
register_param("GMIN", m_gmin, NETLIST_GMIN_DEFAULT);
|
||||
register_param("DYNAMIC_TS", m_dynamic, 0);
|
||||
register_param("LTE", m_lte, 1e-2); // 100mV diff/timestep
|
||||
register_param("MIN_TIMESTEP", m_min_timestep, 2e-9); // double timestep resolution
|
||||
register_param("LTE", m_lte, 5e-5); // diff/timestep
|
||||
register_param("MIN_TIMESTEP", m_min_timestep, 1e-6); // double timestep resolution
|
||||
|
||||
// internal staff
|
||||
|
||||
@ -927,12 +926,11 @@ NETLIB_UPDATE(solver)
|
||||
this_resched[i] = m_mat_solvers[i]->solve();
|
||||
}
|
||||
#else
|
||||
// FIXME: parameter
|
||||
for (int i = 0; i < t_cnt; i++)
|
||||
{
|
||||
if (m_mat_solvers[i]->is_timestep())
|
||||
{
|
||||
// Ignore return value
|
||||
// Ignore return value
|
||||
ATTR_UNUSED const double ts = m_mat_solvers[i]->solve();
|
||||
}
|
||||
}
|
||||
@ -965,8 +963,7 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start()
|
||||
{
|
||||
netlist_analog_net_t::list_t groups[100];
|
||||
int cur_group = -1;
|
||||
// FIXME: Turn into parameters ...
|
||||
const int gs_threshold = 5;
|
||||
const int gs_threshold = m_gs_threshold.Value();
|
||||
const bool use_specific = true;
|
||||
|
||||
m_params.m_accuracy = m_accuracy.Value();
|
||||
|
@ -79,22 +79,42 @@ protected:
|
||||
{
|
||||
m_term.clear();
|
||||
m_net_other.clear();
|
||||
m_gt.clear();
|
||||
}
|
||||
|
||||
void add(netlist_terminal_t *term, int net_other)
|
||||
{
|
||||
m_term.add(term);
|
||||
m_net_other.add(net_other);
|
||||
m_gt.add(0.0);
|
||||
m_go.add(0.0);
|
||||
m_Idr.add(0.0);
|
||||
}
|
||||
|
||||
inline int count() { return m_term.count(); }
|
||||
|
||||
inline netlist_terminal_t **terms() { return m_term; }
|
||||
inline int *net_other() { return m_net_other; }
|
||||
inline double *gt() { return m_gt; }
|
||||
inline double *go() { return m_go; }
|
||||
inline double *Idr() { return m_Idr; }
|
||||
|
||||
void set_pointers()
|
||||
{
|
||||
for (int i = 0; i < count(); i++)
|
||||
{
|
||||
m_term[i]->m_gt1 = &m_gt[i];
|
||||
m_term[i]->m_go1 = &m_go[i];
|
||||
m_term[i]->m_Idr1 = &m_Idr[i];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
plinearlist_t<netlist_terminal_t *> m_term;
|
||||
plinearlist_t<int> m_net_other;
|
||||
plinearlist_t<double> m_gt;
|
||||
plinearlist_t<double> m_go;
|
||||
plinearlist_t<double> m_Idr;
|
||||
|
||||
};
|
||||
|
||||
@ -230,24 +250,23 @@ protected:
|
||||
ATTR_HOT void reset();
|
||||
ATTR_HOT void update_param();
|
||||
|
||||
//typedef netlist_core_device_t::list_t dev_list_t;
|
||||
netlist_ttl_input_t m_fb_step;
|
||||
netlist_ttl_output_t m_Q_step;
|
||||
|
||||
netlist_ttl_input_t m_fb_step;
|
||||
netlist_ttl_output_t m_Q_step;
|
||||
netlist_param_double_t m_freq;
|
||||
netlist_param_double_t m_sync_delay;
|
||||
netlist_param_double_t m_accuracy;
|
||||
netlist_param_double_t m_gmin;
|
||||
netlist_param_double_t m_lte;
|
||||
netlist_param_logic_t m_dynamic;
|
||||
netlist_param_double_t m_min_timestep;
|
||||
|
||||
netlist_param_double_t m_freq;
|
||||
netlist_param_double_t m_sync_delay;
|
||||
netlist_param_double_t m_accuracy;
|
||||
netlist_param_double_t m_gmin;
|
||||
netlist_param_double_t m_lte;
|
||||
netlist_param_logic_t m_dynamic;
|
||||
netlist_param_double_t m_min_timestep;
|
||||
netlist_param_int_t m_nr_loops;
|
||||
netlist_param_int_t m_gs_loops;
|
||||
netlist_param_int_t m_gs_threshold;
|
||||
netlist_param_int_t m_parallel;
|
||||
|
||||
netlist_param_int_t m_nr_loops;
|
||||
netlist_param_int_t m_gs_loops;
|
||||
netlist_param_int_t m_parallel;
|
||||
|
||||
netlist_matrix_solver_t::list_t m_mat_solvers;
|
||||
netlist_matrix_solver_t::list_t m_mat_solvers;
|
||||
private:
|
||||
|
||||
netlist_solver_parameters_t m_params;
|
||||
|
@ -39,8 +39,8 @@ ATTR_COLD void netlist_generic_diode::save(pstring name, netlist_object_t &paren
|
||||
// nld_twoterm
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_COLD NETLIB_NAME(twoterm)::NETLIB_NAME(twoterm)(const family_t afamily) :
|
||||
netlist_device_t(afamily)
|
||||
ATTR_COLD NETLIB_NAME(twoterm)::NETLIB_NAME(twoterm)(const family_t afamily)
|
||||
: netlist_device_t(afamily)
|
||||
{
|
||||
m_P.m_otherterm = &m_N;
|
||||
m_N.m_otherterm = &m_P;
|
||||
@ -177,7 +177,7 @@ NETLIB_START(C)
|
||||
register_param("C", m_C, 1e-6);
|
||||
|
||||
// set up the element
|
||||
set(netlist().gmin(), 0.0, -5.0 / netlist().gmin());
|
||||
//set(netlist().gmin(), 0.0, -5.0 / netlist().gmin());
|
||||
//set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN);
|
||||
}
|
||||
|
||||
|
@ -98,9 +98,9 @@ public:
|
||||
|
||||
ATTR_HOT inline void set(const double G, const double V, const double I)
|
||||
{
|
||||
m_P.m_go = m_N.m_go = m_P.m_gt = m_N.m_gt = G;
|
||||
m_N.m_Idr = ( -V) * G + I;
|
||||
m_P.m_Idr = ( V) * G - I;
|
||||
/* GO, GT, I */
|
||||
m_P.set( G, G, ( V) * G - I);
|
||||
m_N.set( G, G, ( -V) * G + I);
|
||||
}
|
||||
|
||||
ATTR_HOT inline double deltaV()
|
||||
@ -110,14 +110,9 @@ public:
|
||||
|
||||
ATTR_HOT void set_mat(double a11, double a12, double a21, double a22, double r1, double r2)
|
||||
{
|
||||
m_P.m_gt = a11;
|
||||
m_P.m_go = -a12;
|
||||
m_N.m_gt = a22;
|
||||
m_N.m_go = -a21;
|
||||
|
||||
m_P.m_Idr = -r1;
|
||||
m_N.m_Idr = -r2;
|
||||
|
||||
/* GO, GT, I */
|
||||
m_P.set(-a12, a11, -r1);
|
||||
m_N.set(-a21, a22, -r2);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -767,9 +767,9 @@ ATTR_COLD netlist_core_terminal_t::netlist_core_terminal_t(const type_t atype, c
|
||||
|
||||
ATTR_COLD netlist_terminal_t::netlist_terminal_t()
|
||||
: netlist_core_terminal_t(TERMINAL, ANALOG)
|
||||
, m_Idr(0.0)
|
||||
, m_go(NETLIST_GMIN_DEFAULT)
|
||||
, m_gt(NETLIST_GMIN_DEFAULT)
|
||||
, m_Idr1(NULL)
|
||||
, m_go1(NULL)
|
||||
, m_gt1(NULL)
|
||||
, m_otherterm(NULL)
|
||||
{
|
||||
}
|
||||
@ -779,16 +779,16 @@ ATTR_COLD void netlist_terminal_t::reset()
|
||||
{
|
||||
//netlist_terminal_core_terminal_t::reset();
|
||||
set_state(STATE_INP_ACTIVE);
|
||||
m_Idr = 0.0;
|
||||
m_go = netlist().gmin();
|
||||
m_gt = netlist().gmin();
|
||||
set_ptr(m_Idr1, 0.0);
|
||||
set_ptr(m_go1, netlist().gmin());
|
||||
set_ptr(m_gt1, netlist().gmin());
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_terminal_t::save_register()
|
||||
{
|
||||
save(NAME(m_Idr));
|
||||
save(NAME(m_go));
|
||||
save(NAME(m_gt));
|
||||
save(NAME(m_Idr1));
|
||||
save(NAME(m_go1));
|
||||
save(NAME(m_gt1));
|
||||
netlist_core_terminal_t::save_register();
|
||||
}
|
||||
|
||||
|
@ -433,28 +433,29 @@ public:
|
||||
|
||||
ATTR_COLD netlist_terminal_t();
|
||||
|
||||
double m_Idr; // drive current
|
||||
double m_go; // conductance for Voltage from other term
|
||||
double m_gt; // conductance for total conductance
|
||||
double *m_Idr1; // drive current
|
||||
double *m_go1; // conductance for Voltage from other term
|
||||
double *m_gt1; // conductance for total conductance
|
||||
|
||||
ATTR_HOT inline void set(const double G)
|
||||
{
|
||||
m_Idr = 0;
|
||||
m_go = m_gt = G;
|
||||
set_ptr(m_Idr1, 0);
|
||||
set_ptr(m_go1, G);
|
||||
set_ptr(m_gt1, G);
|
||||
}
|
||||
|
||||
ATTR_HOT inline void set(const double GO, const double GT)
|
||||
{
|
||||
m_Idr = 0;
|
||||
m_go = GO;
|
||||
m_gt = GT;
|
||||
set_ptr(m_Idr1, 0);
|
||||
set_ptr(m_go1, GO);
|
||||
set_ptr(m_gt1, GT);
|
||||
}
|
||||
|
||||
ATTR_HOT inline void set(const double GO, const double GT, const double I)
|
||||
{
|
||||
m_Idr = I;
|
||||
m_go = GO;
|
||||
m_gt = GT;
|
||||
set_ptr(m_Idr1, I);
|
||||
set_ptr(m_go1, GO);
|
||||
set_ptr(m_gt1, GT);
|
||||
}
|
||||
|
||||
|
||||
@ -464,6 +465,12 @@ protected:
|
||||
ATTR_COLD virtual void save_register();
|
||||
|
||||
ATTR_COLD virtual void reset();
|
||||
private:
|
||||
inline void set_ptr(double *ptr, const double val)
|
||||
{
|
||||
if (ptr != NULL)
|
||||
*ptr = val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@ ATTR_COLD pstate_manager_t::~pstate_manager_t()
|
||||
|
||||
|
||||
|
||||
ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pstate_data_type_e dt, const void *owner, const int size, const int count, void *ptr)
|
||||
ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pstate_data_type_e dt, const void *owner, const int size, const int count, void *ptr, bool is_ptr)
|
||||
{
|
||||
pstring fullname = stname;
|
||||
ATTR_UNUSED pstring ts[] = {
|
||||
@ -27,7 +27,7 @@ ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pst
|
||||
};
|
||||
|
||||
NL_VERBOSE_OUT(("SAVE: <%s> %s(%d) %p\n", fullname.cstr(), ts[dt].cstr(), size, ptr));
|
||||
pstate_entry_t *p = new pstate_entry_t(stname, dt, owner, size, count, ptr);
|
||||
pstate_entry_t *p = new pstate_entry_t(stname, dt, owner, size, count, ptr, is_ptr);
|
||||
m_save.add(p);
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,23 @@ enum pstate_data_type_e {
|
||||
DT_BOOLEAN
|
||||
};
|
||||
|
||||
template<typename _ItemType> struct nl_datatype { static const pstate_data_type_e type = pstate_data_type_e(NOT_SUPPORTED); };
|
||||
template<typename _ItemType> struct nl_datatype
|
||||
{
|
||||
static const pstate_data_type_e type = pstate_data_type_e(NOT_SUPPORTED);
|
||||
static const bool is_ptr = false;
|
||||
};
|
||||
|
||||
template<typename _ItemType> struct nl_datatype<_ItemType *>
|
||||
{
|
||||
static const pstate_data_type_e type = pstate_data_type_e(NOT_SUPPORTED);
|
||||
static const bool is_ptr = true;
|
||||
};
|
||||
|
||||
//template<typename _ItemType> struct type_checker<_ItemType*> { static const bool is_atom = false; static const bool is_pointer = true; };
|
||||
|
||||
#define NETLIST_SAVE_TYPE(TYPE, TYPEDESC) template<> struct nl_datatype<TYPE>{ static const pstate_data_type_e type = pstate_data_type_e(TYPEDESC); }
|
||||
#define NETLIST_SAVE_TYPE(TYPE, TYPEDESC) \
|
||||
template<> struct nl_datatype<TYPE>{ static const pstate_data_type_e type = pstate_data_type_e(TYPEDESC); static const bool is_ptr = false;}; \
|
||||
template<> struct nl_datatype<TYPE *>{ static const pstate_data_type_e type = pstate_data_type_e(TYPEDESC); static const bool is_ptr = true;};
|
||||
|
||||
NETLIST_SAVE_TYPE(char, DT_INT8);
|
||||
NETLIST_SAVE_TYPE(double, DT_DOUBLE);
|
||||
@ -73,11 +86,11 @@ struct pstate_entry_t
|
||||
typedef plinearlist_t<pstate_entry_t *> list_t;
|
||||
|
||||
pstate_entry_t(const pstring &stname, const pstate_data_type_e dt, const void *owner,
|
||||
const int size, const int count, void *ptr)
|
||||
: m_name(stname), m_dt(dt), m_owner(owner), m_callback(NULL), m_size(size), m_count(count), m_ptr(ptr) { }
|
||||
const int size, const int count, void *ptr, bool is_ptr)
|
||||
: m_name(stname), m_dt(dt), m_owner(owner), m_callback(NULL), m_size(size), m_count(count), m_ptr(ptr), m_is_ptr(is_ptr) { }
|
||||
|
||||
pstate_entry_t(const pstring &stname, const void *owner, pstate_callback_t *callback)
|
||||
: m_name(stname), m_dt(DT_CUSTOM), m_owner(owner), m_callback(callback), m_size(0), m_count(0), m_ptr(NULL) { }
|
||||
: m_name(stname), m_dt(DT_CUSTOM), m_owner(owner), m_callback(callback), m_size(0), m_count(0), m_ptr(NULL), m_is_ptr(false) { }
|
||||
|
||||
pstring m_name;
|
||||
const pstate_data_type_e m_dt;
|
||||
@ -86,6 +99,16 @@ struct pstate_entry_t
|
||||
const int m_size;
|
||||
const int m_count;
|
||||
void *m_ptr;
|
||||
bool m_is_ptr;
|
||||
|
||||
template<typename T>
|
||||
T *resolved()
|
||||
{
|
||||
if (m_is_ptr)
|
||||
return *static_cast<T **>(m_ptr);
|
||||
else
|
||||
return static_cast<T *>(m_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
class pstate_manager_t
|
||||
@ -96,17 +119,17 @@ public:
|
||||
|
||||
template<typename C> ATTR_COLD void save_item(C &state, const void *owner, const pstring &stname)
|
||||
{
|
||||
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(C), 1, &state);
|
||||
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(C), 1, &state, nl_datatype<C>::is_ptr);
|
||||
}
|
||||
|
||||
template<typename C, std::size_t N> ATTR_COLD void save_item(C (&state)[N], const void *owner, const pstring &stname)
|
||||
{
|
||||
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(state[0]), N, &(state[0]));
|
||||
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(state[0]), N, &(state[0]), false);
|
||||
}
|
||||
|
||||
template<typename C> ATTR_COLD void save_item(C *state, const void *owner, const pstring &stname, const int count)
|
||||
{
|
||||
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(C), count, state);
|
||||
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(C), count, state, false);
|
||||
}
|
||||
|
||||
ATTR_COLD void pre_save();
|
||||
@ -116,7 +139,7 @@ public:
|
||||
inline const pstate_entry_t::list_t &save_list() const { return m_save; }
|
||||
|
||||
protected:
|
||||
ATTR_COLD void save_state_ptr(const pstring &stname, const pstate_data_type_e, const void *owner, const int size, const int count, void *ptr);
|
||||
ATTR_COLD void save_state_ptr(const pstring &stname, const pstate_data_type_e, const void *owner, const int size, const int count, void *ptr, bool is_ptr);
|
||||
|
||||
private:
|
||||
pstate_entry_t::list_t m_save;
|
||||
@ -132,7 +155,7 @@ template<> ATTR_COLD inline void pstate_manager_t::save_item(pstate_callback_t &
|
||||
|
||||
template<> ATTR_COLD inline void pstate_manager_t::save_item(netlist_time &nlt, const void *owner, const pstring &stname)
|
||||
{
|
||||
save_state_ptr(stname, DT_INT64, owner, sizeof(netlist_time::INTERNALTYPE), 1, nlt.get_internaltype_ptr());
|
||||
save_state_ptr(stname, DT_INT64, owner, sizeof(netlist_time::INTERNALTYPE), 1, nlt.get_internaltype_ptr(), false);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user