summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/solver/nld_solver.h
blob: 06a98d063c6de9ed2e8c0cd3cffd14a0f268414f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
 * nld_solver.h
 *
 */

#ifndef NLD_SOLVER_H_
#define NLD_SOLVER_H_

#include "nl_setup.h"
#include "nl_base.h"

//#define ATTR_ALIGNED(N) __attribute__((aligned(N)))
#define ATTR_ALIGNED(N) ATTR_ALIGN

// ----------------------------------------------------------------------------------------
// Macros
// ----------------------------------------------------------------------------------------

#define SOLVER(_name, _freq)                                                 \
		NET_REGISTER_DEV(SOLVER, _name)                                      \
		PARAM(_name.FREQ, _freq)

// ----------------------------------------------------------------------------------------
// solver
// ----------------------------------------------------------------------------------------

NETLIB_NAMESPACE_DEVICES_START()

class NETLIB_NAME(solver);

/* FIXME: these should become proper devices */

struct solver_parameters_t
{
	int m_pivot;
	nl_double m_accuracy;
	nl_double m_lte;
	nl_double m_min_timestep;
	nl_double m_max_timestep;
	nl_double m_sor;
	bool m_dynamic;
	int m_gs_loops;
	int m_nr_loops;
	netlist_time m_nt_sync_delay;
	bool m_log_stats;
};


class terms_t
{
	P_PREVENT_COPYING(terms_t)

	public:
	ATTR_COLD terms_t() : m_railstart(0)
	{}

	ATTR_COLD void clear()
	{
		m_term.clear();
		m_net_other.clear();
		m_gt.clear();
		m_go.clear();
		m_Idr.clear();
		m_other_curanalog.clear();
	}

	ATTR_COLD void add(terminal_t *term, int net_other, bool sorted);

	ATTR_HOT inline unsigned count() { return m_term.size(); }

	ATTR_HOT inline terminal_t **terms() { return m_term.data(); }
	ATTR_HOT inline int *net_other() { return m_net_other.data(); }
	ATTR_HOT inline nl_double *gt() { return m_gt.data(); }
	ATTR_HOT inline nl_double *go() { return m_go.data(); }
	ATTR_HOT inline nl_double *Idr() { return m_Idr.data(); }
	ATTR_HOT inline nl_double **other_curanalog() { return m_other_curanalog.data(); }

	ATTR_COLD void set_pointers();

	unsigned m_railstart;

	pvector_t<unsigned> m_nz;   /* all non zero for multiplication */
	pvector_t<unsigned> m_nzrd; /* non zero right of the diagonal for elimination */
	pvector_t<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */
private:
	pvector_t<terminal_t *> m_term;
	pvector_t<int> m_net_other;
	pvector_t<nl_double> m_go;
	pvector_t<nl_double> m_gt;
	pvector_t<nl_double> m_Idr;
	pvector_t<nl_double *> m_other_curanalog;
};

class matrix_solver_t : public device_t
{
public:
	typedef pvector_t<matrix_solver_t *> list_t;
	typedef core_device_t::list_t dev_list_t;

	enum eSolverType
	{
		GAUSSIAN_ELIMINATION,
		GAUSS_SEIDEL
	};

	ATTR_COLD matrix_solver_t(const eSolverType type, const solver_parameters_t *params);
	virtual ~matrix_solver_t();

	virtual void vsetup(analog_net_t::list_t &nets) = 0;

	template<class C>
	void solve_base(C *p);

	ATTR_HOT nl_double solve();

	ATTR_HOT inline bool is_dynamic() { return m_dynamic_devices.size() > 0; }
	ATTR_HOT inline bool is_timestep() { return m_step_devices.size() > 0; }

	ATTR_HOT void update_forced();
	ATTR_HOT inline void update_after(const netlist_time after)
	{
		m_Q_sync.net().reschedule_in_queue(after);
	}

	/* netdevice functions */
	ATTR_HOT  virtual void update() override;
	virtual void start() override;
	virtual void reset() override;

	ATTR_COLD int get_net_idx(net_t *net);

	inline eSolverType type() const { return m_type; }
	plog_base<NL_DEBUG> &log() { return netlist().log(); }

	virtual void log_stats();

protected:

	ATTR_COLD void setup(analog_net_t::list_t &nets);
	ATTR_HOT void update_dynamic();

	// should return next time step
	ATTR_HOT virtual nl_double vsolve() = 0;

	virtual void  add_term(int net_idx, terminal_t *term) = 0;

	pvector_t<analog_net_t *> m_nets;
	pvector_t<analog_output_t *> m_inps;

	int m_stat_calculations;
	int m_stat_newton_raphson;
	int m_stat_vsolver_calls;
	int m_iterative_fail;
	int m_iterative_total;

	const solver_parameters_t &m_params;

	ATTR_HOT inline nl_double current_timestep() { return m_cur_ts; }
private:

	netlist_time m_last_step;
	nl_double m_cur_ts;
	dev_list_t m_step_devices;
	dev_list_t m_dynamic_devices;

	logic_input_t m_fb_sync;
	logic_output_t m_Q_sync;

	ATTR_HOT void step(const netlist_time delta);

	ATTR_HOT void update_inputs();

	const eSolverType m_type;
};



class NETLIB_NAME(solver) : public device_t
{
public:
	NETLIB_NAME(solver)()
	: device_t()    { }

	virtual ~NETLIB_NAME(solver)();

	ATTR_COLD void post_start();
	ATTR_COLD void stop() override;

	ATTR_HOT inline nl_double gmin() { return m_gmin.Value(); }

protected:
	ATTR_HOT void update() override;
	ATTR_HOT void start() override;
	ATTR_HOT void reset() override;
	ATTR_HOT void update_param() override;

	logic_input_t m_fb_step;
	logic_output_t m_Q_step;

	param_logic_t  m_pivot;
	param_double_t m_freq;
	param_double_t m_sync_delay;
	param_double_t m_accuracy;
	param_double_t m_gmin;
	param_double_t m_lte;
	param_double_t m_sor;
	param_logic_t  m_dynamic;
	param_double_t m_min_timestep;

	param_str_t m_iterative_solver;
	param_int_t m_nr_loops;
	param_int_t m_gs_loops;
	param_int_t m_gs_threshold;
	param_int_t m_parallel;

	param_logic_t  m_log_stats;

	matrix_solver_t::list_t m_mat_solvers;
private:

	solver_parameters_t m_params;

	template <int m_N, int _storage_N>
	matrix_solver_t *create_solver(int size, bool use_specific);
};

NETLIB_NAMESPACE_DEVICES_END()

#endif /* NLD_SOLVER_H_ */