diff options
author | 2019-03-25 23:13:40 +0100 | |
---|---|---|
committer | 2019-03-25 23:13:40 +0100 | |
commit | b380514764cf857469bae61c11143a19f79a74c5 (patch) | |
tree | 63c8012e262618f08a332da31dd714281aa2c5ed /src/lib/netlist/solver/nld_solver.cpp | |
parent | c24473ddff715ecec2e258a6eb38960cf8c8e98e (diff) |
Revert "conflict resolution (nw)"
This reverts commit c24473ddff715ecec2e258a6eb38960cf8c8e98e, reversing
changes made to 009cba4fb8102102168ef32870892438327f3705.
Diffstat (limited to 'src/lib/netlist/solver/nld_solver.cpp')
-rw-r--r-- | src/lib/netlist/solver/nld_solver.cpp | 641 |
1 files changed, 318 insertions, 323 deletions
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 4734cc3624d..cae76caab1a 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -31,398 +31,393 @@ #pragma GCC optimize "ivopts" #endif -#include "netlist/nl_lists.h" -#include "netlist/nl_factory.h" +#include <algorithm> +#include <cmath> // <<= needed by windows build + +#include "../nl_lists.h" + +#include "../plib/pomp.h" + +#include "../nl_factory.h" + +#include "nld_solver.h" #include "nld_matrix_solver.h" + +#if 1 #include "nld_ms_direct.h" -#include "nld_ms_direct1.h" -#include "nld_ms_direct2.h" #include "nld_ms_gcr.h" -#include "nld_ms_gmres.h" +#else +#include "nld_ms_direct_lu.h" +#endif +#include "nld_ms_w.h" #include "nld_ms_sm.h" +#include "nld_ms_direct1.h" +#include "nld_ms_direct2.h" #include "nld_ms_sor.h" #include "nld_ms_sor_mat.h" -#include "nld_ms_w.h" -#include "nld_solver.h" -#include "plib/pomp.h" - -#include <algorithm> -#include <cmath> +#include "nld_ms_gmres.h" namespace netlist { -namespace devices -{ + namespace devices + { - // ---------------------------------------------------------------------------------------- - // solver - // ---------------------------------------------------------------------------------------- - NETLIB_RESET(solver) - { - for (auto &s : m_mat_solvers) - s->reset(); - } - void NETLIB_NAME(solver)::stop() - { - for (auto &s : m_mat_solvers) - s->log_stats(); - } +// ---------------------------------------------------------------------------------------- +// solver +// ---------------------------------------------------------------------------------------- - NETLIB_UPDATE(solver) - { - if (m_params.m_dynamic_ts) - return; +NETLIB_RESET(solver) +{ + for (std::size_t i = 0; i < m_mat_solvers.size(); i++) + m_mat_solvers[i]->do_reset(); +} - netlist_time now(exec().time()); - /* force solving during start up if there are no time-step devices */ - /* FIXME: Needs a more elegant solution */ - bool force_solve = (now < netlist_time::from_double(2 * m_params.m_max_timestep)); +void NETLIB_NAME(solver)::stop() +{ + for (std::size_t i = 0; i < m_mat_solvers.size(); i++) + m_mat_solvers[i]->log_stats(); +} - std::size_t nthreads = std::min(static_cast<std::size_t>(m_parallel()), plib::omp::get_max_threads()); +NETLIB_NAME(solver)::~NETLIB_NAME(solver)() +{ +} - std::vector<matrix_solver_t *> &solvers = (force_solve ? m_mat_solvers_all : m_mat_solvers_timestepping); +NETLIB_UPDATE(solver) +{ + if (m_params.m_dynamic_ts) + return; - if (nthreads > 1 && solvers.size() > 1) - { - plib::omp::set_num_threads(nthreads); - plib::omp::for_static(static_cast<std::size_t>(0), solvers.size(), [&solvers, now](std::size_t i) - { - const netlist_time ts = solvers[i]->solve(now); - plib::unused_var(ts); - }); - } - else - for (auto & solver : solvers) - { - const netlist_time ts = solver->solve(now); - plib::unused_var(ts); - } + /* force solving during start up if there are no time-step devices */ + /* FIXME: Needs a more elegant solution */ + bool force_solve = (netlist().time() < netlist_time::from_double(2 * m_params.m_max_timestep)); - for (auto & solver : solvers) - solver->update_inputs(); + std::size_t nthreads = std::min(m_parallel(), plib::omp::get_max_threads()); + std::size_t t_cnt = 0; + int solv[128]; + for (int i = 0; i < m_mat_solvers.size(); i++) + if (m_mat_solvers[i]->has_timestep_devices() || force_solve) + solv[t_cnt++] = i; - /* step circuit */ - if (!m_Q_step.net().is_queued()) - { - m_Q_step.net().toggle_and_push_to_queue(netlist_time::from_double(m_params.m_max_timestep)); - } + if (nthreads > 1 && t_cnt > 1) + { + plib::omp::set_num_threads(nthreads); + plib::omp::for_static(0, t_cnt, [this, &solv](int i) { ATTR_UNUSED const netlist_time ts = this->m_mat_solvers[solv[i]]->solve(); }); } + else + for (auto & solver : m_mat_solvers) + if (solver->has_timestep_devices() || force_solve) + ATTR_UNUSED const netlist_time ts = solver->solve(); + + for (auto & solver : m_mat_solvers) + if (solver->has_timestep_devices() || force_solve) + solver->update_inputs(); - template <class C> - pool_owned_ptr<matrix_solver_t> create_it(netlist_state_t &nl, pstring name, solver_parameters_t ¶ms, std::size_t size) + /* step circuit */ + if (!m_Q_step.net().is_queued()) { - return pool().make_poolptr<C>(nl, name, ¶ms, size); + m_Q_step.net().toggle_and_push_to_queue(netlist_time::from_double(m_params.m_max_timestep)); } +} - template <typename FT, int SIZE> - pool_owned_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver(std::size_t size, const pstring &solvername) +template <class C> +std::unique_ptr<matrix_solver_t> create_it(netlist_t &nl, pstring name, solver_parameters_t ¶ms, std::size_t size) +{ + typedef C solver; + return plib::make_unique<solver>(nl, name, ¶ms, size); +} + +template <std::size_t m_N, std::size_t storage_N> +std::unique_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver(std::size_t size, const pstring &solvername) +{ + if (pstring("SOR_MAT").equals(m_method())) { - if (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") - { - if (size > 0) // GCR always outperforms MAT solver - { - return create_it<matrix_solver_GCR_t<FT, SIZE>>(state(), solvername, m_params, size); - } - else - { - return create_it<matrix_solver_direct_t<FT, SIZE>>(state(), solvername, m_params, size); - } - } - else if (m_method() == "MAT") - { - return create_it<matrix_solver_direct_t<FT, SIZE>>(state(), solvername, m_params, size); - } - else if (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") - { - /* Woodbury Formula */ - return create_it<matrix_solver_w_t<FT, SIZE>>(state(), solvername, m_params, size); - } - else if (m_method() == "SOR") - { - return create_it<matrix_solver_SOR_t<FT, SIZE>>(state(), solvername, m_params, size); - } - else if (m_method() == "GMRES") - { - return create_it<matrix_solver_GMRES_t<FT, SIZE>>(state(), solvername, m_params, size); - } - else - { - log().fatal(MF_1_UNKNOWN_SOLVER_TYPE, m_method()); - return pool_owned_ptr<matrix_solver_t>(); - } + return create_it<matrix_solver_SOR_mat_t<m_N, storage_N>>(netlist(), solvername, m_params, size); + //typedef matrix_solver_SOR_mat_t<m_N,storage_N> solver_sor_mat; + //return plib::make_unique<solver_sor_mat>(netlist(), solvername, &m_params, size); } - - template <typename FT, int SIZE> - pool_owned_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver_x(std::size_t size, const pstring &solvername) + else if (pstring("MAT_CR").equals(m_method())) { - if (SIZE > 0) + if (size > 0) // GCR always outperforms MAT solver { - if (size == SIZE) - return create_solver<FT, SIZE>(size, solvername); - else - return this->create_solver_x<FT, SIZE-1>(size, solvername); + typedef matrix_solver_GCR_t<m_N,storage_N> solver_mat; + return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); } else { - if (size * 2 > -SIZE ) - return create_solver<FT, SIZE>(size, solvername); - else - return this->create_solver_x<FT, SIZE / 2>(size, solvername); + typedef matrix_solver_direct_t<m_N,storage_N> solver_mat; + return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); } } - - struct net_splitter + else if (pstring("MAT").equals(m_method())) + { + typedef matrix_solver_direct_t<m_N,storage_N> solver_mat; + return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); + } + else if (pstring("SM").equals(m_method())) + { + /* Sherman-Morrison Formula */ + typedef matrix_solver_sm_t<m_N,storage_N> solver_mat; + return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); + } + else if (pstring("W").equals(m_method())) + { + /* Woodbury Formula */ + typedef matrix_solver_w_t<m_N,storage_N> solver_mat; + return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); + } + else if (pstring("SOR").equals(m_method())) + { + typedef matrix_solver_SOR_t<m_N,storage_N> solver_GS; + return plib::make_unique<solver_GS>(netlist(), solvername, &m_params, size); + } + else if (pstring("GMRES").equals(m_method())) { + typedef matrix_solver_GMRES_t<m_N,storage_N> solver_GMRES; + return plib::make_unique<solver_GMRES>(netlist(), solvername, &m_params, size); + } + else + { + log().fatal(MF_1_UNKNOWN_SOLVER_TYPE, m_method()); + return nullptr; + } +} - bool already_processed(const analog_net_t &n) const - { - /* no need to process rail nets - these are known variables */ - if (n.isRailNet()) +struct net_splitter +{ + + bool already_processed(analog_net_t *n) + { + if (n->isRailNet()) + return true; + for (auto & grp : groups) + if (plib::container::contains(grp, n)) return true; - /* if it's already processed - no need to continue */ - for (auto & grp : groups) - if (plib::container::contains(grp, &n)) - return true; - return false; - } + return false; + } - void process_net(analog_net_t &n) + void process_net(analog_net_t *n) + { + if (n->num_cons() == 0) + return; + /* add the net */ + groups.back().push_back(n); + for (auto &p : n->m_core_terms) { - /* ignore empty nets. FIXME: print a warning message */ - if (n.num_cons() == 0) - return; - /* add the net */ - groups.back().push_back(&n); - /* process all terminals connected to this net */ - for (auto &term : n.core_terms()) + if (p->is_type(detail::terminal_type::TERMINAL)) { - /* only process analog terminals */ - if (term->is_type(detail::terminal_type::TERMINAL)) - { - auto *pt = static_cast<terminal_t *>(term); - /* check the connected terminal */ - analog_net_t &connected_net = pt->connected_terminal()->net(); - if (!already_processed(connected_net)) - process_net(connected_net); - } + terminal_t *pt = static_cast<terminal_t *>(p); + analog_net_t *other_net = &pt->m_otherterm->net(); + if (!already_processed(other_net)) + process_net(other_net); } } + } - void run(netlist_state_t &netlist) + void run(netlist_t &netlist) + { + for (auto & net : netlist.m_nets) { - for (auto & net : netlist.nets()) + netlist.log().debug("processing {1}\n", net->name()); + if (!net->isRailNet() && net->num_cons() > 0) { - netlist.log().debug("processing {1}\n", net->name()); - if (!net->isRailNet() && net->num_cons() > 0) + netlist.log().debug(" ==> not a rail net\n"); + /* Must be an analog net */ + analog_net_t *n = static_cast<analog_net_t *>(net.get()); + if (!already_processed(n)) { - netlist.log().debug(" ==> not a rail net\n"); - /* Must be an analog net */ - auto &n = *static_cast<analog_net_t *>(net.get()); - if (!already_processed(n)) - { - groups.emplace_back(analog_net_t::list_t()); - process_net(n); - } + groups.push_back(analog_net_t::list_t()); + process_net(n); } } } + } - std::vector<analog_net_t::list_t> groups; - }; + std::vector<analog_net_t::list_t> groups; +}; - void NETLIB_NAME(solver)::post_start() +void NETLIB_NAME(solver)::post_start() +{ + const bool use_specific = true; + + 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(); + + if (m_params.m_dynamic_ts) { - 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_max_timestep *= 1;//NL_FCONST(1000.0); + } + else + { + m_params.m_min_timestep = m_params.m_max_timestep; + } - if (m_params.m_dynamic_ts) - { - m_params.m_max_timestep *= 1;//NL_FCONST(1000.0); - } - else - { - m_params.m_min_timestep = m_params.m_max_timestep; - } + //m_params.m_max_timestep = std::max(m_params.m_max_timestep, m_params.m_max_timestep::) - //m_params.m_max_timestep = std::max(m_params.m_max_timestep, m_params.m_max_timestep::) + // Override log statistics + pstring p = plib::util::environment("NL_STATS", ""); + if (p != "") + m_params.m_log_stats = p.as_long(); + else + m_params.m_log_stats = m_log_stats(); - // Override log statistics - pstring p = plib::util::environment("NL_STATS", ""); - if (p != "") - m_params.m_log_stats = plib::pstonum<decltype(m_params.m_log_stats)>(p); - else - m_params.m_log_stats = m_log_stats(); + log().verbose("Scanning net groups ..."); + // determine net groups - log().verbose("Scanning net groups ..."); - // determine net groups + net_splitter splitter; - net_splitter splitter; + splitter.run(netlist()); - splitter.run(state()); + // setup the solvers + log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), netlist().m_nets.size()); + for (auto & grp : splitter.groups) + { + std::unique_ptr<matrix_solver_t> ms; + std::size_t net_count = grp.size(); + pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size()); - // setup the solvers - log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), state().nets().size()); - for (auto & grp : splitter.groups) + switch (net_count) { - pool_owned_ptr<matrix_solver_t> ms; - std::size_t net_count = grp.size(); - pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size()); +#if 1 + case 1: + if (use_specific) + ms = plib::make_unique<matrix_solver_direct1_t>(netlist(), sname, &m_params); + else + ms = create_solver<1,1>(1, sname); + break; + case 2: + if (use_specific) + ms = plib::make_unique<matrix_solver_direct2_t>(netlist(), sname, &m_params); + else + ms = create_solver<2,2>(2, sname); + break; +#if 0 + case 3: + ms = create_solver<3,3>(3, sname); + break; + case 4: + ms = create_solver<4,4>(4, sname); + break; + case 5: + ms = create_solver<5,5>(5, sname); + break; + case 6: + ms = create_solver<6,6>(6, sname); + break; + case 7: + ms = create_solver<7,7>(7, sname); + break; + case 8: + ms = create_solver<8,8>(8, sname); + break; + case 9: + ms = create_solver<9,9>(9, sname); + break; + case 10: + ms = create_solver<10,10>(10, sname); + break; + case 11: + ms = create_solver<11,11>(11, sname); + break; + case 12: + ms = create_solver<12,12>(12, sname); + break; + case 15: + ms = create_solver<15,15>(15, sname); + break; + case 31: + ms = create_solver<31,31>(31, sname); + break; + case 35: + ms = create_solver<35,35>(35, sname); + break; + case 43: + ms = create_solver<43,43>(43, sname); + break; + case 49: + ms = create_solver<49,49>(49, sname); + break; +#endif +#if 0 + case 87: + ms = create_solver<87,87>(87, sname); + break; +#endif +#endif + default: + log().warning(MW_1_NO_SPECIFIC_SOLVER, net_count); + if (net_count <= 8) + { + ms = create_solver<0, 8>(net_count, sname); + } + else if (net_count <= 16) + { + ms = create_solver<0,16>(net_count, sname); + } + else if (net_count <= 32) + { + ms = create_solver<0,32>(net_count, sname); + } + else + if (net_count <= 64) + { + ms = create_solver<0,64>(net_count, sname); + } + else + if (net_count <= 128) + { + ms = create_solver<0,128>(net_count, sname); + } + else + { + log().fatal(MF_1_NETGROUP_SIZE_EXCEEDED_1, 128); + ms = nullptr; /* tease compilers */ + } - switch (net_count) - { - #if 1 - case 1: - ms = pool().make_poolptr<matrix_solver_direct1_t<double>>(state(), sname, &m_params); - break; - case 2: - ms = pool().make_poolptr<matrix_solver_direct2_t<double>>(state(), sname, &m_params); - break; - case 3: - ms = create_solver<double, 3>(3, sname); - break; - case 4: - ms = create_solver<double, 4>(4, sname); - break; - case 5: - ms = create_solver<double, 5>(5, sname); - break; - case 6: - ms = create_solver<double, 6>(6, sname); - break; - case 7: - ms = create_solver<double, 7>(7, sname); - break; - case 8: - ms = create_solver<double, 8>(8, sname); - break; - case 9: - ms = create_solver<double, 9>(9, sname); - break; - case 10: - ms = create_solver<double, 10>(10, sname); - break; - #if 0 - case 11: - ms = create_solver<double, 11>(11, sname); - break; - case 12: - ms = create_solver<double, 12>(12, sname); - break; - case 15: - ms = create_solver<double, 15>(15, sname); - break; - case 31: - ms = create_solver<double, 31>(31, sname); - break; - case 35: - ms = create_solver<double, 35>(35, sname); - break; - case 43: - ms = create_solver<double, 43>(43, sname); - break; - case 49: - ms = create_solver<double, 49>(49, sname); - break; - #endif - #if 1 - case 86: - ms = create_solver<double,86>(86, sname); - break; - #endif - #endif - default: - log().warning(MW_1_NO_SPECIFIC_SOLVER, net_count); - if (net_count <= 8) - { - ms = create_solver<double, -8>(net_count, sname); - } - else if (net_count <= 16) - { - ms = create_solver<double, -16>(net_count, sname); - } - else if (net_count <= 32) - { - ms = create_solver<double, -32>(net_count, sname); - } - else - if (net_count <= 64) - { - ms = create_solver<double, -64>(net_count, sname); - } - else - if (net_count <= 128) - { - ms = create_solver<double, -128>(net_count, sname); - } - else - { - log().fatal(MF_1_NETGROUP_SIZE_EXCEEDED_1, 128); - return; /* tease compilers */ - } - break; - } + break; + } - // FIXME ... - ms->setup(grp); + // FIXME ... + ms->setup(grp); - log().verbose("Solver {1}", ms->name()); - log().verbose(" ==> {2} nets", grp.size()); - log().verbose(" has {1} elements", ms->has_dynamic_devices() ? "dynamic" : "no dynamic"); - log().verbose(" has {1} elements", ms->has_timestep_devices() ? "timestep" : "no timestep"); - for (auto &n : grp) + log().verbose("Solver {1}", ms->name()); + log().verbose(" ==> {2} nets", grp.size()); + log().verbose(" has {1} elements", ms->has_dynamic_devices() ? "dynamic" : "no dynamic"); + log().verbose(" has {1} elements", ms->has_timestep_devices() ? "timestep" : "no timestep"); + for (auto &n : grp) + { + log().verbose("Net {1}", n->name()); + for (const auto &pcore : n->m_core_terms) { - log().verbose("Net {1}", n->name()); - for (const auto &pcore : n->core_terms()) - { - log().verbose(" {1}", pcore->name()); - } + log().verbose(" {1}", pcore->name()); } - - m_mat_solvers_all.push_back(ms.get()); - if (ms->has_timestep_devices()) - m_mat_solvers_timestepping.push_back(ms.get()); - - m_mat_solvers.emplace_back(std::move(ms)); } + + m_mat_solvers.push_back(std::move(ms)); } +} - void NETLIB_NAME(solver)::create_solver_code(std::map<pstring, pstring> &mp) +void NETLIB_NAME(solver)::create_solver_code(std::map<pstring, pstring> &mp) +{ + for (auto & s : m_mat_solvers) { - for (auto & s : m_mat_solvers) - { - auto r = s->create_solver_code(); - mp[r.first] = r.second; // automatically overwrites identical names - } + auto r = s->create_solver_code(); + mp[r.first] = r.second; // automatically overwrites identical names } +} - NETLIB_DEVICE_IMPL(solver, "SOLVER", "FREQ") + NETLIB_DEVICE_IMPL(solver) -} // namespace devices + } //namespace devices } // namespace netlist |