summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatarGravatar couriersud <couriersud@gmx.org>2020-06-13 15:49:35 +0200
committerGravatarGravatar couriersud <couriersud@gmx.org>2020-06-13 15:49:35 +0200
commite949e9c29de82ee7c32692e7b65da05dd22bdc9d (patch) (github)
tree8770696a48827e3b63d94063f8162eaadeff6539
parent75681d760c478f772fdb1603222498f96a9b61e7 (diff)
downloadmame-e949e9c29de82ee7c32692e7b65da05dd22bdc9d.tar.bz2
mame-e949e9c29de82ee7c32692e7b65da05dd22bdc9d.zip
netlist: Performance improvement and refactoring. [Couriersud]
Kidniki now achieves up to 910% when run with static solvers and with nltool. That is significant better than the 860% we have seen previously. This increase is driven by using a global memory pool in the solver code. In addition the following refactoring and code maintenance work is included. Please excuse the large commit, some of this took interfered with other work and the detail development steps were ugly. - gsl support: This commit adds pgsl.h which implements a very limited number of the functionality of the gsl header described in the c++ core guidelines. - clang-tidy fixes - A significant refactoring of palloc.h. Aligned hints were removed, they added complexity without a significant performance gain. Vector operations should better be done on special spans/views. The code has been tested on linux with g++-7, g++-9, clang-11. On Windows mingw-10 and VS2019, OSX clang-11.
-rw-r--r--scripts/src/netlist.lua1
-rw-r--r--src/devices/machine/netlist.cpp9
-rw-r--r--src/lib/netlist/analog/nld_mosfet.cpp4
-rw-r--r--src/lib/netlist/analog/nld_opamps.cpp2
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.h8
-rw-r--r--src/lib/netlist/build/makefile31
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp13
-rw-r--r--src/lib/netlist/devices/nlid_system.h2
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.cpp10
-rw-r--r--src/lib/netlist/nl_base.cpp24
-rw-r--r--src/lib/netlist/nl_base.h29
-rw-r--r--src/lib/netlist/nl_config.h6
-rw-r--r--src/lib/netlist/nl_factory.cpp2
-rw-r--r--src/lib/netlist/nl_factory.h6
-rw-r--r--src/lib/netlist/nl_parser.cpp6
-rw-r--r--src/lib/netlist/nl_setup.cpp34
-rw-r--r--src/lib/netlist/nl_setup.h4
-rw-r--r--src/lib/netlist/nltypes.h4
-rw-r--r--src/lib/netlist/plib/gmres.h26
-rw-r--r--src/lib/netlist/plib/mat_cr.h12
-rw-r--r--src/lib/netlist/plib/palloc.h424
-rw-r--r--src/lib/netlist/plib/parray.h39
-rw-r--r--src/lib/netlist/plib/pchrono.h7
-rw-r--r--src/lib/netlist/plib/pconfig.h17
-rw-r--r--src/lib/netlist/plib/pdynlib.h1
-rw-r--r--src/lib/netlist/plib/penum.h4
-rw-r--r--src/lib/netlist/plib/pexception.cpp2
-rw-r--r--src/lib/netlist/plib/pfmtlog.cpp4
-rw-r--r--src/lib/netlist/plib/pfmtlog.h6
-rw-r--r--src/lib/netlist/plib/pfunction.cpp50
-rw-r--r--src/lib/netlist/plib/pgsl.h105
-rw-r--r--src/lib/netlist/plib/plists.h8
-rw-r--r--src/lib/netlist/plib/pmain.cpp8
-rw-r--r--src/lib/netlist/plib/pmath.h4
-rwxr-xr-x[-rw-r--r--]src/lib/netlist/plib/pmatrix2d.h93
-rw-r--r--src/lib/netlist/plib/pmempool.h65
-rw-r--r--src/lib/netlist/plib/poptions.cpp17
-rw-r--r--src/lib/netlist/plib/poptions.h2
-rw-r--r--src/lib/netlist/plib/ppmf.h33
-rw-r--r--src/lib/netlist/plib/ppreprocessor.cpp6
-rw-r--r--src/lib/netlist/plib/ppreprocessor.h4
-rw-r--r--src/lib/netlist/plib/prandom.h11
-rw-r--r--src/lib/netlist/plib/pstonum.h13
-rw-r--r--src/lib/netlist/plib/pstream.h8
-rw-r--r--src/lib/netlist/plib/pstring.cpp6
-rw-r--r--src/lib/netlist/plib/pstrutil.h7
-rw-r--r--src/lib/netlist/plib/ptimed_queue.h2
-rw-r--r--src/lib/netlist/plib/ptypes.h6
-rw-r--r--src/lib/netlist/plib/putil.cpp20
-rw-r--r--src/lib/netlist/plib/putil.h10
-rw-r--r--src/lib/netlist/prg/nltool.cpp30
-rwxr-xr-xsrc/lib/netlist/prg/nlwav.cpp12
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp22
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h322
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver_ext.h288
-rw-r--r--src/lib/netlist/solver/nld_ms_direct.h4
-rw-r--r--src/lib/netlist/solver/nld_ms_direct1.h1
-rw-r--r--src/lib/netlist/solver/nld_ms_direct2.h1
-rw-r--r--src/lib/netlist/solver/nld_ms_gcr.h15
-rw-r--r--src/lib/netlist/solver/nld_ms_gmres.h1
-rw-r--r--src/lib/netlist/solver/nld_ms_sm.h1
-rw-r--r--src/lib/netlist/solver/nld_ms_sor.h19
-rw-r--r--src/lib/netlist/solver/nld_ms_sor_mat.h3
-rw-r--r--src/lib/netlist/solver/nld_ms_w.h3
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp31
-rw-r--r--src/lib/netlist/solver/nld_solver.h2
-rw-r--r--src/lib/netlist/tools/nl_convert.cpp15
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 &param, 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 &param, 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 &param, 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 &param, 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 &gt = 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 &gt = 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 &params, std::size_t size)
{
- return host_arena::make_unique<C>(nl, name, nets, &params, size);
+ return plib::make_unique<C, host_arena>(nl, name, nets, &params, 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")