mirror of
https://github.com/holub/mame
synced 2025-10-06 09:00:04 +03:00
Netlist: added a simplified BJT Switch Model. This should be sufficient for audio purposes in >> 90% of all cases I have seen so far.
The performance of the analog subsystem has quite some room for improvement :-(
This commit is contained in:
parent
dcd3d5fd03
commit
3c13417a92
@ -786,6 +786,8 @@ void netlist_factory::initialize()
|
||||
ENTRY(R, NETDEV_R)
|
||||
ENTRY(C, NETDEV_C)
|
||||
ENTRY(D, NETDEV_D)
|
||||
ENTRY(QPNP_switch, NETDEV_QPNP)
|
||||
ENTRY(QNPN_switch, NETDEV_QNPN)
|
||||
ENTRY(ttl_const, NETDEV_TTL_CONST)
|
||||
ENTRY(analog_const, NETDEV_ANALOG_CONST)
|
||||
ENTRY(logic_input, NETDEV_LOGIC_INPUT)
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include "nld_system.h"
|
||||
#include "nld_twoterm.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_const
|
||||
@ -92,6 +93,8 @@ NETLIB_START(solver)
|
||||
register_param("FREQ", m_freq, 48000.0);
|
||||
m_inc = netlist_time::from_hz(m_freq.Value());
|
||||
|
||||
register_param("ACCURACY", m_accuracy, 1e-3);
|
||||
|
||||
register_link_internal(m_fb_sync, m_Q_sync, netlist_input_t::STATE_INP_ACTIVE);
|
||||
register_link_internal(m_fb_step, m_Q_step, netlist_input_t::STATE_INP_ACTIVE);
|
||||
m_last_step = netlist_time::zero;
|
||||
@ -116,6 +119,7 @@ NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
|
||||
|
||||
NETLIB_FUNC_VOID(solver, post_start, ())
|
||||
{
|
||||
|
||||
NL_VERBOSE_OUT(("post start solver ...\n"));
|
||||
for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
{
|
||||
@ -127,6 +131,9 @@ NETLIB_FUNC_VOID(solver, post_start, ())
|
||||
case netlist_terminal_t::TERMINAL:
|
||||
m_terms.add(p);
|
||||
NL_VERBOSE_OUT(("Added terminal\n"));
|
||||
if (p->netdev().isFamily(CAPACITOR))
|
||||
if (!m_steps.contains(&p->netdev()))
|
||||
m_steps.add(&p->netdev());
|
||||
break;
|
||||
case netlist_terminal_t::INPUT:
|
||||
m_inps.add(p);
|
||||
@ -154,6 +161,7 @@ NETLIB_UPDATE(solver)
|
||||
//OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc );
|
||||
|
||||
bool resched = false;
|
||||
int resched_cnt = 0;
|
||||
netlist_time now = netlist().time();
|
||||
netlist_time delta = now - m_last_step;
|
||||
|
||||
@ -162,38 +170,73 @@ NETLIB_UPDATE(solver)
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
m_last_step = now;
|
||||
for (terminal_list_t::entry_t *p = m_terms.first(); p != NULL; p = m_terms.next(p))
|
||||
p->object()->netdev().step_time(delta.as_double());
|
||||
for (dev_list_t::entry_t *p = m_steps.first(); p != NULL; p = m_steps.next(p))
|
||||
p->object()->step_time(delta.as_double());
|
||||
}
|
||||
for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
{
|
||||
double gtot = 0;
|
||||
double iIdr = 0;
|
||||
do {
|
||||
resched = false;
|
||||
|
||||
for (netlist_core_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
|
||||
for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
{
|
||||
if (p->isType(netlist_core_terminal_t::TERMINAL))
|
||||
netlist_net_t *net = pn->object();
|
||||
|
||||
double gtot = 0;
|
||||
double iIdr = 0;
|
||||
|
||||
for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next)
|
||||
{
|
||||
netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p);
|
||||
pt->netdev().update_terminals();
|
||||
gtot += pt->m_g;
|
||||
iIdr += pt->m_Idr;
|
||||
if (p->isType(netlist_core_terminal_t::TERMINAL))
|
||||
{
|
||||
netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p);
|
||||
netlist_core_device_t &dev = pt->netdev();
|
||||
#if 0
|
||||
switch (pt->family())
|
||||
{
|
||||
case RESISTOR:
|
||||
static_cast<NETLIB_NAME(R) &>(dev).update_terminals();
|
||||
break;
|
||||
case CAPACITOR:
|
||||
static_cast<NETLIB_NAME(C) &>(dev).update_terminals();
|
||||
break;
|
||||
#if 1
|
||||
case DIODE:
|
||||
static_cast<NETLIB_NAME(D) &>(dev).update_terminals();
|
||||
break;
|
||||
case BJT_SWITCH_NPN:
|
||||
static_cast<NETLIB_NAME(QNPN_switch) &>(dev).update_terminals();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
dev.update_terminals();
|
||||
break;
|
||||
}
|
||||
#else
|
||||
dev.update_terminals();
|
||||
#endif
|
||||
gtot += pt->m_g;
|
||||
iIdr += pt->m_Idr;
|
||||
}
|
||||
}
|
||||
|
||||
double new_val = iIdr / gtot;
|
||||
if (fabs(new_val - net->m_cur.Analog) > m_accuracy.Value())
|
||||
resched = true;
|
||||
resched_cnt++;
|
||||
net->m_cur.Analog = net->m_new.Analog = new_val;
|
||||
|
||||
NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons));
|
||||
NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
|
||||
}
|
||||
|
||||
double new_val = iIdr / gtot;
|
||||
if (fabs(new_val - pn->object()->m_cur.Analog) > 1e-4)
|
||||
resched = true;
|
||||
pn->object()->m_cur.Analog = pn->object()->m_new.Analog = new_val;
|
||||
|
||||
NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons));
|
||||
NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
|
||||
}
|
||||
} while (resched && (resched_cnt < 1));
|
||||
//if (resched_cnt >= 5)
|
||||
// printf("rescheduled\n");
|
||||
if (resched)
|
||||
{
|
||||
schedule();
|
||||
}
|
||||
#if 1
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* update all inputs connected */
|
||||
#if 0
|
||||
@ -201,7 +244,7 @@ NETLIB_UPDATE(solver)
|
||||
{
|
||||
if (pn->object()->m_cur.Analog != pn->object()->m_last.Analog)
|
||||
{
|
||||
for (netlist_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
|
||||
for (netlist_core_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
|
||||
{
|
||||
if (p->isType(netlist_terminal_t::INPUT))
|
||||
p->netdev().update_dev();
|
||||
|
@ -82,6 +82,7 @@ NETLIB_DEVICE_WITH_PARAMS(clock,
|
||||
NETLIB_DEVICE_WITH_PARAMS(solver,
|
||||
typedef netlist_list_t<netlist_core_terminal_t *> terminal_list_t;
|
||||
typedef netlist_list_t<netlist_net_t *> net_list_t;
|
||||
typedef netlist_list_t<netlist_core_device_t *> dev_list_t;
|
||||
|
||||
netlist_ttl_input_t m_fb_sync;
|
||||
netlist_ttl_output_t m_Q_sync;
|
||||
@ -91,6 +92,7 @@ NETLIB_DEVICE_WITH_PARAMS(solver,
|
||||
|
||||
netlist_param_double_t m_freq;
|
||||
netlist_param_double_t m_sync_delay;
|
||||
netlist_param_double_t m_accuracy;
|
||||
|
||||
netlist_time m_inc;
|
||||
netlist_time m_last_step;
|
||||
@ -98,6 +100,7 @@ NETLIB_DEVICE_WITH_PARAMS(solver,
|
||||
|
||||
terminal_list_t m_terms;
|
||||
terminal_list_t m_inps;
|
||||
dev_list_t m_steps;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -94,3 +94,83 @@ 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, "");
|
||||
}
|
||||
|
||||
NETLIB_START(QBJT)
|
||||
{
|
||||
NETLIB_NAME(Q)::start();
|
||||
|
||||
register_terminal("B", m_B);
|
||||
register_terminal("C", m_C);
|
||||
register_terminal("E", m_E);
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
if (_type == BJT_NPN)
|
||||
m_V = d.V(0.005 / alpha);
|
||||
else
|
||||
m_V = - d.V(0.005 / alpha);
|
||||
|
||||
m_gB = d.gI(0.005 / alpha);
|
||||
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);
|
||||
}
|
||||
|
||||
template NETLIB_UPDATE_PARAM(QBJT_switch<NETLIB_NAME(Q)::BJT_NPN>);
|
||||
template NETLIB_UPDATE_PARAM(QBJT_switch<NETLIB_NAME(Q)::BJT_PNP>);
|
||||
|
@ -62,18 +62,15 @@
|
||||
// nld_twoterm
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class nld_twoterm : public netlist_device_t
|
||||
class NETLIB_NAME(twoterm) : public netlist_device_t
|
||||
{
|
||||
public:
|
||||
nld_twoterm()
|
||||
: netlist_device_t(), m_g(0.0), m_V(0.0), m_I(0.0) { }
|
||||
ATTR_COLD NETLIB_NAME(twoterm)(const family_t afamily)
|
||||
: netlist_device_t(afamily), m_g(0.0), m_V(0.0), m_I(0.0) { }
|
||||
|
||||
netlist_terminal_t m_P;
|
||||
netlist_terminal_t m_N;
|
||||
|
||||
protected:
|
||||
virtual void start();
|
||||
|
||||
virtual NETLIB_UPDATE_TERMINALS()
|
||||
{
|
||||
m_P.m_g = m_N.m_g = m_g;
|
||||
@ -81,7 +78,8 @@ protected:
|
||||
m_P.m_Idr = (m_N.net().Q_Analog() + m_V) * m_g - m_I;
|
||||
//printf("%f %f %f %f\n", m_N.m_Idr, m_P.m_Idr, m_N.net().Q_Analog(), m_P.net().Q_Analog());
|
||||
}
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void start();
|
||||
ATTR_HOT ATTR_ALIGN void update();
|
||||
|
||||
double m_g; // conductance
|
||||
@ -94,23 +92,30 @@ private:
|
||||
// nld_R
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS_DERIVED(R, twoterm,
|
||||
netlist_param_double_t m_R;
|
||||
|
||||
NETLIB_UPDATE_TERMINALS() { NETLIB_NAME(twoterm)::update_terminals(); }
|
||||
|
||||
class NETLIB_NAME(R) : public NETLIB_NAME(twoterm)
|
||||
{
|
||||
public:
|
||||
inline void set_R(double R) { m_g = 1.0 / R; }
|
||||
ATTR_COLD NETLIB_NAME(R)() : NETLIB_NAME(twoterm)(RESISTOR) { }
|
||||
|
||||
);
|
||||
inline void set_R(const double R) { m_g = 1.0 / R; }
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void start();
|
||||
ATTR_COLD virtual void update_param();
|
||||
ATTR_HOT ATTR_ALIGN void update();
|
||||
|
||||
netlist_param_double_t m_R;
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// nld_C
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS_DERIVED(C, twoterm,
|
||||
|
||||
netlist_param_double_t m_C;
|
||||
class NETLIB_NAME(C) : public NETLIB_NAME(twoterm)
|
||||
{
|
||||
public:
|
||||
ATTR_COLD NETLIB_NAME(C)() : NETLIB_NAME(twoterm)(CAPACITOR) { }
|
||||
|
||||
ATTR_HOT void step_time(const double st)
|
||||
{
|
||||
@ -118,23 +123,23 @@ NETLIB_DEVICE_WITH_PARAMS_DERIVED(C, twoterm,
|
||||
m_I = -m_g * (m_P.net().Q_Analog()- m_N.net().Q_Analog());
|
||||
}
|
||||
|
||||
);
|
||||
protected:
|
||||
ATTR_COLD virtual void start();
|
||||
ATTR_COLD virtual void update_param();
|
||||
ATTR_HOT ATTR_ALIGN void update();
|
||||
|
||||
netlist_param_double_t m_C;
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// nld_D
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS_DERIVED(D, twoterm,
|
||||
|
||||
netlist_param_multi_t m_model;
|
||||
|
||||
double m_Vt;
|
||||
double m_Is;
|
||||
double m_n;
|
||||
|
||||
double m_VtInv;
|
||||
double m_Vcrit;
|
||||
double m_Vd;
|
||||
class NETLIB_NAME(D) : public NETLIB_NAME(twoterm)
|
||||
{
|
||||
public:
|
||||
ATTR_COLD NETLIB_NAME(D)() : NETLIB_NAME(twoterm)(DIODE) { }
|
||||
|
||||
NETLIB_UPDATE_TERMINALS()
|
||||
{
|
||||
@ -151,11 +156,134 @@ NETLIB_DEVICE_WITH_PARAMS_DERIVED(D, twoterm,
|
||||
m_I = (Id - m_Vd * m_g);
|
||||
//printf("Vd: %f %f %f %f\n", m_Vd, m_g, Id, m_I);
|
||||
|
||||
nld_twoterm::update_terminals();
|
||||
NETLIB_NAME(twoterm)::update_terminals();
|
||||
}
|
||||
|
||||
private:
|
||||
);
|
||||
protected:
|
||||
ATTR_COLD virtual void start();
|
||||
ATTR_COLD virtual void update_param();
|
||||
ATTR_HOT ATTR_ALIGN void update();
|
||||
|
||||
netlist_param_multi_t m_model;
|
||||
|
||||
double m_Vt;
|
||||
double m_Is;
|
||||
double m_n;
|
||||
|
||||
double m_VtInv;
|
||||
double m_Vcrit;
|
||||
double m_Vd;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* + - C
|
||||
* B ----VVV----+ |
|
||||
* | |
|
||||
* Rb Rc
|
||||
* Rb Rc
|
||||
* Rb Rc
|
||||
* | |
|
||||
* +----+----+
|
||||
* |
|
||||
* E
|
||||
*/
|
||||
|
||||
#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_BC238B(_name) NETDEV_QNPN(_name, "IS=1.8E-14 ISE=5.0E-14 ISC=1.72E-13 XTI=3 BF=400 BR=35.5 IKF=0.14 IKR=0.03 XTB=1.5 VAF=80 VAR=12.5 VJE=0.58 VJC=0.54 RE=0.6 RC=0.25 RB=0.56 CJE=13E-12 CJC=4E-12 XCJC=0.75 FC=0.5 NF=0.9955 NR=1.005 NE=1.46 NC=1.27 MJE=0.33 MJC=0.33 TF=0.64E-9 TR=50.72E-9 EG=1.11 KF=0 AF=1 VCEO=45V ICRATING=100M MFG=ZETEX")
|
||||
|
||||
// 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_multi_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) { }
|
||||
|
||||
netlist_terminal_t m_B;
|
||||
netlist_terminal_t m_C;
|
||||
netlist_terminal_t m_E;
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void start();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
//NETLIB_NAME(Q) nld_Q::q_type
|
||||
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_NPN), m_gB(NETLIST_GMIN), m_gC(NETLIST_GMIN), m_V(0.0) { }
|
||||
|
||||
NETLIB_UPDATE_TERMINALS()
|
||||
{
|
||||
double gb = m_gB;
|
||||
double gc = m_gC;
|
||||
double v = m_V;
|
||||
double vE = m_E.net().Q_Analog();
|
||||
double vB = m_B.net().Q_Analog();
|
||||
|
||||
if (vB - vE < m_V )
|
||||
{
|
||||
// not conducting
|
||||
gb = NETLIST_GMIN;
|
||||
v = 0;
|
||||
gc = NETLIST_GMIN;
|
||||
}
|
||||
|
||||
m_B.m_g = m_E.m_g = gb;
|
||||
m_C.m_g = gc;
|
||||
|
||||
m_B.m_Idr = (vE + v) * gb;
|
||||
m_C.m_Idr = (vE) * gc;
|
||||
m_E.m_Idr = (vB - v) * gb + m_C.net().Q_Analog() * gc;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
ATTR_COLD void update_param();
|
||||
|
||||
double m_gB; // conductance
|
||||
double m_gC; // conductance
|
||||
double m_V; // internal voltage source
|
||||
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);
|
||||
|
||||
#endif /* NLD_TWOTERM_H_ */
|
||||
|
@ -197,8 +197,13 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(INT32 &atime)
|
||||
// net_core_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_core_device_t::netlist_core_device_t()
|
||||
: netlist_object_t(DEVICE, ALL)
|
||||
ATTR_COLD netlist_core_device_t::netlist_core_device_t()
|
||||
: netlist_object_t(DEVICE, GENERIC)
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_COLD netlist_core_device_t::netlist_core_device_t(const family_t afamily)
|
||||
: netlist_object_t(DEVICE, afamily)
|
||||
{
|
||||
}
|
||||
|
||||
@ -218,7 +223,7 @@ ATTR_COLD void netlist_core_device_t::init(netlist_setup_t &setup, const pstring
|
||||
|
||||
}
|
||||
|
||||
netlist_core_device_t::~netlist_core_device_t()
|
||||
ATTR_COLD netlist_core_device_t::~netlist_core_device_t()
|
||||
{
|
||||
}
|
||||
|
||||
@ -226,6 +231,28 @@ netlist_core_device_t::~netlist_core_device_t()
|
||||
// net_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_device_t::netlist_device_t()
|
||||
: netlist_core_device_t(),
|
||||
m_terminals(20),
|
||||
m_setup(NULL),
|
||||
m_variable_input_count(false)
|
||||
{
|
||||
}
|
||||
|
||||
netlist_device_t::netlist_device_t(const family_t afamily)
|
||||
: netlist_core_device_t(afamily),
|
||||
m_terminals(20),
|
||||
m_setup(NULL),
|
||||
m_variable_input_count(false)
|
||||
{
|
||||
}
|
||||
|
||||
netlist_device_t::~netlist_device_t()
|
||||
{
|
||||
//NL_VERBOSE_OUT(("~net_device_t\n");
|
||||
}
|
||||
|
||||
|
||||
ATTR_HOT ATTR_ALIGN const netlist_sig_t netlist_core_device_t::INPLOGIC_PASSIVE(netlist_logic_input_t &inp)
|
||||
{
|
||||
if (inp.state() == netlist_input_t::STATE_INP_PASSIVE)
|
||||
@ -240,19 +267,6 @@ ATTR_HOT ATTR_ALIGN const netlist_sig_t netlist_core_device_t::INPLOGIC_PASSIVE(
|
||||
|
||||
}
|
||||
|
||||
netlist_device_t::netlist_device_t()
|
||||
: netlist_core_device_t(),
|
||||
m_terminals(20),
|
||||
m_setup(NULL),
|
||||
m_variable_input_count(false)
|
||||
{
|
||||
}
|
||||
|
||||
netlist_device_t::~netlist_device_t()
|
||||
{
|
||||
//NL_VERBOSE_OUT(("~net_device_t\n");
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::init(netlist_setup_t &setup, const pstring &name)
|
||||
{
|
||||
netlist_core_device_t::init(setup, name);
|
||||
@ -538,9 +552,9 @@ ATTR_COLD void netlist_logic_output_t::set_levels(const double low, const double
|
||||
|
||||
ATTR_COLD double netlist_param_multi_t::dValue(const pstring &entity, const double defval) const
|
||||
{
|
||||
pstring tmp = this->Value();
|
||||
pstring tmp = this->Value().ucase();
|
||||
// .model 1N914 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)
|
||||
int p = tmp.find(entity);
|
||||
int p = tmp.find(entity.ucase() + "=");
|
||||
if (p>=0)
|
||||
{
|
||||
int pblank = tmp.find(" ", p);
|
||||
|
@ -238,15 +238,20 @@ public:
|
||||
TERMINAL = 0,
|
||||
INPUT = 1,
|
||||
OUTPUT = 2,
|
||||
DEVICE = 3,
|
||||
PARAM = 4,
|
||||
NET = 5
|
||||
PARAM = 3,
|
||||
NET = 4,
|
||||
DEVICE = 5,
|
||||
};
|
||||
enum family_t {
|
||||
LOGIC = 1,
|
||||
ANALOG = 2,
|
||||
CURRENT = 3,
|
||||
ALL = 4 // <== devices usually fall into this category
|
||||
// Terminal families
|
||||
LOGIC = 1,
|
||||
ANALOG = 2,
|
||||
// Device families
|
||||
GENERIC = 3, // <== devices usually fall into this category
|
||||
RESISTOR = 4, // Resistor
|
||||
CAPACITOR = 5, // Capacitor
|
||||
DIODE = 6, // Diode
|
||||
BJT_SWITCH_NPN = 7, // BJT(Switch)
|
||||
};
|
||||
|
||||
ATTR_COLD netlist_object_t(const type_t atype, const family_t afamily);
|
||||
@ -708,6 +713,7 @@ class netlist_core_device_t : public netlist_object_t
|
||||
public:
|
||||
|
||||
ATTR_COLD netlist_core_device_t();
|
||||
ATTR_COLD netlist_core_device_t(const family_t afamily);
|
||||
|
||||
ATTR_COLD virtual ~netlist_core_device_t();
|
||||
|
||||
@ -792,6 +798,7 @@ class netlist_device_t : public netlist_core_device_t
|
||||
public:
|
||||
|
||||
ATTR_COLD netlist_device_t();
|
||||
ATTR_COLD netlist_device_t(const family_t afamily);
|
||||
|
||||
ATTR_COLD virtual ~netlist_device_t();
|
||||
|
||||
|
@ -74,6 +74,15 @@ public:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ATTR_HOT inline bool contains(const _ListClass elem) const
|
||||
{
|
||||
for (entry_t *i = m_list; i <= m_ptr; i++)
|
||||
{
|
||||
if (i->object() == elem)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ATTR_HOT inline entry_t *first() const { return (m_ptr >= m_list ? &m_list[0] : NULL ); }
|
||||
ATTR_HOT inline entry_t *next(entry_t *lc) const { return (lc < last() ? lc + 1 : NULL ); }
|
||||
|
@ -588,6 +588,21 @@ static NETLIST_START(pong_schematics)
|
||||
//NETDEV_LOG(log3, 555.OUT)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
NETDEV_BC238B(Q)
|
||||
NETDEV_R(RB, 1000)
|
||||
NETDEV_R(RC, 1000)
|
||||
|
||||
NET_C(RC.1, V5)
|
||||
NET_C(RC.2, Q.C)
|
||||
NET_C(RB.1, 128H)
|
||||
NET_C(RB.2, Q.B)
|
||||
NET_C(Q.E, GND)
|
||||
//NETDEV_LOG(logB, Q.B)
|
||||
//NETDEV_LOG(logC, Q.C)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
NETLIST_END
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user