trunk/src/emu/netlist/devices/nld_system.c
| r30981 | r30982 | |
| 87 | 87 | // nld_d_to_a_proxy |
| 88 | 88 | // ---------------------------------------------------------------------------------------- |
| 89 | 89 | |
| 90 | ATTR_COLD void nld_d_to_a_proxy::start() |
| 91 | { |
| 92 | nld_base_d_to_a_proxy::start(); |
| 93 | |
| 94 | register_sub(m_RV, "RV"); |
| 95 | register_terminal("1", m_RV.m_P); |
| 96 | register_terminal("2", m_RV.m_N); |
| 97 | |
| 98 | register_output("_Q", m_Q); |
| 99 | register_subalias("Q", m_RV.m_P); |
| 100 | |
| 101 | connect(m_RV.m_N, m_Q); |
| 102 | m_Q.initial(0.0); |
| 103 | } |
| 104 | |
| 105 | ATTR_COLD void nld_d_to_a_proxy::reset() |
| 106 | { |
| 107 | m_RV.do_reset(); |
| 108 | } |
| 109 | |
| 110 | ATTR_COLD netlist_core_terminal_t &nld_d_to_a_proxy::out() |
| 111 | { |
| 112 | return m_RV.m_P; |
| 113 | } |
| 114 | |
| 90 | 115 | ATTR_HOT ATTR_ALIGN void nld_d_to_a_proxy::update() |
| 91 | 116 | { |
| 92 | | double R = INPLOGIC(m_I) ? m_family_desc->m_R_high : m_family_desc->m_R_low; |
| 93 | | double V = INPLOGIC(m_I) ? m_family_desc->m_high_V : m_family_desc->m_low_V; |
| 117 | const int state = INPLOGIC(m_I); |
| 118 | if (state != m_last_state) |
| 119 | { |
| 120 | m_last_state = state; |
| 121 | const double R = state ? m_family_desc->m_R_high : m_family_desc->m_R_low; |
| 122 | const double V = state ? m_family_desc->m_high_V : m_family_desc->m_low_V; |
| 94 | 123 | |
| 95 | | m_R.update_dev(); |
| 96 | | OUTANALOG(m_Q, V); |
| 97 | | m_R.set_R(R); |
| 124 | // We only need to update the net first if this is a time stepping net |
| 125 | if (m_RV.m_P.net().as_analog().solver()->is_timestep()) |
| 126 | { |
| 127 | m_RV.update_dev(); |
| 128 | m_RV.set(1.0 / R, V, 0.0); |
| 129 | m_RV.m_P.schedule_after(NLTIME_FROM_NS(1)); |
| 130 | } |
| 131 | else |
| 132 | { |
| 133 | m_RV.set(1.0 / R, V, 0.0); |
| 134 | m_RV.update_dev(); |
| 135 | } |
| 136 | } |
| 98 | 137 | } |
trunk/src/emu/netlist/nl_base.c
| r30981 | r30982 | |
| 356 | 356 | |
| 357 | 357 | |
| 358 | 358 | // ---------------------------------------------------------------------------------------- |
| 359 | | // net_device_t |
| 359 | // netlist_device_t |
| 360 | 360 | // ---------------------------------------------------------------------------------------- |
| 361 | 361 | |
| 362 | 362 | netlist_device_t::netlist_device_t() |
| r30981 | r30982 | |
| 448 | 448 | |
| 449 | 449 | |
| 450 | 450 | // ---------------------------------------------------------------------------------------- |
| 451 | | // net_net_t |
| 451 | // netlist_net_t |
| 452 | 452 | // ---------------------------------------------------------------------------------------- |
| 453 | 453 | |
| 454 | 454 | ATTR_COLD netlist_net_t::netlist_net_t(const family_t afamily) |
| r30981 | r30982 | |
| 471 | 471 | netlist().remove_save_items(this); |
| 472 | 472 | } |
| 473 | 473 | |
| 474 | | ATTR_COLD netlist_analog_net_t::netlist_analog_net_t() |
| 475 | | : netlist_net_t(ANALOG) |
| 476 | | , m_DD_n_m_1(0.0) |
| 477 | | , m_h_n_m_1(1e-6) |
| 478 | | , m_solver(NULL) |
| 474 | ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname) |
| 479 | 475 | { |
| 480 | | }; |
| 476 | netlist_object_t::init_object(nl, aname); |
| 477 | nl.m_nets.add(this); |
| 478 | } |
| 481 | 479 | |
| 482 | | ATTR_COLD netlist_logic_net_t::netlist_logic_net_t() |
| 483 | | : netlist_net_t(LOGIC) |
| 484 | | { |
| 485 | | }; |
| 486 | | |
| 487 | | |
| 488 | 480 | ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term) |
| 489 | 481 | { |
| 490 | 482 | m_active++; |
| r30981 | r30982 | |
| 530 | 522 | } |
| 531 | 523 | } |
| 532 | 524 | |
| 525 | ATTR_COLD void netlist_net_t::register_railterminal(netlist_output_t &mr) |
| 526 | { |
| 527 | assert(m_railterminal == NULL); |
| 528 | m_railterminal = &mr; |
| 529 | } |
| 530 | |
| 533 | 531 | ATTR_COLD void netlist_net_t::rebuild_list() |
| 534 | 532 | { |
| 535 | 533 | /* rebuild m_list */ |
| r30981 | r30982 | |
| 540 | 538 | m_list_active.add(*m_core_terms[i]); |
| 541 | 539 | } |
| 542 | 540 | |
| 541 | ATTR_COLD void netlist_net_t::save_register() |
| 542 | { |
| 543 | save(NAME(m_time)); |
| 544 | save(NAME(m_active)); |
| 545 | save(NAME(m_in_queue)); |
| 546 | save(NAME(m_last_Analog)); |
| 547 | save(NAME(m_cur_Analog)); |
| 548 | save(NAME(m_last_Q)); |
| 549 | save(NAME(m_cur_Q)); |
| 550 | save(NAME(m_new_Q)); |
| 551 | netlist_object_t::save_register(); |
| 552 | } |
| 553 | |
| 554 | ATTR_HOT ATTR_ALIGN static inline void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) |
| 555 | { |
| 556 | if ((inp->state() & mask) != 0) |
| 557 | { |
| 558 | netlist_core_device_t &netdev = inp->netdev(); |
| 559 | begin_timing(netdev.total_time); |
| 560 | inc_stat(netdev.stat_count); |
| 561 | netdev.update_dev(); |
| 562 | end_timing(netdev().total_time); |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs() |
| 567 | { |
| 568 | //assert(m_num_cons != 0); |
| 569 | assert(this->isRailNet()); |
| 570 | |
| 571 | const UINT32 masks[4] = { 1, 5, 3, 1 }; |
| 572 | const UINT32 mask = masks[ (m_last_Q << 1) | m_new_Q ]; |
| 573 | netlist_core_terminal_t *p = m_list_active.first(); |
| 574 | |
| 575 | m_in_queue = 2; /* mark as taken ... */ |
| 576 | m_cur_Q = m_new_Q; |
| 577 | |
| 578 | switch (m_active) |
| 579 | { |
| 580 | case 2: |
| 581 | update_dev(p, mask); |
| 582 | p = m_list_active.next(p); |
| 583 | if (p == NULL) break; |
| 584 | case 1: |
| 585 | update_dev(p, mask); |
| 586 | break; |
| 587 | default: |
| 588 | while (p != NULL) |
| 589 | { |
| 590 | update_dev(p, mask); |
| 591 | p = m_list_active.next(p); |
| 592 | } |
| 593 | break; |
| 594 | } |
| 595 | m_last_Q = m_cur_Q; |
| 596 | m_last_Analog = m_cur_Analog; |
| 597 | } |
| 598 | |
| 543 | 599 | ATTR_COLD void netlist_net_t::reset() |
| 544 | 600 | { |
| 545 | 601 | m_time = netlist_time::zero; |
| r30981 | r30982 | |
| 566 | 622 | m_active++; |
| 567 | 623 | } |
| 568 | 624 | |
| 569 | | ATTR_COLD void netlist_logic_net_t::reset() |
| 625 | ATTR_COLD void netlist_net_t::register_con(netlist_core_terminal_t &terminal) |
| 570 | 626 | { |
| 571 | | netlist_net_t::reset(); |
| 572 | | } |
| 627 | terminal.set_net(*this); |
| 573 | 628 | |
| 574 | | ATTR_COLD void netlist_analog_net_t::reset() |
| 575 | | { |
| 576 | | netlist_net_t::reset(); |
| 577 | | } |
| 629 | m_core_terms.add(&terminal); |
| 578 | 630 | |
| 579 | | ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname) |
| 580 | | { |
| 581 | | netlist_object_t::init_object(nl, aname); |
| 582 | | nl.m_nets.add(this); |
| 631 | if (terminal.state() != netlist_input_t::STATE_INP_PASSIVE) |
| 632 | m_active++; |
| 583 | 633 | } |
| 584 | 634 | |
| 585 | | ATTR_COLD void netlist_net_t::save_register() |
| 635 | ATTR_COLD void netlist_net_t::move_connections(netlist_net_t *dest_net) |
| 586 | 636 | { |
| 587 | | save(NAME(m_time)); |
| 588 | | save(NAME(m_active)); |
| 589 | | save(NAME(m_in_queue)); |
| 590 | | save(NAME(m_last_Analog)); |
| 591 | | save(NAME(m_cur_Analog)); |
| 592 | | save(NAME(m_last_Q)); |
| 593 | | save(NAME(m_cur_Q)); |
| 594 | | save(NAME(m_new_Q)); |
| 595 | | netlist_object_t::save_register(); |
| 637 | for (int i = 0; i < m_core_terms.count(); i++) |
| 638 | { |
| 639 | netlist_core_terminal_t *p = m_core_terms[i]; |
| 640 | dest_net->register_con(*p); |
| 641 | } |
| 642 | m_core_terms.clear(); // FIXME: othernet needs to be free'd from memory |
| 596 | 643 | } |
| 597 | 644 | |
| 598 | | ATTR_COLD void netlist_analog_net_t::save_register() |
| 599 | | { |
| 600 | | save(NAME(m_DD_n_m_1)); |
| 601 | | save(NAME(m_h_n_m_1)); |
| 602 | | netlist_net_t::save_register(); |
| 603 | | } |
| 604 | | |
| 605 | | ATTR_COLD void netlist_logic_net_t::save_register() |
| 606 | | { |
| 607 | | netlist_net_t::save_register(); |
| 608 | | } |
| 609 | | |
| 610 | | ATTR_COLD void netlist_net_t::register_railterminal(netlist_output_t &mr) |
| 611 | | { |
| 612 | | assert(m_railterminal == NULL); |
| 613 | | m_railterminal = &mr; |
| 614 | | } |
| 615 | | |
| 616 | 645 | ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet) |
| 617 | 646 | { |
| 618 | 647 | NL_VERBOSE_OUT(("merging nets ...\n")); |
| r30981 | r30982 | |
| 639 | 668 | } |
| 640 | 669 | } |
| 641 | 670 | |
| 642 | | ATTR_COLD void netlist_net_t::move_connections(netlist_net_t *dest_net) |
| 671 | // ---------------------------------------------------------------------------------------- |
| 672 | // netlist_logic_net_t |
| 673 | // ---------------------------------------------------------------------------------------- |
| 674 | |
| 675 | ATTR_COLD netlist_logic_net_t::netlist_logic_net_t() |
| 676 | : netlist_net_t(LOGIC) |
| 643 | 677 | { |
| 644 | | for (int i = 0; i < m_core_terms.count(); i++) |
| 645 | | { |
| 646 | | netlist_core_terminal_t *p = m_core_terms[i]; |
| 647 | | dest_net->register_con(*p); |
| 648 | | } |
| 649 | | m_core_terms.clear(); // FIXME: othernet needs to be free'd from memory |
| 678 | }; |
| 679 | |
| 680 | |
| 681 | ATTR_COLD void netlist_logic_net_t::reset() |
| 682 | { |
| 683 | netlist_net_t::reset(); |
| 650 | 684 | } |
| 651 | 685 | |
| 686 | ATTR_COLD void netlist_logic_net_t::save_register() |
| 687 | { |
| 688 | netlist_net_t::save_register(); |
| 689 | } |
| 690 | |
| 691 | // ---------------------------------------------------------------------------------------- |
| 692 | // netlist_analog_net_t |
| 693 | // ---------------------------------------------------------------------------------------- |
| 694 | |
| 695 | ATTR_COLD netlist_analog_net_t::netlist_analog_net_t() |
| 696 | : netlist_net_t(ANALOG) |
| 697 | , m_DD_n_m_1(0.0) |
| 698 | , m_h_n_m_1(1e-6) |
| 699 | , m_solver(NULL) |
| 700 | { |
| 701 | }; |
| 702 | |
| 703 | ATTR_COLD void netlist_analog_net_t::reset() |
| 704 | { |
| 705 | netlist_net_t::reset(); |
| 706 | } |
| 707 | |
| 708 | ATTR_COLD void netlist_analog_net_t::save_register() |
| 709 | { |
| 710 | save(NAME(m_DD_n_m_1)); |
| 711 | save(NAME(m_h_n_m_1)); |
| 712 | netlist_net_t::save_register(); |
| 713 | } |
| 714 | |
| 652 | 715 | ATTR_COLD bool netlist_analog_net_t::already_processed(list_t *groups, int cur_group) |
| 653 | 716 | { |
| 654 | 717 | if (isRailNet()) |
| r30981 | r30982 | |
| 684 | 747 | } |
| 685 | 748 | |
| 686 | 749 | |
| 687 | | |
| 688 | | ATTR_COLD void netlist_net_t::register_con(netlist_core_terminal_t &terminal) |
| 689 | | { |
| 690 | | terminal.set_net(*this); |
| 691 | | |
| 692 | | m_core_terms.add(&terminal); |
| 693 | | |
| 694 | | if (terminal.state() != netlist_input_t::STATE_INP_PASSIVE) |
| 695 | | m_active++; |
| 696 | | } |
| 697 | | |
| 698 | | ATTR_HOT ATTR_ALIGN static inline void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) |
| 699 | | { |
| 700 | | if ((inp->state() & mask) != 0) |
| 701 | | { |
| 702 | | netlist_core_device_t &netdev = inp->netdev(); |
| 703 | | begin_timing(netdev.total_time); |
| 704 | | inc_stat(netdev.stat_count); |
| 705 | | netdev.update_dev(); |
| 706 | | end_timing(netdev().total_time); |
| 707 | | } |
| 708 | | } |
| 709 | | |
| 710 | | ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs() |
| 711 | | { |
| 712 | | //assert(m_num_cons != 0); |
| 713 | | assert(this->isRailNet()); |
| 714 | | |
| 715 | | const UINT32 masks[4] = { 1, 5, 3, 1 }; |
| 716 | | const UINT32 mask = masks[ (m_last_Q << 1) | m_new_Q ]; |
| 717 | | netlist_core_terminal_t *p = m_list_active.first(); |
| 718 | | |
| 719 | | m_in_queue = 2; /* mark as taken ... */ |
| 720 | | m_cur_Q = m_new_Q; |
| 721 | | |
| 722 | | switch (m_active) |
| 723 | | { |
| 724 | | case 2: |
| 725 | | update_dev(p, mask); |
| 726 | | p = m_list_active.next(p); |
| 727 | | if (p == NULL) break; |
| 728 | | case 1: |
| 729 | | update_dev(p, mask); |
| 730 | | break; |
| 731 | | default: |
| 732 | | while (p != NULL) |
| 733 | | { |
| 734 | | update_dev(p, mask); |
| 735 | | p = m_list_active.next(p); |
| 736 | | } |
| 737 | | break; |
| 738 | | } |
| 739 | | m_last_Q = m_cur_Q; |
| 740 | | m_last_Analog = m_cur_Analog; |
| 741 | | } |
| 742 | | |
| 743 | | ATTR_HOT void netlist_analog_net_t::schedule_solve() |
| 744 | | { |
| 745 | | if (m_solver != NULL) |
| 746 | | m_solver->update_forced(); |
| 747 | | } |
| 748 | | |
| 749 | 750 | // ---------------------------------------------------------------------------------------- |
| 750 | | // netlist_terminal_t |
| 751 | // netlist_core_terminal_t |
| 751 | 752 | // ---------------------------------------------------------------------------------------- |
| 752 | 753 | |
| 753 | 754 | ATTR_COLD netlist_core_terminal_t::netlist_core_terminal_t(const type_t atype, const family_t afamily) |
| r30981 | r30982 | |
| 759 | 760 | { |
| 760 | 761 | } |
| 761 | 762 | |
| 763 | ATTR_COLD void netlist_core_terminal_t::set_net(netlist_net_t &anet) |
| 764 | { |
| 765 | m_net = &anet; |
| 766 | } |
| 767 | |
| 768 | // ---------------------------------------------------------------------------------------- |
| 769 | // netlist_terminal_t |
| 770 | // ---------------------------------------------------------------------------------------- |
| 771 | |
| 762 | 772 | ATTR_COLD netlist_terminal_t::netlist_terminal_t() |
| 763 | 773 | : netlist_core_terminal_t(TERMINAL, ANALOG) |
| 764 | 774 | , m_Idr1(NULL) |
| r30981 | r30982 | |
| 768 | 778 | { |
| 769 | 779 | } |
| 770 | 780 | |
| 781 | ATTR_HOT void netlist_terminal_t::schedule_solve() |
| 782 | { |
| 783 | net().as_analog().solver()->update_forced(); |
| 784 | } |
| 771 | 785 | |
| 786 | ATTR_HOT void netlist_terminal_t::schedule_after(const netlist_time &after) |
| 787 | { |
| 788 | net().as_analog().solver()->update_after(after); |
| 789 | } |
| 790 | |
| 772 | 791 | ATTR_COLD void netlist_terminal_t::reset() |
| 773 | 792 | { |
| 774 | 793 | //netlist_terminal_core_terminal_t::reset(); |
| r30981 | r30982 | |
| 787 | 806 | } |
| 788 | 807 | |
| 789 | 808 | |
| 790 | | ATTR_COLD void netlist_core_terminal_t::set_net(netlist_net_t &anet) |
| 791 | | { |
| 792 | | m_net = &anet; |
| 793 | | } |
| 794 | | |
| 795 | 809 | // ---------------------------------------------------------------------------------------- |
| 796 | 810 | // net_input_t |
| 797 | 811 | // ---------------------------------------------------------------------------------------- |
trunk/src/emu/netlist/nl_base.h
| r30981 | r30982 | |
| 296 | 296 | }; |
| 297 | 297 | enum family_t { |
| 298 | 298 | // Terminal families |
| 299 | | LOGIC = 1, |
| 300 | | ANALOG = 2, |
| 299 | LOGIC, |
| 300 | ANALOG, |
| 301 | 301 | // Device families |
| 302 | | GENERIC = 3, // <== devices usually fall into this category |
| 303 | | RESISTOR = 4, // Resistor |
| 304 | | CAPACITOR = 5, // Capacitor |
| 305 | | DIODE = 6, // Diode |
| 306 | | BJT_SWITCH = 7, // BJT(Switch) |
| 307 | | VCVS = 8, // Voltage controlled voltage source |
| 308 | | VCCS = 9, // Voltage controlled current source |
| 309 | | BJT_EB = 10, // BJT(Ebers-Moll) |
| 310 | | GND = 11, // GND device |
| 302 | GENERIC, // <== devices usually fall into this category |
| 303 | TWOTERM, // Generic twoterm ... |
| 304 | RESISTOR, // Resistor |
| 305 | CAPACITOR, // Capacitor |
| 306 | DIODE, // Diode |
| 307 | BJT_EB, // BJT(Ebers-Moll) |
| 308 | BJT_SWITCH, // BJT(Switch) |
| 309 | VCVS, // Voltage controlled voltage source |
| 310 | VCCS, // Voltage controlled current source |
| 311 | GND, // GND device |
| 311 | 312 | }; |
| 312 | 313 | |
| 313 | 314 | ATTR_COLD netlist_object_t(const type_t atype, const family_t afamily); |
| r30981 | r30982 | |
| 458 | 459 | set_ptr(m_gt1, GT); |
| 459 | 460 | } |
| 460 | 461 | |
| 462 | ATTR_HOT void schedule_solve(); |
| 463 | ATTR_HOT void schedule_after(const netlist_time &after); |
| 461 | 464 | |
| 462 | 465 | netlist_terminal_t *m_otherterm; |
| 463 | 466 | |
| r30981 | r30982 | |
| 715 | 718 | return m_cur_Analog; |
| 716 | 719 | } |
| 717 | 720 | |
| 718 | | ATTR_HOT void schedule_solve(); |
| 721 | ATTR_HOT inline netlist_matrix_solver_t *solver() { return m_solver; } |
| 719 | 722 | |
| 720 | 723 | ATTR_COLD bool already_processed(list_t *groups, int cur_group); |
| 721 | 724 | ATTR_COLD void process_net(list_t *groups, int &cur_group); |
| r30981 | r30982 | |
| 734 | 737 | |
| 735 | 738 | //FIXME: needed by current solver code |
| 736 | 739 | netlist_matrix_solver_t *m_solver; |
| 737 | | // netlist_terminal_t::list_t m_terms; |
| 738 | | // netlist_terminal_t::list_t m_rails; |
| 739 | 740 | }; |
| 740 | 741 | |
| 741 | 742 | // ---------------------------------------------------------------------------------------- |
| r30981 | r30982 | |
| 964 | 965 | out.set_Q(val, delay); |
| 965 | 966 | } |
| 966 | 967 | |
| 967 | | ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const |
| 968 | ATTR_HOT inline bool INP_CHANGED(const netlist_logic_input_t &inp) const |
| 969 | { |
| 970 | return (inp.last_Q() != inp.Q()); |
| 971 | } |
| 972 | |
| 973 | ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const |
| 968 | 974 | { |
| 969 | 975 | return ((inp.last_Q() & !inp.Q()) == 1); |
| 970 | 976 | } |