diff options
67 files changed, 1126 insertions, 859 deletions
diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index b260e8e3dec..a2a309d4a18 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -53,6 +53,7 @@ project "netlist" MAME_DIR .. "src/lib/netlist/plib/pconfig.h", MAME_DIR .. "src/lib/netlist/plib/palloc.h", MAME_DIR .. "src/lib/netlist/plib/pchrono.h", + MAME_DIR .. "src/lib/netlist/plib/pgsl.h", MAME_DIR .. "src/lib/netlist/plib/penum.h", MAME_DIR .. "src/lib/netlist/plib/pexception.cpp", MAME_DIR .. "src/lib/netlist/plib/pexception.h", diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index a47d453762d..1dd17acd8b1 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -127,7 +127,7 @@ protected: netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const noexcept override { //return plib::make_unique<plib::dynlib_static>(nullptr); - return netlist::host_arena::make_unique<plib::dynlib_static>(nl_static_solver_syms); + return plib::make_unique<plib::dynlib_static, netlist::host_arena>(nl_static_solver_syms); } private: @@ -169,7 +169,7 @@ protected: netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const noexcept override { - return netlist::host_arena::make_unique<plib::dynlib_static>(nullptr); + return plib::make_unique<plib::dynlib_static, netlist::host_arena>(nullptr); } private: @@ -181,7 +181,7 @@ class netlist_mame_device::netlist_mame_t : public netlist::netlist_state_t public: netlist_mame_t(netlist_mame_device &parent, const pstring &name) - : netlist::netlist_state_t(name, netlist::host_arena::make_unique<netlist_mame_device::netlist_mame_callbacks_t>(parent)) + : netlist::netlist_state_t(name, plib::make_unique<netlist_mame_device::netlist_mame_callbacks_t, netlist::host_arena>(parent)) , m_parent(parent) { } @@ -978,7 +978,8 @@ netlist::host_arena::unique_ptr<netlist::netlist_state_t> netlist_mame_device::b { try { - auto lnetlist = netlist::host_arena::make_unique<netlist::netlist_state_t>("netlist", netlist::host_arena::make_unique<netlist_validate_callbacks_t>()); + auto lnetlist = plib::make_unique<netlist::netlist_state_t, netlist::host_arena>("netlist", + plib::make_unique<netlist_validate_callbacks_t, netlist::host_arena>()); // enable validation mode lnetlist->set_extended_validation(true); common_dev_start(lnetlist.get()); diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp index b285f099adb..846ba8f3ba1 100644 --- a/src/lib/netlist/analog/nld_mosfet.cpp +++ b/src/lib/netlist/analog/nld_mosfet.cpp @@ -415,8 +415,8 @@ namespace analog else { // linear - const auto Sqr1(static_cast<nl_fptype>(plib::pow(Vdsat - Vds, 2))); - const auto Sqr2(static_cast<nl_fptype>(plib::pow(nlconst::two() * Vdsat - Vds, 2))); + const auto Sqr1(plib::narrow_cast<nl_fptype>(plib::pow(Vdsat - Vds, 2))); + const auto Sqr2(plib::narrow_cast<nl_fptype>(plib::pow(nlconst::two() * Vdsat - Vds, 2))); Cgb = 0; Cgs = m_CoxWL * (nlconst::one() - Sqr1 / Sqr2) * nlconst::two_thirds(); Cgd = m_CoxWL * (nlconst::one() - Vdsat * Vdsat / Sqr2) * nlconst::two_thirds(); diff --git a/src/lib/netlist/analog/nld_opamps.cpp b/src/lib/netlist/analog/nld_opamps.cpp index 1890ba85826..7b5db6b2fb6 100644 --- a/src/lib/netlist/analog/nld_opamps.cpp +++ b/src/lib/netlist/analog/nld_opamps.cpp @@ -115,7 +115,7 @@ namespace netlist , m_VL(*this, "VL") , m_VREF(*this, "VREF") { - m_type = static_cast<int>(m_modacc.m_TYPE); + m_type = plib::narrow_cast<int>(m_modacc.m_TYPE); if (m_type < 1 || m_type > 3) { log().fatal(MF_OPAMP_UNKNOWN_TYPE(m_type)); diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h index 87411ee8109..de2a69a23f7 100644 --- a/src/lib/netlist/analog/nlid_twoterm.h +++ b/src/lib/netlist/analog/nlid_twoterm.h @@ -561,11 +561,11 @@ namespace analog { register_subalias("P", P()); register_subalias("N", N()); - if (m_func() != "") + if (!m_func().empty()) m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}})); } - NETLIB_IS_TIMESTEP(m_func() != "") + NETLIB_IS_TIMESTEP(!m_func().empty()) NETLIB_TIMESTEPI() { @@ -609,11 +609,11 @@ namespace analog { register_subalias("P", P()); register_subalias("N", N()); - if (m_func() != "") + if (!m_func().empty()) m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}})); } - NETLIB_IS_TIMESTEP(m_func() != "") + NETLIB_IS_TIMESTEP(!m_func().empty()) NETLIB_TIMESTEPI() { m_t += step; diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index 5f5352d0c69..1d442953fb6 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -25,11 +25,13 @@ VSBUILD = $(SRC)/buildVS DOC = $(SRC)/documentation TIDY_FLAGSX = -checks=*,-google*,-hicpp*,readability*,-fuchsia*,cert-*,-android-*, -TIDY_FLAGSX += -llvm-header-guard,-cppcoreguidelines-pro-type-reinterpret-cast, +TIDY_FLAGSX += -llvm-header-guard, +# TIDY_FLAGSX += -cppcoreguidelines-pro-type-reinterpret-cast, TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-pointer-arithmetic, #TIDY_FLAGSX += -cppcoreguidelines-owning-memory, TIDY_FLAGSX += -modernize-use-default-member-init,-cppcoreguidelines-pro-bounds-constant-array-index, -TIDY_FLAGSX += -modernize-pass-by-value,-cppcoreguidelines-pro-type-static-cast-downcast, +TIDY_FLAGSX += -modernize-pass-by-value, +#TIDY_FLAGSX += -cppcoreguidelines-pro-type-static-cast-downcast, TIDY_FLAGSX += -cppcoreguidelines-avoid-magic-numbers, TIDY_FLAGSX += -cppcoreguidelines-macro-usage, TIDY_FLAGSX += -cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes, @@ -37,7 +39,7 @@ TIDY_FLAGSX += -bugprone-macro-parentheses, #TIDY_FLAGSX += -misc-macro-parentheses, TIDY_FLAGSX += -bugprone-too-small-loop-variable, TIDY_FLAGSX += -modernize-use-trailing-return-type, -TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay, +#TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay, TIDY_FLAGSX += -readability-magic-numbers,-readability-braces-around-statements, TIDY_FLAGSX += -readability-implicit-bool-conversion, TIDY_FLAGSX += -readability-named-parameter,-readability-function-size, @@ -85,7 +87,7 @@ CC = g++ LD = @g++ MD = @mkdir RM = @rm -CLANG_TIDY = clang-tidy-10 +CLANG_TIDY = clang-tidy-11 DEPENDCC=$(CC) @@ -132,6 +134,8 @@ POBJS := \ PMAIN := $(POBJ)/pmain.o NLOBJS := \ + $(NLOBJ)/solver/nld_solver.o \ + $(NLOBJ)/solver/nld_matrix_solver.o \ $(NLOBJ)/nl_base.o \ $(NLOBJ)/nl_parser.o \ $(NLOBJ)/nl_setup.o \ @@ -142,8 +146,6 @@ NLOBJS := \ $(NLOBJ)/analog/nld_switches.o \ $(NLOBJ)/analog/nlid_twoterm.o \ $(NLOBJ)/analog/nld_opamps.o \ - $(NLOBJ)/solver/nld_solver.o \ - $(NLOBJ)/solver/nld_matrix_solver.o \ $(NLOBJ)/tools/nl_convert.o \ $(NLOBJ)/generated/static_solvers.o \ $(NLOBJ)/devices/nld_2102A.o \ @@ -287,27 +289,32 @@ native: $(MAKE) CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra " gcc9: - $(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -fext-numeric-literals -Wall -pedantic -Wpedantic -Wsign-compare -Wextra" EXTRALIBS="-lquadmath" + $(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -Wall -pedantic -Wpedantic -fext-numeric-literals -Wsign-compare -Wextra" EXTRALIBS="-lquadmath" clang: #$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field -Wno-padded -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors" $(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native \ -mllvm -inline-threshold=2000 \ + -Wunknown-warning-option \ -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field \ -Werror -Wno-padded -Wno-weak-vtables -Wno-weak-template-vtables -Wno-unused-template \ - -Wno-missing-variable-declarations -Wno-float-equal -Wconversion \ + -Wmissing-variable-declarations -Wno-float-equal -Wconversion \ -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral \ - -Wno-exit-time-destructors -Winconsistent-missing-destructor-override" + -Wno-exit-time-destructors -Winconsistent-missing-destructor-override \ + -Wno-return-std-move-in-c++11 -Wno-unreachable-code" clang-libc: + #clang-11 currently broken #$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field -Wno-padded -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors" - $(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang-libc CEXTRAFLAGS="-march=native \ + $(MAKE) CC=clang++-10 LD=clang++-10 OBJ=obj/clang-libc CEXTRAFLAGS="-march=native \ -stdlib=libc++ -mllvm -inline-threshold=2000 \ + -Wunknown-warning-option \ -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field \ -Werror -Wno-padded -Wno-weak-vtables -Wno-weak-template-vtables -Wno-unused-template \ - -Wno-missing-variable-declarations -Wno-float-equal -Wconversion \ + -Wmissing-variable-declarations -Wno-float-equal -Wconversion \ -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral \ - -Wno-exit-time-destructors -Winconsistent-missing-destructor-override" \ + -Wno-exit-time-destructors -Winconsistent-missing-destructor-override \ + -Wno-return-std-move-in-c++11 -Wno-unreachable-code" LDEXTRAFLAGS=-stdlib=libc++ clang-5: diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index d804988c6fd..585637fb5f9 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -9,6 +9,8 @@ #include "nl_errstr.h" #include "solver/nld_solver.h" +#include <array> + namespace netlist { namespace devices @@ -18,6 +20,8 @@ namespace netlist // nld_base_proxy // ----------------------------------------------------------------------------- + static const std::array<std::pair<const char *, const char *>, 3> power_syms = {{ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}}; + nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name, const logic_t *inout_proxied) : device_t(anetlist, name, inout_proxied->logic_family()) @@ -29,16 +33,15 @@ namespace netlist throw nl_exception(MF_NULLPTR_FAMILY_NP("nld_base_proxy")); } - const std::vector<std::pair<pstring, pstring>> power_syms = { {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}; bool f = false; for (const auto & pwr_sym : power_syms) { pstring devname = inout_proxied->device().name(); - auto *tp_ct(anetlist.setup().find_terminal(devname + "." + pwr_sym.first, + auto *tp_ct(anetlist.setup().find_terminal(devname + "." + pstring(pwr_sym.first), /*detail::terminal_type::INPUT,*/ false)); - auto *tp_cn(anetlist.setup().find_terminal(devname + "." + pwr_sym.second, + auto *tp_cn(anetlist.setup().find_terminal(devname + "." + pstring(pwr_sym.second), /*detail::terminal_type::INPUT,*/ false)); if ((tp_ct != nullptr) && (tp_cn != nullptr)) { @@ -47,8 +50,8 @@ namespace netlist if (!tp_cn->is_analog()) throw nl_exception(plib::pfmt("Not an analog terminal: {1}")(tp_cn->name())); - auto *tp_t = static_cast<analog_t* >(tp_ct); - auto *tn_t = static_cast<analog_t *>(tp_cn); + auto *tp_t = dynamic_cast<analog_t* >(tp_ct); + auto *tn_t = dynamic_cast<analog_t *>(tp_cn); if (f && (tp_t != nullptr && tn_t != nullptr)) log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(inout_proxied->device().name(), m_tp->name(), m_tn->name(), diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index fc1bfefd84b..31a31c62d88 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -93,7 +93,7 @@ namespace devices , m_compiled(*this, "m_compiled") , m_funcparam({nlconst::zero()}) { - if (m_func() != "") + if (!m_func().empty()) m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}})); connect(m_feedback, m_Q); } diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp index 1718f53560d..a1bcc26d035 100644 --- a/src/lib/netlist/devices/nlid_truthtable.cpp +++ b/src/lib/netlist/devices/nlid_truthtable.cpp @@ -440,7 +440,7 @@ namespace devices if (!m_ttbl) { - m_ttbl = pool.make_unique<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t>(); + m_ttbl = plib::make_unique<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t>(pool); truthtable_parser desc_s(m_NO, m_NI, packed_int(m_ttbl->m_out_state.data(), sizeof(m_ttbl->m_out_state[0]) * 8), m_ttbl->m_timing_index.data(), m_ttbl->m_timing_nt.data()); @@ -448,7 +448,7 @@ namespace devices desc_s.parse(m_desc); } - return pool.make_unique<tt_type>(anetlist, name, m_family_name, *m_ttbl, m_desc); + return plib::make_unique<tt_type>(pool, anetlist, name, m_family_name, *m_ttbl, m_desc); } private: device_arena::unique_ptr<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t> m_ttbl; @@ -578,7 +578,7 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable) for (int j=0; j < 16; j++) m_timing_nt[j] = netlist_time::zero(); - while (!(ttline == "")) + while (!ttline.empty()) { std::vector<pstring> io(plib::psplit(ttline,"|")); // checks @@ -670,7 +670,7 @@ namespace factory #define ENTRYY(n, m, s) case (n * 100 + m): \ { using xtype = devices::netlist_factory_truthtable_t<n, m>; \ auto cs=s; \ - ret = host_arena::make_unique<xtype>(desc.name, std::move(cs)); } \ + ret = plib::make_unique<xtype, host_arena>(desc.name, std::move(cs)); } \ break #define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \ @@ -700,7 +700,7 @@ namespace factory nl_assert_always(false, msg.c_str()); } ret->m_desc = desc.desc; - ret->m_family_name = (desc.family != "" ? desc.family : pstring(config::DEFAULT_LOGIC_FAMILY())); + ret->m_family_name = (!desc.family.empty() ? desc.family : pstring(config::DEFAULT_LOGIC_FAMILY())); return ret; } diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index 42104458f7a..a9ac57f620d 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -27,7 +27,7 @@ namespace netlist host_arena::unique_ptr<plib::dynlib_base> callbacks_t:: static_solver_lib() const { - return host_arena::make_unique<plib::dynlib_static>(nullptr); + return plib::make_unique<plib::dynlib_static, host_arena>(nullptr); } // ---------------------------------------------------------------------------------------- @@ -129,9 +129,9 @@ namespace netlist m_lib = m_callbacks->static_solver_lib(); - m_setup = host_arena::make_unique<setup_t>(*this); + m_setup = plib::make_unique<setup_t, host_arena>(*this); // create the run interface - m_netlist = m_pool.make_unique<netlist_t>(*this, name); + m_netlist = plib::make_unique<netlist_t>(m_pool, *this, name); // Make sure save states are invalidated when a new version is deployed @@ -313,7 +313,7 @@ namespace netlist case 0: { std::vector<core_device_t *> d; - std::vector<nldelegate *> t; + std::vector<const nldelegate *> t; log().verbose("Using default startup strategy"); for (auto &n : m_nets) for (auto & term : n->core_terms()) @@ -402,7 +402,7 @@ namespace netlist } log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count, - total_time, total_time / static_cast<decltype(total_time)>((total_count > 0) ? total_count : 1)); + total_time, total_time / gsl::narrow<decltype(total_time)>((total_count > 0) ? total_count : 1)); log().verbose("Total loop {1:15}", si.m_stat_mainloop()); log().verbose("Total time {1:15}", total_time); @@ -424,8 +424,8 @@ namespace netlist } plib::pperftime_t<true>::type total_overhead = overhead() - * static_cast<plib::pperftime_t<true>::type>(total_count) - / static_cast<plib::pperftime_t<true>::type>(200000); + * gsl::narrow<plib::pperftime_t<true>::type>(total_count) + / gsl::narrow<plib::pperftime_t<true>::type>(200000); log().verbose("Queue Pushes {1:15}", si.m_queue.m_prof_call()); log().verbose("Queue Moves {1:15}", si.m_queue.m_prof_sortmove()); @@ -436,7 +436,7 @@ namespace netlist log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation."); log().verbose("Total overhead {1:15}", total_overhead); plib::pperftime_t<true>::type overhead_per_pop = (si.m_stat_mainloop()-2*total_overhead - (total_time - total_overhead)) - / static_cast<plib::pperftime_t<true>::type>(si.m_queue.m_prof_call()); + / gsl::narrow<plib::pperftime_t<true>::type>(si.m_queue.m_prof_call()); log().verbose("Overhead per pop {1:11}", overhead_per_pop ); log().verbose(""); } @@ -450,7 +450,7 @@ namespace netlist if (stats->m_stat_inc_active() > 3 * stats->m_stat_total_time.count() && stats->m_stat_inc_active() > trigger) log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(), - static_cast<nl_fptype>(stats->m_stat_inc_active()) / static_cast<nl_fptype>(stats->m_stat_total_time.count()), + gsl::narrow<nl_fptype>(stats->m_stat_inc_active()) / gsl::narrow<nl_fptype>(stats->m_stat_total_time.count()), stats->m_stat_inc_active(), stats->m_stat_total_time.count()); } log().verbose(""); @@ -856,14 +856,14 @@ namespace netlist pstring param_t::get_initial(const core_device_t *dev, bool *found) const { pstring res = dev->state().setup().get_initial_param_val(this->name(), ""); - *found = (res != ""); + *found = (!res.empty()); return res; } param_str_t::param_str_t(core_device_t &device, const pstring &name, const pstring &val) : param_t(device, name) { - m_param = host_arena::make_unique<pstring>(val); + m_param = plib::make_unique<pstring, host_arena>(val); *m_param = device.state().setup().get_initial_param_val(this->name(),val); } @@ -871,7 +871,7 @@ namespace netlist : param_t(name) { // deviceless parameter, no registration, owner is responsible - m_param = host_arena::make_unique<pstring>(val); + m_param = plib::make_unique<pstring, host_arena>(val); *m_param = state.setup().get_initial_param_val(this->name(),val); } diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index 7597989d71b..97e3f404a36 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -708,9 +708,8 @@ namespace netlist #endif void set_delegate(const nldelegate &delegate) noexcept { m_delegate = delegate; } - nldelegate &delegate() noexcept { return m_delegate; } const nldelegate &delegate() const noexcept { return m_delegate; } - inline void run_delegate() noexcept { m_delegate(); } + inline void run_delegate() noexcept { return m_delegate(); } private: nldelegate m_delegate; net_t * m_net; @@ -997,7 +996,7 @@ namespace netlist { public: - using list_t = std::vector<analog_net_t *>; + using list_t = plib::aligned_vector<analog_net_t *>; analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *railterminal = nullptr); @@ -1209,7 +1208,7 @@ namespace netlist pstring valstr() const override { - return plib::pfmt("{}").e(static_cast<nl_fptype>(m_param)); + return plib::pfmt("{}").e(gsl::narrow<nl_fptype>(m_param)); } private: @@ -1309,7 +1308,7 @@ namespace netlist public: template <typename P, typename Y=T, typename DUMMY = std::enable_if_t<plib::is_arithmetic<Y>::value>> value_base_t(P ¶m, const pstring &name) - : m_value(static_cast<T>(param.value(name))) + : m_value(gsl::narrow<T>(param.value(name))) { } template <typename P, typename Y=T, std::enable_if_t<!plib::is_arithmetic<Y>::value, int> = 0> @@ -1513,7 +1512,8 @@ namespace netlist ~device_t() noexcept override = default; - nldelegate default_delegate() { return nldelegate(&device_t::update, this); } + //nldelegate default_delegate() { return nldelegate(&device_t::update, this); } + nldelegate default_delegate() { return { &device_t::update, this }; } protected: NETLIB_UPDATEI() { } @@ -1757,7 +1757,7 @@ namespace netlist template<typename T, typename... Args> device_arena::unique_ptr<T> make_pool_object(Args&&... args) { - return m_pool.make_unique<T>(std::forward<Args>(args)...); + return plib::make_unique<T>(m_pool, std::forward<Args>(args)...); } // memory pool - still needed in some places device_arena &pool() noexcept { return m_pool; } @@ -2302,6 +2302,7 @@ namespace netlist inline void detail::net_t::remove_from_active_list(core_terminal_t &term) noexcept { + gsl_Expects(!m_list_active.empty()); m_list_active.remove(&term); if (m_list_active.empty()) railterminal().device().do_dec_active(); @@ -2309,24 +2310,24 @@ namespace netlist inline const analog_net_t & analog_t::net() const noexcept { - return static_cast<const analog_net_t &>(core_terminal_t::net()); + return plib::downcast<const analog_net_t &>(core_terminal_t::net()); } inline analog_net_t & analog_t::net() noexcept { - return static_cast<analog_net_t &>(core_terminal_t::net()); + return plib::downcast<analog_net_t &>(core_terminal_t::net()); } inline nl_fptype terminal_t::operator ()() const noexcept { return net().Q_Analog(); } inline logic_net_t & logic_t::net() noexcept { - return static_cast<logic_net_t &>(core_terminal_t::net()); + return plib::downcast<logic_net_t &>(core_terminal_t::net()); } inline const logic_net_t & logic_t::net() const noexcept { - return static_cast<const logic_net_t &>(core_terminal_t::net()); + return plib::downcast<const logic_net_t &>(core_terminal_t::net()); } inline netlist_sig_t logic_input_t::operator()() const noexcept @@ -2516,7 +2517,7 @@ namespace netlist if (plib::is_integral<T>::value) if (plib::abs(valx - plib::trunc(valx)) > nlconst::magic(1e-6)) throw nl_exception(MF_INVALID_NUMBER_CONVERSION_1_2(device.name() + "." + name, p)); - m_param = static_cast<T>(valx); + m_param = plib::narrow_cast<T>(valx); } device.state().save(*this, m_param, this->name(), "m_param"); @@ -2599,7 +2600,7 @@ namespace netlist state_container<C>::state_container(O &owner, const pstring &name, const state_container<C>::value_type & value) { - owner.state().save(owner, *static_cast<C *>(this), owner.name(), name); + owner.state().save(owner, static_cast<C &>(*this), owner.name(), name); for (std::size_t i=0; i < this->size(); i++) (*this)[i] = value; } @@ -2610,7 +2611,7 @@ namespace netlist std::size_t n, const state_container<C>::value_type & value) : C(n, value) { - owner.state().save(owner, *static_cast<C *>(this), owner.name(), name); + owner.state().save(owner, static_cast<C &>(*this), owner.name(), name); } extern template struct state_var<std::uint8_t>; diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index 8740b5ddbd9..81e0c860aa9 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -200,6 +200,12 @@ namespace netlist /// using MAX_QUEUE_SIZE = std::integral_constant<std::size_t, 512>; // NOLINT + using use_float_matrix = std::integral_constant<bool, NL_USE_FLOAT_MATRIX>; + using use_long_double_matrix = std::integral_constant<bool, NL_USE_LONG_DOUBLE_MATRIX>; + using use_float128_matrix = std::integral_constant<bool, NL_USE_FLOAT128>; + + using use_mempool = std::integral_constant<bool, NL_USE_MEMPOOL>; + /// \brief Floating point types used /// /// nl_fptype is the floating point type used throughout the diff --git a/src/lib/netlist/nl_factory.cpp b/src/lib/netlist/nl_factory.cpp index 8ef9799101a..519c4ea029c 100644 --- a/src/lib/netlist/nl_factory.cpp +++ b/src/lib/netlist/nl_factory.cpp @@ -76,7 +76,7 @@ namespace factory { device_arena::unique_ptr<core_device_t> library_element_t::make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name) { - return pool.make_unique<NETLIB_NAME(wrapper)>(anetlist, name); + return plib::make_unique<NETLIB_NAME(wrapper)>(pool, anetlist, name); } diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h index 4c9a47cc749..5b3ee4bb3a6 100644 --- a/src/lib/netlist/nl_factory.h +++ b/src/lib/netlist/nl_factory.h @@ -129,7 +129,7 @@ namespace factory { netlist_state_t &anetlist, const pstring &name, std::tuple<Args...>& args, std::index_sequence<Is...>) { - return pool.make_unique<C>(anetlist, name, std::forward<Args>(std::get<Is>(args))...); + return plib::make_unique<C>(pool, anetlist, name, std::forward<Args>(std::get<Is>(args))...); } dev_uptr make_device(device_arena &pool, @@ -149,7 +149,7 @@ namespace factory { static uptr create(const pstring &name, properties &&props, Args&&... args) { - return host_arena::make_unique<device_element_t<C, Args...>>(name, + return plib::make_unique<device_element_t<C, Args...>, host_arena>(name, std::move(props), std::forward<Args>(args)...); } private: @@ -194,7 +194,7 @@ namespace factory { template <typename T> element_t::uptr constructor_t(const pstring &name, properties &&props) { - return host_arena::make_unique<device_element_t<T>>(name, std::move(props)); + return plib::make_unique<device_element_t<T>, host_arena>(name, std::move(props)); } // ----------------------------------------------------------------------------- diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp index 8e76538632a..e34683d5261 100644 --- a/src/lib/netlist/nl_parser.cpp +++ b/src/lib/netlist/nl_parser.cpp @@ -83,7 +83,7 @@ bool parser_t::parse(const pstring &nlname) require_token(m_tok_paren_left); token_t name = get_token(); require_token(m_tok_paren_right); - if (name.str() == nlname || nlname == "") + if (name.str() == nlname || nlname.empty()) { parse_netlist(name.str()); return true; @@ -164,8 +164,8 @@ void parser_t::net_truthtable_start(const pstring &nlname) netlist::tt_desc desc; desc.name = name; - desc.ni = static_cast<unsigned long>(ni); - desc.no = static_cast<unsigned long>(no); + desc.ni = gsl::narrow<unsigned long>(ni); + desc.no = gsl::narrow<unsigned long>(no); desc.family = ""; while (true) diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index 1b63b002492..b6c466be6e7 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -200,7 +200,7 @@ namespace netlist || plib::abs(value) > nlconst::magic(1e9)) register_param(param, plib::pfmt("{1:.9}").e(value)); else - register_param(param, plib::pfmt("{1}")(static_cast<long>(value))); + register_param(param, plib::pfmt("{1}")(gsl::narrow<long>(value))); } void nlparse_t::register_param(const pstring ¶m, const pstring &value) @@ -248,7 +248,7 @@ namespace netlist void nlparse_t::register_lib_entry(const pstring &name, factory::properties &&props) { - m_factory.add(host_arena::make_unique<factory::library_element_t>(name, std::move(props))); + m_factory.add(plib::make_unique<factory::library_element_t, host_arena>(name, std::move(props))); } void nlparse_t::register_frontier(const pstring &attach, const pstring &r_IN, @@ -508,7 +508,7 @@ pstring setup_t::resolve_alias(const pstring &name) const ret = temp; auto p = m_abstract.m_alias.find(ret); temp = (p != m_abstract.m_alias.end() ? p->second : ""); - } while (temp != "" && temp != ret); + } while (!temp.empty() && temp != ret); log().debug("{1}==>{2}\n", name, ret); return ret; @@ -532,7 +532,7 @@ pstring setup_t::de_alias(const pstring &alias) const break; } } - } while (temp != "" && temp != ret); + } while (!temp.empty() && temp != ret); log().debug("{1}==>{2}\n", alias, ret); return ret; @@ -650,7 +650,7 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(const detail::core_terminal_t &o { nl_assert(out.is_logic()); - const auto &out_cast = static_cast<const logic_output_t &>(out); + const auto &out_cast = dynamic_cast<const logic_output_t &>(out); auto iter_proxy(m_proxies.find(&out)); if (iter_proxy != m_proxies.end()) @@ -878,7 +878,7 @@ void setup_t::connect_terminals(detail::core_terminal_t &t1,detail::core_termina { log().debug("adding analog net ...\n"); // FIXME: Nets should have a unique name - auto anet = nlstate().pool().make_owned<analog_net_t>(m_nlstate,"net." + t1.name()); + auto anet = plib::make_owned<analog_net_t>(nlstate().pool(), m_nlstate,"net." + t1.name()); auto *anetp = anet.get(); m_nlstate.register_net(std::move(anet)); t1.set_net(anetp); @@ -1043,7 +1043,7 @@ void setup_t::resolve_inputs() detail::core_terminal_t *t1 = find_terminal(t1s); detail::core_terminal_t *t2 = find_terminal(t2s); if (connect(*t1, *t2)) - m_abstract.m_links.erase(m_abstract.m_links.begin() + static_cast<std::ptrdiff_t>(i)); + m_abstract.m_links.erase(m_abstract.m_links.begin() + plib::narrow_cast<std::ptrdiff_t>(i)); else i++; } @@ -1104,16 +1104,16 @@ void setup_t::resolve_inputs() detail::core_terminal_t *term = i.second; if (term->is_tristate_output()) { - const auto *tri(static_cast<tristate_output_t *>(term)); + const auto &tri(dynamic_cast<tristate_output_t &>(*term)); // check if we are connected to a proxy - const auto iter_proxy(m_proxies.find(tri)); + const auto iter_proxy(m_proxies.find(&tri)); - if (iter_proxy == m_proxies.end() && !tri->is_force_logic()) + if (iter_proxy == m_proxies.end() && !tri.is_force_logic()) { log().error(ME_TRISTATE_NO_PROXY_FOUND_2(term->name(), term->device().name())); err = true; } - else if (iter_proxy != m_proxies.end() && tri->is_force_logic()) + else if (iter_proxy != m_proxies.end() && tri.is_force_logic()) { log().error(ME_TRISTATE_PROXY_FOUND_2(term->name(), term->device().name())); err = true; @@ -1256,7 +1256,7 @@ nl_fptype models_t::model_t::value(const pstring &entity) const pstring tmp = value_str(entity); nl_fptype factor = nlconst::one(); - auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.size() - 1)); + auto p = std::next(tmp.begin(), plib::narrow_cast<pstring::difference_type>(tmp.size() - 1)); switch (*p) { case 'M': factor = nlconst::magic(1e6); break; // NOLINT @@ -1390,7 +1390,7 @@ const logic_family_desc_t *setup_t::family_from_model(const pstring &model) if (it != m_nlstate.family_cache().end()) return it->second.get(); - auto ret = host_arena::make_unique<logic_family_std_proxy_t>(ft); + auto ret = plib::make_unique<logic_family_std_proxy_t, host_arena>(ft); ret->m_low_thresh_PCNT = modv.m_IVL(); ret->m_high_thresh_PCNT = modv.m_IVH(); @@ -1434,7 +1434,7 @@ void setup_t::prepare_to_run() { pstring envlog = plib::util::environment("NL_LOGS", ""); - if (envlog != "") + if (!envlog.empty()) { std::vector<pstring> loglist(plib::psplit(envlog, ":")); m_parser.register_dynamic_log_devices(loglist); @@ -1444,7 +1444,7 @@ void setup_t::prepare_to_run() for (auto & e : m_abstract.m_defparams) { - auto param(host_arena::make_unique<param_str_t>(nlstate(), e.first, e.second)); + auto param(plib::make_unique<param_str_t, host_arena>(nlstate(), e.first, e.second)); register_param_t(*param); m_defparam_lifetime.push_back(std::move(param)); } @@ -1597,7 +1597,7 @@ source_string_t::stream_ptr source_string_t::stream(const pstring &name) plib::unused_var(name); auto ret(std::make_unique<std::istringstream>(m_str)); ret->imbue(std::locale::classic()); - return std::move(ret); // FIXME: for c++11 clang builds + return ret; } source_mem_t::stream_ptr source_mem_t::stream(const pstring &name) @@ -1605,7 +1605,7 @@ source_mem_t::stream_ptr source_mem_t::stream(const pstring &name) plib::unused_var(name); auto ret(std::make_unique<std::istringstream>(m_str, std::ios_base::binary)); ret->imbue(std::locale::classic()); - return std::move(ret); // FIXME: for c++11 clang builds + return ret; } source_file_t::stream_ptr source_file_t::stream(const pstring &name) diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 9e6714007f0..6d99f1ca183 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -307,10 +307,10 @@ namespace netlist void register_param(const pstring ¶m, nl_fptype value); template <typename T> - std::enable_if_t<plib::is_floating_point<T>::value || plib::is_integral<T>::value> + std::enable_if_t<plib::is_arithmetic<T>::value> register_param_val(const pstring ¶m, T value) { - register_param(param, static_cast<nl_fptype>(value)); + register_param(param, plib::narrow_cast<nl_fptype>(value)); } void register_lib_entry(const pstring &name, factory::properties &&props); diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index 17912a41d13..98bfbb49a92 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -78,9 +78,9 @@ namespace netlist /// \note This is not the right location yet. /// - using device_arena = std::conditional<NL_USE_MEMPOOL, + using device_arena = std::conditional_t<config::use_mempool::value, plib::mempool_arena<plib::aligned_arena>, - plib::aligned_arena>::type; + plib::aligned_arena>; using host_arena = plib::aligned_arena; /// \brief Interface definition for netlist callbacks into calling code diff --git a/src/lib/netlist/plib/gmres.h b/src/lib/netlist/plib/gmres.h index c8ea1cad2f8..df0fc787c52 100644 --- a/src/lib/netlist/plib/gmres.h +++ b/src/lib/netlist/plib/gmres.h @@ -38,9 +38,9 @@ namespace plib mat_precondition_ILU(std::size_t size, std::size_t ilu_scale = 4 , std::size_t bw = plib::pmatrix_cr_t<FT, SIZE>::FILL_INFINITY) - : m_mat(static_cast<typename mat_type::index_type>(size)) - , m_LU(static_cast<typename mat_type::index_type>(size)) - , m_ILU_scale(static_cast<std::size_t>(ilu_scale)) + : m_mat(narrow_cast<typename mat_type::index_type>(size)) + , m_LU(narrow_cast<typename mat_type::index_type>(size)) + , m_ILU_scale(narrow_cast<std::size_t>(ilu_scale)) , m_band_width(bw) { } @@ -103,7 +103,7 @@ namespace plib if (m_mat.col_idx[k] == i && k < m_mat.row_idx[j+1]) nzcol[i].push_back(k); } - nzcol[i].push_back(static_cast<std::size_t>(-1)); + nzcol[i].push_back(narrow_cast<std::size_t>(-1)); } } @@ -139,7 +139,7 @@ namespace plib const auto &nz = nzcol[i]; std::size_t j; - while ((j = nz[nzcolp++])!=static_cast<std::size_t>(-1)) // NOLINT(bugprone-infinite-loop) + while ((j = nz[nzcolp++])!=narrow_cast<std::size_t>(-1)) // NOLINT(bugprone-infinite-loop) { v += m_mat.A[j] * m_mat.A[j]; } @@ -209,14 +209,12 @@ namespace plib // FIXME: hardcoding RESTART to 20 becomes an issue on very large // systems. - template <typename FT, int SIZE, int RESTART = 80> + template <typename FT, int SIZE, int RESTART = 16> struct gmres_t { public: using float_type = FT; - // FIXME: dirty hack to make this compile - static constexpr const std::size_t storage_N = plib::sizeabs<FT, SIZE>::ABS(); explicit gmres_t(std::size_t size) : residual(size) @@ -236,7 +234,7 @@ namespace plib g1 = s * g0_last + c * g1; } - std::size_t size() const { return (SIZE<=0) ? m_size : static_cast<std::size_t>(SIZE); } + std::size_t size() const { return (SIZE<=0) ? m_size : narrow_cast<std::size_t>(SIZE); } template <int k, typename OPS, typename VT> bool do_k(OPS &ops, VT &x, std::size_t &itr_used, FT rho_delta, bool dummy) @@ -360,7 +358,7 @@ namespace plib rho_delta = accuracy * rho_to_accuracy; } else - rho_delta = accuracy * plib::sqrt(static_cast<FT>(n)); + rho_delta = accuracy * plib::sqrt(narrow_cast<FT>(n)); // // Using @@ -407,8 +405,6 @@ namespace plib private: - //typedef typename plib::mat_cr_t<FT, SIZE>::index_type mattype; - plib::parray<float_type, SIZE> residual; plib::parray<float_type, SIZE> Ax; @@ -423,8 +419,6 @@ namespace plib std::size_t m_size; bool m_use_more_precise_stop_condition; - - }; @@ -454,7 +448,7 @@ namespace plib { } - std::size_t size() const { return (SIZE<=0) ? m_size : static_cast<std::size_t>(SIZE); } + std::size_t size() const { return (SIZE<=0) ? m_size : narrow_cast<std::size_t>(SIZE); } template <typename OPS, typename VT, typename VRHS> std::size_t solve(OPS &ops, VT &x0, const VRHS & rhs, const std::size_t iter_max, float_type accuracy) @@ -478,7 +472,7 @@ namespace plib ops.calc_rhs(Ax, x); vec_sub(size(), rhs, Ax, residual); - FT rho_delta = accuracy * std::sqrt(static_cast<FT>(size())); + FT rho_delta = accuracy * std::sqrt(narrow_cast<FT>(size())); rho_delta = 1e-9; diff --git a/src/lib/netlist/plib/mat_cr.h b/src/lib/netlist/plib/mat_cr.h index 061e186d37f..2da661d39d7 100644 --- a/src/lib/netlist/plib/mat_cr.h +++ b/src/lib/netlist/plib/mat_cr.h @@ -73,7 +73,7 @@ namespace plib ~pmatrix_cr_t() = default; - constexpr std::size_t size() const noexcept { return (N>0) ? static_cast<std::size_t>(N) : m_size; } + constexpr std::size_t size() const noexcept { return (N>0) ? narrow_cast<std::size_t>(N) : m_size; } void clear() noexcept { @@ -132,9 +132,9 @@ namespace plib row_idx[k] = nz; for (std::size_t j=0; j < size(); j++) - if (f[k][j] <= max_fill && plib::abs(static_cast<int>(k)-static_cast<int>(j)) <= static_cast<int>(band_width)) + if (f[k][j] <= max_fill && plib::abs(narrow_cast<int>(k)-narrow_cast<int>(j)) <= narrow_cast<int>(band_width)) { - col_idx[nz] = static_cast<C>(j); + col_idx[nz] = narrow_cast<C>(j); if (j == k) diag[k] = nz; nz++; @@ -150,7 +150,7 @@ namespace plib { for (std::size_t j=k + 1; j < size(); j++) if (f[j][k] < FILL_INFINITY) - nzbd[k].push_back(static_cast<C>(j)); + nzbd[k].push_back(narrow_cast<C>(j)); nzbd[k].push_back(0); // end of sequence } @@ -343,7 +343,7 @@ namespace plib { for (std::size_t i = 0; i < m_ge_par.size(); i++) if (plib::container::contains( m_ge_par[i], k)) - return static_cast<int>(i); + return narrow_cast<int>(i); return -1; } @@ -525,7 +525,7 @@ namespace plib } } if (found) - ilu_rows[p++] = static_cast<index_type>(i); + ilu_rows[p++] = narrow_cast<index_type>(i); } ilu_rows[p] = 0; // end of array this->build_from_fill_mat(fill, ilup); //, m_band_width); // ILU(2) diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index 045461c8418..b3ebcbc52e5 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -9,6 +9,7 @@ /// #include "pconfig.h" +#include "pgsl.h" #include "pmath.h" #include "pstring.h" #include "ptypes.h" @@ -27,27 +28,51 @@ namespace plib { //============================================================ + // aligned types + //============================================================ + +#if 0 +#if (PUSE_ALIGNED_HINTS) + template <typename T, std::size_t A> + using aligned_type __attribute__((aligned(A))) = T; +#else + template <typename T, std::size_t A> + using aligned_type = T; +#endif + + template <typename T, std::size_t A> + using aligned_pointer = aligned_type<T, A> *; + + template <typename T, std::size_t A> + using const_aligned_pointer = const aligned_type<T, A> *; + + template <typename T, std::size_t A> + using aligned_reference = aligned_type<T, A> &; + + template <typename T, std::size_t A> + using const_aligned_reference = const aligned_type<T, A> &; +#endif + //============================================================ // Standard arena_deleter //============================================================ - template <typename P, typename T, typename A = void> - struct arena_deleter + template <typename P, typename T, bool X> + struct arena_deleter_base { - }; template <typename P, typename T> - struct arena_deleter<P, T, std::enable_if_t<!P::has_static_deallocator>> + struct arena_deleter_base<P, T, false> { using arena_storage_type = P; - constexpr arena_deleter(arena_storage_type *a = nullptr) noexcept + constexpr arena_deleter_base(arena_storage_type *a = nullptr) noexcept : m_a(a) { } template<typename U, typename = std::enable_if_t<std::is_convertible< U*, T*>::value>> - arena_deleter(const arena_deleter<P, U> &rhs) noexcept + arena_deleter_base(const arena_deleter_base<P, U, false> &rhs) noexcept : m_a(rhs.m_a) { } void operator()(T *p) noexcept @@ -61,18 +86,18 @@ namespace plib { }; template <typename P, typename T> - struct arena_deleter<P, T, std::enable_if_t<P::has_static_deallocator>> + struct arena_deleter_base<P, T, true> { using arena_storage_type = P; - constexpr arena_deleter(arena_storage_type *a = nullptr) noexcept + constexpr arena_deleter_base(arena_storage_type *a = nullptr) noexcept { plib::unused_var(a); } template<typename U, typename = typename std::enable_if<std::is_convertible< U*, T*>::value>::type> - arena_deleter(const arena_deleter<P, U> &rhs) noexcept + arena_deleter_base(const arena_deleter_base<P, U, true> &rhs) noexcept { plib::unused_var(rhs); } @@ -85,6 +110,13 @@ namespace plib { } }; + template <typename P, typename T> + struct arena_deleter : public arena_deleter_base<P, T, P::has_static_deallocator> + { + using base_type = arena_deleter_base<P, T, P::has_static_deallocator>; + using base_type::base_type; + }; + //============================================================ // owned_ptr: smart pointer with ownership information //============================================================ @@ -209,7 +241,8 @@ namespace plib { { public: using value_type = T; - static constexpr const std::size_t align_size = ALIGN; + using pointer = T *; + static /*constexpr*/ const std::size_t align_size = ALIGN; using arena_type = ARENA; static_assert(align_size >= alignof(T) && (align_size % alignof(T)) == 0, @@ -237,14 +270,14 @@ namespace plib { using other = arena_allocator<ARENA, U, ALIGN>; }; - T* allocate(std::size_t n) + pointer allocate(std::size_t n) { return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n)); //NOLINT } - void deallocate(T* p, std::size_t n) noexcept + void deallocate(pointer p, std::size_t n) noexcept { - m_a.deallocate(p, n); + m_a.deallocate(p, sizeof(T) * n); } template<typename U, typename... Args> @@ -296,171 +329,88 @@ namespace plib { // The previous code compiled with gcc and clang on all platforms and // compilers apart from MSVC. - template <typename P, bool HSD> + template <typename P, bool HSD, bool HSA> + struct arena_base; + + template <typename P, bool HSD, bool HSA> struct arena_core { static constexpr const bool has_static_deallocator = HSD; + static constexpr const bool has_static_allocator = HSA; using size_type = std::size_t; template <class T, size_type ALIGN = alignof(T)> using allocator_type = arena_allocator<P, T, ALIGN>; + template <class T> + using deleter_type = arena_deleter<P, T>; + + template <typename T> + using unique_ptr = std::unique_ptr<T, deleter_type<T>>; + + template <typename T> + using owned_ptr = plib::owned_ptr<T, deleter_type<T>>; + static inline P &instance() noexcept { static P s_arena; return s_arena; } - size_type cur_alloc() const noexcept { return m_stat_cur_alloc(); } // NOLINT(readability-convert-member-functions-to-static) - size_type max_alloc() const noexcept { return m_stat_max_alloc(); } // NOLINT(readability-convert-member-functions-to-static) - protected: - static size_t &m_stat_cur_alloc() noexcept { static size_t val = 0; return val; } - static size_t &m_stat_max_alloc() noexcept { static size_t val = 0; return val; } - - }; - - template <typename P, bool HSD> - struct arena_hsd : public arena_core<P, HSD> - { - template<typename T> - inline void free(T *ptr) noexcept - { - ptr->~T(); - static_cast<P *>(this)->deallocate(ptr, sizeof(T)); - } - }; + friend struct arena_base<P, HSD, HSA>; + private: + size_t m_stat_cur_alloc = 0; + size_t m_stat_max_alloc = 0; - template <typename P> - struct arena_hsd<P, true> : public arena_core<P, true> - { - template<typename T> - static inline void free(T *ptr) noexcept - { - ptr->~T(); - P::deallocate(ptr, sizeof(T)); - } }; - template <typename P, bool HSD, bool HSA> - struct arena_base : public arena_hsd<P, HSD> + struct arena_base : public arena_core<P, HSD, HSA> { - template <class T> - using deleter_type = arena_deleter<P, T>; + using base_type = arena_core<P, HSD, HSA>; + using size_type = typename base_type::size_type; - template <typename T> - using unique_ptr = std::unique_ptr<T, deleter_type<T>>; - - template <typename T> - using owned_ptr = plib::owned_ptr<T, deleter_type<T>>; + static size_type cur_alloc() noexcept { return base_type::instance().m_stat_cur_alloc; } + static size_type max_alloc() noexcept { return base_type::instance().m_stat_max_alloc; } - template<typename T, typename... Args> - inline unique_ptr<T> make_unique(Args&&... args) + static inline void inc_alloc_stat(size_type size) { - auto *mem = static_cast<P *>(this)->allocate(alignof(T), sizeof(T)); - try - { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto *mema = new (mem) T(std::forward<Args>(args)...); - return unique_ptr<T>(mema, deleter_type<T>()); - } - catch (...) - { - static_cast<P *>(this)->deallocate(mem, sizeof(T)); - throw; - } + auto &i = base_type::instance(); + i.m_stat_cur_alloc += size; + if (i.m_stat_max_alloc <i.m_stat_cur_alloc) + i.m_stat_max_alloc = i.m_stat_cur_alloc; } - - template<typename T, typename... Args> - inline owned_ptr<T> make_owned(Args&&... args) + static inline void dec_alloc_stat(size_type size) { - auto *mem = static_cast<P *>(this)->allocate(alignof(T), sizeof(T)); - try - { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto *mema = new (mem) T(std::forward<Args>(args)...); - return owned_ptr<T>(mema, true, deleter_type<T>()); - } - catch (...) - { - static_cast<P *>(this)->deallocate(mem, sizeof(T)); - throw; - } + base_type::instance().m_stat_cur_alloc -= size; } - - template<typename T, typename... Args> - inline T * alloc(Args&&... args) - { - auto *p = static_cast<P *>(this)->allocate(alignof(T), sizeof(T)); - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - return new(p) T(std::forward<Args>(args)...); - } - }; - template <typename P, bool HSD> - struct arena_base<P, HSD, true> : public arena_hsd<P, HSD> + template <typename P> + struct arena_base<P, false, false> : public arena_core<P, false, false> { - template <class T> - using deleter_type = arena_deleter<P, T>; + using size_type = typename arena_core<P, false, false>::size_type; - template <typename T> - using unique_ptr = std::unique_ptr<T, deleter_type<T>>; - - template <typename T> - using owned_ptr = plib::owned_ptr<T, deleter_type<T>>; + size_type cur_alloc() const noexcept { return this->m_stat_cur_alloc; } + size_type max_alloc() const noexcept { return this->m_stat_max_alloc; } - template<typename T, typename... Args> - static inline unique_ptr<T> make_unique(Args&&... args) + inline void inc_alloc_stat(size_type size) { - auto *mem = P::allocate(alignof(T), sizeof(T)); - try - { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto *mema = new (mem) T(std::forward<Args>(args)...); - return unique_ptr<T>(mema, deleter_type<T>()); - } - catch (...) - { - P::deallocate(mem, sizeof(T)); - throw; - } + this->m_stat_cur_alloc += size; + if (this->m_stat_max_alloc < this->m_stat_cur_alloc) + this->m_stat_max_alloc = this->m_stat_cur_alloc; } - - template<typename T, typename... Args> - static inline owned_ptr<T> make_owned(Args&&... args) + inline void dec_alloc_stat(size_type size) { - auto *mem = P::allocate(alignof(T), sizeof(T)); - try - { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto *mema = new (mem) T(std::forward<Args>(args)...); - return owned_ptr<T>(mema, true, deleter_type<T>()); - } - catch (...) - { - P::deallocate(mem, sizeof(T)); - throw; - } - } - - template<typename T, typename... Args> - static inline T * alloc(Args&&... args) - { - auto *p = P::allocate(alignof(T), sizeof(T)); - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - return new(p) T(std::forward<Args>(args)...); + this->m_stat_cur_alloc -= size; } }; - struct aligned_arena : public arena_base<aligned_arena, true, true> { - static inline void *allocate( size_t alignment, size_t size ) + static inline gsl::owner<void *> allocate( size_t alignment, size_t size ) { - m_stat_cur_alloc() += size; - if (m_stat_max_alloc() < m_stat_cur_alloc()) - m_stat_max_alloc() = m_stat_cur_alloc(); + inc_alloc_stat(size); #if (PUSE_ALIGNED_ALLOCATION) #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) @@ -472,7 +422,7 @@ namespace plib { } return p; #else - return aligned_alloc(alignment, size); + return static_cast<gsl::owner<void *>>(aligned_alloc(alignment, size)); #endif #else unused_var(alignment); @@ -480,10 +430,10 @@ namespace plib { #endif } - static inline void deallocate( void *ptr, size_t size ) noexcept + static inline void deallocate(gsl::owner<void *> ptr, size_t size ) noexcept { //unused_var(size); - m_stat_cur_alloc() -= size; + dec_alloc_stat(size); #if (PUSE_ALIGNED_ALLOCATION) // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) ::free(ptr); @@ -504,14 +454,14 @@ namespace plib { { static inline void *allocate( size_t alignment, size_t size ) { - m_stat_cur_alloc() += size; + inc_alloc_stat(size); unused_var(alignment); return ::operator new(size); } static inline void deallocate( void *ptr, size_t size ) noexcept { - m_stat_cur_alloc() -= size; + dec_alloc_stat(size); ::operator delete(ptr); } @@ -522,31 +472,116 @@ namespace plib { } }; - template <typename T, std::size_t ALIGN> - constexpr T *assume_aligned_ptr(T *p) noexcept + namespace detail { - static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)"); - static_assert(is_pow2(ALIGN), "Alignment must be a power of 2"); + template<typename T, typename ARENA, typename... Args> + static inline T * alloc(Args&&... args) + { + auto *mem = ARENA::allocate(alignof(T), sizeof(T)); + try + { + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + return new (mem) T(std::forward<Args>(args)...); + } + catch (...) + { + ARENA::deallocate(mem, sizeof(T)); + throw; + } + } -#if (PUSE_ALIGNED_HINTS) - return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN)); -#else - return p; -#endif + template<typename ARENA, typename T> + static inline void free(T *ptr) noexcept + { + ptr->~T(); + ARENA::deallocate(ptr, sizeof(T)); + } + + template<typename T, typename ARENA, typename... Args> + static inline T * alloc(ARENA &arena, Args&&... args) + { + auto *mem = arena.allocate(alignof(T), sizeof(T)); + try + { + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + return new (mem) T(std::forward<Args>(args)...); + } + catch (...) + { + arena.deallocate(mem, sizeof(T)); + throw; + } + } + + template<typename ARENA, typename T> + static inline void free(ARENA &arena, T *ptr) noexcept + { + ptr->~T(); + arena.deallocate(ptr, sizeof(T)); + } + } // namespace detail + + + + template<typename T, typename ARENA, typename... Args> + static inline + std::enable_if_t<ARENA::has_static_allocator, typename ARENA::template unique_ptr<T>> + make_unique(Args&&... args) + { + using up_type = typename ARENA::template unique_ptr<T>; + using deleter_type = typename ARENA::template deleter_type<T>; + auto *mem = detail::alloc<T, ARENA>(std::forward<Args>(args)...); + return up_type(mem, deleter_type()); } - template <typename T, std::size_t ALIGN> - constexpr const T *assume_aligned_ptr(const T *p) noexcept + template<typename T, typename ARENA, typename... Args> + static inline + std::enable_if_t<!ARENA::has_static_allocator, typename ARENA::template unique_ptr<T>> + make_unique(Args&&... args) { - static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)"); - static_assert(is_pow2(ALIGN), "Alignment must be a power of 2"); -#if (PUSE_ALIGNED_HINTS) - return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN)); -#else - return p; -#endif + return make_unique<T>(ARENA::instance(), std::forward<Args>(args)...); } + template<typename T, typename ARENA, typename... Args> + static inline + typename ARENA::template unique_ptr<T> + make_unique(ARENA &arena, Args&&... args) + { + using up_type = typename ARENA::template unique_ptr<T>; + using deleter_type = typename ARENA::template deleter_type<T>; + auto *mem = detail::alloc<T>(arena, std::forward<Args>(args)...); + return up_type(mem, deleter_type(&arena)); + } + + template<typename T, typename ARENA, typename... Args> + static inline + std::enable_if_t<ARENA::has_static_allocator, typename ARENA::template owned_ptr<T>> + make_owned(Args&&... args) + { + using op_type = typename ARENA::template owned_ptr<T>; + using deleter_type = typename ARENA::template deleter_type<T>; + auto *mem = detail::alloc<T, ARENA>(std::forward<Args>(args)...); + return op_type(mem, true, deleter_type()); + } + + template<typename T, typename ARENA, typename... Args> + static inline + std::enable_if_t<!ARENA::has_static_allocator, typename ARENA::template owned_ptr<T>> + make_owned(Args&&... args) + { + return make_owned<T>(ARENA::instance(), std::forward<Args>(args)...); + } + + template<typename T, typename ARENA, typename... Args> + static inline typename ARENA::template owned_ptr<T> make_owned(ARENA &arena, Args&&... args) + { + using op_type = typename ARENA::template owned_ptr<T>; + using deleter_type = typename ARENA::template deleter_type<T>; + auto *mem = detail::alloc<T>(arena, std::forward<Args>(args)...); + return op_type(mem, true, deleter_type(&arena)); + } + + template <class T, std::size_t ALIGN = alignof(T)> using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>; @@ -557,56 +592,71 @@ namespace plib { PDEFINE_HAS_MEMBER(has_align, align_size); - template <typename T, typename X = void> - struct align_traits + template <typename T, bool X> + struct align_traits_base { + static_assert(!has_align<T>::value, "no align"); static constexpr const std::size_t align_size = alignof(std::max_align_t); static constexpr const std::size_t value_size = sizeof(typename T::value_type); static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size; }; template <typename T> - struct align_traits<T, std::enable_if_t<has_align<T>::value, void>> + struct align_traits_base<T, true> { + static_assert(has_align<T>::value, "no align"); static constexpr const std::size_t align_size = T::align_size; static constexpr const std::size_t value_size = sizeof(typename T::value_type); static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size; }; - //============================================================ - // Aligned vector - //============================================================ + template <typename T> + struct align_traits : public align_traits_base<T, has_align<T>::value> + {}; - // FIXME: needs a separate file - template <typename T, std::size_t ALIGN = PALIGN_VECTOROPT, typename A = aligned_allocator<T, ALIGN>> - class aligned_vector : public std::vector<T, A> + template <typename BASEARENA = aligned_arena, std::size_t PAGESIZE = 1024> + class paged_arena : public arena_base<paged_arena<BASEARENA, PAGESIZE>, true, true> { public: - using base = std::vector<T, A>; - - using reference = typename base::reference; - using const_reference = typename base::const_reference; - using pointer = typename base::pointer; - using const_pointer = typename base::const_pointer; - using size_type = typename base::size_type; + paged_arena() + { + } - using base::base; + PCOPYASSIGNMOVE(paged_arena, delete) - base & as_base() noexcept { return *this; } - const base & as_base() const noexcept { return *this; } + ~paged_arena() = default; - constexpr reference operator[](size_type i) noexcept + static void *allocate(size_t align, size_t size) { - return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i]; + plib::unused_var(align); + //size = ((size + PAGESIZE - 1) / PAGESIZE) * PAGESIZE; + return arena().allocate(PAGESIZE, size); } - constexpr const_reference operator[](size_type i) const noexcept + static void deallocate(void *ptr, size_t size) noexcept { - return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i]; + //size = ((size + PAGESIZE - 1) / PAGESIZE) * PAGESIZE; + arena().deallocate(ptr, size); } - pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); } - const_pointer data() const noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); } + bool operator ==(const paged_arena &rhs) const noexcept { return this == &rhs; } + + static BASEARENA &arena() noexcept { static BASEARENA m_arena; return m_arena; } + private: + }; + + //============================================================ + // Aligned vector + //============================================================ + + // FIXME: needs a separate file + template <typename T, std::size_t ALIGN = PALIGN_VECTOROPT, typename A = paged_arena<>>//aligned_arena> + class aligned_vector : public std::vector<T, typename A::template allocator_type<T, ALIGN>> + { + public: + using base = std::vector<T, typename A::template allocator_type<T, ALIGN>>; + + using base::base; }; diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h index 0d89a56195c..2c2b0fc4270 100644 --- a/src/lib/netlist/plib/parray.h +++ b/src/lib/netlist/plib/parray.h @@ -21,19 +21,20 @@ namespace plib { - template <typename FT, int SIZE> + template <typename FT, int SIZE, typename ARENA> struct sizeabs { - static constexpr std::size_t ABS() noexcept { return (SIZE < 0) ? static_cast<std::size_t>(0 - SIZE) : static_cast<std::size_t>(SIZE); } + static constexpr std::size_t ABS() noexcept { return (SIZE < 0) ? narrow_cast<std::size_t>(0 - SIZE) : narrow_cast<std::size_t>(SIZE); } using container = typename std::array<FT, ABS()> ; }; - template <typename FT> - struct sizeabs<FT, 0> + template <typename FT, typename ARENA> + struct sizeabs<FT, 0, ARENA> { static constexpr std::size_t ABS() noexcept { return 0; } + using allocator_type = typename ARENA::template allocator_type<FT, PALIGN_VECTOROPT>; //using container = typename std::vector<FT, arena_allocator<mempool, FT, 64>>; - using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>; + using container = typename std::vector<FT, allocator_type>; }; /// \brief Array with preallocated or dynamic allocation. @@ -51,17 +52,20 @@ namespace plib { /// I consider > 10% performance difference to be a use case. /// - template <typename FT, int SIZE> + template <typename FT, int SIZE, typename ARENA = aligned_arena> struct parray { public: - static constexpr std::size_t SIZEABS() noexcept { return sizeabs<FT, SIZE>::ABS(); } + static constexpr std::size_t SIZEABS() noexcept { return sizeabs<FT, SIZE, ARENA>::ABS(); } - using base_type = typename sizeabs<FT, SIZE>::container; + using base_type = typename sizeabs<FT, SIZE, ARENA>::container; using size_type = typename base_type::size_type; - using reference = typename base_type::reference; - using const_reference = typename base_type::const_reference; - using value_type = typename base_type::value_type; + using value_type = FT; + using reference = FT &; + using const_reference = const FT &; + + using pointer = FT *; + using const_pointer = const FT *; template <int X = SIZE > parray(size_type size, std::enable_if_t<(X==0), int> = 0) @@ -70,7 +74,7 @@ namespace plib { } template <int X = SIZE > - parray(size_type size, FT val, std::enable_if_t<(X==0), int> = 0) + parray(size_type size, const FT &val, std::enable_if_t<(X==0), int> = 0) : m_a(size, val), m_size(size) { } @@ -85,7 +89,7 @@ namespace plib { } template <int X = SIZE > - parray(size_type size, FT val, std::enable_if_t<(X != 0), int> = 0) noexcept(false) + parray(size_type size, const FT &val, std::enable_if_t<(X != 0), int> = 0) noexcept(false) : m_size(size) { if ((SIZE < 0 && size > SIZEABS()) @@ -131,20 +135,19 @@ namespace plib { constexpr reference operator[](size_type i) noexcept { - return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i]; + return data()[i]; } constexpr const_reference operator[](size_type i) const noexcept { - return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i]; + return data()[i]; } - FT * data() noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); } - const FT * data() const noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); } + pointer data() noexcept { return m_a.data(); } + const_pointer data() const noexcept { return m_a.data(); } private: PALIGNAS_VECTOROPT() base_type m_a; - PALIGNAS_CACHELINE() size_type m_size; }; diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h index feee8a30c3e..4a5e77d9ca2 100644 --- a/src/lib/netlist/plib/pchrono.h +++ b/src/lib/netlist/plib/pchrono.h @@ -9,6 +9,7 @@ /// #include "pconfig.h" +#include "pgsl.h" #include "ptypes.h" #include <chrono> @@ -212,8 +213,8 @@ namespace plib { ctype count() const noexcept { return m_count; } template <typename S> - S as_seconds() const noexcept { return static_cast<S>(total()) - / static_cast<S>(T::per_second()); } + S as_seconds() const noexcept { return narrow_cast<S>(total()) + / narrow_cast<S>(T::per_second()); } guard_t guard() noexcept { return guard_t(*this); } private: @@ -244,7 +245,7 @@ namespace plib { constexpr type total() const noexcept { return 0; } constexpr ctype count() const noexcept { return 0; } template <typename S> - S as_seconds() const noexcept { return static_cast<S>(0.0); } + S as_seconds() const noexcept { return narrow_cast<S>(0); } constexpr static bool enabled = false; guard_t guard() { return guard_t(); } }; diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h index b719139d73f..984ed944acb 100644 --- a/src/lib/netlist/plib/pconfig.h +++ b/src/lib/netlist/plib/pconfig.h @@ -72,10 +72,11 @@ #define PALIGNAS_CACHELINE() PALIGNAS(PALIGN_CACHELINE) #define PALIGNAS_VECTOROPT() PALIGNAS(PALIGN_VECTOROPT) -// FIXME: Breaks mame build on windows due to -Wattribute +// FIXME: Breaks mame build on windows mingw due to -Wattribute // also triggers -Wattribute on ARM +// This is fixed on mingw version 10 // FIXME: no error on cross-compile - need further checks -#if defined(__GNUC__) && (defined(_WIN32) || defined(__arm__) || defined(__ARMEL__)) +#if defined(__GNUC__) && ((defined(_WIN32) && __GNUC__ < 10) || defined(__arm__) || defined(__ARMEL__)) #define PALIGNAS(x) #else #define PALIGNAS(x) alignas(x) @@ -83,7 +84,7 @@ /// \brief nvcc build flag. /// -/// Set this to 1 if you are building with NVIDIA nvcc +/// Set this to 101 if you are building with NVIDIA nvcc 10.1 /// #ifndef NVCCBUILD #define NVCCBUILD (0) @@ -166,5 +167,15 @@ typedef __float128 FLOAT128; #endif #endif +#if (PUSE_FLOAT128) +#if defined(__has_include) +#if !__has_include(<quadmath.h>) +//#pragma message "disabling PUSE_FLOAT128 due to missing quadmath.h" +#undef PUSE_FLOAT128 +#define PUSE_FLOAT128 (0) +#endif +#endif +#endif + #endif // PCONFIG_H_ diff --git a/src/lib/netlist/plib/pdynlib.h b/src/lib/netlist/plib/pdynlib.h index ffb3ae03b99..6fe91953529 100644 --- a/src/lib/netlist/plib/pdynlib.h +++ b/src/lib/netlist/plib/pdynlib.h @@ -31,6 +31,7 @@ namespace plib { template <typename T> T getsym(const pstring &name) const noexcept { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast<T>(getsym_p(name)); } diff --git a/src/lib/netlist/plib/penum.h b/src/lib/netlist/plib/penum.h index 2765e262773..f965411d546 100644 --- a/src/lib/netlist/plib/penum.h +++ b/src/lib/netlist/plib/penum.h @@ -24,7 +24,7 @@ namespace plib // Implementation in putil.cpp. // Putting the code here leads to a performance decrease. static int from_string_int(const pstring &str, const pstring &x); - static pstring nthstr(int n, const pstring &str); + static pstring nthstr(std::size_t n, const pstring &str); }; } // namespace plib @@ -43,7 +43,7 @@ namespace plib constexpr bool operator==(const ename &rhs) const noexcept {return m_v == rhs.m_v;} \ constexpr bool operator==(const E &rhs) const noexcept {return m_v == rhs;} \ pstring name() const { \ - return nthstr(static_cast<int>(m_v), strings()); \ + return nthstr(m_v, strings()); \ } \ private: E m_v; \ static pstring strings() {\ diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp index d332f989321..56ef7f93efb 100644 --- a/src/lib/netlist/plib/pexception.cpp +++ b/src/lib/netlist/plib/pexception.cpp @@ -5,8 +5,8 @@ #include "pfmtlog.h" #include <cfenv> -#include <iostream> #include <cfloat> +#include <iostream> #if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__) #define HAS_FEENABLE_EXCEPT (1) diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp index d776e0133da..ddb9b5dd2e5 100644 --- a/src/lib/netlist/plib/pfmtlog.cpp +++ b/src/lib/netlist/plib/pfmtlog.cpp @@ -92,7 +92,7 @@ pfmt::rtype pfmt::setfmt(std::stringstream &strm, char32_t cfmt_spec) // a.b format here ... char32_t pend(0); int width(0); - if (fmt != "" && pstring("duxofge").find(static_cast<pstring::value_type>(cfmt_spec)) != pstring::npos) + if (!fmt.empty() && pstring("duxofge").find(static_cast<pstring::value_type>(cfmt_spec)) != pstring::npos) { pend = static_cast<char32_t>(fmt.at(fmt.size() - 1)); if (pstring("duxofge").find(static_cast<pstring::value_type>(pend)) == pstring::npos) @@ -113,7 +113,7 @@ pfmt::rtype pfmt::setfmt(std::stringstream &strm, char32_t cfmt_spec) strm << std::setprecision(pstonum_ne_def<int>(fmt.substr(pdot + 1), 6)); width = pstonum_ne_def<int>(left(fmt,pdot), 0); } - else if (fmt != "") + else if (!fmt.empty()) width = pstonum_ne_def<int>(fmt, 0); auto aw(plib::abs(width)); diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h index 793c59bf954..ac2a5e9a747 100644 --- a/src/lib/netlist/plib/pfmtlog.h +++ b/src/lib/netlist/plib/pfmtlog.h @@ -55,7 +55,7 @@ namespace plib { static char32_t fmt_spec() { return 'f'; } static inline void streamify(std::ostream &s, const FLOAT128 &v) { - s << static_cast<long double>(v); + s << narrow_cast<long double>(v); } }; #endif @@ -322,7 +322,7 @@ namespace plib { if (build_enabled && enabled && m_enabled) { pfmt pf(fmt); - static_cast<T *>(this)->vdowrite(xlog(pf, std::forward<Args>(args)...)); + dynamic_cast<T &>(*this).vdowrite(xlog(pf, std::forward<Args>(args)...)); } } @@ -332,7 +332,7 @@ namespace plib { if (build_enabled && m_enabled) { pfmt pf(fmt); - static_cast<const T *>(this)->vdowrite(xlog(pf, std::forward<Args>(args)...)); + static_cast<const T &>(*this).vdowrite(xlog(pf, std::forward<Args>(args)...)); } } diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp index c5e011dfbb9..3a360c7a33f 100644 --- a/src/lib/netlist/plib/pfunction.cpp +++ b/src/lib/netlist/plib/pfunction.cpp @@ -25,26 +25,26 @@ namespace plib { { static std::map<pstring, F> units_si_stat = { - //{ "Y", static_cast<F>(1e24) }, // NOLINT: Yotta - //{ "Z", static_cast<F>(1e21) }, // NOLINT: Zetta - //{ "E", static_cast<F>(1e18) }, // NOLINT: Exa - { "P", static_cast<F>(1e15) }, // NOLINT: Peta - { "T", static_cast<F>(1e12) }, // NOLINT: Tera - { "G", static_cast<F>( 1e9) }, // NOLINT: Giga - { "M", static_cast<F>( 1e6) }, // NOLINT: Mega - { "k", static_cast<F>( 1e3) }, // NOLINT: Kilo - { "h", static_cast<F>( 1e2) }, // NOLINT: Hekto - //{ "da", static_cast<F>(1e1) }, // NOLINT: Deka - { "d", static_cast<F>(1e-1) }, // NOLINT: Dezi - { "c", static_cast<F>(1e-2) }, // NOLINT: Zenti - { "m", static_cast<F>(1e-3) }, // NOLINT: Milli - { "μ", static_cast<F>(1e-6) }, // NOLINT: Mikro - { "n", static_cast<F>(1e-9) }, // NOLINT: Nano - { "p", static_cast<F>(1e-12) }, // NOLINT: Piko - { "f", static_cast<F>(1e-15) }, // NOLINT: Femto - { "a", static_cast<F>(1e-18) }, // NOLINT: Atto - { "z", static_cast<F>(1e-21) }, // NOLINT: Zepto - { "y", static_cast<F>(1e-24) }, // NOLINT: Yokto + //{ "Y", narrow_cast<F>(1e24) }, // NOLINT: Yotta + //{ "Z", narrow_cast<F>(1e21) }, // NOLINT: Zetta + //{ "E", narrow_cast<F>(1e18) }, // NOLINT: Exa + { "P", narrow_cast<F>(1e15) }, // NOLINT: Peta + { "T", narrow_cast<F>(1e12) }, // NOLINT: Tera + { "G", narrow_cast<F>( 1e9) }, // NOLINT: Giga + { "M", narrow_cast<F>( 1e6) }, // NOLINT: Mega + { "k", narrow_cast<F>( 1e3) }, // NOLINT: Kilo + { "h", narrow_cast<F>( 1e2) }, // NOLINT: Hekto + //{ "da", narrow_cast<F>(1e1) }, // NOLINT: Deka + { "d", narrow_cast<F>(1e-1) }, // NOLINT: Dezi + { "c", narrow_cast<F>(1e-2) }, // NOLINT: Zenti + { "m", narrow_cast<F>(1e-3) }, // NOLINT: Milli + { "μ", narrow_cast<F>(1e-6) }, // NOLINT: Mikro + { "n", narrow_cast<F>(1e-9) }, // NOLINT: Nano + { "p", narrow_cast<F>(1e-12) }, // NOLINT: Piko + { "f", narrow_cast<F>(1e-15) }, // NOLINT: Femto + { "a", narrow_cast<F>(1e-18) }, // NOLINT: Atto + { "z", narrow_cast<F>(1e-21) }, // NOLINT: Zepto + { "y", narrow_cast<F>(1e-24) }, // NOLINT: Yokto }; return units_si_stat; } @@ -105,7 +105,7 @@ namespace plib { if (inputs[i] == cmd) { rc.m_cmd = PUSH_INPUT; - rc.m_param = static_cast<NT>(i); + rc.m_param = narrow_cast<NT>(i); stk += 1; break; } @@ -128,7 +128,7 @@ namespace plib { } if (stk < 1) throw pexception(plib::pfmt("pfunction: stack underflow on token <{1}> in <{2}>")(cmd)(expr)); - if (stk >= static_cast<int>(MAX_STACK)) + if (stk >= narrow_cast<int>(MAX_STACK)) throw pexception(plib::pfmt("pfunction: stack overflow on token <{1}> in <{2}>")(cmd)(expr)); m_precompiled.push_back(rc); } @@ -286,7 +286,7 @@ namespace plib { lfsr >>= 1; if (lsb) lfsr ^= 0xB400U; // NOLINT: taps 15, 13, 12, 10 - return static_cast<NT>(lfsr) / static_cast<NT>(0xffffU); // NOLINT + return narrow_cast<NT>(lfsr) / narrow_cast<NT>(0xffffU); // NOLINT } template <typename NT> @@ -297,7 +297,7 @@ namespace plib { lfsr >>= 1; if (lsb) lfsr ^= 0xB400U; // NOLINT: taps 15, 13, 12, 10 - return static_cast<NT>(lfsr); + return narrow_cast<NT>(lfsr); } #define ST1 stack[ptr] @@ -333,7 +333,7 @@ namespace plib { stack[ptr++] = lfsr_random<value_type>(m_lfsr); break; case PUSH_INPUT: - stack[ptr++] = values[static_cast<unsigned>(rc.m_param)]; + stack[ptr++] = values[narrow_cast<unsigned>(rc.m_param)]; break; case PUSH_CONST: stack[ptr++] = rc.m_param; diff --git a/src/lib/netlist/plib/pgsl.h b/src/lib/netlist/plib/pgsl.h new file mode 100644 index 00000000000..ab7798071a5 --- /dev/null +++ b/src/lib/netlist/plib/pgsl.h @@ -0,0 +1,105 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud + +#ifndef PGSL_H_ +#define PGSL_H_ + +/// +/// \file pgsl.h +/// +/// This core guidelines gsl implementation currently provides only enough +/// functionality to syntactically support a very limited number of the +/// gsl specification. +/// +/// Going forward this approach may be extended. +/// + +#include "pconfig.h" +#include "pexception.h" +#include "ptypes.h" + +#include <exception> +#include <type_traits> +#include <utility> + +#if defined(__has_builtin) // clang and gcc 10 + #if __has_builtin(__builtin_unreachable) + #define gsl_Expects(e) ((e) ? static_cast<void>(0) : __builtin_unreachable()) + #endif +#elif defined(__GNUC__) && !(defined( __CUDACC__ ) && defined( __CUDA_ARCH__ )) + #define gsl_Expects(e) ((e) ? static_cast<void>(0) : __builtin_unreachable()) +#elif defined(_MSC_VER) + #define gsl_Expects(e) __assume(e) +#else + #define gsl_Expects(e) ((e) ? static_cast<void>(0) : static_cast<void>(0)) +#endif + +#undef gsl_Expects +#define gsl_Expects(e) do {} while (0) +#define gsl_Ensures(e) gsl_Expects(e) + +namespace plib { + namespace pgsl { + + struct narrowing_error : public std::exception {}; + + template <typename T> + using owner = T; + + template <typename T> + using not_null = T; + + /// \brief perform a narrowing cast without checks + /// + template <typename T, typename O> + inline constexpr T narrow_cast(O && v) noexcept + { + static_assert(plib::is_arithmetic<T>::value && std::is_convertible<std::remove_reference_t<O>, T>::value, "narrow cast expects conversion between arithmetic types"); + return static_cast<T>(std::forward<O>(v)); + } + + /// \brief perform a narrowing cast terminating if loss of precision + /// + /// The c++ core guidelines require the narrow function to raise an error + /// This will make narrow noexcept(false). This has shown to have a + /// measurable impact on performance and thus we deviate we deviate from + /// the standard here. + /// + template <typename T, typename O> + inline T narrow(O && v) noexcept + { + static_assert(plib::is_arithmetic<T>::value && std::is_convertible<std::remove_reference_t<O>, T>::value, "narrow cast expects conversion between arithmetic types"); + + const auto val = static_cast<T>(std::forward<O>(v)); + if( v == static_cast<std::remove_reference_t<O>>(val)) + { + return val; + } + + plib::terminate("narrowing_error"); + // throw narrowing_error(); + } + + } // namespace pgsl + + /// \brief downcast from base tpye to derived type + /// + /// The cpp core guidelines require a very careful use of static cast + /// for downcast operations. This template is used to identify these uses + /// and later for debug builds use dynamic_cast. + /// + template <typename D, typename B> + inline constexpr D downcast(B && b) noexcept + { + static_assert(std::is_pointer<D>::value || std::is_reference<D>::value, "downcast only supports pointers or reference for derived"); + static_assert(std::is_pointer<B>::value || std::is_reference<B>::value, "downcast only supports pointers or reference for base"); + return static_cast<D>(std::forward<B>(b)); + } + + using pgsl::narrow_cast; +} // namespace plib + +//FIXME: This is the place to use more complete implementations +namespace gsl = plib::pgsl; + +#endif // PGSL_H_ diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h index f5151b95011..4e3ddace57e 100644 --- a/src/lib/netlist/plib/plists.h +++ b/src/lib/netlist/plib/plists.h @@ -62,11 +62,13 @@ namespace plib { reference operator[](size_type index) noexcept { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast<reference>(m_buf[index]); } constexpr const_reference operator[](size_type index) const noexcept { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast<const_reference>(m_buf[index]); } @@ -78,13 +80,19 @@ namespace plib { new (&m_buf[index]) C(std::forward<Args>(args)...); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) iterator begin() const noexcept { return reinterpret_cast<iterator>(&m_buf[0]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) iterator end() const noexcept { return reinterpret_cast<iterator>(&m_buf[N]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) iterator begin() noexcept { return reinterpret_cast<iterator>(&m_buf[0]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) iterator end() noexcept { return reinterpret_cast<iterator>(&m_buf[N]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) const_iterator cbegin() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[0]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) const_iterator cend() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[N]); } protected: diff --git a/src/lib/netlist/plib/pmain.cpp b/src/lib/netlist/plib/pmain.cpp index 1e4791adea8..fb428a179fa 100644 --- a/src/lib/netlist/plib/pmain.cpp +++ b/src/lib/netlist/plib/pmain.cpp @@ -29,8 +29,8 @@ namespace plib { int app::main_utfX(int argc, char *argv[]) { std::vector<putf8string> arg; - for (std::size_t i = 0; i < static_cast<std::size_t>(argc); i++) - arg.push_back(putf8string(argv[i])); + for (std::size_t i = 0; i < narrow_cast<std::size_t>(argc); i++) + arg.emplace_back(putf8string(argv[i])); return main_utfX(arg); } @@ -38,8 +38,8 @@ namespace plib { int app::main_utfX(int argc, wchar_t *argv[]) { std::vector<putf8string> arg; - for (std::size_t i = 0; i < static_cast<std::size_t>(argc); i++) - arg.push_back(putf8string(pwstring(argv[i]))); + for (std::size_t i = 0; i < narrow_cast<std::size_t>(argc); i++) + arg.emplace_back(putf8string(pwstring(argv[i]))); return main_utfX(arg); } diff --git a/src/lib/netlist/plib/pmath.h b/src/lib/netlist/plib/pmath.h index 652cff059d2..e70c8f7fd55 100644 --- a/src/lib/netlist/plib/pmath.h +++ b/src/lib/netlist/plib/pmath.h @@ -15,9 +15,7 @@ #include <cmath> #include <type_traits> -#if (PUSE_FLOAT128) -#include <quadmath.h> -#endif +// quadmath.h included by ptypes.h namespace plib { diff --git a/src/lib/netlist/plib/pmatrix2d.h b/src/lib/netlist/plib/pmatrix2d.h index 33e3169c64a..b9a2ebee116 100644..100755 --- a/src/lib/netlist/plib/pmatrix2d.h +++ b/src/lib/netlist/plib/pmatrix2d.h @@ -17,70 +17,102 @@ namespace plib { - template<typename T, typename A = aligned_allocator<T>> + template<typename T, typename A = aligned_arena> class pmatrix2d { public: using size_type = std::size_t; + using arena_type = A; + using allocator_type = typename A::template allocator_type<T>; + + static constexpr const size_type align_size = align_traits<allocator_type>::align_size; + static constexpr const size_type stride_size = align_traits<allocator_type>::stride_size; + using value_type = T; - using allocator_type = A; + using reference = T &; + using const_reference = const T &; + + using pointer = T *; + using const_pointer = const T *; - static constexpr const size_type align_size = align_traits<A>::align_size; - static constexpr const size_type stride_size = align_traits<A>::stride_size; pmatrix2d() noexcept - : m_N(0), m_M(0), m_stride(8), m_v() + : m_N(0), m_M(0), m_stride(8), m_v(nullptr) { } pmatrix2d(size_type N, size_type M) : m_N(N), m_M(M), m_v() { + gsl_Expects(N>0); + gsl_Expects(M>0); m_stride = ((M + stride_size-1) / stride_size) * stride_size; - m_v.resize(N * m_stride); + m_v = m_a.allocate(N * m_stride); + for (std::size_t i = 0; i < N * m_stride; i++) + ::new(&m_v[i]) T(); + } + + ~pmatrix2d() + { + if (m_v != nullptr) + { + for (std::size_t i = 0; i < m_N * m_stride; i++) + (&m_v[i])->~T(); + m_a.deallocate(m_v, m_N * m_stride); + } } void resize(size_type N, size_type M) { + gsl_Expects(N>0); + gsl_Expects(M>0); + if (m_v != nullptr) + { + for (std::size_t i = 0; i < N * m_stride; i++) + (&m_v[i])->~T(); + m_a.deallocate(m_v, N * m_stride); + } m_N = N; m_M = M; m_stride = ((M + stride_size-1) / stride_size) * stride_size; - m_v.resize(N * m_stride); + m_v = m_a.allocate(N * m_stride); + for (std::size_t i = 0; i < N * m_stride; i++) + ::new(&m_v[i]) T(); } - constexpr T * operator[] (size_type row) noexcept + constexpr pointer operator[] (size_type row) noexcept { - return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]); + return &m_v[m_stride * row]; } - constexpr const T * operator[] (size_type row) const noexcept + constexpr const_pointer operator[] (size_type row) const noexcept { - return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]); + return &m_v[m_stride * row]; } - T & operator()(size_type r, size_type c) noexcept + reference operator()(size_type r, size_type c) noexcept { return (*this)[r][c]; } - const T & operator()(size_type r, size_type c) const noexcept + const_reference operator()(size_type r, size_type c) const noexcept { return (*this)[r][c]; } // for compatibility with vrl variant - void set(size_type r, size_type c, const T &v) noexcept + void set(size_type r, size_type c, const value_type &v) noexcept { (*this)[r][c] = v; } - T * data() noexcept + pointer data() noexcept { - return m_v.data(); + return m_v; } - const T * data() const noexcept + const_pointer data() const noexcept { - return m_v.data(); + return m_v; } size_type didx(size_type r, size_type c) const noexcept @@ -93,20 +125,23 @@ namespace plib size_type m_M; size_type m_stride; - std::vector<T, A> m_v; + T * __restrict m_v; + + allocator_type m_a; }; // variable row length matrix - template<typename T, typename A = aligned_allocator<T>> + template<typename T, typename A = aligned_arena> class pmatrix2d_vrl { public: using size_type = std::size_t; using value_type = T; - using allocator_type = A; + using arena_type = A; + using allocator_type = typename A::template allocator_type<T>; - static constexpr const size_type align_size = align_traits<A>::align_size; - static constexpr const size_type stride_size = align_traits<A>::stride_size; + static constexpr const size_type align_size = align_traits<allocator_type>::align_size; + static constexpr const size_type stride_size = align_traits<allocator_type>::stride_size; pmatrix2d_vrl() noexcept : m_N(0), m_M(0), m_v() { @@ -139,24 +174,24 @@ namespace plib return &(m_v[m_row[row]]); } -#if 0 + //FIXME: no check! T & operator()(size_type r, size_type c) noexcept { return (*this)[r][c]; } -#else + void set(size_type r, size_type c, const T &v) noexcept { if (c + m_row[r] >= m_row[r + 1]) { - m_v.insert(m_v.begin() + m_row[r+1], v); + m_v.insert(m_v.begin() + narrow_cast<std::ptrdiff_t>(m_row[r+1]), v); for (size_type i = r + 1; i <= m_N; i++) m_row[i] = m_row[i] + 1; } else (*this)[r][c] = v; } -#endif + //FIXME: no check! const T & operator()(size_type r, size_type c) const noexcept { @@ -184,8 +219,8 @@ namespace plib size_type m_N; size_type m_M; - std::vector<size_type, A> m_row; - std::vector<T, A> m_v; + std::vector<size_type, typename A::template allocator_type<size_type>> m_row; + std::vector<T, allocator_type> m_v; }; diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h index 441595d9e58..ece0f117a8d 100644 --- a/src/lib/netlist/plib/pmempool.h +++ b/src/lib/netlist/plib/pmempool.h @@ -40,31 +40,26 @@ namespace plib { mempool_arena(size_t min_alloc = (1<<21), size_t min_align = PALIGN_CACHELINE) : m_min_alloc(min_alloc) , m_min_align(min_align) + , m_block_align(1024) , m_blocks(base_allocator_type<block *>(m_arena)) { - icount()++; } PCOPYASSIGNMOVE(mempool_arena, delete) ~mempool_arena() { - for (auto & b : m_blocks) { if (b->m_num_alloc != 0) { - plib::perrlogger("Found {} info blocks\n", sinfo().size()); + plib::perrlogger("Found {} info blocks\n", m_info.size()); plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc); } - m_arena.free(b); - //::operator delete(b->m_data); - } - if (icount()-- == 1) - { - if (!sinfo().empty()) - plib::perrlogger("Still found {} info blocks after last mempool deleted\n", sinfo().size()); + detail::free(m_arena, b); } + if (!m_info.empty()) + plib::perrlogger("Still found {} info blocks after mempool deleted\n", m_info.size()); } void *allocate(size_t align, size_t size) @@ -92,21 +87,18 @@ namespace plib { void *ret = reinterpret_cast<void *>(b->m_data + b->m_cur); auto capacity(rs); ret = std::align(align, size, ret, capacity); - sinfo().insert({ ret, info(b, b->m_cur)}); + m_info.insert({ ret, info(b, b->m_cur)}); rs -= (capacity - size); b->m_cur += rs; - base_type::m_stat_cur_alloc() += size; - if (base_type::m_stat_max_alloc() < base_type::m_stat_cur_alloc()) - base_type::m_stat_max_alloc() = base_type::m_stat_cur_alloc(); + this->inc_alloc_stat(size); return ret; } - /*static */ void deallocate(void *ptr, size_t size) noexcept + void deallocate(void *ptr, size_t size) noexcept { - - auto it = sinfo().find(ptr); - if (it == sinfo().end()) + auto it = m_info.find(ptr); + if (it == m_info.end()) plib::terminate("mempool::free - pointer not found"); block *b = it->second.m_block; if (b->m_num_alloc == 0) @@ -115,7 +107,7 @@ namespace plib { { mempool_arena &mp = b->m_mempool; b->m_num_alloc--; - mp.m_stat_cur_alloc() -= size; + mp.dec_alloc_stat(size); if (b->m_num_alloc == 0) { auto itb = std::find(mp.m_blocks.begin(), mp.m_blocks.end(), b); @@ -123,14 +115,15 @@ namespace plib { plib::terminate("mempool::free - block not found"); mp.m_blocks.erase(itb); - m_arena.free(b); + detail::free(mp.base_arena(), b); } - sinfo().erase(it); + m_info.erase(it); } } bool operator ==(const mempool_arena &rhs) const noexcept { return this == &rhs; } + BASEARENA &base_arena() noexcept { return m_arena; } private: struct block { @@ -142,17 +135,19 @@ namespace plib { { min_bytes = std::max(mp.m_min_alloc, min_bytes); m_free = min_bytes; - size_type alloc_bytes = (min_bytes + mp.m_min_align); // - 1); // & ~(mp.m_min_align - 1); + m_bytes_allocated = (min_bytes + mp.m_block_align); // - 1); // & ~(mp.m_min_align - 1); // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - m_data_allocated = new std::uint8_t[alloc_bytes]; + //m_data_allocated = new std::uint8_t[alloc_bytes]; + m_data_allocated = static_cast<std::uint8_t *>(mp.base_arena().allocate(mp.m_block_align, m_bytes_allocated)); void *r = m_data_allocated; - std::align(mp.m_min_align, min_bytes, r, alloc_bytes); + std::align(mp.m_block_align, min_bytes, r, m_bytes_allocated); m_data = reinterpret_cast<std::uint8_t *>(r); } ~block() { //::operator delete(m_data_allocated); - delete [] m_data_allocated; + //delete [] m_data_allocated; + m_mempool.base_arena().deallocate(m_data_allocated, m_bytes_allocated); } block(const block &) = delete; @@ -163,6 +158,7 @@ namespace plib { size_type m_num_alloc; size_type m_free; size_type m_cur; + size_type m_bytes_allocated; std::uint8_t *m_data; std::uint8_t *m_data_allocated; mempool_arena &m_mempool; @@ -180,27 +176,20 @@ namespace plib { block * new_block(size_type min_bytes) { - auto *b = m_arena.template alloc<block>(*this, min_bytes); + auto *b = detail::alloc<block>(m_arena, *this, min_bytes); m_blocks.push_back(b); return b; } - static std::unordered_map<void *, info> &sinfo() - { - static std::unordered_map<void *, info> spinfo; - return spinfo; - } - - static std::size_t &icount() - { - static std::size_t count = 0; - return count; - } - size_t m_min_alloc; size_t m_min_align; + size_t m_block_align; BASEARENA m_arena; + using base_allocator_typex = typename BASEARENA::template allocator_type<std::pair<void * const, info>>; + std::unordered_map<void *, info, std::hash<void *>, std::equal_to<void *>, + base_allocator_typex> m_info; +// std::unordered_map<void *, info> m_info; std::vector<block *, typename BASEARENA::template allocator_type<block *>> m_blocks; }; diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp index 690feb38c61..c22076f6d0c 100644 --- a/src/lib/netlist/plib/poptions.cpp +++ b/src/lib/netlist/plib/poptions.cpp @@ -68,7 +68,7 @@ namespace plib { auto *o = dynamic_cast<option *>(opt); if (o != nullptr) { - if (o->short_opt() == "" && o->long_opt() == "") + if (o->short_opt().empty() && o->long_opt().empty()) { auto *ov = dynamic_cast<option_args *>(o); if (ov != nullptr) @@ -103,7 +103,7 @@ namespace plib { if (!seen_other_args && plib::startsWith(arg, "--")) { auto v = psplit(arg.substr(2),"="); - if (!v.empty() && v[0] != "") + if (!v.empty() && !v[0].empty()) { opt = getopt_long(v[0]); has_equal_arg = (v.size() > 1); @@ -210,11 +210,11 @@ namespace plib { if (auto * const opt = dynamic_cast<option *>(optbase)) { pstring line = ""; - if (opt->short_opt() != "") + if (!opt->short_opt().empty()) line += " -" + opt->short_opt(); - if (opt->long_opt() != "") + if (!opt->long_opt().empty()) { - if (line != "") + if (!line.empty()) line += ", "; else line = " "; @@ -248,7 +248,8 @@ namespace plib { else if (auto *grp = dynamic_cast<option_group *>(optbase)) { ret += "\n" + grp->group() + ":\n"; - if (grp->help() != "") ret += split_paragraphs(grp->help(), width, 4, 4) + "\n\n"; + if (!grp->help().empty()) + ret += split_paragraphs(grp->help(), width, 4, 4) + "\n\n"; } } // FIXME: other help ... @@ -274,7 +275,7 @@ namespace plib { for (const auto & optbase : m_opts) { auto *opt = dynamic_cast<option *>(optbase); - if (opt != nullptr && arg != "" && opt->short_opt() == arg) + if (opt != nullptr && !arg.empty() && opt->short_opt() == arg) return opt; } return nullptr; @@ -284,7 +285,7 @@ namespace plib { for (const auto & optbase : m_opts) { auto *opt = dynamic_cast<option *>(optbase); - if (opt != nullptr && arg !="" && opt->long_opt() == arg) + if (opt != nullptr && !arg.empty() && opt->long_opt() == arg) return opt; } return nullptr; diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h index ba39ba24050..714a357da86 100644 --- a/src/lib/netlist/plib/poptions.h +++ b/src/lib/netlist/plib/poptions.h @@ -136,7 +136,7 @@ namespace plib { if (raw != plib::container::npos) { - m_val = static_cast<T>(raw); + m_val = narrow_cast<T>(raw); return 0; } diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h index 622a295d3dd..8e20ddcf2f1 100644 --- a/src/lib/netlist/plib/ppmf.h +++ b/src/lib/netlist/plib/ppmf.h @@ -159,32 +159,43 @@ namespace plib { if (PMFINTERNAL == 1) { // apply the "this" delta to the object first - // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) + // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult,cppcoreguidelines-pro-type-reinterpret-cast) generic_class *o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); // if the low bit of the vtable index is clear, then it is just a raw function pointer if ((m_function & 1) == 0) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) func = reinterpret_cast<generic_function>(m_function); + } else { // otherwise, it is the byte index into the vtable where the actual function lives + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) func = *reinterpret_cast<generic_function *>(vtable_base + m_function - 1); } object = o_p_delta; } else if (PMFINTERNAL == 2) { - if ((m_this_delta & 1) == 0) { + if ((m_this_delta & 1) == 0) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) func = reinterpret_cast<generic_function>(m_function); } else { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object)); // otherwise, it is the byte index into the vtable where the actual function lives + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) func = *reinterpret_cast<generic_function *>(vtable_base + m_function + m_this_delta - 1); } } @@ -192,8 +203,10 @@ namespace plib { { const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (generic_class::*)()); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) func = reinterpret_cast<generic_function>(m_function); if (m_size == SINGLE_MEMFUNCPTR_SIZE + sizeof(int)) + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); } } @@ -231,8 +244,10 @@ namespace plib { { raw_type mfpo(mftp); generic_function_storage rfunc(nullptr); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto *robject = reinterpret_cast<generic_class *>(object); mfpo.convert_to_generic(rfunc, robject); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return std::make_pair(reinterpret_cast<FunctionType>(rfunc), reinterpret_cast<ObjectType *>(robject)); } template<typename O> @@ -259,6 +274,7 @@ namespace plib { template<typename FunctionType, typename MemberFunctionType, typename ObjectType> static std::pair<FunctionType, ObjectType *> get(MemberFunctionType mftp, ObjectType *object) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return std::make_pair(reinterpret_cast<FunctionType>(mftp), reinterpret_cast<ObjectType *>(object)); } @@ -286,6 +302,7 @@ namespace plib { template<typename FunctionType, typename MemberFunctionType, typename ObjectType> static std::pair<FunctionType, ObjectType *> get(MemberFunctionType mftp, ObjectType *object) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return std::make_pair(reinterpret_cast<FunctionType>(object->*mftp), reinterpret_cast<ObjectType *>(object)); } template<typename O> @@ -315,6 +332,7 @@ namespace plib { pmfp_base() : m_obj(nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto *s = reinterpret_cast<std::uint8_t *>(&m_resolved); std::fill(s, s + sizeof(m_resolved), 0); } @@ -323,6 +341,7 @@ namespace plib { pmfp_base(specific_member_function<O> mftp, O *object) : m_obj(nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto *s = reinterpret_cast<std::uint8_t *>(&m_resolved); std::fill(s, s + sizeof(m_resolved), 0); bind(object, &mftp); @@ -351,6 +370,7 @@ namespace plib { //auto pFunc = *reinterpret_cast<specific_member_function<O> *>(fraw); // mftp; specific_member_function<O> pFunc; static_assert(sizeof(pFunc) >= sizeof(MF), "size error"); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) *reinterpret_cast<MF *>(&pFunc) = *fraw; auto r = helper::template get<member_abi_function<O>>(pFunc, object); @@ -360,18 +380,21 @@ namespace plib { //*reinterpret_cast<member_abi_function<O> *>(&m_resolved) = r.first; reinterpret_copy(r.first, m_resolved); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) m_obj = reinterpret_cast<generic_class *>(r.second); } template<typename O> R call(O *obj, Targs&&... args) const noexcept(true) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return helper::call(reinterpret_cast<member_abi_function<O> *>(&m_resolved), obj, std::forward<Targs>(args)...); } R call(Targs&&... args) const noexcept(true) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return helper::call(reinterpret_cast<const member_abi_function<generic_class> *>(&m_resolved), m_obj, std::forward<Targs>(args)...); } @@ -414,12 +437,13 @@ namespace plib { using static_creator = return_type (*)(const generic_member_function *, generic_class *); - late_pmfp() {} + late_pmfp() = default; template<typename O> late_pmfp(specific_member_function<O> mftp) { static_assert(sizeof(m_raw) >= sizeof(specific_member_function<O>), "size issue"); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) *reinterpret_cast<specific_member_function<O> *>(&m_raw) = mftp; m_creator = creator<O>; } @@ -427,6 +451,7 @@ namespace plib { template<typename O> return_type operator()(O *object) const { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return m_creator(&m_raw, reinterpret_cast<generic_class *>(object)); } @@ -435,7 +460,9 @@ namespace plib { template <typename O> static return_type creator(const generic_member_function *raw, generic_class *obj) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto p = reinterpret_cast<const specific_member_function<O> *>(raw); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto o = reinterpret_cast<O *>(obj); return return_type(*p, o); } diff --git a/src/lib/netlist/plib/ppreprocessor.cpp b/src/lib/netlist/plib/ppreprocessor.cpp index f13d3aeef43..b563576c6a8 100644 --- a/src/lib/netlist/plib/ppreprocessor.cpp +++ b/src/lib/netlist/plib/ppreprocessor.cpp @@ -461,7 +461,7 @@ namespace plib { m_if_level++; lt = replace_macros(lt); simple_iter<ppreprocessor> t(this, tokenize(lt.substr(3), m_expr_sep, true, true)); - auto val = static_cast<int>(prepro_expr(t, 255)); + auto val = narrow_cast<int>(prepro_expr(t, 255)); t.skip_ws(); if (!t.eod()) error("found unprocessed content at end of line"); @@ -489,7 +489,7 @@ namespace plib { m_if_flag ^= (1 << m_if_level); lt = replace_macros(lt); simple_iter<ppreprocessor> t(this, tokenize(lt.substr(5), m_expr_sep, true, true)); - auto val = static_cast<int>(prepro_expr(t, 255)); + auto val = narrow_cast<int>(prepro_expr(t, 255)); t.skip_ws(); if (!t.eod()) error("found unprocessed content at end of line"); @@ -559,7 +559,7 @@ namespace plib { auto *prevdef = get_define(n); if (lti.size() == 2) { - if (prevdef != nullptr && prevdef->m_replace != "") + if (prevdef != nullptr && !prevdef->m_replace.empty()) error("redefinition of " + n); m_defines.insert({n, define_t(n, "")}); } diff --git a/src/lib/netlist/plib/ppreprocessor.h b/src/lib/netlist/plib/ppreprocessor.h index 115f344cc69..467db358264 100644 --- a/src/lib/netlist/plib/ppreprocessor.h +++ b/src/lib/netlist/plib/ppreprocessor.h @@ -95,14 +95,14 @@ namespace plib { if (this->gptr() == this->egptr()) { // clang reports sign error - weird - std::size_t bytes = m_strm->m_outbuf.size() - static_cast<std::size_t>(m_strm->m_pos); + std::size_t bytes = m_strm->m_outbuf.size() - narrow_cast<std::size_t>(m_strm->m_pos); if (bytes > m_buf.size()) bytes = m_buf.size(); std::copy(m_strm->m_outbuf.c_str() + m_strm->m_pos, m_strm->m_outbuf.c_str() + m_strm->m_pos + bytes, m_buf.data()); this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes); - m_strm->m_pos += static_cast<long>(bytes); + m_strm->m_pos += narrow_cast<long>(bytes); } return this->gptr() == this->egptr() diff --git a/src/lib/netlist/plib/prandom.h b/src/lib/netlist/plib/prandom.h index 65cdb3e1cf2..b2f9c89a9cf 100644 --- a/src/lib/netlist/plib/prandom.h +++ b/src/lib/netlist/plib/prandom.h @@ -9,6 +9,7 @@ /// #include "pconfig.h" +#include "pgsl.h" #include "pmath.h" #include "ptypes.h" @@ -50,7 +51,7 @@ namespace plib seed(5489); } - static constexpr T min() noexcept { return static_cast<T>(0); } + static constexpr T min() noexcept { return T(0); } static constexpr T max() noexcept { return ~T(0) >> (sizeof(T)*8 - w); } template <typename ST> @@ -103,7 +104,7 @@ namespace plib void twist() { const T lowest_w(~T(0) >> (sizeof(T)*8 - w)); - const T lower_mask((static_cast<T>(1) << r) - 1); // That is, the binary number of r 1's + const T lower_mask((T(1) << r) - 1); // That is, the binary number of r 1's const T upper_mask((~lower_mask) & lowest_w); for (std::size_t i=0; i<N; i++) @@ -122,10 +123,10 @@ namespace plib template <typename FT, typename T> FT normalize_uniform(T &p, FT m = constants<FT>::one(), FT b = constants<FT>::zero()) { - const auto mmin(static_cast<FT>(p.min())); - const auto mmax(static_cast<FT>(p.max())); + const auto mmin(narrow_cast<FT>(p.min())); + const auto mmax(narrow_cast<FT>(p.max())); // -> 0 to a - return (static_cast<FT>(p())- mmin) / (mmax - mmin) * m - b; + return (narrow_cast<FT>(p())- mmin) / (mmax - mmin) * m - b; } template<typename FT> diff --git a/src/lib/netlist/plib/pstonum.h b/src/lib/netlist/plib/pstonum.h index 630dee68422..c4bf692d177 100644 --- a/src/lib/netlist/plib/pstonum.h +++ b/src/lib/netlist/plib/pstonum.h @@ -10,6 +10,7 @@ #include "pconfig.h" #include "pexception.h" +#include "pgsl.h" #include "pmath.h" // for pstonum #include "pstring.h" @@ -36,9 +37,9 @@ namespace plib if (ss >> x) { auto pos(ss.tellg()); - if (pos == static_cast<decltype(pos)>(-1)) + if (pos == decltype(pos)(-1)) pos = len; - *idx = static_cast<std::size_t>(pos); + *idx = narrow_cast<std::size_t>(pos); } else *idx = constants<std::size_t>::zero(); @@ -88,7 +89,7 @@ namespace plib template <typename S> FLOAT128 operator()(std::locale loc, const S &arg, std::size_t *idx) { - return static_cast<FLOAT128>(pstonum_locale<long double>(loc, arg, idx)); + return narrow_cast<FLOAT128>(pstonum_locale<long double>(loc, arg, idx)); } }; #endif @@ -100,8 +101,8 @@ namespace plib std::size_t idx(0); auto ret = pstonum_helper<T>()(loc, cstr, &idx); using ret_type = decltype(ret); - if (ret >= static_cast<ret_type>(plib::numeric_limits<T>::lowest()) - && ret <= static_cast<ret_type>(plib::numeric_limits<T>::max())) + if (ret >= narrow_cast<ret_type>(plib::numeric_limits<T>::lowest()) + && ret <= narrow_cast<ret_type>(plib::numeric_limits<T>::max())) { if (cstr[idx] != 0) throw pexception(pstring("Continuation after numeric value ends: ") + pstring(cstr)); @@ -110,7 +111,7 @@ namespace plib { throw pexception(pstring("Out of range: ") + pstring(cstr)); } - return static_cast<T>(ret); + return narrow_cast<T>(ret); } template<typename R, typename T> diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h index c47bd71ab1e..b96c1f91a3b 100644 --- a/src/lib/netlist/plib/pstream.h +++ b/src/lib/netlist/plib/pstream.h @@ -18,10 +18,10 @@ #include <array> #include <fstream> +#include <fstream> #include <ios> #include <iostream> #include <sstream> -#include <fstream> #include <type_traits> #include <vector> @@ -204,7 +204,7 @@ public: { const auto sz(static_cast<std::streamsize>(val.size())); write(sz); - m_strm.write(reinterpret_cast<const std::ostream::char_type *>(val.data()), sz * static_cast<std::streamsize>(sizeof(T))); + m_strm.write(reinterpret_cast<const std::ostream::char_type *>(val.data()), sz * gsl::narrow<std::streamsize>(sizeof(T))); } private: @@ -225,7 +225,7 @@ public: template <typename T> void read(T &val) { - m_strm.read(reinterpret_cast<std::istream::char_type *>(&val), sizeof(T)); + m_strm.read(reinterpret_cast<std::istream::char_type *>(&val), gsl::narrow<std::streamsize>(sizeof(T))); } void read( pstring &s) @@ -244,7 +244,7 @@ public: std::size_t sz = 0; read(sz); val.resize(sz); - m_strm.read(reinterpret_cast<std::istream::char_type *>(val.data()), static_cast<std::streamsize>(sizeof(T) * sz)); + m_strm.read(reinterpret_cast<std::istream::char_type *>(val.data()), gsl::narrow<std::streamsize>(sizeof(T) * sz)); } private: diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp index 5d26ed984aa..b0dc3d313c6 100644 --- a/src/lib/netlist/plib/pstring.cpp +++ b/src/lib/netlist/plib/pstring.cpp @@ -27,7 +27,7 @@ int pstring_t<F>::compare(const pstring_t &right) const noexcept } if (si != this->end() && ri != right.end()) - return static_cast<int>(*si) - static_cast<int>(*ri); + return plib::narrow_cast<int>(*si) - plib::narrow_cast<int>(*ri); if (this->mem_t_size() > right.mem_t_size()) return 1; if (this->mem_t_size() < right.mem_t_size()) @@ -45,8 +45,8 @@ pstring_t<F> pstring_t<F>::substr(size_type start, size_type nlen) const { if (nlen == npos || start + nlen > l) nlen = l - start; - auto ps = std::next(begin(), static_cast<difference_type>(start)); - auto pe = std::next(ps, static_cast<difference_type>(nlen)); + auto ps = std::next(begin(), plib::narrow_cast<difference_type>(start)); + auto pe = std::next(ps, plib::narrow_cast<difference_type>(nlen)); ret.m_str.assign(ps.p, pe.p); } return ret; diff --git a/src/lib/netlist/plib/pstrutil.h b/src/lib/netlist/plib/pstrutil.h index 651e5bfd558..2b79935dc3a 100644 --- a/src/lib/netlist/plib/pstrutil.h +++ b/src/lib/netlist/plib/pstrutil.h @@ -8,6 +8,7 @@ /// \file pstrutil.h /// +#include "pgsl.h" #include "pstring.h" #include "ptypes.h" @@ -157,13 +158,13 @@ namespace plib template<typename T, typename TA> bool startsWith(const T &str, const TA &arg) { - return startsWith(str, static_cast<pstring>(arg)); + return startsWith(str, static_cast<T>(arg)); } template<typename T, typename TA> bool endsWith(const T &str, const TA &arg) { - return endsWith(str, static_cast<pstring>(arg)); + return endsWith(str, static_cast<T>(arg)); } template<typename T> @@ -172,7 +173,7 @@ namespace plib const T *p = str; while (*p != 0) p++; - return static_cast<std::size_t>(p - str); + return narrow_cast<std::size_t>(p - str); } template<typename T> diff --git a/src/lib/netlist/plib/ptimed_queue.h b/src/lib/netlist/plib/ptimed_queue.h index 191657b60c0..f257580c726 100644 --- a/src/lib/netlist/plib/ptimed_queue.h +++ b/src/lib/netlist/plib/ptimed_queue.h @@ -210,7 +210,7 @@ namespace plib { // save state support & mame disasm const T *listptr() const noexcept { return &m_list[1]; } - std::size_t size() const noexcept { return static_cast<std::size_t>(m_end - &m_list[1]); } + std::size_t size() const noexcept { return narrow_cast<std::size_t>(m_end - &m_list[1]); } const T & operator[](std::size_t index) const noexcept { return m_list[ 1 + index]; } private: using mutex_type = pspin_mutex<TS>; diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h index ef3dd724388..fdeeb69eca4 100644 --- a/src/lib/netlist/plib/ptypes.h +++ b/src/lib/netlist/plib/ptypes.h @@ -15,8 +15,12 @@ #include <type_traits> #if (PUSE_FLOAT128) +#if defined(__has_include) +#if __has_include(<quadmath.h>) #include <quadmath.h> #endif +#endif +#endif // noexcept on move operator -> issue with macosx clang #define PCOPYASSIGNMOVE(name, def) \ @@ -273,7 +277,7 @@ namespace plib template <typename T> class name \ { \ template <typename U> static long test(decltype(&U:: member)); \ - template <typename U> static char test(...); \ + template <typename U> static char test(...); \ public: \ static constexpr const bool value = sizeof(test<T>(nullptr)) == sizeof(long); \ } diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp index 9cc6e5ec9ae..60eab248c9d 100644 --- a/src/lib/netlist/plib/putil.cpp +++ b/src/lib/netlist/plib/putil.cpp @@ -3,9 +3,9 @@ #include "putil.h" #include "penum.h" +#include "pstream.h" #include "pstrutil.h" #include "ptypes.h" -#include "pstream.h" #include <algorithm> #include <cstdlib> // needed for getenv ... @@ -22,7 +22,7 @@ namespace plib { auto p=find_last_of(filename, pstring(PATH_SEPS)); pstring ret = (p == pstring::npos) ? filename : filename.substr(p+1); - if (suffix != "" && endsWith(ret, suffix)) + if (!suffix.empty() && endsWith(ret, suffix)) return ret.substr(0, ret.length() - suffix.length()); return ret; } @@ -49,7 +49,7 @@ namespace plib pstring ret = ""; for( const auto &elem : list ) { - if (ret == "") + if (ret.empty()) ret = elem; else ret += (PATH_SEP + elem); @@ -126,7 +126,7 @@ namespace plib auto i = str.begin(); while (i != str.end()) { - auto p = static_cast<std::size_t>(-1); + auto p = pstring::npos; for (std::size_t j=0; j < onstrl.size(); j++) { if (std::equal(onstrl[j].begin(), onstrl[j].end(), i)) @@ -135,14 +135,14 @@ namespace plib break; } } - if (p != static_cast<std::size_t>(-1)) + if (p != pstring::npos) { - if (col != "") + if (!col.empty()) ret.push_back(col); col = ""; ret.push_back(onstrl[p]); - i = std::next(i, static_cast<pstring::difference_type>(onstrl[p].length())); + i = std::next(i, narrow_cast<pstring::difference_type>(onstrl[p].length())); } else { @@ -151,7 +151,7 @@ namespace plib i++; } } - if (col != "") + if (!col.empty()) ret.push_back(col); return ret; @@ -170,8 +170,8 @@ namespace plib return -1; } - pstring penum_base::nthstr(int n, const pstring &str) + pstring penum_base::nthstr(std::size_t n, const pstring &str) { - return psplit(str, ",", false)[static_cast<std::size_t>(n)]; + return psplit(str, ",", false)[n]; } } // namespace plib diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h index 8ceec3d7151..dde1918ebaf 100644 --- a/src/lib/netlist/plib/putil.h +++ b/src/lib/netlist/plib/putil.h @@ -14,8 +14,8 @@ #include <algorithm> #include <initializer_list> -#include <vector> #include <sstream> +#include <vector> #define PSTRINGIFY_HELP(y) # y #define PSTRINGIFY(x) PSTRINGIFY_HELP(x) @@ -262,7 +262,9 @@ namespace plib void reinterpret_copy(S &s, D &d) { static_assert(sizeof(D) >= sizeof(S), "size mismatch"); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto *dp = reinterpret_cast<std::uint8_t *>(&d); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) const auto *sp = reinterpret_cast<std::uint8_t *>(&s); std::copy(sp, sp + sizeof(S), dp); } @@ -290,14 +292,14 @@ namespace plib { auto it = std::find(con.begin(), con.end(), elem); if (it != con.end()) - return static_cast<std::size_t>(it - con.begin()); + return narrow_cast<std::size_t>(it - con.begin()); return npos; } template <class C> void insert_at(C &con, const std::size_t index, const typename C::value_type &elem) { - con.insert(con.begin() + static_cast<std::ptrdiff_t>(index), elem); + con.insert(con.begin() + narrow_cast<std::ptrdiff_t>(index), elem); } template <class C> @@ -336,7 +338,7 @@ namespace plib { std::size_t result = 5381; // NOLINT for (const T* p = buf; p != buf + size; p++) - result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ static_cast<std::size_t>(*p); // NOLINT + result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ narrow_cast<std::size_t>(*p); // NOLINT return result; } diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp index 10a6f19a454..a7eaa6927a9 100644 --- a/src/lib/netlist/prg/nltool.cpp +++ b/src/lib/netlist/prg/nltool.cpp @@ -206,7 +206,7 @@ public: return stream_ptr(nullptr); strm->imbue(std::locale::classic()); - return std::move(strm); // FIXME: for c++11 clang builds; + return strm; } private: @@ -225,14 +225,14 @@ public: netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const override { if (m_boostlib == "builtin") - return netlist::host_arena::make_unique<plib::dynlib_static>(nl_static_solver_syms); + return plib::make_unique<plib::dynlib_static, netlist::host_arena>(nl_static_solver_syms); if (m_boostlib == "generic") - return netlist::host_arena::make_unique<plib::dynlib_static>(nullptr); + return plib::make_unique<plib::dynlib_static, netlist::host_arena>(nullptr); if (NL_DISABLE_DYNAMIC_LOAD) throw netlist::nl_exception("Dynamic library loading not supported due to project security concerns."); //pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"})); - return netlist::host_arena::make_unique<plib::dynlib>(m_boostlib); + return plib::make_unique<plib::dynlib, netlist::host_arena>(m_boostlib); } private: @@ -245,7 +245,7 @@ class netlist_tool_t : public netlist::netlist_state_t public: netlist_tool_t(tool_app_t &app, const pstring &name, const pstring &boostlib) - : netlist::netlist_state_t(name, netlist::host_arena::make_unique<netlist_tool_callbacks_t>(app, boostlib)) + : netlist::netlist_state_t(name, plib::make_unique<netlist_tool_callbacks_t, netlist::host_arena>(app, boostlib)) { } @@ -364,13 +364,13 @@ struct input_t case netlist::param_t::POINTER: throw netlist::nl_exception(plib::pfmt("param {1} is not numeric\n")(m_param.param().name())); case netlist::param_t::DOUBLE: - static_cast<netlist::param_fp_t*>(&m_param.param())->set(m_value); + plib::downcast<netlist::param_fp_t &>(m_param.param()).set(m_value); break; case netlist::param_t::INTEGER: - static_cast<netlist::param_int_t*>(&m_param.param())->set(static_cast<int>(m_value)); + plib::downcast<netlist::param_int_t &>(m_param.param()).set(static_cast<int>(m_value)); break; case netlist::param_t::LOGIC: - static_cast<netlist::param_logic_t*>(&m_param.param())->set(static_cast<bool>(m_value)); + plib::downcast<netlist::param_logic_t &>(m_param.param()).set(static_cast<bool>(m_value)); break; } } @@ -383,7 +383,7 @@ struct input_t static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstring &fname) { std::vector<input_t> ret; - if (fname != "") + if (!fname.empty()) { plib::putf8_reader r = plib::putf8_reader(std::make_unique<plib::ifstream>(plib::filesystem::u8path(fname))); if (r.stream().fail()) @@ -392,7 +392,7 @@ static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstr pstring l; while (r.readline(l)) { - if (l != "") + if (!l.empty()) { input_t inp(setup, l); ret.push_back(inp); @@ -724,7 +724,7 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id) if (plib::startsWith(l, "//-")) { l = plib::trim(l.substr(3)); - if (l != "") + if (!l.empty()) { auto a(plib::psplit(l, ":", true)); if (a.empty() || (a.size() > 2)) @@ -821,7 +821,7 @@ void tool_app_t::header_entry(const netlist::factory::element_t *e) avs += ", " + s.substr(1); mac_out("// usage : " + e->name() + "(name" + vs + ")", false); - if (avs != "") + if (!avs.empty()) mac_out("// auto connect: " + avs.substr(2), false); mac_out("#define " + e->name() + "(...)"); @@ -945,7 +945,7 @@ void tool_app_t::create_docheader() { auto d(read_docsrc(e->source().file_name(), e->name())); - if (d.id != "") + if (!d.id.empty()) { pout("//! [{1} csynopsis]\n", e->name()); header_entry(e.get()); @@ -967,7 +967,7 @@ void tool_app_t::create_docheader() { //auto d(read_docsrc(e->source().file_name(), e->name())); - if (d.id != "") + if (!d.id.empty()) { poutprefix("///", ""); @@ -1020,7 +1020,7 @@ void tool_app_t::create_docheader() poutprefix("///", ""); poutprefix("///", " @section {}_4 Function Table", d.id); poutprefix("///", ""); - if (d.functiontable == "") + if (!d.functiontable.empty()) poutprefix("///", " Please refer to the datasheet."); else poutprefix("///", " {}", d.functiontable); diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp index 9e3ba795554..2317495c677 100755 --- a/src/lib/netlist/prg/nlwav.cpp +++ b/src/lib/netlist/prg/nlwav.cpp @@ -655,10 +655,10 @@ void nlwav_app::convert_wav(std::ostream &ostrm, wav_t::format fmt) double dt = plib::reciprocal(static_cast<double>(opt_rate())); auto nchan = m_instrms.size(); - auto wo = arena::make_unique<wavwriter>(ostrm, opt_out() != "-", fmt, nchan, opt_rate(), opt_amp()); - auto ago = arena::make_unique<aggregator>(nchan, dt, aggregator::callback_type(&wavwriter::process, wo.get())); - auto fgo_hp = arena::make_unique<filter_hp>(opt_highpass(), opt_hpboost(), nchan, filter_hp::callback_type(&aggregator::process, ago.get())); - auto fgo_lp = arena::make_unique<filter_lp>(opt_lowpass(), nchan, filter_lp::callback_type(&filter_hp::process, fgo_hp.get())); + auto wo = plib::make_unique<wavwriter, arena>(ostrm, opt_out() != "-", fmt, nchan, opt_rate(), opt_amp()); + auto ago = plib::make_unique<aggregator, arena>(nchan, dt, aggregator::callback_type(&wavwriter::process, wo.get())); + auto fgo_hp = plib::make_unique<filter_hp, arena>(opt_highpass(), opt_hpboost(), nchan, filter_hp::callback_type(&aggregator::process, ago.get())); + auto fgo_lp = plib::make_unique<filter_lp, arena>(opt_lowpass(), nchan, filter_lp::callback_type(&filter_hp::process, fgo_hp.get())); auto topcb = log_processor::callback_type(&filter_lp::process, fgo_lp.get()); @@ -680,7 +680,7 @@ void nlwav_app::convert_wav(std::ostream &ostrm, wav_t::format fmt) void nlwav_app::convert_vcd(std::ostream &ostrm, vcdwriter::format_e format) { - arena::unique_ptr<vcdwriter> wo = arena::make_unique<vcdwriter>(ostrm, opt_args(), + arena::unique_ptr<vcdwriter> wo = plib::make_unique<vcdwriter, arena>(ostrm, opt_args(), format, opt_high(), opt_low()); log_processor::callback_type agcb = log_processor::callback_type(&vcdwriter::process, wo.get()); @@ -702,7 +702,7 @@ void nlwav_app::convert_vcd(std::ostream &ostrm, vcdwriter::format_e format) void nlwav_app::convert_tab(std::ostream &ostrm) { - auto wo = arena::make_unique<tabwriter>(ostrm, opt_args(), + auto wo = plib::make_unique<tabwriter, arena>(ostrm, opt_args(), opt_start(), opt_inc(), opt_samples()); log_processor::callback_type agcb = log_processor::callback_type(&tabwriter::process, wo.get()); diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index aeb5d11055f..87ae2de71d7 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -121,7 +121,7 @@ namespace solver { pstring nname(this->name() + "." + pstring(plib::pfmt("m{1}")(m_inps.size()))); nl_assert(p->net().is_analog()); - auto net_proxy_output_u = state().make_pool_object<proxied_analog_output_t>(*this, nname, static_cast<analog_net_t *>(&p->net())); + auto net_proxy_output_u = state().make_pool_object<proxied_analog_output_t>(*this, nname, &dynamic_cast<analog_net_t &>(p->net())); net_proxy_output = net_proxy_output_u.get(); m_inps.emplace_back(std::move(net_proxy_output_u)); } @@ -432,7 +432,7 @@ namespace solver void matrix_solver_t::step(netlist_time delta) noexcept { - const auto dd(delta.as_fp<nl_fptype>()); + const auto dd(delta.as_fp<fptype>()); for (auto &d : m_step_funcs) d(dd); } @@ -489,7 +489,7 @@ namespace solver if (m_params.m_dynamic_ts) - return compute_next_timestep(delta.as_fp<nl_fptype>(), m_params.m_max_timestep); + return compute_next_timestep(delta.as_fp<fptype>(), m_params.m_max_timestep); return netlist_time::from_fp(m_params.m_max_timestep); } @@ -534,7 +534,7 @@ namespace solver return {colmax, colmin}; } - nl_fptype matrix_solver_t::get_weight_around_diag(std::size_t row, std::size_t diag) + matrix_solver_t::fptype matrix_solver_t::get_weight_around_diag(std::size_t row, std::size_t diag) { { // @@ -543,7 +543,7 @@ namespace solver std::vector<bool> touched(1024, false); // FIXME! - nl_fptype weight = nlconst::zero(); + fptype weight = nlconst::zero(); auto &term = m_terms[row]; for (std::size_t i = 0; i < term.count(); i++) { @@ -556,7 +556,7 @@ namespace solver if (colu==row) colu = static_cast<unsigned>(diag); else if (colu==diag) colu = static_cast<unsigned>(row); - weight = weight + plib::abs(static_cast<nl_fptype>(colu) - static_cast<nl_fptype>(diag)); + weight = weight + plib::abs(static_cast<fptype>(colu) - static_cast<fptype>(diag)); touched[colu] = true; } } @@ -596,14 +596,14 @@ namespace solver log().verbose(" has {1} dynamic elements", this->dynamic_device_count()); log().verbose(" has {1} timestep elements", this->timestep_device_count()); log().verbose(" {1:6.3} average newton raphson loops", - static_cast<nl_fptype>(this->m_stat_newton_raphson) / static_cast<nl_fptype>(this->m_stat_vsolver_calls)); + static_cast<fptype>(this->m_stat_newton_raphson) / static_cast<fptype>(this->m_stat_vsolver_calls)); log().verbose(" {1:10} invocations ({2:6.0} Hz) {3:10} gs fails ({4:6.2} %) {5:6.3} average", this->m_stat_calculations, - static_cast<nl_fptype>(this->m_stat_calculations) / this->exec().time().as_fp<nl_fptype>(), + static_cast<fptype>(this->m_stat_calculations) / this->exec().time().as_fp<fptype>(), this->m_iterative_fail, - nlconst::hundred() * static_cast<nl_fptype>(this->m_iterative_fail) - / static_cast<nl_fptype>(this->m_stat_calculations), - static_cast<nl_fptype>(this->m_iterative_total) / static_cast<nl_fptype>(this->m_stat_calculations)); + nlconst::hundred() * static_cast<fptype>(this->m_iterative_fail) + / static_cast<fptype>(this->m_stat_calculations), + static_cast<fptype>(this->m_iterative_total) / static_cast<fptype>(this->m_stat_calculations)); } } diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h index 606ccbb9ee2..6a769775248 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.h +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -14,6 +14,7 @@ #include "netlist/plib/palloc.h" #include "netlist/plib/penum.h" #include "netlist/plib/pmatrix2d.h" +#include "netlist/plib/pmempool.h" #include "netlist/plib/putil.h" #include "netlist/plib/vector_ops.h" @@ -183,6 +184,8 @@ namespace solver { public: using list_t = std::vector<matrix_solver_t *>; + using fptype = nl_fptype; + using arena_type = plib::mempool_arena<plib::aligned_arena>; // after every call to solve, update inputs must be called. // this can be done as well as a batch to ease parallel processing. @@ -259,57 +262,31 @@ namespace solver } // return number of floating point operations for solve - std::size_t ops() const { return m_ops; } + constexpr std::size_t ops() const { return m_ops; } protected: - template <typename T> - using aligned_alloc = plib::aligned_allocator<T, PALIGN_VECTOROPT>; - matrix_solver_t(netlist_state_t &anetlist, const pstring &name, const analog_net_t::list_t &nets, const solver_parameters_t *params); virtual void vsolve_non_dynamic() = 0; - virtual netlist_time compute_next_timestep(nl_fptype cur_ts, nl_fptype max_ts) = 0; - virtual bool check_err() = 0; + virtual netlist_time compute_next_timestep(fptype cur_ts, fptype max_ts) = 0; + virtual bool check_err() const = 0; virtual void store() = 0; -#if 0 - plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_gonn; - plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_gtn; - plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_Idrn; - plib::pmatrix2d<nl_fptype *, aligned_alloc<nl_fptype *>> m_connected_net_Vn; -#else - plib::pmatrix2d_vrl<nl_fptype, aligned_alloc<nl_fptype>> m_gonn; - plib::pmatrix2d_vrl<nl_fptype, aligned_alloc<nl_fptype>> m_gtn; - plib::pmatrix2d_vrl<nl_fptype, aligned_alloc<nl_fptype>> m_Idrn; - plib::pmatrix2d_vrl<nl_fptype *, aligned_alloc<nl_fptype *>> m_connected_net_Vn; -#endif - - plib::aligned_vector<terms_for_net_t> m_terms; + plib::pmatrix2d_vrl<fptype, arena_type> m_gonn; + plib::pmatrix2d_vrl<fptype, arena_type> m_gtn; + plib::pmatrix2d_vrl<fptype, arena_type> m_Idrn; + plib::pmatrix2d_vrl<fptype *, arena_type> m_connected_net_Vn; const solver_parameters_t &m_params; state_var<std::size_t> m_iterative_fail; state_var<std::size_t> m_iterative_total; - private: - - plib::aligned_vector<terms_for_net_t> m_rails_temp; - std::vector<device_arena::unique_ptr<proxied_analog_output_t>> m_inps; - - state_var<std::size_t> m_stat_calculations; - state_var<std::size_t> m_stat_newton_raphson; - state_var<std::size_t> m_stat_vsolver_calls; - - state_var<netlist_time_ext> m_last_step; - plib::aligned_vector<nldelegate_ts> m_step_funcs; - plib::aligned_vector<nldelegate_dyn> m_dynamic_funcs; + plib::aligned_vector<terms_for_net_t> m_terms; // setup only - logic_input_t m_fb_sync; - logic_output_t m_Q_sync; - - std::size_t m_ops; + private: // base setup - called from constructor void setup_base(setup_t &setup, const analog_net_t::list_t &nets) noexcept(false); @@ -321,7 +298,7 @@ namespace solver int get_net_idx(const analog_net_t *net) const noexcept; std::pair<int, int> get_left_right_of_diag(std::size_t irow, std::size_t idiag); - nl_fptype get_weight_around_diag(std::size_t row, std::size_t diag); + fptype get_weight_around_diag(std::size_t row, std::size_t diag); void add_term(std::size_t net_idx, terminal_t *term) noexcept(false); @@ -332,272 +309,21 @@ namespace solver analog_net_t *get_connected_net(terminal_t *term); - }; - - template <typename FT, int SIZE> - class matrix_solver_ext_t: public matrix_solver_t - { - public: - - using float_type = FT; - - matrix_solver_ext_t(netlist_state_t &anetlist, const pstring &name, - const analog_net_t::list_t &nets, - const solver_parameters_t *params, const std::size_t size) - : matrix_solver_t(anetlist, name, nets, params) - , m_dim(size) - , m_new_V(size) - , m_RHS(size) - , m_mat_ptr(size, this->max_railstart() + 1) - , m_last_V(size, nlconst::zero()) - , m_DD_n_m_1(size, nlconst::zero()) - , m_h_n_m_1(size, nlconst::magic(1e-6)) // we need a non zero value here - { - // - // save states - // - state().save(*this, m_last_V.as_base(), this->name(), "m_last_V"); - state().save(*this, m_DD_n_m_1.as_base(), this->name(), "m_DD_n_m_1"); - state().save(*this, m_h_n_m_1.as_base(), this->name(), "m_h_n_m_1"); - } - - - private: - const std::size_t m_dim; - - protected: - static constexpr const std::size_t SIZEABS = plib::parray<FT, SIZE>::SIZEABS(); - static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 0) + 7) / 8) * 8; - - PALIGNAS_VECTOROPT() - plib::parray<float_type, SIZE> m_new_V; - PALIGNAS_VECTOROPT() - plib::parray<float_type, SIZE> m_RHS; - - PALIGNAS_VECTOROPT() - plib::pmatrix2d<float_type *> m_mat_ptr; - - // FIXME: below should be private - // state - variable time_stepping - PALIGNAS_VECTOROPT() - plib::parray<nl_fptype, SIZE> m_last_V; - PALIGNAS_VECTOROPT() - plib::parray<nl_fptype, SIZE> m_DD_n_m_1; - PALIGNAS_VECTOROPT() - plib::parray<nl_fptype, SIZE> m_h_n_m_1; - - std::size_t max_railstart() const noexcept - { - std::size_t max_rail = 0; - for (std::size_t k = 0; k < m_terms.size(); k++) - max_rail = std::max(max_rail, m_terms[k].railstart()); - return max_rail; - } - - - template <typename T, typename M> - void log_fill(const T &fill, M &mat) - { - const std::size_t iN = fill.size(); - - // FIXME: Not yet working, mat_cr.h needs some more work -#if 0 - auto mat_GE = dynamic_cast<plib::pGEmatrix_cr_t<typename M::base> *>(&mat); -#else - plib::unused_var(mat); -#endif - std::vector<unsigned> levL(iN, 0); - std::vector<unsigned> levU(iN, 0); - - // parallel scheme for L x = y - for (std::size_t k = 0; k < iN; k++) - { - unsigned lm=0; - for (std::size_t j = 0; j<k; j++) - if (fill[k][j] < M::FILL_INFINITY) - lm = std::max(lm, levL[j]); - levL[k] = 1+lm; - } - - // parallel scheme for U x = y - for (std::size_t k = iN; k-- > 0; ) - { - unsigned lm=0; - for (std::size_t j = iN; --j > k; ) - if (fill[k][j] < M::FILL_INFINITY) - lm = std::max(lm, levU[j]); - levU[k] = 1+lm; - } - for (std::size_t k = 0; k < iN; k++) - { - unsigned fm = 0; - pstring ml = ""; - for (std::size_t j = 0; j < iN; j++) - { - ml += fill[k][j] == 0 ? 'X' : fill[k][j] < M::FILL_INFINITY ? '+' : '.'; - if (fill[k][j] < M::FILL_INFINITY) - if (fill[k][j] > fm) - fm = fill[k][j]; - } -#if 0 - this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml, - levL[k], levU[k], mat_GE ? mat_GE->get_parallel_level(k) : 0, fm); -#else - this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml, - levL[k], levU[k], 0, fm); -#endif - } - } - - constexpr std::size_t size() const noexcept - { - return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim; - } - -#if 1 - void store() override - { - const std::size_t iN = size(); - for (std::size_t i = 0; i < iN; i++) - this->m_terms[i].setV(static_cast<nl_fptype>(m_new_V[i])); - } -#else - // global tanh damping (4.197) - // partially cures the symptoms but not the cause - void store() override - { - const std::size_t iN = size(); - for (std::size_t i = 0; i < iN; i++) - { - auto oldV = this->m_terms[i].template getV<nl_fptype>(); - this->m_terms[i].setV(oldV + 0.02 * plib::tanh((m_new_V[i]-oldV)*50.0)); - } - } -#endif - bool check_err() override - { - // NOTE: Ideally we should also include currents (RHS) here. This would - // need a reevaluation of the right hand side after voltages have been updated - // and thus belong into a different calculation. This applies to all solvers. - - const std::size_t iN = size(); - const auto reltol(static_cast<float_type>(m_params.m_reltol)); - const auto vntol(static_cast<float_type>(m_params.m_vntol)); - for (std::size_t i = 0; i < iN; i++) - { - const auto vold(static_cast<float_type>(this->m_terms[i].getV())); - const auto vnew(m_new_V[i]); - const auto tol(vntol + reltol * std::max(plib::abs(vnew),plib::abs(vold))); - if (plib::abs(vnew - vold) > tol) - return true; - } - return false; - } - - netlist_time compute_next_timestep(nl_fptype cur_ts, nl_fptype max_ts) override - { - nl_fptype new_solver_timestep(max_ts); - - for (std::size_t k = 0; k < size(); k++) - { - const auto &t = m_terms[k]; - const auto v(static_cast<nl_fptype>(t.getV())); - // avoid floating point exceptions - const nl_fptype DD_n = std::max(-fp_constants<nl_fptype>::TIMESTEP_MAXDIFF(), - std::min(+fp_constants<nl_fptype>::TIMESTEP_MAXDIFF(),(v - m_last_V[k]))); - - m_last_V[k] = v; - const nl_fptype hn = cur_ts; - - nl_fptype DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]); - nl_fptype new_net_timestep(0); - - m_h_n_m_1[k] = hn; - m_DD_n_m_1[k] = DD_n; - if (plib::abs(DD2) > fp_constants<nl_fptype>::TIMESTEP_MINDIV()) // avoid div-by-zero - new_net_timestep = plib::sqrt(m_params.m_dynamic_lte / plib::abs(nlconst::half()*DD2)); - else - new_net_timestep = m_params.m_max_timestep; - - new_solver_timestep = std::min(new_net_timestep, new_solver_timestep); - } - new_solver_timestep = std::max(new_solver_timestep, m_params.m_min_timestep); - - // FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere. - return std::max(netlist_time::from_fp(new_solver_timestep), netlist_time::quantum() * 2); - } - - template <typename M> - void build_mat_ptr(M &mat) - { - const std::size_t iN = size(); - - for (std::size_t k=0; k<iN; k++) - { - std::size_t cnt(0); - // build pointers into the compressed row format matrix for each terminal - for (std::size_t j=0; j< this->m_terms[k].railstart();j++) - { - int other = this->m_terms[k].m_connected_net_idx[j]; - if (other >= 0) - { - m_mat_ptr[k][j] = &(mat[k][static_cast<std::size_t>(other)]); - cnt++; - } - } - nl_assert_always(cnt == this->m_terms[k].railstart(), "Count and railstart mismatch"); - m_mat_ptr[k][this->m_terms[k].railstart()] = &(mat[k][k]); - } - } - - template <typename M> - void clear_square_mat(M &m) - { - const std::size_t n = size(); - for (std::size_t k=0; k < n; k++) - { - auto *p = &(m[k][0]); - using mat_elem_type = typename std::decay<decltype(*p)>::type; - for (std::size_t i=0; i < n; i++) - p[i] = plib::constants<mat_elem_type>::zero(); - } - } - - void fill_matrix_and_rhs() - { - const std::size_t N = size(); - - for (std::size_t k = 0; k < N; k++) - { - auto &net = m_terms[k]; - auto **tcr_r = &(m_mat_ptr[k][0]); - - using source_type = typename decltype(m_gtn)::value_type; - const std::size_t term_count = net.count(); - const std::size_t railstart = net.railstart(); - const auto &go = m_gonn[k]; - const auto > = m_gtn[k]; - const auto &Idr = m_Idrn[k]; - const auto &cnV = m_connected_net_Vn[k]; - - // FIXME: gonn, gtn and Idr - which float types should they have? - - auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<source_type>::zero()); - - // update diagonal element ... - *tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t; + state_var<std::size_t> m_stat_calculations; + state_var<std::size_t> m_stat_newton_raphson; + state_var<std::size_t> m_stat_vsolver_calls; - for (std::size_t i = 0; i < railstart; i++) - *tcr_r[i] += static_cast<FT>(go[i]); + state_var<netlist_time_ext> m_last_step; + plib::aligned_vector<nldelegate_ts> m_step_funcs; + plib::aligned_vector<nldelegate_dyn> m_dynamic_funcs; + plib::aligned_vector<device_arena::unique_ptr<proxied_analog_output_t>> m_inps; - auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<source_type>::zero())); + logic_input_t m_fb_sync; + logic_output_t m_Q_sync; - for (std::size_t i = railstart; i < term_count; i++) - RHS_t += (- go[i]) * *cnV[i]; + std::size_t m_ops; - m_RHS[k] = static_cast<FT>(RHS_t); - } - } + plib::aligned_vector<terms_for_net_t> m_rails_temp; // setup only }; diff --git a/src/lib/netlist/solver/nld_matrix_solver_ext.h b/src/lib/netlist/solver/nld_matrix_solver_ext.h new file mode 100644 index 00000000000..275ef135c69 --- /dev/null +++ b/src/lib/netlist/solver/nld_matrix_solver_ext.h @@ -0,0 +1,288 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud + +#ifndef NLD_MATRIX_SOLVER_EXT_H_ +#define NLD_MATRIX_SOLVER_EXT_H_ + +/// +/// \file nld_matrix_solver.h +/// + +#include "nld_matrix_solver.h" + +#include <numeric> + +namespace netlist +{ +namespace solver +{ + + template <typename FT, int SIZE> + class matrix_solver_ext_t: public matrix_solver_t + { + public: + + using float_type = FT; + + matrix_solver_ext_t(netlist_state_t &anetlist, const pstring &name, + const analog_net_t::list_t &nets, + const solver_parameters_t *params, const std::size_t size) + : matrix_solver_t(anetlist, name, nets, params) + , m_new_V(size) + , m_RHS(size) + , m_mat_ptr(size, this->max_railstart() + 1) + , m_last_V(size, nlconst::zero()) + , m_DD_n_m_1(size, nlconst::zero()) + , m_h_n_m_1(size, nlconst::magic(1e-6)) // we need a non zero value here + , m_dim(size) + { + // + // save states + // + state().save(*this, m_last_V.as_base(), this->name(), "m_last_V"); + state().save(*this, m_DD_n_m_1.as_base(), this->name(), "m_DD_n_m_1"); + state().save(*this, m_h_n_m_1.as_base(), this->name(), "m_h_n_m_1"); + } + + protected: + static constexpr const std::size_t SIZEABS = plib::parray<FT, SIZE>::SIZEABS(); + static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 0) + 7) / 8) * 8; + + //PALIGNAS_VECTOROPT() parrays define alignment already + plib::parray<float_type, SIZE> m_new_V; + //PALIGNAS_VECTOROPT() parrays define alignment already + plib::parray<float_type, SIZE> m_RHS; + + //PALIGNAS_VECTOROPT() parrays define alignment already + plib::pmatrix2d<float_type *> m_mat_ptr; + + std::size_t max_railstart() const noexcept + { + std::size_t max_rail = 0; + for (std::size_t k = 0; k < m_terms.size(); k++) + max_rail = std::max(max_rail, m_terms[k].railstart()); + return max_rail; + } + + + template <typename T, typename M> + void log_fill(const T &fill, M &mat) + { + const std::size_t iN = fill.size(); + + // FIXME: Not yet working, mat_cr.h needs some more work +#if 0 + auto mat_GE = dynamic_cast<plib::pGEmatrix_cr_t<typename M::base> *>(&mat); +#else + plib::unused_var(mat); +#endif + std::vector<unsigned> levL(iN, 0); + std::vector<unsigned> levU(iN, 0); + + // parallel scheme for L x = y + for (std::size_t k = 0; k < iN; k++) + { + unsigned lm=0; + for (std::size_t j = 0; j<k; j++) + if (fill[k][j] < M::FILL_INFINITY) + lm = std::max(lm, levL[j]); + levL[k] = 1+lm; + } + + // parallel scheme for U x = y + for (std::size_t k = iN; k-- > 0; ) + { + unsigned lm=0; + for (std::size_t j = iN; --j > k; ) + if (fill[k][j] < M::FILL_INFINITY) + lm = std::max(lm, levU[j]); + levU[k] = 1+lm; + } + for (std::size_t k = 0; k < iN; k++) + { + unsigned fm = 0; + pstring ml = ""; + for (std::size_t j = 0; j < iN; j++) + { + ml += fill[k][j] == 0 ? 'X' : fill[k][j] < M::FILL_INFINITY ? '+' : '.'; + if (fill[k][j] < M::FILL_INFINITY) + if (fill[k][j] > fm) + fm = fill[k][j]; + } +#if 0 + this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml, + levL[k], levU[k], mat_GE ? mat_GE->get_parallel_level(k) : 0, fm); +#else + this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml, + levL[k], levU[k], 0, fm); +#endif + } + } + + constexpr std::size_t size() const noexcept + { + return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim; + } + +#if 1 + void store() override + { + const std::size_t iN = size(); + for (std::size_t i = 0; i < iN; i++) + this->m_terms[i].setV(static_cast<fptype>(m_new_V[i])); + } +#else + // global tanh damping (4.197) + // partially cures the symptoms but not the cause + void store() override + { + const std::size_t iN = size(); + for (std::size_t i = 0; i < iN; i++) + { + auto oldV = this->m_terms[i].template getV<fptype>(); + this->m_terms[i].setV(oldV + 0.02 * plib::tanh((m_new_V[i]-oldV)*50.0)); + } + } +#endif + bool check_err() const override + { + // NOTE: Ideally we should also include currents (RHS) here. This would + // need a reevaluation of the right hand side after voltages have been updated + // and thus belong into a different calculation. This applies to all solvers. + + const std::size_t iN = size(); + const auto reltol(static_cast<float_type>(m_params.m_reltol)); + const auto vntol(static_cast<float_type>(m_params.m_vntol)); + for (std::size_t i = 0; i < iN; i++) + { + const auto vold(static_cast<float_type>(this->m_terms[i].getV())); + const auto vnew(m_new_V[i]); + const auto tol(vntol + reltol * std::max(plib::abs(vnew),plib::abs(vold))); + if (plib::abs(vnew - vold) > tol) + return true; + } + return false; + } + + netlist_time compute_next_timestep(fptype cur_ts, fptype max_ts) override + { + fptype new_solver_timestep(max_ts); + + for (std::size_t k = 0; k < size(); k++) + { + const auto &t = m_terms[k]; + const auto v(static_cast<fptype>(t.getV())); + // avoid floating point exceptions + const fptype DD_n = std::max(-fp_constants<fptype>::TIMESTEP_MAXDIFF(), + std::min(+fp_constants<fptype>::TIMESTEP_MAXDIFF(),(v - m_last_V[k]))); + + m_last_V[k] = v; + const fptype hn = cur_ts; + + fptype DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]); + fptype new_net_timestep(0); + + m_h_n_m_1[k] = hn; + m_DD_n_m_1[k] = DD_n; + if (plib::abs(DD2) > fp_constants<fptype>::TIMESTEP_MINDIV()) // avoid div-by-zero + new_net_timestep = plib::sqrt(m_params.m_dynamic_lte / plib::abs(nlconst::half()*DD2)); + else + new_net_timestep = m_params.m_max_timestep; + + new_solver_timestep = std::min(new_net_timestep, new_solver_timestep); + } + new_solver_timestep = std::max(new_solver_timestep, m_params.m_min_timestep); + + // FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere. + return std::max(netlist_time::from_fp(new_solver_timestep), netlist_time::quantum() * 2); + } + + template <typename M> + void build_mat_ptr(M &mat) + { + const std::size_t iN = size(); + + for (std::size_t k=0; k<iN; k++) + { + std::size_t cnt(0); + // build pointers into the compressed row format matrix for each terminal + for (std::size_t j=0; j< this->m_terms[k].railstart();j++) + { + int other = this->m_terms[k].m_connected_net_idx[j]; + if (other >= 0) + { + m_mat_ptr[k][j] = &(mat[k][static_cast<std::size_t>(other)]); + cnt++; + } + } + nl_assert_always(cnt == this->m_terms[k].railstart(), "Count and railstart mismatch"); + m_mat_ptr[k][this->m_terms[k].railstart()] = &(mat[k][k]); + } + } + + template <typename M> + void clear_square_mat(M &m) + { + const std::size_t n = size(); + for (std::size_t k=0; k < n; k++) + { + auto *p = &(m[k][0]); + using mat_elem_type = typename std::decay<decltype(*p)>::type; + for (std::size_t i=0; i < n; i++) + p[i] = plib::constants<mat_elem_type>::zero(); + } + } + + void fill_matrix_and_rhs() + { + const std::size_t N = size(); + + for (std::size_t k = 0; k < N; k++) + { + auto &net = m_terms[k]; + auto **tcr_r = &(m_mat_ptr[k][0]); + + using source_type = typename decltype(m_gtn)::value_type; + const std::size_t term_count = net.count(); + const std::size_t railstart = net.railstart(); + const auto &go = m_gonn[k]; + const auto > = m_gtn[k]; + const auto &Idr = m_Idrn[k]; + const auto &cnV = m_connected_net_Vn[k]; + + // FIXME: gonn, gtn and Idr - which float types should they have? + + auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<source_type>::zero()); + + // update diagonal element ... + *tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t; + + for (std::size_t i = 0; i < railstart; i++) + *tcr_r[i] += static_cast<FT>(go[i]); + + auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<source_type>::zero())); + + for (std::size_t i = railstart; i < term_count; i++) + RHS_t += (- go[i]) * *cnV[i]; + + m_RHS[k] = static_cast<FT>(RHS_t); + } + } + + private: + // state - variable time_stepping + //PALIGNAS_VECTOROPT() parrays define alignment already + plib::parray<fptype, SIZE> m_last_V; + // PALIGNAS_VECTOROPT() parrays define alignment already + plib::parray<fptype, SIZE> m_DD_n_m_1; + // PALIGNAS_VECTOROPT() parrays define alignment already + plib::parray<fptype, SIZE> m_h_n_m_1; + + const std::size_t m_dim; + + }; + +} // namespace solver +} // namespace netlist + +#endif // NLD_MATRIX_SOLVER_EXT_H_ diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h index ab4df0758e1..b32e4d2172b 100644 --- a/src/lib/netlist/solver/nld_ms_direct.h +++ b/src/lib/netlist/solver/nld_ms_direct.h @@ -13,6 +13,8 @@ #include "plib/parray.h" #include "plib/vector_ops.h" +#include "nld_matrix_solver_ext.h" + #include <algorithm> namespace netlist @@ -49,7 +51,7 @@ namespace solver template <typename T> void LE_back_subst(T & x); - PALIGNAS_VECTOROPT() + // PALIGNAS_VECTOROPT() parrays define alignment already plib::parray2D<FT, SIZE, m_pitch_ABS> m_A; }; diff --git a/src/lib/netlist/solver/nld_ms_direct1.h b/src/lib/netlist/solver/nld_ms_direct1.h index 095d35a30c0..e33846ad403 100644 --- a/src/lib/netlist/solver/nld_ms_direct1.h +++ b/src/lib/netlist/solver/nld_ms_direct1.h @@ -8,6 +8,7 @@ /// \file nld_ms_direct1.h /// +#include "nld_matrix_solver_ext.h" #include "nld_ms_direct.h" #include "nld_solver.h" diff --git a/src/lib/netlist/solver/nld_ms_direct2.h b/src/lib/netlist/solver/nld_ms_direct2.h index 744737b3892..365c1cac33e 100644 --- a/src/lib/netlist/solver/nld_ms_direct2.h +++ b/src/lib/netlist/solver/nld_ms_direct2.h @@ -8,6 +8,7 @@ /// \file nld_ms_direct2.h /// +#include "nld_matrix_solver_ext.h" #include "nld_ms_direct.h" #include "nld_solver.h" diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h index 6c7f5d7e502..3de955627ee 100644 --- a/src/lib/netlist/solver/nld_ms_gcr.h +++ b/src/lib/netlist/solver/nld_ms_gcr.h @@ -12,7 +12,8 @@ #include "plib/mat_cr.h" -#include "nld_ms_direct.h" +//#include "nld_ms_direct.h" +#include "nld_matrix_solver_ext.h" #include "nld_solver.h" #include "plib/pdynlib.h" #include "plib/pstream.h" @@ -31,6 +32,8 @@ namespace solver public: using mat_type = plib::pGEmatrix_cr_t<plib::pmatrix_cr_t<FT, SIZE>>; + using base_type = matrix_solver_ext_t<FT, SIZE>; + using fptype = typename base_type::fptype; matrix_solver_GCR_t(netlist_state_t &anetlist, const pstring &name, const analog_net_t::list_t &nets, @@ -85,9 +88,9 @@ namespace solver anetlist.log().verbose("maximum fill: {1}", gr.first); anetlist.log().verbose("Post elimination occupancy ratio: {2} Ops: {1}", gr.second, - static_cast<nl_fptype>(mat.nz_num) / static_cast<nl_fptype>(iN * iN)); + static_cast<fptype>(mat.nz_num) / static_cast<fptype>(iN * iN)); anetlist.log().verbose(" Pre elimination occupancy ratio: {2}", - static_cast<nl_fptype>(raw_elements) / static_cast<nl_fptype>(iN * iN)); + static_cast<fptype>(raw_elements) / static_cast<fptype>(iN * iN)); // FIXME: Move me // @@ -123,7 +126,7 @@ namespace solver pstring static_compile_name(); mat_type mat; - plib::dynproc<void, FT *, nl_fptype *, nl_fptype *, nl_fptype *, nl_fptype ** > m_proc; + plib::dynproc<void, FT *, fptype *, fptype *, fptype *, fptype ** > m_proc; }; @@ -273,7 +276,7 @@ namespace solver pstring matrix_solver_GCR_t<FT, SIZE>::static_compile_name() { pstring str_floattype(fp_constants<FT>::name()); - pstring str_fptype(fp_constants<nl_fptype>::name()); + pstring str_fptype(fp_constants<fptype>::name()); std::stringstream t; t.imbue(std::locale::classic()); plib::putf8_fmt_writer w(&t); @@ -290,7 +293,7 @@ namespace solver plib::putf8_fmt_writer strm(&t); pstring name = static_compile_name(); pstring str_floattype(fp_constants<FT>::name()); - pstring str_fptype(fp_constants<nl_fptype>::name()); + pstring str_fptype(fp_constants<fptype>::name()); pstring extqual; if (target == CXX_EXTERNAL_C) diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h index add885c2bfb..837c0bc780e 100644 --- a/src/lib/netlist/solver/nld_ms_gmres.h +++ b/src/lib/netlist/solver/nld_ms_gmres.h @@ -8,6 +8,7 @@ /// \file nld_ms_gmres.h /// +#include "nld_matrix_solver_ext.h" #include "nld_ms_direct.h" #include "nld_solver.h" #include "plib/gmres.h" diff --git a/src/lib/netlist/solver/nld_ms_sm.h b/src/lib/netlist/solver/nld_ms_sm.h index 599252adf6a..fd11a32a102 100644 --- a/src/lib/netlist/solver/nld_ms_sm.h +++ b/src/lib/netlist/solver/nld_ms_sm.h @@ -33,6 +33,7 @@ /// #include "nld_matrix_solver.h" +#include "nld_matrix_solver_ext.h" #include "nld_solver.h" #include "plib/vector_ops.h" diff --git a/src/lib/netlist/solver/nld_ms_sor.h b/src/lib/netlist/solver/nld_ms_sor.h index a253f160c4a..6b1a21afd39 100644 --- a/src/lib/netlist/solver/nld_ms_sor.h +++ b/src/lib/netlist/solver/nld_ms_sor.h @@ -12,8 +12,8 @@ /// Fow w==1 we will do the classic Gauss-Seidel approach. /// +#include "nld_matrix_solver_ext.h" #include "nld_ms_direct.h" -#include "nld_solver.h" #include <algorithm> @@ -70,16 +70,19 @@ namespace solver for (std::size_t k = 0; k < iN; k++) { - nl_fptype gtot_t = nlconst::zero(); - nl_fptype gabs_t = nlconst::zero(); - nl_fptype RHS_t = nlconst::zero(); const std::size_t term_count = this->m_terms[k].count(); - const nl_fptype * const gt = this->m_gtn[k]; - const nl_fptype * const go = this->m_gonn[k]; - const nl_fptype * const Idr = this->m_Idrn[k]; + const auto * const gt = this->m_gtn[k]; + const auto * const go = this->m_gonn[k]; + const auto * const Idr = this->m_Idrn[k]; auto other_cur_analog = this->m_connected_net_Vn[k]; + using fpaggtype = std::remove_reference_t<std::remove_cv_t<decltype(this->m_gtn[0][0])>>; + + fpaggtype gtot_t = nlconst_base<fpaggtype>::zero(); + fpaggtype gabs_t = nlconst_base<fpaggtype>::zero(); + fpaggtype RHS_t = nlconst_base<fpaggtype>::zero(); + this->m_new_V[k] = static_cast<float_type>(this->m_terms[k].getV()); for (std::size_t i = 0; i < term_count; i++) @@ -126,7 +129,7 @@ namespace solver { const int * net_other = this->m_terms[k].m_connected_net_idx.data(); const std::size_t railstart = this->m_terms[k].railstart(); - const nl_fptype * go = this->m_gonn[k]; + const auto * go = this->m_gonn[k]; float_type Idrive = plib::constants<float_type>::zero(); for (std::size_t i = 0; i < railstart; i++) diff --git a/src/lib/netlist/solver/nld_ms_sor_mat.h b/src/lib/netlist/solver/nld_ms_sor_mat.h index d575cbb1f37..2d29d0f01cd 100644 --- a/src/lib/netlist/solver/nld_ms_sor_mat.h +++ b/src/lib/netlist/solver/nld_ms_sor_mat.h @@ -12,9 +12,8 @@ /// For w==1 we will do the classic Gauss-Seidel approach /// -#include "nld_matrix_solver.h" +#include "nld_matrix_solver_ext.h" #include "nld_ms_direct.h" -#include "nld_solver.h" #include <algorithm> diff --git a/src/lib/netlist/solver/nld_ms_w.h b/src/lib/netlist/solver/nld_ms_w.h index 8571d459ad8..598a4b9e516 100644 --- a/src/lib/netlist/solver/nld_ms_w.h +++ b/src/lib/netlist/solver/nld_ms_w.h @@ -40,8 +40,7 @@ /// introduces numerical instability. /// -#include "nld_matrix_solver.h" -#include "nld_solver.h" +#include "nld_matrix_solver_ext.h" #include "plib/vector_ops.h" #include <algorithm> diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 8787247e505..4e0d8f4c4b3 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -87,7 +87,7 @@ namespace devices analog_net_t::list_t &nets, solver::solver_parameters_t ¶ms, std::size_t size) { - return host_arena::make_unique<C>(nl, name, nets, ¶ms, size); + return plib::make_unique<C, host_arena>(nl, name, nets, ¶ms, size); } template <typename FT, int SIZE> @@ -136,29 +136,21 @@ namespace devices switch (net_count) { case 1: - return host_arena::make_unique<solver::matrix_solver_direct1_t<FT>>(state(), sname, nets, &m_params); - break; + return plib::make_unique<solver::matrix_solver_direct1_t<FT>, host_arena>(state(), sname, nets, &m_params); case 2: - return host_arena::make_unique<solver::matrix_solver_direct2_t<FT>>(state(), sname, nets, &m_params); - break; + return plib::make_unique<solver::matrix_solver_direct2_t<FT>, host_arena>(state(), sname, nets, &m_params); case 3: return create_solver<FT, 3>(3, sname, nets); - break; case 4: return create_solver<FT, 4>(4, sname, nets); - break; case 5: return create_solver<FT, 5>(5, sname, nets); - break; case 6: return create_solver<FT, 6>(6, sname, nets); - break; case 7: return create_solver<FT, 7>(7, sname, nets); - break; case 8: return create_solver<FT, 8>(8, sname, nets); - break; default: log().info(MI_NO_SPECIFIC_SOLVER(net_count)); if (net_count <= 16) @@ -186,7 +178,6 @@ namespace devices return create_solver<FT, -512>(net_count, sname, nets); } return create_solver<FT, 0>(net_count, sname, nets); - break; } } @@ -201,7 +192,7 @@ namespace devices { netlist.log().verbose(" ==> not a rail net"); // Must be an analog net - auto &n = *static_cast<analog_net_t *>(net.get()); + auto &n = dynamic_cast<analog_net_t &>(*net); if (!already_processed(n)) { groupspre.emplace_back(analog_net_t::list_t()); @@ -273,9 +264,9 @@ namespace devices // only process analog terminals if (term->is_type(detail::terminal_type::TERMINAL)) { - auto *pt = static_cast<terminal_t *>(term); + auto &pt = dynamic_cast<terminal_t &>(*term); // check the connected terminal - analog_net_t &connected_net = netlist.setup().get_connected_terminal(*pt)->net(); + analog_net_t &connected_net = netlist.setup().get_connected_terminal(pt)->net(); netlist.log().verbose(" Connected net {}", connected_net.name()); if (!check_if_processed_and_join(connected_net)) process_net(netlist, connected_net); @@ -306,17 +297,17 @@ namespace devices switch (m_params.m_fp_type()) { case solver::matrix_fp_type_e::FLOAT: - if (!NL_USE_FLOAT_MATRIX) + if (!config::use_float_matrix()) log().info("FPTYPE {1} not supported. Using DOUBLE", m_params.m_fp_type().name()); - ms = create_solvers<std::conditional_t<NL_USE_FLOAT_MATRIX,float, double>>(sname, grp); + ms = create_solvers<std::conditional_t<config::use_float_matrix::value, float, double>>(sname, grp); break; case solver::matrix_fp_type_e::DOUBLE: ms = create_solvers<double>(sname, grp); break; case solver::matrix_fp_type_e::LONGDOUBLE: - if (!NL_USE_LONG_DOUBLE_MATRIX) + if (!config::use_long_double_matrix()) log().info("FPTYPE {1} not supported. Using DOUBLE", m_params.m_fp_type().name()); - ms = create_solvers<std::conditional_t<NL_USE_LONG_DOUBLE_MATRIX, long double, double>>(sname, grp); + ms = create_solvers<std::conditional_t<config::use_long_double_matrix::value, long double, double>>(sname, grp); break; case solver::matrix_fp_type_e::FLOATQ128: #if (NL_USE_FLOAT128) @@ -355,7 +346,7 @@ namespace devices for (auto & s : m_mat_solvers) { auto r = s->create_solver_code(target); - if (r.first != "") // ignore solvers not supporting static compile + if (!r.first.empty()) // ignore solvers not supporting static compile mp.push_back(r); } return mp; diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h index a0c28e6b302..e9734af1520 100644 --- a/src/lib/netlist/solver/nld_solver.h +++ b/src/lib/netlist/solver/nld_solver.h @@ -39,7 +39,7 @@ namespace devices void post_start(); void stop(); - nl_fptype gmin() const { return m_params.m_gmin(); } + auto gmin() const -> decltype(solver::solver_parameters_t::m_gmin()) { return m_params.m_gmin(); } solver::static_compile_container create_solver_code(solver::static_compile_target target); diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp index 393456a67f2..ee6a9827eb3 100644 --- a/src/lib/netlist/tools/nl_convert.cpp +++ b/src/lib/netlist/tools/nl_convert.cpp @@ -112,7 +112,7 @@ nl_convert_base_t::~nl_convert_base_t() void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias) { pstring pname = devname + "." + name; - m_pins.emplace(pname, arena::make_unique<pin_alias_t>(pname, devname + "." + alias)); + m_pins.emplace(pname, plib::make_unique<pin_alias_t, arena>(pname, devname + "." + alias)); } void nl_convert_base_t::add_ext_alias(const pstring &alias) @@ -138,15 +138,15 @@ void nl_convert_base_t::add_device(arena::unique_ptr<dev_t> dev) void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, const pstring &amodel) { - add_device(arena::make_unique<dev_t>(atype, aname, amodel)); + add_device(plib::make_unique<dev_t, arena>(atype, aname, amodel)); } void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, double aval) { - add_device(arena::make_unique<dev_t>(atype, aname, aval)); + add_device(plib::make_unique<dev_t, arena>(atype, aname, aval)); } void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname) { - add_device(arena::make_unique<dev_t>(atype, aname)); + add_device(plib::make_unique<dev_t, arena>(atype, aname)); } void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname) @@ -161,7 +161,7 @@ void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname net = m_nets[netname].get(); else { - auto nets = arena::make_unique<net_t>(netname); + auto nets = plib::make_unique<net_t, arena>(netname); net = nets.get(); m_nets.emplace(netname, std::move(nets)); } @@ -245,6 +245,7 @@ void nl_convert_base_t::dump_nl() } std::vector<size_t> sorted; + sorted.reserve(m_devs.size()); for (size_t i=0; i < m_devs.size(); i++) sorted.push_back(i); std::sort(sorted.begin(), sorted.end(), @@ -436,7 +437,7 @@ static int npoly(const pstring &s) void nl_convert_spice_t::process_line(const pstring &line) { - if (line != "") + if (!line.empty()) { //printf("// %s\n", line.c_str()); std::vector<pstring> tt(plib::psplit(line, " ", true)); @@ -976,7 +977,7 @@ void nl_convert_rinf_t::convert(const pstring &contents) pstring sim = attr["Simulation"]; pstring val = attr["Value"]; pstring com = attr["Comment"]; - if (val == "") + if (val.empty()) val = com; if (sim == "CAP") |