netlist: Added capacitor. At 50kHz, calculating a resistor net and a cap doesn't hit performance. Promising.

This commit is contained in:
Couriersud 2013-11-17 19:07:14 +00:00
parent 932d0281f2
commit 4a64c9b058
12 changed files with 202 additions and 42 deletions

View File

@ -75,7 +75,7 @@ NETLIB_START(log)
NETLIB_UPDATE(log)
{
printf("%s: %d %d\n", name().cstr(), (UINT32) (netlist().time().as_raw() / 1000000), INPLOGIC(m_I));
printf("%s: %f %f\n", name().cstr(), netlist().time().as_double(), INPANALOG(m_I));
}
@ -950,6 +950,7 @@ NETLIB_FUNC_VOID(nic9316_sub, update_outputs, (void))
static const net_device_t_base_factory *netregistry[] =
{
ENTRY(R, NETDEV_R)
ENTRY(C, NETDEV_C)
ENTRY(ttl_const, NETDEV_TTL_CONST)
ENTRY(analog_const, NETDEV_ANALOG_CONST)
ENTRY(logic_input, NETDEV_LOGIC_INPUT)

View File

@ -71,7 +71,11 @@
#define NETDEV_R(_name, _R) \
NET_REGISTER_DEV(R, _name) \
NETDEV_PARAMI(_name, R, _R) \
NETDEV_PARAMI(_name, R, _R)
#define NETDEV_C(_name, _C) \
NET_REGISTER_DEV(C, _name) \
NETDEV_PARAMI(_name, C, _C)
// ----------------------------------------------------------------------------------------
@ -238,7 +242,7 @@ NETLIB_DEVICE(analog_input,
);
NETLIB_DEVICE(log,
netlist_ttl_input_t m_I;
netlist_analog_input_t m_I;
);

View File

@ -85,9 +85,10 @@ NETLIB_START(solver)
register_output("Q", m_Q);
//register_input("FB", m_feedback);
m_inc = netlist_time::from_hz(48000);
m_inc = netlist_time::from_hz(50000);
register_link_internal(m_feedback, m_Q, netlist_input_t::STATE_INP_ACTIVE);
m_last_step = netlist_time::zero;
}
@ -96,40 +97,78 @@ NETLIB_UPDATE_PARAM(solver)
//m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
NETLIB_FUNC_VOID(solver, post_start, ())
{
for (netlist_net_t **pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
{
for (netlist_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next)
{
switch (p->type())
{
case netlist_terminal_t::TERMINAL:
m_terms.add(p);
break;
case netlist_terminal_t::INPUT:
m_inps.add(p);
break;
default:
fatalerror("unhandled element found\n");
break;
}
}
}
}
NETLIB_UPDATE(solver)
{
//m_Q.setToNoCheck(!m_Q.new_Q(), m_inc );
//OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc );
netlist_net_t **pn = m_nets.first();
bool resched = false;
netlist_time now = netlist().time();
netlist_time delta = now - m_last_step;
while (pn <= m_nets.last())
if (delta >= m_inc)
{
/* update all terminals for new time step */
m_last_step = now;
for (netlist_terminal_t **p = m_terms.first(); p != NULL; p = m_terms.next(p))
(*p)->netdev().step_time(delta.as_double());
}
for (netlist_net_t **pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
{
double gtot = 0;
double iIdr = 0;
netlist_terminal_t *p = (*pn)->m_head;
do
for (netlist_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next)
{
p->netdev().update_terminals();
gtot += p->m_g;
iIdr += p->m_Idr;
}
p = p->m_update_list_next;
} while (p != NULL);
(*pn)->m_new.Analog = iIdr / gtot;
if (fabs((*pn)->m_new.Analog - (*pn)->m_cur.Analog) > 1e-4)
double new_val = iIdr / gtot;
if (fabs(new_val - (*pn)->m_cur.Analog) > 1e-4)
resched = true;
(*pn)->m_cur.Analog = (*pn)->m_new.Analog;
(*pn)->m_cur.Analog = (*pn)->m_new.Analog = new_val;
//printf("New: %f\n", (*pn)->m_new.Analog);
pn++;
//printf("New: %d %lld %f %f\n", ts_cnt, netlist().time().as_raw(), netlist().time().as_double(), new_val);
}
if (resched)
{
schedule();
}
else
m_Q.net().push_to_queue(m_inc); // step circuit
{
/* update all inputs connected to this drive */
for (netlist_terminal_t **p = m_inps.first(); p != NULL; p = m_inps.next(p))
(*p)->netdev().update_dev();
/* step circuit */
if (!m_Q.net().is_queued())
{
m_Q.net().push_to_queue(m_inc);
}
}
/* only inputs and terminals connected
* approach:

View File

@ -11,7 +11,6 @@
#include "../nl_setup.h"
#include "../nl_base.h"
#include "../nl_lists.h"
// ----------------------------------------------------------------------------------------
// Macros
@ -83,17 +82,24 @@ NETLIB_DEVICE_WITH_PARAMS(solver,
netlist_ttl_output_t m_Q;
netlist_time m_inc;
netlist_time m_last_step;
netlist_list_t<netlist_terminal_t *> m_terms;
netlist_list_t<netlist_terminal_t *> m_inps;
public:
netlist_list_t<netlist_net_t *> m_nets;
ATTR_HOT inline void schedule();
ATTR_COLD void post_start();
);
inline void NETLIB_NAME(solver)::schedule()
{
// FIXME: time should be parameter;
if (!m_Q.net().is_queued())
if (!m_Q.net().is_queued()) {
m_Q.net().push_to_queue(NLTIME_FROM_NS(10));
}
}
// ----------------------------------------------------------------------------------------
@ -154,13 +160,8 @@ protected:
ATTR_HOT ATTR_ALIGN virtual void update()
{
netlist().solver().schedule();
#if 0
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));
#endif
/* only called if connected to a rail net ==> notify the solver to recalculate */
netlist().solver()->schedule();
}
double m_g; // conductance
@ -198,4 +199,38 @@ protected:
private:
};
class nld_C : public nld_twoterm
{
public:
nld_C()
: nld_twoterm()
{
}
netlist_param_t m_C;
protected:
void start()
{
register_terminal("1", m_P);
register_terminal("2", m_N);
register_param("C", m_C, NETLIST_GMIN);
}
virtual void update_param()
{
// set to some very big step time for now
// ==> large resistance
step_time(1e-9);
}
ATTR_HOT virtual void step_time(const double st)
{
m_g = m_P.m_g = m_N.m_g = m_C.Value() / st;
m_I = -m_g * (m_P.net().Q_Analog()- m_N.net().Q_Analog());
}
private:
};
#endif /* NLD_SYSTEM_H_ */

