diff --git a/src/emu/netlist/devices/nld_system.c b/src/emu/netlist/devices/nld_system.c index a1d53629495..3ae4a4aeb02 100644 --- a/src/emu/netlist/devices/nld_system.c +++ b/src/emu/netlist/devices/nld_system.c @@ -129,14 +129,26 @@ NETLIB_FUNC_VOID(solver, post_start, ()) switch (p->type()) { case netlist_terminal_t::TERMINAL: - m_terms.add(p); + switch (p->netdev().family()) + { + case CAPACITOR: + if (!m_steps.contains(&p->netdev())) + m_steps.add(&p->netdev()); + break; + case DIODE: + case BJT_SWITCH: + if (!m_dynamic.contains(&p->netdev())) + m_dynamic.add(&p->netdev()); + break; + default: + break; + } + pn->object()->m_terms.add(static_cast(p)); NL_VERBOSE_OUT(("Added terminal\n")); - if (p->netdev().isFamily(CAPACITOR)) - if (!m_steps.contains(&p->netdev())) - m_steps.add(&p->netdev()); break; case netlist_terminal_t::INPUT: - m_inps.add(p); + if (!m_inps.contains(&p->netdev())) + m_inps.add(&p->netdev()); NL_VERBOSE_OUT(("Added input\n")); break; default: @@ -174,6 +186,10 @@ NETLIB_UPDATE(solver) p->object()->step_time(delta.as_double()); } do { + /* update all non-linear devices */ + for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p)) + p->object()->update_terminals(); + resched = false; for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn)) @@ -183,39 +199,11 @@ NETLIB_UPDATE(solver) double gtot = 0; double iIdr = 0; - for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next) + for (netlist_net_t::terminal_list_t::entry_t *e = net->m_terms.first(); e != NULL; e = net->m_terms.next(e)) { - if (p->isType(netlist_core_terminal_t::TERMINAL)) - { - netlist_terminal_t *pt = static_cast(p); - netlist_core_device_t &dev = pt->netdev(); -#if 0 - switch (pt->family()) - { - case RESISTOR: - static_cast(dev).update_terminals(); - break; - case CAPACITOR: - static_cast(dev).update_terminals(); - break; -#if 1 - case DIODE: - static_cast(dev).update_terminals(); - break; - case BJT_SWITCH_NPN: - static_cast(dev).update_terminals(); - break; -#endif - default: - dev.update_terminals(); - break; - } -#else - dev.update_terminals(); -#endif - gtot += pt->m_g; - iIdr += pt->m_Idr; - } + netlist_terminal_t *pt = e->object(); + gtot += pt->m_g; + iIdr += pt->m_Idr + pt->m_g * pt->m_otherterm->net().Q_Analog(); } double new_val = iIdr / gtot; @@ -227,35 +215,19 @@ NETLIB_UPDATE(solver) NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons)); NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val)); } - } while (resched && (resched_cnt < 1)); + } while (resched && (resched_cnt < 5)); //if (resched_cnt >= 5) // printf("rescheduled\n"); if (resched) { schedule(); } -#if 1 else -#endif { /* update all inputs connected */ -#if 0 - for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn)) - { - if (pn->object()->m_cur.Analog != pn->object()->m_last.Analog) - { - for (netlist_core_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next) - { - if (p->isType(netlist_terminal_t::INPUT)) - p->netdev().update_dev(); - } - } - pn->object()->m_last.Analog = pn->object()->m_cur.Analog; - } -#else - for (terminal_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p)) - p->object()->netdev().update_dev(); -#endif + for (dev_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p)) + p->object()->update_dev(); + /* step circuit */ if (!m_Q_step.net().is_queued()) m_Q_step.net().push_to_queue(m_inc); diff --git a/src/emu/netlist/devices/nld_system.h b/src/emu/netlist/devices/nld_system.h index 0ee4f4cf046..515aca7f957 100644 --- a/src/emu/netlist/devices/nld_system.h +++ b/src/emu/netlist/devices/nld_system.h @@ -80,7 +80,6 @@ NETLIB_DEVICE_WITH_PARAMS(clock, // ---------------------------------------------------------------------------------------- NETLIB_DEVICE_WITH_PARAMS(solver, - typedef netlist_list_t terminal_list_t; typedef netlist_list_t net_list_t; typedef netlist_list_t dev_list_t; @@ -98,8 +97,8 @@ NETLIB_DEVICE_WITH_PARAMS(solver, netlist_time m_last_step; netlist_time m_nt_sync_delay; - terminal_list_t m_terms; - terminal_list_t m_inps; + dev_list_t m_dynamic; + dev_list_t m_inps; dev_list_t m_steps; public: diff --git a/src/emu/netlist/devices/nld_twoterm.c b/src/emu/netlist/devices/nld_twoterm.c index 407728a9889..4a432552a11 100644 --- a/src/emu/netlist/devices/nld_twoterm.c +++ b/src/emu/netlist/devices/nld_twoterm.c @@ -10,6 +10,13 @@ // nld_twoterm // ---------------------------------------------------------------------------------------- +ATTR_COLD NETLIB_NAME(twoterm)::NETLIB_NAME(twoterm)(const family_t afamily) : + netlist_device_t(afamily) +{ + m_P.m_otherterm = &m_N; + m_N.m_otherterm = &m_P; +} + NETLIB_START(twoterm) { } @@ -34,7 +41,7 @@ NETLIB_START(R) NETLIB_UPDATE_PARAM(R) { - m_g = 1.0 / m_R.Value(); + set_R(m_R.Value()); } NETLIB_UPDATE(R) @@ -138,7 +145,14 @@ NETLIB_START(QBJT) register_terminal("B", m_B); register_terminal("C", m_C); register_terminal("E", m_E); + register_terminal("EB", m_EB); + m_setup->connect(m_E, m_EB); + + m_B.m_otherterm = &m_EB; + m_EB.m_otherterm = &m_B; + m_C.m_otherterm = &m_E; + m_E.m_otherterm = &m_C; } NETLIB_UPDATE(Q) diff --git a/src/emu/netlist/devices/nld_twoterm.h b/src/emu/netlist/devices/nld_twoterm.h index 21278d54978..504982d8899 100644 --- a/src/emu/netlist/devices/nld_twoterm.h +++ b/src/emu/netlist/devices/nld_twoterm.h @@ -65,26 +65,25 @@ class NETLIB_NAME(twoterm) : public netlist_device_t { public: - ATTR_COLD NETLIB_NAME(twoterm)(const family_t afamily) - : netlist_device_t(afamily), m_g(0.0), m_V(0.0), m_I(0.0) { } + ATTR_COLD NETLIB_NAME(twoterm)(const family_t afamily); netlist_terminal_t m_P; netlist_terminal_t m_N; virtual NETLIB_UPDATE_TERMINALS() { - m_P.m_g = m_N.m_g = m_g; - m_N.m_Idr = (m_P.net().Q_Analog() - m_V) * m_g + m_I; - m_P.m_Idr = (m_N.net().Q_Analog() + m_V) * m_g - m_I; - //printf("%f %f %f %f\n", m_N.m_Idr, m_P.m_Idr, m_N.net().Q_Analog(), m_P.net().Q_Analog()); + } + + ATTR_HOT inline void set(const double G, const double V, const double I) + { + m_P.m_g = m_N.m_g = G; + m_N.m_Idr = ( -V) * G + I; + m_P.m_Idr = ( V) * G - I; } protected: ATTR_COLD virtual void start(); ATTR_HOT ATTR_ALIGN void update(); - double m_g; // conductance - double m_V; // internal voltage source - double m_I; // internal current source private: }; @@ -97,7 +96,7 @@ class NETLIB_NAME(R) : public NETLIB_NAME(twoterm) public: ATTR_COLD NETLIB_NAME(R)() : NETLIB_NAME(twoterm)(RESISTOR) { } - inline void set_R(const double R) { m_g = 1.0 / R; } + inline void set_R(const double R) { set(1.0 / R, 0.0, 0.0); } protected: ATTR_COLD virtual void start(); @@ -119,8 +118,9 @@ public: ATTR_HOT void step_time(const double st) { - m_g = m_P.m_g = m_N.m_g = m_C.Value() / st; - m_I = -m_g * (m_P.net().Q_Analog()- m_N.net().Q_Analog()); + double G = m_C.Value() / st; + double I = -G * (m_P.net().Q_Analog()- m_N.net().Q_Analog()); + set(G, 0.0, I); } protected: @@ -151,12 +151,11 @@ public: const double eVDVt = exp(m_Vd * m_VtInv); const double Id = m_Is * (eVDVt - 1.0); - m_g = m_Is * m_VtInv * eVDVt; + double G = m_Is * m_VtInv * eVDVt; - m_I = (Id - m_Vd * m_g); - //printf("Vd: %f %f %f %f\n", m_Vd, m_g, Id, m_I); + double I = (Id - m_Vd * G); - NETLIB_NAME(twoterm)::update_terminals(); + set(G, 0.0, I); } protected: @@ -235,6 +234,8 @@ public: netlist_terminal_t m_C; netlist_terminal_t m_E; + netlist_terminal_t m_EB; + protected: ATTR_COLD virtual void start(); @@ -247,7 +248,7 @@ class NETLIB_NAME(QBJT_switch) : public NETLIB_NAME(QBJT) { public: ATTR_COLD NETLIB_NAME(QBJT_switch)() - : NETLIB_NAME(QBJT)(_type, BJT_SWITCH_NPN), m_gB(NETLIST_GMIN), m_gC(NETLIST_GMIN), m_V(0.0) { } + : NETLIB_NAME(QBJT)(_type, BJT_SWITCH), m_gB(NETLIST_GMIN), m_gC(NETLIST_GMIN), m_V(0.0) { } NETLIB_UPDATE_TERMINALS() { @@ -257,6 +258,7 @@ public: double vE = m_E.net().Q_Analog(); double vB = m_B.net().Q_Analog(); + //printf("diff %f = %f - %f\n", vB - vE, vB, vE); if (vB - vE < m_V ) { // not conducting @@ -265,21 +267,23 @@ public: gc = NETLIST_GMIN; } - m_B.m_g = m_E.m_g = gb; - m_C.m_g = gc; + m_B.m_g = m_EB.m_g = gb; + m_C.m_g = m_E.m_g = gc; - m_B.m_Idr = (vE + v) * gb; - m_C.m_Idr = (vE) * gc; - m_E.m_Idr = (vB - v) * gb + m_C.net().Q_Analog() * gc; + m_B.m_Idr = ( v) * gb; + m_EB.m_Idr = ( -v) * gb; + m_C.m_Idr = 0.0; + m_E.m_Idr = 0.0; } protected: ATTR_COLD void update_param(); - double m_gB; // conductance - double m_gC; // conductance + double m_gB; // base conductance / switch on + double m_gC; // collector conductance / switch on double m_V; // internal voltage source + private: }; diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h index 76f1423e470..3cf00ce151f 100644 --- a/src/emu/netlist/nl_base.h +++ b/src/emu/netlist/nl_base.h @@ -251,7 +251,7 @@ public: RESISTOR = 4, // Resistor CAPACITOR = 5, // Capacitor DIODE = 6, // Diode - BJT_SWITCH_NPN = 7, // BJT(Switch) + BJT_SWITCH = 7, // BJT(Switch) }; ATTR_COLD netlist_object_t(const type_t atype, const family_t afamily); @@ -346,6 +346,7 @@ public: double m_Idr; // drive current double m_g; // conductance + netlist_terminal_t *m_otherterm; }; @@ -489,6 +490,10 @@ public: ATTR_HOT inline void push_to_queue(const netlist_time &delay); ATTR_HOT bool is_queued() { return m_in_queue == 1; } + // m_terms is only used by analog subsystem + typedef netlist_list_t terminal_list_t; + terminal_list_t m_terms; + protected: /* prohibit use in device functions