netlist: more code cleanup. (nw)

- avoid duplication in solver parameter code
- matrix sort type is now a parameter
This commit is contained in:
couriersud 2019-10-05 01:26:54 +02:00
parent 552d31e6c0
commit 2de7ed7ddc
15 changed files with 119 additions and 142 deletions

View File

@ -1015,12 +1015,27 @@ namespace netlist
public:
param_num_t(device_t &device, const pstring &name, const T val);
const T operator()() const NL_NOEXCEPT { return m_param; }
T operator()() const NL_NOEXCEPT { return m_param; }
operator T() const NL_NOEXCEPT { return m_param; }
void setTo(const T &param) { set(m_param, param); }
private:
T m_param;
};
template <typename T>
class param_enum_t final: public param_t
{
public:
param_enum_t(device_t &device, const pstring &name, const T val);
T operator()() const NL_NOEXCEPT { return T(m_param); }
operator T() const NL_NOEXCEPT { return T(m_param); }
void setTo(const T &param) { set(m_param, static_cast<int>(param)); }
private:
int m_param;
};
/* FIXME: these should go as well */
using param_logic_t = param_num_t<bool>;
using param_int_t = param_num_t<int>;
@ -1628,6 +1643,24 @@ namespace netlist
device.state().save(*this, m_param, this->name(), "m_param");
}
template <typename T>
param_enum_t<T>::param_enum_t(device_t &device, const pstring &name, const T val)
: param_t(device, name), m_param(val)
{
bool found = false;
pstring p = this->get_initial(device, &found);
if (found)
{
T temp(val);
bool ok = temp.set_from_string(p);
if (!ok)
device.state().log().fatal(MF_INVALID_ENUM_CONVERSION_1_2(name, p));
m_param = temp;
}
device.state().save(*this, m_param, this->name(), "m_param");
}
template <typename ST, std::size_t AW, std::size_t DW>
param_rom_t<ST, AW, DW>::param_rom_t(device_t &device, const pstring &name)
: param_data_t(device, name)

View File

@ -69,6 +69,7 @@ namespace netlist
PERRMSGV(MF_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1, 1,"You must pass an equal number of pins to DIPPINS {1}")
PERRMSGV(MF_UNKNOWN_OBJECT_TYPE_1, 1, "Unknown object type {1}")
PERRMSGV(MF_INVALID_NUMBER_CONVERSION_1_2, 2, "Invalid number conversion {1} : {2}")
PERRMSGV(MF_INVALID_ENUM_CONVERSION_1_2, 2, "Invalid element found {1} : {2}")
PERRMSGV(MF_ADDING_PARAMETER_1_TO_PARAMETER_LIST,1, "Error adding parameter {1} to parameter list")
PERRMSGV(MF_ADDING_1_2_TO_TERMINAL_LIST, 2, "Error adding {1} {2} to terminal list")
PERRMSGV(MF_NET_C_NEEDS_AT_LEAST_2_TERMINAL, 0, "You must pass at least 2 terminals to NET_C")

View File

@ -139,7 +139,7 @@ namespace plib
int cnt = 0;
for (auto &s : psplit(str, ",", false))
{
if (s == x)
if (trim(s) == x)
return cnt;
cnt++;
}

View File