View File

@ -233,6 +233,7 @@ ATTR_COLD void netlist_device_t::register_output(const astring &name, netlist_ou
ATTR_COLD void netlist_device_t::register_input(netlist_core_device_t &dev, const astring &name, netlist_input_t &inp, netlist_input_t::state_e type)
{
m_terminals.add(name);
m_setup->register_object(*this, dev, name, inp, type);
}

View File

@ -168,7 +168,7 @@ typedef delegate<void ()> net_update_delegate;
// : net_device_t(setup, name)
#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_FUNC_VOID(_chip, _name, _params) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: _name _params
#define NETLIB_DEVICE_BASE(_name, _pclass, _extra, _priv) \
class _name : public _pclass \
@ -661,6 +661,7 @@ public:
ATTR_HOT virtual void dec_active() { /*printf("DeActivate %s\n", m_name);*/ }
ATTR_HOT virtual void step_time(const double st) { }
ATTR_HOT virtual void update_terminals() { }
/* stats */
@ -774,7 +775,7 @@ public:
m_queue.push(queue_t::entry_t(attime, out));
}
ATTR_HOT NETLIB_NAME(solver) &solver() { return *m_solver; }
ATTR_HOT NETLIB_NAME(solver) *solver() { return m_solver; }
ATTR_HOT void process_queue(INT32 &atime);

View File

