trunk/src/emu/netlist/analog/nld_solver.c
| r30707 | r30708 | |
| 41 | 41 | |
| 42 | 42 | for (int k = 0; k < nets.count(); k++) |
| 43 | 43 | { |
| 44 | | m_nets.add(net_entry(nets[k])); |
| 44 | m_nets.add(nets[k]); |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | for (int k = 0; k < nets.count(); k++) |
| r30707 | r30708 | |
| 80 | 80 | netlist_terminal_t *pterm = dynamic_cast<netlist_terminal_t *>(p); |
| 81 | 81 | // for gauss seidel |
| 82 | 82 | pterm->m_new_analog_ptr = &pterm->m_otherterm->net().as_analog().m_new_Analog; |
| 83 | | |
| 83 | #if 0 |
| 84 | 84 | if (pterm->m_otherterm->net().isRailNet()) |
| 85 | 85 | m_nets[k].m_rails.add(pterm); |
| 86 | 86 | else |
| 87 | 87 | m_nets[k].m_terms.add(pterm); |
| 88 | #endif |
| 89 | add_term(k, pterm); |
| 88 | 90 | } |
| 89 | 91 | NL_VERBOSE_OUT(("Added terminal\n")); |
| 90 | 92 | break; |
| r30707 | r30708 | |
| 139 | 141 | #else |
| 140 | 142 | for (int k = 0; k < N(); k++) |
| 141 | 143 | { |
| 142 | | netlist_analog_net_t *n = m_nets[k].m_net; |
| 144 | netlist_analog_net_t *n = m_nets[k]; |
| 143 | 145 | #endif |
| 144 | 146 | double DD_n = (n->m_cur_Analog - n->m_last_Analog); |
| 145 | 147 | |
| r30707 | r30708 | |
| 190 | 192 | #if 1 |
| 191 | 193 | for (int k = 0; k < m_nets.count(); k++) |
| 192 | 194 | { |
| 193 | | netlist_analog_net_t *p= m_nets[k].m_net; |
| 195 | netlist_analog_net_t *p= m_nets[k]; |
| 194 | 196 | p->m_last_Analog = p->m_cur_Analog; |
| 195 | 197 | } |
| 196 | 198 | #else |
| r30707 | r30708 | |
| 323 | 325 | ATTR_COLD int netlist_matrix_solver_t::get_net_idx(netlist_net_t *net) |
| 324 | 326 | { |
| 325 | 327 | for (int k = 0; k < m_nets.count(); k++) |
| 326 | | if (m_nets[k].m_net == net) |
| 328 | if (m_nets[k] == net) |
| 327 | 329 | return k; |
| 328 | 330 | return -1; |
| 329 | 331 | } |
| 330 | 332 | |
| 331 | 333 | template <int m_N, int _storage_N> |
| 334 | ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::add_term(int k, netlist_terminal_t *term) |
| 335 | { |
| 336 | if (term->m_otherterm->net().isRailNet()) |
| 337 | { |
| 338 | //m_nets[k].m_rails.add(pterm); |
| 339 | m_rails[k].add(terms_t(term, -1)); |
| 340 | } |
| 341 | else |
| 342 | { |
| 343 | int ot = get_net_idx(&term->m_otherterm->net()); |
| 344 | if (ot>=0) |
| 345 | { |
| 346 | m_terms[k].add(terms_t(term, ot)); |
| 347 | SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go)); |
| 348 | } |
| 349 | /* Should this be allowed ? */ |
| 350 | else // if (ot<0) |
| 351 | { |
| 352 | m_rails[k].add(terms_t(term, ot)); |
| 353 | netlist().error("found term with missing othernet %s\n", term->name().cstr()); |
| 354 | } |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | |
| 359 | template <int m_N, int _storage_N> |
| 332 | 360 | ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_analog_net_t::list_t &nets) |
| 333 | 361 | { |
| 334 | 362 | m_dim = nets.count(); |
| 335 | | netlist_matrix_solver_t::setup(nets); |
| 336 | 363 | |
| 337 | | m_terms.clear(); |
| 338 | | m_rail_start = 0; |
| 364 | for (int k = 0; k < N(); k++) |
| 365 | { |
| 366 | m_terms[k].clear(); |
| 367 | m_rails[k].clear(); |
| 368 | } |
| 369 | |
| 370 | netlist_matrix_solver_t::setup(nets); |
| 371 | |
| 372 | #if 0 |
| 339 | 373 | for (int k = 0; k < N(); k++) |
| 340 | 374 | { |
| 341 | 375 | const netlist_terminal_t::list_t &terms = m_nets[k].m_terms; |
| r30707 | r30708 | |
| 344 | 378 | int ot = get_net_idx(&terms[i]->m_otherterm->net()); |
| 345 | 379 | if (ot>=0) |
| 346 | 380 | { |
| 347 | | m_terms.add(terms_t(terms[i], k, ot)); |
| 381 | m_terms[k].add(terms_t(terms[i], ot)); |
| 348 | 382 | SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go)); |
| 349 | 383 | } |
| 350 | 384 | } |
| 351 | 385 | } |
| 352 | | m_rail_start = m_terms.count(); |
| 386 | |
| 387 | /* Should this be allowed ? */ |
| 353 | 388 | for (int k = 0; k < N(); k++) |
| 354 | 389 | { |
| 355 | 390 | const netlist_terminal_t::list_t &terms = m_nets[k].m_terms; |
| 356 | | const netlist_terminal_t::list_t &rails = m_nets[k].m_rails; |
| 357 | 391 | for (int i = 0; i < terms.count(); i++) |
| 358 | 392 | { |
| 359 | 393 | int ot = get_net_idx(&terms[i]->m_otherterm->net()); |
| 360 | 394 | if (ot<0) |
| 361 | 395 | { |
| 362 | | m_terms.add(terms_t(terms[i], k, ot)); |
| 396 | m_rails[k].add(terms_t(terms[i], ot)); |
| 363 | 397 | netlist().warning("found term with missing othernet %s\n", terms[i]->name().cstr()); |
| 364 | 398 | } |
| 365 | 399 | } |
| 400 | } |
| 401 | |
| 402 | |
| 403 | for (int k = 0; k < N(); k++) |
| 404 | { |
| 405 | const netlist_terminal_t::list_t &rails = m_nets[k].m_rails; |
| 366 | 406 | for (int i = 0; i < rails.count(); i++) |
| 367 | 407 | { |
| 368 | | m_terms.add(terms_t(rails[i], k, -1)); |
| 408 | m_rails[k].add(terms_t(rails[i], -1)); |
| 369 | 409 | SOLVER_VERBOSE_OUT(("Net %d Rail %s %f %f\n", k, rails[i]->name().cstr(), rails[i]->m_gt, rails[i]->m_go)); |
| 370 | 410 | } |
| 371 | 411 | } |
| 412 | #endif |
| 372 | 413 | } |
| 373 | 414 | |
| 374 | 415 | template <int m_N, int _storage_N> |
| r30707 | r30708 | |
| 378 | 419 | for (int i=0; i < _storage_N; i++) |
| 379 | 420 | m_A[k][i] = 0.0; |
| 380 | 421 | |
| 381 | | for (int k=0; k < _storage_N; k++) |
| 382 | | m_RHS[k] = 0.0; |
| 383 | | #if 0 |
| 422 | for (int k = 0; k < N(); k++) |
| 423 | { |
| 424 | double rhsk = 0.0; |
| 425 | double akk = 0.0; |
| 426 | const int terms_count = m_terms[k].count(); |
| 427 | const terms_t *terms = m_terms[k]; |
| 384 | 428 | |
| 385 | | for (int i = 0; i < m_term_num; i++) |
| 386 | | { |
| 387 | | terms_t &t = m_terms[i]; |
| 388 | | m_RHS[t.m_net_this] += t.m_term->m_Idr; |
| 389 | | m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt; |
| 390 | | if (t.m_net_other >= 0) |
| 429 | for (int i = 0; i < terms_count; i++) |
| 391 | 430 | { |
| 392 | | //m_A[t.net_other][t.net_other] += t.term->m_otherterm->m_gt; |
| 393 | | m_A[t.m_net_this][t.m_net_other] += -t.m_term->m_go; |
| 394 | | //m_A[t.net_other][t.net_this] += -t.term->m_otherterm->m_go; |
| 431 | //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); |
| 432 | |
| 433 | rhsk = rhsk + terms[i].m_term->m_Idr; |
| 434 | akk = akk + terms[i].m_term->m_gt; |
| 435 | m_A[k][terms[i].m_net_other] += -terms[i].m_term->m_go; |
| 395 | 436 | } |
| 396 | | else |
| 397 | | m_RHS[t.m_net_this] += t.m_term->m_go * t.m_term->m_otherterm->net().as_analog().Q_Analog(); |
| 398 | | } |
| 399 | | #else |
| 400 | | for (int i = 0; i < m_rail_start; i++) |
| 401 | | { |
| 402 | | const terms_t &t = m_terms[i]; |
| 403 | | //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); |
| 404 | 437 | |
| 405 | | m_RHS[t.m_net_this] += t.m_term->m_Idr; |
| 406 | | m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt; |
| 407 | | m_A[t.m_net_this][t.m_net_other] += -t.m_term->m_go; |
| 408 | | } |
| 409 | | for (int i = m_rail_start; i < m_terms.count(); i++) |
| 410 | | { |
| 411 | | const terms_t &t = m_terms[i]; |
| 438 | const int rails_count = m_rails[k].count(); |
| 439 | const terms_t *rails = m_rails[k]; |
| 412 | 440 | |
| 413 | | m_RHS[t.m_net_this] += t.m_term->m_Idr; |
| 414 | | m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt; |
| 415 | | m_RHS[t.m_net_this] += t.m_term->m_go * t.m_term->m_otherterm->net().as_analog().Q_Analog(); |
| 416 | | } |
| 417 | | #endif |
| 441 | for (int i = 0; i < rails_count; i++) |
| 442 | { |
| 443 | const terms_t t = rails[i]; |
| 444 | |
| 445 | rhsk = rhsk + t.m_term->m_Idr + t.m_term->m_go * t.m_term->m_otherterm->net().as_analog().Q_Analog(); |
| 446 | akk = akk + t.m_term->m_gt; |
| 447 | } |
| 448 | m_RHS[k] = rhsk; |
| 449 | m_A[k][k] += akk; |
| 450 | } |
| 418 | 451 | } |
| 419 | 452 | |
| 420 | 453 | template <int m_N, int _storage_N> |
| r30707 | r30708 | |
| 504 | 537 | double cerr2 = 0; |
| 505 | 538 | for (int i = 0; i < this->N(); i++) |
| 506 | 539 | { |
| 507 | | const double e = (V[i] - this->m_nets[i].m_net->m_cur_Analog); |
| 540 | const double e = (V[i] - this->m_nets[i]->m_cur_Analog); |
| 508 | 541 | const double e2 = (m_RHS[i] - this->m_last_RHS[i]); |
| 509 | 542 | cerr = (fabs(e) > cerr ? fabs(e) : cerr); |
| 510 | 543 | cerr2 = (fabs(e2) > cerr2 ? fabs(e2) : cerr2); |
| r30707 | r30708 | |
| 519 | 552 | { |
| 520 | 553 | for (int i = 0; i < this->N(); i++) |
| 521 | 554 | { |
| 522 | | this->m_nets[i].m_net->m_cur_Analog = this->m_nets[i].m_net->m_new_Analog = V[i]; |
| 555 | this->m_nets[i]->m_cur_Analog = this->m_nets[i]->m_new_Analog = V[i]; |
| 523 | 556 | } |
| 524 | 557 | if (store_RHS) |
| 525 | 558 | { |
| r30707 | r30708 | |
| 569 | 602 | ATTR_HOT int netlist_matrix_solver_direct1_t::vsolve_non_dynamic() |
| 570 | 603 | { |
| 571 | 604 | |
| 572 | | netlist_analog_net_t *net = m_nets[0].m_net; |
| 605 | netlist_analog_net_t *net = m_nets[0]; |
| 573 | 606 | this->build_LE(); |
| 574 | 607 | //NL_VERBOSE_OUT(("%f %f\n", new_val, m_RHS[0] / m_A[0][0]); |
| 575 | 608 | |
| r30707 | r30708 | |
| 646 | 679 | |
| 647 | 680 | for (int k = 0; k < iN; k++) |
| 648 | 681 | { |
| 649 | | new_v[k] = this->m_nets[k].m_net->m_cur_Analog; |
| 682 | new_v[k] = this->m_nets[k]->m_cur_Analog; |
| 650 | 683 | } |
| 651 | 684 | do { |
| 652 | 685 | resched = false; |
| r30707 | r30708 | |
| 708 | 741 | |
| 709 | 742 | for (int k = 0; k < iN; k++) |
| 710 | 743 | { |
| 711 | | this->m_nets[k].m_net->m_new_Analog = this->m_nets[k].m_net->m_cur_Analog; |
| 744 | this->m_nets[k]->m_new_Analog = this->m_nets[k]->m_cur_Analog; |
| 712 | 745 | } |
| 713 | 746 | |
| 714 | 747 | for (int k = 0; k < iN; k++) |
| r30707 | r30708 | |
| 717 | 750 | double gabs_t = 0.0; |
| 718 | 751 | double RHS_t = 0.0; |
| 719 | 752 | |
| 720 | | //const netlist_analog_net_t &net = *this->m_nets[k]; |
| 721 | | const netlist_terminal_t::list_t &terms = this->m_nets[k].m_terms; |
| 722 | | const netlist_terminal_t::list_t &rails = this->m_nets[k].m_rails; |
| 753 | const typename netlist_matrix_solver_direct_t<m_N, _storage_N>::xlist_t &terms = this->m_terms[k]; |
| 754 | const typename netlist_matrix_solver_direct_t<m_N, _storage_N>::xlist_t &rails = this->m_rails[k]; |
| 723 | 755 | const int term_count = terms.count(); |
| 724 | 756 | const int rail_count = rails.count(); |
| 725 | 757 | |
| 726 | 758 | for (int i = 0; i < rail_count; i++) |
| 727 | 759 | { |
| 728 | | gtot_t += rails[i]->m_gt; |
| 729 | | gabs_t += fabs(rails[i]->m_go); |
| 730 | | RHS_t += rails[i]->m_Idr; |
| 731 | | RHS_t += rails[i]->m_go * rails[i]->m_otherterm->net().as_analog().Q_Analog(); |
| 760 | const netlist_terminal_t *rail = rails[i].m_term; |
| 761 | gtot_t += rail->m_gt; |
| 762 | gabs_t += fabs(rail->m_go); |
| 763 | RHS_t += rail->m_Idr; |
| 764 | RHS_t += rail->m_go * rail->m_otherterm->net().as_analog().Q_Analog(); |
| 732 | 765 | } |
| 733 | 766 | |
| 734 | 767 | for (int i = 0; i < term_count; i++) |
| 735 | 768 | { |
| 736 | | gtot_t += terms[i]->m_gt; |
| 737 | | gabs_t += fabs(terms[i]->m_go); |
| 738 | | RHS_t += terms[i]->m_Idr; |
| 769 | const netlist_terminal_t *term = terms[i].m_term; |
| 770 | gtot_t += term->m_gt; |
| 771 | gabs_t += fabs(term->m_go); |
| 772 | RHS_t += term->m_Idr; |
| 739 | 773 | } |
| 740 | 774 | |
| 741 | 775 | gabs_t *= 1.0; |
| r30707 | r30708 | |
| 760 | 794 | |
| 761 | 795 | for (int k = 0; k < iN; k++) |
| 762 | 796 | { |
| 763 | | netlist_analog_net_t & RESTRICT net = *this->m_nets[k].m_net; |
| 764 | | const netlist_terminal_t::list_t &terms = this->m_nets[k].m_terms; |
| 797 | netlist_analog_net_t & RESTRICT net = *this->m_nets[k]; |
| 798 | const typename netlist_matrix_solver_direct_t<m_N, _storage_N>::xlist_t &terms = this->m_terms[k]; |
| 765 | 799 | const int term_count = terms.count(); |
| 766 | 800 | double Idrive = 0; |
| 767 | 801 | |
| 768 | 802 | for (int i = 0; i < term_count; i++) |
| 769 | | Idrive += terms[i]->m_go * *(terms[i]->m_new_analog_ptr); |
| 803 | Idrive += terms[i].m_term->m_go * *(terms[i].m_term->m_new_analog_ptr); |
| 770 | 804 | |
| 771 | 805 | //double new_val = (net->m_cur_Analog * gabs[k] + iIdr) / (gtot[k]); |
| 772 | 806 | const double new_val = net.m_new_Analog * one_m_w[k] + (Idrive + RHS[k]) * w[k]; |
| r30707 | r30708 | |
| 796 | 830 | this->m_calculations++; |
| 797 | 831 | |
| 798 | 832 | for (int k = 0; k < this->N(); k++) |
| 799 | | this->m_nets[k].m_net->m_cur_Analog = this->m_nets[k].m_net->m_new_Analog; |
| 833 | this->m_nets[k]->m_cur_Analog = this->m_nets[k]->m_new_Analog; |
| 800 | 834 | |
| 801 | 835 | return resched_cnt; |
| 802 | 836 | } |
| r30707 | r30708 | |
| 906 | 940 | } |
| 907 | 941 | } |
| 908 | 942 | |
| 943 | template <int m_N, int _storage_N> |
| 944 | netlist_matrix_solver_t * NETLIB_NAME(solver)::create_solver(const int gs_threshold, const bool use_specific) |
| 945 | { |
| 946 | if (use_specific && m_N == 1) |
| 947 | return new netlist_matrix_solver_direct1_t(); |
| 948 | else if (use_specific && m_N == 2) |
| 949 | return new netlist_matrix_solver_direct2_t(); |
| 950 | else |
| 951 | { |
| 952 | if (_storage_N >= gs_threshold) |
| 953 | return new netlist_matrix_solver_gauss_seidel_t<m_N,_storage_N>(); |
| 954 | else |
| 955 | return new netlist_matrix_solver_direct_t<m_N, _storage_N>(); |
| 956 | } |
| 957 | } |
| 909 | 958 | |
| 910 | 959 | ATTR_COLD void NETLIB_NAME(solver)::post_start() |
| 911 | 960 | { |
| 912 | 961 | netlist_analog_net_t::list_t groups[100]; |
| 913 | 962 | int cur_group = -1; |
| 963 | // FIXME: Turn into parameters ... |
| 964 | const int gs_threshold = 5; |
| 965 | const bool use_specific = true; |
| 914 | 966 | |
| 915 | 967 | m_params.m_accuracy = m_accuracy.Value(); |
| 916 | 968 | m_params.m_gs_loops = m_gs_loops.Value(); |
| r30707 | r30708 | |
| 956 | 1008 | |
| 957 | 1009 | switch (net_count) |
| 958 | 1010 | { |
| 959 | | #if 1 |
| 960 | 1011 | case 1: |
| 961 | | ms = new netlist_matrix_solver_direct1_t(); |
| 1012 | ms = create_solver<1,1>(gs_threshold, use_specific); |
| 962 | 1013 | break; |
| 963 | 1014 | case 2: |
| 964 | | ms = new netlist_matrix_solver_direct2_t(); |
| 1015 | ms = create_solver<2,2>(gs_threshold, use_specific); |
| 965 | 1016 | break; |
| 966 | 1017 | case 3: |
| 967 | | ms = new netlist_matrix_solver_direct_t<3,3>(); |
| 968 | | //ms = new netlist_matrix_solver_gauss_seidel_t<3,3>(); |
| 1018 | ms = create_solver<3,3>(gs_threshold, use_specific); |
| 969 | 1019 | break; |
| 970 | 1020 | case 4: |
| 971 | | ms = new netlist_matrix_solver_direct_t<4,4>(); |
| 972 | | //ms = new netlist_matrix_solver_gauss_seidel_t<4,4>(); |
| 1021 | ms = create_solver<4,4>(gs_threshold, use_specific); |
| 973 | 1022 | break; |
| 974 | 1023 | case 5: |
| 975 | | ms = new netlist_matrix_solver_direct_t<5,5>(); |
| 976 | | //ms = new netlist_matrix_solver_gauss_seidel_t<5,5>(); |
| 1024 | ms = create_solver<5,5>(gs_threshold, use_specific); |
| 977 | 1025 | break; |
| 978 | 1026 | case 6: |
| 979 | | ms = new netlist_matrix_solver_direct_t<6,6>(); |
| 980 | | //ms = new netlist_matrix_solver_gauss_seidel_t<6,6>(); |
| 1027 | ms = create_solver<6,6>(gs_threshold, use_specific); |
| 981 | 1028 | break; |
| 982 | 1029 | case 7: |
| 983 | | //ms = new netlist_matrix_solver_direct_t<6,6>(); |
| 984 | | ms = new netlist_matrix_solver_gauss_seidel_t<7,7>(); |
| 1030 | ms = create_solver<7,7>(gs_threshold, use_specific); |
| 985 | 1031 | break; |
| 986 | 1032 | case 8: |
| 987 | | //ms = new netlist_matrix_solver_direct_t<6,6>(); |
| 988 | | ms = new netlist_matrix_solver_gauss_seidel_t<8,8>(); |
| 1033 | ms = create_solver<8,8>(gs_threshold, use_specific); |
| 989 | 1034 | break; |
| 990 | | #endif |
| 991 | 1035 | default: |
| 992 | 1036 | if (net_count <= 16) |
| 993 | 1037 | { |
| 994 | | //ms = new netlist_matrix_solver_direct_t<0,16>(); |
| 995 | | ms = new netlist_matrix_solver_gauss_seidel_t<0,16>(); |
| 1038 | ms = create_solver<0,16>(gs_threshold, use_specific); |
| 996 | 1039 | } |
| 997 | 1040 | else if (net_count <= 32) |
| 998 | 1041 | { |
| 999 | | //ms = new netlist_matrix_solver_direct_t<0,16>(); |
| 1000 | | ms = new netlist_matrix_solver_gauss_seidel_t<0,32>(); |
| 1042 | ms = create_solver<0,32>(gs_threshold, use_specific); |
| 1001 | 1043 | } |
| 1002 | 1044 | else if (net_count <= 64) |
| 1003 | 1045 | { |
| 1004 | | //ms = new netlist_matrix_solver_direct_t<0,16>(); |
| 1005 | | ms = new netlist_matrix_solver_gauss_seidel_t<0,64>(); |
| 1046 | ms = create_solver<0,64>(gs_threshold, use_specific); |
| 1006 | 1047 | } |
| 1007 | 1048 | else |
| 1008 | 1049 | { |
trunk/src/emu/netlist/analog/nld_solver.h
| r30707 | r30708 | |
| 9 | 9 | #include "../nl_setup.h" |
| 10 | 10 | #include "../nl_base.h" |
| 11 | 11 | |
| 12 | //#define ATTR_ALIGNED(N) __attribute__((aligned(N))) |
| 13 | #define ATTR_ALIGNED(N) ATTR_ALIGN |
| 14 | |
| 12 | 15 | // ---------------------------------------------------------------------------------------- |
| 13 | 16 | // Macros |
| 14 | 17 | // ---------------------------------------------------------------------------------------- |
| r30707 | r30708 | |
| 37 | 40 | netlist_time m_nt_sync_delay; |
| 38 | 41 | }; |
| 39 | 42 | |
| 40 | | class netlist_matrix_solver_t : public netlist_device_t |
| 43 | class ATTR_ALIGNED(64) netlist_matrix_solver_t : public netlist_device_t |
| 41 | 44 | { |
| 42 | 45 | public: |
| 43 | 46 | typedef plinearlist_t<netlist_matrix_solver_t *> list_t; |
| r30707 | r30708 | |
| 67 | 70 | |
| 68 | 71 | protected: |
| 69 | 72 | |
| 70 | | class net_entry |
| 71 | | { |
| 72 | | public: |
| 73 | | net_entry(netlist_analog_net_t *net) : m_net(net) {} |
| 74 | | net_entry() : m_net(NULL) {} |
| 75 | | |
| 76 | | net_entry(const net_entry &rhs) |
| 77 | | { |
| 78 | | m_net = rhs.m_net; |
| 79 | | m_terms = rhs.m_terms; |
| 80 | | m_rails = rhs.m_rails; |
| 81 | | } |
| 82 | | |
| 83 | | net_entry &operator=(const net_entry &rhs) |
| 84 | | { |
| 85 | | m_net = rhs.m_net; |
| 86 | | m_terms = rhs.m_terms; |
| 87 | | m_rails = rhs.m_rails; |
| 88 | | return *this; |
| 89 | | } |
| 90 | | |
| 91 | | netlist_analog_net_t * RESTRICT m_net; |
| 92 | | netlist_terminal_t::list_t m_terms; |
| 93 | | netlist_terminal_t::list_t m_rails; |
| 94 | | }; |
| 95 | | |
| 96 | 73 | ATTR_COLD void setup(netlist_analog_net_t::list_t &nets); |
| 97 | 74 | |
| 98 | 75 | // return true if a reschedule is needed ... |
| 99 | 76 | ATTR_HOT virtual int vsolve_non_dynamic() = 0; |
| 100 | 77 | |
| 78 | ATTR_COLD virtual void add_term(int net_idx, netlist_terminal_t *term) = 0; |
| 101 | 79 | int m_calculations; |
| 102 | 80 | |
| 103 | | plinearlist_t<net_entry> m_nets; |
| 81 | plinearlist_t<netlist_analog_net_t *> m_nets; |
| 104 | 82 | plinearlist_t<netlist_analog_output_t *> m_inps; |
| 105 | 83 | |
| 106 | 84 | private: |
| r30707 | r30708 | |
| 126 | 104 | }; |
| 127 | 105 | |
| 128 | 106 | template <int m_N, int _storage_N> |
| 129 | | class netlist_matrix_solver_direct_t: public netlist_matrix_solver_t |
| 107 | class ATTR_ALIGNED(64) netlist_matrix_solver_direct_t: public netlist_matrix_solver_t |
| 130 | 108 | { |
| 131 | 109 | public: |
| 132 | 110 | |
| 133 | 111 | netlist_matrix_solver_direct_t() |
| 134 | 112 | : netlist_matrix_solver_t() |
| 135 | 113 | , m_dim(0) |
| 136 | | , m_rail_start(0) |
| 137 | 114 | {} |
| 138 | 115 | |
| 139 | 116 | virtual ~netlist_matrix_solver_direct_t() {} |
| r30707 | r30708 | |
| 144 | 121 | ATTR_HOT inline const int N() const { if (m_N == 0) return m_dim; else return m_N; } |
| 145 | 122 | |
| 146 | 123 | protected: |
| 124 | ATTR_COLD virtual void add_term(int net_idx, netlist_terminal_t *term); |
| 125 | |
| 147 | 126 | ATTR_HOT virtual int vsolve_non_dynamic(); |
| 148 | 127 | ATTR_HOT int solve_non_dynamic(); |
| 149 | 128 | ATTR_HOT inline void build_LE(); |
| r30707 | r30708 | |
| 154 | 133 | |
| 155 | 134 | ATTR_HOT virtual double compute_next_timestep(const double); |
| 156 | 135 | |
| 157 | | double m_A[_storage_N][_storage_N]; |
| 158 | | double m_RHS[_storage_N]; |
| 159 | | double m_last_RHS[_storage_N]; // right hand side - contains currents |
| 136 | ATTR_ALIGNED(64) double m_A[_storage_N][_storage_N]; |
| 137 | ATTR_ALIGNED(64) double m_RHS[_storage_N]; |
| 138 | ATTR_ALIGNED(64) double m_last_RHS[_storage_N]; // right hand side - contains currents |
| 160 | 139 | |
| 161 | | struct terms_t{ |
| 140 | struct ATTR_ALIGNED(64) terms_t{ |
| 162 | 141 | |
| 163 | | terms_t(netlist_terminal_t *term, int net_this, int net_other) |
| 164 | | : m_term(term), m_net_this(net_this), m_net_other(net_other) |
| 142 | terms_t(netlist_terminal_t *term, int net_other) |
| 143 | : m_term(term), m_net_other(net_other) |
| 165 | 144 | {} |
| 166 | 145 | terms_t() |
| 167 | | : m_term(NULL), m_net_this(-1), m_net_other(-1) |
| 146 | : m_term(NULL), m_net_other(-1) |
| 168 | 147 | {} |
| 169 | 148 | |
| 170 | | netlist_terminal_t * RESTRICT m_term; |
| 171 | | int m_net_this; |
| 149 | ATTR_ALIGNED(64) netlist_terminal_t ATTR_ALIGNED(64) * RESTRICT m_term; |
| 172 | 150 | int m_net_other; |
| 173 | 151 | }; |
| 174 | 152 | |
| 153 | typedef plinearlist_t<terms_t> xlist_t; |
| 154 | xlist_t m_terms[_storage_N]; |
| 155 | xlist_t m_rails[_storage_N]; |
| 156 | plinearlist_t<double> xx[_storage_N]; |
| 157 | |
| 158 | private: |
| 159 | |
| 175 | 160 | int m_dim; |
| 176 | | int m_rail_start; |
| 177 | | plinearlist_t<terms_t> m_terms; |
| 178 | 161 | }; |
| 179 | 162 | |
| 180 | 163 | template <int m_N, int _storage_N> |
| 181 | | class netlist_matrix_solver_gauss_seidel_t: public netlist_matrix_solver_direct_t<m_N, _storage_N> |
| 164 | class ATTR_ALIGNED(64) netlist_matrix_solver_gauss_seidel_t: public netlist_matrix_solver_direct_t<m_N, _storage_N> |
| 182 | 165 | { |
| 183 | 166 | public: |
| 184 | 167 | |
| r30707 | r30708 | |
| 201 | 184 | |
| 202 | 185 | }; |
| 203 | 186 | |
| 204 | | class netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1> |
| 187 | class ATTR_ALIGNED(64) netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1> |
| 205 | 188 | { |
| 206 | 189 | protected: |
| 207 | 190 | ATTR_HOT int vsolve_non_dynamic(); |
| 208 | 191 | private: |
| 209 | 192 | }; |
| 210 | 193 | |
| 211 | | class netlist_matrix_solver_direct2_t: public netlist_matrix_solver_direct_t<2,2> |
| 194 | class ATTR_ALIGNED(64) netlist_matrix_solver_direct2_t: public netlist_matrix_solver_direct_t<2,2> |
| 212 | 195 | { |
| 213 | 196 | protected: |
| 214 | 197 | ATTR_HOT int vsolve_non_dynamic(); |
| 215 | 198 | private: |
| 216 | 199 | }; |
| 217 | 200 | |
| 218 | | NETLIB_DEVICE_WITH_PARAMS(solver, |
| 219 | | typedef netlist_core_device_t::list_t dev_list_t; |
| 201 | class ATTR_ALIGNED(64) NETLIB_NAME(solver) : public netlist_device_t |
| 202 | { |
| 203 | public: |
| 204 | NETLIB_NAME(solver)() |
| 205 | : netlist_device_t() { } |
| 220 | 206 | |
| 207 | ATTR_COLD virtual ~NETLIB_NAME(solver)(); |
| 208 | |
| 209 | ATTR_COLD void post_start(); |
| 210 | |
| 211 | ATTR_HOT inline double gmin() { return m_gmin.Value(); } |
| 212 | |
| 213 | protected: |
| 214 | ATTR_HOT void update(); |
| 215 | ATTR_HOT void start(); |
| 216 | ATTR_HOT void reset(); |
| 217 | ATTR_HOT void update_param(); |
| 218 | |
| 219 | //typedef netlist_core_device_t::list_t dev_list_t; |
| 220 | |
| 221 | 221 | netlist_ttl_input_t m_fb_step; |
| 222 | 222 | netlist_ttl_output_t m_Q_step; |
| 223 | 223 | |
| r30707 | r30708 | |
| 234 | 234 | netlist_param_int_t m_parallel; |
| 235 | 235 | |
| 236 | 236 | netlist_matrix_solver_t::list_t m_mat_solvers; |
| 237 | | public: |
| 237 | private: |
| 238 | 238 | |
| 239 | | ATTR_COLD virtual ~NETLIB_NAME(solver)(); |
| 239 | netlist_solver_parameters_t m_params; |
| 240 | 240 | |
| 241 | | ATTR_COLD void post_start(); |
| 241 | template <int m_N, int _storage_N> |
| 242 | netlist_matrix_solver_t *create_solver(int gs_threshold, bool use_specific); |
| 243 | }; |
| 242 | 244 | |
| 243 | | ATTR_HOT inline double gmin() { return m_gmin.Value(); } |
| 244 | 245 | |
| 245 | | private: |
| 246 | | netlist_solver_parameters_t m_params; |
| 247 | | ); |
| 248 | 246 | |
| 249 | | |
| 250 | 247 | #endif /* NLD_SOLVER_H_ */ |