summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Couriersud <couriersud@users.noreply.github.com>2014-01-07 01:03:44 +0000
committer Couriersud <couriersud@users.noreply.github.com>2014-01-07 01:03:44 +0000
commit1242ec6d32874dc6c8cef63ec2224e459184526d (patch)
treebf6319c0e7dcebd329752a827cad2f4e547c86f5 /src
parent4a0c90702813e0e9fd782258321b3d7ef32b15ed (diff)
More house-cleaning on netlist. No wn
Diffstat (limited to 'src')
-rw-r--r--src/emu/netlist/analog/nld_bjt.c170
-rw-r--r--src/emu/netlist/analog/nld_bjt.h207
-rw-r--r--src/emu/netlist/analog/nld_fourterm.c88
-rw-r--r--src/emu/netlist/analog/nld_fourterm.h145
-rw-r--r--src/emu/netlist/analog/nld_twoterm.c243
-rw-r--r--src/emu/netlist/analog/nld_twoterm.h446
-rw-r--r--src/emu/netlist/devices/net_lib.h4
-rw-r--r--src/emu/netlist/netlist.mak4
8 files changed, 678 insertions, 629 deletions
diff --git a/src/emu/netlist/analog/nld_bjt.c b/src/emu/netlist/analog/nld_bjt.c
new file mode 100644
index 00000000000..ba59bb0b954
--- /dev/null
+++ b/src/emu/netlist/analog/nld_bjt.c
@@ -0,0 +1,170 @@
+/*
+ * nld_bjt.c
+ *
+ */
+
+#include "nld_bjt.h"
+#include "../nl_setup.h"
+#include "nld_solver.h"
+
+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); }
+
+private:
+ double m_Is;
+ double m_VT;
+ double m_VT_inv;
+};
+
+
+
+// ----------------------------------------------------------------------------------------
+// nld_Q
+// ----------------------------------------------------------------------------------------
+
+NETLIB_START(Q)
+{
+ register_param("model", m_model, "");
+}
+
+template <NETLIB_NAME(Q)::q_type _type>
+NETLIB_START(QBJT_switch<_type>)
+{
+ NETLIB_NAME(Q)::start();
+
+ register_sub(m_RB, "RB");
+ register_sub(m_RC, "RC");
+ register_input("BV", m_BV);
+ register_input("EV", m_EV);
+
+ register_subalias("B", m_RB.m_P);
+ register_subalias("E", m_RB.m_N);
+ register_subalias("C", m_RC.m_P);
+
+ setup().connect(m_RB.m_N, m_RC.m_N);
+ setup().connect(m_RB.m_P, m_BV);
+ setup().connect(m_RB.m_N, m_EV);
+
+ save(NAME(m_state_on));
+
+ m_RB.set(NETLIST_GMIN, 0.0, 0.0);
+ m_RC.set(NETLIST_GMIN, 0.0, 0.0);
+
+ m_state_on = 0;
+
+}
+
+NETLIB_UPDATE(Q)
+{
+ netlist().solver()->schedule();
+}
+
+template <NETLIB_NAME(Q)::q_type _type>
+NETLIB_UPDATE_PARAM(QBJT_switch<_type>)
+{
+ double IS = m_model.dValue("IS", 1e-15);
+ double BF = m_model.dValue("BF", 100);
+ double NF = m_model.dValue("NF", 1);
+ //double VJE = m_model.dValue("VJE", 0.75);
+
+ double alpha = BF / (1.0 + BF);
+
+ diode d(IS, NF);
+
+ // Assume 5mA Collector current for switch operation
+
+ m_V = d.V(0.005 / alpha);
+
+ /* Base current is 0.005 / beta
+ * as a rough estimate, we just scale the conductance down */
+
+ m_gB = d.gI(0.005 / alpha) / BF;
+
+ if (m_gB < NETLIST_GMIN)
+ m_gB = NETLIST_GMIN;
+ m_gC = BF * m_gB; // very rough estimate
+ //printf("%f %f \n", m_V, m_gB);
+ m_RB.set(NETLIST_GMIN, 0.0, 0.0);
+ m_RC.set(NETLIST_GMIN, 0.0, 0.0);
+}
+
+template NETLIB_START(QBJT_switch<NETLIB_NAME(Q)::BJT_NPN>);
+template NETLIB_START(QBJT_switch<NETLIB_NAME(Q)::BJT_PNP>);
+template NETLIB_UPDATE_PARAM(QBJT_switch<NETLIB_NAME(Q)::BJT_NPN>);
+template NETLIB_UPDATE_PARAM(QBJT_switch<NETLIB_NAME(Q)::BJT_PNP>);
+
+// ----------------------------------------------------------------------------------------
+// nld_Q - Ebers Moll
+// ----------------------------------------------------------------------------------------
+
+template <NETLIB_NAME(Q)::q_type _type>
+NETLIB_START(QBJT_EB<_type>)
+{
+ NETLIB_NAME(Q)::start();
+
+ register_terminal("B", m_D_BE.m_P); // Anode
+ register_terminal("E", m_D_BE.m_N); // Cathode
+
+ register_terminal("_B1", m_D_BC.m_P); // Anode
+ register_terminal("C", m_D_BC.m_N); // Cathode
+
+ register_terminal("_B2", m_I_BE.m_P);
+ register_terminal("_E2", m_I_BE.m_N);
+
+ register_terminal("_B3", m_I_BC.m_P);
+ register_terminal("_C1", m_I_BC.m_N);
+
+ setup().connect(m_D_BE.m_P, m_D_BC.m_P);
+ setup().connect(m_D_BE.m_P, m_I_BE.m_P);
+ setup().connect(m_D_BE.m_P, m_I_BC.m_P);
+
+ setup().connect(m_D_BE.m_N, m_I_BE.m_N);
+ setup().connect(m_D_BC.m_N, m_I_BC.m_N);
+
+ m_gD_BE.save("m_D_BE", *this);
+ m_gD_BC.save("m_D_BC", *this);
+
+}
+
+
+template <NETLIB_NAME(Q)::q_type _type>
+NETLIB_UPDATE_PARAM(QBJT_EB<_type>)
+{
+ double IS = m_model.dValue("IS", 1e-15);
+ double BF = m_model.dValue("BF", 100);
+ double NF = m_model.dValue("NF", 1);
+ double BR = m_model.dValue("BR", 1);
+ double NR = m_model.dValue("NR", 1);
+ //double VJE = m_model.dValue("VJE", 0.75);
+
+ m_alpha_f = BF / (1.0 + BF);
+ m_alpha_r = BR / (1.0 + BR);
+
+ m_gD_BE.set_param(IS / m_alpha_f, NF);
+ m_gD_BC.set_param(IS / m_alpha_r, NR);
+
+}
+
+template NETLIB_START(QBJT_EB<NETLIB_NAME(Q)::BJT_NPN>);
+template NETLIB_START(QBJT_EB<NETLIB_NAME(Q)::BJT_PNP>);
+template NETLIB_UPDATE_PARAM(QBJT_EB<NETLIB_NAME(Q)::BJT_NPN>);
+template NETLIB_UPDATE_PARAM(QBJT_EB<NETLIB_NAME(Q)::BJT_PNP>);
+
diff --git a/src/emu/netlist/analog/nld_bjt.h b/src/emu/netlist/analog/nld_bjt.h
new file mode 100644
index 00000000000..a0079895436
--- /dev/null
+++ b/src/emu/netlist/analog/nld_bjt.h
@@ -0,0 +1,207 @@
+/*
+ * nld_bjt.h
+ *
+ */
+
+#ifndef NLD_BJT_H_
+#define NLD_BJT_H_
+
+#include "../nl_base.h"
+#include "nld_twoterm.h"
+
+// ----------------------------------------------------------------------------------------
+// Macros
+// ----------------------------------------------------------------------------------------
+
+#define NETDEV_QPNP(_name, _model) \
+ NET_REGISTER_DEV(QPNP_switch, _name) \
+ NETDEV_PARAMI(_name, model, # _model)
+
+#define NETDEV_QNPN(_name, _model) \
+ NET_REGISTER_DEV(QNPN_switch, _name) \
+ NETDEV_PARAMI(_name, model, # _model)
+
+#define NETDEV_QPNP_EB(_name, _model) \
+ NET_REGISTER_DEV(QPNP_EB, _name) \
+ NETDEV_PARAMI(_name, model, # _model)
+
+#define NETDEV_QNPN_EB(_name, _model) \
+ NET_REGISTER_DEV(QNPN_switch, _name) \
+ NETDEV_PARAMI(_name, model, # _model)
+
+
+// ----------------------------------------------------------------------------------------
+// nld_Q - Base classes
+// ----------------------------------------------------------------------------------------
+
+// Have a common start for transistors
+
+class NETLIB_NAME(Q) : public netlist_device_t
+{
+public:
+ enum q_type {
+ BJT_NPN,
+ BJT_PNP
+ };
+
+ ATTR_COLD NETLIB_NAME(Q)(const q_type atype, const family_t afamily)
+ : netlist_device_t(afamily)
+ , m_qtype(atype) { }
+
+ inline q_type qtype() const { return m_qtype; }
+ inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
+protected:
+ ATTR_COLD virtual void start();
+ ATTR_HOT ATTR_ALIGN void update();
+
+ netlist_param_model_t m_model;
+private:
+ q_type m_qtype;
+};
+
+class NETLIB_NAME(QBJT) : public NETLIB_NAME(Q)
+{
+public:
+
+ ATTR_COLD NETLIB_NAME(QBJT)(const q_type atype, const family_t afamily)
+ : NETLIB_NAME(Q)(atype, afamily) { }
+
+protected:
+
+private:
+};
+
+
+
+
+// ----------------------------------------------------------------------------------------
+// nld_QBJT_switch
+// ----------------------------------------------------------------------------------------
+
+
+/*
+ * + - C
+ * B ----VVV----+ |
+ * | |
+ * Rb Rc
+ * Rb Rc
+ * Rb Rc
+ * | |
+ * +----+----+
+ * |
+ * E
+ */
+
+template <NETLIB_NAME(Q)::q_type _type>
+class NETLIB_NAME(QBJT_switch) : public NETLIB_NAME(QBJT)
+{
+public:
+ ATTR_COLD NETLIB_NAME(QBJT_switch)()
+ : NETLIB_NAME(QBJT)(_type, BJT_SWITCH), m_gB(NETLIST_GMIN), m_gC(NETLIST_GMIN), m_V(0.0), m_state_on(0) { }
+
+ NETLIB_UPDATEI()
+ {
+ double vE = INPANALOG(m_EV);
+ double vB = INPANALOG(m_BV);
+ double m = (_type == BJT_NPN) ? 1 : -1;
+
+ int new_state = ((vB - vE) * 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;
+ m_RB.update_dev();
+ m_RC.update_dev();
+ }
+
+ }
+
+ NETLIB_NAME(R) m_RB;
+ NETLIB_NAME(R) m_RC;
+
+ netlist_analog_input_t m_BV;
+ netlist_analog_input_t m_EV;
+
+protected:
+
+ 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;
+
+private:
+};
+
+typedef NETLIB_NAME(QBJT_switch)<NETLIB_NAME(Q)::BJT_PNP> NETLIB_NAME(QPNP_switch);
+typedef NETLIB_NAME(QBJT_switch)<NETLIB_NAME(Q)::BJT_NPN> NETLIB_NAME(QNPN_switch);
+
+// ----------------------------------------------------------------------------------------
+// nld_QBJT_EB
+// ----------------------------------------------------------------------------------------
+
+
+
+
+template <NETLIB_NAME(Q)::q_type _type>
+class NETLIB_NAME(QBJT_EB) : public NETLIB_NAME(QBJT)
+{
+public:
+ ATTR_COLD NETLIB_NAME(QBJT_EB)()
+ : NETLIB_NAME(QBJT)(_type, BJT_EB),
+ m_D_BC(netlist_object_t::ANALOG),
+ m_D_BE(netlist_object_t::ANALOG),
+ m_I_BC(netlist_object_t::ANALOG),
+ m_I_BE(netlist_object_t::ANALOG)
+ { }
+
+ NETLIB_UPDATE_TERMINALS()
+ {
+ m_gD_BE.update_diode(m_D_BE.deltaV());
+ m_gD_BC.update_diode(m_D_BC.deltaV());
+
+ m_D_BE.set(m_gD_BE.G(), 0.0, m_gD_BE.Ieq());
+ m_D_BC.set(m_gD_BC.G(), 0.0, m_gD_BC.Ieq());
+
+ m_I_BE.set(0.0, 0.0, - m_alpha_r * m_gD_BC.I());
+ m_I_BC.set(0.0, 0.0, - m_alpha_f * m_gD_BE.I());
+ }
+
+protected:
+
+ ATTR_COLD virtual void start();
+ ATTR_HOT void update_param();
+
+ netlist_generic_diode m_gD_BC;
+ netlist_generic_diode m_gD_BE;
+
+ nld_twoterm m_D_BC;
+ nld_twoterm m_D_BE;
+
+ nld_twoterm m_I_BC;
+ nld_twoterm m_I_BE;
+
+ double m_alpha_f;
+ double m_alpha_r;
+
+private:
+};
+
+typedef NETLIB_NAME(QBJT_EB)<NETLIB_NAME(Q)::BJT_PNP> NETLIB_NAME(QPNP_EB);
+typedef NETLIB_NAME(QBJT_EB)<NETLIB_NAME(Q)::BJT_NPN> NETLIB_NAME(QNPN_EB);
+
+
+#endif /* NLD_BJT_H_ */
diff --git a/src/emu/netlist/analog/nld_fourterm.c b/src/emu/netlist/analog/nld_fourterm.c
new file mode 100644
index 00000000000..0c8a51e07cb
--- /dev/null
+++ b/src/emu/netlist/analog/nld_fourterm.c
@@ -0,0 +1,88 @@
+/*
+ * nld_fourterm.c
+ *
+ */
+
+#include "nld_fourterm.h"
+#include "../nl_setup.h"
+#include "nld_solver.h"
+
+// ----------------------------------------------------------------------------------------
+// nld_VCCS
+// ----------------------------------------------------------------------------------------
+
+NETLIB_START(VCCS)
+{
+ configure(1.0, NETLIST_GMIN);
+}
+
+ATTR_COLD void NETLIB_NAME(VCCS)::configure(const double Gfac, const double GI)
+{
+ register_param("G", m_G, 1.0);
+
+ register_terminal("IP", m_IP);
+ register_terminal("IN", m_IN);
+ register_terminal("OP", m_OP);
+ register_terminal("ON", m_ON);
+
+ m_OP1.init_object(*this, name() + ".OP1", netlist_core_terminal_t::STATE_INP_ACTIVE);
+ m_ON1.init_object(*this, name() + ".ON1", netlist_core_terminal_t::STATE_INP_ACTIVE);
+
+ const double m_mult = m_G.Value() * Gfac; // 1.0 ==> 1V ==> 1A
+ m_IP.set(GI);
+ m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
+ m_IN.set(GI);
+ m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
+
+ m_OP.set(m_mult, 0.0);
+ m_OP.m_otherterm = &m_IP;
+ m_OP1.set(-m_mult, 0.0);
+ m_OP1.m_otherterm = &m_IN;
+
+ m_ON.set(-m_mult, 0.0);
+ m_ON.m_otherterm = &m_IP;
+ m_ON1.set(m_mult, 0.0);
+ m_ON1.m_otherterm = &m_IN;
+
+ setup().connect(m_OP, m_OP1);
+ setup().connect(m_ON, m_ON1);
+}
+
+NETLIB_UPDATE_PARAM(VCCS)
+{
+}
+
+NETLIB_UPDATE(VCCS)
+{
+ /* only called if connected to a rail net ==> notify the solver to recalculate */
+ netlist().solver()->schedule();
+}
+
+// ----------------------------------------------------------------------------------------
+// nld_VCVS
+// ----------------------------------------------------------------------------------------
+
+NETLIB_START(VCVS)
+{
+ register_param("RO", m_RO, 1.0);
+
+ const double gRO = 1.0 / m_RO.Value();
+
+ configure(gRO, NETLIST_GMIN);
+
+ m_OP2.init_object(*this, "OP2", netlist_core_terminal_t::STATE_INP_ACTIVE);
+ m_ON2.init_object(*this, "ON2", netlist_core_terminal_t::STATE_INP_ACTIVE);
+
+ m_OP2.set(gRO);
+ m_ON2.set(gRO);
+ m_OP2.m_otherterm = &m_ON2;
+ m_ON2.m_otherterm = &m_OP2;
+
+ setup().connect(m_OP2, m_OP1);
+ setup().connect(m_ON2, m_ON1);
+}
+
+NETLIB_UPDATE_PARAM(VCVS)
+{
+}
+
diff --git a/src/emu/netlist/analog/nld_fourterm.h b/src/emu/netlist/analog/nld_fourterm.h
new file mode 100644
index 00000000000..0520329a08d
--- /dev/null
+++ b/src/emu/netlist/analog/nld_fourterm.h
@@ -0,0 +1,145 @@
+/*
+ * nld_fourterm.h
+ *
+ */
+
+#ifndef NLD_FOURTERM_H_
+#define NLD_FOURTERM_H_
+
+
+#include "../nl_base.h"
+#include "nld_twoterm.h"
+
+// ----------------------------------------------------------------------------------------
+// Macros
+// ----------------------------------------------------------------------------------------
+
+#define NETDEV_VCCS(_name) \
+ NET_REGISTER_DEV(VCCS, _name)
+//NETDEV_PARAMI(_name, model, _model)
+
+#define NETDEV_VCVS(_name) \
+ NET_REGISTER_DEV(VCVS, _name)
+//NETDEV_PARAMI(_name, model, _model)
+
+// ----------------------------------------------------------------------------------------
+// nld_CCCS
+// ----------------------------------------------------------------------------------------
+
+/*
+ * Current controlled current source
+ *
+ * IP ---+ +------> OP
+ * | |
+ * RI I
+ * RI => G => I IOut = (V(IP)-V(IN)) / RI * G
+ * RI I
+ * | |
+ * IN ---+ +------< ON
+ *
+ * G=1 ==> 1A ==> 1A
+ *
+ * RI = 1
+ *
+ * FIXME: This needs extremely high levels of accuracy to work
+ * With the current default of 1mv we can only measure
+ * currents of 1mA. Therefore not yet implemented.
+ *
+ */
+
+
+// ----------------------------------------------------------------------------------------
+// nld_VCCS
+// ----------------------------------------------------------------------------------------
+
+/*
+ * Voltage controlled current source
+ *
+ * IP ---+ +------> OP
+ * | |
+ * RI I
+ * RI => G => I IOut = (V(IP)-V(IN)) * G
+ * RI I
+ * | |
+ * IN ---+ +------< ON
+ *
+ * G=1 ==> 1V ==> 1A
+ *
+ * RI = 1 / NETLIST_GMIN
+ *
+ */
+
+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) { }
+
+protected:
+ ATTR_COLD virtual void start();
+ ATTR_COLD virtual void update_param();
+ ATTR_HOT ATTR_ALIGN void update();
+
+ ATTR_COLD void configure(const double Gfac, const double GI);
+
+ netlist_terminal_t m_OP;
+ netlist_terminal_t m_ON;
+
+ netlist_terminal_t m_IP;
+ netlist_terminal_t m_IN;
+
+ netlist_terminal_t m_OP1;
+ netlist_terminal_t m_ON1;
+
+ netlist_param_double_t m_G;
+};
+
+// ----------------------------------------------------------------------------------------
+// nld_VCVS
+// ----------------------------------------------------------------------------------------
+
+/*
+ * Voltage controlled voltage source
+ *
+ * Parameters:
+ * G Default: 1
+ * RO Default: 1 (would be typically 50 for an op-amp
+ *
+ * IP ---+ +--+---- OP
+ * | | |
+ * RI I RO
+ * RI => G => I RO V(OP) - V(ON) = (V(IP)-V(IN)) * G
+ * RI I RO
+ * | | |
+ * IN ---+ +--+---- ON
+ *
+ * G=1 ==> 1V ==> 1V
+ *
+ * RI = 1 / NETLIST_GMIN
+ *
+ * Internal GI = G / RO
+ *
+ */
+
+
+class NETLIB_NAME(VCVS) : public NETLIB_NAME(VCCS)
+{
+public:
+ ATTR_COLD NETLIB_NAME(VCVS)()
+ : NETLIB_NAME(VCCS)(VCVS) { }
+
+protected:
+ ATTR_COLD virtual void start();
+ ATTR_COLD virtual void update_param();
+ //ATTR_HOT ATTR_ALIGN void update();
+
+ netlist_terminal_t m_OP2;
+ netlist_terminal_t m_ON2;
+
+ netlist_param_double_t m_RO;
+};
+
+
+#endif /* NLD_FOURTERM_H_ */
diff --git a/src/emu/netlist/analog/nld_twoterm.c b/src/emu/netlist/analog/nld_twoterm.c
index 5dc493a9b84..c2ebd93f0d8 100644
--- a/src/emu/netlist/analog/nld_twoterm.c
+++ b/src/emu/netlist/analog/nld_twoterm.c
@@ -127,23 +127,17 @@ NETLIB_START(D)
register_terminal("K", m_N);
register_param("model", m_model, "");
- m_Vd = 0.7;
-
- save(NAME(m_Vd));
+ m_D.save("m_D", *this);
}
NETLIB_UPDATE_PARAM(D)
{
- m_Is = m_model.dValue("Is", 1e-15);
- m_n = m_model.dValue("N", 1);
-
- m_Vt = 0.0258 * m_n;
+ double Is = m_model.dValue("Is", 1e-15);
+ double n = m_model.dValue("N", 1);
- m_Vcrit = m_Vt * log(m_Vt / m_Is / sqrt(2.0));
- m_VtInv = 1.0 / m_Vt;
- NL_VERBOSE_OUT(("VCutoff: %f\n", m_Vcrit));
+ m_D.set_param(Is, n);
}
NETLIB_UPDATE(D)
@@ -151,233 +145,4 @@ NETLIB_UPDATE(D)
NETLIB_NAME(twoterm)::update();
}
-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); }
-
-private:
- double m_Is;
- double m_VT;
- double m_VT_inv;
-};
-
-// ----------------------------------------------------------------------------------------
-// nld_Q
-// ----------------------------------------------------------------------------------------
-
-NETLIB_START(Q)
-{
- register_param("model", m_model, "");
-}
-
-template <NETLIB_NAME(Q)::q_type _type>
-NETLIB_START(QBJT_switch<_type>)
-{
- NETLIB_NAME(Q)::start();
-
- register_sub(m_RB, "RB");
- register_sub(m_RC, "RC");
- register_input("BV", m_BV);
- register_input("EV", m_EV);
-
- register_subalias("B", m_RB.m_P);
- register_subalias("E", m_RB.m_N);
- register_subalias("C", m_RC.m_P);
-
- setup().connect(m_RB.m_N, m_RC.m_N);
- setup().connect(m_RB.m_P, m_BV);
- setup().connect(m_RB.m_N, m_EV);
-
- save(NAME(m_state_on));
-
- m_RB.set(NETLIST_GMIN, 0.0, 0.0);
- m_RC.set(NETLIST_GMIN, 0.0, 0.0);
-
- m_state_on = 0;
-
-}
-
-NETLIB_UPDATE(Q)
-{
- netlist().solver()->schedule();
-}
-
-template <NETLIB_NAME(Q)::q_type _type>
-NETLIB_UPDATE_PARAM(QBJT_switch<_type>)
-{
- double IS = m_model.dValue("IS", 1e-15);
- double BF = m_model.dValue("BF", 100);
- double NF = m_model.dValue("NF", 1);
- //double VJE = m_model.dValue("VJE", 0.75);
-
- //double alpha = BF / (1.0 + BF);
-
- diode d(IS, NF);
-
- // Assume 5mA Collector current for switch operation
-
- m_V = d.V(0.005 / BF);
-
- m_gB = d.gI(0.005 / BF);
- if (m_gB < NETLIST_GMIN)
- m_gB = NETLIST_GMIN;
- m_gC = BF * m_gB; // very rough estimate
- //printf("%f %f \n", m_V, m_gB);
- m_RB.set(NETLIST_GMIN, 0.0, 0.0);
- m_RC.set(NETLIST_GMIN, 0.0, 0.0);
-}
-
-template NETLIB_START(QBJT_switch<NETLIB_NAME(Q)::BJT_NPN>);
-template NETLIB_START(QBJT_switch<NETLIB_NAME(Q)::BJT_PNP>);
-template NETLIB_UPDATE_PARAM(QBJT_switch<NETLIB_NAME(Q)::BJT_NPN>);
-template NETLIB_UPDATE_PARAM(QBJT_switch<NETLIB_NAME(Q)::BJT_PNP>);
-
-// ----------------------------------------------------------------------------------------
-// nld_Q - Ebers Moll
-// ----------------------------------------------------------------------------------------
-
-template <NETLIB_NAME(Q)::q_type _type>
-NETLIB_START(QBJT_EB<_type>)
-{
- NETLIB_NAME(Q)::start();
-
- register_terminal("B", m_D_BE.m_tt.m_P); // Anode
- register_terminal("E", m_D_BE.m_tt.m_N); // Cathode
-
- register_terminal("_B1", m_D_BC.m_tt.m_P); // Anode
- register_terminal("C", m_D_BC.m_tt.m_N); // Cathode
-
- register_terminal("_B2", m_I_BE.m_P);
- register_terminal("_E2", m_I_BE.m_N);
-
- register_terminal("_B3", m_I_BC.m_P);
- register_terminal("_C1", m_I_BC.m_N);
-
- setup().connect(m_D_BE.m_tt.m_P, m_D_BC.m_tt.m_P);
- setup().connect(m_D_BE.m_tt.m_P, m_I_BE.m_P);
- setup().connect(m_D_BE.m_tt.m_P, m_I_BC.m_P);
-
- setup().connect(m_D_BE.m_tt.m_N, m_I_BE.m_N);
- setup().connect(m_D_BC.m_tt.m_N, m_I_BC.m_N);
-
-}
-
-
-template <NETLIB_NAME(Q)::q_type _type>
-NETLIB_UPDATE_PARAM(QBJT_EB<_type>)
-{
- double IS = m_model.dValue("IS", 1e-15);
- double BF = m_model.dValue("BF", 100);
- double NF = m_model.dValue("NF", 1);
- double BR = m_model.dValue("BR", 1);
- double NR = m_model.dValue("NR", 1);
- //double VJE = m_model.dValue("VJE", 0.75);
-
- m_alpha_f = BF / (1.0 + BF);
- m_alpha_r = BR / (1.0 + BR);
-
- m_D_BE.set_param(IS / m_alpha_f, NF);
- m_D_BC.set_param(IS / m_alpha_r, NR);
-
-}
-
-template NETLIB_START(QBJT_EB<NETLIB_NAME(Q)::BJT_NPN>);
-template NETLIB_START(QBJT_EB<NETLIB_NAME(Q)::BJT_PNP>);
-template NETLIB_UPDATE_PARAM(QBJT_EB<NETLIB_NAME(Q)::BJT_NPN>);
-template NETLIB_UPDATE_PARAM(QBJT_EB<NETLIB_NAME(Q)::BJT_PNP>);
-
-// ----------------------------------------------------------------------------------------
-// nld_VCCS
-// ----------------------------------------------------------------------------------------
-
-NETLIB_START(VCCS)
-{
- configure(1.0, NETLIST_GMIN);
-}
-
-ATTR_COLD void NETLIB_NAME(VCCS)::configure(const double Gfac, const double GI)
-{
- register_param("G", m_G, 1.0);
-
- register_terminal("IP", m_IP);
- register_terminal("IN", m_IN);
- register_terminal("OP", m_OP);
- register_terminal("ON", m_ON);
-
- m_OP1.init_object(*this, name() + ".OP1", netlist_core_terminal_t::STATE_INP_ACTIVE);
- m_ON1.init_object(*this, name() + ".ON1", netlist_core_terminal_t::STATE_INP_ACTIVE);
-
- const double m_mult = m_G.Value() * Gfac; // 1.0 ==> 1V ==> 1A
- m_IP.set(GI);
- m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
- m_IN.set(GI);
- m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
-
- m_OP.set(m_mult, 0.0);
- m_OP.m_otherterm = &m_IP;
- m_OP1.set(-m_mult, 0.0);
- m_OP1.m_otherterm = &m_IN;
-
- m_ON.set(-m_mult, 0.0);
- m_ON.m_otherterm = &m_IP;
- m_ON1.set(m_mult, 0.0);
- m_ON1.m_otherterm = &m_IN;
-
- setup().connect(m_OP, m_OP1);
- setup().connect(m_ON, m_ON1);
-}
-
-NETLIB_UPDATE_PARAM(VCCS)
-{
-}
-
-NETLIB_UPDATE(VCCS)
-{
- /* only called if connected to a rail net ==> notify the solver to recalculate */
- netlist().solver()->schedule();
-}
-
-// ----------------------------------------------------------------------------------------
-// nld_VCVS
-// ----------------------------------------------------------------------------------------
-NETLIB_START(VCVS)
-{
- register_param("RO", m_RO, 1.0);
-
- const double gRO = 1.0 / m_RO.Value();
-
- configure(gRO, NETLIST_GMIN);
-
- m_OP2.init_object(*this, "OP2", netlist_core_terminal_t::STATE_INP_ACTIVE);
- m_ON2.init_object(*this, "ON2", netlist_core_terminal_t::STATE_INP_ACTIVE);
-
- m_OP2.set(gRO);
- m_ON2.set(gRO);
- m_OP2.m_otherterm = &m_ON2;
- m_ON2.m_otherterm = &m_OP2;
-
- setup().connect(m_OP2, m_OP1);
- setup().connect(m_ON2, m_ON1);
-}
-
-NETLIB_UPDATE_PARAM(VCVS)
-{
-}
diff --git a/src/emu/netlist/analog/nld_twoterm.h b/src/emu/netlist/analog/nld_twoterm.h
index 894afdfbf9b..74a589ac233 100644
--- a/src/emu/netlist/analog/nld_twoterm.h
+++ b/src/emu/netlist/analog/nld_twoterm.h
@@ -57,23 +57,6 @@
NET_REGISTER_DEV(D, _name) \
NETDEV_PARAMI(_name, model, # _model)
-#define NETDEV_QPNP(_name, _model) \
- NET_REGISTER_DEV(QPNP_switch, _name) \
- NETDEV_PARAMI(_name, model, # _model)
-
-#define NETDEV_QNPN(_name, _model) \
- NET_REGISTER_DEV(QNPN_switch, _name) \
- NETDEV_PARAMI(_name, model, # _model)
-
-#define NETDEV_QPNP_EB(_name, _model) \
- NET_REGISTER_DEV(QPNP_EB, _name) \
- NETDEV_PARAMI(_name, model, # _model)
-
-#define NETDEV_QNPN_EB(_name, _model) \
- NET_REGISTER_DEV(QNPN_switch, _name) \
- NETDEV_PARAMI(_name, model, # _model)
-
-
// ----------------------------------------------------------------------------------------
// Implementation
// ----------------------------------------------------------------------------------------
@@ -100,6 +83,9 @@ public:
m_N.m_Idr = ( -V) * G + I;
m_P.m_Idr = ( V) * G - I;
}
+
+ ATTR_HOT inline double deltaV() { return m_P.net().Q_Analog()- m_N.net().Q_Analog(); }
+
protected:
ATTR_COLD virtual void start();
ATTR_HOT ATTR_ALIGN void update();
@@ -153,7 +139,7 @@ public:
ATTR_HOT void step_time(const double st)
{
double G = m_C.Value() / st;
- double I = -G * (m_P.net().Q_Analog()- m_N.net().Q_Analog());
+ double I = -G * deltaV();
set(G, 0.0, I);
}
@@ -166,237 +152,24 @@ protected:
};
-// ----------------------------------------------------------------------------------------
-// nld_D
-// ----------------------------------------------------------------------------------------
-
-
-// this one has an accuracy of better than 5%. That's enough for our purpose
-// add c3 and it'll be better than 1%
-
-#if 0
-inline double fastexp_h(const double x)
-{
- static const double ln2r = 1.442695040888963387;
- static const double ln2 = 0.693147180559945286;
- //static const double c3 = 0.166666666666666667;
-
- const double y = x * ln2r;
- const unsigned int t = y;
- const double z = (x - ln2 * (double) t);
- const double zz = z * z;
- //const double zzz = zz * z;
-
- return (double)(1 << t)*(1.0 + z + 0.5 * zz); // + c3*zzz;
-}
-
-inline double fastexp(const double x)
-{
- if (x<0)
- return 1.0 / fastexp_h(-x);
- else
- return fastexp_h(x);
-}
-#endif
-
-class NETLIB_NAME(D) : public NETLIB_NAME(twoterm)
-{
-public:
- ATTR_COLD NETLIB_NAME(D)() : NETLIB_NAME(twoterm)(DIODE) { }
-
- NETLIB_UPDATE_TERMINALS()
- {
- const double nVd = m_P.net().Q_Analog()- m_N.net().Q_Analog();
-
- //FIXME: Optimize cutoff case
-
- double Id;
- double G;
-
- if (nVd < -5.0 * m_Vt)
- {
- m_Vd = nVd;
- G = NETLIST_GMIN;
- Id = - m_Is;
- }
- else if (nVd < m_Vcrit)
- {
- m_Vd = nVd;
-
- const double eVDVt = exp(m_Vd * m_VtInv);
- Id = m_Is * (eVDVt - 1.0);
- G = m_Is * m_VtInv * eVDVt;
- }
- else
- {
-#if defined(_MSC_VER) && _MSC_VER < 1800
- m_Vd = m_Vd + log((nVd - m_Vd) * m_VtInv + 1.0) * m_Vt;
-#else
- m_Vd = m_Vd + log1p((nVd - m_Vd) * m_VtInv) * m_Vt;
-#endif
- const double eVDVt = exp(m_Vd * m_VtInv);
- Id = m_Is * (eVDVt - 1.0);
-
- G = m_Is * m_VtInv * eVDVt;
- }
-
- double I = (Id - m_Vd * G);
- set(G, 0.0, I);
- }
-
-protected:
- ATTR_COLD virtual void start();
- ATTR_COLD virtual void update_param();
- ATTR_HOT ATTR_ALIGN void update();
-
- netlist_param_model_t m_model;
-
- double m_Vt;
- double m_Is;
- double m_n;
-
- double m_VtInv;
- double m_Vcrit;
- double m_Vd;
-
-};
-
-// ----------------------------------------------------------------------------------------
-// nld_Q - Base classes
-// ----------------------------------------------------------------------------------------
-
-// Have a common start for transistors
-
-class NETLIB_NAME(Q) : public netlist_device_t
-{
-public:
- enum q_type {
- BJT_NPN,
- BJT_PNP
- };
-
- ATTR_COLD NETLIB_NAME(Q)(const q_type atype, const family_t afamily)
- : netlist_device_t(afamily)
- , m_qtype(atype) { }
-
- inline q_type qtype() const { return m_qtype; }
- inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
-protected:
- ATTR_COLD virtual void start();
- ATTR_HOT ATTR_ALIGN void update();
-
- netlist_param_model_t m_model;
-private:
- q_type m_qtype;
-};
-
-class NETLIB_NAME(QBJT) : public NETLIB_NAME(Q)
-{
-public:
-
- ATTR_COLD NETLIB_NAME(QBJT)(const q_type atype, const family_t afamily)
- : NETLIB_NAME(Q)(atype, afamily) { }
-
-protected:
-
-private:
-};
// ----------------------------------------------------------------------------------------
-// nld_QBJT_switch
+// A generic diode model to be used in other devices (Diode, BJT ...)
// ----------------------------------------------------------------------------------------
-
-/*
- * + - C
- * B ----VVV----+ |
- * | |
- * Rb Rc
- * Rb Rc
- * Rb Rc
- * | |
- * +----+----+
- * |
- * E
- */
-
-template <NETLIB_NAME(Q)::q_type _type>
-class NETLIB_NAME(QBJT_switch) : public NETLIB_NAME(QBJT)
+class netlist_generic_diode
{
public:
- ATTR_COLD NETLIB_NAME(QBJT_switch)()
- : NETLIB_NAME(QBJT)(_type, BJT_SWITCH), m_gB(NETLIST_GMIN), m_gC(NETLIST_GMIN), m_V(0.0), m_state_on(0) { }
-
- NETLIB_UPDATEI()
- {
- double vE = INPANALOG(m_EV);
- double vB = INPANALOG(m_BV);
- double m = (_type == BJT_NPN) ? 1 : -1;
-
- int new_state = ((vB - vE) * 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;
- m_RB.update_dev();
- m_RC.update_dev();
- }
-
- }
-
- NETLIB_NAME(R) m_RB;
- NETLIB_NAME(R) m_RC;
-
- netlist_analog_input_t m_BV;
- netlist_analog_input_t m_EV;
-
-protected:
-
- 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;
-
-private:
-};
-
-typedef NETLIB_NAME(QBJT_switch)<NETLIB_NAME(Q)::BJT_PNP> NETLIB_NAME(QPNP_switch);
-typedef NETLIB_NAME(QBJT_switch)<NETLIB_NAME(Q)::BJT_NPN> NETLIB_NAME(QNPN_switch);
-
-// ----------------------------------------------------------------------------------------
-// nld_QBJT_EB
-// ----------------------------------------------------------------------------------------
-
-struct generic_diode
-{
- generic_diode() : m_tt(netlist_object_t::ANALOG) {}
+ netlist_generic_diode() {}
- ATTR_HOT inline void update_diode()
+ ATTR_HOT inline void update_diode(const double nVd)
{
//FIXME: Optimize cutoff case
- const double nVd = m_tt.m_P.net().Q_Analog()- m_tt.m_N.net().Q_Analog();
-
- double G;
-
if (nVd < -5.0 * m_Vt)
{
m_Vd = nVd;
- G = NETLIST_GMIN;
+ m_G = NETLIST_GMIN;
m_Id = - m_Is;
}
else if (nVd < m_Vcrit)
@@ -405,7 +178,7 @@ struct generic_diode
const double eVDVt = exp(m_Vd * m_VtInv);
m_Id = m_Is * (eVDVt - 1.0);
- G = m_Is * m_VtInv * eVDVt;
+ m_G = m_Is * m_VtInv * eVDVt;
}
else
{
@@ -417,11 +190,9 @@ struct generic_diode
const double eVDVt = exp(m_Vd * m_VtInv);
m_Id = m_Is * (eVDVt - 1.0);
- G = m_Is * m_VtInv * eVDVt;
+ m_G = m_Is * m_VtInv * eVDVt;
}
- double I = (m_Id - m_Vd * G);
- m_tt.set(G, 0.0, I);
//printf("nVd %f m_Vd %f Vcrit %f\n", nVd, m_Vd, m_Vcrit);
}
@@ -439,11 +210,22 @@ struct generic_diode
}
ATTR_HOT inline double I() { return m_Id; }
+ ATTR_HOT inline double G() { return m_G; }
+ ATTR_HOT inline double Ieq() { return (m_Id - m_Vd * m_G); }
- nld_twoterm m_tt;
+ /* owning object must save those ... */
+
+ void 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");
+ }
private:
+ double m_Vd;
double m_Id;
+ double m_G;
double m_Vt;
double m_Is;
@@ -451,174 +233,62 @@ private:
double m_VtInv;
double m_Vcrit;
- double m_Vd;
};
-
-template <NETLIB_NAME(Q)::q_type _type>
-class NETLIB_NAME(QBJT_EB) : public NETLIB_NAME(QBJT)
-{
-public:
- ATTR_COLD NETLIB_NAME(QBJT_EB)()
- : NETLIB_NAME(QBJT)(_type, BJT_EB),
- m_I_BC(netlist_object_t::ANALOG),
- m_I_BE(netlist_object_t::ANALOG)
- { }
-
- NETLIB_UPDATE_TERMINALS()
- {
- m_D_BE.update_diode();
- m_D_BC.update_diode();
- m_I_BC.set(0.0, 0.0, - m_alpha_f * m_D_BE.I());
- m_I_BE.set(0.0, 0.0, - m_alpha_r * m_D_BC.I());
- }
-
-protected:
-
- ATTR_COLD virtual void start();
- ATTR_HOT void update_param();
-
- generic_diode m_D_BE;
- generic_diode m_D_BC;
-
- nld_twoterm m_I_BC;
- nld_twoterm m_I_BE;
-
- double m_alpha_f;
- double m_alpha_r;
-
-private:
-};
-
-typedef NETLIB_NAME(QBJT_EB)<NETLIB_NAME(Q)::BJT_PNP> NETLIB_NAME(QPNP_EB);
-typedef NETLIB_NAME(QBJT_EB)<NETLIB_NAME(Q)::BJT_NPN> NETLIB_NAME(QNPN_EB);
-
-// ----------------------------------------------------------------------------------------
-// nld_CCCS
-// ----------------------------------------------------------------------------------------
-
-/*
- * Current controlled current source
- *
- * IP ---+ +------> OP
- * | |
- * RI I
- * RI => G => I IOut = (V(IP)-V(IN)) / RI * G
- * RI I
- * | |
- * IN ---+ +------< ON
- *
- * G=1 ==> 1A ==> 1A
- *
- * RI = 1
- *
- * FIXME: This needs extremely high levels of accuracy to work
- * With the current default of 1mv we can only measure
- * currents of 1mA. Therefore not yet implemented.
- *
- */
-
-
// ----------------------------------------------------------------------------------------
-// nld_VCCS
+// nld_D
// ----------------------------------------------------------------------------------------
-/*
- * Voltage controlled current source
- *
- * IP ---+ +------> OP
- * | |
- * RI I
- * RI => G => I IOut = (V(IP)-V(IN)) * G
- * RI I
- * | |
- * IN ---+ +------< ON
- *
- * G=1 ==> 1V ==> 1A
- *
- * RI = 1 / NETLIST_GMIN
- *
- */
-#define NETDEV_VCCS(_name) \
- NET_REGISTER_DEV(VCCS, _name)
-//NETDEV_PARAMI(_name, model, _model)
+// this one has an accuracy of better than 5%. That's enough for our purpose
+// add c3 and it'll be better than 1%
-class NETLIB_NAME(VCCS) : public netlist_device_t
+#if 0
+inline double fastexp_h(const double x)
{
-public:
- 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 update_param();
- ATTR_HOT ATTR_ALIGN void update();
-
- ATTR_COLD void configure(const double Gfac, const double GI);
-
- netlist_terminal_t m_OP;
- netlist_terminal_t m_ON;
-
- netlist_terminal_t m_IP;
- netlist_terminal_t m_IN;
-
- netlist_terminal_t m_OP1;
- netlist_terminal_t m_ON1;
-
- netlist_param_double_t m_G;
-};
-
-// ----------------------------------------------------------------------------------------
-// nld_VCVS
-// ----------------------------------------------------------------------------------------
+ static const double ln2r = 1.442695040888963387;
+ static const double ln2 = 0.693147180559945286;
+ //static const double c3 = 0.166666666666666667;
-/*
- * Voltage controlled voltage source
- *
- * Parameters:
- * G Default: 1
- * RO Default: 1 (would be typically 50 for an op-amp
- *
- * IP ---+ +--+---- OP
- * | | |
- * RI I RO
- * RI => G => I RO V(OP) - V(ON) = (V(IP)-V(IN)) * G
- * RI I RO
- * | | |
- * IN ---+ +--+---- ON
- *
- * G=1 ==> 1V ==> 1V
- *
- * RI = 1 / NETLIST_GMIN
- *
- * Internal GI = G / RO
- *
- */
+ const double y = x * ln2r;
+ const unsigned int t = y;
+ const double z = (x - ln2 * (double) t);
+ const double zz = z * z;
+ //const double zzz = zz * z;
-#define NETDEV_VCVS(_name) \
- NET_REGISTER_DEV(VCVS, _name)
-//NETDEV_PARAMI(_name, model, _model)
+ return (double)(1 << t)*(1.0 + z + 0.5 * zz); // + c3*zzz;
+}
+inline double fastexp(const double x)
+{
+ if (x<0)
+ return 1.0 / fastexp_h(-x);
+ else
+ return fastexp_h(x);
+}
+#endif
-class NETLIB_NAME(VCVS) : public NETLIB_NAME(VCCS)
+class NETLIB_NAME(D) : public NETLIB_NAME(twoterm)
{
public:
- ATTR_COLD NETLIB_NAME(VCVS)()
- : NETLIB_NAME(VCCS)(VCVS) { }
+ ATTR_COLD NETLIB_NAME(D)() : NETLIB_NAME(twoterm)(DIODE) { }
+
+ NETLIB_UPDATE_TERMINALS()
+ {
+ m_D.update_diode(deltaV());
+ set(m_D.G(), 0.0, m_D.Ieq());
+ }
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void update_param();
- //ATTR_HOT ATTR_ALIGN void update();
+ ATTR_HOT ATTR_ALIGN void update();
- netlist_terminal_t m_OP2;
- netlist_terminal_t m_ON2;
+ netlist_param_model_t m_model;
- netlist_param_double_t m_RO;
+ netlist_generic_diode m_D;
};
+
#endif /* NLD_TWOTERM_H_ */
diff --git a/src/emu/netlist/devices/net_lib.h b/src/emu/netlist/devices/net_lib.h
index fbe953565fd..e1ac0f20f1e 100644
--- a/src/emu/netlist/devices/net_lib.h
+++ b/src/emu/netlist/devices/net_lib.h
@@ -75,9 +75,11 @@
#include "nld_log.h"
-#include "../analog/nld_twoterm.h"
+#include "../analog/nld_bjt.h"
+#include "../analog/nld_fourterm.h"
#include "../analog/nld_solver.h"
#include "../analog/nld_switches.h"
+#include "../analog/nld_twoterm.h"
#include "nld_legacy.h"
diff --git a/src/emu/netlist/netlist.mak b/src/emu/netlist/netlist.mak
index 6b3644d6c81..1cea6f87e52 100644
--- a/src/emu/netlist/netlist.mak
+++ b/src/emu/netlist/netlist.mak
@@ -28,9 +28,11 @@ NETLISTOBJS+= \
$(NETLISTOBJ)/nl_setup.o \
$(NETLISTOBJ)/pstring.o \
$(NETLISTOBJ)/pstate.o \
+ $(NETLISTOBJ)/analog/nld_bjt.o \
+ $(NETLISTOBJ)/analog/nld_fourterm.o \
$(NETLISTOBJ)/analog/nld_solver.o \
- $(NETLISTOBJ)/analog/nld_twoterm.o \
$(NETLISTOBJ)/analog/nld_switches.o \
+ $(NETLISTOBJ)/analog/nld_twoterm.o \
$(NETLISTOBJ)/devices/nld_7404.o \
$(NETLISTOBJ)/devices/nld_7474.o \
$(NETLISTOBJ)/devices/nld_7483.o \