diff options
Diffstat (limited to 'src/emu/netlist/analog')
| -rw-r--r-- | src/emu/netlist/analog/nld_bjt.c | 175 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_bjt.h | 234 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_fourterm.c | 95 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_fourterm.h | 56 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_solver.c | 1318 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_solver.h | 112 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_switches.c | 50 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_switches.h | 2 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_twoterm.c | 60 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_twoterm.h | 124 |
10 files changed, 1110 insertions, 1116 deletions
diff --git a/src/emu/netlist/analog/nld_bjt.c b/src/emu/netlist/analog/nld_bjt.c index 93893a97d10..c5feca26848 100644 --- a/src/emu/netlist/analog/nld_bjt.c +++ b/src/emu/netlist/analog/nld_bjt.c @@ -10,28 +10,28 @@ class diode { public: - diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(1.0 / m_VT) {} - diode(const double Is, const double n) - { - m_Is = Is; - m_VT = 0.0258 * n; - m_VT_inv = 1.0 / m_VT; - } - void set(const double Is, const double n) - { - m_Is = Is; - m_VT = 0.0258 * n; - m_VT_inv = 1.0 / m_VT; - } - double I(const double V) const { return m_Is * exp(V * m_VT_inv) - m_Is; } - double g(const double V) const { return m_Is * m_VT_inv * exp(V * m_VT_inv); } - double V(const double I) const { return log(1.0 + I / m_Is) * m_VT; } - double gI(const double I) const { return m_VT_inv * (I + m_Is); } + diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(1.0 / m_VT) {} + diode(const double Is, const double n) + { + m_Is = Is; + m_VT = 0.0258 * n; + m_VT_inv = 1.0 / m_VT; + } + void set(const double Is, const double n) + { + m_Is = Is; + m_VT = 0.0258 * n; + m_VT_inv = 1.0 / m_VT; + } + double I(const double V) const { return m_Is * exp(V * m_VT_inv) - m_Is; } + double g(const double V) const { return m_Is * m_VT_inv * exp(V * m_VT_inv); } + double V(const double I) const { return log(1.0 + I / m_Is) * m_VT; } + double gI(const double I) const { return m_VT_inv * (I + m_Is); } private: - double m_Is; - double m_VT; - double m_VT_inv; + double m_Is; + double m_VT; + double m_VT_inv; }; @@ -42,7 +42,7 @@ private: NETLIB_START(Q) { - register_param("model", m_model, ""); + register_param("model", m_model, ""); } NETLIB_RESET(Q) @@ -60,56 +60,56 @@ NETLIB_UPDATE(Q) NETLIB_START(QBJT_switch) { - NETLIB_NAME(Q)::start(); + NETLIB_NAME(Q)::start(); - register_terminal("B", m_RB.m_P); - register_terminal("E", m_RB.m_N); - register_terminal("C", m_RC.m_P); - register_terminal("_E1", m_RC.m_N); + register_terminal("B", m_RB.m_P); + register_terminal("E", m_RB.m_N); + register_terminal("C", m_RC.m_P); + register_terminal("_E1", m_RC.m_N); - register_terminal("_B1", m_BC_dummy.m_P); - register_terminal("_C1", m_BC_dummy.m_N); + register_terminal("_B1", m_BC_dummy.m_P); + register_terminal("_C1", m_BC_dummy.m_N); - connect(m_RB.m_N, m_RC.m_N); + connect(m_RB.m_N, m_RC.m_N); - connect(m_RB.m_P, m_BC_dummy.m_P); - connect(m_RC.m_P, m_BC_dummy.m_N); + connect(m_RB.m_P, m_BC_dummy.m_P); + connect(m_RC.m_P, m_BC_dummy.m_N); - save(NAME(m_state_on)); + save(NAME(m_state_on)); - m_RB.set(netlist().gmin(), 0.0, 0.0); - m_RC.set(netlist().gmin(), 0.0, 0.0); + m_RB.set(netlist().gmin(), 0.0, 0.0); + m_RC.set(netlist().gmin(), 0.0, 0.0); - m_BC_dummy.set(netlist().gmin(), 0.0, 0.0); + m_BC_dummy.set(netlist().gmin(), 0.0, 0.0); - m_state_on = 0; + m_state_on = 0; - { - double IS = m_model.model_value("IS", 1e-15); - double BF = m_model.model_value("BF", 100); - double NF = m_model.model_value("NF", 1); - //double VJE = m_model.dValue("VJE", 0.75); + { + double IS = m_model.model_value("IS", 1e-15); + double BF = m_model.model_value("BF", 100); + double NF = m_model.model_value("NF", 1); + //double VJE = m_model.dValue("VJE", 0.75); - set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP); + set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP); - double alpha = BF / (1.0 + BF); + double alpha = BF / (1.0 + BF); - diode d(IS, NF); + diode d(IS, NF); - // Assume 5mA Collector current for switch operation + // Assume 5mA Collector current for switch operation - m_V = d.V(0.005 / alpha); + m_V = d.V(0.005 / alpha); - /* Base current is 0.005 / beta - * as a rough estimate, we just scale the conductance down */ + /* Base current is 0.005 / beta + * as a rough estimate, we just scale the conductance down */ - m_gB = d.gI(0.005 / alpha); + m_gB = d.gI(0.005 / alpha); - if (m_gB < netlist().gmin()) - m_gB = netlist().gmin(); - m_gC = d.gI(0.005); // very rough estimate - //printf("%f %f \n", m_V, m_gB); - } + if (m_gB < netlist().gmin()) + m_gB = netlist().gmin(); + m_gC = d.gI(0.005); // very rough estimate + //printf("%f %f \n", m_V, m_gB); + } } @@ -125,56 +125,56 @@ NETLIB_UPDATE_PARAM(QBJT_switch) NETLIB_START(QBJT_EB) { - NETLIB_NAME(Q)::start(); + NETLIB_NAME(Q)::start(); - register_terminal("E", m_D_EB.m_P); // Cathode - register_terminal("B", m_D_EB.m_N); // Anode + register_terminal("E", m_D_EB.m_P); // Cathode + register_terminal("B", m_D_EB.m_N); // Anode - register_terminal("C", m_D_CB.m_P); // Cathode - register_terminal("_B1", m_D_CB.m_N); // Anode + register_terminal("C", m_D_CB.m_P); // Cathode + register_terminal("_B1", m_D_CB.m_N); // Anode - register_terminal("_E1", m_D_EC.m_P); - register_terminal("_C1", m_D_EC.m_N); + register_terminal("_E1", m_D_EC.m_P); + register_terminal("_C1", m_D_EC.m_N); - connect(m_D_EB.m_P, m_D_EC.m_P); - connect(m_D_EB.m_N, m_D_CB.m_N); - connect(m_D_CB.m_P, m_D_EC.m_N); + connect(m_D_EB.m_P, m_D_EC.m_P); + connect(m_D_EB.m_N, m_D_CB.m_N); + connect(m_D_CB.m_P, m_D_EC.m_N); - m_gD_BE.save("m_D_BE", *this); - m_gD_BC.save("m_D_BC", *this); + m_gD_BE.save("m_D_BE", *this); + m_gD_BC.save("m_D_BC", *this); - { - double IS = m_model.model_value("IS", 1e-15); - double BF = m_model.model_value("BF", 100); - double NF = m_model.model_value("NF", 1); - double BR = m_model.model_value("BR", 1); - double NR = m_model.model_value("NR", 1); - //double VJE = m_model.dValue("VJE", 0.75); + { + double IS = m_model.model_value("IS", 1e-15); + double BF = m_model.model_value("BF", 100); + double NF = m_model.model_value("NF", 1); + double BR = m_model.model_value("BR", 1); + double NR = m_model.model_value("NR", 1); + //double VJE = m_model.dValue("VJE", 0.75); - set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP); - //printf("type %s\n", m_model.model_type().cstr()); + set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP); + //printf("type %s\n", m_model.model_type().cstr()); - m_alpha_f = BF / (1.0 + BF); - m_alpha_r = BR / (1.0 + BR); + m_alpha_f = BF / (1.0 + BF); + m_alpha_r = BR / (1.0 + BR); - m_gD_BE.set_param(IS / m_alpha_f, NF, netlist().gmin()); - m_gD_BC.set_param(IS / m_alpha_r, NR, netlist().gmin()); - } + m_gD_BE.set_param(IS / m_alpha_f, NF, netlist().gmin()); + m_gD_BC.set_param(IS / m_alpha_r, NR, netlist().gmin()); + } } NETLIB_UPDATE(QBJT_EB) { - if (!m_D_EB.m_P.net().isRailNet()) - m_D_EB.m_P.net().solve(); // Basis - else if (!m_D_EB.m_N.net().isRailNet()) - m_D_EB.m_N.net().solve(); // Emitter - else - m_D_CB.m_N.net().solve(); // Collector + if (!m_D_EB.m_P.net().isRailNet()) + m_D_EB.m_P.net().solve(); // Basis + else if (!m_D_EB.m_N.net().isRailNet()) + m_D_EB.m_N.net().solve(); // Emitter + else + m_D_CB.m_N.net().solve(); // Collector } NETLIB_RESET(QBJT_EB) { - NETLIB_NAME(Q)::reset(); + NETLIB_NAME(Q)::reset(); } @@ -182,4 +182,3 @@ NETLIB_RESET(QBJT_EB) NETLIB_UPDATE_PARAM(QBJT_EB) { } - diff --git a/src/emu/netlist/analog/nld_bjt.h b/src/emu/netlist/analog/nld_bjt.h index 317a390bef4..78306f80ad9 100644 --- a/src/emu/netlist/analog/nld_bjt.h +++ b/src/emu/netlist/analog/nld_bjt.h @@ -14,12 +14,12 @@ // ---------------------------------------------------------------------------------------- #define QBJT_SW(_name, _model) \ - NET_REGISTER_DEV(QBJT_switch, _name) \ - NETDEV_PARAMI(_name, model, _model) + NET_REGISTER_DEV(QBJT_switch, _name) \ + NETDEV_PARAMI(_name, model, _model) #define QBJT_EB(_name, _model) \ - NET_REGISTER_DEV(QBJT_EB, _name) \ - NETDEV_PARAMI(_name, model, _model) + NET_REGISTER_DEV(QBJT_EB, _name) \ + NETDEV_PARAMI(_name, model, _model) // ---------------------------------------------------------------------------------------- @@ -31,34 +31,34 @@ class NETLIB_NAME(Q) : public netlist_device_t { public: - enum q_type { - BJT_NPN, - BJT_PNP - }; - - ATTR_COLD NETLIB_NAME(Q)(const family_t afamily) - : netlist_device_t(afamily) - , m_qtype(BJT_NPN) { } - - inline q_type qtype() const { return m_qtype; } - inline bool is_qtype(q_type atype) const { return m_qtype == atype; } - inline void set_qtype(q_type atype) { m_qtype = atype; } + enum q_type { + BJT_NPN, + BJT_PNP + }; + + ATTR_COLD NETLIB_NAME(Q)(const family_t afamily) + : netlist_device_t(afamily) + , m_qtype(BJT_NPN) { } + + inline q_type qtype() const { return m_qtype; } + inline bool is_qtype(q_type atype) const { return m_qtype == atype; } + inline void set_qtype(q_type atype) { m_qtype = atype; } protected: - ATTR_COLD virtual void start(); - ATTR_COLD virtual void reset(); - ATTR_HOT ATTR_ALIGN void update(); + ATTR_COLD virtual void start(); + ATTR_COLD virtual void reset(); + ATTR_HOT ATTR_ALIGN void update(); - netlist_param_model_t m_model; + netlist_param_model_t m_model; private: - q_type m_qtype; + q_type m_qtype; }; class NETLIB_NAME(QBJT) : public NETLIB_NAME(Q) { public: - ATTR_COLD NETLIB_NAME(QBJT)(const family_t afamily) - : NETLIB_NAME(Q)(afamily) { } + ATTR_COLD NETLIB_NAME(QBJT)(const family_t afamily) + : NETLIB_NAME(Q)(afamily) { } protected: @@ -89,63 +89,63 @@ private: class NETLIB_NAME(QBJT_switch) : public NETLIB_NAME(QBJT) { public: - ATTR_COLD NETLIB_NAME(QBJT_switch)() - : NETLIB_NAME(QBJT)(BJT_SWITCH), - m_RB(netlist_object_t::ANALOG), - m_RC(netlist_object_t::ANALOG), - m_BC_dummy(netlist_object_t::ANALOG), - m_gB(NETLIST_GMIN_DEFAULT), m_gC(NETLIST_GMIN_DEFAULT), m_V(0.0), m_state_on(0) { } - - NETLIB_UPDATE_TERMINALS() - { - double m = (is_qtype( BJT_NPN) ? 1 : -1); - - int new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0; - if (m_state_on ^ new_state) - { - double gb = m_gB; - double gc = m_gC; - double v = m_V * m; - if (!new_state ) - { - // not conducting - gb = netlist().gmin(); - v = 0; - gc = netlist().gmin(); - } - m_RB.set(gb, v, 0.0); - m_RC.set(gc, 0.0, 0.0); - m_state_on = new_state; - } - } - - ATTR_HOT ATTR_ALIGN void virtual update() - { - if (!m_RB.m_P.net().isRailNet()) - m_RB.m_P.net().solve(); // Basis - else if (!m_RB.m_N.net().isRailNet()) - m_RB.m_N.net().solve(); // Emitter - else if (!m_RC.m_P.net().isRailNet()) - m_RB.m_P.net().solve(); // Collector - } - - nld_twoterm m_RB; - nld_twoterm m_RC; - - // FIXME: the matrix solvers should be devices so we can properly - // schedule them. This is a workaround and blows netgroup size - - nld_twoterm m_BC_dummy; + ATTR_COLD NETLIB_NAME(QBJT_switch)() + : NETLIB_NAME(QBJT)(BJT_SWITCH), + m_RB(netlist_object_t::ANALOG), + m_RC(netlist_object_t::ANALOG), + m_BC_dummy(netlist_object_t::ANALOG), + m_gB(NETLIST_GMIN_DEFAULT), m_gC(NETLIST_GMIN_DEFAULT), m_V(0.0), m_state_on(0) { } + + NETLIB_UPDATE_TERMINALS() + { + double m = (is_qtype( BJT_NPN) ? 1 : -1); + + int new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0; + if (m_state_on ^ new_state) + { + double gb = m_gB; + double gc = m_gC; + double v = m_V * m; + if (!new_state ) + { + // not conducting + gb = netlist().gmin(); + v = 0; + gc = netlist().gmin(); + } + m_RB.set(gb, v, 0.0); + m_RC.set(gc, 0.0, 0.0); + m_state_on = new_state; + } + } + + ATTR_HOT ATTR_ALIGN void virtual update() + { + if (!m_RB.m_P.net().isRailNet()) + m_RB.m_P.net().solve(); // Basis + else if (!m_RB.m_N.net().isRailNet()) + m_RB.m_N.net().solve(); // Emitter + else if (!m_RC.m_P.net().isRailNet()) + m_RB.m_P.net().solve(); // Collector + } + + nld_twoterm m_RB; + nld_twoterm m_RC; + + // FIXME: the matrix solvers should be devices so we can properly + // schedule them. This is a workaround and blows netgroup size + + nld_twoterm m_BC_dummy; protected: - ATTR_COLD virtual void start(); - ATTR_HOT void update_param(); + ATTR_COLD virtual void start(); + ATTR_HOT void update_param(); - double m_gB; // base conductance / switch on - double m_gC; // collector conductance / switch on - double m_V; // internal voltage source - UINT8 m_state_on; + double m_gB; // base conductance / switch on + double m_gC; // collector conductance / switch on + double m_V; // internal voltage source + UINT8 m_state_on; private: }; @@ -158,53 +158,53 @@ private: class NETLIB_NAME(QBJT_EB) : public NETLIB_NAME(QBJT) { public: - ATTR_COLD NETLIB_NAME(QBJT_EB)() - : NETLIB_NAME(QBJT)(BJT_EB), - m_D_CB(netlist_object_t::ANALOG), - m_D_EB(netlist_object_t::ANALOG), - m_D_EC(netlist_object_t::ANALOG) - { } - - NETLIB_UPDATE_TERMINALS() - { - double polarity = (qtype() == BJT_NPN ? 1.0 : -1.0); - - m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity); - m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity); - - double gee = m_gD_BE.G(); - double gcc = m_gD_BC.G(); - double gec = m_alpha_r * gcc; - double gce = m_alpha_f * gee; - double sIe = -m_gD_BE.I() + m_alpha_r * m_gD_BC.I(); - double sIc = m_alpha_f * m_gD_BE.I() - m_gD_BC.I(); - double Ie = (sIe + gee * m_gD_BE.Vd() - gec * m_gD_BC.Vd()) * polarity; - double Ic = (sIc - gce * m_gD_BE.Vd() + gcc * m_gD_BC.Vd()) * polarity; - //double Ie = sIe + gee * -m_D_EB.deltaV() - gec * -m_D_CB.deltaV(); - //double Ic = sIc - gce * -m_D_EB.deltaV() + gcc * -m_D_CB.deltaV(); - //printf("EB %f sIe %f sIc %f\n", m_D_BE.deltaV(), sIe, sIc); - - m_D_EB.set_mat(gee, gec - gee, gce - gee, gee - gec, Ie, -Ie); - m_D_CB.set_mat(gcc, gce - gcc, gec - gcc, gcc - gce, Ic, -Ic); - m_D_EC.set_mat( 0, -gec, -gce, 0, 0, 0); - } + ATTR_COLD NETLIB_NAME(QBJT_EB)() + : NETLIB_NAME(QBJT)(BJT_EB), + m_D_CB(netlist_object_t::ANALOG), + m_D_EB(netlist_object_t::ANALOG), + m_D_EC(netlist_object_t::ANALOG) + { } + + NETLIB_UPDATE_TERMINALS() + { + double polarity = (qtype() == BJT_NPN ? 1.0 : -1.0); + + m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity); + m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity); + + double gee = m_gD_BE.G(); + double gcc = m_gD_BC.G(); + double gec = m_alpha_r * gcc; + double gce = m_alpha_f * gee; + double sIe = -m_gD_BE.I() + m_alpha_r * m_gD_BC.I(); + double sIc = m_alpha_f * m_gD_BE.I() - m_gD_BC.I(); + double Ie = (sIe + gee * m_gD_BE.Vd() - gec * m_gD_BC.Vd()) * polarity; + double Ic = (sIc - gce * m_gD_BE.Vd() + gcc * m_gD_BC.Vd()) * polarity; + //double Ie = sIe + gee * -m_D_EB.deltaV() - gec * -m_D_CB.deltaV(); + //double Ic = sIc - gce * -m_D_EB.deltaV() + gcc * -m_D_CB.deltaV(); + //printf("EB %f sIe %f sIc %f\n", m_D_BE.deltaV(), sIe, sIc); + + m_D_EB.set_mat(gee, gec - gee, gce - gee, gee - gec, Ie, -Ie); + m_D_CB.set_mat(gcc, gce - gcc, gec - gcc, gcc - gce, Ic, -Ic); + m_D_EC.set_mat( 0, -gec, -gce, 0, 0, 0); + } protected: - ATTR_COLD virtual void start(); - ATTR_COLD virtual void reset(); - ATTR_HOT void update_param(); - ATTR_HOT ATTR_ALIGN void virtual update(); + ATTR_COLD virtual void start(); + ATTR_COLD virtual void reset(); + ATTR_HOT void update_param(); + ATTR_HOT ATTR_ALIGN void virtual update(); - netlist_generic_diode m_gD_BC; - netlist_generic_diode m_gD_BE; + netlist_generic_diode m_gD_BC; + netlist_generic_diode m_gD_BE; - nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic - nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie - nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0 + nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic + nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie + nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0 - double m_alpha_f; - double m_alpha_r; + double m_alpha_f; + double m_alpha_r; private: }; diff --git a/src/emu/netlist/analog/nld_fourterm.c b/src/emu/netlist/analog/nld_fourterm.c index 301aca9a4e7..61579e50bfb 100644 --- a/src/emu/netlist/analog/nld_fourterm.c +++ b/src/emu/netlist/analog/nld_fourterm.c @@ -13,45 +13,45 @@ NETLIB_START(VCCS) { - register_param("G", m_G, 1.0); - register_param("RI", m_RI, 1.0 / netlist().gmin()); + register_param("G", m_G, 1.0); + register_param("RI", m_RI, 1.0 / netlist().gmin()); - register_terminal("IP", m_IP); - register_terminal("IN", m_IN); - register_terminal("OP", m_OP); - register_terminal("ON", m_ON); + register_terminal("IP", m_IP); + register_terminal("IN", m_IN); + register_terminal("OP", m_OP); + register_terminal("ON", m_ON); - register_terminal("_OP1", m_OP1); - register_terminal("_ON1", m_ON1); + register_terminal("_OP1", m_OP1); + register_terminal("_ON1", m_ON1); - m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving... - m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving... + m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving... + m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving... - m_OP.m_otherterm = &m_IP; - m_OP1.m_otherterm = &m_IN; + m_OP.m_otherterm = &m_IP; + m_OP1.m_otherterm = &m_IN; - m_ON.m_otherterm = &m_IP; - m_ON1.m_otherterm = &m_IN; + m_ON.m_otherterm = &m_IP; + m_ON1.m_otherterm = &m_IN; - connect(m_OP, m_OP1); - connect(m_ON, m_ON1); + connect(m_OP, m_OP1); + connect(m_ON, m_ON1); - m_gfac = 1.0; + m_gfac = 1.0; } NETLIB_RESET(VCCS) { - const double m_mult = m_G.Value() * m_gfac; // 1.0 ==> 1V ==> 1A - const double GI = 1.0 / m_RI.Value(); + const double m_mult = m_G.Value() * m_gfac; // 1.0 ==> 1V ==> 1A + const double GI = 1.0 / m_RI.Value(); - m_IP.set(GI); - m_IN.set(GI); + m_IP.set(GI); + m_IN.set(GI); - m_OP.set(m_mult, 0.0); - m_OP1.set(-m_mult, 0.0); + m_OP.set(m_mult, 0.0); + m_OP1.set(-m_mult, 0.0); - m_ON.set(-m_mult, 0.0); - m_ON1.set(m_mult, 0.0); + m_ON.set(-m_mult, 0.0); + m_ON1.set(m_mult, 0.0); } NETLIB_UPDATE_PARAM(VCCS) @@ -60,16 +60,16 @@ NETLIB_UPDATE_PARAM(VCCS) 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().solve(); - else if (!m_IN.net().isRailNet()) - m_IN.net().solve(); - else if (!m_OP.net().isRailNet()) - m_OP.net().solve(); - else if (!m_ON.net().isRailNet()) - m_ON.net().solve(); + /* only called if connected to a rail net ==> notify the solver to recalculate */ + /* Big FIXME ... */ + if (!m_IP.net().isRailNet()) + m_IP.net().solve(); + else if (!m_IN.net().isRailNet()) + m_IN.net().solve(); + else if (!m_OP.net().isRailNet()) + m_OP.net().solve(); + else if (!m_ON.net().isRailNet()) + m_ON.net().solve(); } // ---------------------------------------------------------------------------------------- @@ -78,30 +78,29 @@ NETLIB_UPDATE(VCCS) NETLIB_START(VCVS) { - NETLIB_NAME(VCCS)::start(); + NETLIB_NAME(VCCS)::start(); - register_param("RO", m_RO, 1.0); + register_param("RO", m_RO, 1.0); - register_terminal("_OP2", m_OP2); - register_terminal("_ON2", m_ON2); + register_terminal("_OP2", m_OP2); + register_terminal("_ON2", m_ON2); - m_OP2.m_otherterm = &m_ON2; - m_ON2.m_otherterm = &m_OP2; + m_OP2.m_otherterm = &m_ON2; + m_ON2.m_otherterm = &m_OP2; - connect(m_OP2, m_OP1); - connect(m_ON2, m_ON1); + connect(m_OP2, m_OP1); + connect(m_ON2, m_ON1); } NETLIB_RESET(VCVS) { - m_gfac = 1.0 / m_RO.Value(); - NETLIB_NAME(VCCS)::reset(); + m_gfac = 1.0 / m_RO.Value(); + NETLIB_NAME(VCCS)::reset(); - m_OP2.set(1.0 / m_RO.Value()); - m_ON2.set(1.0 / m_RO.Value()); + m_OP2.set(1.0 / m_RO.Value()); + m_ON2.set(1.0 / m_RO.Value()); } NETLIB_UPDATE_PARAM(VCVS) { } - diff --git a/src/emu/netlist/analog/nld_fourterm.h b/src/emu/netlist/analog/nld_fourterm.h index 0f330333bcd..56d307a653f 100644 --- a/src/emu/netlist/analog/nld_fourterm.h +++ b/src/emu/netlist/analog/nld_fourterm.h @@ -15,10 +15,10 @@ // ---------------------------------------------------------------------------------------- #define VCCS(_name) \ - NET_REGISTER_DEV(VCCS, _name) + NET_REGISTER_DEV(VCCS, _name) #define VCVS(_name) \ - NET_REGISTER_DEV(VCVS, _name) + NET_REGISTER_DEV(VCVS, _name) // ---------------------------------------------------------------------------------------- // nld_CCCS @@ -70,30 +70,30 @@ class NETLIB_NAME(VCCS) : public netlist_device_t { public: - ATTR_COLD NETLIB_NAME(VCCS)() - : netlist_device_t(VCCS) { } - ATTR_COLD NETLIB_NAME(VCCS)(const family_t afamily) - : netlist_device_t(afamily) { } + ATTR_COLD NETLIB_NAME(VCCS)() + : netlist_device_t(VCCS) { } + ATTR_COLD NETLIB_NAME(VCCS)(const family_t afamily) + : netlist_device_t(afamily) { } protected: - ATTR_COLD virtual void start(); - ATTR_COLD virtual void reset(); - ATTR_COLD virtual void update_param(); - ATTR_HOT ATTR_ALIGN void update(); + ATTR_COLD virtual void start(); + ATTR_COLD virtual void reset(); + ATTR_COLD virtual void update_param(); + ATTR_HOT ATTR_ALIGN void update(); - netlist_terminal_t m_OP; - netlist_terminal_t m_ON; + netlist_terminal_t m_OP; + netlist_terminal_t m_ON; - netlist_terminal_t m_IP; - netlist_terminal_t m_IN; + netlist_terminal_t m_IP; + netlist_terminal_t m_IN; - netlist_terminal_t m_OP1; - netlist_terminal_t m_ON1; + netlist_terminal_t m_OP1; + netlist_terminal_t m_ON1; - netlist_param_double_t m_G; - netlist_param_double_t m_RI; + netlist_param_double_t m_G; + netlist_param_double_t m_RI; - double m_gfac; + double m_gfac; }; // ---------------------------------------------------------------------------------------- @@ -127,19 +127,19 @@ protected: class NETLIB_NAME(VCVS) : public NETLIB_NAME(VCCS) { public: - ATTR_COLD NETLIB_NAME(VCVS)() - : NETLIB_NAME(VCCS)(VCVS) { } + ATTR_COLD NETLIB_NAME(VCVS)() + : NETLIB_NAME(VCCS)(VCVS) { } protected: - ATTR_COLD virtual void start(); - ATTR_COLD virtual void reset(); - ATTR_COLD virtual void update_param(); - //ATTR_HOT ATTR_ALIGN void update(); + ATTR_COLD virtual void start(); + ATTR_COLD virtual void reset(); + ATTR_COLD virtual void update_param(); + //ATTR_HOT ATTR_ALIGN void update(); - netlist_terminal_t m_OP2; - netlist_terminal_t m_ON2; + netlist_terminal_t m_OP2; + netlist_terminal_t m_ON2; - netlist_param_double_t m_RO; + netlist_param_double_t m_RO; }; diff --git a/src/emu/netlist/analog/nld_solver.c b/src/emu/netlist/analog/nld_solver.c index df70766d589..6e4d02c9667 100644 --- a/src/emu/netlist/analog/nld_solver.c +++ b/src/emu/netlist/analog/nld_solver.c @@ -20,157 +20,157 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &aowner) { - m_owner = &aowner; - - NL_VERBOSE_OUT(("New solver setup\n")); - - for (netlist_net_t * const * pn = nets.first(); pn != NULL; pn = nets.next(pn)) - { - NL_VERBOSE_OUT(("setting up net\n")); - - m_nets.add(*pn); - - (*pn)->m_solver = this; - - for (netlist_core_terminal_t *p = (*pn)->m_list.first(); p != NULL; p = (*pn)->m_list.next(p)) - { - NL_VERBOSE_OUT(("%s %s %d\n", p->name().cstr(), (*pn)->name().cstr(), (int) (*pn)->isRailNet())); - switch (p->type()) - { - case netlist_terminal_t::TERMINAL: - switch (p->netdev().family()) - { - case netlist_device_t::CAPACITOR: - if (!m_steps.contains(&p->netdev())) - m_steps.add(&p->netdev()); - break; - case netlist_device_t::BJT_EB: - case netlist_device_t::DIODE: - //case netlist_device_t::VCVS: - case netlist_device_t::BJT_SWITCH: - NL_VERBOSE_OUT(("found BJT/Diode\n")); - if (!m_dynamic.contains(&p->netdev())) - m_dynamic.add(&p->netdev()); - break; - default: - break; - } - { - netlist_terminal_t *pterm = static_cast<netlist_terminal_t *>(p); - if (pterm->m_otherterm->net().isRailNet()) - (*pn)->m_rails.add(pterm); - else - (*pn)->m_terms.add(pterm); - } - NL_VERBOSE_OUT(("Added terminal\n")); - break; - case netlist_terminal_t::INPUT: - if (!m_inps.contains(p)) - m_inps.add(p); - NL_VERBOSE_OUT(("Added input\n")); - break; - default: - owner().netlist().error("unhandled element found\n"); - break; - } - } - NL_VERBOSE_OUT(("added net with %d populated connections (%d railnets)\n", (*pn)->m_terms.count(), (*pn)->m_rails.count())); - } + m_owner = &aowner; + + NL_VERBOSE_OUT(("New solver setup\n")); + + for (netlist_net_t * const * pn = nets.first(); pn != NULL; pn = nets.next(pn)) + { + NL_VERBOSE_OUT(("setting up net\n")); + + m_nets.add(*pn); + + (*pn)->m_solver = this; + + for (netlist_core_terminal_t *p = (*pn)->m_list.first(); p != NULL; p = (*pn)->m_list.next(p)) + { + NL_VERBOSE_OUT(("%s %s %d\n", p->name().cstr(), (*pn)->name().cstr(), (int) (*pn)->isRailNet())); + switch (p->type()) + { + case netlist_terminal_t::TERMINAL: + switch (p->netdev().family()) + { + case netlist_device_t::CAPACITOR: + if (!m_steps.contains(&p->netdev())) + m_steps.add(&p->netdev()); + break; + case netlist_device_t::BJT_EB: + case netlist_device_t::DIODE: + //case netlist_device_t::VCVS: + case netlist_device_t::BJT_SWITCH: + NL_VERBOSE_OUT(("found BJT/Diode\n")); + if (!m_dynamic.contains(&p->netdev())) + m_dynamic.add(&p->netdev()); + break; + default: + break; + } + { + netlist_terminal_t *pterm = static_cast<netlist_terminal_t *>(p); + if (pterm->m_otherterm->net().isRailNet()) + (*pn)->m_rails.add(pterm); + else + (*pn)->m_terms.add(pterm); + } + NL_VERBOSE_OUT(("Added terminal\n")); + break; + case netlist_terminal_t::INPUT: + if (!m_inps.contains(p)) + m_inps.add(p); + NL_VERBOSE_OUT(("Added input\n")); + break; + default: + owner().netlist().error("unhandled element found\n"); + break; + } + } + NL_VERBOSE_OUT(("added net with %d populated connections (%d railnets)\n", (*pn)->m_terms.count(), (*pn)->m_rails.count())); + } } ATTR_HOT void netlist_matrix_solver_t::update_inputs() { - for (netlist_core_terminal_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) - { - if ((*p)->net().m_last_Analog != (*p)->net().m_cur_Analog) - { - (*p)->netdev().update_dev(); - } - } - for (netlist_core_terminal_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) - { - (*p)->net().m_last_Analog = (*p)->net().m_cur_Analog; - } + for (netlist_core_terminal_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) + { + if ((*p)->net().m_last_Analog != (*p)->net().m_cur_Analog) + { + (*p)->netdev().update_dev(); + } + } + for (netlist_core_terminal_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) + { + (*p)->net().m_last_Analog = (*p)->net().m_cur_Analog; + } } ATTR_HOT void netlist_matrix_solver_t::update_dynamic() { - /* update all non-linear devices */ - for (netlist_core_device_t * const *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p)) - switch ((*p)->family()) - { - case netlist_device_t::DIODE: - static_cast<NETLIB_NAME(D) *>((*p))->update_terminals(); - break; - default: - (*p)->update_terminals(); - break; - } + /* update all non-linear devices */ + for (netlist_core_device_t * const *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p)) + switch ((*p)->family()) + { + case netlist_device_t::DIODE: + static_cast<NETLIB_NAME(D) *>((*p))->update_terminals(); + break; + default: + (*p)->update_terminals(); + break; + } } ATTR_HOT void netlist_matrix_solver_t::schedule() { - if (!solve()) - { - // NL_VERBOSE_OUT(("update_inputs\n"); - update_inputs(); - } - else - { - m_owner->netlist().warning("Matrix solver reschedule .. Consider increasing RESCHED_LOOPS"); - if (m_owner != NULL) - this->m_owner->schedule(); - } - //solve(); - // update_inputs(); + if (!solve()) + { + // NL_VERBOSE_OUT(("update_inputs\n"); + update_inputs(); + } + else + { + m_owner->netlist().warning("Matrix solver reschedule .. Consider increasing RESCHED_LOOPS"); + if (m_owner != NULL) + this->m_owner->schedule(); + } + //solve(); + // update_inputs(); } ATTR_COLD void netlist_matrix_solver_t::reset() { - m_last_step = netlist_time::zero; + m_last_step = netlist_time::zero; } ATTR_HOT void netlist_matrix_solver_t::step(const netlist_time delta) { - const double dd = delta.as_double(); - for (int k=0; k < m_steps.count(); k++) - m_steps[k]->step_time(dd); + const double dd = delta.as_double(); + for (int k=0; k < m_steps.count(); k++) + m_steps[k]->step_time(dd); } ATTR_HOT bool netlist_matrix_solver_t::solve() { - int resched_cnt = 0; - - netlist_time now = owner().netlist().time(); - netlist_time delta = now - m_last_step; - - if (delta < netlist_time::from_nsec(1)) // always update capacitors - delta = netlist_time::from_nsec(1); - { - NL_VERBOSE_OUT(("Step!\n")); - /* update all terminals for new time step */ - m_last_step = now; - step(delta); - } - - if (is_dynamic()) - { - int this_resched; - do - { - update_dynamic(); - this_resched = solve_non_dynamic(); - resched_cnt += this_resched; - } while (this_resched > 1 && resched_cnt < m_params.m_resched_loops); - } - else - { - resched_cnt = solve_non_dynamic(); - //printf("resched_cnt %d %d\n", resched_cnt, m_resched_loops); - } - return (resched_cnt >= m_params.m_resched_loops); + int resched_cnt = 0; + + netlist_time now = owner().netlist().time(); + netlist_time delta = now - m_last_step; + + if (delta < netlist_time::from_nsec(1)) // always update capacitors + delta = netlist_time::from_nsec(1); + { + NL_VERBOSE_OUT(("Step!\n")); + /* update all terminals for new time step */ + m_last_step = now; + step(delta); + } + + if (is_dynamic()) + { + int this_resched; + do + { + update_dynamic(); + this_resched = solve_non_dynamic(); + resched_cnt += this_resched; + } while (this_resched > 1 && resched_cnt < m_params.m_resched_loops); + } + else + { + resched_cnt = solve_non_dynamic(); + //printf("resched_cnt %d %d\n", resched_cnt, m_resched_loops); + } + return (resched_cnt >= m_params.m_resched_loops); } // ---------------------------------------------------------------------------------------- @@ -181,241 +181,239 @@ ATTR_HOT bool netlist_matrix_solver_t::solve() template <int m_N, int _storage_N> ATTR_COLD int netlist_matrix_solver_direct_t<m_N, _storage_N>::get_net_idx(netlist_net_t *net) { - for (int k = 0; k < N(); k++) - if (m_nets[k] == net) - return k; - return -1; + for (int k = 0; k < N(); k++) + if (m_nets[k] == net) + return k; + return -1; } template <int m_N, int _storage_N> ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner) { - netlist_matrix_solver_t::setup(nets, owner); - - m_term_num = 0; - m_rail_start = 0; - for (int k = 0; k < N(); k++) - { - netlist_net_t *net = m_nets[k]; - const netlist_net_t::terminal_list_t &terms = net->m_terms; - for (int i = 0; i < terms.count(); i++) - { - m_terms[m_term_num].net_this = k; - int ot = get_net_idx(&terms[i]->m_otherterm->net()); - m_terms[m_term_num].net_other = ot; - m_terms[m_term_num].term = terms[i]; - if (ot>=0) - { - m_term_num++; - SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go)); - } - } - } - m_rail_start = m_term_num; - for (int k = 0; k < N(); k++) - { - netlist_net_t *net = m_nets[k]; - const netlist_net_t::terminal_list_t &terms = net->m_terms; - const netlist_net_t::terminal_list_t &rails = net->m_rails; - for (int i = 0; i < terms.count(); i++) - { - m_terms[m_term_num].net_this = k; - int ot = get_net_idx(&terms[i]->m_otherterm->net()); - m_terms[m_term_num].net_other = ot; - m_terms[m_term_num].term = terms[i]; - if (ot<0) - { - m_term_num++; - SOLVER_VERBOSE_OUT(("found term with missing othernet %s\n", terms[i]->name().cstr())); - } - } - for (int i = 0; i < rails.count(); i++) - { - m_terms[m_term_num].net_this = k; - m_terms[m_term_num].net_other = -1; //get_net_idx(&rails[i]->m_otherterm->net()); - m_terms[m_term_num].term = rails[i]; - m_term_num++; - SOLVER_VERBOSE_OUT(("Net %d Rail %s %f %f\n", k, rails[i]->name().cstr(), rails[i]->m_gt, rails[i]->m_go)); - } - } + netlist_matrix_solver_t::setup(nets, owner); + + m_term_num = 0; + m_rail_start = 0; + for (int k = 0; k < N(); k++) + { + netlist_net_t *net = m_nets[k]; + const netlist_net_t::terminal_list_t &terms = net->m_terms; + for (int i = 0; i < terms.count(); i++) + { + m_terms[m_term_num].net_this = k; + int ot = get_net_idx(&terms[i]->m_otherterm->net()); + m_terms[m_term_num].net_other = ot; + m_terms[m_term_num].term = terms[i]; + if (ot>=0) + { + m_term_num++; + SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go)); + } + } + } + m_rail_start = m_term_num; + for (int k = 0; k < N(); k++) + { + netlist_net_t *net = m_nets[k]; + const netlist_net_t::terminal_list_t &terms = net->m_terms; + const netlist_net_t::terminal_list_t &rails = net->m_rails; + for (int i = 0; i < terms.count(); i++) + { + m_terms[m_term_num].net_this = k; + int ot = get_net_idx(&terms[i]->m_otherterm->net()); + m_terms[m_term_num].net_other = ot; + m_terms[m_term_num].term = terms[i]; + if (ot<0) + { + m_term_num++; + SOLVER_VERBOSE_OUT(("found term with missing othernet %s\n", terms[i]->name().cstr())); + } + } + for (int i = 0; i < rails.count(); i++) + { + m_terms[m_term_num].net_this = k; + m_terms[m_term_num].net_other = -1; //get_net_idx(&rails[i]->m_otherterm->net()); + m_terms[m_term_num].term = rails[i]; + m_term_num++; + SOLVER_VERBOSE_OUT(("Net %d Rail %s %f %f\n", k, rails[i]->name().cstr(), rails[i]->m_gt, rails[i]->m_go)); + } + } } template <int m_N, int _storage_N> ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE( - double (* RESTRICT A)[_storage_N], - double (* RESTRICT RHS)) + double (* RESTRICT A)[_storage_N], + double (* RESTRICT RHS)) { - #if 0 - for (int i = 0; i < m_term_num; i++) - { - terms_t &t = m_terms[i]; - m_RHS[t.net_this] += t.term->m_Idr; - m_A[t.net_this][t.net_this] += t.term->m_gt; - if (t.net_other >= 0) - { - //m_A[t.net_other][t.net_other] += t.term->m_otherterm->m_gt; - m_A[t.net_this][t.net_other] += -t.term->m_go; - //m_A[t.net_other][t.net_this] += -t.term->m_otherterm->m_go; - } - else - m_RHS[t.net_this] += t.term->m_go * t.term->m_otherterm->net().Q_Analog(); - } + for (int i = 0; i < m_term_num; i++) + { + terms_t &t = m_terms[i]; + m_RHS[t.net_this] += t.term->m_Idr; + m_A[t.net_this][t.net_this] += t.term->m_gt; + if (t.net_other >= 0) + { + //m_A[t.net_other][t.net_other] += t.term->m_otherterm->m_gt; + m_A[t.net_this][t.net_other] += -t.term->m_go; + //m_A[t.net_other][t.net_this] += -t.term->m_otherterm->m_go; + } + else + m_RHS[t.net_this] += t.term->m_go * t.term->m_otherterm->net().Q_Analog(); + } #else - for (int i = 0; i < m_rail_start; i++) - { - terms_t &t = m_terms[i]; - //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); - RHS[t.net_this] += t.term->m_Idr; - A[t.net_this][t.net_this] += t.term->m_gt; - - A[t.net_this][t.net_other] += -t.term->m_go; - } - for (int i = m_rail_start; i < m_term_num; i++) - { - terms_t &t = m_terms[i]; - RHS[t.net_this] += t.term->m_Idr; - A[t.net_this][t.net_this] += t.term->m_gt; - - RHS[t.net_this] += t.term->m_go * t.term->m_otherterm->net().Q_Analog(); - } + for (int i = 0; i < m_rail_start; i++) + { + terms_t &t = m_terms[i]; + //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); + RHS[t.net_this] += t.term->m_Idr; + A[t.net_this][t.net_this] += t.term->m_gt; + + A[t.net_this][t.net_other] += -t.term->m_go; + } + for (int i = m_rail_start; i < m_term_num; i++) + { + terms_t &t = m_terms[i]; + RHS[t.net_this] += t.term->m_Idr; + A[t.net_this][t.net_this] += t.term->m_gt; + + RHS[t.net_this] += t.term->m_go * t.term->m_otherterm->net().Q_Analog(); + } #endif } template <int m_N, int _storage_N> ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE( - double (* RESTRICT A)[_storage_N], - double (* RESTRICT RHS), - double (* RESTRICT x)) + double (* RESTRICT A)[_storage_N], + double (* RESTRICT RHS), + double (* RESTRICT x)) { #if 0 - for (int i = 0; i < N(); i++) - { - for (int k = 0; k < N(); k++) - printf("%f ", A[i][k]); - printf("| %f = %f \n", x[i], RHS[i]); - } - printf("\n"); + for (int i = 0; i < N(); i++) + { + for (int k = 0; k < N(); k++) + printf("%f ", A[i][k]); + printf("| %f = %f \n", x[i], RHS[i]); + } + printf("\n"); #endif - for (int i = 0; i < N(); i++) { - + for (int i = 0; i < N(); i++) { #if 0 - /* Find the row with the largest first value */ - maxrow = i; - for (j=i+1;j<n;j++) { - if (ABS(a[i][j]) > ABS(a[i][maxrow])) - maxrow = j; - } - - /* Swap the maxrow and ith row */ - for (k=i;k<n+1;k++) { - tmp = a[k][i]; - a[k][i] = a[k][maxrow]; - a[k][maxrow] = tmp; - } + /* Find the row with the largest first value */ + maxrow = i; + for (j=i+1;j<n;j++) { + if (ABS(a[i][j]) > ABS(a[i][maxrow])) + maxrow = j; + } + + /* Swap the maxrow and ith row */ + for (k=i;k<n+1;k++) { + tmp = a[k][i]; + a[k][i] = a[k][maxrow]; + a[k][maxrow] = tmp; + } #endif - /* Singular matrix? */ - double f = A[i][i]; - //if (fabs(f) < 1e-20) printf("Singular!"); - f = 1.0 / f; - - /* Eliminate column i from row j */ - for (int j = i + 1; j < N(); j++) - { - double f1 = A[j][i] * f; - - if (f1 != 0.0) - { - for (int k = i; k < N(); k++) - { - A[j][k] -= A[i][k] * f1; - } - RHS[j] -= RHS[i] * f1; - } - } - } - /* back substitution */ - for (int j = N() - 1; j >= 0; j--) - { - double tmp = 0; - for (int k = j + 1; k < N(); k++) - tmp += A[j][k] * x[k]; - x[j] = (RHS[j] - tmp) / A[j][j]; - } + /* Singular matrix? */ + double f = A[i][i]; + //if (fabs(f) < 1e-20) printf("Singular!"); + f = 1.0 / f; + + /* Eliminate column i from row j */ + for (int j = i + 1; j < N(); j++) + { + double f1 = A[j][i] * f; + + if (f1 != 0.0) + { + for (int k = i; k < N(); k++) + { + A[j][k] -= A[i][k] * f1; + } + RHS[j] -= RHS[i] * f1; + } + } + } + /* back substitution */ + for (int j = N() - 1; j >= 0; j--) + { + double tmp = 0; + for (int k = j + 1; k < N(); k++) + tmp += A[j][k] * x[k]; + x[j] = (RHS[j] - tmp) / A[j][j]; + } #if 0 - printf("Solution:\n"); - for (int i = 0; i < N(); i++) - { - for (int k = 0; k < N(); k++) - printf("%f ", A[i][k]); - printf("| %f = %f \n", x[i], RHS[i]); - } - printf("\n"); + printf("Solution:\n"); + for (int i = 0; i < N(); i++) + { + for (int k = 0; k < N(); k++) + printf("%f ", A[i][k]); + printf("| %f = %f \n", x[i], RHS[i]); + } + printf("\n"); #endif } template <int m_N, int _storage_N> ATTR_HOT double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta( - const double (* RESTRICT RHS), - const double (* RESTRICT V)) + const double (* RESTRICT RHS), + const double (* RESTRICT V)) { - double cerr = 0; - double cerr2 = 0; - for (int i = 0; i < this->N(); i++) - { - double e = (V[i] - this->m_nets[i]->m_cur_Analog); - double e2 = (RHS[i] - this->m_RHS[i]); - cerr += e * e; - cerr2 += e2 * e2; - } - return (cerr + cerr2*(100000.0 * 100000.0)) / this->N(); + double cerr = 0; + double cerr2 = 0; + for (int i = 0; i < this->N(); i++) + { + double e = (V[i] - this->m_nets[i]->m_cur_Analog); + double e2 = (RHS[i] - this->m_RHS[i]); + cerr += e * e; + cerr2 += e2 * e2; + } + return (cerr + cerr2*(100000.0 * 100000.0)) / this->N(); } template <int m_N, int _storage_N> ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::store( - const double (* RESTRICT RHS), - const double (* RESTRICT V)) + const double (* RESTRICT RHS), + const double (* RESTRICT V)) { - for (int i = 0; i < this->N(); i++) - { - this->m_nets[i]->m_cur_Analog = this->m_nets[i]->m_new_Analog = V[i]; - } - if (RHS != NULL) - { - for (int i = 0; i < this->N(); i++) - { - this->m_RHS[i] = RHS[i]; - } - } + for (int i = 0; i < this->N(); i++) + { + this->m_nets[i]->m_cur_Analog = this->m_nets[i]->m_new_Analog = V[i]; + } + if (RHS != NULL) + { + for (int i = 0; i < this->N(); i++) + { + this->m_RHS[i] = RHS[i]; + } + } } template <int m_N, int _storage_N> ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic() { - double A[_storage_N][_storage_N] = { { 0.0 } }; - double RHS[_storage_N] = { 0.0 }; - double new_v[_storage_N] = { 0.0 }; + double A[_storage_N][_storage_N] = { { 0.0 } }; + double RHS[_storage_N] = { 0.0 }; + double new_v[_storage_N] = { 0.0 }; - this->build_LE(A, RHS); + this->build_LE(A, RHS); - this->gauss_LE(A, RHS, new_v); + this->gauss_LE(A, RHS, new_v); - if (this->is_dynamic()) - { - double err = delta(RHS, new_v); + if (this->is_dynamic()) + { + double err = delta(RHS, new_v); - store(RHS, new_v); + store(RHS, new_v); - if (err > this->m_params.m_accuracy * this->m_params.m_accuracy) - { - return 2; - } - return 1; - } - store(NULL, new_v); // ==> No need to store RHS - return 1; + if (err > this->m_params.m_accuracy * this->m_params.m_accuracy) + { + return 2; + } + return 1; + } + store(NULL, new_v); // ==> No need to store RHS + return 1; } @@ -427,43 +425,43 @@ ATTR_HOT int netlist_matrix_solver_direct1_t::solve_non_dynamic() { #if 1 - double gtot_t = 0.0; - double RHS_t = 0.0; + double gtot_t = 0.0; + double RHS_t = 0.0; - netlist_net_t *net = m_nets[0]; - const netlist_net_t::terminal_list_t &rails = net->m_rails; - int rail_count = rails.count(); + netlist_net_t *net = m_nets[0]; + const netlist_net_t::terminal_list_t &rails = net->m_rails; + int rail_count = rails.count(); - for (int i = 0; i < rail_count; i++) - { - gtot_t += rails[i]->m_gt; - RHS_t += rails[i]->m_Idr; - RHS_t += rails[i]->m_go * rails[i]->m_otherterm->net().Q_Analog(); - } + for (int i = 0; i < rail_count; i++) + { + gtot_t += rails[i]->m_gt; + RHS_t += rails[i]->m_Idr; + RHS_t += rails[i]->m_go * rails[i]->m_otherterm->net().Q_Analog(); + } - double iIdr = RHS_t; - double new_val = iIdr / gtot_t; + double iIdr = RHS_t; + double new_val = iIdr / gtot_t; #else - netlist_net_t *net = m_nets[0]; - double m_A[1][1] = { {0.0} }; - double m_RHS[1] = { 0.0 }; - build_LE(m_A, m_RHS); - //NL_VERBOSE_OUT(("%f %f\n", new_val, m_RHS[0] / m_A[0][0]); + netlist_net_t *net = m_nets[0]; + double m_A[1][1] = { {0.0} }; + double m_RHS[1] = { 0.0 }; + build_LE(m_A, m_RHS); + //NL_VERBOSE_OUT(("%f %f\n", new_val, m_RHS[0] / m_A[0][0]); - double new_val = m_RHS[0] / m_A[0][0]; + double new_val = m_RHS[0] / m_A[0][0]; #endif - double e = (new_val - net->m_cur_Analog); - double cerr = e * e; + double e = (new_val - net->m_cur_Analog); + double cerr = e * e; - net->m_cur_Analog = net->m_new_Analog = new_val; + net->m_cur_Analog = net->m_new_Analog = new_val; - if (is_dynamic() && (cerr > m_params.m_accuracy * m_params.m_accuracy)) - { - return 2; - } - else - return 1; + if (is_dynamic() && (cerr > m_params.m_accuracy * m_params.m_accuracy)) + { + return 2; + } + else + return 1; } @@ -475,33 +473,33 @@ ATTR_HOT int netlist_matrix_solver_direct1_t::solve_non_dynamic() ATTR_HOT int netlist_matrix_solver_direct2_t::solve_non_dynamic() { - double A[2][2] = { { 0.0 } }; - double RHS[2] = { 0.0 }; - - build_LE(A, RHS); - - //NL_VERBOSE_OUT(("%f %f\n", new_val, m_RHS[0] / m_A[0][0]); - - const double a = A[0][0]; - const double b = A[0][1]; - const double c = A[1][0]; - const double d = A[1][1]; - - double new_val[2]; - new_val[1] = a / (a*d - b*c) * (RHS[1] - c / a * RHS[0]); - new_val[0] = (RHS[0] - b * new_val[1]) / a; - - if (is_dynamic()) - { - double err = delta(RHS, new_val); - store(RHS, new_val); - if (err > m_params.m_accuracy * m_params.m_accuracy) - return 2; - else - return 1; - } - store(NULL, new_val); - return 1; + double A[2][2] = { { 0.0 } }; + double RHS[2] = { 0.0 }; + + build_LE(A, RHS); + + //NL_VERBOSE_OUT(("%f %f\n", new_val, m_RHS[0] / m_A[0][0]); + + const double a = A[0][0]; + const double b = A[0][1]; + const double c = A[1][0]; + const double d = A[1][1]; + + double new_val[2]; + new_val[1] = a / (a*d - b*c) * (RHS[1] - c / a * RHS[0]); + new_val[0] = (RHS[0] - b * new_val[1]) / a; + + if (is_dynamic()) + { + double err = delta(RHS, new_val); + store(RHS, new_val); + if (err > m_params.m_accuracy * m_params.m_accuracy) + return 2; + else + return 1; + } + store(NULL, new_val); + return 1; } // ---------------------------------------------------------------------------------------- @@ -511,100 +509,100 @@ ATTR_HOT int netlist_matrix_solver_direct2_t::solve_non_dynamic() template <int m_N, int _storage_N> ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::solve_non_dynamic() { - bool resched = false; - - int resched_cnt = 0; - ATTR_UNUSED netlist_net_t *last_resched_net = NULL; - - /* over-relaxation not really works on these matrices */ - //const double w = 1.0; //2.0 / (1.0 + sin(3.14159 / (m_nets.count()+1))); - //const double w1 = 1.0 - w; - - double w[_storage_N]; - double one_m_w[_storage_N]; - double RHS[_storage_N]; - - for (int k = 0; k < N(); k++) - { - double gtot_t = 0.0; - double gabs_t = 0.0; - double RHS_t = 0.0; - - netlist_net_t *net = m_nets[k]; - const netlist_net_t::terminal_list_t &terms = net->m_terms; - const netlist_net_t::terminal_list_t &rails = net->m_rails; - const int term_count = terms.count(); - const int rail_count = rails.count(); - - for (int i = 0; i < rail_count; i++) - { - gtot_t += rails[i]->m_gt; - gabs_t += fabs(rails[i]->m_go); - RHS_t += rails[i]->m_Idr; - RHS_t += rails[i]->m_go * rails[i]->m_otherterm->net().Q_Analog(); - } - - for (int i = 0; i < term_count; i++) - { - gtot_t += terms[i]->m_gt; - gabs_t += fabs(terms[i]->m_go); - RHS_t += terms[i]->m_Idr; - } - - gabs_t *= m_params.m_convergence_factor; - if (gabs_t > gtot_t) - { - // Actually 1.0 / g_tot * g_tot / (gtot_t + gabs_t) - w[k] = 1.0 / (gtot_t + gabs_t); - one_m_w[k] = gabs_t / (gtot_t + gabs_t); - } - else - { - w[k] = 1.0 / gtot_t; - one_m_w[k] = 0.0; - } - - RHS[k] = RHS_t; - } - - //NL_VERBOSE_OUT(("%f %d\n", w, m_nets.count()); - do { - resched = false; - double cerr = 0.0; - - for (int k = 0; k < N(); k++) - { - netlist_net_t *net = m_nets[k]; - const netlist_net_t::terminal_list_t &terms = net->m_terms; - const int term_count = terms.count(); - - double iIdr = RHS[k]; - - for (int i = 0; i < term_count; i++) - { - iIdr += terms[i]->m_go * terms[i]->m_otherterm->net().Q_Analog(); - } - - //double new_val = (net->m_cur_Analog * gabs[k] + iIdr) / (gtot[k]); - double new_val = net->m_cur_Analog * one_m_w[k] + iIdr * w[k]; - - double e = (new_val - net->m_cur_Analog); - cerr += e * e; - - net->m_cur_Analog = net->m_new_Analog = new_val; - } - if (resched || cerr / m_nets.count() > m_params.m_accuracy * m_params.m_accuracy) - { - resched = true; - //last_resched_net = net; - } - resched_cnt++; - } while (resched && (resched_cnt < m_params.m_resched_loops / 3 )); - - if (resched) - return m_fallback.solve_non_dynamic(); - - return resched_cnt; + bool resched = false; + + int resched_cnt = 0; + ATTR_UNUSED netlist_net_t *last_resched_net = NULL; + + /* over-relaxation not really works on these matrices */ + //const double w = 1.0; //2.0 / (1.0 + sin(3.14159 / (m_nets.count()+1))); + //const double w1 = 1.0 - w; + + double w[_storage_N]; + double one_m_w[_storage_N]; + double RHS[_storage_N]; + + for (int k = 0; k < N(); k++) + { + double gtot_t = 0.0; + double gabs_t = 0.0; + double RHS_t = 0.0; + + netlist_net_t *net = m_nets[k]; + const netlist_net_t::terminal_list_t &terms = net->m_terms; + const netlist_net_t::terminal_list_t &rails = net->m_rails; + const int term_count = terms.count(); + const int rail_count = rails.count(); + + for (int i = 0; i < rail_count; i++) + { + gtot_t += rails[i]->m_gt; + gabs_t += fabs(rails[i]->m_go); + RHS_t += rails[i]->m_Idr; + RHS_t += rails[i]->m_go * rails[i]->m_otherterm->net().Q_Analog(); + } + + for (int i = 0; i < term_count; i++) + { + gtot_t += terms[i]->m_gt; + gabs_t += fabs(terms[i]->m_go); + RHS_t += terms[i]->m_Idr; + } + + gabs_t *= m_params.m_convergence_factor; + if (gabs_t > gtot_t) + { + // Actually 1.0 / g_tot * g_tot / (gtot_t + gabs_t) + w[k] = 1.0 / (gtot_t + gabs_t); + one_m_w[k] = gabs_t / (gtot_t + gabs_t); + } + else + { + w[k] = 1.0 / gtot_t; + one_m_w[k] = 0.0; + } + + RHS[k] = RHS_t; + } + + //NL_VERBOSE_OUT(("%f %d\n", w, m_nets.count()); + do { + resched = false; + double cerr = 0.0; + + for (int k = 0; k < N(); k++) + { + netlist_net_t *net = m_nets[k]; + const netlist_net_t::terminal_list_t &terms = net->m_terms; + const int term_count = terms.count(); + + double iIdr = RHS[k]; + + for (int i = 0; i < term_count; i++) + { + iIdr += terms[i]->m_go * terms[i]->m_otherterm->net().Q_Analog(); + } + + //double new_val = (net->m_cur_Analog * gabs[k] + iIdr) / (gtot[k]); + double new_val = net->m_cur_Analog * one_m_w[k] + iIdr * w[k]; + + double e = (new_val - net->m_cur_Analog); + cerr += e * e; + + net->m_cur_Analog = net->m_new_Analog = new_val; + } + if (resched || cerr / m_nets.count() > m_params.m_accuracy * m_params.m_accuracy) + { + resched = true; + //last_resched_net = net; + } + resched_cnt++; + } while (resched && (resched_cnt < m_params.m_resched_loops / 3 )); + + if (resched) + return m_fallback.solve_non_dynamic(); + + return resched_cnt; } // ---------------------------------------------------------------------------------------- @@ -615,251 +613,251 @@ typedef netlist_net_t::list_t *net_groups_t; ATTR_COLD static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net) { - if (net->isRailNet()) - return true; - for (int i = 0; i <= cur_group; i++) - { - if (groups[i].contains(net)) - return true; - } - return false; + if (net->isRailNet()) + return true; + for (int i = 0; i <= cur_group; i++) + { + if (groups[i].contains(net)) + return true; + } + return false; } ATTR_COLD static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net) { - if (net->m_list.is_empty()) - return; - /* add the net */ - SOLVER_VERBOSE_OUT(("add %d - %s\n", cur_group, net->name().cstr())); - groups[cur_group].add(net); - for (netlist_core_terminal_t *p = net->m_list.first(); p != NULL; p = net->m_list.next(p)) - { - SOLVER_VERBOSE_OUT(("terminal %s\n", p->name().cstr())); - if (p->isType(netlist_terminal_t::TERMINAL)) - { - SOLVER_VERBOSE_OUT(("isterminal\n")); - netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p); - netlist_net_t *other_net = &pt->m_otherterm->net(); - if (!already_processed(groups, cur_group, other_net)) - process_net(groups, cur_group, other_net); - } - } + if (net->m_list.is_empty()) + return; + /* add the net */ + SOLVER_VERBOSE_OUT(("add %d - %s\n", cur_group, net->name().cstr())); + groups[cur_group].add(net); + for (netlist_core_terminal_t *p = net->m_list.first(); p != NULL; p = net->m_list.next(p)) + { + SOLVER_VERBOSE_OUT(("terminal %s\n", p->name().cstr())); + if (p->isType(netlist_terminal_t::TERMINAL)) + { + SOLVER_VERBOSE_OUT(("isterminal\n")); + netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p); + netlist_net_t *other_net = &pt->m_otherterm->net(); + if (!already_processed(groups, cur_group, other_net)) + process_net(groups, cur_group, other_net); + } + } } NETLIB_START(solver) { - register_output("Q_sync", m_Q_sync); - register_output("Q_step", m_Q_step); - //register_input("FB", m_feedback); + register_output("Q_sync", m_Q_sync); + register_output("Q_step", m_Q_step); + //register_input("FB", m_feedback); - register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(5).as_double()); - m_nt_sync_delay = m_sync_delay.Value(); + register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(5).as_double()); + m_nt_sync_delay = m_sync_delay.Value(); - register_param("FREQ", m_freq, 48000.0); - m_inc = netlist_time::from_hz(m_freq.Value()); + register_param("FREQ", m_freq, 48000.0); + m_inc = netlist_time::from_hz(m_freq.Value()); - register_param("ACCURACY", m_accuracy, 1e-7); - register_param("CONVERG", m_convergence, 0.3); - register_param("RESCHED_LOOPS", m_resched_loops, 35); - register_param("PARALLEL", m_parallel, 0); - register_param("GMIN", m_gmin, NETLIST_GMIN_DEFAULT); + register_param("ACCURACY", m_accuracy, 1e-7); + register_param("CONVERG", m_convergence, 0.3); + register_param("RESCHED_LOOPS", m_resched_loops, 35); + register_param("PARALLEL", m_parallel, 0); + register_param("GMIN", m_gmin, NETLIST_GMIN_DEFAULT); - // internal staff + // internal staff - register_input("FB_sync", m_fb_sync); - register_input("FB_step", m_fb_step); + register_input("FB_sync", m_fb_sync); + register_input("FB_step", m_fb_step); - connect(m_fb_sync, m_Q_sync); - connect(m_fb_step, m_Q_step); + connect(m_fb_sync, m_Q_sync); + connect(m_fb_step, m_Q_step); - save(NAME(m_last_step)); + save(NAME(m_last_step)); } NETLIB_RESET(solver) { - m_last_step = netlist_time::zero; - for (int i = 0; i < m_mat_solvers.count(); i++) - m_mat_solvers[i]->reset(); + m_last_step = netlist_time::zero; + for (int i = 0; i < m_mat_solvers.count(); i++) + m_mat_solvers[i]->reset(); } NETLIB_UPDATE_PARAM(solver) { - m_inc = netlist_time::from_hz(m_freq.Value()); + m_inc = netlist_time::from_hz(m_freq.Value()); } NETLIB_NAME(solver)::~NETLIB_NAME(solver)() { - netlist_matrix_solver_t * const *e = m_mat_solvers.first(); - while (e != NULL) - { - netlist_matrix_solver_t * const *en = m_mat_solvers.next(e); - delete *e; - e = en; - } + netlist_matrix_solver_t * const *e = m_mat_solvers.first(); + while (e != NULL) + { + netlist_matrix_solver_t * const *en = m_mat_solvers.next(e); + delete *e; + e = en; + } } NETLIB_UPDATE(solver) { - netlist_time now = netlist().time(); - netlist_time delta = now - m_last_step; - bool do_full = false; - bool global_resched = false; - bool this_resched[100]; - int t_cnt = m_mat_solvers.count(); + netlist_time now = netlist().time(); + netlist_time delta = now - m_last_step; + bool do_full = false; + bool global_resched = false; + bool this_resched[100]; + int t_cnt = m_mat_solvers.count(); - if (delta < m_inc) - do_full = true; // we have been called between updates + if (delta < m_inc) + do_full = true; // we have been called between updates - m_last_step = now; + m_last_step = now; #if HAS_OPENMP && USE_OPENMP - if (m_parallel.Value()) - { - omp_set_num_threads(4); - omp_set_dynamic(0); - #pragma omp parallel - { - #pragma omp for nowait - for (int i = 0; i < t_cnt; i++) - { - this_resched[i] = m_mat_solvers[i]->solve(); - } - } - } - else - for (int i = 0; i < t_cnt; i++) - { - if (do_full || (m_mat_solvers[i]->is_timestep())) - this_resched[i] = m_mat_solvers[i]->solve(); - } + if (m_parallel.Value()) + { + omp_set_num_threads(4); + omp_set_dynamic(0); + #pragma omp parallel + { + #pragma omp for nowait + for (int i = 0; i < t_cnt; i++) + { + this_resched[i] = m_mat_solvers[i]->solve(); + } + } + } + else + for (int i = 0; i < t_cnt; i++) + { + if (do_full || (m_mat_solvers[i]->is_timestep())) + this_resched[i] = m_mat_solvers[i]->solve(); + } #else - for (int i = 0; i < t_cnt; i++) - { - if (do_full || (m_mat_solvers[i]->is_timestep())) - this_resched[i] = m_mat_solvers[i]->solve(); - } + for (int i = 0; i < t_cnt; i++) + { + if (do_full || (m_mat_solvers[i]->is_timestep())) + this_resched[i] = m_mat_solvers[i]->solve(); + } #endif - for (int i = 0; i < t_cnt; i++) - { - if (do_full || m_mat_solvers[i]->is_timestep()) - { - global_resched = global_resched || this_resched[i]; - if (!this_resched[i]) - m_mat_solvers[i]->update_inputs(); - } - } - - if (global_resched) - { - netlist().warning("Gobal reschedule .. Consider increasing RESCHED_LOOPS"); - schedule(); - } - else - { - /* step circuit */ - if (!m_Q_step.net().is_queued()) - m_Q_step.net().push_to_queue(m_inc); - } + for (int i = 0; i < t_cnt; i++) + { + if (do_full || m_mat_solvers[i]->is_timestep()) + { + global_resched = global_resched || this_resched[i]; + if (!this_resched[i]) + m_mat_solvers[i]->update_inputs(); + } + } + + if (global_resched) + { + netlist().warning("Gobal reschedule .. Consider increasing RESCHED_LOOPS"); + schedule(); + } + else + { + /* step circuit */ + if (!m_Q_step.net().is_queued()) + m_Q_step.net().push_to_queue(m_inc); + } } ATTR_COLD void NETLIB_NAME(solver)::post_start() { - netlist_net_t::list_t groups[100]; - int cur_group = -1; - - SOLVER_VERBOSE_OUT(("Scanning net groups ...\n")); - // determine net groups - for (netlist_net_t * const *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn)) - { - NL_VERBOSE_OUT(("proc %s\n", (*pn)->name().cstr())); - if (!already_processed(groups, cur_group, *pn)) - { - cur_group++; - process_net(groups, cur_group, *pn); - } - } - - // setup the solvers - SOLVER_VERBOSE_OUT(("Found %d net groups in %d nets\n", cur_group + 1, netlist().m_nets.count())); - for (int i = 0; i <= cur_group; i++) - { - netlist_matrix_solver_t *ms; - int net_count = groups[i].count(); - - switch (net_count) - { - case 1: - ms = new netlist_matrix_solver_direct1_t(); - break; - case 2: - ms = new netlist_matrix_solver_direct2_t(); - break; - case 3: - ms = new netlist_matrix_solver_direct_t<3,3>(); - //ms = new netlist_matrix_solver_gauss_seidel_t<3,3>(); - break; - case 4: - ms = new netlist_matrix_solver_direct_t<4,4>(); - //ms = new netlist_matrix_solver_gauss_seidel_t<4,4>(); - break; + netlist_net_t::list_t groups[100]; + int cur_group = -1; + + SOLVER_VERBOSE_OUT(("Scanning net groups ...\n")); + // determine net groups + for (netlist_net_t * const *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn)) + { + NL_VERBOSE_OUT(("proc %s\n", (*pn)->name().cstr())); + if (!already_processed(groups, cur_group, *pn)) + { + cur_group++; + process_net(groups, cur_group, *pn); + } + } + + // setup the solvers + SOLVER_VERBOSE_OUT(("Found %d net groups in %d nets\n", cur_group + 1, netlist().m_nets.count())); + for (int i = 0; i <= cur_group; i++) + { + netlist_matrix_solver_t *ms; + int net_count = groups[i].count(); + + switch (net_count) + { + case 1: + ms = new netlist_matrix_solver_direct1_t(); + break; + case 2: + ms = new netlist_matrix_solver_direct2_t(); + break; + case 3: + ms = new netlist_matrix_solver_direct_t<3,3>(); + //ms = new netlist_matrix_solver_gauss_seidel_t<3,3>(); + break; + case 4: + ms = new netlist_matrix_solver_direct_t<4,4>(); + //ms = new netlist_matrix_solver_gauss_seidel_t<4,4>(); + break; #if 0 - case 5: - //ms = new netlist_matrix_solver_direct_t<5,5>(); - ms = new netlist_matrix_solver_gauss_seidel_t<5,5>(); - break; - case 6: - //ms = new netlist_matrix_solver_direct_t<6,6>(); - ms = new netlist_matrix_solver_gauss_seidel_t<6,6>(); - break; + case 5: + //ms = new netlist_matrix_solver_direct_t<5,5>(); + ms = new netlist_matrix_solver_gauss_seidel_t<5,5>(); + break; + case 6: + //ms = new netlist_matrix_solver_direct_t<6,6>(); + ms = new netlist_matrix_solver_gauss_seidel_t<6,6>(); + break; #endif - default: - if (net_count <= 16) - { - //ms = new netlist_matrix_solver_direct_t<0,16>(); - ms = new netlist_matrix_solver_gauss_seidel_t<0,16>(); - } - else if (net_count <= 32) - { - //ms = new netlist_matrix_solver_direct_t<0,16>(); - ms = new netlist_matrix_solver_gauss_seidel_t<0,32>(); - } - else if (net_count <= 64) - { - //ms = new netlist_matrix_solver_direct_t<0,16>(); - ms = new netlist_matrix_solver_gauss_seidel_t<0,64>(); - } - else - { - netlist().error("Encountered netgroup with > 64 nets"); - ms = NULL; /* tease compilers */ - } - - break; - } - - ms->m_params.m_accuracy = m_accuracy.Value(); - ms->m_params.m_convergence_factor = m_convergence.Value(); - ms->m_params.m_resched_loops = m_resched_loops.Value(); - ms->setup(groups[i], *this); - m_mat_solvers.add(ms); - SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), (*groups[i].first())->m_head->name().cstr())); - SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic")); - SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_timestep() ? "timestep" : "no timestep")); - for (int j=0; j<groups[i].count(); j++) - { - SOLVER_VERBOSE_OUT(("Net %d: %s\n", j, groups[i][j]->name().cstr())); - netlist_net_t *n = groups[i][j]; - for (netlist_core_terminal_t *p = n->m_list.first(); p != NULL; p = n->m_list.next(p)) - { - SOLVER_VERBOSE_OUT((" %s\n", p->name().cstr())); - } - } - } + default: + if (net_count <= 16) + { + //ms = new netlist_matrix_solver_direct_t<0,16>(); + ms = new netlist_matrix_solver_gauss_seidel_t<0,16>(); + } + else if (net_count <= 32) + { + //ms = new netlist_matrix_solver_direct_t<0,16>(); + ms = new netlist_matrix_solver_gauss_seidel_t<0,32>(); + } + else if (net_count <= 64) + { + //ms = new netlist_matrix_solver_direct_t<0,16>(); + ms = new netlist_matrix_solver_gauss_seidel_t<0,64>(); + } + else + { + netlist().error("Encountered netgroup with > 64 nets"); + ms = NULL; /* tease compilers */ + } + + break; + } + + ms->m_params.m_accuracy = m_accuracy.Value(); + ms->m_params.m_convergence_factor = m_convergence.Value(); + ms->m_params.m_resched_loops = m_resched_loops.Value(); + ms->setup(groups[i], *this); + m_mat_solvers.add(ms); + SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), (*groups[i].first())->m_head->name().cstr())); + SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic")); + SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_timestep() ? "timestep" : "no timestep")); + for (int j=0; j<groups[i].count(); j++) + { + SOLVER_VERBOSE_OUT(("Net %d: %s\n", j, groups[i][j]->name().cstr())); + netlist_net_t *n = groups[i][j]; + for (netlist_core_terminal_t *p = n->m_list.first(); p != NULL; p = n->m_list.next(p)) + { + SOLVER_VERBOSE_OUT((" %s\n", p->name().cstr())); + } + } + } } diff --git a/src/emu/netlist/analog/nld_solver.h b/src/emu/netlist/analog/nld_solver.h index 99bb45d7e5b..ca8129bf207 100644 --- a/src/emu/netlist/analog/nld_solver.h +++ b/src/emu/netlist/analog/nld_solver.h @@ -15,7 +15,7 @@ #define SOLVER(_name, _freq) \ NET_REGISTER_DEV(solver, _name) \ - PARAM(_name.FREQ, _freq) + PARAM(_name.FREQ, _freq) // ---------------------------------------------------------------------------------------- // solver @@ -27,9 +27,9 @@ class NETLIB_NAME(solver); struct netlist_solver_parameters_t { - double m_accuracy; - double m_convergence_factor; - int m_resched_loops; + double m_accuracy; + double m_convergence_factor; + int m_resched_loops; }; class netlist_matrix_solver_t @@ -39,23 +39,23 @@ public: typedef netlist_core_device_t::list_t dev_list_t; netlist_matrix_solver_t() : m_owner(NULL) {} - virtual ~netlist_matrix_solver_t() {} + virtual ~netlist_matrix_solver_t() {} ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner); // return true if a reschedule is needed ... - ATTR_HOT virtual int solve_non_dynamic() = 0; + ATTR_HOT virtual int solve_non_dynamic() = 0; ATTR_HOT virtual void step(const netlist_time delta); - ATTR_HOT bool solve(); + ATTR_HOT bool solve(); ATTR_HOT void update_inputs(); - ATTR_HOT void update_dynamic(); + ATTR_HOT void update_dynamic(); ATTR_HOT void schedule(); ATTR_HOT inline bool is_dynamic() { return m_dynamic.count() > 0; } - ATTR_HOT inline bool is_timestep() { return m_steps.count() > 0; } + ATTR_HOT inline bool is_timestep() { return m_steps.count() > 0; } ATTR_HOT inline const NETLIB_NAME(solver) &owner() const; ATTR_COLD virtual void reset(); @@ -67,9 +67,9 @@ protected: dev_list_t m_dynamic; netlist_core_terminal_t::list_t m_inps; dev_list_t m_steps; - netlist_time m_last_step; + netlist_time m_last_step; - NETLIB_NAME(solver) *m_owner; + NETLIB_NAME(solver) *m_owner; }; template <int m_N, int _storage_N> @@ -77,40 +77,40 @@ class netlist_matrix_solver_direct_t: public netlist_matrix_solver_t { public: - netlist_matrix_solver_direct_t() : netlist_matrix_solver_t() {} + netlist_matrix_solver_direct_t() : netlist_matrix_solver_t() {} - virtual ~netlist_matrix_solver_direct_t() {} + virtual ~netlist_matrix_solver_direct_t() {} - ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner); - ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); } - ATTR_HOT virtual int solve_non_dynamic(); + ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner); + ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); } + ATTR_HOT virtual int solve_non_dynamic(); - ATTR_HOT inline const int N() const { return (m_N == 0) ? m_nets.count() : m_N; } + ATTR_HOT inline const int N() const { return (m_N == 0) ? m_nets.count() : m_N; } protected: - ATTR_HOT inline void build_LE(double (* RESTRICT A)[_storage_N], double (* RESTRICT RHS)); - ATTR_HOT inline void gauss_LE(double (* RESTRICT A)[_storage_N], - double (* RESTRICT RHS), - double (* RESTRICT x)); - ATTR_HOT inline double delta( - const double (* RESTRICT RHS), - const double (* RESTRICT V)); - ATTR_HOT inline void store(const double (* RESTRICT RHS), const double (* RESTRICT V)); + ATTR_HOT inline void build_LE(double (* RESTRICT A)[_storage_N], double (* RESTRICT RHS)); + ATTR_HOT inline void gauss_LE(double (* RESTRICT A)[_storage_N], + double (* RESTRICT RHS), + double (* RESTRICT x)); + ATTR_HOT inline double delta( + const double (* RESTRICT RHS), + const double (* RESTRICT V)); + ATTR_HOT inline void store(const double (* RESTRICT RHS), const double (* RESTRICT V)); - double m_RHS[_storage_N]; // right hand side - contains currents + double m_RHS[_storage_N]; // right hand side - contains currents private: - ATTR_COLD int get_net_idx(netlist_net_t *net); + ATTR_COLD int get_net_idx(netlist_net_t *net); - struct terms_t{ - int net_this; - int net_other; - netlist_terminal_t *term; - }; - int m_term_num; - int m_rail_start; - terms_t m_terms[100]; + struct terms_t{ + int net_this; + int net_other; + netlist_terminal_t *term; + }; + int m_term_num; + int m_rail_start; + terms_t m_terms[100]; }; template <int m_N, int _storage_N> @@ -118,42 +118,42 @@ class netlist_matrix_solver_gauss_seidel_t: public netlist_matrix_solver_t { public: - netlist_matrix_solver_gauss_seidel_t() : netlist_matrix_solver_t() {} + netlist_matrix_solver_gauss_seidel_t() : netlist_matrix_solver_t() {} - virtual ~netlist_matrix_solver_gauss_seidel_t() {} + virtual ~netlist_matrix_solver_gauss_seidel_t() {} - ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner) - { - netlist_matrix_solver_t::setup(nets, owner); - m_fallback.m_params = m_params; - m_fallback.setup(nets, owner); - } + ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner) + { + netlist_matrix_solver_t::setup(nets, owner); + m_fallback.m_params = m_params; + m_fallback.setup(nets, owner); + } - ATTR_HOT int solve_non_dynamic(); + ATTR_HOT int solve_non_dynamic(); - ATTR_HOT inline const int N() const { if (m_N == 0) return m_nets.count(); else return m_N; } + ATTR_HOT inline const int N() const { if (m_N == 0) return m_nets.count(); else return m_N; } - ATTR_COLD virtual void reset() - { - netlist_matrix_solver_t::reset(); - m_fallback.reset(); - } + ATTR_COLD virtual void reset() + { + netlist_matrix_solver_t::reset(); + m_fallback.reset(); + } private: - netlist_matrix_solver_direct_t<m_N, _storage_N> m_fallback; + netlist_matrix_solver_direct_t<m_N, _storage_N> m_fallback; }; class netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1> { public: - ATTR_HOT int solve_non_dynamic(); + ATTR_HOT int solve_non_dynamic(); private: }; class netlist_matrix_solver_direct2_t: public netlist_matrix_solver_direct_t<2,2> { public: - ATTR_HOT int solve_non_dynamic(); + ATTR_HOT int solve_non_dynamic(); private: }; @@ -170,9 +170,9 @@ NETLIB_DEVICE_WITH_PARAMS(solver, netlist_param_double_t m_sync_delay; netlist_param_double_t m_accuracy; netlist_param_double_t m_convergence; - netlist_param_double_t m_gmin; - netlist_param_int_t m_resched_loops; - netlist_param_int_t m_parallel; + netlist_param_double_t m_gmin; + netlist_param_int_t m_resched_loops; + netlist_param_int_t m_parallel; netlist_time m_inc; netlist_time m_last_step; diff --git a/src/emu/netlist/analog/nld_switches.c b/src/emu/netlist/analog/nld_switches.c index e1f5bf0c0b0..340808c3c46 100644 --- a/src/emu/netlist/analog/nld_switches.c +++ b/src/emu/netlist/analog/nld_switches.c @@ -11,46 +11,46 @@ NETLIB_START(switch2) { - register_sub(m_R[0], "R1"); - register_sub(m_R[1], "R2"); + register_sub(m_R[0], "R1"); + register_sub(m_R[1], "R2"); - register_param("POS", m_POS, 0); + register_param("POS", m_POS, 0); - connect(m_R[0].m_N, m_R[1].m_N); + connect(m_R[0].m_N, m_R[1].m_N); - register_subalias("1", m_R[0].m_P); - register_subalias("2", m_R[1].m_P); + register_subalias("1", m_R[0].m_P); + register_subalias("2", m_R[1].m_P); - register_subalias("Q", m_R[0].m_N); + register_subalias("Q", m_R[0].m_N); } NETLIB_RESET(switch2) { - m_R[0].do_reset(); - m_R[1].do_reset(); + m_R[0].do_reset(); + m_R[1].do_reset(); - m_R[0].set_R(R_ON); - m_R[1].set_R(R_OFF); + m_R[0].set_R(R_ON); + m_R[1].set_R(R_OFF); } NETLIB_UPDATE(switch2) { - if (m_POS.Value() == 0) - { - m_R[0].set_R(R_ON); - m_R[1].set_R(R_OFF); - } - else - { - m_R[0].set_R(R_OFF); - m_R[1].set_R(R_ON); - } - - m_R[0].update_dev(); - m_R[1].update_dev(); + if (m_POS.Value() == 0) + { + m_R[0].set_R(R_ON); + m_R[1].set_R(R_OFF); + } + else + { + m_R[0].set_R(R_OFF); + m_R[1].set_R(R_ON); + } + + m_R[0].update_dev(); + m_R[1].update_dev(); } NETLIB_UPDATE_PARAM(switch2) { - update(); + update(); } diff --git a/src/emu/netlist/analog/nld_switches.h b/src/emu/netlist/analog/nld_switches.h index df98738f470..5d8cf535379 100644 --- a/src/emu/netlist/analog/nld_switches.h +++ b/src/emu/netlist/analog/nld_switches.h @@ -25,7 +25,7 @@ // ---------------------------------------------------------------------------------------- NETLIB_DEVICE_WITH_PARAMS(switch2, - NETLIB_NAME(R_base) m_R[2]; + NETLIB_NAME(R_base) m_R[2]; netlist_param_int_t m_POS; ); diff --git a/src/emu/netlist/analog/nld_twoterm.c b/src/emu/netlist/analog/nld_twoterm.c index 0e55f4a39de..fa06c784cdf 100644 --- a/src/emu/netlist/analog/nld_twoterm.c +++ b/src/emu/netlist/analog/nld_twoterm.c @@ -12,26 +12,26 @@ ATTR_COLD netlist_generic_diode::netlist_generic_diode() { - m_Vd = 0.7; + m_Vd = 0.7; } ATTR_COLD void netlist_generic_diode::set_param(const double Is, const double n, double gmin) { - m_Is = Is; - m_n = n; - m_gmin = gmin; + m_Is = Is; + m_n = n; + m_gmin = gmin; - m_Vt = 0.0258 * m_n; + m_Vt = 0.0258 * m_n; - m_Vcrit = m_Vt * log(m_Vt / m_Is / sqrt(2.0)); - m_VtInv = 1.0 / m_Vt; + m_Vcrit = m_Vt * log(m_Vt / m_Is / sqrt(2.0)); + m_VtInv = 1.0 / m_Vt; } ATTR_COLD void netlist_generic_diode::save(pstring name, netlist_object_t &parent) { - parent.save(m_Vd, name + ".m_Vd"); - parent.save(m_Id, name + ".m_Id"); - parent.save(m_G, name + ".m_G"); + parent.save(m_Vd, name + ".m_Vd"); + parent.save(m_Id, name + ".m_Id"); + parent.save(m_G, name + ".m_G"); } // ---------------------------------------------------------------------------------------- @@ -57,11 +57,11 @@ NETLIB_RESET(twoterm) 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().solve(); - else - m_N.net().solve(); + /* we only need to call the non-rail terminal */ + if (!m_P.net().isRailNet()) + m_P.net().solve(); + else + m_N.net().solve(); } // ---------------------------------------------------------------------------------------- @@ -76,8 +76,8 @@ NETLIB_START(R_base) NETLIB_RESET(R_base) { - NETLIB_NAME(twoterm)::reset(); - set_R(1.0 / netlist().gmin()); + NETLIB_NAME(twoterm)::reset(); + set_R(1.0 / netlist().gmin()); } NETLIB_UPDATE(R_base) @@ -93,7 +93,7 @@ NETLIB_START(R) NETLIB_RESET(R) { - NETLIB_NAME(R_base)::reset(); + NETLIB_NAME(R_base)::reset(); } NETLIB_UPDATE(R) @@ -105,10 +105,10 @@ NETLIB_UPDATE_PARAM(R) { //printf("updating %s to %f\n", name().cstr(), m_R.Value()); if (m_R.Value() > 1e-9) - set_R(m_R.Value()); + set_R(m_R.Value()); else - set_R(1e-9); - update_dev(); + set_R(1e-9); + update_dev(); } // ---------------------------------------------------------------------------------------- @@ -134,8 +134,8 @@ NETLIB_START(POT) NETLIB_RESET(POT) { - m_R1.do_reset(); - m_R2.do_reset(); + m_R1.do_reset(); + m_R2.do_reset(); } NETLIB_UPDATE(POT) @@ -152,8 +152,8 @@ NETLIB_UPDATE_PARAM(POT) m_R1.set_R(MAX(m_R.Value() * v, netlist().gmin())); m_R2.set_R(MAX(m_R.Value() * (1.0 - v), netlist().gmin())); // force a schedule all - m_R1.update_dev(); - m_R2.update_dev(); + m_R1.update_dev(); + m_R2.update_dev(); } // ---------------------------------------------------------------------------------------- @@ -168,14 +168,14 @@ NETLIB_START(C) register_param("C", m_C, 1e-6); // set up the element - set(netlist().gmin(), 0.0, -5.0 / netlist().gmin()); - //set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN); + set(netlist().gmin(), 0.0, -5.0 / netlist().gmin()); + //set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN); } NETLIB_RESET(C) { - set(netlist().gmin(), 0.0, -5.0 / netlist().gmin()); - //set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN); + set(netlist().gmin(), 0.0, -5.0 / netlist().gmin()); + //set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN); } NETLIB_UPDATE_PARAM(C) @@ -215,5 +215,3 @@ NETLIB_UPDATE(D) { NETLIB_NAME(twoterm)::update(); } - - diff --git a/src/emu/netlist/analog/nld_twoterm.h b/src/emu/netlist/analog/nld_twoterm.h index 59f95c9983a..d5a2bf7d6f4 100644 --- a/src/emu/netlist/analog/nld_twoterm.h +++ b/src/emu/netlist/analog/nld_twoterm.h @@ -84,23 +84,23 @@ public: m_P.m_Idr = ( V) * G - I; } - ATTR_HOT inline double deltaV() { return m_P.net().Q_Analog()- m_N.net().Q_Analog(); } + ATTR_HOT inline double deltaV() { return m_P.net().Q_Analog()- m_N.net().Q_Analog(); } - ATTR_HOT void set_mat(double a11, double a12, double a21, double a22, double r1, double r2) - { - m_P.m_gt = a11; - m_P.m_go = -a12; - m_N.m_gt = a22; - m_N.m_go = -a21; + ATTR_HOT void set_mat(double a11, double a12, double a21, double a22, double r1, double r2) + { + m_P.m_gt = a11; + m_P.m_go = -a12; + m_N.m_gt = a22; + m_N.m_go = -a21; - m_P.m_Idr = -r1; - m_N.m_Idr = -r2; + m_P.m_Idr = -r1; + m_N.m_Idr = -r2; - } + } protected: ATTR_COLD virtual void start(); - ATTR_COLD virtual void reset(); + ATTR_COLD virtual void reset(); ATTR_HOT ATTR_ALIGN void update(); private: @@ -119,7 +119,7 @@ public: protected: ATTR_COLD virtual void start(); - ATTR_COLD virtual void reset(); + ATTR_COLD virtual void reset(); ATTR_HOT ATTR_ALIGN void update(); }; @@ -159,7 +159,7 @@ public: protected: ATTR_COLD virtual void start(); - ATTR_COLD virtual void reset(); + ATTR_COLD virtual void reset(); ATTR_COLD virtual void update_param(); ATTR_HOT ATTR_ALIGN void update(); @@ -175,67 +175,67 @@ protected: class netlist_generic_diode { public: - ATTR_COLD netlist_generic_diode(); - - ATTR_HOT inline void update_diode(const double nVd) - { - //FIXME: Optimize cutoff case - - if (nVd < -5.0 * m_Vt) - { - m_Vd = nVd; - m_G = m_gmin; - m_Id = - m_Is; - } - else if (nVd < m_Vcrit) - { - m_Vd = nVd; - - const double eVDVt = exp(m_Vd * m_VtInv); - m_Id = m_Is * (eVDVt - 1.0); - m_G = m_Is * m_VtInv * eVDVt + m_gmin; - } - else - { + ATTR_COLD netlist_generic_diode(); + + ATTR_HOT inline void update_diode(const double nVd) + { + //FIXME: Optimize cutoff case + + if (nVd < -5.0 * m_Vt) + { + m_Vd = nVd; + m_G = m_gmin; + m_Id = - m_Is; + } + else if (nVd < m_Vcrit) + { + m_Vd = nVd; + + const double eVDVt = exp(m_Vd * m_VtInv); + m_Id = m_Is * (eVDVt - 1.0); + m_G = m_Is * m_VtInv * eVDVt + m_gmin; + } + else + { #if defined(_MSC_VER) && _MSC_VER < 1800 - m_Vd = m_Vd + log((nVd - m_Vd) * m_VtInv + 1.0) * m_Vt; + m_Vd = m_Vd + log((nVd - m_Vd) * m_VtInv + 1.0) * m_Vt; #else - double a = (nVd - m_Vd) * m_VtInv; - if (a<1e-12 - 1.0) a = 1e-12 - 1.0; - m_Vd = m_Vd + log1p(a) * m_Vt; + double a = (nVd - m_Vd) * m_VtInv; + if (a<1e-12 - 1.0) a = 1e-12 - 1.0; + m_Vd = m_Vd + log1p(a) * m_Vt; #endif - const double eVDVt = exp(m_Vd * m_VtInv); - m_Id = m_Is * (eVDVt - 1.0); + const double eVDVt = exp(m_Vd * m_VtInv); + m_Id = m_Is * (eVDVt - 1.0); - m_G = m_Is * m_VtInv * eVDVt + m_gmin; - } + m_G = m_Is * m_VtInv * eVDVt + m_gmin; + } - //printf("nVd %f m_Vd %f Vcrit %f\n", nVd, m_Vd, m_Vcrit); - } + //printf("nVd %f m_Vd %f Vcrit %f\n", nVd, m_Vd, m_Vcrit); + } - ATTR_COLD void set_param(const double Is, const double n, double gmin); + ATTR_COLD void set_param(const double Is, const double n, double gmin); - ATTR_HOT inline double I() const { return m_Id; } - ATTR_HOT inline double G() const { return m_G; } - ATTR_HOT inline double Ieq() const { return (m_Id - m_Vd * m_G); } - ATTR_HOT inline double Vd() const { return m_Vd; } + ATTR_HOT inline double I() const { return m_Id; } + ATTR_HOT inline double G() const { return m_G; } + ATTR_HOT inline double Ieq() const { return (m_Id - m_Vd * m_G); } + ATTR_HOT inline double Vd() const { return m_Vd; } - /* owning object must save those ... */ + /* owning object must save those ... */ - ATTR_COLD void save(pstring name, netlist_object_t &parent); + ATTR_COLD void save(pstring name, netlist_object_t &parent); private: - double m_Vd; - double m_Id; - double m_G; + double m_Vd; + double m_Id; + double m_G; - double m_Vt; - double m_Is; - double m_n; - double m_gmin; + double m_Vt; + double m_Is; + double m_n; + double m_gmin; - double m_VtInv; - double m_Vcrit; + double m_VtInv; + double m_Vcrit; }; // ---------------------------------------------------------------------------------------- @@ -278,7 +278,7 @@ public: NETLIB_UPDATE_TERMINALS() { - m_D.update_diode(deltaV()); + m_D.update_diode(deltaV()); set(m_D.G(), 0.0, m_D.Ieq()); } |