@ -36,6 +36,15 @@ public:
*(++m_ptr) = elem;
}
ATTR_HOT inline void resize(const int new_size)
{
int cnt = count();
_ListClass *m_new = new _ListClass[new_size];
memcpy(m_new, m_list, new_size * sizeof(_ListClass));
delete[] m_list;
m_list = m_new;
m_ptr = m_list + cnt - 1;
}
ATTR_HOT inline void del(const _ListClass elem)
{
for (_ListClass * i=m_list; i<=m_ptr; i++)
@ -52,7 +61,8 @@ public:
}
}
}
ATTR_HOT inline _ListClass *first() { return &m_list[0]; }
ATTR_HOT inline _ListClass *first() { return (m_ptr >= m_list ? &m_list[0] : NULL ); }
ATTR_HOT inline _ListClass *next(_ListClass *lc) { return (lc < last() ? lc + 1 : NULL ); }
ATTR_HOT inline _ListClass *last() { return m_ptr; }
ATTR_HOT inline _ListClass *item(int i) { return &m_list[i]; }
ATTR_HOT inline int count() const { return m_ptr - m_list + 1; }

View File

@ -96,7 +96,7 @@ void netlist_parser::netdev_device(const astring &dev_type)
skipws();
astring output_name = getname2(',', ')');
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);
m_setup.register_link(devname + "." + *dev->m_terminals.item(cnt), output_name);
skipws();
cnt++;
}

View File

@ -41,7 +41,7 @@ static void tagmap_free_entries(T &tm)
netlist_setup_t::~netlist_setup_t()
{
tagmap_free_entries<tagmap_devices_t>(m_devices);
tagmap_free_entries<tagmap_astring_t>(m_links);
tagmap_free_entries<tagmap_link_t>(m_links);
tagmap_free_entries<tagmap_astring_t>(m_alias);
m_params.reset();
m_terminals.reset();
@ -82,7 +82,15 @@ void netlist_setup_t::remove_dev(const astring &name)
//remove_start_with<tagmap_input_t>(m_inputs, temp);
remove_start_with<tagmap_terminal_t>(m_terminals, temp);
remove_start_with<tagmap_param_t>(m_params, temp);
remove_start_with<tagmap_astring_t>(m_links, temp);
tagmap_link_t::entry_t *p = m_links.first();
while (p != NULL)
{
tagmap_link_t::entry_t *n = m_links.next(p);
if (temp.cmpsubstr(p->object()->e1,0,temp.len()) == 0 || temp.cmpsubstr(p->object()->e2,0,temp.len()) == 0)
m_links.remove(p->object());
p = n;
}
m_devices.remove(name);
}
@ -141,7 +149,7 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
term.init_terminal(upd_dev);
term.set_state(state);
if (!(m_terminals.add(temp, &term, false)==TMERR_NONE))
fatalerror("Error adding %s %s to terminal list\n", objtype_as_astr(term).cstr(), name.cstr());
fatalerror("Error adding %s %s to terminal list\n", objtype_as_astr(term).cstr(), temp.cstr());
NL_VERBOSE_OUT(("%s %s\n", objtype_as_astr(term).cstr(), name.cstr()));
}
break;
@ -164,9 +172,9 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
void netlist_setup_t::register_link(const astring &sin, const astring &sout)
{
const astring *temp = new astring(sout);
link_t *temp = new link_t(sin, sout);
NL_VERBOSE_OUT(("link %s <== %s\n", sin.cstr(), sout.cstr()));
if (!(m_links.add(sin, temp, false)==TMERR_NONE))
if (!(m_links.add(sin + "." + sout, temp, false)==TMERR_NONE))
fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr());
}
@ -266,6 +274,34 @@ void netlist_setup_t::connect_input_output(netlist_input_t &in, netlist_output_t
}
}
void netlist_setup_t::connect_terminal_input(netlist_terminal_t &term, netlist_input_t &inp)
{
if (inp.isFamily(netlist_terminal_t::ANALOG))
{
connect_terminals(term, inp);
}
else if (inp.isFamily(netlist_terminal_t::LOGIC))
{
//printf("here 1\n");
nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(inp);
astring x = "";
x.printf("proxy_da_%d", m_proxy_cnt++);
proxy->init(*this, x.cstr());
register_dev(proxy);
connect_terminals(term, proxy->m_I);
if (inp.has_net())
proxy->m_Q.net().merge_net(&inp.net());
else
proxy->m_Q.net().register_con(inp);
}
else
{
fatalerror("Netlist: Severe Error");
}
}
// FIXME: optimize code ...
void netlist_setup_t::connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out)
{
@ -322,7 +358,7 @@ void netlist_setup_t::connect_terminals(netlist_terminal_t &in, netlist_terminal
NL_VERBOSE_OUT(("adding net ...\n"));
netlist_net_t *anet = new netlist_net_t(netlist_object_t::NET, netlist_object_t::ANALOG);
in.set_net(*anet);
m_netlist.solver().m_nets.add(anet);
m_netlist.solver()->m_nets.add(anet);
in.net().init_object(netlist());
in.net().register_con(out);
in.net().register_con(in);
@ -347,10 +383,10 @@ void netlist_setup_t::resolve_inputs(void)
}
NL_VERBOSE_OUT(("Resolving ...\n"));
for (tagmap_astring_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry))
for (tagmap_link_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry))
{
const astring t1s = *entry->object();
const astring t2s = entry->tag();
const astring t1s = entry->object()->e1;
const astring t2s = entry->object()->e2;
netlist_terminal_t &t1 = find_terminal(t1s);
netlist_terminal_t &t2 = find_terminal(t2s);
@ -376,6 +412,14 @@ void netlist_setup_t::resolve_inputs(void)
{
connect_terminal_output(dynamic_cast<netlist_terminal_t &>(t1), dynamic_cast<netlist_output_t &>(t2));
}
else if (t1.isType(netlist_terminal_t::INPUT) && t2.isType(netlist_terminal_t::TERMINAL))
{
connect_terminal_input(dynamic_cast<netlist_terminal_t &>(t2), dynamic_cast<netlist_input_t &>(t1));
}
else if (t1.isType(netlist_terminal_t::TERMINAL) && t2.isType(netlist_terminal_t::INPUT))
{
connect_terminal_input(dynamic_cast<netlist_terminal_t &>(t1), dynamic_cast<netlist_input_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));
@ -392,6 +436,9 @@ void netlist_setup_t::resolve_inputs(void)
//VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
}
if (m_netlist.solver() != NULL)
m_netlist.solver()->post_start();
}