@ -240,6 +240,7 @@ namespace plib
struct ename : public plib::penum_base { \
enum E { __VA_ARGS__ }; \
ename (E v) : m_v(v) { } \
template <typename T> explicit ename(T val) { m_v = static_cast<E>(val); } \
bool set_from_string (const std::string &s) { \
static char const *const strings = # __VA_ARGS__; \
int f = from_string_int(strings, s.c_str()); \

View File

@ -44,7 +44,7 @@ namespace devices
// ----------------------------------------------------------------------------------------
matrix_solver_t::matrix_solver_t(netlist_state_t &anetlist, const pstring &name,
const matrix_sort_type_e sort, const solver_parameters_t *params)
const solver_parameters_t *params)
: device_t(anetlist, name)
, m_params(*params)
, m_stat_calculations(*this, "m_stat_calculations", 0)
@ -56,7 +56,6 @@ namespace devices
, m_fb_sync(*this, "FB_sync")
, m_Q_sync(*this, "Q_sync")
, m_ops(0)
, m_sort(sort)
{
connect_post_start(m_fb_sync, m_Q_sync);
}
@ -203,7 +202,7 @@ namespace devices
case matrix_sort_type_e::ASCENDING:
case matrix_sort_type_e::DESCENDING:
{
int sort_order = (m_sort == matrix_sort_type_e::DESCENDING ? 1 : -1);
int sort_order = (sort == matrix_sort_type_e::DESCENDING ? 1 : -1);
for (std::size_t k = 0; k < iN - 1; k++)
for (std::size_t i = k+1; i < iN; i++)
@ -244,7 +243,7 @@ namespace devices
// free all - no longer needed
m_rails_temp.clear();
sort_terms(m_sort);
sort_terms(m_params.m_sort_type);
this->set_pointers();
@ -438,7 +437,7 @@ namespace devices
if (this_resched > 1 && !m_Q_sync.net().is_queued())
{
log().warning(MW_NEWTON_LOOPS_EXCEEDED_ON_NET_1(this->name()));
m_Q_sync.net().toggle_and_push_to_queue(m_params.m_nr_recalc_delay);
m_Q_sync.net().toggle_and_push_to_queue(netlist_time::from_double(m_params.m_nr_recalc_delay));
}
}
else

View File

@ -21,22 +21,66 @@ namespace netlist
{
namespace devices
{
/* FIXME: these should become proper devices */
P_ENUM(matrix_sort_type_e,
NOSORT,
ASCENDING,
DESCENDING,
PREFER_IDENTITY_TOP_LEFT,
PREFER_BAND_MATRIX
)
struct solver_parameters_t
{
bool m_pivot;
nl_double m_accuracy;
nl_double m_dynamic_lte;
solver_parameters_t(device_t &parent)
: m_freq(parent, "FREQ", 48000.0)
/* iteration parameters */
, m_gs_sor(parent, "SOR_FACTOR", 1.059)
, m_method(parent, "METHOD", "MAT_CR")
, m_accuracy(parent, "ACCURACY", 1e-7)
, m_gs_loops(parent, "GS_LOOPS", 9) // Gauss-Seidel loops
/* general parameters */
, m_gmin(parent, "GMIN", 1e-9)
, m_pivot(parent, "PIVOT", false) // use pivoting - on supported solvers
, m_nr_loops(parent, "NR_LOOPS", 250) // Newton-Raphson loops
, m_nr_recalc_delay(parent, "NR_RECALC_DELAY", netlist_time::quantum().as_double()) // Delay to next solve attempt if nr loops exceeded
, m_parallel(parent, "PARALLEL", 0)
/* automatic time step */
, m_dynamic_ts(parent, "DYNAMIC_TS", false)
, m_dynamic_lte(parent, "DYNAMIC_LTE", 1e-5) // diff/timestep
, m_dynamic_min_ts(parent, "DYNAMIC_MIN_TIMESTEP", 1e-6) // nl_double timestep resolution
/* matrix sorting */
, m_sort_type(parent, "SORT_TYPE", matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT)
/* special */
, m_use_gabs(parent, "USE_GABS", true)
, m_use_linear_prediction(parent, "USE_LINEAR_PREDICTION", false) // // savings are eaten up by effort
{}
param_double_t m_freq;
param_double_t m_gs_sor;
param_str_t m_method;
param_double_t m_accuracy;
param_num_t<std::size_t> m_gs_loops;
param_double_t m_gmin;
param_logic_t m_pivot;
param_int_t m_nr_loops;
param_double_t m_nr_recalc_delay;
param_int_t m_parallel;
param_logic_t m_dynamic_ts;
param_double_t m_dynamic_lte;
param_double_t m_dynamic_min_ts;
param_enum_t<matrix_sort_type_e> m_sort_type;
param_logic_t m_use_gabs;
param_logic_t m_use_linear_prediction;
nl_double m_min_timestep;
nl_double m_max_timestep;
nl_double m_gs_sor;
bool m_dynamic_ts;
std::size_t m_gs_loops;
std::size_t m_nr_loops;
netlist_time m_nr_recalc_delay;
bool m_use_gabs;
bool m_use_linear_prediction;
};
@ -84,14 +128,6 @@ namespace devices
analog_net_t *m_proxied_net; // only for proxy nets in analog input logic
};
P_ENUM(matrix_sort_type_e,
NOSORT,
ASCENDING,
DESCENDING,
PREFER_IDENTITY_TOP_LEFT,
PREFER_BAND_MATRIX
)
class matrix_solver_t : public device_t
{
public:
@ -141,7 +177,7 @@ namespace devices
protected:
matrix_solver_t(netlist_state_t &anetlist, const pstring &name,
matrix_sort_type_e sort, const solver_parameters_t *params);
const solver_parameters_t *params);
void sort_terms(matrix_sort_type_e sort);
@ -279,7 +315,6 @@ namespace devices
void step(const netlist_time &delta);
std::size_t m_ops;
const matrix_sort_type_e m_sort;
};
template <typename T>

View File

@ -30,7 +30,6 @@ namespace devices
using float_type = FT;
matrix_solver_direct_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size);
matrix_solver_direct_t(netlist_state_t &anetlist, const pstring &name, const matrix_sort_type_e sort, const solver_parameters_t *params, const std::size_t size);
void vsetup(analog_net_t::list_t &nets) override;
void reset() override { matrix_solver_t::reset(); }
@ -210,18 +209,7 @@ namespace devices
template <typename FT, int SIZE>
matrix_solver_direct_t<FT, SIZE>::matrix_solver_direct_t(netlist_state_t &anetlist, const pstring &name,
const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, matrix_sort_type_e::ASCENDING, params)
, m_new_V(size)
, m_dim(size)
, m_pitch(m_pitch_ABS ? m_pitch_ABS : (((m_dim + 1) + 7) / 8) * 8)
, m_A(size * m_pitch)
{
}
template <typename FT, int SIZE>
matrix_solver_direct_t<FT, SIZE>::matrix_solver_direct_t(netlist_state_t &anetlist, const pstring &name,
const matrix_sort_type_e sort, const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, sort, params)
: matrix_solver_t(anetlist, name, params)
, m_new_V(size)
, m_dim(size)
, m_pitch(m_pitch_ABS ? m_pitch_ABS : (((m_dim + 1) + 7) / 8) * 8)

