diff options
author | 2014-01-02 14:40:36 +0000 | |
---|---|---|
committer | 2014-01-02 14:40:36 +0000 | |
commit | 838276728a99327d99e45768bac9cc659160d7b1 (patch) | |
tree | 1865bc684a201354e8842f9da2a847b5395bfc89 /src | |
parent | e778a278d7c08399a6232ce5625aad463645f0bf (diff) |
Netlist:
- fixed 7474 save state
- remove a printf
- simplified netlist_list_t
- increased reschedule count to 15 - diodes are dog-slow
- made reschedule count a solver parameter
- simplified solver code
- solver time now also resets
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/machine/netlist.c | 2 | ||||
-rw-r--r-- | src/emu/netlist/devices/nld_7474.c | 15 | ||||
-rw-r--r-- | src/emu/netlist/devices/nld_solver.c | 253 | ||||
-rw-r--r-- | src/emu/netlist/devices/nld_solver.h | 17 | ||||
-rw-r--r-- | src/emu/netlist/devices/nld_twoterm.c | 6 | ||||
-rw-r--r-- | src/emu/netlist/nl_base.c | 6 | ||||
-rw-r--r-- | src/emu/netlist/nl_base.h | 6 | ||||
-rw-r--r-- | src/emu/netlist/nl_lists.h | 51 |
8 files changed, 174 insertions, 182 deletions
diff --git a/src/emu/machine/netlist.c b/src/emu/machine/netlist.c index 9ddef77cc29..dd2377e03e8 100644 --- a/src/emu/machine/netlist.c +++ b/src/emu/machine/netlist.c @@ -178,7 +178,7 @@ void netlist_mame_device_t::device_start() { LOG_DEV_CALLS(("device_start %s\n", tag())); - printf("clock is %d\n", clock()); + //printf("clock is %d\n", clock()); m_netlist = global_alloc_clear(netlist_mame_t(*this)); m_setup = global_alloc_clear(netlist_setup_t(*m_netlist)); diff --git a/src/emu/netlist/devices/nld_7474.c b/src/emu/netlist/devices/nld_7474.c index ef23fe819c5..90d11c3e284 100644 --- a/src/emu/netlist/devices/nld_7474.c +++ b/src/emu/netlist/devices/nld_7474.c @@ -47,13 +47,13 @@ NETLIB_START(7474) { register_sub(sub, "sub"); - register_subalias("CLK", sub.m_clk); - register_input("D", m_D); - register_input("CLRQ", m_clrQ); - register_input("PREQ", m_preQ); + register_subalias("CLK", sub.m_clk); + register_input("D", m_D); + register_input("CLRQ", m_clrQ); + register_input("PREQ", m_preQ); - register_subalias("Q", sub.m_Q); - register_subalias("QQ", sub.m_QQ); + register_subalias("Q", sub.m_Q); + register_subalias("QQ", sub.m_QQ); } @@ -64,6 +64,9 @@ NETLIB_START(7474sub) register_output("Q", m_Q); register_output("QQ", m_QQ); + m_nextD = 0; m_Q.initial(1); m_QQ.initial(0); + + save(NAME(m_nextD)); } diff --git a/src/emu/netlist/devices/nld_solver.c b/src/emu/netlist/devices/nld_solver.c index 99f6a1d33c4..9055d5f1781 100644 --- a/src/emu/netlist/devices/nld_solver.c +++ b/src/emu/netlist/devices/nld_solver.c @@ -47,8 +47,8 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets, NETLI NL_VERBOSE_OUT(("Added terminal\n")); break; case netlist_terminal_t::INPUT: - if (!m_inps.contains(&p->netdev())) - m_inps.add(&p->netdev()); + if (!m_inps.contains(p)) + m_inps.add(p); NL_VERBOSE_OUT(("Added input\n")); break; default: @@ -68,103 +68,85 @@ ATTR_HOT inline void netlist_matrix_solver_t::step(const netlist_time delta) ATTR_HOT inline void netlist_matrix_solver_t::update_inputs() { - for (dev_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p)) + for (netlist_core_terminal_t::list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p)) { - p->object()->update_dev(); + if (p->object()->net().m_last.Analog != p->object()->net().m_cur.Analog) + { + p->object()->netdev().update_dev(); + } } + for (netlist_core_terminal_t::list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p)) + { + p->object()->net().m_last.Analog = p->object()->net().m_cur.Analog; + } + } ATTR_HOT inline bool netlist_matrix_solver_t::solve() { - bool resched = false; - - /* update all non-linear devices */ - for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p)) - switch (p->object()->family()) - { - case netlist_device_t::DIODE: - static_cast<NETLIB_NAME(D) *>(p->object())->update_terminals(); - break; - default: - p->object()->update_terminals(); - break; - } + bool resched; + // FIXME: There may be situations where we *could* need more than one iteration for dynamic elements + + int resched_cnt = (is_dynamic() ? /* 0 */ 1 : 1); + ATTR_UNUSED netlist_net_t *last_resched_net = NULL; + + do { + resched = false; + /* update all non-linear devices */ + for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p)) + switch (p->object()->family()) + { + case netlist_device_t::DIODE: + static_cast<NETLIB_NAME(D) *>(p->object())->update_terminals(); + break; + default: + p->object()->update_terminals(); + break; + } + + for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn)) + { + netlist_net_t *net = pn->object(); + const netlist_net_t::terminal_list_t &terms = net->m_terms; + + double gtot = 0; + double gabs = 0; + double iIdr = 0; + double new_val; + + for (int i = 0; i < terms.count(); i++) + { + gtot += terms[i]->m_gt; + gabs += fabs(terms[i]->m_go); + iIdr += terms[i]->m_Idr + terms[i]->m_go * terms[i]->m_otherterm->net().Q_Analog(); + } + + gabs *= m_convergence_factor; + if (gabs > gtot) + new_val = (net->m_cur.Analog * gabs + iIdr) / (gtot + gabs); + else + new_val = iIdr / gtot; + + if (fabs(new_val - net->m_cur.Analog) > m_accuracy) + { + resched = true; + last_resched_net = net; + } + + 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)); + } + resched_cnt++; + } while ((resched && (resched_cnt < m_resched_loops)) || (resched_cnt <= 1)); + + if (!resched) + update_inputs(); + //if (resched) + //printf("Resched on net %s first term %s\n", last_resched_net->name().cstr(), last_resched_net->m_terms[0]->name().cstr()); - for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn)) - { - netlist_net_t *net = pn->object(); - - double gtot = 0; - double gabs = 0; - double iIdr = 0; - const netlist_net_t::terminal_list_t &terms = net->m_terms; -#if 1 - switch (terms.count()) - { - case 1: - { - const netlist_terminal_t *pt = terms.first()->object(); - gtot = pt->m_gt; - gabs = fabs(pt->m_go); - iIdr = pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog(); - } - break; - case 2: - { - const netlist_terminal_t *pt1 = terms[0]; - const netlist_terminal_t *pt2 = terms[1]; - gtot = pt1->m_gt + pt2->m_gt; - gabs = fabs(pt1->m_go) + fabs(pt2->m_go); - iIdr = pt1->m_Idr + pt1->m_go * pt1->m_otherterm->net().Q_Analog() - + pt2->m_Idr + pt2->m_go * pt2->m_otherterm->net().Q_Analog(); - } - break; - case 3: - { - const netlist_terminal_t *pt1 = terms[0]; - const netlist_terminal_t *pt2 = terms[1]; - const netlist_terminal_t *pt3 = terms[2]; - gtot = pt1->m_gt + pt2->m_gt + pt3->m_gt; - gabs = fabs(pt1->m_go) + fabs(pt2->m_go) + fabs(pt3->m_go); - iIdr = pt1->m_Idr + pt1->m_go * pt1->m_otherterm->net().Q_Analog() - + pt2->m_Idr + pt2->m_go * pt2->m_otherterm->net().Q_Analog() - + pt3->m_Idr + pt3->m_go * pt3->m_otherterm->net().Q_Analog(); - } - break; - default: - for (netlist_net_t::terminal_list_t::entry_t *e = terms.first(); e != NULL; e = terms.next(e)) - { - netlist_terminal_t *pt = e->object(); - gtot += pt->m_gt; - gabs += fabs(pt->m_go); - iIdr += pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog(); - } - break; - } -#else - for (netlist_net_t::terminal_list_t::entry_t *e = terms.first(); e != NULL; e = terms.next(e)) - { - netlist_terminal_t *pt = e->object(); - gtot += pt->m_gt; - gabs += fabs(pt->m_go); - iIdr += pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog(); - } -#endif - double new_val; - gabs *= m_convergence_factor; - if (gabs > gtot) - new_val = (net->m_cur.Analog * gabs + iIdr) / (gtot + gabs); - else - new_val = iIdr / gtot; - - if (fabs(new_val - net->m_cur.Analog) > m_accuracy) - resched = true; - 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)); - } return resched; } @@ -174,7 +156,7 @@ ATTR_HOT inline bool netlist_matrix_solver_t::solve() typedef netlist_net_t::list_t *net_groups_t; -static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net) +ATTR_COLD static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net) { if (net->isRailNet()) return true; @@ -186,7 +168,7 @@ static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t return false; } -static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net) +ATTR_COLD static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net) { /* add the net */ if (net->m_head == NULL) @@ -219,6 +201,7 @@ NETLIB_START(solver) register_param("ACCURACY", m_accuracy, 1e-3); register_param("CONVERG", m_convergence, 0.3); + register_param("RESCHED_LOOPS", m_resched_loops, 15); // internal staff @@ -251,44 +234,8 @@ NETLIB_NAME(solver)::~NETLIB_NAME(solver)() } -NETLIB_FUNC_VOID(solver, post_start, ()) -{ - netlist_net_t::list_t groups[100]; - int cur_group = -1; - - SOLVER_VERBOSE_OUT(("Scanning net groups ...\n")); - // determine net groups - for (netlist_net_t::list_t::entry_t *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn)) - { - if (!already_processed(groups, cur_group, pn->object())) - { - cur_group++; - process_net(groups, cur_group, pn->object()); - } - } - - // setup the solvers - SOLVER_VERBOSE_OUT(("Found %d net groups in %d nets\n", cur_group + 1, m_nets.count())); - for (int i = 0; i <= cur_group; i++) - { - netlist_matrix_solver_t *ms = new netlist_matrix_solver_t(); - ms->m_accuracy = m_accuracy.Value(); - ms->m_convergence_factor = m_convergence.Value(); - ms->setup(groups[i], *this); - m_mat_solvers.add(ms); - SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), groups[i].first()->object()->m_head->name().cstr())); - SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic")); - } - -} - NETLIB_UPDATE(solver) { - //m_Q.setToNoCheck(!m_Q.new_Q(), m_inc ); - //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; @@ -305,30 +252,50 @@ NETLIB_UPDATE(solver) bool global_resched = false; for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e)) { - resched_cnt = (e->object()->is_dynamic() ? 0 : 1); - do { - resched = e->object()->solve(); - resched_cnt++; - } while ((resched && (resched_cnt < 5)) || (resched_cnt <= 1)); - global_resched = global_resched || resched; + global_resched = global_resched || e->object()->solve(); } - //if (global_resched) - // printf("rescheduled\n"); if (global_resched) { schedule(); } else { - /* update all inputs connected */ - for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e)) - { - e->object()->update_inputs(); - } - /* step circuit */ if (!m_Q_step.net().is_queued()) m_Q_step.net().push_to_queue(m_inc); } } + +ATTR_COLD void NETLIB_NAME(solver)::post_start() +{ + netlist_net_t::list_t groups[100]; + int cur_group = -1; + + SOLVER_VERBOSE_OUT(("Scanning net groups ...\n")); + // determine net groups + for (netlist_net_t::list_t::entry_t *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn)) + { + if (!already_processed(groups, cur_group, pn->object())) + { + cur_group++; + process_net(groups, cur_group, pn->object()); + } + } + + // setup the solvers + SOLVER_VERBOSE_OUT(("Found %d net groups in %d nets\n", cur_group + 1, netlist().m_nets.count())); + for (int i = 0; i <= cur_group; i++) + { + netlist_matrix_solver_t *ms = new netlist_matrix_solver_t(); + ms->m_accuracy = m_accuracy.Value(); + ms->m_convergence_factor = m_convergence.Value(); + ms->m_resched_loops = m_resched_loops.Value(); + ms->setup(groups[i], *this); + m_mat_solvers.add(ms); + SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), groups[i].first()->object()->m_head->name().cstr())); + SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic")); + SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_timestep() ? "timestep" : "no timestep")); + } + +} diff --git a/src/emu/netlist/devices/nld_solver.h b/src/emu/netlist/devices/nld_solver.h index 0f9d0f54c28..c937e42386b 100644 --- a/src/emu/netlist/devices/nld_solver.h +++ b/src/emu/netlist/devices/nld_solver.h @@ -36,16 +36,18 @@ public: ATTR_HOT void update_inputs(); ATTR_HOT inline bool is_dynamic() { return m_dynamic.count() > 0; } + ATTR_HOT inline bool is_timestep() { return m_steps.count() > 0; } - inline const NETLIB_NAME(solver) &owner() const; + ATTR_HOT inline const NETLIB_NAME(solver) &owner() const; double m_accuracy; double m_convergence_factor; + int m_resched_loops; private: netlist_net_t::list_t m_nets; dev_list_t m_dynamic; - dev_list_t m_inps; + netlist_core_terminal_t::list_t m_inps; dev_list_t m_steps; NETLIB_NAME(solver) *m_owner; @@ -64,6 +66,7 @@ NETLIB_DEVICE_WITH_PARAMS(solver, netlist_param_double_t m_sync_delay; netlist_param_double_t m_accuracy; netlist_param_double_t m_convergence; + netlist_param_int_t m_resched_loops; netlist_time m_inc; netlist_time m_last_step; @@ -72,21 +75,25 @@ NETLIB_DEVICE_WITH_PARAMS(solver, netlist_matrix_solver_t::list_t m_mat_solvers; public: - ~NETLIB_NAME(solver)(); + ATTR_COLD ~NETLIB_NAME(solver)(); ATTR_HOT inline void schedule(); ATTR_COLD void post_start(); + ATTR_COLD void reset() + { + m_last_step = netlist_time::zero; + } ); -inline void NETLIB_NAME(solver)::schedule() +ATTR_HOT inline void NETLIB_NAME(solver)::schedule() { // FIXME: time should be parameter; if (!m_Q_sync.net().is_queued()) m_Q_sync.net().push_to_queue(m_nt_sync_delay); } -inline const NETLIB_NAME(solver) &netlist_matrix_solver_t::owner() const +ATTR_HOT inline const NETLIB_NAME(solver) &netlist_matrix_solver_t::owner() const { return *m_owner; } diff --git a/src/emu/netlist/devices/nld_twoterm.c b/src/emu/netlist/devices/nld_twoterm.c index ba647e35420..cbd4e3b8cf8 100644 --- a/src/emu/netlist/devices/nld_twoterm.c +++ b/src/emu/netlist/devices/nld_twoterm.c @@ -207,6 +207,12 @@ NETLIB_START(QBJT_switch<_type>) setup().connect(m_RB.m_N, m_EV); save(NAME(m_state_on)); + + m_RB.set(NETLIST_GMIN, 0.0, 0.0); + m_RC.set(NETLIST_GMIN, 0.0, 0.0); + + m_state_on = 0; + } NETLIB_UPDATE(Q) diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c index 7704fc6fdec..eb86f8b93ea 100644 --- a/src/emu/netlist/nl_base.c +++ b/src/emu/netlist/nl_base.c @@ -5,6 +5,7 @@ #include "nl_base.h" #include "devices/nld_system.h" +#include "devices/nld_solver.h" #include "pstring.h" #include "nl_util.h" @@ -170,6 +171,8 @@ ATTR_COLD void netlist_base_t::reset() m_queue.clear(); if (m_mainclock != NULL) m_mainclock->m_Q.net().set_time(netlist_time::zero); + if (m_solver != NULL) + m_solver->reset(); // FIXME: some const devices rely on this /* make sure params are set now .. */ @@ -429,6 +432,9 @@ ATTR_COLD netlist_net_t::netlist_net_t(const type_t atype, const family_t afamil , m_in_queue(2) , m_railterminal(NULL) { + m_last.Analog = -123456789.0; // set to something we will never hit. + m_new.Analog = 0.0; + m_cur.Analog = 0.0; }; ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname) diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h index b0c9d238f96..92087f91bff 100644 --- a/src/emu/netlist/nl_base.h +++ b/src/emu/netlist/nl_base.h @@ -332,6 +332,8 @@ class netlist_core_terminal_t : public netlist_owned_object_t NETLIST_PREVENT_COPYING(netlist_core_terminal_t) public: + typedef netlist_list_t<netlist_core_terminal_t *> list_t; + /* needed here ... */ enum state_e { @@ -1093,8 +1095,8 @@ protected: OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1)); else if (m_I.Q_Analog() < m_I.m_low_thresh_V) OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1)); - else - OUTLOGIC(m_Q, m_Q.net().last_Q(), NLTIME_FROM_NS(1)); + //else + // OUTLOGIC(m_Q, m_Q.net().last_Q(), NLTIME_FROM_NS(1)); } }; diff --git a/src/emu/netlist/nl_lists.h b/src/emu/netlist/nl_lists.h index f38def1aa14..8f303d26140 100644 --- a/src/emu/netlist/nl_lists.h +++ b/src/emu/netlist/nl_lists.h @@ -20,10 +20,13 @@ struct netlist_list_t { public: - struct entry_t { + struct entry_t + { + friend class netlist_list_t; + public: // keep compatibility with tagmap - _ListClass object() { return m_obj; } - + ATTR_HOT inline _ListClass object() { return m_obj; } + private: _ListClass m_obj; }; @@ -31,16 +34,14 @@ public: { m_num_elements = numElements; m_list = new entry_t[m_num_elements]; - m_ptr = m_list; - m_ptr--; + m_count = 0; } ATTR_COLD netlist_list_t(const netlist_list_t &rhs) { m_num_elements = rhs.capacity(); m_list = new entry_t[m_num_elements]; - m_ptr = m_list; - m_ptr--; + m_count = 0; for (int i=0; i<rhs.count(); i++) { this->add(rhs[i]); @@ -64,10 +65,10 @@ public: ATTR_HOT inline void add(const _ListClass elem) { - if (m_ptr-m_list >= m_num_elements - 1) + if (m_count >= m_num_elements) resize(m_num_elements * 2); - (++m_ptr)->m_obj = elem; + m_list[m_count++].m_obj = elem; } ATTR_HOT inline void resize(const int new_size) @@ -76,26 +77,26 @@ public: entry_t *m_new = new entry_t[new_size]; entry_t *pd = m_new; - for (entry_t *ps = m_list; ps <= m_ptr; ps++, pd++) + for (entry_t *ps = m_list; ps < m_list + cnt; ps++, pd++) *pd = *ps; delete[] m_list; m_list = m_new; - m_ptr = m_list + cnt - 1; + m_count = cnt; m_num_elements = new_size; } ATTR_HOT inline void remove(const _ListClass elem) { - for (entry_t *i = m_list; i <= m_ptr; i++) + for (int i =0; i < m_count; i++) { - if (i->object() == elem) + if (m_list[i].object() == elem) { - while (i < m_ptr) + m_count --; + while (i < m_count) { - *i = *(i+1); + m_list[i] = m_list[i+1]; i++; } - m_ptr--; return; } } @@ -103,7 +104,7 @@ public: ATTR_HOT inline bool contains(const _ListClass elem) const { - for (entry_t *i = m_list; i <= m_ptr; i++) + for (entry_t *i = m_list; i < m_list + m_count; i++) { if (i->object() == elem) return true; @@ -111,17 +112,17 @@ public: 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 ); } - ATTR_HOT inline entry_t *last() const { return m_ptr; } - ATTR_HOT inline int count() const { return m_ptr - m_list + 1; } - ATTR_HOT inline bool empty() const { return (m_ptr < m_list); } - ATTR_HOT inline void reset() { m_ptr = m_list - 1; } + ATTR_HOT inline entry_t *first() const { return ((m_count > 0) ? &m_list[0] : NULL ); } + ATTR_HOT inline entry_t *next(entry_t *lc) const { return ((lc < last()) ? lc + 1 : NULL ); } + ATTR_HOT inline entry_t *last() const { return &m_list[m_count -1]; } + ATTR_HOT inline int count() const { return m_count; } + ATTR_HOT inline bool empty() const { return (m_count == 0); } + ATTR_HOT inline void reset() { m_count = 0; } ATTR_HOT inline int capacity() const { return m_num_elements; } ATTR_COLD void reset_and_free() { - for (entry_t *i = m_list; i <= m_ptr; i++) + for (entry_t *i = m_list; i < m_list + m_count; i++) { delete i->object(); } @@ -132,7 +133,7 @@ public: ATTR_HOT inline const _ListClass& operator[](const int & index) const { return m_list[index].m_obj; } private: - entry_t * m_ptr; + int m_count; entry_t * m_list; int m_num_elements; //_ListClass m_list[_NumElements]; |