View File

@ -63,7 +63,19 @@ class netlist_setup_t
{
public:
struct link_t
{
link_t(const astring &ae1, const astring &ae2)
{
e1 = ae1;
e2 = ae2;
}
astring e1;
astring e2;
};
typedef tagmap_t<netlist_device_t *, 393> tagmap_devices_t;
typedef tagmap_t<link_t *, 393> tagmap_link_t;
typedef tagmap_t<const astring *, 393> tagmap_astring_t;
typedef tagmap_t<netlist_param_t *, 393> tagmap_param_t;
typedef tagmap_t<netlist_terminal_t *, 393> tagmap_terminal_t;
@ -108,13 +120,14 @@ private:
tagmap_devices_t m_devices;
tagmap_astring_t m_alias;
tagmap_param_t m_params;
tagmap_astring_t m_links;
tagmap_link_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);
void connect_terminal_input(netlist_terminal_t &term, netlist_input_t &inp);
// helpers
astring objtype_as_astr(netlist_object_t &in);

View File

@ -45,6 +45,7 @@ public:
ATTR_HOT inline const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
ATTR_HOT inline const double as_double() const { return (double) m_time / (double) RESOLUTION; }
ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }

View File

@ -465,10 +465,10 @@ static NETLIST_START(pong_schematics)
NETDEV_PARAM(videomix.R2, RES_K(1.2))
NETDEV_PARAM(videomix.R3, RES_K(22))
#if 0
NETDEV_SOLVER(Solver)
NETDEV_ANALOG_CONST(V5, 5)
NETDEV_SOLVER(Solver)
NETDEV_ANALOG_CONST(V5, 5)
NETDEV_ANALOG_CONST(V0, 0)
#if 1
NETDEV_R(R1, 10)
NETDEV_R(R2, 10)
NETDEV_R(R3, 10)
@ -477,6 +477,14 @@ static NETLIST_START(pong_schematics)
NET_C(R2.2, R3.1)
NET_C(R3.2, V0)
#endif
#if 1
NETDEV_R(R4, 1000)
NETDEV_C(C1, 1e-6)
NET_C(V5,R4.1)
NET_C(R4.2, C1.1)
NET_C(C1.2, V0)
//NETDEV_LOG(log1, C1.1)
#endif
NETLIST_END
static NETLIST_START(pong)