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 static_solver_lib() const noexcept override { //return plib::make_unique(nullptr); - return netlist::host_arena::make_unique(nl_static_solver_syms); + return plib::make_unique(nl_static_solver_syms); } private: @@ -169,7 +169,7 @@ protected: netlist::host_arena::unique_ptr static_solver_lib() const noexcept override { - return netlist::host_arena::make_unique(nullptr); + return plib::make_unique(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(parent)) + : netlist::netlist_state_t(name, plib::make_unique(parent)) , m_parent(parent) { } @@ -978,7 +978,8 @@ netlist::host_arena::unique_ptr netlist_mame_device::b { try { - auto lnetlist = netlist::host_arena::make_unique("netlist", netlist::host_arena::make_unique()); + auto lnetlist = plib::make_unique("netlist", + plib::make_unique()); // 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(plib::pow(Vdsat - Vds, 2))); - const auto Sqr2(static_cast(plib::pow(nlconst::two() * Vdsat - Vds, 2))); + const auto Sqr1(plib::narrow_cast(plib::pow(Vdsat - Vds, 2))); + const auto Sqr2(plib::narrow_cast(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(m_modacc.m_TYPE); + m_type = plib::narrow_cast(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("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("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 + namespace netlist { namespace devices @@ -18,6 +20,8 @@ namespace netlist // nld_base_proxy // ----------------------------------------------------------------------------- + static const std::array, 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> 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(tp_ct); - auto *tn_t = static_cast(tp_cn); + auto *tp_t = dynamic_cast(tp_ct); + auto *tn_t = dynamic_cast(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("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::truthtable_t>(); + m_ttbl = plib::make_unique::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(anetlist, name, m_family_name, *m_ttbl, m_desc); + return plib::make_unique(pool, anetlist, name, m_family_name, *m_ttbl, m_desc); } private: device_arena::unique_ptr::truthtable_t> m_ttbl; @@ -578,7 +578,7 @@ void truthtable_parser::parse(const std::vector &truthtable) for (int j=0; j < 16; j++) m_timing_nt[j] = netlist_time::zero(); - while (!(ttline == "")) + while (!ttline.empty()) { std::vector 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; \ auto cs=s; \ - ret = host_arena::make_unique(desc.name, std::move(cs)); } \ + ret = plib::make_unique(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 callbacks_t:: static_solver_lib() const { - return host_arena::make_unique(nullptr); + return plib::make_unique(nullptr); } // ---------------------------------------------------------------------------------------- @@ -129,9 +129,9 @@ namespace netlist m_lib = m_callbacks->static_solver_lib(); - m_setup = host_arena::make_unique(*this); + m_setup = plib::make_unique(*this); // create the run interface - m_netlist = m_pool.make_unique(*this, name); + m_netlist = plib::make_unique(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 d; - std::vector t; + std::vector 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((total_count > 0) ? total_count : 1)); + total_time, total_time / gsl::narrow((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::type total_overhead = overhead() - * static_cast::type>(total_count) - / static_cast::type>(200000); + * gsl::narrow::type>(total_count) + / gsl::narrow::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::type overhead_per_pop = (si.m_stat_mainloop()-2*total_overhead - (total_time - total_overhead)) - / static_cast::type>(si.m_queue.m_prof_call()); + / gsl::narrow::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(stats->m_stat_inc_active()) / static_cast(stats->m_stat_total_time.count()), + gsl::narrow(stats->m_stat_inc_active()) / gsl::narrow(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(val); + m_param = plib::make_unique(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(val); + m_param = plib::make_unique(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; + using list_t = plib::aligned_vector; 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(m_param)); + return plib::pfmt("{}").e(gsl::narrow(m_param)); } private: @@ -1309,7 +1308,7 @@ namespace netlist public: template ::value>> value_base_t(P ¶m, const pstring &name) - : m_value(static_cast(param.value(name))) + : m_value(gsl::narrow(param.value(name))) { } template ::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 device_arena::unique_ptr make_pool_object(Args&&... args) { - return m_pool.make_unique(std::forward(args)...); + return plib::make_unique(m_pool, std::forward(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(core_terminal_t::net()); + return plib::downcast(core_terminal_t::net()); } inline analog_net_t & analog_t::net() noexcept { - return static_cast(core_terminal_t::net()); + return plib::downcast(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(core_terminal_t::net()); + return plib::downcast(core_terminal_t::net()); } inline const logic_net_t & logic_t::net() const noexcept { - return static_cast(core_terminal_t::net()); + return plib::downcast(core_terminal_t::net()); } inline netlist_sig_t logic_input_t::operator()() const noexcept @@ -2516,7 +2517,7 @@ namespace netlist if (plib::is_integral::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(valx); + m_param = plib::narrow_cast(valx); } device.state().save(*this, m_param, this->name(), "m_param"); @@ -2599,7 +2600,7 @@ namespace netlist state_container::state_container(O &owner, const pstring &name, const state_container::value_type & value) { - owner.state().save(owner, *static_cast(this), owner.name(), name); + owner.state().save(owner, static_cast(*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::value_type & value) : C(n, value) { - owner.state().save(owner, *static_cast(this), owner.name(), name); + owner.state().save(owner, static_cast(*this), owner.name(), name); } extern template struct state_var; 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; // NOLINT + using use_float_matrix = std::integral_constant; + using use_long_double_matrix = std::integral_constant; + using use_float128_matrix = std::integral_constant; + + using use_mempool = std::integral_constant; + /// \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 library_element_t::make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name) { - return pool.make_unique(anetlist, name); + return plib::make_unique(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, std::index_sequence) { - return pool.make_unique(anetlist, name, std::forward(std::get(args))...); + return plib::make_unique(pool, anetlist, name, std::forward(std::get(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>(name, + return plib::make_unique, host_arena>(name, std::move(props), std::forward(args)...); } private: @@ -194,7 +194,7 @@ namespace factory { template element_t::uptr constructor_t(const pstring &name, properties &&props) { - return host_arena::make_unique>(name, std::move(props)); + return plib::make_unique, 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(ni); - desc.no = static_cast(no); + desc.ni = gsl::narrow(ni); + desc.no = gsl::narrow(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(value))); + register_param(param, plib::pfmt("{1}")(gsl::narrow(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(name, std::move(props))); + m_factory.add(plib::make_unique(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(out); + const auto &out_cast = dynamic_cast(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(m_nlstate,"net." + t1.name()); + auto anet = plib::make_owned(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(i)); + m_abstract.m_links.erase(m_abstract.m_links.begin() + plib::narrow_cast(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(term)); + const auto &tri(dynamic_cast(*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(tmp.size() - 1)); + auto p = std::next(tmp.begin(), plib::narrow_cast(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(ft); + auto ret = plib::make_unique(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 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(nlstate(), e.first, e.second)); + auto param(plib::make_unique(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(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(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 - std::enable_if_t::value || plib::is_integral::value> + std::enable_if_t::value> register_param_val(const pstring ¶m, T value) { - register_param(param, static_cast(value)); + register_param(param, plib::narrow_cast(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, - 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::FILL_INFINITY) - : m_mat(static_cast(size)) - , m_LU(static_cast(size)) - , m_ILU_scale(static_cast(ilu_scale)) + : m_mat(narrow_cast(size)) + , m_LU(narrow_cast(size)) + , m_ILU_scale(narrow_cast(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(-1)); + nzcol[i].push_back(narrow_cast(-1)); } } @@ -139,7 +139,7 @@ namespace plib const auto &nz = nzcol[i]; std::size_t j; - while ((j = nz[nzcolp++])!=static_cast(-1)) // NOLINT(bugprone-infinite-loop) + while ((j = nz[nzcolp++])!=narrow_cast(-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 + template 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::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(SIZE); } + std::size_t size() const { return (SIZE<=0) ? m_size : narrow_cast(SIZE); } template 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(n)); + rho_delta = accuracy * plib::sqrt(narrow_cast(n)); // // Using @@ -407,8 +405,6 @@ namespace plib private: - //typedef typename plib::mat_cr_t::index_type mattype; - plib::parray residual; plib::parray 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(SIZE); } + std::size_t size() const { return (SIZE<=0) ? m_size : narrow_cast(SIZE); } template 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(size())); + FT rho_delta = accuracy * std::sqrt(narrow_cast(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(N) : m_size; } + constexpr std::size_t size() const noexcept { return (N>0) ? narrow_cast(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(k)-static_cast(j)) <= static_cast(band_width)) + if (f[k][j] <= max_fill && plib::abs(narrow_cast(k)-narrow_cast(j)) <= narrow_cast(band_width)) { - col_idx[nz] = static_cast(j); + col_idx[nz] = narrow_cast(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(j)); + nzbd[k].push_back(narrow_cast(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(i); + return narrow_cast(i); return -1; } @@ -525,7 +525,7 @@ namespace plib } } if (found) - ilu_rows[p++] = static_cast(i); + ilu_rows[p++] = narrow_cast(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" @@ -26,28 +27,52 @@ namespace plib { + //============================================================ + // aligned types + //============================================================ + +#if 0 +#if (PUSE_ALIGNED_HINTS) + template + using aligned_type __attribute__((aligned(A))) = T; +#else + template + using aligned_type = T; +#endif + + template + using aligned_pointer = aligned_type *; + + template + using const_aligned_pointer = const aligned_type *; + + template + using aligned_reference = aligned_type &; + + template + using const_aligned_reference = const aligned_type &; +#endif //============================================================ // Standard arena_deleter //============================================================ - template - struct arena_deleter + template + struct arena_deleter_base { - }; template - struct arena_deleter> + struct arena_deleter_base { 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::value>> - arena_deleter(const arena_deleter &rhs) noexcept + arena_deleter_base(const arena_deleter_base &rhs) noexcept : m_a(rhs.m_a) { } void operator()(T *p) noexcept @@ -61,18 +86,18 @@ namespace plib { }; template - struct arena_deleter> + struct arena_deleter_base { 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::value>::type> - arena_deleter(const arena_deleter &rhs) noexcept + arena_deleter_base(const arena_deleter_base &rhs) noexcept { plib::unused_var(rhs); } @@ -85,6 +110,13 @@ namespace plib { } }; + template + struct arena_deleter : public arena_deleter_base + { + using base_type = arena_deleter_base; + 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; }; - T* allocate(std::size_t n) + pointer allocate(std::size_t n) { return reinterpret_cast(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 @@ -296,171 +329,88 @@ namespace plib { // The previous code compiled with gcc and clang on all platforms and // compilers apart from MSVC. - template + template + struct arena_base; + + template 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 using allocator_type = arena_allocator; + template + using deleter_type = arena_deleter; + + template + using unique_ptr = std::unique_ptr>; + + template + using owned_ptr = plib::owned_ptr>; + 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; } + friend struct arena_base; + private: + size_t m_stat_cur_alloc = 0; + size_t m_stat_max_alloc = 0; }; - template - struct arena_hsd : public arena_core + template + struct arena_base : public arena_core { - template - inline void free(T *ptr) noexcept + using base_type = arena_core; + using size_type = typename base_type::size_type; + + 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; } + + static inline void inc_alloc_stat(size_type size) { - ptr->~T(); - static_cast

(this)->deallocate(ptr, sizeof(T)); + auto &i = base_type::instance(); + i.m_stat_cur_alloc += size; + if (i.m_stat_max_alloc - struct arena_hsd : public arena_core + struct arena_base : public arena_core { - template - static inline void free(T *ptr) noexcept + using size_type = typename arena_core::size_type; + + size_type cur_alloc() const noexcept { return this->m_stat_cur_alloc; } + size_type max_alloc() const noexcept { return this->m_stat_max_alloc; } + + inline void inc_alloc_stat(size_type size) { - ptr->~T(); - P::deallocate(ptr, sizeof(T)); + 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; + } + inline void dec_alloc_stat(size_type size) + { + this->m_stat_cur_alloc -= size; } }; - - template - struct arena_base : public arena_hsd - { - template - using deleter_type = arena_deleter; - - template - using unique_ptr = std::unique_ptr>; - - template - using owned_ptr = plib::owned_ptr>; - - template - inline unique_ptr make_unique(Args&&... args) - { - auto *mem = static_cast

(this)->allocate(alignof(T), sizeof(T)); - try - { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto *mema = new (mem) T(std::forward(args)...); - return unique_ptr(mema, deleter_type()); - } - catch (...) - { - static_cast

(this)->deallocate(mem, sizeof(T)); - throw; - } - } - - template - inline owned_ptr make_owned(Args&&... args) - { - auto *mem = static_cast

(this)->allocate(alignof(T), sizeof(T)); - try - { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto *mema = new (mem) T(std::forward(args)...); - return owned_ptr(mema, true, deleter_type()); - } - catch (...) - { - static_cast

(this)->deallocate(mem, sizeof(T)); - throw; - } - } - - template - inline T * alloc(Args&&... args) - { - auto *p = static_cast

(this)->allocate(alignof(T), sizeof(T)); - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - return new(p) T(std::forward(args)...); - } - - }; - - template - struct arena_base : public arena_hsd - { - template - using deleter_type = arena_deleter; - - template - using unique_ptr = std::unique_ptr>; - - template - using owned_ptr = plib::owned_ptr>; - - template - static inline unique_ptr make_unique(Args&&... args) - { - auto *mem = P::allocate(alignof(T), sizeof(T)); - try - { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto *mema = new (mem) T(std::forward(args)...); - return unique_ptr(mema, deleter_type()); - } - catch (...) - { - P::deallocate(mem, sizeof(T)); - throw; - } - } - - template - static inline owned_ptr make_owned(Args&&... args) - { - auto *mem = P::allocate(alignof(T), sizeof(T)); - try - { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto *mema = new (mem) T(std::forward(args)...); - return owned_ptr(mema, true, deleter_type()); - } - catch (...) - { - P::deallocate(mem, sizeof(T)); - throw; - } - } - - template - 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)...); - } - }; - - struct aligned_arena : public arena_base { - static inline void *allocate( size_t alignment, size_t size ) + static inline gsl::owner 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>(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 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 - 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 + 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)...); + } + catch (...) + { + ARENA::deallocate(mem, sizeof(T)); + throw; + } + } -#if (PUSE_ALIGNED_HINTS) - return reinterpret_cast(__builtin_assume_aligned(p, ALIGN)); -#else - return p; -#endif + template + static inline void free(T *ptr) noexcept + { + ptr->~T(); + ARENA::deallocate(ptr, sizeof(T)); + } + + template + 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)...); + } + catch (...) + { + arena.deallocate(mem, sizeof(T)); + throw; + } + } + + template + static inline void free(ARENA &arena, T *ptr) noexcept + { + ptr->~T(); + arena.deallocate(ptr, sizeof(T)); + } + } // namespace detail + + + + template + static inline + std::enable_if_t> + make_unique(Args&&... args) + { + using up_type = typename ARENA::template unique_ptr; + using deleter_type = typename ARENA::template deleter_type; + auto *mem = detail::alloc(std::forward(args)...); + return up_type(mem, deleter_type()); } - template - constexpr const T *assume_aligned_ptr(const T *p) noexcept + template + static inline + std::enable_if_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(__builtin_assume_aligned(p, ALIGN)); -#else - return p; -#endif + return make_unique(ARENA::instance(), std::forward(args)...); } + template + static inline + typename ARENA::template unique_ptr + make_unique(ARENA &arena, Args&&... args) + { + using up_type = typename ARENA::template unique_ptr; + using deleter_type = typename ARENA::template deleter_type; + auto *mem = detail::alloc(arena, std::forward(args)...); + return up_type(mem, deleter_type(&arena)); + } + + template + static inline + std::enable_if_t> + make_owned(Args&&... args) + { + using op_type = typename ARENA::template owned_ptr; + using deleter_type = typename ARENA::template deleter_type; + auto *mem = detail::alloc(std::forward(args)...); + return op_type(mem, true, deleter_type()); + } + + template + static inline + std::enable_if_t> + make_owned(Args&&... args) + { + return make_owned(ARENA::instance(), std::forward(args)...); + } + + template + static inline typename ARENA::template owned_ptr make_owned(ARENA &arena, Args&&... args) + { + using op_type = typename ARENA::template owned_ptr; + using deleter_type = typename ARENA::template deleter_type; + auto *mem = detail::alloc(arena, std::forward(args)...); + return op_type(mem, true, deleter_type(&arena)); + } + + template using aligned_allocator = aligned_arena::allocator_type; @@ -557,57 +592,72 @@ namespace plib { PDEFINE_HAS_MEMBER(has_align, align_size); - template - struct align_traits + template + struct align_traits_base { + static_assert(!has_align::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 - struct align_traits::value, void>> + struct align_traits_base { + static_assert(has_align::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; }; + template + struct align_traits : public align_traits_base::value> + {}; + + template + class paged_arena : public arena_base, true, true> + { + public: + paged_arena() + { + } + + PCOPYASSIGNMOVE(paged_arena, delete) + + ~paged_arena() = default; + + static void *allocate(size_t align, size_t size) + { + plib::unused_var(align); + //size = ((size + PAGESIZE - 1) / PAGESIZE) * PAGESIZE; + return arena().allocate(PAGESIZE, size); + } + + static void deallocate(void *ptr, size_t size) noexcept + { + //size = ((size + PAGESIZE - 1) / PAGESIZE) * PAGESIZE; + arena().deallocate(ptr, size); + } + + 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 > - class aligned_vector : public std::vector + template >//aligned_arena> + class aligned_vector : public std::vector> { public: - using base = std::vector; - - 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; + using base = std::vector>; using base::base; - base & as_base() noexcept { return *this; } - const base & as_base() const noexcept { return *this; } - - constexpr reference operator[](size_type i) noexcept - { - return assume_aligned_ptr(&(base::operator[](0)))[i]; - } - - constexpr const_reference operator[](size_type i) const noexcept - { - return assume_aligned_ptr(&(base::operator[](0)))[i]; - } - - pointer data() noexcept { return assume_aligned_ptr(base::data()); } - const_pointer data() const noexcept { return assume_aligned_ptr(base::data()); } - }; } // namespace plib 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 + template struct sizeabs { - static constexpr std::size_t ABS() noexcept { return (SIZE < 0) ? static_cast(0 - SIZE) : static_cast(SIZE); } + static constexpr std::size_t ABS() noexcept { return (SIZE < 0) ? narrow_cast(0 - SIZE) : narrow_cast(SIZE); } using container = typename std::array ; }; - template - struct sizeabs + template + struct sizeabs { static constexpr std::size_t ABS() noexcept { return 0; } + using allocator_type = typename ARENA::template allocator_type; //using container = typename std::vector>; - using container = typename std::vector>; + using container = typename std::vector; }; /// \brief Array with preallocated or dynamic allocation. @@ -51,17 +52,20 @@ namespace plib { /// I consider > 10% performance difference to be a use case. /// - template + template struct parray { public: - static constexpr std::size_t SIZEABS() noexcept { return sizeabs::ABS(); } + static constexpr std::size_t SIZEABS() noexcept { return sizeabs::ABS(); } - using base_type = typename sizeabs::container; + using base_type = typename sizeabs::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 parray(size_type size, std::enable_if_t<(X==0), int> = 0) @@ -70,7 +74,7 @@ namespace plib { } template - 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 - 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(&m_a[0])[i]; + return data()[i]; } constexpr const_reference operator[](size_type i) const noexcept { - return assume_aligned_ptr(&m_a[0])[i]; + return data()[i]; } - FT * data() noexcept { return assume_aligned_ptr(m_a.data()); } - const FT * data() const noexcept { return assume_aligned_ptr(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 @@ -212,8 +213,8 @@ namespace plib { ctype count() const noexcept { return m_count; } template - S as_seconds() const noexcept { return static_cast(total()) - / static_cast(T::per_second()); } + S as_seconds() const noexcept { return narrow_cast(total()) + / narrow_cast(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 - S as_seconds() const noexcept { return static_cast(0.0); } + S as_seconds() const noexcept { return narrow_cast(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() +//#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 T getsym(const pstring &name) const noexcept { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast(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(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 -#include #include +#include #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(cfmt_spec)) != pstring::npos) + if (!fmt.empty() && pstring("duxofge").find(static_cast(cfmt_spec)) != pstring::npos) { pend = static_cast(fmt.at(fmt.size() - 1)); if (pstring("duxofge").find(static_cast(pend)) == pstring::npos) @@ -113,7 +113,7 @@ pfmt::rtype pfmt::setfmt(std::stringstream &strm, char32_t cfmt_spec) strm << std::setprecision(pstonum_ne_def(fmt.substr(pdot + 1), 6)); width = pstonum_ne_def(left(fmt,pdot), 0); } - else if (fmt != "") + else if (!fmt.empty()) width = pstonum_ne_def(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(v); + s << narrow_cast(v); } }; #endif @@ -322,7 +322,7 @@ namespace plib { if (build_enabled && enabled && m_enabled) { pfmt pf(fmt); - static_cast(this)->vdowrite(xlog(pf, std::forward(args)...)); + dynamic_cast(*this).vdowrite(xlog(pf, std::forward(args)...)); } } @@ -332,7 +332,7 @@ namespace plib { if (build_enabled && m_enabled) { pfmt pf(fmt); - static_cast(this)->vdowrite(xlog(pf, std::forward(args)...)); + static_cast(*this).vdowrite(xlog(pf, std::forward(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 units_si_stat = { - //{ "Y", static_cast(1e24) }, // NOLINT: Yotta - //{ "Z", static_cast(1e21) }, // NOLINT: Zetta - //{ "E", static_cast(1e18) }, // NOLINT: Exa - { "P", static_cast(1e15) }, // NOLINT: Peta - { "T", static_cast(1e12) }, // NOLINT: Tera - { "G", static_cast( 1e9) }, // NOLINT: Giga - { "M", static_cast( 1e6) }, // NOLINT: Mega - { "k", static_cast( 1e3) }, // NOLINT: Kilo - { "h", static_cast( 1e2) }, // NOLINT: Hekto - //{ "da", static_cast(1e1) }, // NOLINT: Deka - { "d", static_cast(1e-1) }, // NOLINT: Dezi - { "c", static_cast(1e-2) }, // NOLINT: Zenti - { "m", static_cast(1e-3) }, // NOLINT: Milli - { "μ", static_cast(1e-6) }, // NOLINT: Mikro - { "n", static_cast(1e-9) }, // NOLINT: Nano - { "p", static_cast(1e-12) }, // NOLINT: Piko - { "f", static_cast(1e-15) }, // NOLINT: Femto - { "a", static_cast(1e-18) }, // NOLINT: Atto - { "z", static_cast(1e-21) }, // NOLINT: Zepto - { "y", static_cast(1e-24) }, // NOLINT: Yokto + //{ "Y", narrow_cast(1e24) }, // NOLINT: Yotta + //{ "Z", narrow_cast(1e21) }, // NOLINT: Zetta + //{ "E", narrow_cast(1e18) }, // NOLINT: Exa + { "P", narrow_cast(1e15) }, // NOLINT: Peta + { "T", narrow_cast(1e12) }, // NOLINT: Tera + { "G", narrow_cast( 1e9) }, // NOLINT: Giga + { "M", narrow_cast( 1e6) }, // NOLINT: Mega + { "k", narrow_cast( 1e3) }, // NOLINT: Kilo + { "h", narrow_cast( 1e2) }, // NOLINT: Hekto + //{ "da", narrow_cast(1e1) }, // NOLINT: Deka + { "d", narrow_cast(1e-1) }, // NOLINT: Dezi + { "c", narrow_cast(1e-2) }, // NOLINT: Zenti + { "m", narrow_cast(1e-3) }, // NOLINT: Milli + { "μ", narrow_cast(1e-6) }, // NOLINT: Mikro + { "n", narrow_cast(1e-9) }, // NOLINT: Nano + { "p", narrow_cast(1e-12) }, // NOLINT: Piko + { "f", narrow_cast(1e-15) }, // NOLINT: Femto + { "a", narrow_cast(1e-18) }, // NOLINT: Atto + { "z", narrow_cast(1e-21) }, // NOLINT: Zepto + { "y", narrow_cast(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(i); + rc.m_param = narrow_cast(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(MAX_STACK)) + if (stk >= narrow_cast(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(lfsr) / static_cast(0xffffU); // NOLINT + return narrow_cast(lfsr) / narrow_cast(0xffffU); // NOLINT } template @@ -297,7 +297,7 @@ namespace plib { lfsr >>= 1; if (lsb) lfsr ^= 0xB400U; // NOLINT: taps 15, 13, 12, 10 - return static_cast(lfsr); + return narrow_cast(lfsr); } #define ST1 stack[ptr] @@ -333,7 +333,7 @@ namespace plib { stack[ptr++] = lfsr_random(m_lfsr); break; case PUSH_INPUT: - stack[ptr++] = values[static_cast(rc.m_param)]; + stack[ptr++] = values[narrow_cast(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 +#include +#include + +#if defined(__has_builtin) // clang and gcc 10 + #if __has_builtin(__builtin_unreachable) + #define gsl_Expects(e) ((e) ? static_cast(0) : __builtin_unreachable()) + #endif +#elif defined(__GNUC__) && !(defined( __CUDACC__ ) && defined( __CUDA_ARCH__ )) + #define gsl_Expects(e) ((e) ? static_cast(0) : __builtin_unreachable()) +#elif defined(_MSC_VER) + #define gsl_Expects(e) __assume(e) +#else + #define gsl_Expects(e) ((e) ? static_cast(0) : static_cast(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 + using owner = T; + + template + using not_null = T; + + /// \brief perform a narrowing cast without checks + /// + template + inline constexpr T narrow_cast(O && v) noexcept + { + static_assert(plib::is_arithmetic::value && std::is_convertible, T>::value, "narrow cast expects conversion between arithmetic types"); + return static_cast(std::forward(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 + inline T narrow(O && v) noexcept + { + static_assert(plib::is_arithmetic::value && std::is_convertible, T>::value, "narrow cast expects conversion between arithmetic types"); + + const auto val = static_cast(std::forward(v)); + if( v == static_cast>(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 + inline constexpr D downcast(B && b) noexcept + { + static_assert(std::is_pointer::value || std::is_reference::value, "downcast only supports pointers or reference for derived"); + static_assert(std::is_pointer::value || std::is_reference::value, "downcast only supports pointers or reference for base"); + return static_cast(std::forward(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(m_buf[index]); } constexpr const_reference operator[](size_type index) const noexcept { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast(m_buf[index]); } @@ -78,13 +80,19 @@ namespace plib { new (&m_buf[index]) C(std::forward(args)...); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) iterator begin() const noexcept { return reinterpret_cast(&m_buf[0]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) iterator end() const noexcept { return reinterpret_cast(&m_buf[N]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) iterator begin() noexcept { return reinterpret_cast(&m_buf[0]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) iterator end() noexcept { return reinterpret_cast(&m_buf[N]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) const_iterator cbegin() const noexcept { return reinterpret_cast(&m_buf[0]); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) const_iterator cend() const noexcept { return reinterpret_cast(&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 arg; - for (std::size_t i = 0; i < static_cast(argc); i++) - arg.push_back(putf8string(argv[i])); + for (std::size_t i = 0; i < narrow_cast(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 arg; - for (std::size_t i = 0; i < static_cast(argc); i++) - arg.push_back(putf8string(pwstring(argv[i]))); + for (std::size_t i = 0; i < narrow_cast(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 #include -#if (PUSE_FLOAT128) -#include -#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 old mode 100644 new mode 100755 index 33e3169c64a..b9a2ebee116 --- a/src/lib/netlist/plib/pmatrix2d.h +++ b/src/lib/netlist/plib/pmatrix2d.h @@ -17,70 +17,102 @@ namespace plib { - template> + template class pmatrix2d { 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; + + static constexpr const size_type align_size = align_traits::align_size; + static constexpr const size_type stride_size = align_traits::stride_size; + + using value_type = T; + 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::align_size; - static constexpr const size_type stride_size = align_traits::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(&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(&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 m_v; + T * __restrict m_v; + + allocator_type m_a; }; // variable row length matrix - template> + template 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; - static constexpr const size_type align_size = align_traits::align_size; - static constexpr const size_type stride_size = align_traits::stride_size; + static constexpr const size_type align_size = align_traits::align_size; + static constexpr const size_type stride_size = align_traits::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(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 m_row; - std::vector m_v; + std::vector> m_row; + std::vector 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(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(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(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(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(*this, min_bytes); + auto *b = detail::alloc(m_arena, *this, min_bytes); m_blocks.push_back(b); return b; } - static std::unordered_map &sinfo() - { - static std::unordered_map 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::unordered_map, std::equal_to, + base_allocator_typex> m_info; +// std::unordered_map m_info; std::vector> 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