trunk/src/emu/netlist/analog/nld_ms_direct.h
| r242641 | r242642 | |
| 14 | 14 | public: |
| 15 | 15 | |
| 16 | 16 | netlist_matrix_solver_direct_t(const netlist_solver_parameters_t ¶ms, int size); |
| 17 | netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t ¶ms, int size); |
| 17 | 18 | |
| 18 | 19 | virtual ~netlist_matrix_solver_direct_t(); |
| 19 | 20 | |
| r242641 | r242642 | |
| 186 | 187 | * Sorting as a general matrix pre-conditioning is mentioned in |
| 187 | 188 | * literature but I have found no articles about Gauss Seidel. |
| 188 | 189 | * |
| 190 | * For Gaussian Elimination however increasing order is better suited. |
| 191 | * FIXME: Even better would be to sort on elements right of the matrix diagonal. |
| 192 | * |
| 189 | 193 | */ |
| 190 | 194 | |
| 195 | int sort_order = (type() == GAUSS_SEIDEL ? 1 : -1); |
| 191 | 196 | |
| 192 | 197 | for (int k = 0; k < N() / 2; k++) |
| 193 | 198 | for (int i = 0; i < N() - 1; i++) |
| 194 | 199 | { |
| 195 | | if (m_terms[i]->m_railstart < m_terms[i+1]->m_railstart) |
| 200 | if ((m_terms[i]->m_railstart - m_terms[i+1]->m_railstart) * sort_order < 0) |
| 196 | 201 | { |
| 197 | 202 | std::swap(m_terms[i],m_terms[i+1]); |
| 198 | 203 | m_nets.swap(i, i+1); |
| r242641 | r242642 | |
| 443 | 448 | |
| 444 | 449 | template <int m_N, int _storage_N> |
| 445 | 450 | netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const netlist_solver_parameters_t ¶ms, int size) |
| 446 | | : netlist_matrix_solver_t(params) |
| 451 | : netlist_matrix_solver_t(GAUSSIAN_ELIMINATION, params) |
| 447 | 452 | , m_dim(size) |
| 448 | 453 | , m_lp_fact(0) |
| 449 | 454 | { |
| r242641 | r242642 | |
| 458 | 463 | m_row_ops[N()] = vector_ops_t::create_ops(N()); |
| 459 | 464 | } |
| 460 | 465 | |
| 466 | template <int m_N, int _storage_N> |
| 467 | netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t ¶ms, int size) |
| 468 | : netlist_matrix_solver_t(type, params) |
| 469 | , m_dim(size) |
| 470 | , m_lp_fact(0) |
| 471 | { |
| 472 | m_terms = new terms_t *[N()]; |
| 473 | m_rails_temp = new terms_t[N()]; |
| 461 | 474 | |
| 475 | for (int k = 0; k < N(); k++) |
| 476 | { |
| 477 | m_terms[k] = new terms_t; |
| 478 | m_row_ops[k] = vector_ops_t::create_ops(k); |
| 479 | } |
| 480 | m_row_ops[N()] = vector_ops_t::create_ops(N()); |
| 481 | } |
| 462 | 482 | |
| 483 | |
| 463 | 484 | #endif /* NLD_MS_DIRECT_H_ */ |
trunk/src/emu/netlist/analog/nld_ms_gauss_seidel.h
| r242641 | r242642 | |
| 17 | 17 | public: |
| 18 | 18 | |
| 19 | 19 | netlist_matrix_solver_gauss_seidel_t(const netlist_solver_parameters_t ¶ms, int size) |
| 20 | | : netlist_matrix_solver_direct_t<m_N, _storage_N>(params, size) |
| 20 | : netlist_matrix_solver_direct_t<m_N, _storage_N>(netlist_matrix_solver_t::GAUSS_SEIDEL, params, size) |
| 21 | 21 | , m_lp_fact(0) |
| 22 | 22 | , m_gs_fail(0) |
| 23 | 23 | , m_gs_total(0) |
| r242641 | r242642 | |
| 45 | 45 | template <int m_N, int _storage_N> |
| 46 | 46 | void netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::log_stats() |
| 47 | 47 | { |
| 48 | | #if 0 |
| 49 | | if (this->m_calculations == 0) |
| 48 | #if 1 |
| 49 | if (this->m_stat_calculations == 0) |
| 50 | 50 | return; |
| 51 | 51 | printf("==============================================\n"); |
| 52 | 52 | printf("Solver %s\n", this->name().cstr()); |
| 53 | 53 | printf(" ==> %d nets\n", this->N()); //, (*(*groups[i].first())->m_core_terms.first())->name().cstr()); |
| 54 | 54 | printf(" has %s elements\n", this->is_dynamic() ? "dynamic" : "no dynamic"); |
| 55 | 55 | printf(" has %s elements\n", this->is_timestep() ? "timestep" : "no timestep"); |
| 56 | printf(" %6.3f average newton raphson loops\n", (double) this->m_stat_newton_raphson / (double) this->m_stat_vsolver_calls); |
| 56 | 57 | printf(" %10d invocations (%6d Hz) %10d gs fails (%6.2f%%) %6.3f average\n", |
| 57 | | this->m_calculations, |
| 58 | | this->m_calculations * 10 / (int) (this->netlist().time().as_double() * 10.0), |
| 58 | this->m_stat_calculations, |
| 59 | this->m_stat_calculations * 10 / (int) (this->netlist().time().as_double() * 10.0), |
| 59 | 60 | this->m_gs_fail, |
| 60 | | 100.0 * (double) this->m_gs_fail / (double) this->m_calculations, |
| 61 | | (double) this->m_gs_total / (double) this->m_calculations); |
| 61 | 100.0 * (double) this->m_gs_fail / (double) this->m_stat_calculations, |
| 62 | (double) this->m_gs_total / (double) this->m_stat_calculations); |
| 62 | 63 | #endif |
| 63 | 64 | } |
| 64 | 65 | |
| r242641 | r242642 | |
| 292 | 293 | //if (fabs(gabs_t - fabs(gtot_t)) > 1e-20) |
| 293 | 294 | // printf("%d %e abs: %f tot: %f\n",k, gabs_t / gtot_t -1.0, gabs_t, gtot_t); |
| 294 | 295 | |
| 295 | | gabs_t *= 0.5; // avoid rounding issues |
| 296 | gabs_t *= 0.95; // avoid rounding issues |
| 296 | 297 | if (!USE_GABS || gabs_t <= gtot_t) |
| 297 | 298 | { |
| 298 | 299 | w[k] = ws / gtot_t; |
| r242641 | r242642 | |
| 336 | 337 | this->m_nets[k]->m_cur_Analog = new_V[k]; |
| 337 | 338 | |
| 338 | 339 | this->m_gs_total += resched_cnt; |
| 339 | | this->m_calculations++; |
| 340 | this->m_stat_calculations++; |
| 340 | 341 | |
| 341 | 342 | if (resched) |
| 342 | 343 | { |
trunk/src/emu/netlist/analog/nld_solver.c
| r242641 | r242642 | |
| 36 | 36 | #include "../nl_lists.h" |
| 37 | 37 | |
| 38 | 38 | #if HAS_OPENMP |
| 39 | | #include <omp.h> |
| 39 | #include "omp.h" |
| 40 | 40 | #endif |
| 41 | 41 | |
| 42 | 42 | vector_ops_t *vector_ops_t::create_ops(const int size) |
| r242641 | r242642 | |
| 99 | 99 | // netlist_matrix_solver |
| 100 | 100 | // ---------------------------------------------------------------------------------------- |
| 101 | 101 | |
| 102 | | ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const netlist_solver_parameters_t ¶ms) |
| 103 | | : m_calculations(0), m_params(params), m_cur_ts(0) |
| 102 | ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t ¶ms) |
| 103 | : m_stat_calculations(0), |
| 104 | m_stat_newton_raphson(0), |
| 105 | m_stat_vsolver_calls(0), |
| 106 | m_params(params), |
| 107 | m_cur_ts(0), |
| 108 | m_type(type) |
| 104 | 109 | { |
| 105 | 110 | } |
| 106 | 111 | |
| r242641 | r242642 | |
| 254 | 259 | template<class C > |
| 255 | 260 | void netlist_matrix_solver_t::solve_base(C *p) |
| 256 | 261 | { |
| 262 | m_stat_vsolver_calls++; |
| 257 | 263 | if (is_dynamic()) |
| 258 | 264 | { |
| 259 | 265 | int this_resched; |
| r242641 | r242642 | |
| 266 | 272 | newton_loops++; |
| 267 | 273 | } while (this_resched > 1 && newton_loops < m_params.m_nr_loops); |
| 268 | 274 | |
| 275 | m_stat_newton_raphson += newton_loops; |
| 269 | 276 | // reschedule .... |
| 270 | 277 | if (this_resched > 1 && !m_Q_sync.net().is_queued()) |
| 271 | 278 | { |
| r242641 | r242642 | |
| 285 | 292 | netlist_time delta = now - m_last_step; |
| 286 | 293 | |
| 287 | 294 | // We are already up to date. Avoid oscillations. |
| 295 | // FIXME: Make this a parameter! |
| 288 | 296 | if (delta < netlist_time::from_nsec(1)) |
| 289 | 297 | return -1.0; |
| 290 | 298 | |
trunk/src/emu/netlist/analog/nld_solver.h
| r242641 | r242642 | |
| 14 | 14 | |
| 15 | 15 | #define USE_PIVOT_SEARCH (0) |
| 16 | 16 | #define VECTALT 1 |
| 17 | | #define USE_GABS 0 |
| 17 | #define USE_GABS 1 |
| 18 | 18 | #define USE_MATRIX_GS 0 |
| 19 | 19 | // savings are eaten up by effort |
| 20 | 20 | #define USE_LINEAR_PREDICTION (0) |
| r242641 | r242642 | |
| 197 | 197 | typedef plinearlist_t<netlist_matrix_solver_t *> list_t; |
| 198 | 198 | typedef netlist_core_device_t::list_t dev_list_t; |
| 199 | 199 | |
| 200 | | ATTR_COLD netlist_matrix_solver_t(const netlist_solver_parameters_t ¶ms); |
| 200 | enum eSolverType |
| 201 | { |
| 202 | GAUSSIAN_ELIMINATION, |
| 203 | GAUSS_SEIDEL |
| 204 | }; |
| 205 | |
| 206 | ATTR_COLD netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t ¶ms); |
| 201 | 207 | ATTR_COLD virtual ~netlist_matrix_solver_t(); |
| 202 | 208 | |
| 203 | 209 | ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets) = 0; |
| r242641 | r242642 | |
| 224 | 230 | ATTR_COLD int get_net_idx(netlist_net_t *net); |
| 225 | 231 | ATTR_COLD virtual void log_stats() {}; |
| 226 | 232 | |
| 233 | inline const eSolverType type() const { return m_type; } |
| 234 | |
| 227 | 235 | protected: |
| 228 | 236 | |
| 229 | 237 | ATTR_COLD void setup(netlist_analog_net_t::list_t &nets); |
| r242641 | r242642 | |
| 237 | 245 | plinearlist_t<netlist_analog_net_t *> m_nets; |
| 238 | 246 | plinearlist_t<netlist_analog_output_t *> m_inps; |
| 239 | 247 | |
| 240 | | int m_calculations; |
| 248 | int m_stat_calculations; |
| 249 | int m_stat_newton_raphson; |
| 250 | int m_stat_vsolver_calls; |
| 251 | |
| 241 | 252 | const netlist_solver_parameters_t &m_params; |
| 242 | 253 | |
| 243 | 254 | ATTR_HOT inline const double current_timestep() { return m_cur_ts; } |
| r242641 | r242642 | |
| 255 | 266 | |
| 256 | 267 | ATTR_HOT void update_inputs(); |
| 257 | 268 | |
| 269 | const eSolverType m_type; |
| 258 | 270 | }; |
| 259 | 271 | |
| 260 | 272 | |
trunk/src/emu/netlist/devices/net_lib.c
| r242641 | r242642 | |
| 91 | 91 | ENTRY(VCCS, VCCS, "-") |
| 92 | 92 | ENTRY(CCCS, CCCS, "-") |
| 93 | 93 | ENTRY(dummy_input, DUMMY_INPUT, "-") |
| 94 | ENTRY(frontier, FRONTIER, "+I,Q") |
| 94 | 95 | ENTRY(QBJT_EB, QBJT_EB, "model") |
| 95 | 96 | ENTRY(QBJT_switch, QBJT_SW, "model") |
| 96 | 97 | ENTRY(ttl_input, TTL_INPUT, "IN") |
trunk/src/emu/netlist/devices/nld_4020.c
| r242641 | r242642 | |
| 8 | 8 | NETLIB_START(4020) |
| 9 | 9 | { |
| 10 | 10 | register_sub(sub, "sub"); |
| 11 | register_sub(m_supply, "supply"); |
| 11 | 12 | |
| 12 | 13 | register_input("RESET", m_RESET); |
| 13 | 14 | register_subalias("IP", sub.m_IP); |
| r242641 | r242642 | |
| 42 | 43 | register_output("Q5", m_Q[4]); |
| 43 | 44 | register_output("Q6", m_Q[5]); |
| 44 | 45 | register_output("Q7", m_Q[6]); |
| 45 | | register_output("Q8", m_Q[8]); |
| 46 | register_output("Q8", m_Q[7]); |
| 46 | 47 | register_output("Q9", m_Q[8]); |
| 47 | 48 | register_output("Q10", m_Q[9]); |
| 48 | 49 | register_output("Q11", m_Q[10]); |
trunk/src/emu/netlist/devices/nld_system.h
| r242641 | r242642 | |
| 39 | 39 | #define DUMMY_INPUT(_name) \ |
| 40 | 40 | NET_REGISTER_DEV(dummy_input, _name) |
| 41 | 41 | |
| 42 | #define FRONTIER(_name, _IN, _OUT) \ |
| 43 | NET_REGISTER_DEV(frontier, _name) \ |
| 44 | NET_C(_IN, _name.I) \ |
| 45 | NET_C(_OUT, _name.Q) \ |
| 46 | |
| 42 | 47 | // ----------------------------------------------------------------------------- |
| 43 | 48 | // mainclock |
| 44 | 49 | // ----------------------------------------------------------------------------- |
| r242641 | r242642 | |
| 147 | 152 | |
| 148 | 153 | }; |
| 149 | 154 | |
| 155 | // ----------------------------------------------------------------------------- |
| 156 | // nld_frontier |
| 157 | // ----------------------------------------------------------------------------- |
| 150 | 158 | |
| 159 | class NETLIB_NAME(frontier) : public netlist_device_t |
| 160 | { |
| 161 | public: |
| 162 | ATTR_COLD NETLIB_NAME(frontier)() |
| 163 | : netlist_device_t(DUMMY) { } |
| 164 | |
| 165 | ATTR_COLD virtual ~NETLIB_NAME(frontier)() {} |
| 166 | |
| 167 | protected: |
| 168 | |
| 169 | ATTR_COLD void start() |
| 170 | { |
| 171 | register_input("I", m_I); |
| 172 | register_output("Q", m_Q); |
| 173 | } |
| 174 | |
| 175 | ATTR_COLD void reset() |
| 176 | { |
| 177 | } |
| 178 | |
| 179 | ATTR_HOT ATTR_ALIGN void update() |
| 180 | { |
| 181 | OUTANALOG(m_Q, INPANALOG(m_I)); |
| 182 | } |
| 183 | |
| 184 | private: |
| 185 | netlist_analog_input_t m_I; |
| 186 | netlist_analog_output_t m_Q; |
| 187 | |
| 188 | }; |
| 189 | |
| 190 | |
| 151 | 191 | // ----------------------------------------------------------------------------- |
| 152 | 192 | // netdev_a_to_d |
| 153 | 193 | // ----------------------------------------------------------------------------- |