From e198be8555f69608c13d2d44a50517bde8ebf73c Mon Sep 17 00:00:00 2001 From: couriersud Date: Wed, 31 Dec 2014 14:51:20 +0100 Subject: Netlist update. Most prominent one is a "frontier" element which on a low to high impedance node will - no other connections provided - let the system create two matrices. --- src/emu/netlist/analog/nld_ms_direct.h | 25 +++++++++++++++-- src/emu/netlist/analog/nld_ms_gauss_seidel.h | 19 ++++++------- src/emu/netlist/analog/nld_opamps.c | 2 +- src/emu/netlist/analog/nld_solver.c | 14 +++++++--- src/emu/netlist/analog/nld_solver.h | 18 ++++++++++--- src/emu/netlist/devices/net_lib.c | 1 + src/emu/netlist/devices/nld_4020.c | 3 ++- src/emu/netlist/devices/nld_cmos.h | 6 ++++- src/emu/netlist/devices/nld_system.h | 40 ++++++++++++++++++++++++++++ src/emu/netlist/nl_base.h | 1 + 10 files changed, 109 insertions(+), 20 deletions(-) diff --git a/src/emu/netlist/analog/nld_ms_direct.h b/src/emu/netlist/analog/nld_ms_direct.h index e067a476989..ed1215ec293 100644 --- a/src/emu/netlist/analog/nld_ms_direct.h +++ b/src/emu/netlist/analog/nld_ms_direct.h @@ -14,6 +14,7 @@ class netlist_matrix_solver_direct_t: public netlist_matrix_solver_t public: netlist_matrix_solver_direct_t(const netlist_solver_parameters_t ¶ms, int size); + netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t ¶ms, int size); virtual ~netlist_matrix_solver_direct_t(); @@ -186,13 +187,17 @@ ATTR_COLD void netlist_matrix_solver_direct_t::vsetup(netlist_a * Sorting as a general matrix pre-conditioning is mentioned in * literature but I have found no articles about Gauss Seidel. * + * For Gaussian Elimination however increasing order is better suited. + * FIXME: Even better would be to sort on elements right of the matrix diagonal. + * */ + int sort_order = (type() == GAUSS_SEIDEL ? 1 : -1); for (int k = 0; k < N() / 2; k++) for (int i = 0; i < N() - 1; i++) { - if (m_terms[i]->m_railstart < m_terms[i+1]->m_railstart) + if ((m_terms[i]->m_railstart - m_terms[i+1]->m_railstart) * sort_order < 0) { std::swap(m_terms[i],m_terms[i+1]); m_nets.swap(i, i+1); @@ -443,7 +448,7 @@ ATTR_HOT inline int netlist_matrix_solver_direct_t::vsolve_non_ template netlist_matrix_solver_direct_t::netlist_matrix_solver_direct_t(const netlist_solver_parameters_t ¶ms, int size) -: netlist_matrix_solver_t(params) +: netlist_matrix_solver_t(GAUSSIAN_ELIMINATION, params) , m_dim(size) , m_lp_fact(0) { @@ -458,6 +463,22 @@ netlist_matrix_solver_direct_t::netlist_matrix_solver_direct_t( m_row_ops[N()] = vector_ops_t::create_ops(N()); } +template +netlist_matrix_solver_direct_t::netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t ¶ms, int size) +: netlist_matrix_solver_t(type, params) +, m_dim(size) +, m_lp_fact(0) +{ + m_terms = new terms_t *[N()]; + m_rails_temp = new terms_t[N()]; + + for (int k = 0; k < N(); k++) + { + m_terms[k] = new terms_t; + m_row_ops[k] = vector_ops_t::create_ops(k); + } + m_row_ops[N()] = vector_ops_t::create_ops(N()); +} #endif /* NLD_MS_DIRECT_H_ */ diff --git a/src/emu/netlist/analog/nld_ms_gauss_seidel.h b/src/emu/netlist/analog/nld_ms_gauss_seidel.h index 270aaf227a3..e09bf33cfb2 100644 --- a/src/emu/netlist/analog/nld_ms_gauss_seidel.h +++ b/src/emu/netlist/analog/nld_ms_gauss_seidel.h @@ -17,7 +17,7 @@ class ATTR_ALIGNED(64) netlist_matrix_solver_gauss_seidel_t: public netlist_matr public: netlist_matrix_solver_gauss_seidel_t(const netlist_solver_parameters_t ¶ms, int size) - : netlist_matrix_solver_direct_t(params, size) + : netlist_matrix_solver_direct_t(netlist_matrix_solver_t::GAUSS_SEIDEL, params, size) , m_lp_fact(0) , m_gs_fail(0) , m_gs_total(0) @@ -45,20 +45,21 @@ private: template void netlist_matrix_solver_gauss_seidel_t::log_stats() { -#if 0 - if (this->m_calculations == 0) +#if 1 + if (this->m_stat_calculations == 0) return; printf("==============================================\n"); 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(" %6.3f average newton raphson loops\n", (double) this->m_stat_newton_raphson / (double) this->m_stat_vsolver_calls); printf(" %10d invocations (%6d Hz) %10d gs fails (%6.2f%%) %6.3f average\n", - this->m_calculations, - this->m_calculations * 10 / (int) (this->netlist().time().as_double() * 10.0), + this->m_stat_calculations, + this->m_stat_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); + 100.0 * (double) this->m_gs_fail / (double) this->m_stat_calculations, + (double) this->m_gs_total / (double) this->m_stat_calculations); #endif } @@ -292,7 +293,7 @@ ATTR_HOT inline int netlist_matrix_solver_gauss_seidel_t::vsolv //if (fabs(gabs_t - fabs(gtot_t)) > 1e-20) // printf("%d %e abs: %f tot: %f\n",k, gabs_t / gtot_t -1.0, gabs_t, gtot_t); - gabs_t *= 0.5; // avoid rounding issues + gabs_t *= 0.95; // avoid rounding issues if (!USE_GABS || gabs_t <= gtot_t) { w[k] = ws / gtot_t; @@ -336,7 +337,7 @@ ATTR_HOT inline int netlist_matrix_solver_gauss_seidel_t::vsolv this->m_nets[k]->m_cur_Analog = new_V[k]; this->m_gs_total += resched_cnt; - this->m_calculations++; + this->m_stat_calculations++; if (resched) { diff --git a/src/emu/netlist/analog/nld_opamps.c b/src/emu/netlist/analog/nld_opamps.c index 6ee4f8e3640..32d2457e71f 100644 --- a/src/emu/netlist/analog/nld_opamps.c +++ b/src/emu/netlist/analog/nld_opamps.c @@ -31,7 +31,7 @@ NETLIST_START(opamp_lm3900) NET_C(R1.2, R2.2, G1.ON) VCVS(G1) PARAM(G1.G, 10000000) - //PARAM(G1.RI, 100) + //PARAM(G1.RI, 1) PARAM(G1.RO, RES_K(8)) NETLIST_END() diff --git a/src/emu/netlist/analog/nld_solver.c b/src/emu/netlist/analog/nld_solver.c index 653a621b6e0..bef3dcbcd77 100644 --- a/src/emu/netlist/analog/nld_solver.c +++ b/src/emu/netlist/analog/nld_solver.c @@ -36,7 +36,7 @@ #include "../nl_lists.h" #if HAS_OPENMP -#include +#include "omp.h" #endif vector_ops_t *vector_ops_t::create_ops(const int size) @@ -99,8 +99,13 @@ ATTR_COLD void terms_t::set_pointers() // netlist_matrix_solver // ---------------------------------------------------------------------------------------- -ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const netlist_solver_parameters_t ¶ms) -: m_calculations(0), m_params(params), m_cur_ts(0) +ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t ¶ms) +: m_stat_calculations(0), + m_stat_newton_raphson(0), + m_stat_vsolver_calls(0), + m_params(params), + m_cur_ts(0), + m_type(type) { } @@ -254,6 +259,7 @@ ATTR_HOT void netlist_matrix_solver_t::step(const netlist_time delta) template void netlist_matrix_solver_t::solve_base(C *p) { + m_stat_vsolver_calls++; if (is_dynamic()) { int this_resched; @@ -266,6 +272,7 @@ void netlist_matrix_solver_t::solve_base(C *p) newton_loops++; } while (this_resched > 1 && newton_loops < m_params.m_nr_loops); + m_stat_newton_raphson += newton_loops; // reschedule .... if (this_resched > 1 && !m_Q_sync.net().is_queued()) { @@ -285,6 +292,7 @@ ATTR_HOT double netlist_matrix_solver_t::solve() netlist_time delta = now - m_last_step; // We are already up to date. Avoid oscillations. + // FIXME: Make this a parameter! if (delta < netlist_time::from_nsec(1)) return -1.0; diff --git a/src/emu/netlist/analog/nld_solver.h b/src/emu/netlist/analog/nld_solver.h index a0f6ea470f9..8aa87025e53 100644 --- a/src/emu/netlist/analog/nld_solver.h +++ b/src/emu/netlist/analog/nld_solver.h @@ -14,7 +14,7 @@ #define USE_PIVOT_SEARCH (0) #define VECTALT 1 -#define USE_GABS 0 +#define USE_GABS 1 #define USE_MATRIX_GS 0 // savings are eaten up by effort #define USE_LINEAR_PREDICTION (0) @@ -197,7 +197,13 @@ public: typedef plinearlist_t list_t; typedef netlist_core_device_t::list_t dev_list_t; - ATTR_COLD netlist_matrix_solver_t(const netlist_solver_parameters_t ¶ms); + enum eSolverType + { + GAUSSIAN_ELIMINATION, + GAUSS_SEIDEL + }; + + ATTR_COLD netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t ¶ms); ATTR_COLD virtual ~netlist_matrix_solver_t(); ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets) = 0; @@ -224,6 +230,8 @@ public: ATTR_COLD int get_net_idx(netlist_net_t *net); ATTR_COLD virtual void log_stats() {}; + inline const eSolverType type() const { return m_type; } + protected: ATTR_COLD void setup(netlist_analog_net_t::list_t &nets); @@ -237,7 +245,10 @@ protected: plinearlist_t m_nets; plinearlist_t m_inps; - int m_calculations; + int m_stat_calculations; + int m_stat_newton_raphson; + int m_stat_vsolver_calls; + const netlist_solver_parameters_t &m_params; ATTR_HOT inline const double current_timestep() { return m_cur_ts; } @@ -255,6 +266,7 @@ private: ATTR_HOT void update_inputs(); + const eSolverType m_type; }; diff --git a/src/emu/netlist/devices/net_lib.c b/src/emu/netlist/devices/net_lib.c index 28e2809f777..b9d6686b964 100644 --- a/src/emu/netlist/devices/net_lib.c +++ b/src/emu/netlist/devices/net_lib.c @@ -91,6 +91,7 @@ void netlist_factory_t::initialize() ENTRY(VCCS, VCCS, "-") ENTRY(CCCS, CCCS, "-") ENTRY(dummy_input, DUMMY_INPUT, "-") + ENTRY(frontier, FRONTIER, "+I,Q") ENTRY(QBJT_EB, QBJT_EB, "model") ENTRY(QBJT_switch, QBJT_SW, "model") ENTRY(ttl_input, TTL_INPUT, "IN") diff --git a/src/emu/netlist/devices/nld_4020.c b/src/emu/netlist/devices/nld_4020.c index b9b5eb2f0c0..4a477efcff6 100644 --- a/src/emu/netlist/devices/nld_4020.c +++ b/src/emu/netlist/devices/nld_4020.c @@ -8,6 +8,7 @@ NETLIB_START(4020) { register_sub(sub, "sub"); + register_sub(m_supply, "supply"); register_input("RESET", m_RESET); register_subalias("IP", sub.m_IP); @@ -42,7 +43,7 @@ NETLIB_START(4020_sub) register_output("Q5", m_Q[4]); register_output("Q6", m_Q[5]); register_output("Q7", m_Q[6]); - register_output("Q8", m_Q[8]); + register_output("Q8", m_Q[7]); register_output("Q9", m_Q[8]); register_output("Q10", m_Q[9]); register_output("Q11", m_Q[10]); diff --git a/src/emu/netlist/devices/nld_cmos.h b/src/emu/netlist/devices/nld_cmos.h index 4d450c2003e..5be09d905cd 100644 --- a/src/emu/netlist/devices/nld_cmos.h +++ b/src/emu/netlist/devices/nld_cmos.h @@ -21,7 +21,11 @@ class nld_vdd_vss : public netlist_device_t protected: ATTR_HOT void update() {}; - ATTR_HOT void start() {}; + ATTR_HOT void start() + { + register_input("VDD,", m_vdd); + register_input("VSS,", m_vss); + }; ATTR_HOT void reset() {}; public: diff --git a/src/emu/netlist/devices/nld_system.h b/src/emu/netlist/devices/nld_system.h index f1397e4365a..47ca470d197 100644 --- a/src/emu/netlist/devices/nld_system.h +++ b/src/emu/netlist/devices/nld_system.h @@ -39,6 +39,11 @@ #define DUMMY_INPUT(_name) \ NET_REGISTER_DEV(dummy_input, _name) +#define FRONTIER(_name, _IN, _OUT) \ + NET_REGISTER_DEV(frontier, _name) \ + NET_C(_IN, _name.I) \ + NET_C(_OUT, _name.Q) \ + // ----------------------------------------------------------------------------- // mainclock // ----------------------------------------------------------------------------- @@ -147,6 +152,41 @@ private: }; +// ----------------------------------------------------------------------------- +// nld_frontier +// ----------------------------------------------------------------------------- + +class NETLIB_NAME(frontier) : public netlist_device_t +{ +public: + ATTR_COLD NETLIB_NAME(frontier)() + : netlist_device_t(DUMMY) { } + + ATTR_COLD virtual ~NETLIB_NAME(frontier)() {} + +protected: + + ATTR_COLD void start() + { + register_input("I", m_I); + register_output("Q", m_Q); + } + + ATTR_COLD void reset() + { + } + + ATTR_HOT ATTR_ALIGN void update() + { + OUTANALOG(m_Q, INPANALOG(m_I)); + } + +private: + netlist_analog_input_t m_I; + netlist_analog_output_t m_Q; + +}; + // ----------------------------------------------------------------------------- // netdev_a_to_d diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h index 1a94734ed93..59803356a9c 100644 --- a/src/emu/netlist/nl_base.h +++ b/src/emu/netlist/nl_base.h @@ -337,6 +337,7 @@ public: CAPACITOR, // Capacitor DIODE, // Diode DUMMY, // DUMMY device without function + FRONTIER, // Net frontier BJT_EB, // BJT(Ebers-Moll) BJT_SWITCH, // BJT(Switch) VCVS, // Voltage controlled voltage source -- cgit v1.2.3