diff --git a/src/emu/netlist/analog/nld_bjt.c b/src/emu/netlist/analog/nld_bjt.c index dd536eeadc0..3238f407ae7 100644 --- a/src/emu/netlist/analog/nld_bjt.c +++ b/src/emu/netlist/analog/nld_bjt.c @@ -116,11 +116,11 @@ NETLIB_START(QBJT_switch) NETLIB_UPDATE(QBJT_switch) { if (!m_RB.m_P.net().isRailNet()) - m_RB.m_P.net().as_analog().schedule_solve(); // Basis + m_RB.m_P.schedule_solve(); // Basis else if (!m_RB.m_N.net().isRailNet()) - m_RB.m_N.net().as_analog().schedule_solve(); // Emitter + m_RB.m_N.schedule_solve(); // Emitter else if (!m_RC.m_P.net().isRailNet()) - m_RC.m_P.net().as_analog().schedule_solve(); // Collector + m_RC.m_P.schedule_solve(); // Collector } @@ -176,11 +176,11 @@ NETLIB_START(QBJT_EB) NETLIB_UPDATE(QBJT_EB) { if (!m_D_EB.m_P.net().isRailNet()) - m_D_EB.m_P.net().as_analog().schedule_solve(); // Basis + m_D_EB.m_P.schedule_solve(); // Basis else if (!m_D_EB.m_N.net().isRailNet()) - m_D_EB.m_N.net().as_analog().schedule_solve(); // Emitter + m_D_EB.m_N.schedule_solve(); // Emitter else - m_D_CB.m_N.net().as_analog().schedule_solve(); // Collector + m_D_CB.m_N.schedule_solve(); // Collector } NETLIB_RESET(QBJT_EB) diff --git a/src/emu/netlist/analog/nld_fourterm.c b/src/emu/netlist/analog/nld_fourterm.c index 08ca9c39983..e9c9074ac12 100644 --- a/src/emu/netlist/analog/nld_fourterm.c +++ b/src/emu/netlist/analog/nld_fourterm.c @@ -63,13 +63,13 @@ NETLIB_UPDATE(VCCS) /* only called if connected to a rail net ==> notify the solver to recalculate */ /* Big FIXME ... */ if (!m_IP.net().isRailNet()) - m_IP.net().as_analog().schedule_solve(); + m_IP.schedule_solve(); else if (!m_IN.net().isRailNet()) - m_IN.net().as_analog().schedule_solve(); + m_IN.schedule_solve(); else if (!m_OP.net().isRailNet()) - m_OP.net().as_analog().schedule_solve(); + m_OP.schedule_solve(); else if (!m_ON.net().isRailNet()) - m_ON.net().as_analog().schedule_solve(); + m_ON.schedule_solve(); } // ---------------------------------------------------------------------------------------- diff --git a/src/emu/netlist/analog/nld_solver.h b/src/emu/netlist/analog/nld_solver.h index bcbec7b2b7c..30edb99f089 100644 --- a/src/emu/netlist/analog/nld_solver.h +++ b/src/emu/netlist/analog/nld_solver.h @@ -205,6 +205,10 @@ public: ATTR_HOT inline bool is_timestep() { return m_step_devices.count() > 0; } ATTR_HOT void update_forced(); + ATTR_HOT inline void update_after(const netlist_time after) + { + m_Q_sync.net().reschedule_in_queue(after); + } /* netdevice functions */ ATTR_HOT virtual void update(); diff --git a/src/emu/netlist/analog/nld_twoterm.c b/src/emu/netlist/analog/nld_twoterm.c index 4b3652fce0b..9321599f61f 100644 --- a/src/emu/netlist/analog/nld_twoterm.c +++ b/src/emu/netlist/analog/nld_twoterm.c @@ -60,9 +60,9 @@ NETLIB_UPDATE(twoterm) /* only called if connected to a rail net ==> notify the solver to recalculate */ /* we only need to call the non-rail terminal */ if (!m_P.net().isRailNet()) - m_P.net().as_analog().schedule_solve(); + m_P.schedule_solve(); else - m_N.net().as_analog().schedule_solve(); + m_N.schedule_solve(); } // ---------------------------------------------------------------------------------------- diff --git a/src/emu/netlist/devices/nld_system.c b/src/emu/netlist/devices/nld_system.c index 01a0b8648cd..f89f9cdede5 100644 --- a/src/emu/netlist/devices/nld_system.c +++ b/src/emu/netlist/devices/nld_system.c @@ -87,12 +87,51 @@ NETLIB_UPDATE_PARAM(analog_input) // nld_d_to_a_proxy // ---------------------------------------------------------------------------------------- +ATTR_COLD void nld_d_to_a_proxy::start() +{ + nld_base_d_to_a_proxy::start(); + + register_sub(m_RV, "RV"); + register_terminal("1", m_RV.m_P); + register_terminal("2", m_RV.m_N); + + register_output("_Q", m_Q); + register_subalias("Q", m_RV.m_P); + + connect(m_RV.m_N, m_Q); + m_Q.initial(0.0); +} + +ATTR_COLD void nld_d_to_a_proxy::reset() +{ + m_RV.do_reset(); +} + +ATTR_COLD netlist_core_terminal_t &nld_d_to_a_proxy::out() +{ + return m_RV.m_P; +} + ATTR_HOT ATTR_ALIGN void nld_d_to_a_proxy::update() { - double R = INPLOGIC(m_I) ? m_family_desc->m_R_high : m_family_desc->m_R_low; - double V = INPLOGIC(m_I) ? m_family_desc->m_high_V : m_family_desc->m_low_V; + const int state = INPLOGIC(m_I); + if (state != m_last_state) + { + m_last_state = state; + const double R = state ? m_family_desc->m_R_high : m_family_desc->m_R_low; + const double V = state ? m_family_desc->m_high_V : m_family_desc->m_low_V; - m_R.update_dev(); - OUTANALOG(m_Q, V); - m_R.set_R(R); + // We only need to update the net first if this is a time stepping net + if (m_RV.m_P.net().as_analog().solver()->is_timestep()) + { + m_RV.update_dev(); + m_RV.set(1.0 / R, V, 0.0); + m_RV.m_P.schedule_after(NLTIME_FROM_NS(1)); + } + else + { + m_RV.set(1.0 / R, V, 0.0); + m_RV.update_dev(); + } + } } diff --git a/src/emu/netlist/devices/nld_system.h b/src/emu/netlist/devices/nld_system.h index 78282ba4f73..db07cb01f64 100644 --- a/src/emu/netlist/devices/nld_system.h +++ b/src/emu/netlist/devices/nld_system.h @@ -225,39 +225,27 @@ class nld_d_to_a_proxy : public nld_base_d_to_a_proxy { public: ATTR_COLD nld_d_to_a_proxy(netlist_output_t &out_proxied) - : nld_base_d_to_a_proxy(out_proxied) + : nld_base_d_to_a_proxy(out_proxied) + , m_RV(TWOTERM) + , m_last_state(-1) { } ATTR_COLD virtual ~nld_d_to_a_proxy() {} protected: - ATTR_COLD void start() - { - nld_base_d_to_a_proxy::start(); + ATTR_COLD virtual void start(); - register_sub(m_R, "R"); - register_output("_Q", m_Q); - register_subalias("Q", m_R.m_P); + ATTR_COLD virtual void reset(); - connect(m_R.m_N, m_Q); - } - - ATTR_COLD void reset() - { - m_R.do_reset(); - } - - ATTR_COLD virtual netlist_core_terminal_t &out() - { - return m_R.m_P; - } + ATTR_COLD virtual netlist_core_terminal_t &out(); ATTR_HOT ATTR_ALIGN void update(); private: netlist_analog_output_t m_Q; - nld_R_base m_R; + nld_twoterm m_RV; + int m_last_state; }; #endif diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c index 28e72b37993..e45204a5fc7 100644 --- a/src/emu/netlist/nl_base.c +++ b/src/emu/netlist/nl_base.c @@ -356,7 +356,7 @@ ATTR_HOT ATTR_ALIGN const netlist_sig_t netlist_core_device_t::INPLOGIC_PASSIVE( // ---------------------------------------------------------------------------------------- -// net_device_t +// netlist_device_t // ---------------------------------------------------------------------------------------- netlist_device_t::netlist_device_t() @@ -448,7 +448,7 @@ template ATTR_COLD void netlist_device_t::register_param(const pstring &sname, n // ---------------------------------------------------------------------------------------- -// net_net_t +// netlist_net_t // ---------------------------------------------------------------------------------------- ATTR_COLD netlist_net_t::netlist_net_t(const family_t afamily) @@ -471,19 +471,11 @@ ATTR_COLD netlist_net_t::~netlist_net_t() netlist().remove_save_items(this); } -ATTR_COLD netlist_analog_net_t::netlist_analog_net_t() - : netlist_net_t(ANALOG) - , m_DD_n_m_1(0.0) - , m_h_n_m_1(1e-6) - , m_solver(NULL) +ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname) { -}; - -ATTR_COLD netlist_logic_net_t::netlist_logic_net_t() - : netlist_net_t(LOGIC) -{ -}; - + netlist_object_t::init_object(nl, aname); + nl.m_nets.add(this); +} ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term) { @@ -530,6 +522,12 @@ ATTR_HOT void netlist_net_t::dec_active(netlist_core_terminal_t &term) } } +ATTR_COLD void netlist_net_t::register_railterminal(netlist_output_t &mr) +{ + assert(m_railterminal == NULL); + m_railterminal = &mr; +} + ATTR_COLD void netlist_net_t::rebuild_list() { /* rebuild m_list */ @@ -540,6 +538,64 @@ ATTR_COLD void netlist_net_t::rebuild_list() m_list_active.add(*m_core_terms[i]); } +ATTR_COLD void netlist_net_t::save_register() +{ + save(NAME(m_time)); + save(NAME(m_active)); + save(NAME(m_in_queue)); + save(NAME(m_last_Analog)); + save(NAME(m_cur_Analog)); + save(NAME(m_last_Q)); + save(NAME(m_cur_Q)); + save(NAME(m_new_Q)); + netlist_object_t::save_register(); +} + +ATTR_HOT ATTR_ALIGN static inline void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) +{ + if ((inp->state() & mask) != 0) + { + netlist_core_device_t &netdev = inp->netdev(); + begin_timing(netdev.total_time); + inc_stat(netdev.stat_count); + netdev.update_dev(); + end_timing(netdev().total_time); + } +} + +ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs() +{ + //assert(m_num_cons != 0); + assert(this->isRailNet()); + + const UINT32 masks[4] = { 1, 5, 3, 1 }; + const UINT32 mask = masks[ (m_last_Q << 1) | m_new_Q ]; + netlist_core_terminal_t *p = m_list_active.first(); + + m_in_queue = 2; /* mark as taken ... */ + m_cur_Q = m_new_Q; + + switch (m_active) + { + case 2: + update_dev(p, mask); + p = m_list_active.next(p); + if (p == NULL) break; + case 1: + update_dev(p, mask); + break; + default: + while (p != NULL) + { + update_dev(p, mask); + p = m_list_active.next(p); + } + break; + } + m_last_Q = m_cur_Q; + m_last_Analog = m_cur_Analog; +} + ATTR_COLD void netlist_net_t::reset() { m_time = netlist_time::zero; @@ -566,51 +622,24 @@ ATTR_COLD void netlist_net_t::reset() m_active++; } -ATTR_COLD void netlist_logic_net_t::reset() +ATTR_COLD void netlist_net_t::register_con(netlist_core_terminal_t &terminal) { - netlist_net_t::reset(); + terminal.set_net(*this); + + m_core_terms.add(&terminal); + + if (terminal.state() != netlist_input_t::STATE_INP_PASSIVE) + m_active++; } -ATTR_COLD void netlist_analog_net_t::reset() +ATTR_COLD void netlist_net_t::move_connections(netlist_net_t *dest_net) { - netlist_net_t::reset(); -} - -ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname) -{ - netlist_object_t::init_object(nl, aname); - nl.m_nets.add(this); -} - -ATTR_COLD void netlist_net_t::save_register() -{ - save(NAME(m_time)); - save(NAME(m_active)); - save(NAME(m_in_queue)); - save(NAME(m_last_Analog)); - save(NAME(m_cur_Analog)); - save(NAME(m_last_Q)); - save(NAME(m_cur_Q)); - save(NAME(m_new_Q)); - netlist_object_t::save_register(); -} - -ATTR_COLD void netlist_analog_net_t::save_register() -{ - save(NAME(m_DD_n_m_1)); - save(NAME(m_h_n_m_1)); - netlist_net_t::save_register(); -} - -ATTR_COLD void netlist_logic_net_t::save_register() -{ - netlist_net_t::save_register(); -} - -ATTR_COLD void netlist_net_t::register_railterminal(netlist_output_t &mr) -{ - assert(m_railterminal == NULL); - m_railterminal = &mr; + for (int i = 0; i < m_core_terms.count(); i++) + { + netlist_core_terminal_t *p = m_core_terms[i]; + dest_net->register_con(*p); + } + m_core_terms.clear(); // FIXME: othernet needs to be free'd from memory } ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet) @@ -639,14 +668,48 @@ ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet) } } -ATTR_COLD void netlist_net_t::move_connections(netlist_net_t *dest_net) +// ---------------------------------------------------------------------------------------- +// netlist_logic_net_t +// ---------------------------------------------------------------------------------------- + +ATTR_COLD netlist_logic_net_t::netlist_logic_net_t() + : netlist_net_t(LOGIC) { - for (int i = 0; i < m_core_terms.count(); i++) - { - netlist_core_terminal_t *p = m_core_terms[i]; - dest_net->register_con(*p); - } - m_core_terms.clear(); // FIXME: othernet needs to be free'd from memory +}; + + +ATTR_COLD void netlist_logic_net_t::reset() +{ + netlist_net_t::reset(); +} + +ATTR_COLD void netlist_logic_net_t::save_register() +{ + netlist_net_t::save_register(); +} + +// ---------------------------------------------------------------------------------------- +// netlist_analog_net_t +// ---------------------------------------------------------------------------------------- + +ATTR_COLD netlist_analog_net_t::netlist_analog_net_t() + : netlist_net_t(ANALOG) + , m_DD_n_m_1(0.0) + , m_h_n_m_1(1e-6) + , m_solver(NULL) +{ +}; + +ATTR_COLD void netlist_analog_net_t::reset() +{ + netlist_net_t::reset(); +} + +ATTR_COLD void netlist_analog_net_t::save_register() +{ + save(NAME(m_DD_n_m_1)); + save(NAME(m_h_n_m_1)); + netlist_net_t::save_register(); } ATTR_COLD bool netlist_analog_net_t::already_processed(list_t *groups, int cur_group) @@ -684,70 +747,8 @@ ATTR_COLD void netlist_analog_net_t::process_net(list_t *groups, int &cur_group) } - -ATTR_COLD void netlist_net_t::register_con(netlist_core_terminal_t &terminal) -{ - terminal.set_net(*this); - - m_core_terms.add(&terminal); - - if (terminal.state() != netlist_input_t::STATE_INP_PASSIVE) - m_active++; -} - -ATTR_HOT ATTR_ALIGN static inline void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) -{ - if ((inp->state() & mask) != 0) - { - netlist_core_device_t &netdev = inp->netdev(); - begin_timing(netdev.total_time); - inc_stat(netdev.stat_count); - netdev.update_dev(); - end_timing(netdev().total_time); - } -} - -ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs() -{ - //assert(m_num_cons != 0); - assert(this->isRailNet()); - - const UINT32 masks[4] = { 1, 5, 3, 1 }; - const UINT32 mask = masks[ (m_last_Q << 1) | m_new_Q ]; - netlist_core_terminal_t *p = m_list_active.first(); - - m_in_queue = 2; /* mark as taken ... */ - m_cur_Q = m_new_Q; - - switch (m_active) - { - case 2: - update_dev(p, mask); - p = m_list_active.next(p); - if (p == NULL) break; - case 1: - update_dev(p, mask); - break; - default: - while (p != NULL) - { - update_dev(p, mask); - p = m_list_active.next(p); - } - break; - } - m_last_Q = m_cur_Q; - m_last_Analog = m_cur_Analog; -} - -ATTR_HOT void netlist_analog_net_t::schedule_solve() -{ - if (m_solver != NULL) - m_solver->update_forced(); -} - // ---------------------------------------------------------------------------------------- -// netlist_terminal_t +// netlist_core_terminal_t // ---------------------------------------------------------------------------------------- ATTR_COLD netlist_core_terminal_t::netlist_core_terminal_t(const type_t atype, const family_t afamily) @@ -759,6 +760,15 @@ ATTR_COLD netlist_core_terminal_t::netlist_core_terminal_t(const type_t atype, c { } +ATTR_COLD void netlist_core_terminal_t::set_net(netlist_net_t &anet) +{ + m_net = &anet; +} + +// ---------------------------------------------------------------------------------------- +// netlist_terminal_t +// ---------------------------------------------------------------------------------------- + ATTR_COLD netlist_terminal_t::netlist_terminal_t() : netlist_core_terminal_t(TERMINAL, ANALOG) , m_Idr1(NULL) @@ -768,6 +778,15 @@ ATTR_COLD netlist_terminal_t::netlist_terminal_t() { } +ATTR_HOT void netlist_terminal_t::schedule_solve() +{ + net().as_analog().solver()->update_forced(); +} + +ATTR_HOT void netlist_terminal_t::schedule_after(const netlist_time &after) +{ + net().as_analog().solver()->update_after(after); +} ATTR_COLD void netlist_terminal_t::reset() { @@ -787,11 +806,6 @@ ATTR_COLD void netlist_terminal_t::save_register() } -ATTR_COLD void netlist_core_terminal_t::set_net(netlist_net_t &anet) -{ - m_net = &anet; -} - // ---------------------------------------------------------------------------------------- // net_input_t // ---------------------------------------------------------------------------------------- diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h index 6912be0a820..00c5cecb190 100644 --- a/src/emu/netlist/nl_base.h +++ b/src/emu/netlist/nl_base.h @@ -296,18 +296,19 @@ public: }; enum family_t { // Terminal families - LOGIC = 1, - ANALOG = 2, + LOGIC, + ANALOG, // Device families - GENERIC = 3, // <== devices usually fall into this category - RESISTOR = 4, // Resistor - CAPACITOR = 5, // Capacitor - DIODE = 6, // Diode - BJT_SWITCH = 7, // BJT(Switch) - VCVS = 8, // Voltage controlled voltage source - VCCS = 9, // Voltage controlled current source - BJT_EB = 10, // BJT(Ebers-Moll) - GND = 11, // GND device + GENERIC, // <== devices usually fall into this category + TWOTERM, // Generic twoterm ... + RESISTOR, // Resistor + CAPACITOR, // Capacitor + DIODE, // Diode + BJT_EB, // BJT(Ebers-Moll) + BJT_SWITCH, // BJT(Switch) + VCVS, // Voltage controlled voltage source + VCCS, // Voltage controlled current source + GND, // GND device }; ATTR_COLD netlist_object_t(const type_t atype, const family_t afamily); @@ -458,6 +459,8 @@ public: set_ptr(m_gt1, GT); } + ATTR_HOT void schedule_solve(); + ATTR_HOT void schedule_after(const netlist_time &after); netlist_terminal_t *m_otherterm; @@ -715,7 +718,7 @@ public: return m_cur_Analog; } - ATTR_HOT void schedule_solve(); + ATTR_HOT inline netlist_matrix_solver_t *solver() { return m_solver; } ATTR_COLD bool already_processed(list_t *groups, int cur_group); ATTR_COLD void process_net(list_t *groups, int &cur_group); @@ -734,8 +737,6 @@ public: //FIXME: needed by current solver code netlist_matrix_solver_t *m_solver; -// netlist_terminal_t::list_t m_terms; -// netlist_terminal_t::list_t m_rails; }; // ---------------------------------------------------------------------------------------- @@ -964,7 +965,12 @@ public: out.set_Q(val, delay); } - ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const + ATTR_HOT inline bool INP_CHANGED(const netlist_logic_input_t &inp) const + { + return (inp.last_Q() != inp.Q()); + } + + ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const { return ((inp.last_Q() & !inp.Q()) == 1); }