View File

@ -36,7 +36,7 @@ namespace devices
matrix_solver_GCR_t(netlist_state_t &anetlist, const pstring &name,
const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT, params)
: matrix_solver_t(anetlist, name, params)
, m_dim(size)
, RHS(size)
, new_V(size)

View File

@ -37,7 +37,7 @@ namespace devices
*/
matrix_solver_GMRES_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size)
// matrix_solver_direct_t<FT, SIZE>(anetlist, name, matrix_solver_t::PREFER_BAND_MATRIX, params, size)
: matrix_solver_direct_t<FT, SIZE>(anetlist, name, matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT, params, size)
: matrix_solver_direct_t<FT, SIZE>(anetlist, name, params, size)
, m_ops(size, 0)
, m_gmres(size)
{
@ -118,7 +118,7 @@ namespace devices
const float_type accuracy = this->m_params.m_accuracy;
auto iter = std::max(plib::constants<std::size_t>::one(), this->m_params.m_gs_loops);
auto iter = std::max(plib::constants<std::size_t>::one(), this->m_params.m_gs_loops());
auto gsl = m_gmres.solve(m_ops, this->m_new_V, RHS, iter, accuracy);
this->m_iterative_total += gsl;

View File

@ -297,7 +297,7 @@ namespace devices
template <typename FT, int SIZE>
matrix_solver_sm_t<FT, SIZE>::matrix_solver_sm_t(netlist_state_t &anetlist, const pstring &name,
const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, matrix_sort_type_e::NOSORT, params)
: matrix_solver_t(anetlist, name, params)
, m_dim(size)
, m_cnt(0)
{

View File

@ -30,7 +30,7 @@ public:
using float_type = FT;
matrix_solver_SOR_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size)
: matrix_solver_direct_t<FT, SIZE>(anetlist, name, matrix_sort_type_e::ASCENDING, params, size)
: matrix_solver_direct_t<FT, SIZE>(anetlist, name, params, size)
, m_lp_fact(*this, "m_lp_fact", 0)
, w(size, 0.0)
, one_m_w(size, 0.0)

View File

@ -33,7 +33,7 @@ namespace devices
using float_type = FT;
matrix_solver_SOR_mat_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, std::size_t size)
: matrix_solver_direct_t<FT, SIZE>(anetlist, name, matrix_sort_type_e::ASCENDING, params, size)
: matrix_solver_direct_t<FT, SIZE>(anetlist, name, params, size)
, m_Vdelta(*this, "m_Vdelta", std::vector<float_type>(size))
, m_omega(*this, "m_omega", params->m_gs_sor)
, m_lp_fact(*this, "m_lp_fact", 0)

