Previous 199869 Revisions Next

r26547 Sunday 8th December, 2013 at 18:20:12 UTC by Couriersud
Netlist: First steps at taking advantage of sparse matrix properties.
The code now identifies net groups. A net group contains nets which depend on each other. Purely conductive nets can going forward be updated solely if one of the rail nets they are connected to changes.
[src/emu/netlist]nl_base.h
[src/emu/netlist/devices]nld_system.c nld_system.h

trunk/src/emu/netlist/nl_base.h
r26546r26547
117117 *
118118 *  These equations represent a linear Matrix equation (with more math).
119119 *
120 *  In the context of this exercise, in a first step, we will not solve it. Instead,
121 *  we calculate the net voltage V(l) by using a mirror of the above device on each terminal.
120 *  In the end the solution of the analog subsystem boils down to
122121 *
122 *  (G - D) * V = I
123 *
124 *  with G being the conductance matrix, D a diagonal matrix with the total conductance
125 *  on the diagonal elements, V the net voltage vector and I the current vector.
126 *
127 *  By using solely two terminal devices, we can simplify the whole calculation
128 *  significantly. A BJT now is a four terminal device with two terminals being
129 *  connected internally.
130 *
131 *  The system is solved using an iterative approach:
132 *
133 *  G * V - D * V = I
134 *
135 *  assuming V=Vn=Vo
136 *
137 *  Vn = D-1 * (I - G * Vo)
138 *
123139 *  Each terminal thus has three properties:
124140 *
125141 *  a) Resistance
126142 *  b) Voltage source
127143 *  c) Current source/sink
128144 *
129 *  Going forward, approach can be extended to use a linear equation solver.
145 *  Going forward, the approach can be extended e.g. to use a linear equation solver
130146 *
131147 *  The formal representation of the circuit will stay the same, thus scales.
132148 *
r26546r26547
225241class netlist_param_t;
226242class netlist_setup_t;
227243class netlist_base_t;
244class netlist_matrix_solver_t;
228245
229246
230247// ----------------------------------------------------------------------------------------
r26546r26547
438455{
439456public:
440457
458    typedef netlist_list_t<netlist_net_t *> list_t;
459
441460    friend class NETLIB_NAME(mainclock);
442461    friend class NETLIB_NAME(solver);
462    friend class netlist_matrix_solver_t;
443463    friend class netlist_output_t;
444464    friend class netlist_input_t;
445465    friend class netlist_logic_output_t;
r26546r26547
493513    // m_terms is only used by analog subsystem
494514    typedef netlist_list_t<netlist_terminal_t *> terminal_list_t;
495515    terminal_list_t m_terms;
516    netlist_matrix_solver_t *m_solver;
496517
518    netlist_core_terminal_t *m_head;
519
497520protected:
498521
499522    /* prohibit use in device functions
r26546r26547
510533    hybrid_t m_cur;
511534    hybrid_t m_new;
512535
513    netlist_core_terminal_t *m_head;
514536    UINT32 m_num_cons;
515537
516538private:
r26546r26547
717739{
718740public:
719741
742    typedef netlist_list_t<netlist_core_device_t *> list_t;
743
720744    ATTR_COLD netlist_core_device_t();
721745    ATTR_COLD netlist_core_device_t(const family_t afamily);
722746
trunk/src/emu/netlist/devices/nld_system.h
r26546r26547
7979// solver
8080// ----------------------------------------------------------------------------------------
8181
82struct netlist_matrix_solver_t
83{
84    typedef netlist_list_t<netlist_matrix_solver_t *> list_t;
85    typedef netlist_core_device_t::list_t dev_list_t;
86    ATTR_COLD void setup(netlist_net_t::list_t &nets);
87
88    // return true if a reschedule is needed ...
89    ATTR_HOT bool solve();
90    ATTR_HOT void step(const netlist_time delta);
91    ATTR_HOT void update_inputs();
92
93    double m_accuracy;
94
95private:
96    netlist_net_t::list_t m_nets;
97    dev_list_t m_dynamic;
98    dev_list_t m_inps;
99    dev_list_t m_steps;
100};
101
82102NETLIB_DEVICE_WITH_PARAMS(solver,
83        typedef netlist_list_t<netlist_net_t *>      net_list_t;
84        typedef netlist_list_t<netlist_core_device_t *>      dev_list_t;
103        typedef netlist_core_device_t::list_t dev_list_t;
85104
86105        netlist_ttl_input_t m_fb_sync;
87106        netlist_ttl_output_t m_Q_sync;
r26546r26547
97116        netlist_time m_last_step;
98117        netlist_time m_nt_sync_delay;
99118
100        dev_list_t m_dynamic;
101        dev_list_t m_inps;
102        dev_list_t m_steps;
103
119        netlist_matrix_solver_t::list_t m_mat_solvers;
104120public:
105121
106122        ~NETLIB_NAME(solver)();
107123
108        net_list_t m_nets;
124        netlist_net_t::list_t m_nets;
109125
110126        ATTR_HOT inline void schedule();
111127
trunk/src/emu/netlist/devices/nld_system.c
r26546r26547
7878}
7979
8080// ----------------------------------------------------------------------------------------
81// netlist_matrix_solver
82// ----------------------------------------------------------------------------------------
83
84
85ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets)
86{
87    for (netlist_net_t::list_t::entry_t *pn = nets.first(); pn != NULL; pn = nets.next(pn))
88    {
89        NL_VERBOSE_OUT(("setting up net\n"));
90
91        m_nets.add(pn->object());
92        pn->object()->m_solver = this;
93
94        for (netlist_core_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
95        {
96            switch (p->type())
97            {
98                case netlist_terminal_t::TERMINAL:
99                    switch (p->netdev().family())
100                    {
101                        case netlist_device_t::CAPACITOR:
102                            if (!m_steps.contains(&p->netdev()))
103                                m_steps.add(&p->netdev());
104                            break;
105                        case netlist_device_t::DIODE:
106                        case netlist_device_t::BJT_SWITCH:
107                            if (!m_dynamic.contains(&p->netdev()))
108                                m_dynamic.add(&p->netdev());
109                            break;
110                        default:
111                            break;
112                    }
113                    pn->object()->m_terms.add(static_cast<netlist_terminal_t *>(p));
114                    NL_VERBOSE_OUT(("Added terminal\n"));
115                    break;
116                case netlist_terminal_t::INPUT:
117                    if (!m_inps.contains(&p->netdev()))
118                        m_inps.add(&p->netdev());
119                    NL_VERBOSE_OUT(("Added input\n"));
120                    break;
121                default:
122                    fatalerror("unhandled element found\n");
123                    break;
124            }
125        }
126    }
127}
128
129ATTR_HOT inline void netlist_matrix_solver_t::step(const netlist_time delta)
130{
131    const double dd = delta.as_double();
132    for (dev_list_t::entry_t *p = m_steps.first(); p != NULL; p = m_steps.next(p))
133        p->object()->step_time(dd);
134}
135
136ATTR_HOT inline void netlist_matrix_solver_t::update_inputs()
137{
138    for (dev_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p))
139        p->object()->update_dev();
140}
141
142
143ATTR_HOT inline bool netlist_matrix_solver_t::solve()
144{
145    bool resched = false;
146
147    /* update all non-linear devices  */
148    for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p))
149        p->object()->update_terminals();
150
151    for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
152    {
153        netlist_net_t *net = pn->object();
154
155        double gtot = 0;
156        double iIdr = 0;
157
158        for (netlist_net_t::terminal_list_t::entry_t *e = net->m_terms.first(); e != NULL; e = net->m_terms.next(e))
159        {
160            netlist_terminal_t *pt = e->object();
161            gtot += pt->m_g;
162            iIdr += pt->m_Idr + pt->m_g * pt->m_otherterm->net().Q_Analog();
163        }
164
165        double new_val = iIdr / gtot;
166        if (fabs(new_val - net->m_cur.Analog) > m_accuracy)
167            resched = true;
168        net->m_cur.Analog = net->m_new.Analog = new_val;
169
170        NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons));
171        NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
172    }
173    return resched;
174}
175
176// ----------------------------------------------------------------------------------------
81177// solver
82178// ----------------------------------------------------------------------------------------
83179
180typedef netlist_net_t::list_t  *net_groups_t;
181
182static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net)
183{
184    if (net->isRailNet())
185        return true;
186    for (int i = 0; i <= cur_group; i++)
187    {
188        if (groups[i].contains(net))
189            return true;
190    }
191    return false;
192}
193
194static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net)
195{
196    /* add the net */
197    groups[cur_group].add(net);
198    for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next)
199    {
200        if (p->isType(netlist_terminal_t::TERMINAL))
201        {
202            netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p);
203            netlist_net_t *nnet = &pt->m_otherterm->net();
204            if (!already_processed(groups, cur_group, nnet))
205                process_net(groups, cur_group, nnet);
206        }
207    }
208}
209
210
84211NETLIB_START(solver)
85212{
86213    register_output("Q_sync", m_Q_sync);
r26546r26547
108235
109236NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
110237{
111    net_list_t::entry_t *p = m_nets.first();
238    netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first();
239    while (e != NULL)
240    {
241        netlist_matrix_solver_t::list_t::entry_t *en = m_mat_solvers.next(e);
242        delete e->object();
243        e = en;
244    }
245
246    netlist_net_t::list_t::entry_t *p = m_nets.first();
112247    while (p != NULL)
113248    {
114        net_list_t::entry_t *pn = m_nets.next(p);
249        netlist_net_t::list_t::entry_t *pn = m_nets.next(p);
115250        delete p->object();
116251        p = pn;
117252    }
r26546r26547
119254
120255NETLIB_FUNC_VOID(solver, post_start, ())
121256{
257    netlist_net_t::list_t groups[100];
258    int cur_group = -1;
122259
123260    NL_VERBOSE_OUT(("post start solver ...\n"));
124    for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
261
262    // delete empty nets ...
263    for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
125264    {
126        NL_VERBOSE_OUT(("setting up net\n"));
127        for (netlist_core_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
128        {
129            switch (p->type())
130            {
131                case netlist_terminal_t::TERMINAL:
132                    switch (p->netdev().family())
133                    {
134                        case CAPACITOR:
135                            if (!m_steps.contains(&p->netdev()))
136                                m_steps.add(&p->netdev());
137                            break;
138                        case DIODE:
139                        case BJT_SWITCH:
140                            if (!m_dynamic.contains(&p->netdev()))
141                                m_dynamic.add(&p->netdev());
142                            break;
143                        default:
144                            break;
145                    }
146                    pn->object()->m_terms.add(static_cast<netlist_terminal_t *>(p));
147                    NL_VERBOSE_OUT(("Added terminal\n"));
148                    break;
149                case netlist_terminal_t::INPUT:
150                    if (!m_inps.contains(&p->netdev()))
151                        m_inps.add(&p->netdev());
152                    NL_VERBOSE_OUT(("Added input\n"));
153                    break;
154                default:
155                    fatalerror("unhandled element found\n");
156                    break;
157            }
158        }
159265        if (pn->object()->m_head == NULL)
160266        {
161267            NL_VERBOSE_OUT(("Deleting net ...\n"));
r26546r26547
165271            pn--;
166272        }
167273    }
274
275    printf("Scanning net groups ...\n");
276    // determine net groups
277    for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = 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    printf("Found %d net groups in %d nets\n", cur_group + 1, m_nets.count());
286    for (int i = 0; i <= cur_group; i++)
287    {
288        printf("%d ==> %d nets %s\n", i, groups[i].count(), groups[i].first()->object()->m_head->name().cstr());
289    }
290
291
292    // setup the solvers
293    for (int i = 0; i <= cur_group; i++)
294    {
295        netlist_matrix_solver_t *ms = new netlist_matrix_solver_t;
296        ms->m_accuracy = m_accuracy.Value();
297        ms->setup(groups[i]);
298        m_mat_solvers.add(ms);
299    }
300
168301}
169302
170303NETLIB_UPDATE(solver)
r26546r26547
182315        NL_VERBOSE_OUT(("Step!\n"));
183316        /* update all terminals for new time step */
184317        m_last_step = now;
185        for (dev_list_t::entry_t *p = m_steps.first(); p != NULL; p = m_steps.next(p))
186            p->object()->step_time(delta.as_double());
187    }
188    do {
189        /* update all non-linear devices  */
190        for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p))
191            p->object()->update_terminals();
192
193        resched = false;
194
195        for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
318        for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
196319        {
197            netlist_net_t *net = pn->object();
198
199            double gtot = 0;
200            double iIdr = 0;
201
202            for (netlist_net_t::terminal_list_t::entry_t *e = net->m_terms.first(); e != NULL; e = net->m_terms.next(e))
203            {
204                netlist_terminal_t *pt = e->object();
205                gtot += pt->m_g;
206                iIdr += pt->m_Idr + pt->m_g * pt->m_otherterm->net().Q_Analog();
207            }
208
209            double new_val = iIdr / gtot;
210            if (fabs(new_val - net->m_cur.Analog) > m_accuracy.Value())
211                resched = true;
212            resched_cnt++;
213            net->m_cur.Analog = net->m_new.Analog = new_val;
214
215            NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons));
216            NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
320            e->object()->step(delta);
217321        }
218    } while (resched && (resched_cnt < 5));
219    //if (resched_cnt >= 5)
220    //    printf("rescheduled\n");
221    if (resched)
322    }
323    bool global_resched = false;
324    for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
222325    {
326        resched_cnt = 0;
327        do {
328            resched = e->object()->solve();
329            resched_cnt++;
330        } while (resched && (resched_cnt < 5));
331        global_resched = global_resched || resched;
332    }
333    if (global_resched)
334        printf("rescheduled\n");
335    if (global_resched)
336    {
223337        schedule();
224338    }
225339    else
226340    {
227341        /* update all inputs connected */
228        for (dev_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p))
229            p->object()->update_dev();
342        for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
343        {
344            e->object()->update_inputs();
345        }
230346
231347        /* step circuit */
232348        if (!m_Q_step.net().is_queued())
233349            m_Q_step.net().push_to_queue(m_inc);
234350    }
235351
236        /* only inputs and terminals connected
237         * approach:
238         *
239         * a) Update voltage on this net
240         * b) Update devices
241         * c) If difference old - new > trigger schedule immediate update
242         *    of number of updates < max_update_count
243         *    else clear number of updates
244         */
245
246352}

Previous 199869 Revisions Next


© 1997-2024 The MAME Team