mirror of
https://github.com/holub/mame
synced 2025-07-02 16:49:22 +03:00
Netlist: Need a checkpoint before I continue.
This commit is contained in:
parent
4333d8f25a
commit
12ae4ea748
@ -78,28 +78,6 @@ NETLIB_UPDATE(log)
|
||||
printf("%s: %d %d\n", name().cstr(), (UINT32) (netlist().time().as_raw() / 1000000), INPLOGIC(m_I));
|
||||
}
|
||||
|
||||
NETLIB_START(clock)
|
||||
{
|
||||
register_output("Q", m_Q);
|
||||
//register_input("FB", m_feedback);
|
||||
|
||||
register_param("FREQ", m_freq, 7159000.0 * 5);
|
||||
m_inc = netlist_time::from_hz(m_freq.Value()*2);
|
||||
|
||||
register_link_internal(m_feedback, m_Q, netlist_input_t::INP_STATE_ACTIVE);
|
||||
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(clock)
|
||||
{
|
||||
m_inc = netlist_time::from_hz(m_freq.Value()*2);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(clock)
|
||||
{
|
||||
//m_Q.setToNoCheck(!m_Q.new_Q(), m_inc );
|
||||
OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc );
|
||||
}
|
||||
|
||||
NETLIB_START(nicMultiSwitch)
|
||||
{
|
||||
@ -223,16 +201,16 @@ NETLIB_START(nicNE555N_MSTABLE)
|
||||
m_last = false;
|
||||
}
|
||||
|
||||
INLINE double nicNE555N_cv(NETLIB_NAME(nicNE555N_MSTABLE) &dev)
|
||||
inline double NETLIB_NAME(nicNE555N_MSTABLE)::nicNE555N_cv()
|
||||
{
|
||||
return (dev.m_CV.is_highz() ? 0.67 * dev.m_VS.Value() : dev.INPANALOG(dev.m_CV));
|
||||
return (m_CV.is_highz() ? 0.67 * m_VS.Value() : INPANALOG(m_CV));
|
||||
}
|
||||
|
||||
INLINE double nicNE555N_clamp(NETLIB_NAME(nicNE555N_MSTABLE) &dev, const double v, const double a, const double b)
|
||||
inline double NETLIB_NAME(nicNE555N_MSTABLE)::nicNE555N_clamp(const double v, const double a, const double b)
|
||||
{
|
||||
double ret = v;
|
||||
if (ret > dev.m_VS.Value() - a)
|
||||
ret = dev.m_VS.Value() - a;
|
||||
if (ret > m_VS.Value() - a)
|
||||
ret = m_VS.Value() - a;
|
||||
if (ret < b)
|
||||
ret = b;
|
||||
return ret;
|
||||
@ -246,9 +224,9 @@ NETLIB_UPDATE(nicNE555N_MSTABLE)
|
||||
{
|
||||
update_param(); // FIXME : m_CV should be on a sub device ...
|
||||
|
||||
double vt = nicNE555N_clamp(*this, nicNE555N_cv(*this), 0.7, 1.4);
|
||||
double vt = nicNE555N_clamp(nicNE555N_cv(), 0.7, 1.4);
|
||||
bool bthresh = (INPANALOG(m_THRESHOLD) > vt);
|
||||
bool btrig = (INPANALOG(m_trigger) > nicNE555N_clamp(*this, nicNE555N_cv(*this) * 0.5, 0.7, 1.4));
|
||||
bool btrig = (INPANALOG(m_trigger) > nicNE555N_clamp(nicNE555N_cv() * 0.5, 0.7, 1.4));
|
||||
bool out = m_last;
|
||||
|
||||
if (!btrig)
|
||||
@ -624,7 +602,6 @@ NETLIB_START(nic7493)
|
||||
register_output(C, "QC", C.m_Q);
|
||||
register_output(D, "QD", D.m_Q);
|
||||
|
||||
//B.register_link_internal(B.m_I, A.m_Q);
|
||||
register_link_internal(C, C.m_I, B.m_Q, netlist_input_t::INP_STATE_HL);
|
||||
register_link_internal(D, D.m_I, C.m_Q, netlist_input_t::INP_STATE_HL);
|
||||
|
||||
@ -972,6 +949,7 @@ NETLIB_FUNC_VOID(nic9316_sub, update_outputs, (void))
|
||||
|
||||
static const net_device_t_base_factory *netregistry[] =
|
||||
{
|
||||
ENTRY(R, NETDEV_R)
|
||||
ENTRY(ttl_const, NETDEV_TTL_CONST)
|
||||
ENTRY(analog_const, NETDEV_ANALOG_CONST)
|
||||
ENTRY(logic_input, NETDEV_LOGIC_INPUT)
|
||||
|
@ -64,6 +64,16 @@
|
||||
// this is a bad hack
|
||||
#define USE_OLD7493 (0)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// 2 terminal devices
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#define NETDEV_R(_name, _R) \
|
||||
NET_REGISTER_DEV(R, _name) \
|
||||
NETDEV_PARAMI(_name, R, _R) \
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Special chips
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -77,7 +87,7 @@
|
||||
#define NETDEV_ANALOG_INPUT(_name) \
|
||||
NET_REGISTER_DEV(analog_input, _name)
|
||||
#define NETDEV_CALLBACK(_name, _IN) \
|
||||
NET_REGISTER_DEV(analog_callback, _name) \
|
||||
NET_REGISTER_DEV(analog_callback, _name) \
|
||||
NET_CONNECT(_name, IN, _IN)
|
||||
#define NETDEV_SWITCH2(_name, _i1, _i2) \
|
||||
NET_REGISTER_DEV(nicMultiSwitch, _name) \
|
||||
@ -241,13 +251,7 @@ NETLIB_DEVICE(log,
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(clock,
|
||||
netlist_ttl_input_t m_feedback;
|
||||
netlist_ttl_output_t m_Q;
|
||||
|
||||
netlist_param_t m_freq;
|
||||
netlist_time m_inc;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch,
|
||||
netlist_analog_input_t m_I[8];
|
||||
@ -301,6 +305,10 @@ NETLIB_DEVICE_WITH_PARAMS(nicNE555N_MSTABLE,
|
||||
netlist_param_t m_C;
|
||||
netlist_param_t m_VS;
|
||||
netlist_param_t m_VL;
|
||||
|
||||
double nicNE555N_cv();
|
||||
double nicNE555N_clamp(const double v, const double a, const double b);
|
||||
|
||||
);
|
||||
|
||||
NETLIB_SIGNAL(nic7430, 8, 0, 0);
|
||||
|
@ -90,7 +90,7 @@ public:
|
||||
register_output("Q", m_Q);
|
||||
for (int i=0; i < _numdev; i++)
|
||||
{
|
||||
register_input(sIN[i], m_i[i], netlist_input_t::INP_STATE_ACTIVE);
|
||||
register_input(sIN[i], m_i[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,10 @@ NETLIB_UPDATE_PARAM(analog_const)
|
||||
m_Q.initial(m_const.Value());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// analog_callback
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_UPDATE(analog_callback)
|
||||
{
|
||||
// FIXME: Remove after device cleanup
|
||||
@ -46,3 +50,29 @@ NETLIB_UPDATE(analog_callback)
|
||||
m_callback(INPANALOG(m_in));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// clock
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_START(clock)
|
||||
{
|
||||
register_output("Q", m_Q);
|
||||
//register_input("FB", m_feedback);
|
||||
|
||||
register_param("FREQ", m_freq, 7159000.0 * 5);
|
||||
m_inc = netlist_time::from_hz(m_freq.Value()*2);
|
||||
|
||||
register_link_internal(m_feedback, m_Q, netlist_input_t::INP_STATE_ACTIVE);
|
||||
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(clock)
|
||||
{
|
||||
m_inc = netlist_time::from_hz(m_freq.Value()*2);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(clock)
|
||||
{
|
||||
//m_Q.setToNoCheck(!m_Q.new_Q(), m_inc );
|
||||
OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc );
|
||||
}
|
||||
|
@ -43,7 +43,8 @@ NETLIB_DEVICE_WITH_PARAMS(analog_const,
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(mainclock,
|
||||
netlist_ttl_output_t m_Q;
|
||||
public:
|
||||
netlist_ttl_output_t m_Q;
|
||||
|
||||
netlist_param_t m_freq;
|
||||
netlist_time m_inc;
|
||||
@ -51,6 +52,26 @@ NETLIB_DEVICE_WITH_PARAMS(mainclock,
|
||||
ATTR_HOT inline static void mc_update(netlist_net_t &net, const netlist_time curtime);
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// clock
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(clock,
|
||||
netlist_ttl_input_t m_feedback;
|
||||
netlist_ttl_output_t m_Q;
|
||||
|
||||
netlist_param_t m_freq;
|
||||
netlist_time m_inc;
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// solver_clock
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS_DERIVED(solver_clock, clock,
|
||||
public:
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_callback
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -216,6 +216,11 @@ void netlist_device_t::register_output(netlist_core_device_t &dev, const astring
|
||||
m_setup->register_output(*this, dev, name, port);
|
||||
}
|
||||
|
||||
void netlist_device_t::register_terminal(const astring &name, netlist_terminal_t &port)
|
||||
{
|
||||
m_setup->register_terminal(*this,*this,name, port);
|
||||
}
|
||||
|
||||
void netlist_device_t::register_output(const astring &name, netlist_output_t &port)
|
||||
{
|
||||
m_setup->register_output(*this,*this,name, port);
|
||||
@ -234,7 +239,9 @@ void netlist_device_t::register_input(const astring &name, netlist_input_t &inp,
|
||||
void netlist_device_t::register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, netlist_input_t::net_input_state aState)
|
||||
{
|
||||
in.init_input(dev, aState);
|
||||
out.init_terminal(dev);
|
||||
// ensure we are not yet initialized ...
|
||||
if (!out.net().isRailNet())
|
||||
out.init_terminal(dev);
|
||||
//if (in.state() != net_input_t::INP_STATE_PASSIVE)
|
||||
out.net().register_con(in);
|
||||
}
|
||||
@ -274,6 +281,39 @@ ATTR_COLD netlist_net_t::netlist_net_t(const type_t atype, const family_t afamil
|
||||
m_last.Q = 0;
|
||||
};
|
||||
|
||||
ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet)
|
||||
{
|
||||
if (othernet == NULL)
|
||||
return; // Nothing to do
|
||||
|
||||
if (this->isRailNet() && othernet->isRailNet())
|
||||
fatalerror("Trying to merge to rail nets\n");
|
||||
|
||||
if (othernet->isRailNet())
|
||||
othernet->merge_net(this);
|
||||
else
|
||||
{
|
||||
netlist_terminal_t *p = othernet->m_head;
|
||||
if (p == NULL)
|
||||
return;
|
||||
if (m_head == NULL)
|
||||
{
|
||||
m_head = p;
|
||||
m_head->set_net(*this);
|
||||
p = p->m_update_list_next;
|
||||
}
|
||||
while (p != NULL)
|
||||
{
|
||||
netlist_terminal_t *pn = p->m_update_list_next;
|
||||
p->m_update_list_next = m_head;
|
||||
p->set_net(*this);
|
||||
m_head = p;
|
||||
p = pn;
|
||||
}
|
||||
othernet->m_head = NULL; // FIXME: othernet needs to be free'd from memory
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_net_t::register_con(netlist_terminal_t &terminal)
|
||||
{
|
||||
terminal.set_net(*this);
|
||||
@ -306,30 +346,61 @@ ATTR_HOT inline void netlist_net_t::update_devs()
|
||||
{
|
||||
assert(m_num_cons != 0);
|
||||
|
||||
const UINT32 masks[4] = { 1, 5, 3, 1 };
|
||||
m_cur = m_new;
|
||||
m_in_queue = 2; /* mark as taken ... */
|
||||
|
||||
const UINT32 mask = masks[ (m_last.Q << 1) | m_cur.Q ];
|
||||
|
||||
netlist_terminal_t *p = m_head;
|
||||
switch (m_num_cons)
|
||||
{
|
||||
case 2:
|
||||
update_dev(p, mask);
|
||||
p = p->m_update_list_next;
|
||||
case 1:
|
||||
update_dev(p, mask);
|
||||
break;
|
||||
default:
|
||||
//assert(this->isRailNet());
|
||||
if (UNEXPECTED(!this->isRailNet()))
|
||||
{
|
||||
/* only inputs and terminals connected
|
||||
* approach:
|
||||
*
|
||||
* a) Update voltage on this net
|
||||
* b) Update devices
|
||||
* c) If difference old - new > trigger schedule immediate update
|
||||
* of number of updates < max_update_count
|
||||
* else clear number of updates
|
||||
*/
|
||||
m_in_queue = 2; /* mark as taken ... */
|
||||
double gtot = 0;
|
||||
double iIdr = 0;
|
||||
netlist_terminal_t *p = m_head;
|
||||
do
|
||||
{
|
||||
update_dev(p, mask);
|
||||
p->netdev().update_dev();
|
||||
gtot += p->m_g;
|
||||
iIdr += p->m_Idr;
|
||||
|
||||
p = p->m_update_list_next;
|
||||
} while (p != NULL);
|
||||
break;
|
||||
}
|
||||
m_last = m_cur;
|
||||
m_new.Analog = iIdr / gtot;
|
||||
printf("New: %f\n", m_new.Analog);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
const UINT32 masks[4] = { 1, 5, 3, 1 };
|
||||
m_cur = m_new;
|
||||
m_in_queue = 2; /* mark as taken ... */
|
||||
|
||||
const UINT32 mask = masks[ (m_last.Q << 1) | m_cur.Q ];
|
||||
|
||||
netlist_terminal_t *p = m_head;
|
||||
switch (m_num_cons)
|
||||
{
|
||||
case 2:
|
||||
update_dev(p, mask);
|
||||
p = p->m_update_list_next;
|
||||
case 1:
|
||||
update_dev(p, mask);
|
||||
break;
|
||||
default:
|
||||
do
|
||||
{
|
||||
update_dev(p, mask);
|
||||
p = p->m_update_list_next;
|
||||
} while (p != NULL);
|
||||
break;
|
||||
}
|
||||
m_last = m_cur;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -170,17 +170,24 @@ typedef delegate<void ()> net_update_delegate;
|
||||
#define NETLIB_UPDATE_PARAM(_chip) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: update_param(void)
|
||||
#define NETLIB_FUNC_VOID(_chip, _name, _params) ATTR_HOT ATTR_ALIGN inline void NETLIB_NAME(_chip) :: _name _params
|
||||
|
||||
#define NETLIB_DEVICE_BASE(_name, _pclass, _extra, _priv) \
|
||||
class _name : public _pclass \
|
||||
{ \
|
||||
public: \
|
||||
_name() \
|
||||
: _pclass() { } \
|
||||
protected: \
|
||||
_extra \
|
||||
ATTR_HOT void update(); \
|
||||
ATTR_HOT void start(); \
|
||||
_priv \
|
||||
}
|
||||
|
||||
#define NETLIB_DEVICE_DERIVED(_name, _pclass, _priv) \
|
||||
NETLIB_DEVICE_BASE(NETLIB_NAME(_name), NETLIB_NAME(_pclass), , _priv)
|
||||
|
||||
#define NETLIB_DEVICE(_name, _priv) \
|
||||
class NETLIB_NAME(_name) : public netlist_device_t \
|
||||
{ \
|
||||
public: \
|
||||
NETLIB_NAME(_name) () \
|
||||
: netlist_device_t() { } \
|
||||
protected: \
|
||||
ATTR_HOT void update(); \
|
||||
ATTR_HOT void start(); \
|
||||
_priv \
|
||||
}
|
||||
NETLIB_DEVICE_BASE(NETLIB_NAME(_name), netlist_device_t, , _priv)
|
||||
|
||||
#define NETLIB_SUBDEVICE(_name, _priv) \
|
||||
class NETLIB_NAME(_name) : public netlist_core_device_t \
|
||||
@ -195,17 +202,14 @@ typedef delegate<void ()> net_update_delegate;
|
||||
}
|
||||
|
||||
#define NETLIB_DEVICE_WITH_PARAMS(_name, _priv) \
|
||||
class NETLIB_NAME(_name) : public netlist_device_t \
|
||||
{ \
|
||||
public: \
|
||||
NETLIB_NAME(_name) () \
|
||||
: netlist_device_t() { } \
|
||||
ATTR_HOT void update_param(); \
|
||||
ATTR_HOT void update(); \
|
||||
ATTR_HOT void start(); \
|
||||
/* protected: */ \
|
||||
_priv \
|
||||
}
|
||||
NETLIB_DEVICE_BASE(NETLIB_NAME(_name), netlist_device_t, \
|
||||
ATTR_HOT void update_param(); \
|
||||
, _priv)
|
||||
|
||||
#define NETLIB_DEVICE_WITH_PARAMS_DERIVED(_name, _pclass, _priv) \
|
||||
NETLIB_DEVICE_BASE(NETLIB_NAME(_name), NETLIB_NAME(_pclass), \
|
||||
ATTR_HOT void update_param(); \
|
||||
, _priv)
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// forward definitions
|
||||
@ -287,15 +291,27 @@ public:
|
||||
|
||||
ATTR_COLD netlist_terminal_t(const type_t atype, const family_t afamily)
|
||||
: netlist_object_t(atype, afamily)
|
||||
, m_Idr(0.0)
|
||||
, m_g(NETLIST_GMIN)
|
||||
, m_update_list_next(NULL)
|
||||
, m_netdev(NULL)
|
||||
, m_net(NULL)
|
||||
, m_state(INP_STATE_ACTIVE)
|
||||
{}
|
||||
|
||||
ATTR_COLD netlist_terminal_t()
|
||||
: netlist_object_t(TERMINAL, ANALOG)
|
||||
, m_Idr(0.0)
|
||||
, m_update_list_next(NULL)
|
||||
, m_netdev(NULL)
|
||||
, m_net(NULL)
|
||||
, m_state(INP_STATE_ACTIVE)
|
||||
{}
|
||||
|
||||
ATTR_COLD virtual void init_terminal(netlist_core_device_t &dev);
|
||||
|
||||
ATTR_COLD void set_net(netlist_net_t &anet) { m_net = &anet; }
|
||||
ATTR_COLD bool has_net() { return (m_net != NULL); }
|
||||
|
||||
ATTR_HOT inline const netlist_net_t & RESTRICT net() const { return *m_net;}
|
||||
ATTR_HOT inline netlist_net_t & RESTRICT net() { return *m_net;}
|
||||
@ -306,6 +322,9 @@ public:
|
||||
|
||||
ATTR_HOT inline netlist_core_device_t & RESTRICT netdev() const { return *m_netdev; }
|
||||
|
||||
double m_Idr; // drive current
|
||||
double m_g; // conductance
|
||||
|
||||
netlist_terminal_t *m_update_list_next;
|
||||
|
||||
private:
|
||||
@ -421,6 +440,7 @@ public:
|
||||
ATTR_COLD netlist_net_t(const type_t atype, const family_t afamily);
|
||||
|
||||
ATTR_COLD void register_con(netlist_terminal_t &terminal);
|
||||
ATTR_COLD void merge_net(netlist_net_t *othernet);
|
||||
ATTR_COLD void register_railterminal(netlist_terminal_t &mr)
|
||||
{
|
||||
assert(m_railterminal == NULL);
|
||||
@ -447,6 +467,16 @@ public:
|
||||
ATTR_HOT inline const netlist_sig_t last_Q() const { return m_last.Q; }
|
||||
ATTR_HOT inline const netlist_sig_t new_Q() const { return m_new.Q; }
|
||||
|
||||
ATTR_HOT inline const double Q_Analog() const
|
||||
{
|
||||
//assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG);
|
||||
assert(family() == ANALOG);
|
||||
return m_cur.Analog;
|
||||
}
|
||||
|
||||
ATTR_HOT inline void push_to_queue(const netlist_time &delay);
|
||||
ATTR_HOT bool is_queued() { return m_in_queue == 1; }
|
||||
|
||||
protected:
|
||||
|
||||
/* prohibit use in device functions
|
||||
@ -458,14 +488,6 @@ protected:
|
||||
assert(family() == LOGIC);
|
||||
return m_cur.Q;
|
||||
}
|
||||
ATTR_HOT inline const double Q_Analog() const
|
||||
{
|
||||
//assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG);
|
||||
assert(family() == ANALOG);
|
||||
return m_cur.Analog;
|
||||
}
|
||||
|
||||
ATTR_HOT inline void push_to_queue(const netlist_time &delay);
|
||||
|
||||
hybrid_t m_last;
|
||||
hybrid_t m_cur;
|
||||
@ -670,6 +692,8 @@ public:
|
||||
|
||||
ATTR_COLD void register_sub(netlist_core_device_t &dev, const astring &name);
|
||||
|
||||
ATTR_COLD void register_terminal(const astring &name, netlist_terminal_t &port);
|
||||
|
||||
ATTR_COLD void register_output(const astring &name, netlist_output_t &out);
|
||||
ATTR_COLD void register_output(netlist_core_device_t &dev, const astring &name, netlist_output_t &out);
|
||||
|
||||
@ -850,6 +874,71 @@ private:
|
||||
double m_high_V;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// nld_twoterm
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class nld_twoterm : public netlist_device_t
|
||||
{
|
||||
public:
|
||||
nld_twoterm()
|
||||
: netlist_device_t(), 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()
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_HOT ATTR_ALIGN virtual void update()
|
||||
{
|
||||
m_N.m_Idr = (m_P.net().Q_Analog() - m_V) * m_g + m_I;
|
||||
m_P.m_Idr = (m_N.net().Q_Analog() + m_V) * m_g - m_I;
|
||||
printf("%f %f %f %f\n", m_N.m_Idr, m_P.m_Idr, m_N.net().Q_Analog(), m_P.net().Q_Analog());
|
||||
if (!m_N.net().is_queued() && !m_N.net().isRailNet())
|
||||
m_N.net().push_to_queue(NLTIME_FROM_NS(10));
|
||||
if (!m_P.net().is_queued() && !m_P.net().isRailNet() )
|
||||
m_P.net().push_to_queue(NLTIME_FROM_NS(10));
|
||||
}
|
||||
|
||||
double m_g; // conductance
|
||||
double m_V; // internal voltage source
|
||||
double m_I; // internal current source
|
||||
private:
|
||||
};
|
||||
|
||||
class nld_R : public nld_twoterm
|
||||
{
|
||||
public:
|
||||
nld_R()
|
||||
: nld_twoterm()
|
||||
{
|
||||
}
|
||||
|
||||
netlist_param_t m_R;
|
||||
|
||||
protected:
|
||||
void start()
|
||||
{
|
||||
register_terminal("1", m_P);
|
||||
register_terminal("2", m_N);
|
||||
|
||||
register_param("R", m_R, NETLIST_GMIN);
|
||||
}
|
||||
|
||||
virtual void update_param()
|
||||
{
|
||||
m_g = 1.0 / m_R.Value();
|
||||
m_P.m_g = m_g;
|
||||
m_N.m_g = m_g;
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Inline implementations
|
||||
|
@ -38,6 +38,8 @@
|
||||
|
||||
#define NETLIST_HIGHIMP_V (1.23456e20) /* some voltage we should never see */
|
||||
|
||||
#define NETLIST_GMIN (1e-9)
|
||||
|
||||
typedef UINT8 netlist_sig_t;
|
||||
|
||||
/* FIXME: We need a different solution to output delegates !
|
||||
|
@ -95,7 +95,7 @@ void netlist_parser::netdev_device(const astring &dev_type)
|
||||
m_p++;
|
||||
skipws();
|
||||
astring output_name = getname2(',', ')');
|
||||
NL_VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), dev->m_inputs.item(cnt)->cstr()));
|
||||
NL_VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), dev->m_terminals.item(cnt)->cstr()));
|
||||
m_setup.register_link(*dev->m_terminals.item(cnt), output_name);
|
||||
skipws();
|
||||
cnt++;
|
||||
|
@ -23,6 +23,7 @@ NETLIST_END
|
||||
|
||||
netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
|
||||
: m_netlist(netlist)
|
||||
, m_proxy_cnt(0)
|
||||
{
|
||||
NETLIST_NAME(base)(*this);
|
||||
}
|
||||
@ -110,6 +111,18 @@ void netlist_setup_t::register_output(netlist_core_device_t &dev, netlist_core_d
|
||||
fatalerror("Error adding output %s to terminal list\n", name.cstr());
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_terminal(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_terminal_t &out)
|
||||
{
|
||||
NL_VERBOSE_OUT(("output %s\n", name.cstr()));
|
||||
assert(out.isType(netlist_terminal_t::TERMINAL));
|
||||
astring temp = dev.name();
|
||||
temp.cat(".");
|
||||
temp.cat(name);
|
||||
out.init_terminal(upd_dev);
|
||||
if (!(m_terminals.add(temp, &out, false)==TMERR_NONE))
|
||||
fatalerror("Error adding output %s to terminal list\n", name.cstr());
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_input(netlist_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_input_t &inp, netlist_input_t::net_input_state type)
|
||||
{
|
||||
NL_VERBOSE_OUT(("input %s\n", name.cstr()));
|
||||
@ -176,6 +189,26 @@ netlist_output_t &netlist_setup_t::find_output(const astring &outname_in)
|
||||
return *ret;
|
||||
}
|
||||
|
||||
netlist_terminal_t &netlist_setup_t::find_terminal(const astring &terminal_in)
|
||||
{
|
||||
const astring &tname = resolve_alias(terminal_in);
|
||||
netlist_terminal_t *ret;
|
||||
|
||||
ret = dynamic_cast<netlist_terminal_t *>(m_terminals.find(tname));
|
||||
/* look for default */
|
||||
if (ret == NULL)
|
||||
{
|
||||
/* look for ".Q" std output */
|
||||
astring s = tname;
|
||||
s.cat(".Q");
|
||||
ret = dynamic_cast<netlist_terminal_t *>(m_terminals.find(s));
|
||||
}
|
||||
if (ret == NULL)
|
||||
fatalerror("terminal %s(%s) not found!\n", terminal_in.cstr(), tname.cstr());
|
||||
NL_VERBOSE_OUT(("Found input %s\n", tname.cstr()));
|
||||
return *ret;
|
||||
}
|
||||
|
||||
netlist_param_t &netlist_setup_t::find_param(const astring ¶m_in)
|
||||
{
|
||||
const astring &outname = resolve_alias(param_in);
|
||||
@ -188,68 +221,163 @@ netlist_param_t &netlist_setup_t::find_param(const astring ¶m_in)
|
||||
return *ret;
|
||||
}
|
||||
|
||||
|
||||
void netlist_setup_t::connect_input_output(netlist_input_t &in, netlist_output_t &out)
|
||||
{
|
||||
if (out.isFamily(netlist_terminal_t::ANALOG) && in.isFamily(netlist_terminal_t::LOGIC))
|
||||
{
|
||||
nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(in);
|
||||
astring x = "";
|
||||
x.printf("proxy_ad_%d", m_proxy_cnt++);
|
||||
|
||||
proxy->init(*this, x.cstr());
|
||||
register_dev(proxy);
|
||||
|
||||
proxy->m_Q.net().register_con(in);
|
||||
out.net().register_con(proxy->m_I);
|
||||
|
||||
}
|
||||
else if (out.isFamily(netlist_terminal_t::LOGIC) && in.isFamily(netlist_terminal_t::ANALOG))
|
||||
{
|
||||
//printf("here 1\n");
|
||||
nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out);
|
||||
astring x = "";
|
||||
x.printf("proxy_da_%d", m_proxy_cnt++);
|
||||
proxy->init(*this, x.cstr());
|
||||
register_dev(proxy);
|
||||
|
||||
proxy->m_Q.net().register_con(in);
|
||||
out.net().register_con(proxy->m_I);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.net().register_con(in);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: optimize code ...
|
||||
void netlist_setup_t::connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out)
|
||||
{
|
||||
if (out.isFamily(netlist_terminal_t::ANALOG))
|
||||
{
|
||||
/* no proxy needed, just merge existing terminal net */
|
||||
if (in.has_net())
|
||||
out.net().merge_net(&in.net());
|
||||
else
|
||||
out.net().register_con(in);
|
||||
|
||||
}
|
||||
else if (out.isFamily(netlist_terminal_t::LOGIC))
|
||||
{
|
||||
//printf("here 1\n");
|
||||
nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out);
|
||||
astring x = "";
|
||||
x.printf("proxy_da_%d", m_proxy_cnt++);
|
||||
proxy->init(*this, x.cstr());
|
||||
register_dev(proxy);
|
||||
|
||||
out.net().register_con(proxy->m_I);
|
||||
|
||||
if (in.has_net())
|
||||
proxy->m_Q.net().merge_net(&in.net());
|
||||
else
|
||||
proxy->m_Q.net().register_con(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalerror("Netlist: Severe Error");
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_setup_t::connect_terminals(netlist_terminal_t &in, netlist_terminal_t &out)
|
||||
{
|
||||
assert(in.isType(netlist_terminal_t::TERMINAL));
|
||||
assert(out.isType(netlist_terminal_t::TERMINAL));
|
||||
|
||||
if (in.has_net() && out.has_net())
|
||||
{
|
||||
in.net().merge_net(&out.net());
|
||||
//in.net().register_con(out);
|
||||
//in.net().register_con(in);
|
||||
}
|
||||
else if (out.has_net())
|
||||
{
|
||||
out.net().register_con(in);
|
||||
//out.net().register_con(out);
|
||||
}
|
||||
else if (in.has_net())
|
||||
{
|
||||
in.net().register_con(out);
|
||||
//in.net().register_con(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
NL_VERBOSE_OUT(("adding net ...\n"));
|
||||
in.set_net(*(new netlist_net_t(netlist_object_t::NET, netlist_object_t::ANALOG)));
|
||||
in.net().init_object(netlist());
|
||||
in.net().register_con(out);
|
||||
in.net().register_con(in);
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_setup_t::resolve_inputs(void)
|
||||
{
|
||||
NL_VERBOSE_OUT(("Resolving ...\n"));
|
||||
int proxy_cnt = 0;
|
||||
for (tagmap_astring_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry))
|
||||
{
|
||||
const astring *sout = entry->object();
|
||||
astring sin = entry->tag();
|
||||
netlist_input_t *in = dynamic_cast<netlist_input_t *>(m_terminals.find(sin));
|
||||
NL_VERBOSE_OUT(("Searching for clocks ...\n"));
|
||||
/* find the main clock ... */
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
netlist_device_t *dev = entry->object();
|
||||
if (dynamic_cast<NETLIB_NAME(mainclock)*>(dev) != NULL)
|
||||
{
|
||||
m_netlist.set_mainclock_dev(dynamic_cast<NETLIB_NAME(mainclock)*>(dev));
|
||||
}
|
||||
}
|
||||
|
||||
if (in == NULL)
|
||||
fatalerror("Unable to find %s\n", sin.cstr());
|
||||
NL_VERBOSE_OUT(("Resolving ...\n"));
|
||||
for (tagmap_astring_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry))
|
||||
{
|
||||
const astring t1s = *entry->object();
|
||||
const astring t2s = entry->tag();
|
||||
netlist_terminal_t &t1 = find_terminal(t1s);
|
||||
netlist_terminal_t &t2 = find_terminal(t2s);
|
||||
|
||||
netlist_output_t &out = find_output(sout->cstr());
|
||||
if (out.isFamily(netlist_terminal_t::ANALOG) && in->isFamily(netlist_terminal_t::LOGIC))
|
||||
{
|
||||
nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(*in);
|
||||
astring x = "";
|
||||
x.printf("proxy_ad_%d", proxy_cnt++);
|
||||
// FIXME: amend device design so that warnings can be turned into errors
|
||||
// Only variable inputs have this issue
|
||||
if (t1.isType(netlist_terminal_t::OUTPUT) && t2.isType(netlist_terminal_t::INPUT))
|
||||
{
|
||||
if (t2.has_net())
|
||||
mame_printf_warning("Input %s already connected\n", t2s.cstr());
|
||||
connect_input_output(dynamic_cast<netlist_input_t &>(t2), dynamic_cast<netlist_output_t &>(t1));
|
||||
}
|
||||
else if (t1.isType(netlist_terminal_t::INPUT) && t2.isType(netlist_terminal_t::OUTPUT))
|
||||
{
|
||||
if (t1.has_net())
|
||||
mame_printf_warning("Input %s already connected\n", t1s.cstr());
|
||||
connect_input_output(dynamic_cast<netlist_input_t &>(t1), dynamic_cast<netlist_output_t &>(t2));
|
||||
}
|
||||
else if (t1.isType(netlist_terminal_t::OUTPUT) && t2.isType(netlist_terminal_t::TERMINAL))
|
||||
{
|
||||
connect_terminal_output(dynamic_cast<netlist_terminal_t &>(t2), dynamic_cast<netlist_output_t &>(t1));
|
||||
}
|
||||
else if (t1.isType(netlist_terminal_t::TERMINAL) && t2.isType(netlist_terminal_t::OUTPUT))
|
||||
{
|
||||
connect_terminal_output(dynamic_cast<netlist_terminal_t &>(t1), dynamic_cast<netlist_output_t &>(t2));
|
||||
}
|
||||
else if (t1.isType(netlist_terminal_t::TERMINAL) && t2.isType(netlist_terminal_t::TERMINAL))
|
||||
{
|
||||
connect_terminals(dynamic_cast<netlist_terminal_t &>(t1), dynamic_cast<netlist_terminal_t &>(t2));
|
||||
}
|
||||
else
|
||||
fatalerror("Connecting %s to %s not supported!\n", t1s.cstr(), t2s.cstr());
|
||||
}
|
||||
|
||||
proxy->init(*this, x.cstr());
|
||||
register_dev(proxy);
|
||||
|
||||
proxy->m_Q.net().register_con(*in);
|
||||
out.net().register_con(proxy->m_I);
|
||||
|
||||
}
|
||||
else if (out.isFamily(netlist_terminal_t::LOGIC) && in->isFamily(netlist_terminal_t::ANALOG))
|
||||
{
|
||||
//printf("here 1\n");
|
||||
nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out);
|
||||
astring x = "";
|
||||
x.printf("proxy_da_%d", proxy_cnt++);
|
||||
proxy->init(*this, x.cstr());
|
||||
register_dev(proxy);
|
||||
|
||||
proxy->m_Q.net().register_con(*in);
|
||||
out.net().register_con(proxy->m_I);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.net().register_con(*in);
|
||||
}
|
||||
}
|
||||
|
||||
/* find the main clock ... */
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
netlist_device_t *dev = entry->object();
|
||||
if (dynamic_cast<NETLIB_NAME(mainclock)*>(dev) != NULL)
|
||||
{
|
||||
m_netlist.set_mainclock_dev(dynamic_cast<NETLIB_NAME(mainclock)*>(dev));
|
||||
}
|
||||
}
|
||||
|
||||
/* print all outputs */
|
||||
for (tagmap_terminal_t::entry_t *entry = m_terminals.first(); entry != NULL; entry = m_terminals.next(entry))
|
||||
{
|
||||
ATTR_UNUSED netlist_output_t *out = dynamic_cast<netlist_output_t *>(entry->object());
|
||||
//if (out != NULL)
|
||||
//VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
|
||||
}
|
||||
/* print all outputs */
|
||||
for (tagmap_terminal_t::entry_t *entry = m_terminals.first(); entry != NULL; entry = m_terminals.next(entry))
|
||||
{
|
||||
ATTR_UNUSED netlist_output_t *out = dynamic_cast<netlist_output_t *>(entry->object());
|
||||
//if (out != NULL)
|
||||
//VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -28,8 +28,13 @@
|
||||
NET_REGISTER_DEV(_type ## _ ## sig, _name)
|
||||
#define NET_CONNECT(_name, _input, _output) \
|
||||
netlist.register_link(# _name "." # _input, # _output);
|
||||
#define NET_C(_input, _output) \
|
||||
netlist.register_link(# _input , # _output);
|
||||
#define NETDEV_PARAM(_name, _val) \
|
||||
netlist.find_param(# _name).initial(_val);
|
||||
#define NETDEV_PARAMI(_name, _param, _val) \
|
||||
netlist.find_param(# _name "." # _param).initial(_val);
|
||||
|
||||
|
||||
#define NETLIST_NAME(_name) netlist ## _ ## _name
|
||||
|
||||
@ -71,6 +76,7 @@ public:
|
||||
netlist_device_t *register_dev(netlist_device_t *dev);
|
||||
void remove_dev(const astring &name);
|
||||
|
||||
void register_terminal(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_terminal_t &out);
|
||||
void register_output(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_output_t &out);
|
||||
void register_input(netlist_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_input_t &inp, netlist_input_t::net_input_state type);
|
||||
void register_alias(const astring &alias, const astring &out);
|
||||
@ -79,6 +85,7 @@ public:
|
||||
void register_link(const astring &sin, const astring &sout);
|
||||
|
||||
netlist_output_t &find_output(const astring &outname_in);
|
||||
netlist_terminal_t &find_terminal(const astring &outname_in);
|
||||
netlist_param_t &find_param(const astring ¶m_in);
|
||||
|
||||
void register_callback(const astring &devname, netlist_output_delegate delegate);
|
||||
@ -105,6 +112,12 @@ private:
|
||||
tagmap_param_t m_params;
|
||||
tagmap_astring_t m_links;
|
||||
|
||||
int m_proxy_cnt;
|
||||
|
||||
void connect_terminals(netlist_terminal_t &in, netlist_terminal_t &out);
|
||||
void connect_input_output(netlist_input_t &in, netlist_output_t &out);
|
||||
void connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out);
|
||||
|
||||
netlist_output_t *find_output_exact(const astring &outname_in);
|
||||
const astring &resolve_alias(const astring &name) const;
|
||||
};
|
||||
|
@ -464,6 +464,16 @@ static NETLIST_START(pong_schematics)
|
||||
NETDEV_PARAM(videomix.R1, RES_K(1))
|
||||
NETDEV_PARAM(videomix.R2, RES_K(1.2))
|
||||
NETDEV_PARAM(videomix.R3, RES_K(22))
|
||||
|
||||
#if 0
|
||||
NETDEV_ANALOG_CONST(V5, 5)
|
||||
NETDEV_ANALOG_CONST(V0, 0)
|
||||
NETDEV_R(R1, 10)
|
||||
NETDEV_R(R2, 10)
|
||||
NET_C(V5,R1.1)
|
||||
NET_C(R1.2, R2.1)
|
||||
NET_C(R2.2, V0)
|
||||
#endif
|
||||
NETLIST_END
|
||||
|
||||
static NETLIST_START(pong)
|
||||
|
Loading…
Reference in New Issue
Block a user