View File

@ -369,7 +369,7 @@ unsigned matrix_solver_w_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphs
template <typename FT, int SIZE>
matrix_solver_w_t<FT, SIZE>::matrix_solver_w_t(netlist_state_t &anetlist, const pstring &name,
const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, matrix_sort_type_e::NOSORT, params)
: matrix_solver_t(anetlist, name, params)
, m_cnt(0)
, m_dim(size)
{

View File

@ -80,7 +80,7 @@ namespace devices
/* FIXME: Needs a more elegant solution */
bool force_solve = (now < netlist_time::from_double(2 * m_params.m_max_timestep));
std::size_t nthreads = std::min(static_cast<std::size_t>(m_parallel()), plib::omp::get_max_threads());
std::size_t nthreads = std::min(static_cast<std::size_t>(m_params.m_parallel()), plib::omp::get_max_threads());
std::vector<matrix_solver_t *> &solvers = (force_solve ? m_mat_solvers_all : m_mat_solvers_timestepping);
@ -119,13 +119,13 @@ namespace devices
template <typename FT, int SIZE>
pool_owned_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver(std::size_t size, const pstring &solvername)
{
if (m_method() == "SOR_MAT")
if (m_params.m_method() == "SOR_MAT")
{
return create_it<matrix_solver_SOR_mat_t<FT, SIZE>>(state(), solvername, m_params, size);
//typedef matrix_solver_SOR_mat_t<m_N,storage_N> solver_sor_mat;
//return plib::make_unique<solver_sor_mat>(state(), solvername, &m_params, size);
}
else if (m_method() == "MAT_CR")
else if (m_params.m_method() == "MAT_CR")
{
if (size > 0) // GCR always outperforms MAT solver
{
@ -136,54 +136,35 @@ namespace devices
return create_it<matrix_solver_direct_t<FT, SIZE>>(state(), solvername, m_params, size);
}
}
else if (m_method() == "MAT")
else if (m_params.m_method() == "MAT")
{
return create_it<matrix_solver_direct_t<FT, SIZE>>(state(), solvername, m_params, size);
}
else if (m_method() == "SM")
else if (m_params.m_method() == "SM")
{
/* Sherman-Morrison Formula */
return create_it<matrix_solver_sm_t<FT, SIZE>>(state(), solvername, m_params, size);
}
else if (m_method() == "W")
else if (m_params.m_method() == "W")
{
/* Woodbury Formula */
return create_it<matrix_solver_w_t<FT, SIZE>>(state(), solvername, m_params, size);
}
else if (m_method() == "SOR")
else if (m_params.m_method() == "SOR")
{
return create_it<matrix_solver_SOR_t<FT, SIZE>>(state(), solvername, m_params, size);
}
else if (m_method() == "GMRES")
else if (m_params.m_method() == "GMRES")
{
return create_it<matrix_solver_GMRES_t<FT, SIZE>>(state(), solvername, m_params, size);
}
else
{
log().fatal(MF_UNKNOWN_SOLVER_TYPE(m_method()));
log().fatal(MF_UNKNOWN_SOLVER_TYPE(m_params.m_method()));
return pool_owned_ptr<matrix_solver_t>();
}
}
template <typename FT, int SIZE>
pool_owned_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver_x(std::size_t size, const pstring &solvername)
{
if (SIZE > 0)
{
if (size == SIZE)
return create_solver<FT, SIZE>(size, solvername);
else
return this->create_solver_x<FT, SIZE-1>(size, solvername);
}
else
{
if (size * 2 > -SIZE )
return create_solver<FT, SIZE>(size, solvername);
else
return this->create_solver_x<FT, SIZE / 2>(size, solvername);
}
}
struct net_splitter
{
@ -245,22 +226,8 @@ namespace devices
void NETLIB_NAME(solver)::post_start()
{
m_params.m_pivot = m_pivot();
m_params.m_accuracy = m_accuracy();
/* FIXME: Throw when negative */
m_params.m_gs_loops = static_cast<unsigned>(m_gs_loops());
m_params.m_nr_loops = static_cast<unsigned>(m_nr_loops());
m_params.m_nr_recalc_delay = netlist_time::from_double(m_nr_recalc_delay());
m_params.m_dynamic_lte = m_dynamic_lte();
m_params.m_gs_sor = m_gs_sor();
m_params.m_min_timestep = m_dynamic_min_ts();
m_params.m_dynamic_ts = (m_dynamic_ts() == 1 ? true : false);
m_params.m_max_timestep = netlist_time::from_double(1.0 / m_freq()).as_double();
m_params.m_use_gabs = m_use_gabs();
m_params.m_use_linear_prediction = m_use_linear_prediction();
m_params.m_min_timestep = m_params.m_dynamic_min_ts();
m_params.m_max_timestep = netlist_time::from_double(1.0 / m_params.m_freq()).as_double();
if (m_params.m_dynamic_ts)
{

View File

@ -16,9 +16,6 @@
#include <memory>
#include <vector>
//#define ATTR_ALIGNED(N) __attribute__((aligned(N)))
#define ATTR_ALIGNED(N) ATTR_ALIGN
// ----------------------------------------------------------------------------------------
// solver
// ----------------------------------------------------------------------------------------
@ -36,31 +33,7 @@ namespace devices
NETLIB_CONSTRUCTOR(solver)
, m_fb_step(*this, "FB_step")
, m_Q_step(*this, "Q_step")
, m_freq(*this, "FREQ", 48000.0)
/* iteration parameters */
, m_gs_sor(*this, "SOR_FACTOR", 1.059)
, m_method(*this, "METHOD", "MAT_CR")
, m_accuracy(*this, "ACCURACY", 1e-7)
, m_gs_loops(*this, "GS_LOOPS", 9) // Gauss-Seidel loops
/* general parameters */
, m_gmin(*this, "GMIN", 1e-9)
, m_pivot(*this, "PIVOT", false) // use pivoting - on supported solvers
, m_nr_loops(*this, "NR_LOOPS", 250) // Newton-Raphson loops
, m_nr_recalc_delay(*this, "NR_RECALC_DELAY", netlist_time::quantum().as_double()) // Delay to next solve attempt if nr loops exceeded
, m_parallel(*this, "PARALLEL", 0)
/* automatic time step */
, m_dynamic_ts(*this, "DYNAMIC_TS", false)
, m_dynamic_lte(*this, "DYNAMIC_LTE", 1e-5) // diff/timestep
, m_dynamic_min_ts(*this, "DYNAMIC_MIN_TIMESTEP", 1e-6) // nl_double timestep resolution
/* special */
, m_use_gabs(*this, "USE_GABS", true)
, m_use_linear_prediction(*this, "USE_LINEAR_PREDICTION", false) // // savings are eaten up by effort
, m_params()
, m_params(*this)
{
// internal staff
@ -70,7 +43,7 @@ namespace devices
void post_start();
void stop();
nl_double gmin() const { return m_gmin(); }
nl_double gmin() const { return m_params.m_gmin(); }
void create_solver_code(std::map<pstring, pstring> &mp);
@ -82,23 +55,6 @@ namespace devices
logic_input_t m_fb_step;
logic_output_t m_Q_step;
param_double_t m_freq;
param_double_t m_gs_sor;
param_str_t m_method;
param_double_t m_accuracy;
param_int_t m_gs_loops;
param_double_t m_gmin;
param_logic_t m_pivot;
param_int_t m_nr_loops;
param_double_t m_nr_recalc_delay;
param_int_t m_parallel;
param_logic_t m_dynamic_ts;
param_double_t m_dynamic_lte;
param_double_t m_dynamic_min_ts;
param_logic_t m_use_gabs;
param_logic_t m_use_linear_prediction;
std::vector<pool_owned_ptr<matrix_solver_t>> m_mat_solvers;
std::vector<matrix_solver_t *> m_mat_solvers_all;
std::vector<matrix_solver_t *> m_mat_solvers_timestepping;
@ -107,12 +63,9 @@ namespace devices
template <typename FT, int SIZE>
pool_owned_ptr<matrix_solver_t> create_solver(std::size_t size, const pstring &solvername);
template <typename FT, int SIZE>
pool_owned_ptr<matrix_solver_t> create_solver_x(std::size_t size, const pstring &solvername);
};
} //namespace devices
} // namespace devices
} // namespace netlist
#endif /* NLD_SOLVER_H_ */