summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-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")