Previous 199869 Revisions Next

r26895 Thursday 2nd January, 2014 at 14:40:36 UTC by Couriersud
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
[src/emu/machine]netlist.c
[src/emu/netlist]nl_base.c nl_base.h nl_lists.h
[src/emu/netlist/devices]nld_7474.c nld_solver.c nld_solver.h nld_twoterm.c

trunk/src/emu/machine/netlist.c
r26894r26895
178178{
179179   LOG_DEV_CALLS(("device_start %s\n", tag()));
180180
181   printf("clock is %d\n", clock());
181   //printf("clock is %d\n", clock());
182182
183183   m_netlist = global_alloc_clear(netlist_mame_t(*this));
184184   m_setup = global_alloc_clear(netlist_setup_t(*m_netlist));
trunk/src/emu/netlist/nl_lists.h
r26894r26895
2020{
2121public:
2222
23   struct entry_t {
23   struct entry_t
24   {
25       friend class netlist_list_t;
26   public:
2427      // keep compatibility with tagmap
25      _ListClass object() { return m_obj; }
26
28      ATTR_HOT inline _ListClass object() { return m_obj; }
29   private:
2730      _ListClass m_obj;
2831   };
2932
r26894r26895
3134   {
3235      m_num_elements = numElements;
3336      m_list = new entry_t[m_num_elements];
34      m_ptr = m_list;
35      m_ptr--;
37        m_count = 0;
3638   }
3739
3840   ATTR_COLD netlist_list_t(const netlist_list_t &rhs)
3941   {
4042       m_num_elements = rhs.capacity();
4143      m_list = new entry_t[m_num_elements];
42      m_ptr = m_list;
43      m_ptr--;
44      m_count = 0;
4445      for (int i=0; i<rhs.count(); i++)
4546      {
4647         this->add(rhs[i]);
r26894r26895
6465
6566   ATTR_HOT inline void add(const _ListClass elem)
6667   {
67      if (m_ptr-m_list >= m_num_elements - 1)
68      if (m_count >= m_num_elements)
6869         resize(m_num_elements * 2);
6970
70      (++m_ptr)->m_obj = elem;
71      m_list[m_count++].m_obj = elem;
7172   }
7273
7374   ATTR_HOT inline void resize(const int new_size)
r26894r26895
7677      entry_t *m_new = new entry_t[new_size];
7778      entry_t *pd = m_new;
7879
79      for (entry_t *ps = m_list; ps <= m_ptr; ps++, pd++)
80      for (entry_t *ps = m_list; ps < m_list + cnt; ps++, pd++)
8081         *pd = *ps;
8182      delete[] m_list;
8283      m_list = m_new;
83      m_ptr = m_list + cnt - 1;
84      m_count = cnt;
8485      m_num_elements = new_size;
8586   }
8687
8788   ATTR_HOT inline void remove(const _ListClass elem)
8889   {
89      for (entry_t *i = m_list; i <= m_ptr; i++)
90      for (int i =0; i < m_count; i++)
9091      {
91         if (i->object() == elem)
92         if (m_list[i].object() == elem)
9293         {
93            while (i < m_ptr)
94             m_count --;
95            while (i < m_count)
9496            {
95               *i = *(i+1);
97               m_list[i] = m_list[i+1];
9698               i++;
9799            }
98            m_ptr--;
99100            return;
100101         }
101102      }
r26894r26895
103104
104105   ATTR_HOT inline bool contains(const _ListClass elem) const
105106   {
106      for (entry_t *i = m_list; i <= m_ptr; i++)
107      for (entry_t *i = m_list; i < m_list + m_count; i++)
107108      {
108109         if (i->object() == elem)
109110            return true;
r26894r26895
111112      return false;
112113   }
113114
114   ATTR_HOT inline entry_t *first() const { return (m_ptr >= m_list ? &m_list[0] : NULL ); }
115   ATTR_HOT inline entry_t *next(entry_t *lc) const { return (lc < last() ? lc + 1 : NULL ); }
116   ATTR_HOT inline entry_t *last() const { return m_ptr; }
117   ATTR_HOT inline int count() const { return m_ptr - m_list + 1; }
118   ATTR_HOT inline bool empty() const { return (m_ptr < m_list); }
119   ATTR_HOT inline void reset() { m_ptr = m_list - 1; }
115   ATTR_HOT inline entry_t *first() const { return ((m_count > 0) ? &m_list[0] : NULL ); }
116   ATTR_HOT inline entry_t *next(entry_t *lc) const { return ((lc < last()) ? lc + 1 : NULL ); }
117   ATTR_HOT inline entry_t *last() const { return &m_list[m_count -1]; }
118   ATTR_HOT inline int count() const { return m_count; }
119   ATTR_HOT inline bool empty() const { return (m_count == 0); }
120   ATTR_HOT inline void reset() { m_count = 0; }
120121    ATTR_HOT inline int capacity() const { return m_num_elements; }
121122
122123   ATTR_COLD void reset_and_free()
123124   {
124      for (entry_t *i = m_list; i <= m_ptr; i++)
125      for (entry_t *i = m_list; i < m_list + m_count; i++)
125126      {
126127         delete i->object();
127128      }
r26894r26895
132133   ATTR_HOT inline const _ListClass& operator[](const int & index) const { return m_list[index].m_obj; }
133134
134135private:
135   entry_t * m_ptr;
136   int m_count;
136137   entry_t * m_list;
137138   int m_num_elements;
138139   //_ListClass m_list[_NumElements];
trunk/src/emu/netlist/devices/nld_twoterm.c
r26894r26895
207207   setup().connect(m_RB.m_N, m_EV);
208208
209209   save(NAME(m_state_on));
210
211    m_RB.set(NETLIST_GMIN, 0.0, 0.0);
212    m_RC.set(NETLIST_GMIN, 0.0, 0.0);
213
214    m_state_on = 0;
215
210216}
211217
212218NETLIB_UPDATE(Q)
trunk/src/emu/netlist/devices/nld_7474.c
r26894r26895
4747{
4848   register_sub(sub, "sub");
4949
50   register_subalias("CLK",  sub.m_clk);
51   register_input("D",    m_D);
52   register_input("CLRQ", m_clrQ);
53   register_input("PREQ", m_preQ);
50   register_subalias("CLK",    sub.m_clk);
51   register_input("D",         m_D);
52   register_input("CLRQ",      m_clrQ);
53   register_input("PREQ",      m_preQ);
5454
55   register_subalias("Q",   sub.m_Q);
56   register_subalias("QQ",  sub.m_QQ);
55   register_subalias("Q",      sub.m_Q);
56   register_subalias("QQ",     sub.m_QQ);
5757
5858}
5959
r26894r26895
6464   register_output("Q",   m_Q);
6565   register_output("QQ",  m_QQ);
6666
67   m_nextD = 0;
6768   m_Q.initial(1);
6869   m_QQ.initial(0);
70
71   save(NAME(m_nextD));
6972}
trunk/src/emu/netlist/devices/nld_solver.c
r26894r26895
4747               NL_VERBOSE_OUT(("Added terminal\n"));
4848               break;
4949            case netlist_terminal_t::INPUT:
50               if (!m_inps.contains(&p->netdev()))
51                  m_inps.add(&p->netdev());
50               if (!m_inps.contains(p))
51                  m_inps.add(p);
5252               NL_VERBOSE_OUT(("Added input\n"));
5353               break;
5454            default:
r26894r26895
6868
6969ATTR_HOT inline void netlist_matrix_solver_t::update_inputs()
7070{
71   for (dev_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p))
71   for (netlist_core_terminal_t::list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p))
7272   {
73        p->object()->update_dev();
73       if (p->object()->net().m_last.Analog != p->object()->net().m_cur.Analog)
74       {
75           p->object()->netdev().update_dev();
76       }
7477   }
78    for (netlist_core_terminal_t::list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p))
79    {
80        p->object()->net().m_last.Analog = p->object()->net().m_cur.Analog;
81    }
82
7583}
7684
7785
7886ATTR_HOT inline bool netlist_matrix_solver_t::solve()
7987{
80   bool resched = false;
88   bool resched;
89   // FIXME: There may be situations where we *could* need more than one iteration for dynamic elements
8190
82   /* update all non-linear devices  */
83   for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p))
84      switch (p->object()->family())
85      {
86         case netlist_device_t::DIODE:
87            static_cast<NETLIB_NAME(D) *>(p->object())->update_terminals();
88            break;
89         default:
90            p->object()->update_terminals();
91            break;
92      }
91    int  resched_cnt = (is_dynamic() ? /* 0 */ 1 : 1);
92    ATTR_UNUSED netlist_net_t *last_resched_net = NULL;
9393
94   for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
95   {
96      netlist_net_t *net = pn->object();
94    do {
95        resched = false;
96        /* update all non-linear devices  */
97        for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p))
98            switch (p->object()->family())
99            {
100                case netlist_device_t::DIODE:
101                    static_cast<NETLIB_NAME(D) *>(p->object())->update_terminals();
102                    break;
103                default:
104                    p->object()->update_terminals();
105                    break;
106            }
97107
98      double gtot = 0;
99      double gabs = 0;
100      double iIdr = 0;
101      const netlist_net_t::terminal_list_t &terms = net->m_terms;
102#if 1
103      switch (terms.count())
104      {
105         case 1:
106            {
107               const netlist_terminal_t *pt = terms.first()->object();
108               gtot = pt->m_gt;
109               gabs = fabs(pt->m_go);
110               iIdr = pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
111            }
112            break;
113         case 2:
114            {
115               const netlist_terminal_t *pt1 = terms[0];
116               const netlist_terminal_t *pt2 = terms[1];
117               gtot = pt1->m_gt + pt2->m_gt;
118               gabs = fabs(pt1->m_go) + fabs(pt2->m_go);
119               iIdr = pt1->m_Idr + pt1->m_go * pt1->m_otherterm->net().Q_Analog()
120                     + pt2->m_Idr + pt2->m_go * pt2->m_otherterm->net().Q_Analog();
121            }
122            break;
123         case 3:
124            {
125               const netlist_terminal_t *pt1 = terms[0];
126               const netlist_terminal_t *pt2 = terms[1];
127               const netlist_terminal_t *pt3 = terms[2];
128               gtot = pt1->m_gt + pt2->m_gt + pt3->m_gt;
129               gabs = fabs(pt1->m_go) + fabs(pt2->m_go) + fabs(pt3->m_go);
130               iIdr = pt1->m_Idr + pt1->m_go * pt1->m_otherterm->net().Q_Analog()
131                     + pt2->m_Idr + pt2->m_go * pt2->m_otherterm->net().Q_Analog()
132                     + pt3->m_Idr + pt3->m_go * pt3->m_otherterm->net().Q_Analog();
133            }
134            break;
135         default:
136            for (netlist_net_t::terminal_list_t::entry_t *e = terms.first(); e != NULL; e = terms.next(e))
137            {
138               netlist_terminal_t *pt = e->object();
139               gtot += pt->m_gt;
140               gabs += fabs(pt->m_go);
141               iIdr += pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
142            }
143            break;
144      }
145#else
146      for (netlist_net_t::terminal_list_t::entry_t *e = terms.first(); e != NULL; e = terms.next(e))
147      {
148         netlist_terminal_t *pt = e->object();
149         gtot += pt->m_gt;
150         gabs += fabs(pt->m_go);
151         iIdr += pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
152      }
153#endif
154      double new_val;
155      gabs *= m_convergence_factor;
156      if (gabs > gtot)
157         new_val = (net->m_cur.Analog * gabs + iIdr) / (gtot + gabs);
158      else
159         new_val = iIdr / gtot;
108        for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
109        {
110            netlist_net_t *net = pn->object();
111            const netlist_net_t::terminal_list_t &terms = net->m_terms;
160112
161      if (fabs(new_val - net->m_cur.Analog) > m_accuracy)
162         resched = true;
163      net->m_cur.Analog = net->m_new.Analog = new_val;
113            double gtot = 0;
114            double gabs = 0;
115            double iIdr = 0;
116            double new_val;
164117
165      NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons));
166      //NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
167   }
118            for (int i = 0; i < terms.count(); i++)
119            {
120                gtot += terms[i]->m_gt;
121                gabs += fabs(terms[i]->m_go);
122                iIdr += terms[i]->m_Idr + terms[i]->m_go * terms[i]->m_otherterm->net().Q_Analog();
123            }
124
125            gabs *= m_convergence_factor;
126            if (gabs > gtot)
127                new_val = (net->m_cur.Analog * gabs + iIdr) / (gtot + gabs);
128            else
129                new_val = iIdr / gtot;
130
131            if (fabs(new_val - net->m_cur.Analog) > m_accuracy)
132            {
133                resched = true;
134                last_resched_net = net;
135            }
136
137            net->m_cur.Analog = net->m_new.Analog = new_val;
138
139            NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons));
140            //NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
141        }
142        resched_cnt++;
143    } while ((resched && (resched_cnt < m_resched_loops)) || (resched_cnt <= 1));
144
145    if (!resched)
146        update_inputs();
147    //if (resched)
148        //printf("Resched on net %s first term %s\n", last_resched_net->name().cstr(), last_resched_net->m_terms[0]->name().cstr());
149
168150   return resched;
169151}
170152
r26894r26895
174156
175157typedef netlist_net_t::list_t  *net_groups_t;
176158
177static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net)
159ATTR_COLD static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net)
178160{
179161   if (net->isRailNet())
180162      return true;
r26894r26895
186168   return false;
187169}
188170
189static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net)
171ATTR_COLD static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net)
190172{
191173   /* add the net */
192174   if (net->m_head == NULL)
r26894r26895
219201
220202   register_param("ACCURACY", m_accuracy, 1e-3);
221203   register_param("CONVERG", m_convergence, 0.3);
204    register_param("RESCHED_LOOPS", m_resched_loops, 15);
222205
223206   // internal staff
224207
r26894r26895
251234
252235}
253236
254NETLIB_FUNC_VOID(solver, post_start, ())
255{
256   netlist_net_t::list_t groups[100];
257   int cur_group = -1;
258
259   SOLVER_VERBOSE_OUT(("Scanning net groups ...\n"));
260   // determine net groups
261   for (netlist_net_t::list_t::entry_t *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
262   {
263      if (!already_processed(groups, cur_group, pn->object()))
264      {
265         cur_group++;
266         process_net(groups, cur_group, pn->object());
267      }
268   }
269
270   // setup the solvers
271   SOLVER_VERBOSE_OUT(("Found %d net groups in %d nets\n", cur_group + 1, m_nets.count()));
272   for (int i = 0; i <= cur_group; i++)
273   {
274      netlist_matrix_solver_t *ms = new netlist_matrix_solver_t();
275      ms->m_accuracy = m_accuracy.Value();
276      ms->m_convergence_factor = m_convergence.Value();
277      ms->setup(groups[i], *this);
278      m_mat_solvers.add(ms);
279      SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), groups[i].first()->object()->m_head->name().cstr()));
280      SOLVER_VERBOSE_OUT(("  has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic"));
281   }
282
283}
284
285237NETLIB_UPDATE(solver)
286238{
287   //m_Q.setToNoCheck(!m_Q.new_Q(), m_inc  );
288   //OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc  );
289
290   bool resched = false;
291   int  resched_cnt = 0;
292239   netlist_time now = netlist().time();
293240   netlist_time delta = now - m_last_step;
294241
r26894r26895
305252   bool global_resched = false;
306253   for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
307254   {
308      resched_cnt = (e->object()->is_dynamic() ? 0 : 1);
309      do {
310         resched = e->object()->solve();
311         resched_cnt++;
312      } while ((resched && (resched_cnt < 5)) || (resched_cnt <= 1));
313      global_resched = global_resched || resched;
255       global_resched = global_resched || e->object()->solve();
314256   }
315   //if (global_resched)
316   //    printf("rescheduled\n");
317257   if (global_resched)
318258   {
319259      schedule();
320260   }
321261   else
322262   {
323      /* update all inputs connected */
324      for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
325      {
326         e->object()->update_inputs();
327      }
328
329263      /* step circuit */
330264      if (!m_Q_step.net().is_queued())
331265         m_Q_step.net().push_to_queue(m_inc);
332266   }
333267
334268}
269
270ATTR_COLD void NETLIB_NAME(solver)::post_start()
271{
272    netlist_net_t::list_t groups[100];
273    int cur_group = -1;
274
275    SOLVER_VERBOSE_OUT(("Scanning net groups ...\n"));
276    // determine net groups
277    for (netlist_net_t::list_t::entry_t *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
278    {
279        if (!already_processed(groups, cur_group, pn->object()))
280        {
281            cur_group++;
282            process_net(groups, cur_group, pn->object());
283        }
284    }
285
286    // setup the solvers
287    SOLVER_VERBOSE_OUT(("Found %d net groups in %d nets\n", cur_group + 1, netlist().m_nets.count()));
288    for (int i = 0; i <= cur_group; i++)
289    {
290        netlist_matrix_solver_t *ms = new netlist_matrix_solver_t();
291        ms->m_accuracy = m_accuracy.Value();
292        ms->m_convergence_factor = m_convergence.Value();
293        ms->m_resched_loops = m_resched_loops.Value();
294        ms->setup(groups[i], *this);
295        m_mat_solvers.add(ms);
296        SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), groups[i].first()->object()->m_head->name().cstr()));
297        SOLVER_VERBOSE_OUT(("       has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic"));
298        SOLVER_VERBOSE_OUT(("       has %s elements\n", ms->is_timestep() ? "timestep" : "no timestep"));
299    }
300
301}
trunk/src/emu/netlist/devices/nld_solver.h
r26894r26895
3636   ATTR_HOT void update_inputs();
3737
3838   ATTR_HOT inline bool is_dynamic() { return m_dynamic.count() > 0; }
39    ATTR_HOT inline bool is_timestep() { return m_steps.count() > 0; }
3940
40   inline const NETLIB_NAME(solver) &owner() const;
41   ATTR_HOT inline const NETLIB_NAME(solver) &owner() const;
4142
4243   double m_accuracy;
4344   double m_convergence_factor;
45   int m_resched_loops;
4446
4547private:
4648   netlist_net_t::list_t m_nets;
4749   dev_list_t m_dynamic;
48   dev_list_t m_inps;
50   netlist_core_terminal_t::list_t m_inps;
4951   dev_list_t m_steps;
5052
5153   NETLIB_NAME(solver) *m_owner;
r26894r26895
6466      netlist_param_double_t m_sync_delay;
6567      netlist_param_double_t m_accuracy;
6668      netlist_param_double_t m_convergence;
69        netlist_param_int_t m_resched_loops;
6770
6871      netlist_time m_inc;
6972      netlist_time m_last_step;
r26894r26895
7275      netlist_matrix_solver_t::list_t m_mat_solvers;
7376public:
7477
75      ~NETLIB_NAME(solver)();
78      ATTR_COLD ~NETLIB_NAME(solver)();
7679
7780      ATTR_HOT inline void schedule();
7881
7982      ATTR_COLD void post_start();
83      ATTR_COLD void reset()
84      {
85          m_last_step = netlist_time::zero;
86      }
8087);
8188
82inline void NETLIB_NAME(solver)::schedule()
89ATTR_HOT inline void NETLIB_NAME(solver)::schedule()
8390{
8491   // FIXME: time should be parameter;
8592   if (!m_Q_sync.net().is_queued())
8693      m_Q_sync.net().push_to_queue(m_nt_sync_delay);
8794}
8895
89inline const NETLIB_NAME(solver) &netlist_matrix_solver_t::owner() const
96ATTR_HOT inline const NETLIB_NAME(solver) &netlist_matrix_solver_t::owner() const
9097{
9198   return *m_owner;
9299}
trunk/src/emu/netlist/nl_base.c
r26894r26895
55
66#include "nl_base.h"
77#include "devices/nld_system.h"
8#include "devices/nld_solver.h"
89#include "pstring.h"
910#include "nl_util.h"
1011
r26894r26895
170171   m_queue.clear();
171172   if (m_mainclock != NULL)
172173      m_mainclock->m_Q.net().set_time(netlist_time::zero);
174    if (m_solver != NULL)
175        m_solver->reset();
173176
174177   // FIXME: some const devices rely on this
175178   /* make sure params are set now .. */
r26894r26895
429432   , m_in_queue(2)
430433   , m_railterminal(NULL)
431434{
435    m_last.Analog = -123456789.0; // set to something we will never hit.
436    m_new.Analog = 0.0;
437    m_cur.Analog = 0.0;
432438};
433439
434440ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname)
trunk/src/emu/netlist/nl_base.h
r26894r26895
332332   NETLIST_PREVENT_COPYING(netlist_core_terminal_t)
333333public:
334334
335    typedef netlist_list_t<netlist_core_terminal_t *> list_t;
336
335337   /* needed here ... */
336338
337339   enum state_e {
r26894r26895
10931095         OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1));
10941096      else if (m_I.Q_Analog() < m_I.m_low_thresh_V)
10951097         OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1));
1096      else
1097         OUTLOGIC(m_Q, m_Q.net().last_Q(), NLTIME_FROM_NS(1));
1098      //else
1099      //   OUTLOGIC(m_Q, m_Q.net().last_Q(), NLTIME_FROM_NS(1));
10981100   }
10991101
11001102};

Previous 199869 Revisions Next


© 1997-2024 The MAME Team