mirror of
https://github.com/holub/mame
synced 2025-06-07 05:13:46 +03:00
More house-cleaning on netlist. No wn
This commit is contained in:
parent
4a0c907028
commit
1242ec6d32
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -2136,6 +2136,10 @@ src/emu/memarray.c svneol=native#text/plain
|
|||||||
src/emu/memarray.h svneol=native#text/plain
|
src/emu/memarray.h svneol=native#text/plain
|
||||||
src/emu/memory.c svneol=native#text/plain
|
src/emu/memory.c svneol=native#text/plain
|
||||||
src/emu/memory.h svneol=native#text/plain
|
src/emu/memory.h svneol=native#text/plain
|
||||||
|
src/emu/netlist/analog/nld_bjt.c svneol=native#text/plain
|
||||||
|
src/emu/netlist/analog/nld_bjt.h svneol=native#text/plain
|
||||||
|
src/emu/netlist/analog/nld_fourterm.c svneol=native#text/plain
|
||||||
|
src/emu/netlist/analog/nld_fourterm.h svneol=native#text/plain
|
||||||
src/emu/netlist/analog/nld_solver.c svneol=native#text/plain
|
src/emu/netlist/analog/nld_solver.c svneol=native#text/plain
|
||||||
src/emu/netlist/analog/nld_solver.h svneol=native#text/plain
|
src/emu/netlist/analog/nld_solver.h svneol=native#text/plain
|
||||||
src/emu/netlist/analog/nld_switches.c svneol=native#text/plain
|
src/emu/netlist/analog/nld_switches.c svneol=native#text/plain
|
||||||
|
170
src/emu/netlist/analog/nld_bjt.c
Normal file
170
src/emu/netlist/analog/nld_bjt.c
Normal file
@ -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>);
|
||||||
|
|
207
src/emu/netlist/analog/nld_bjt.h
Normal file
207
src/emu/netlist/analog/nld_bjt.h
Normal file
@ -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_ */
|
88
src/emu/netlist/analog/nld_fourterm.c
Normal file
88
src/emu/netlist/analog/nld_fourterm.c
Normal file
@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
145
src/emu/netlist/analog/nld_fourterm.h
Normal file
145
src/emu/netlist/analog/nld_fourterm.h
Normal file
@ -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_ */
|
@ -127,23 +127,17 @@ NETLIB_START(D)
|
|||||||
register_terminal("K", m_N);
|
register_terminal("K", m_N);
|
||||||
register_param("model", m_model, "");
|
register_param("model", m_model, "");
|
||||||
|
|
||||||
m_Vd = 0.7;
|
m_D.save("m_D", *this);
|
||||||
|
|
||||||
save(NAME(m_Vd));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NETLIB_UPDATE_PARAM(D)
|
NETLIB_UPDATE_PARAM(D)
|
||||||
{
|
{
|
||||||
m_Is = m_model.dValue("Is", 1e-15);
|
double Is = m_model.dValue("Is", 1e-15);
|
||||||
m_n = m_model.dValue("N", 1);
|
double n = m_model.dValue("N", 1);
|
||||||
|
|
||||||
m_Vt = 0.0258 * m_n;
|
m_D.set_param(Is, n);
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NETLIB_UPDATE(D)
|
NETLIB_UPDATE(D)
|
||||||
@ -151,233 +145,4 @@ NETLIB_UPDATE(D)
|
|||||||
NETLIB_NAME(twoterm)::update();
|
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
@ -57,23 +57,6 @@
|
|||||||
NET_REGISTER_DEV(D, _name) \
|
NET_REGISTER_DEV(D, _name) \
|
||||||
NETDEV_PARAMI(_name, model, # _model)
|
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
|
// Implementation
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
@ -100,6 +83,9 @@ public:
|
|||||||
m_N.m_Idr = ( -V) * G + I;
|
m_N.m_Idr = ( -V) * G + I;
|
||||||
m_P.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:
|
protected:
|
||||||
ATTR_COLD virtual void start();
|
ATTR_COLD virtual void start();
|
||||||
ATTR_HOT ATTR_ALIGN void update();
|
ATTR_HOT ATTR_ALIGN void update();
|
||||||
@ -153,7 +139,7 @@ public:
|
|||||||
ATTR_HOT void step_time(const double st)
|
ATTR_HOT void step_time(const double st)
|
||||||
{
|
{
|
||||||
double G = m_C.Value() / 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);
|
set(G, 0.0, I);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +152,89 @@ protected:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
// A generic diode model to be used in other devices (Diode, BJT ...)
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class netlist_generic_diode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
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 = NETLIST_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;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
m_Id = m_Is * (eVDVt - 1.0);
|
||||||
|
|
||||||
|
m_G = m_Is * m_VtInv * eVDVt;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("nVd %f m_Vd %f Vcrit %f\n", nVd, m_Vd, m_Vcrit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_param(const double Is, const double n)
|
||||||
|
{
|
||||||
|
m_Is = Is;
|
||||||
|
m_n = 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_Vd = 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
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); }
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
double m_n;
|
||||||
|
|
||||||
|
double m_VtInv;
|
||||||
|
double m_Vcrit;
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
// nld_D
|
// nld_D
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
@ -206,42 +275,8 @@ public:
|
|||||||
|
|
||||||
NETLIB_UPDATE_TERMINALS()
|
NETLIB_UPDATE_TERMINALS()
|
||||||
{
|
{
|
||||||
const double nVd = m_P.net().Q_Analog()- m_N.net().Q_Analog();
|
m_D.update_diode(deltaV());
|
||||||
|
set(m_D.G(), 0.0, m_D.Ieq());
|
||||||
//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:
|
protected:
|
||||||
@ -251,374 +286,9 @@ protected:
|
|||||||
|
|
||||||
netlist_param_model_t m_model;
|
netlist_param_model_t m_model;
|
||||||
|
|
||||||
double m_Vt;
|
netlist_generic_diode m_D;
|
||||||
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
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* + - 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
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
struct generic_diode
|
|
||||||
{
|
|
||||||
generic_diode() : m_tt(netlist_object_t::ANALOG) {}
|
|
||||||
|
|
||||||
ATTR_HOT inline void update_diode()
|
|
||||||
{
|
|
||||||
//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_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);
|
|
||||||
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);
|
|
||||||
m_Id = m_Is * (eVDVt - 1.0);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_param(const double Is, const double n)
|
|
||||||
{
|
|
||||||
m_Is = Is;
|
|
||||||
m_n = 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_Vd = 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
ATTR_HOT inline double I() { return m_Id; }
|
|
||||||
|
|
||||||
nld_twoterm m_tt;
|
|
||||||
|
|
||||||
private:
|
|
||||||
double m_Id;
|
|
||||||
|
|
||||||
double m_Vt;
|
|
||||||
double m_Is;
|
|
||||||
double m_n;
|
|
||||||
|
|
||||||
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
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
|
|
||||||
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
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NETDEV_VCVS(_name) \
|
|
||||||
NET_REGISTER_DEV(VCVS, _name)
|
|
||||||
//NETDEV_PARAMI(_name, model, _model)
|
|
||||||
|
|
||||||
|
|
||||||
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_TWOTERM_H_ */
|
#endif /* NLD_TWOTERM_H_ */
|
||||||
|
@ -75,9 +75,11 @@
|
|||||||
|
|
||||||
#include "nld_log.h"
|
#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_solver.h"
|
||||||
#include "../analog/nld_switches.h"
|
#include "../analog/nld_switches.h"
|
||||||
|
#include "../analog/nld_twoterm.h"
|
||||||
|
|
||||||
|
|
||||||
#include "nld_legacy.h"
|
#include "nld_legacy.h"
|
||||||
|
@ -28,9 +28,11 @@ NETLISTOBJS+= \
|
|||||||
$(NETLISTOBJ)/nl_setup.o \
|
$(NETLISTOBJ)/nl_setup.o \
|
||||||
$(NETLISTOBJ)/pstring.o \
|
$(NETLISTOBJ)/pstring.o \
|
||||||
$(NETLISTOBJ)/pstate.o \
|
$(NETLISTOBJ)/pstate.o \
|
||||||
|
$(NETLISTOBJ)/analog/nld_bjt.o \
|
||||||
|
$(NETLISTOBJ)/analog/nld_fourterm.o \
|
||||||
$(NETLISTOBJ)/analog/nld_solver.o \
|
$(NETLISTOBJ)/analog/nld_solver.o \
|
||||||
$(NETLISTOBJ)/analog/nld_twoterm.o \
|
|
||||||
$(NETLISTOBJ)/analog/nld_switches.o \
|
$(NETLISTOBJ)/analog/nld_switches.o \
|
||||||
|
$(NETLISTOBJ)/analog/nld_twoterm.o \
|
||||||
$(NETLISTOBJ)/devices/nld_7404.o \
|
$(NETLISTOBJ)/devices/nld_7404.o \
|
||||||
$(NETLISTOBJ)/devices/nld_7474.o \
|
$(NETLISTOBJ)/devices/nld_7474.o \
|
||||||
$(NETLISTOBJ)/devices/nld_7483.o \
|
$(NETLISTOBJ)/devices/nld_7483.o \
|
||||||
|
Loading…
Reference in New Issue
Block a user