Netlist: Need a checkpoint before I continue.

This commit is contained in:
Couriersud 2013-11-15 19:57:34 +00:00
parent 4333d8f25a
commit 12ae4ea748
12 changed files with 497 additions and 147 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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]);
}
}

View File

@ -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 );
}

View File

@ -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
// ----------------------------------------------------------------------------------------

View File

@ -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;
}
}
// ----------------------------------------------------------------------------------------

View File

@ -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

View File

@ -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 !

View File

@ -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++;

View File

@ -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 &param_in)
{
const astring &outname = resolve_alias(param_in);
@ -188,68 +221,163 @@ netlist_param_t &netlist_setup_t::find_param(const astring &param_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()));
}
}

View File

@ -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 &param_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;
};

View File

@ -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)