summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author couriersud <couriersud@arcor.de>2017-01-05 01:43:12 +0100
committer couriersud <couriersud@arcor.de>2017-01-05 01:43:31 +0100
commit02c3f45bff27e8ca27d5f68f52c816e5f055eadf (patch)
treef647ed591e5997496a6bb0ff3dc28fb887534f1f
parent67841056dae03d2e8f418b3be7150701c705d6b5 (diff)
Fix clang "-Wno-weak-vtables" warnings in netlist source. Refactored
code along the way. (nw)
-rw-r--r--scripts/src/netlist.lua1
-rw-r--r--src/lib/netlist/build/makefile4
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp72
-rw-r--r--src/lib/netlist/devices/nlid_proxy.h53
-rw-r--r--src/lib/netlist/nl_base.cpp62
-rw-r--r--src/lib/netlist/nl_base.h25
-rw-r--r--src/lib/netlist/nl_factory.cpp22
-rw-r--r--src/lib/netlist/nl_factory.h31
-rw-r--r--src/lib/netlist/nl_setup.cpp18
-rw-r--r--src/lib/netlist/nl_setup.h17
-rw-r--r--src/lib/netlist/plib/pexception.cpp36
-rw-r--r--src/lib/netlist/plib/pexception.h22
-rw-r--r--src/lib/netlist/plib/pfmtlog.cpp5
-rw-r--r--src/lib/netlist/plib/pfmtlog.h2
-rw-r--r--src/lib/netlist/plib/poptions.cpp12
-rw-r--r--src/lib/netlist/plib/poptions.h3
-rw-r--r--src/lib/netlist/plib/pparser.cpp10
-rw-r--r--src/lib/netlist/plib/pparser.h6
-rw-r--r--src/lib/netlist/plib/pstate.cpp5
-rw-r--r--src/lib/netlist/plib/pstate.h2
-rw-r--r--src/lib/netlist/plib/pstream.cpp39
-rw-r--r--src/lib/netlist/plib/pstream.h17
-rw-r--r--src/lib/netlist/prg/nltool.cpp45
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp562
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h36
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp502
-rw-r--r--src/lib/netlist/tools/nl_convert.cpp90
-rw-r--r--src/lib/netlist/tools/nl_convert.h73
28 files changed, 1042 insertions, 730 deletions
diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua
index 6c3d88c0387..aa3d40ae795 100644
--- a/scripts/src/netlist.lua
+++ b/scripts/src/netlist.lua
@@ -81,6 +81,7 @@ project "netlist"
MAME_DIR .. "src/lib/netlist/analog/nld_opamps.h",
MAME_DIR .. "src/lib/netlist/solver/nld_solver.cpp",
MAME_DIR .. "src/lib/netlist/solver/nld_solver.h",
+ MAME_DIR .. "src/lib/netlist/solver/nld_matrix_solver.cpp",
MAME_DIR .. "src/lib/netlist/solver/nld_matrix_solver.h",
MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct.h",
MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct1.h",
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index cddb4751146..81883053776 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -167,9 +167,9 @@ maketree: $(sort $(OBJDIRS))
.PHONY: clang mingw doc
clang:
- $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-cast-align -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-exit-time-destructors -Wno-format-nonliteral -Wno-weak-template-vtables"
+ $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-Weverything -Werror -Wno-padded -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-cast-align -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-exit-time-destructors -Wno-format-nonliteral -Wno-weak-template-vtables"
-#
+#-Wno-weak-vtables
# FIXME: -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors
#
diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp
index 080f9a27a4b..6b6da2176cf 100644
--- a/src/lib/netlist/devices/nlid_proxy.cpp
+++ b/src/lib/netlist/devices/nlid_proxy.cpp
@@ -17,10 +17,82 @@ namespace netlist
namespace devices
{
+ // -----------------------------------------------------------------------------
+ // nld_base_proxy
+ // -----------------------------------------------------------------------------
+
+ nld_base_proxy::nld_base_proxy(netlist_t &anetlist, const pstring &name,
+ logic_t *inout_proxied, detail::core_terminal_t *proxy_inout)
+ : device_t(anetlist, name)
+ {
+ m_logic_family = inout_proxied->logic_family();
+ m_term_proxied = inout_proxied;
+ m_proxy_term = proxy_inout;
+ }
+
+ nld_base_proxy::~nld_base_proxy()
+ {
+ }
+
+ // ----------------------------------------------------------------------------------------
+ // nld_a_to_d_proxy
+ // ----------------------------------------------------------------------------------------
+
+ nld_base_a_to_d_proxy::nld_base_a_to_d_proxy(netlist_t &anetlist, const pstring &name,
+ logic_input_t *in_proxied, detail::core_terminal_t *in_proxy)
+ : nld_base_proxy(anetlist, name, in_proxied, in_proxy)
+ , m_Q(*this, "Q")
+ {
+ }
+
+ nld_base_a_to_d_proxy::~nld_base_a_to_d_proxy() {}
+
+ nld_a_to_d_proxy::nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied)
+ : nld_base_a_to_d_proxy(anetlist, name, in_proxied, &m_I)
+ , m_I(*this, "I")
+ {
+ }
+
+ nld_a_to_d_proxy::~nld_a_to_d_proxy()
+ {
+ }
+
+ NETLIB_RESET(a_to_d_proxy)
+ {
+ }
+
+ NETLIB_UPDATE(a_to_d_proxy)
+ {
+ nl_assert(m_logic_family != nullptr);
+ // FIXME: Variable supply voltage!
+ double supply_V = logic_family().fixed_V();
+ if (supply_V == 0.0) supply_V = 5.0;
+
+ if (m_I.Q_Analog() > logic_family().high_thresh_V(0.0, supply_V))
+ out().push(1, NLTIME_FROM_NS(1));
+ else if (m_I.Q_Analog() < logic_family().low_thresh_V(0.0, supply_V))
+ out().push(0, NLTIME_FROM_NS(1));
+ else
+ {
+ // do nothing
+ }
+ }
+
// ----------------------------------------------------------------------------------------
// nld_d_to_a_proxy
// ----------------------------------------------------------------------------------------
+ nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name,
+ logic_output_t *out_proxied, detail::core_terminal_t &proxy_out)
+ : nld_base_proxy(anetlist, name, out_proxied, &proxy_out)
+ , m_I(*this, "I")
+ {
+ }
+
+ nld_base_d_to_a_proxy::~nld_base_d_to_a_proxy()
+ {
+ }
+
nld_d_to_a_proxy::nld_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied)
: nld_base_d_to_a_proxy(anetlist, name, out_proxied, m_RV.m_P)
, m_GNDHack(*this, "_Q")
diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h
index 50920c5cf80..eced07f8356 100644
--- a/src/lib/netlist/devices/nlid_proxy.h
+++ b/src/lib/netlist/devices/nlid_proxy.h
@@ -31,15 +31,9 @@ namespace netlist
{
public:
nld_base_proxy(netlist_t &anetlist, const pstring &name,
- logic_t *inout_proxied, detail::core_terminal_t *proxy_inout)
- : device_t(anetlist, name)
- {
- m_logic_family = inout_proxied->logic_family();
- m_term_proxied = inout_proxied;
- m_proxy_term = proxy_inout;
- }
+ logic_t *inout_proxied, detail::core_terminal_t *proxy_inout);
- virtual ~nld_base_proxy() {}
+ virtual ~nld_base_proxy();
logic_t &term_proxied() const { return *m_term_proxied; }
detail::core_terminal_t &proxy_term() const { return *m_proxy_term; }
@@ -65,18 +59,14 @@ namespace netlist
{
public:
- virtual ~nld_base_a_to_d_proxy() {}
+ virtual ~nld_base_a_to_d_proxy();
virtual logic_output_t &out() { return m_Q; }
protected:
nld_base_a_to_d_proxy(netlist_t &anetlist, const pstring &name,
- logic_input_t *in_proxied, detail::core_terminal_t *in_proxy)
- : nld_base_proxy(anetlist, name, in_proxied, in_proxy)
- , m_Q(*this, "Q")
- {
- }
+ logic_input_t *in_proxied, detail::core_terminal_t *in_proxy);
private:
@@ -87,36 +77,17 @@ namespace netlist
NETLIB_OBJECT_DERIVED(a_to_d_proxy, base_a_to_d_proxy)
{
public:
- nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied)
- : nld_base_a_to_d_proxy(anetlist, name, in_proxied, &m_I)
- , m_I(*this, "I")
- {
- }
+ nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied);
- virtual ~nld_a_to_d_proxy() {}
+ virtual ~nld_a_to_d_proxy();
analog_input_t m_I;
protected:
- NETLIB_RESETI() { }
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
- NETLIB_UPDATEI()
- {
- nl_assert(m_logic_family != nullptr);
- // FIXME: Variable supply voltage!
- double supply_V = logic_family().fixed_V();
- if (supply_V == 0.0) supply_V = 5.0;
-
- if (m_I.Q_Analog() > logic_family().high_thresh_V(0.0, supply_V))
- out().push(1, NLTIME_FROM_NS(1));
- else if (m_I.Q_Analog() < logic_family().low_thresh_V(0.0, supply_V))
- out().push(0, NLTIME_FROM_NS(1));
- else
- {
- // do nothing
- }
- }
private:
};
@@ -127,17 +98,13 @@ namespace netlist
NETLIB_OBJECT_DERIVED(base_d_to_a_proxy, base_proxy)
{
public:
- virtual ~nld_base_d_to_a_proxy() {}
+ virtual ~nld_base_d_to_a_proxy();
virtual logic_input_t &in() { return m_I; }
protected:
nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name,
- logic_output_t *out_proxied, detail::core_terminal_t &proxy_out)
- : nld_base_proxy(anetlist, name, out_proxied, &proxy_out)
- , m_I(*this, "I")
- {
- }
+ logic_output_t *out_proxied, detail::core_terminal_t &proxy_out);
logic_input_t m_I;
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index aa6cfc5b340..ab643f1ee87 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -49,10 +49,24 @@ void object_t::operator delete (void * mem)
}
+nl_exception::~nl_exception()
+{
+}
+
+
// ----------------------------------------------------------------------------------------
// logic_family_ttl_t
// ----------------------------------------------------------------------------------------
+logic_family_desc_t::logic_family_desc_t()
+{
+}
+
+logic_family_desc_t::~logic_family_desc_t()
+{
+}
+
+
class logic_family_ttl_t : public logic_family_desc_t
{
public:
@@ -761,6 +775,9 @@ logic_net_t::logic_net_t(netlist_t &nl, const pstring &aname, detail::core_termi
{
}
+logic_net_t::~logic_net_t()
+{
+}
// ----------------------------------------------------------------------------------------
// analog_net_t
@@ -772,6 +789,10 @@ analog_net_t::analog_net_t(netlist_t &nl, const pstring &aname, detail::core_ter
{
}
+analog_net_t::~analog_net_t()
+{
+}
+
// ----------------------------------------------------------------------------------------
// core_terminal_t
// ----------------------------------------------------------------------------------------
@@ -785,6 +806,10 @@ detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &anam
{
}
+detail::core_terminal_t::~core_terminal_t()
+{
+}
+
void detail::core_terminal_t::reset()
{
if (is_type(OUTPUT))
@@ -803,6 +828,13 @@ void detail::core_terminal_t::set_net(net_t *anet)
m_net = nullptr;
}
+analog_t::~analog_t()
+{
+}
+
+logic_t::~logic_t()
+{
+}
// ----------------------------------------------------------------------------------------
// terminal_t
@@ -854,6 +886,11 @@ logic_output_t::logic_output_t(core_device_t &dev, const pstring &aname)
netlist().setup().register_term(*this);
}
+logic_output_t::~logic_output_t()
+{
+}
+
+
void logic_output_t::initial(const netlist_sig_t val)
{
net().initial(val);
@@ -883,6 +920,10 @@ analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname)
netlist().setup().register_term(*this);
}
+analog_output_t::~analog_output_t()
+{
+}
+
void analog_output_t::initial(const nl_double val)
{
net().m_cur_Analog = val;
@@ -899,6 +940,10 @@ logic_input_t::logic_input_t(core_device_t &dev, const pstring &aname)
netlist().setup().register_term(*this);
}
+logic_input_t::~logic_input_t()
+{
+}
+
// ----------------------------------------------------------------------------------------
// Parameters ...
// ----------------------------------------------------------------------------------------
@@ -910,6 +955,10 @@ param_t::param_t(const param_type_t atype, device_t &device, const pstring &name
device.setup().register_param(this->name(), *this);
}
+param_t::~param_t()
+{
+}
+
void param_t::update_param()
{
device().update_param();
@@ -958,6 +1007,15 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
//netlist().save(*this, m_param, "m_param");
}
+void param_str_t::changed()
+{
+}
+
+void param_model_t::changed()
+{
+ m_map.clear();
+}
+
const pstring param_model_t::model_value_str(const pstring &entity)
{
if (m_map.size() == 0)
@@ -972,6 +1030,10 @@ nl_double param_model_t::model_value(const pstring &entity)
return netlist().setup().model_value(m_map, entity);
}
+void param_data_t::changed()
+{
+}
+
std::unique_ptr<plib::pistream> param_data_t::stream()
{
return device().netlist().setup().get_data_stream(Value());
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index cfefc32bc41..e85a891aaaf 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -209,7 +209,7 @@ namespace netlist
: plib::pexception(text) { }
/*! Copy constructor. */
nl_exception(const nl_exception &e) : plib::pexception(e) { }
- virtual ~nl_exception() {}
+ virtual ~nl_exception();
};
class logic_output_t;
@@ -234,8 +234,8 @@ namespace netlist
class logic_family_desc_t
{
public:
- logic_family_desc_t() {}
- virtual ~logic_family_desc_t() {}
+ logic_family_desc_t();
+ virtual ~logic_family_desc_t();
virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist, const pstring &name,
logic_output_t *proxied) const = 0;
@@ -496,7 +496,7 @@ namespace netlist
core_terminal_t(core_device_t &dev, const pstring &aname,
const type_t type, const state_e state);
- virtual ~core_terminal_t() { }
+ virtual ~core_terminal_t();
void set_net(net_t *anet);
void clear_net();
@@ -532,6 +532,7 @@ namespace netlist
: core_terminal_t(dev, aname, type, state)
{
}
+ virtual ~analog_t();
const analog_net_t & net() const NL_NOEXCEPT;
analog_net_t & net() NL_NOEXCEPT;
@@ -613,6 +614,7 @@ namespace netlist
, m_proxy(nullptr)
{
}
+ virtual ~logic_t();
bool has_proxy() const { return (m_proxy != nullptr); }
devices::nld_base_proxy *get_proxy() const { return m_proxy; }
@@ -635,6 +637,7 @@ namespace netlist
{
public:
logic_input_t(core_device_t &dev, const pstring &aname);
+ virtual ~logic_input_t();
netlist_sig_t Q() const NL_NOEXCEPT;
@@ -750,7 +753,7 @@ namespace netlist
public:
logic_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
- virtual ~logic_net_t() { }
+ virtual ~logic_net_t();
netlist_sig_t Q() const { return m_cur_Q; }
netlist_sig_t new_Q() const { return m_new_Q; }
@@ -794,7 +797,7 @@ namespace netlist
analog_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
- virtual ~analog_net_t() { }
+ virtual ~analog_net_t();
nl_double Q_Analog() const { return m_cur_Analog; }
nl_double &Q_Analog_state_ptr() { return m_cur_Analog; }
@@ -817,6 +820,7 @@ namespace netlist
public:
logic_output_t(core_device_t &dev, const pstring &aname);
+ virtual ~logic_output_t();
void initial(const netlist_sig_t val);
@@ -834,6 +838,7 @@ namespace netlist
P_PREVENT_COPYING(analog_output_t)
public:
analog_output_t(core_device_t &dev, const pstring &aname);
+ virtual ~analog_output_t();
void push(const nl_double val) NL_NOEXCEPT { set_Q(val); }
void initial(const nl_double val);
@@ -861,7 +866,7 @@ namespace netlist
};
param_t(const param_type_t atype, device_t &device, const pstring &name);
- virtual ~param_t() {}
+ virtual ~param_t();
param_type_t param_type() const { return m_param_type; }
@@ -937,7 +942,7 @@ namespace netlist
}
}
protected:
- virtual void changed() { }
+ virtual void changed();
pstring Value() const { return m_param; }
private:
pstring m_param;
@@ -954,7 +959,7 @@ namespace netlist
const pstring model_value_str(const pstring &entity);
const pstring model_type();
protected:
- virtual void changed() override { m_map.clear(); }
+ virtual void changed() override;
private:
model_map_t m_map;
};
@@ -966,7 +971,7 @@ namespace netlist
: param_str_t(device, name, "") { }
std::unique_ptr<plib::pistream> stream();
protected:
- virtual void changed() override { }
+ virtual void changed() override;
};
// -----------------------------------------------------------------------------
diff --git a/src/lib/netlist/nl_factory.cpp b/src/lib/netlist/nl_factory.cpp
index 1e5a8e11b44..33fc532331b 100644
--- a/src/lib/netlist/nl_factory.cpp
+++ b/src/lib/netlist/nl_factory.cpp
@@ -14,6 +14,18 @@
namespace netlist { namespace factory
{
+
+element_t::element_t(const pstring &name, const pstring &classname,
+ const pstring &def_param)
+ : m_name(name), m_classname(classname), m_def_param(def_param)
+{
+}
+
+element_t::~element_t()
+{
+}
+
+
// ----------------------------------------------------------------------------------------
// net_device_t_base_factory
// ----------------------------------------------------------------------------------------
@@ -51,7 +63,7 @@ factory::element_t * list_t::factory_by_name(const pstring &devname)
plib::owned_ptr<device_t> library_element_t::Create(netlist_t &anetlist, const pstring &name)
{
- return plib::owned_ptr<device_t>::Create<wrapper>(anetlist, name);
+ return plib::owned_ptr<device_t>::Create<NETLIB_NAME(wrapper)>(anetlist, name);
}
void library_element_t::macro_actions(netlist_t &anetlist, const pstring &name)
@@ -61,5 +73,13 @@ void library_element_t::macro_actions(netlist_t &anetlist, const pstring &name)
anetlist.setup().namespace_pop();
}
+NETLIB_RESET(wrapper)
+{
+}
+
+NETLIB_UPDATE(wrapper)
+{
+}
+
} }
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index a14ff71d5e1..0f4a1344e38 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -30,11 +30,8 @@ namespace netlist { namespace factory
P_PREVENT_COPYING(element_t)
public:
element_t(const pstring &name, const pstring &classname,
- const pstring &def_param)
- : m_name(name), m_classname(classname), m_def_param(def_param)
- {}
-
- virtual ~element_t() {}
+ const pstring &def_param);
+ virtual ~element_t();
virtual plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) = 0;
virtual void macro_actions(netlist_t &anetlist, const pstring &name) {}
@@ -117,6 +114,18 @@ namespace netlist { namespace factory
// factory_lib_entry_t: factory class to wrap macro based chips/elements
// -----------------------------------------------------------------------------
+ class NETLIB_NAME(wrapper) : public device_t
+ {
+ public:
+ NETLIB_NAME(wrapper)(netlist_t &anetlist, const pstring &name)
+ : device_t(anetlist, name)
+ {
+ }
+ protected:
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ };
+
class library_element_t : public element_t
{
P_PREVENT_COPYING(library_element_t)
@@ -126,18 +135,6 @@ namespace netlist { namespace factory
const pstring &def_param)
: element_t(name, classname, def_param), m_setup(setup) { }
- class wrapper : public device_t
- {
- public:
- wrapper(netlist_t &anetlist, const pstring &name)
- : device_t(anetlist, name)
- {
- }
- protected:
- NETLIB_RESETI() { }
- NETLIB_UPDATEI() { }
- };
-
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override;
void macro_actions(netlist_t &anetlist, const pstring &name) override;
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 038fd7ed978..39d85e5be1d 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -1080,4 +1080,22 @@ std::unique_ptr<plib::pistream> source_file_t::stream(const pstring &name)
return plib::make_unique_base<plib::pistream, plib::pifilestream>(m_filename);
}
+bool source_proc_t::parse(const pstring &name)
+{
+ if (name == m_setup_func_name)
+ {
+ m_setup_func(setup());
+ return true;
+ }
+ else
+ return false;
}
+
+std::unique_ptr<plib::pistream> source_proc_t::stream(const pstring &name)
+{
+ std::unique_ptr<plib::pistream> p(nullptr);
+ return p;
+}
+
+}
+
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index 1edc3b50781..66745504c74 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -373,22 +373,9 @@ namespace netlist
{
}
- virtual bool parse(const pstring &name) override
- {
- if (name == m_setup_func_name)
- {
- m_setup_func(setup());
- return true;
- }
- else
- return false;
- }
+ virtual bool parse(const pstring &name) override;
+ virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
- virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override
- {
- std::unique_ptr<plib::pistream> p(nullptr);
- return p;
- }
private:
void (*m_setup_func)(setup_t &);
pstring m_setup_func_name;
diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp
index 7d0adca22c5..2eedd6f9d16 100644
--- a/src/lib/netlist/plib/pexception.cpp
+++ b/src/lib/netlist/plib/pexception.cpp
@@ -26,41 +26,75 @@ pexception::pexception(const pstring text)
m_text = text;
}
+pexception::~pexception() noexcept
+{
+}
+
file_e::file_e(const pstring fmt, const pstring &filename)
: pexception(pfmt(fmt)(filename))
{
}
+file_e::~file_e() noexcept
+{
+}
+
file_open_e::file_open_e(const pstring &filename)
: file_e("File open failed: {}", filename)
{
}
+file_open_e::~file_open_e() noexcept
+{
+
+}
+
file_read_e::file_read_e(const pstring &filename)
: file_e("File read failed: {}", filename)
{
}
+file_read_e::~file_read_e() noexcept
+{
+
+}
+
file_write_e::file_write_e(const pstring &filename)
: file_e("File write failed: {}", filename)
{
}
+file_write_e::~file_write_e() noexcept
+{
+}
+
null_argument_e::null_argument_e(const pstring &argument)
: pexception(pfmt("Null argument passed: {}")(argument))
{
}
+null_argument_e::~null_argument_e() noexcept
+{
+}
+
out_of_mem_e::out_of_mem_e(const pstring &location)
: pexception(pfmt("Out of memory: {}")(location))
{
}
-fpexception::fpexception(const pstring &text)
+out_of_mem_e::~out_of_mem_e() noexcept
+{
+}
+
+fpexception_e::fpexception_e(const pstring &text)
: pexception(pfmt("Out of memory: {}")(text))
{
}
+fpexception_e::~fpexception_e() noexcept
+{
+}
+
bool fpsignalenabler::m_enable = false;
fpsignalenabler::fpsignalenabler(unsigned fpexceptions)
diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h
index d3bccbd54ad..a4d3b3c498f 100644
--- a/src/lib/netlist/plib/pexception.h
+++ b/src/lib/netlist/plib/pexception.h
@@ -21,10 +21,10 @@ namespace plib {
class pexception : public std::exception
{
public:
- pexception(const pstring text);
+ explicit pexception(const pstring text);
pexception(const pexception &e) : std::exception(e) { m_text = e.m_text; }
- virtual ~pexception() noexcept {}
+ virtual ~pexception() noexcept;
const pstring &text() { return m_text; }
@@ -36,46 +36,60 @@ class file_e : public plib::pexception
{
public:
explicit file_e(const pstring fmt, const pstring &filename);
+ file_e(const file_e &e) : pexception(e) { }
+ virtual ~file_e() noexcept;
};
class file_open_e : public file_e
{
public:
explicit file_open_e(const pstring &filename);
+ file_open_e(const file_open_e &e) : file_e(e) { }
+ virtual ~file_open_e() noexcept;
};
class file_read_e : public file_e
{
public:
explicit file_read_e(const pstring &filename);
+ file_read_e(const file_read_e &e) : file_e(e) { }
+ virtual ~file_read_e() noexcept;
};
class file_write_e : public file_e
{
public:
explicit file_write_e(const pstring &filename);
+ file_write_e(const file_write_e &e) : file_e(e) { }
+ virtual ~file_write_e() noexcept;
};
class null_argument_e : public plib::pexception
{
public:
explicit null_argument_e(const pstring &argument);
+ null_argument_e(const null_argument_e &e) : pexception(e) { }
+ virtual ~null_argument_e() noexcept;
};
class out_of_mem_e : public plib::pexception
{
public:
explicit out_of_mem_e(const pstring &location);
+ out_of_mem_e(const out_of_mem_e &e) : pexception(e) { }
+ virtual ~out_of_mem_e() noexcept;
};
/* FIXME: currently only a stub for later use. More use could be added by
* using “-fnon-call-exceptions" and sigaction to enable c++ exception supported.
*/
-class fpexception : public pexception
+class fpexception_e : public pexception
{
public:
- fpexception(const pstring &text);
+ fpexception_e(const pstring &text);
+ fpexception_e(const fpexception_e &e) : pexception(e) { }
+ virtual ~fpexception_e() noexcept;
};
static const unsigned FP_INEXACT = 0x0001;
diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp
index 73da6822d20..48b0f1544c1 100644
--- a/src/lib/netlist/plib/pfmtlog.cpp
+++ b/src/lib/netlist/plib/pfmtlog.cpp
@@ -17,6 +17,11 @@
#include "palloc.h"
namespace plib {
+
+plog_dispatch_intf::~plog_dispatch_intf()
+{
+}
+
pfmt::pfmt(const pstring &fmt)
: m_str(m_str_buf), m_allocated(0), m_arg(0)
{
diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h
index 49f8ae62b44..c5369109b81 100644
--- a/src/lib/netlist/plib/pfmtlog.h
+++ b/src/lib/netlist/plib/pfmtlog.h
@@ -263,7 +263,7 @@ class plog_dispatch_intf
template<plog_level::e, bool> friend class plog_channel;
public:
- virtual ~plog_dispatch_intf() { }
+ virtual ~plog_dispatch_intf();
protected:
virtual void vlog(const plog_level &l, const pstring &ls) const = 0;
};
diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp
index 2060e8ec46c..a14d4ae93e7 100644
--- a/src/lib/netlist/plib/poptions.cpp
+++ b/src/lib/netlist/plib/poptions.cpp
@@ -22,11 +22,23 @@ namespace plib {
{
}
+ option_group::~option_group()
+ {
+ }
+
+ option_example::~option_example()
+ {
+ }
+
option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument)
: option_base(parent, help), m_short(ashort), m_long(along), m_has_argument(has_argument)
{
}
+ option::~option()
+ {
+ }
+
int option_str::parse(pstring argument)
{
m_val = argument;
diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h
index 3fac79b58ef..aa5ce07cbc8 100644
--- a/src/lib/netlist/plib/poptions.h
+++ b/src/lib/netlist/plib/poptions.h
@@ -39,6 +39,7 @@ class option_group : public option_base
public:
option_group(options &parent, pstring group, pstring help)
: option_base(parent, help), m_group(group) { }
+ ~option_group();
pstring group() { return m_group; }
private:
@@ -50,6 +51,7 @@ class option_example : public option_base
public:
option_example(options &parent, pstring group, pstring help)
: option_base(parent, help), m_example(group) { }
+ ~option_example();
pstring example() { return m_example; }
private:
@@ -61,6 +63,7 @@ class option : public option_base
{
public:
option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument);
+ ~option();
/* no_argument options will be called with "" argument */
diff --git a/src/lib/netlist/plib/pparser.cpp b/src/lib/netlist/plib/pparser.cpp
index 0a19685316d..35629aacdee 100644
--- a/src/lib/netlist/plib/pparser.cpp
+++ b/src/lib/netlist/plib/pparser.cpp
@@ -15,6 +15,16 @@ namespace plib {
// A simple tokenizer
// ----------------------------------------------------------------------------------------
+ptokenizer::ptokenizer(pistream &strm)
+: m_strm(strm), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"')
+{
+}
+
+ptokenizer::~ptokenizer()
+{
+}
+
+
pstring ptokenizer::currentline_str()
{
return m_cur_line;
diff --git a/src/lib/netlist/plib/pparser.h b/src/lib/netlist/plib/pparser.h
index 301a4fc30a2..db88299d85c 100644
--- a/src/lib/netlist/plib/pparser.h
+++ b/src/lib/netlist/plib/pparser.h
@@ -22,11 +22,9 @@ class ptokenizer
{
P_PREVENT_COPYING(ptokenizer)
public:
- virtual ~ptokenizer() {}
+ explicit ptokenizer(pistream &strm);
- explicit ptokenizer(pistream &strm)
- : m_strm(strm), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"')
- {}
+ virtual ~ptokenizer();
enum token_type
{
diff --git a/src/lib/netlist/plib/pstate.cpp b/src/lib/netlist/plib/pstate.cpp
index ddfe0a37bc8..91869c26ba7 100644
--- a/src/lib/netlist/plib/pstate.cpp
+++ b/src/lib/netlist/plib/pstate.cpp
@@ -60,4 +60,9 @@ template<> void state_manager_t::save_item(const void *owner, callback_t &state,
state.register_state(*this, stname);
}
+state_manager_t::callback_t::~callback_t()
+{
+}
+
+
}
diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h
index cd6c8efe38b..48420825164 100644
--- a/src/lib/netlist/plib/pstate.h
+++ b/src/lib/netlist/plib/pstate.h
@@ -62,7 +62,7 @@ public:
public:
using list_t = std::vector<callback_t *>;
- virtual ~callback_t() { }
+ virtual ~callback_t();
virtual void register_state(state_manager_t &manager, const pstring &module) = 0;
virtual void on_pre_save() = 0;
diff --git a/src/lib/netlist/plib/pstream.cpp b/src/lib/netlist/plib/pstream.cpp
index b9895036a12..b05d86d7bc5 100644
--- a/src/lib/netlist/plib/pstream.cpp
+++ b/src/lib/netlist/plib/pstream.cpp
@@ -14,10 +14,19 @@
#include "palloc.h"
namespace plib {
+
+pstream::~pstream()
+{
+}
+
// -----------------------------------------------------------------------------
// pistream: input stream
// -----------------------------------------------------------------------------
+pistream::~pistream()
+{
+}
+
bool pistream::readline(pstring &line)
{
char c = 0;
@@ -44,6 +53,10 @@ bool pistream::readline(pstring &line)
// postream: output stream
// -----------------------------------------------------------------------------
+postream::~postream()
+{
+}
+
void postream::write(pistream &strm)
{
char buf[1024];
@@ -142,6 +155,10 @@ pstdin::pstdin()
/* nothing to do */
}
+pstdin::~pstdin()
+{
+}
+
// -----------------------------------------------------------------------------
// Output file stream
// -----------------------------------------------------------------------------
@@ -209,6 +226,11 @@ pstream::pos_type pofilestream::vtell()
return static_cast<pos_type>(ret);
}
+postringstream::~postringstream()
+{
+}
+
+
// -----------------------------------------------------------------------------
// pstderr: write to stderr
// -----------------------------------------------------------------------------
@@ -218,6 +240,10 @@ pstderr::pstderr()
{
}
+pstderr::~pstderr()
+{
+}
+
// -----------------------------------------------------------------------------
// pstdout: write to stdout
// -----------------------------------------------------------------------------
@@ -227,6 +253,10 @@ pstdout::pstdout()
{
}
+pstdout::~pstdout()
+{
+}
+
// -----------------------------------------------------------------------------
// Memory stream
// -----------------------------------------------------------------------------
@@ -273,6 +303,10 @@ pimemstream::pos_type pimemstream::vtell()
return m_pos;
}
+pistringstream::~pistringstream()
+{
+}
+
// -----------------------------------------------------------------------------
// Output memory stream
// -----------------------------------------------------------------------------
@@ -333,4 +367,9 @@ pstream::pos_type pomemstream::vtell()
return m_pos;
}
+pstream_fmt_writer_t::~pstream_fmt_writer_t()
+{
+}
+
+
}
diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h
index 11bf0fb12cf..6d02c4d1551 100644
--- a/src/lib/netlist/plib/pstream.h
+++ b/src/lib/netlist/plib/pstream.h
@@ -32,9 +32,7 @@ public:
explicit pstream(const unsigned flags) : m_flags(flags)
{
}
- virtual ~pstream()
- {
- }
+ virtual ~pstream();
bool seekable() const { return ((m_flags & FLAG_SEEKABLE) != 0); }
@@ -79,7 +77,7 @@ class pistream : public pstream
public:
explicit pistream(const unsigned flags) : pstream(flags) {}
- virtual ~pistream() {}
+ virtual ~pistream();
bool eof() const { return ((flags() & FLAG_EOF) != 0); }
@@ -115,7 +113,7 @@ class postream : public pstream
public:
explicit postream(unsigned flags) : pstream(flags) {}
- virtual ~postream() {}
+ virtual ~postream();
/* this digests linux & dos/windows text files */
@@ -184,7 +182,7 @@ class postringstream : public postream
public:
postringstream() : postream(0) { }
- virtual ~postringstream() { }
+ virtual ~postringstream();
const pstringbuffer &str() { return m_buf; }
@@ -238,6 +236,7 @@ class pstderr : public pofilestream
P_PREVENT_COPYING(pstderr)
public:
pstderr();
+ virtual ~pstderr();
};
// -----------------------------------------------------------------------------
@@ -249,6 +248,7 @@ class pstdout : public pofilestream
P_PREVENT_COPYING(pstdout)
public:
pstdout();
+ virtual ~pstdout();
};
// -----------------------------------------------------------------------------
@@ -290,6 +290,7 @@ class pstdin : public pifilestream
public:
pstdin();
+ virtual ~pstdin();
};
// -----------------------------------------------------------------------------
@@ -325,8 +326,8 @@ class pistringstream : public pimemstream
{
P_PREVENT_COPYING(pistringstream)
public:
-
pistringstream(const pstring &str) : pimemstream(str.c_str(), str.len()), m_str(str) { }
+ virtual ~pistringstream();
private:
/* only needed for a reference till destruction */
@@ -343,7 +344,7 @@ class pstream_fmt_writer_t : public plib::pfmt_writer_t<>
public:
explicit pstream_fmt_writer_t(postream &strm) : m_strm(strm) {}
- virtual ~pstream_fmt_writer_t() { }
+ virtual ~pstream_fmt_writer_t();
protected:
virtual void vdowrite(const pstring &ls) const override
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 60189bfb0cc..f96fd423530 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -102,25 +102,26 @@ public:
{
}
- virtual std::unique_ptr<plib::pistream> stream(const pstring &file) override
- {
- pstring name = m_folder + "/" + file;
- try
- {
- auto strm = plib::make_unique_base<plib::pistream, plib::pifilestream>(name);
- return strm;
- }
- catch (plib::pexception e)
- {
-
- }
- return std::unique_ptr<plib::pistream>(nullptr);
- }
+ virtual std::unique_ptr<plib::pistream> stream(const pstring &file) override;
private:
pstring m_folder;
};
+std::unique_ptr<plib::pistream> netlist_data_folder_t::stream(const pstring &file)
+{
+ pstring name = m_folder + "/" + file;
+ try
+ {
+ auto strm = plib::make_unique_base<plib::pistream, plib::pifilestream>(name);
+ return strm;
+ }
+ catch (plib::pexception e)
+ {
+
+ }
+ return std::unique_ptr<plib::pistream>(nullptr);
+}
class netlist_tool_t : public netlist::netlist_t
{
@@ -182,18 +183,20 @@ public:
protected:
- void vlog(const plib::plog_level &l, const pstring &ls) const override
- {
- pstring err = plib::pfmt("{}: {}\n")(l.name())(ls.c_str());
- pout("{}", err);
- if (l == plib::plog_level::FATAL)
- throw netlist::nl_exception(err);
- }
+ void vlog(const plib::plog_level &l, const pstring &ls) const override;
private:
netlist::setup_t *m_setup;
};
+void netlist_tool_t::vlog(const plib::plog_level &l, const pstring &ls) const
+{
+ pstring err = plib::pfmt("{}: {}\n")(l.name())(ls.c_str());
+ pout("{}", err);
+ if (l == plib::plog_level::FATAL)
+ throw netlist::nl_exception(err);
+}
+
// FIXME: usage should go elsewhere
void usage(tool_options_t &opts);
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
new file mode 100644
index 00000000000..d6032e65912
--- /dev/null
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -0,0 +1,562 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_matrix_solver.cpp
+ *
+ */
+
+#include "nld_matrix_solver.h"
+#include "plib/putil.h"
+
+namespace netlist
+{
+ namespace devices
+ {
+
+proxied_analog_output_t::~proxied_analog_output_t()
+{
+}
+
+terms_t::terms_t()
+ : m_railstart(0)
+ , m_last_V(0.0)
+ , m_DD_n_m_1(0.0)
+ , m_h_n_m_1(1e-9)
+{
+}
+
+void terms_t::clear()
+{
+ m_term.clear();
+ m_net_other.clear();
+ m_gt.clear();
+ m_go.clear();
+ m_Idr.clear();
+ m_other_curanalog.clear();
+}
+
+void terms_t::add(terminal_t *term, int net_other, bool sorted)
+{
+ if (sorted)
+ for (unsigned i=0; i < m_net_other.size(); i++)
+ {
+ if (m_net_other[i] > net_other)
+ {
+ plib::container::insert_at(m_term, i, term);
+ plib::container::insert_at(m_net_other, i, net_other);
+ plib::container::insert_at(m_gt, i, 0.0);
+ plib::container::insert_at(m_go, i, 0.0);
+ plib::container::insert_at(m_Idr, i, 0.0);
+ plib::container::insert_at(m_other_curanalog, i, nullptr);
+ return;
+ }
+ }
+ m_term.push_back(term);
+ m_net_other.push_back(net_other);
+ m_gt.push_back(0.0);
+ m_go.push_back(0.0);
+ m_Idr.push_back(0.0);
+ m_other_curanalog.push_back(nullptr);
+}
+
+void terms_t::set_pointers()
+{
+ for (unsigned i = 0; i < count(); i++)
+ {
+ m_term[i]->set_ptrs(&m_gt[i], &m_go[i], &m_Idr[i]);
+ m_other_curanalog[i] = m_term[i]->m_otherterm->net().m_cur_Analog.ptr();
+ }
+}
+
+// ----------------------------------------------------------------------------------------
+// matrix_solver
+// ----------------------------------------------------------------------------------------
+
+matrix_solver_t::matrix_solver_t(netlist_t &anetlist, const pstring &name,
+ const eSortType sort, const solver_parameters_t *params)
+ : device_t(anetlist, name)
+ , m_params(*params)
+ , m_stat_calculations(*this, "m_stat_calculations", 0)
+ , m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0)
+ , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0)
+ , m_iterative_fail(*this, "m_iterative_fail", 0)
+ , m_iterative_total(*this, "m_iterative_total", 0)
+ , m_last_step(*this, "m_last_step", netlist_time::zero())
+ , m_fb_sync(*this, "FB_sync")
+ , m_Q_sync(*this, "Q_sync")
+ , m_sort(sort)
+{
+ connect_post_start(m_fb_sync, m_Q_sync);
+}
+
+matrix_solver_t::~matrix_solver_t()
+{
+ for (unsigned k = 0; k < m_terms.size(); k++)
+ {
+ plib::pfree(m_terms[k]);
+ }
+
+}
+
+void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
+{
+ log().debug("New solver setup\n");
+
+ m_nets.clear();
+ m_terms.clear();
+
+ for (auto & net : nets)
+ {
+ m_nets.push_back(net);
+ m_terms.push_back(plib::palloc<terms_t>());
+ m_rails_temp.push_back(plib::palloc<terms_t>());
+ }
+
+ for (std::size_t k = 0; k < nets.size(); k++)
+ {
+ analog_net_t *net = nets[k];
+
+ log().debug("setting up net\n");
+
+ net->set_solver(this);
+
+ for (auto &p : net->m_core_terms)
+ {
+ log().debug("{1} {2} {3}\n", p->name(), net->name(), net->isRailNet());
+ switch (p->type())
+ {
+ case terminal_t::TERMINAL:
+ if (p->device().is_timestep())
+ if (!plib::container::contains(m_step_devices, &p->device()))
+ m_step_devices.push_back(&p->device());
+ if (p->device().is_dynamic())
+ if (!plib::container::contains(m_dynamic_devices, &p->device()))
+ m_dynamic_devices.push_back(&p->device());
+ {
+ terminal_t *pterm = dynamic_cast<terminal_t *>(p);
+ add_term(k, pterm);
+ }
+ log().debug("Added terminal {1}\n", p->name());
+ break;
+ case terminal_t::INPUT:
+ {
+ proxied_analog_output_t *net_proxy_output = nullptr;
+ for (auto & input : m_inps)
+ if (input->m_proxied_net == &p->net())
+ {
+ net_proxy_output = input.get();
+ break;
+ }
+
+ if (net_proxy_output == nullptr)
+ {
+ auto net_proxy_output_u = plib::make_unique<proxied_analog_output_t>(*this, this->name() + "." + plib::pfmt("m{1}")(m_inps.size()));
+ net_proxy_output = net_proxy_output_u.get();
+ m_inps.push_back(std::move(net_proxy_output_u));
+ nl_assert(p->net().is_analog());
+ net_proxy_output->m_proxied_net = static_cast<analog_net_t *>(&p->net());
+ }
+ net_proxy_output->net().add_terminal(*p);
+ // FIXME: repeated
+ net_proxy_output->net().rebuild_list();
+ log().debug("Added input\n");
+ }
+ break;
+ case terminal_t::OUTPUT:
+ case terminal_t::PARAM:
+ log().fatal("unhandled element found\n");
+ break;
+ }
+ }
+ log().debug("added net with {1} populated connections\n", net->m_core_terms.size());
+ }
+
+ /* now setup the matrix */
+ setup_matrix();
+}
+
+void matrix_solver_t::setup_matrix()
+{
+ const std::size_t iN = m_nets.size();
+
+ for (std::size_t k = 0; k < iN; k++)
+ {
+ m_terms[k]->m_railstart = m_terms[k]->count();
+ for (std::size_t i = 0; i < m_rails_temp[k]->count(); i++)
+ this->m_terms[k]->add(m_rails_temp[k]->terms()[i], m_rails_temp[k]->net_other()[i], false);
+
+ m_rails_temp[k]->clear(); // no longer needed
+ m_terms[k]->set_pointers();
+ }
+
+ for (unsigned k = 0; k < iN; k++)
+ plib::pfree(m_rails_temp[k]); // no longer needed
+
+ m_rails_temp.clear();
+
+ /* Sort in descending order by number of connected matrix voltages.
+ * The idea is, that for Gauss-Seidel algo the first voltage computed
+ * depends on the greatest number of previous voltages thus taking into
+ * account the maximum amout of information.
+ *
+ * This actually improves performance on popeye slightly. Average
+ * GS computations reduce from 2.509 to 2.370
+ *
+ * Smallest to largest : 2.613
+ * Unsorted : 2.509
+ * Largest to smallest : 2.370
+ *
+ * Sorting as a general matrix pre-conditioning is mentioned in
+ * literature but I have found no articles about Gauss Seidel.
+ *
+ * For Gaussian Elimination however increasing order is better suited.
+ * FIXME: Even better would be to sort on elements right of the matrix diagonal.
+ *
+ */
+
+ if (m_sort != NOSORT)
+ {
+ int sort_order = (m_sort == DESCENDING ? 1 : -1);
+
+ for (unsigned k = 0; k < iN - 1; k++)
+ for (unsigned i = k+1; i < iN; i++)
+ {
+ if ((static_cast<int>(m_terms[k]->m_railstart) - static_cast<int>(m_terms[i]->m_railstart)) * sort_order < 0)
+ {
+ std::swap(m_terms[i], m_terms[k]);
+ std::swap(m_nets[i], m_nets[k]);
+ }
+ }
+
+ for (unsigned k = 0; k < iN; k++)
+ {
+ int *other = m_terms[k]->net_other();
+ for (unsigned i = 0; i < m_terms[k]->count(); i++)
+ if (other[i] != -1)
+ other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_otherterm->net());
+ }
+ }
+
+ /* create a list of non zero elements. */
+ for (unsigned k = 0; k < iN; k++)
+ {
+ terms_t * t = m_terms[k];
+ /* pretty brutal */
+ int *other = t->net_other();
+
+ t->m_nz.clear();
+
+ for (unsigned i = 0; i < t->m_railstart; i++)
+ if (!plib::container::contains(t->m_nz, static_cast<unsigned>(other[i])))
+ t->m_nz.push_back(static_cast<unsigned>(other[i]));
+
+ t->m_nz.push_back(k); // add diagonal
+
+ /* and sort */
+ std::sort(t->m_nz.begin(), t->m_nz.end());
+ }
+
+ /* create a list of non zero elements right of the diagonal
+ * These list anticipate the population of array elements by
+ * Gaussian elimination.
+ */
+ for (unsigned k = 0; k < iN; k++)
+ {
+ terms_t * t = m_terms[k];
+ /* pretty brutal */
+ int *other = t->net_other();
+
+ if (k==0)
+ t->m_nzrd.clear();
+ else
+ {
+ t->m_nzrd = m_terms[k-1]->m_nzrd;
+ for (auto j = t->m_nzrd.begin(); j != t->m_nzrd.end(); )
+ {
+ if (*j < k + 1)
+ j = t->m_nzrd.erase(j);
+ else
+ ++j;
+ }
+ }
+
+ for (unsigned i = 0; i < t->m_railstart; i++)
+ if (!plib::container::contains(t->m_nzrd, static_cast<unsigned>(other[i])) && other[i] >= static_cast<int>(k + 1))
+ t->m_nzrd.push_back(static_cast<unsigned>(other[i]));
+
+ /* and sort */
+ std::sort(t->m_nzrd.begin(), t->m_nzrd.end());
+ }
+
+ /* create a list of non zero elements below diagonal k
+ * This should reduce cache misses ...
+ */
+
+ bool **touched = new bool*[iN];
+ for (unsigned k=0; k<iN; k++)
+ touched[k] = new bool[iN];
+
+ for (unsigned k = 0; k < iN; k++)
+ {
+ for (unsigned j = 0; j < iN; j++)
+ touched[k][j] = false;
+ for (unsigned j = 0; j < m_terms[k]->m_nz.size(); j++)
+ touched[k][m_terms[k]->m_nz[j]] = true;
+ }
+
+ unsigned ops = 0;
+ for (unsigned k = 0; k < iN; k++)
+ {
+ ops++; // 1/A(k,k)
+ for (unsigned row = k + 1; row < iN; row++)
+ {
+ if (touched[row][k])
+ {
+ ops++;
+ if (!plib::container::contains(m_terms[k]->m_nzbd, row))
+ m_terms[k]->m_nzbd.push_back(row);
+ for (unsigned col = k + 1; col < iN; col++)
+ if (touched[k][col])
+ {
+ touched[row][col] = true;
+ ops += 2;
+ }
+ }
+ }
+ }
+ log().verbose("Number of mults/adds for {1}: {2}", name(), ops);
+
+ if ((0))
+ for (unsigned k = 0; k < iN; k++)
+ {
+ pstring line = plib::pfmt("{1}")(k, "3");
+ for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++)
+ line += plib::pfmt(" {1}")(m_terms[k]->m_nzrd[j], "3");
+ log().verbose("{1}", line);
+ }
+
+ /*
+ * save states
+ */
+ for (unsigned k = 0; k < iN; k++)
+ {
+ pstring num = plib::pfmt("{1}")(k);
+
+ netlist().save(*this, m_terms[k]->m_last_V, "lastV." + num);
+ netlist().save(*this, m_terms[k]->m_DD_n_m_1, "m_DD_n_m_1." + num);
+ netlist().save(*this, m_terms[k]->m_h_n_m_1, "m_h_n_m_1." + num);
+
+ netlist().save(*this, m_terms[k]->go(),"GO" + num, m_terms[k]->count());
+ netlist().save(*this, m_terms[k]->gt(),"GT" + num, m_terms[k]->count());
+ netlist().save(*this, m_terms[k]->Idr(),"IDR" + num , m_terms[k]->count());
+ }
+
+ for (unsigned k=0; k<iN; k++)
+ delete [] touched[k];
+ delete [] touched;
+}
+
+void matrix_solver_t::update_inputs()
+{
+ // avoid recursive calls. Inputs are updated outside this call
+ for (auto &inp : m_inps)
+ inp->push(inp->m_proxied_net->Q_Analog());
+}
+
+void matrix_solver_t::update_dynamic()
+{
+ /* update all non-linear devices */
+ for (auto &dyn : m_dynamic_devices)
+ dyn->update_terminals();
+}
+
+void matrix_solver_t::reset()
+{
+ m_last_step = netlist_time::zero();
+}
+
+void matrix_solver_t::update() NL_NOEXCEPT
+{
+ const netlist_time new_timestep = solve();
+
+ if (m_params.m_dynamic && has_timestep_devices() && new_timestep > netlist_time::zero())
+ {
+ m_Q_sync.net().force_queue_execution();
+ m_Q_sync.net().reschedule_in_queue(new_timestep);
+ }
+}
+
+void matrix_solver_t::update_forced()
+{
+ ATTR_UNUSED const netlist_time new_timestep = solve();
+
+ if (m_params.m_dynamic && has_timestep_devices())
+ {
+ m_Q_sync.net().force_queue_execution();
+ m_Q_sync.net().reschedule_in_queue(netlist_time::from_double(m_params.m_min_timestep));
+ }
+}
+
+void matrix_solver_t::step(const netlist_time &delta)
+{
+ const nl_double dd = delta.as_double();
+ for (std::size_t k=0; k < m_step_devices.size(); k++)
+ m_step_devices[k]->timestep(dd);
+}
+
+void matrix_solver_t::solve_base()
+{
+ m_stat_vsolver_calls++;
+ if (has_dynamic_devices())
+ {
+ unsigned this_resched;
+ unsigned newton_loops = 0;
+ do
+ {
+ update_dynamic();
+ // Gauss-Seidel will revert to Gaussian elemination if steps exceeded.
+ this_resched = this->vsolve_non_dynamic(true);
+ newton_loops++;
+ } while (this_resched > 1 && newton_loops < m_params.m_nr_loops);
+
+ m_stat_newton_raphson += newton_loops;
+ // reschedule ....
+ if (this_resched > 1 && !m_Q_sync.net().is_queued())
+ {
+ log().warning("NEWTON_LOOPS exceeded on net {1}... reschedule", this->name());
+ m_Q_sync.net().toggle_new_Q();
+ m_Q_sync.net().reschedule_in_queue(m_params.m_nt_sync_delay);
+ }
+ }
+ else
+ {
+ this->vsolve_non_dynamic(false);
+ }
+}
+
+const netlist_time matrix_solver_t::solve()
+{
+ const netlist_time now = netlist().time();
+ const netlist_time delta = now - m_last_step;
+
+ // We are already up to date. Avoid oscillations.
+ // FIXME: Make this a parameter!
+ if (delta < netlist_time::quantum())
+ return netlist_time::zero();
+
+ /* update all terminals for new time step */
+ m_last_step = now;
+ step(delta);
+ solve_base();
+ const netlist_time next_time_step = compute_next_timestep(delta.as_double());
+
+ update_inputs();
+
+ return next_time_step;
+}
+
+int matrix_solver_t::get_net_idx(detail::net_t *net)
+{
+ for (std::size_t k = 0; k < m_nets.size(); k++)
+ if (m_nets[k] == net)
+ return static_cast<int>(k);
+ return -1;
+}
+
+void matrix_solver_t::add_term(std::size_t k, terminal_t *term)
+{
+ if (term->m_otherterm->net().isRailNet())
+ {
+ m_rails_temp[k]->add(term, -1, false);
+ }
+ else
+ {
+ int ot = get_net_idx(&term->m_otherterm->net());
+ if (ot>=0)
+ {
+ m_terms[k]->add(term, ot, true);
+ }
+ /* Should this be allowed ? */
+ else // if (ot<0)
+ {
+ m_rails_temp[k]->add(term, ot, true);
+ log().fatal("found term with missing othernet {1}\n", term->name());
+ }
+ }
+}
+
+netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
+{
+ nl_double new_solver_timestep = m_params.m_max_timestep;
+
+ if (m_params.m_dynamic)
+ {
+ /*
+ * FIXME: We should extend the logic to use either all nets or
+ * only output nets.
+ */
+ for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++)
+ {
+ analog_net_t *n = m_nets[k];
+ terms_t *t = m_terms[k];
+
+ const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
+ const nl_double hn = cur_ts;
+
+ //printf("%f %f %f %f\n", DD_n, t->m_DD_n_m_1, hn, t->m_h_n_m_1);
+ nl_double DD2 = (DD_n / hn - t->m_DD_n_m_1 / t->m_h_n_m_1) / (hn + t->m_h_n_m_1);
+ nl_double new_net_timestep;
+
+ t->m_h_n_m_1 = hn;
+ t->m_DD_n_m_1 = DD_n;
+ if (std::fabs(DD2) > NL_FCONST(1e-60)) // avoid div-by-zero
+ new_net_timestep = std::sqrt(m_params.m_lte / std::fabs(NL_FCONST(0.5)*DD2));
+ else
+ new_net_timestep = m_params.m_max_timestep;
+
+ if (new_net_timestep < new_solver_timestep)
+ new_solver_timestep = new_net_timestep;
+
+ t->m_last_V = n->Q_Analog();
+ }
+ if (new_solver_timestep < m_params.m_min_timestep)
+ {
+ //log().warning("Dynamic timestep below min timestep. Consider decreasing MIN_TIMESTEP: {1} us", new_solver_timestep*1.0e6);
+ new_solver_timestep = m_params.m_min_timestep;
+ }
+ }
+ //if (new_solver_timestep > 10.0 * hn)
+ // new_solver_timestep = 10.0 * hn;
+ /*
+ * FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere.
+ */
+ return std::max(netlist_time::from_double(new_solver_timestep), netlist_time::quantum() * 2);
+}
+
+
+
+void matrix_solver_t::log_stats()
+{
+ if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && this->m_params.m_log_stats)
+ {
+ log().verbose("==============================================");
+ log().verbose("Solver {1}", this->name());
+ log().verbose(" ==> {1} nets", this->m_nets.size()); //, (*(*groups[i].first())->m_core_terms.first())->name());
+ log().verbose(" has {1} elements", this->has_dynamic_devices() ? "dynamic" : "no dynamic");
+ log().verbose(" has {1} elements", this->has_timestep_devices() ? "timestep" : "no timestep");
+ log().verbose(" {1:6.3} average newton raphson loops",
+ static_cast<double>(this->m_stat_newton_raphson) / static_cast<double>(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<double>(this->m_stat_calculations()) / this->netlist().time().as_double(),
+ this->m_iterative_fail(),
+ 100.0 * static_cast<double>(this->m_iterative_fail())
+ / static_cast<double>(this->m_stat_calculations()),
+ static_cast<double>(this->m_iterative_total()) / static_cast<double>(this->m_stat_calculations()));
+ }
+}
+
+
+ } //namespace devices
+} // namespace netlist
+
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index f1473ce5931..aa3f7e86bfa 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -41,22 +41,9 @@ class terms_t
P_PREVENT_COPYING(terms_t)
public:
- terms_t()
- : m_railstart(0)
- , m_last_V(0.0)
- , m_DD_n_m_1(0.0)
- , m_h_n_m_1(1e-9)
- {}
-
- void clear()
- {
- m_term.clear();
- m_net_other.clear();
- m_gt.clear();
- m_go.clear();
- m_Idr.clear();
- m_other_curanalog.clear();
- }
+ terms_t();
+
+ void clear();
void add(terminal_t *term, int net_other, bool sorted);
@@ -100,6 +87,7 @@ public:
: analog_output_t(dev, aname)
, m_proxied_net(nullptr)
{ }
+ virtual ~proxied_analog_output_t();
analog_net_t *m_proxied_net; // only for proxy nets in analog input logic
};
@@ -118,21 +106,7 @@ public:
};
matrix_solver_t(netlist_t &anetlist, const pstring &name,
- const eSortType sort, const solver_parameters_t *params)
- : device_t(anetlist, name)
- , m_params(*params)
- , m_stat_calculations(*this, "m_stat_calculations", 0)
- , m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0)
- , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0)
- , m_iterative_fail(*this, "m_iterative_fail", 0)
- , m_iterative_total(*this, "m_iterative_total", 0)
- , m_last_step(*this, "m_last_step", netlist_time::zero())
- , m_fb_sync(*this, "FB_sync")
- , m_Q_sync(*this, "Q_sync")
- , m_sort(sort)
- {
- connect_post_start(m_fb_sync, m_Q_sync);
- }
+ const eSortType sort, const solver_parameters_t *params);
virtual ~matrix_solver_t();
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index b0c70ebbde4..25b32401620 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -59,510 +59,8 @@ namespace netlist
{
namespace devices
{
-void terms_t::add(terminal_t *term, int net_other, bool sorted)
-{
- if (sorted)
- for (unsigned i=0; i < m_net_other.size(); i++)
- {
- if (m_net_other[i] > net_other)
- {
- plib::container::insert_at(m_term, i, term);
- plib::container::insert_at(m_net_other, i, net_other);
- plib::container::insert_at(m_gt, i, 0.0);
- plib::container::insert_at(m_go, i, 0.0);
- plib::container::insert_at(m_Idr, i, 0.0);
- plib::container::insert_at(m_other_curanalog, i, nullptr);
- return;
- }
- }
- m_term.push_back(term);
- m_net_other.push_back(net_other);
- m_gt.push_back(0.0);
- m_go.push_back(0.0);
- m_Idr.push_back(0.0);
- m_other_curanalog.push_back(nullptr);
-}
-
-void terms_t::set_pointers()
-{
- for (unsigned i = 0; i < count(); i++)
- {
- m_term[i]->set_ptrs(&m_gt[i], &m_go[i], &m_Idr[i]);
- m_other_curanalog[i] = m_term[i]->m_otherterm->net().m_cur_Analog.ptr();
- }
-}
-
-// ----------------------------------------------------------------------------------------
-// matrix_solver
-// ----------------------------------------------------------------------------------------
-
-matrix_solver_t::~matrix_solver_t()
-{
- for (unsigned k = 0; k < m_terms.size(); k++)
- {
- plib::pfree(m_terms[k]);
- }
-
-}
-
-void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
-{
- log().debug("New solver setup\n");
-
- m_nets.clear();
- m_terms.clear();
-
- for (auto & net : nets)
- {
- m_nets.push_back(net);
- m_terms.push_back(plib::palloc<terms_t>());
- m_rails_temp.push_back(plib::palloc<terms_t>());
- }
-
- for (std::size_t k = 0; k < nets.size(); k++)
- {
- analog_net_t *net = nets[k];
-
- log().debug("setting up net\n");
-
- net->set_solver(this);
-
- for (auto &p : net->m_core_terms)
- {
- log().debug("{1} {2} {3}\n", p->name(), net->name(), net->isRailNet());
- switch (p->type())
- {
- case terminal_t::TERMINAL:
- if (p->device().is_timestep())
- if (!plib::container::contains(m_step_devices, &p->device()))
- m_step_devices.push_back(&p->device());
- if (p->device().is_dynamic())
- if (!plib::container::contains(m_dynamic_devices, &p->device()))
- m_dynamic_devices.push_back(&p->device());
- {
- terminal_t *pterm = dynamic_cast<terminal_t *>(p);
- add_term(k, pterm);
- }
- log().debug("Added terminal {1}\n", p->name());
- break;
- case terminal_t::INPUT:
- {
- proxied_analog_output_t *net_proxy_output = nullptr;
- for (auto & input : m_inps)
- if (input->m_proxied_net == &p->net())
- {
- net_proxy_output = input.get();
- break;
- }
-
- if (net_proxy_output == nullptr)
- {
- auto net_proxy_output_u = plib::make_unique<proxied_analog_output_t>(*this, this->name() + "." + plib::pfmt("m{1}")(m_inps.size()));
- net_proxy_output = net_proxy_output_u.get();
- m_inps.push_back(std::move(net_proxy_output_u));
- nl_assert(p->net().is_analog());
- net_proxy_output->m_proxied_net = static_cast<analog_net_t *>(&p->net());
- }
- net_proxy_output->net().add_terminal(*p);
- // FIXME: repeated
- net_proxy_output->net().rebuild_list();
- log().debug("Added input\n");
- }
- break;
- case terminal_t::OUTPUT:
- case terminal_t::PARAM:
- log().fatal("unhandled element found\n");
- break;
- }
- }
- log().debug("added net with {1} populated connections\n", net->m_core_terms.size());
- }
-
- /* now setup the matrix */
- setup_matrix();
-}
-
-void matrix_solver_t::setup_matrix()
-{
- const std::size_t iN = m_nets.size();
-
- for (std::size_t k = 0; k < iN; k++)
- {
- m_terms[k]->m_railstart = m_terms[k]->count();
- for (std::size_t i = 0; i < m_rails_temp[k]->count(); i++)
- this->m_terms[k]->add(m_rails_temp[k]->terms()[i], m_rails_temp[k]->net_other()[i], false);
-
- m_rails_temp[k]->clear(); // no longer needed
- m_terms[k]->set_pointers();
- }
-
- for (unsigned k = 0; k < iN; k++)
- plib::pfree(m_rails_temp[k]); // no longer needed
-
- m_rails_temp.clear();
-
- /* Sort in descending order by number of connected matrix voltages.
- * The idea is, that for Gauss-Seidel algo the first voltage computed
- * depends on the greatest number of previous voltages thus taking into
- * account the maximum amout of information.
- *
- * This actually improves performance on popeye slightly. Average
- * GS computations reduce from 2.509 to 2.370
- *
- * Smallest to largest : 2.613
- * Unsorted : 2.509
- * Largest to smallest : 2.370
- *
- * Sorting as a general matrix pre-conditioning is mentioned in
- * literature but I have found no articles about Gauss Seidel.
- *
- * For Gaussian Elimination however increasing order is better suited.
- * FIXME: Even better would be to sort on elements right of the matrix diagonal.
- *
- */
-
- if (m_sort != NOSORT)
- {
- int sort_order = (m_sort == DESCENDING ? 1 : -1);
-
- for (unsigned k = 0; k < iN - 1; k++)
- for (unsigned i = k+1; i < iN; i++)
- {
- if ((static_cast<int>(m_terms[k]->m_railstart) - static_cast<int>(m_terms[i]->m_railstart)) * sort_order < 0)
- {
- std::swap(m_terms[i], m_terms[k]);
- std::swap(m_nets[i], m_nets[k]);
- }
- }
-
- for (unsigned k = 0; k < iN; k++)
- {
- int *other = m_terms[k]->net_other();
- for (unsigned i = 0; i < m_terms[k]->count(); i++)
- if (other[i] != -1)
- other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_otherterm->net());
- }
- }
-
- /* create a list of non zero elements. */
- for (unsigned k = 0; k < iN; k++)
- {
- terms_t * t = m_terms[k];
- /* pretty brutal */
- int *other = t->net_other();
-
- t->m_nz.clear();
-
- for (unsigned i = 0; i < t->m_railstart; i++)
- if (!plib::container::contains(t->m_nz, static_cast<unsigned>(other[i])))
- t->m_nz.push_back(static_cast<unsigned>(other[i]));
-
- t->m_nz.push_back(k); // add diagonal
-
- /* and sort */
- std::sort(t->m_nz.begin(), t->m_nz.end());
- }
-
- /* create a list of non zero elements right of the diagonal
- * These list anticipate the population of array elements by
- * Gaussian elimination.
- */
- for (unsigned k = 0; k < iN; k++)
- {
- terms_t * t = m_terms[k];
- /* pretty brutal */
- int *other = t->net_other();
-
- if (k==0)
- t->m_nzrd.clear();
- else
- {
- t->m_nzrd = m_terms[k-1]->m_nzrd;
- for (auto j = t->m_nzrd.begin(); j != t->m_nzrd.end(); )
- {
- if (*j < k + 1)
- j = t->m_nzrd.erase(j);
- else
- ++j;
- }
- }
-
- for (unsigned i = 0; i < t->m_railstart; i++)
- if (!plib::container::contains(t->m_nzrd, static_cast<unsigned>(other[i])) && other[i] >= static_cast<int>(k + 1))
- t->m_nzrd.push_back(static_cast<unsigned>(other[i]));
-
- /* and sort */
- std::sort(t->m_nzrd.begin(), t->m_nzrd.end());
- }
-
- /* create a list of non zero elements below diagonal k
- * This should reduce cache misses ...
- */
-
- bool **touched = new bool*[iN];
- for (unsigned k=0; k<iN; k++)
- touched[k] = new bool[iN];
-
- for (unsigned k = 0; k < iN; k++)
- {
- for (unsigned j = 0; j < iN; j++)
- touched[k][j] = false;
- for (unsigned j = 0; j < m_terms[k]->m_nz.size(); j++)
- touched[k][m_terms[k]->m_nz[j]] = true;
- }
-
- unsigned ops = 0;
- for (unsigned k = 0; k < iN; k++)
- {
- ops++; // 1/A(k,k)
- for (unsigned row = k + 1; row < iN; row++)
- {
- if (touched[row][k])
- {
- ops++;
- if (!plib::container::contains(m_terms[k]->m_nzbd, row))
- m_terms[k]->m_nzbd.push_back(row);
- for (unsigned col = k + 1; col < iN; col++)
- if (touched[k][col])
- {
- touched[row][col] = true;
- ops += 2;
- }
- }
- }
- }
- log().verbose("Number of mults/adds for {1}: {2}", name(), ops);
-
- if ((0))
- for (unsigned k = 0; k < iN; k++)
- {
- pstring line = plib::pfmt("{1}")(k, "3");
- for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++)
- line += plib::pfmt(" {1}")(m_terms[k]->m_nzrd[j], "3");
- log().verbose("{1}", line);
- }
-
- /*
- * save states
- */
- for (unsigned k = 0; k < iN; k++)
- {
- pstring num = plib::pfmt("{1}")(k);
-
- netlist().save(*this, m_terms[k]->m_last_V, "lastV." + num);
- netlist().save(*this, m_terms[k]->m_DD_n_m_1, "m_DD_n_m_1." + num);
- netlist().save(*this, m_terms[k]->m_h_n_m_1, "m_h_n_m_1." + num);
-
- netlist().save(*this, m_terms[k]->go(),"GO" + num, m_terms[k]->count());
- netlist().save(*this, m_terms[k]->gt(),"GT" + num, m_terms[k]->count());
- netlist().save(*this, m_terms[k]->Idr(),"IDR" + num , m_terms[k]->count());
- }
-
- for (unsigned k=0; k<iN; k++)
- delete [] touched[k];
- delete [] touched;
-}
-
-void matrix_solver_t::update_inputs()
-{
- // avoid recursive calls. Inputs are updated outside this call
- for (auto &inp : m_inps)
- inp->push(inp->m_proxied_net->Q_Analog());
-}
-
-void matrix_solver_t::update_dynamic()
-{
- /* update all non-linear devices */
- for (auto &dyn : m_dynamic_devices)
- dyn->update_terminals();
-}
-
-void matrix_solver_t::reset()
-{
- m_last_step = netlist_time::zero();
-}
-
-void matrix_solver_t::update() NL_NOEXCEPT
-{
- const netlist_time new_timestep = solve();
-
- if (m_params.m_dynamic && has_timestep_devices() && new_timestep > netlist_time::zero())
- {
- m_Q_sync.net().force_queue_execution();
- m_Q_sync.net().reschedule_in_queue(new_timestep);
- }
-}
-
-void matrix_solver_t::update_forced()
-{
- ATTR_UNUSED const netlist_time new_timestep = solve();
-
- if (m_params.m_dynamic && has_timestep_devices())
- {
- m_Q_sync.net().force_queue_execution();
- m_Q_sync.net().reschedule_in_queue(netlist_time::from_double(m_params.m_min_timestep));
- }
-}
-
-void matrix_solver_t::step(const netlist_time &delta)
-{
- const nl_double dd = delta.as_double();
- for (std::size_t k=0; k < m_step_devices.size(); k++)
- m_step_devices[k]->timestep(dd);
-}
-
-void matrix_solver_t::solve_base()
-{
- m_stat_vsolver_calls++;
- if (has_dynamic_devices())
- {
- unsigned this_resched;
- unsigned newton_loops = 0;
- do
- {
- update_dynamic();
- // Gauss-Seidel will revert to Gaussian elemination if steps exceeded.
- this_resched = this->vsolve_non_dynamic(true);
- newton_loops++;
- } while (this_resched > 1 && newton_loops < m_params.m_nr_loops);
-
- m_stat_newton_raphson += newton_loops;
- // reschedule ....
- if (this_resched > 1 && !m_Q_sync.net().is_queued())
- {
- log().warning("NEWTON_LOOPS exceeded on net {1}... reschedule", this->name());
- m_Q_sync.net().toggle_new_Q();
- m_Q_sync.net().reschedule_in_queue(m_params.m_nt_sync_delay);
- }
- }
- else
- {
- this->vsolve_non_dynamic(false);
- }
-}
-
-const netlist_time matrix_solver_t::solve()
-{
- const netlist_time now = netlist().time();
- const netlist_time delta = now - m_last_step;
-
- // We are already up to date. Avoid oscillations.
- // FIXME: Make this a parameter!
- if (delta < netlist_time::quantum())
- return netlist_time::zero();
-
- /* update all terminals for new time step */
- m_last_step = now;
- step(delta);
- solve_base();
- const netlist_time next_time_step = compute_next_timestep(delta.as_double());
-
- update_inputs();
-
- return next_time_step;
-}
-
-int matrix_solver_t::get_net_idx(detail::net_t *net)
-{
- for (std::size_t k = 0; k < m_nets.size(); k++)
- if (m_nets[k] == net)
- return static_cast<int>(k);
- return -1;
-}
-
-void matrix_solver_t::add_term(std::size_t k, terminal_t *term)
-{
- if (term->m_otherterm->net().isRailNet())
- {
- m_rails_temp[k]->add(term, -1, false);
- }
- else
- {
- int ot = get_net_idx(&term->m_otherterm->net());
- if (ot>=0)
- {
- m_terms[k]->add(term, ot, true);
- }
- /* Should this be allowed ? */
- else // if (ot<0)
- {
- m_rails_temp[k]->add(term, ot, true);
- log().fatal("found term with missing othernet {1}\n", term->name());
- }
- }
-}
-
-netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
-{
- nl_double new_solver_timestep = m_params.m_max_timestep;
-
- if (m_params.m_dynamic)
- {
- /*
- * FIXME: We should extend the logic to use either all nets or
- * only output nets.
- */
- for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++)
- {
- analog_net_t *n = m_nets[k];
- terms_t *t = m_terms[k];
-
- const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
- const nl_double hn = cur_ts;
-
- //printf("%f %f %f %f\n", DD_n, t->m_DD_n_m_1, hn, t->m_h_n_m_1);
- nl_double DD2 = (DD_n / hn - t->m_DD_n_m_1 / t->m_h_n_m_1) / (hn + t->m_h_n_m_1);
- nl_double new_net_timestep;
-
- t->m_h_n_m_1 = hn;
- t->m_DD_n_m_1 = DD_n;
- if (std::fabs(DD2) > NL_FCONST(1e-60)) // avoid div-by-zero
- new_net_timestep = std::sqrt(m_params.m_lte / std::fabs(NL_FCONST(0.5)*DD2));
- else
- new_net_timestep = m_params.m_max_timestep;
-
- if (new_net_timestep < new_solver_timestep)
- new_solver_timestep = new_net_timestep;
-
- t->m_last_V = n->Q_Analog();
- }
- if (new_solver_timestep < m_params.m_min_timestep)
- {
- //log().warning("Dynamic timestep below min timestep. Consider decreasing MIN_TIMESTEP: {1} us", new_solver_timestep*1.0e6);
- new_solver_timestep = m_params.m_min_timestep;
- }
- }
- //if (new_solver_timestep > 10.0 * hn)
- // new_solver_timestep = 10.0 * hn;
- /*
- * FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere.
- */
- return std::max(netlist_time::from_double(new_solver_timestep), netlist_time::quantum() * 2);
-}
-
-void matrix_solver_t::log_stats()
-{
- if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && this->m_params.m_log_stats)
- {
- log().verbose("==============================================");
- log().verbose("Solver {1}", this->name());
- log().verbose(" ==> {1} nets", this->m_nets.size()); //, (*(*groups[i].first())->m_core_terms.first())->name());
- log().verbose(" has {1} elements", this->has_dynamic_devices() ? "dynamic" : "no dynamic");
- log().verbose(" has {1} elements", this->has_timestep_devices() ? "timestep" : "no timestep");
- log().verbose(" {1:6.3} average newton raphson loops",
- static_cast<double>(this->m_stat_newton_raphson) / static_cast<double>(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<double>(this->m_stat_calculations()) / this->netlist().time().as_double(),
- this->m_iterative_fail(),
- 100.0 * static_cast<double>(this->m_iterative_fail())
- / static_cast<double>(this->m_stat_calculations()),
- static_cast<double>(this->m_iterative_total()) / static_cast<double>(this->m_stat_calculations()));
- }
-}
-
// ----------------------------------------------------------------------------------------
// solver
diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp
index 3dc021cce64..9523febf06a 100644
--- a/src/lib/netlist/tools/nl_convert.cpp
+++ b/src/lib/netlist/tools/nl_convert.cpp
@@ -58,6 +58,19 @@ static lib_map_t read_lib_map(const pstring lm)
convert - convert a spice netlist
-------------------------------------------------*/
+nl_convert_base_t::nl_convert_base_t()
+ : out(m_buf)
+ , m_numberchars("0123456789-+e.")
+{
+}
+
+nl_convert_base_t::~nl_convert_base_t()
+{
+ m_nets.clear();
+ m_devs.clear();
+ m_pins.clear();
+}
+
void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias)
{
pstring pname = devname + "." + name;
@@ -384,19 +397,53 @@ void nl_convert_spice_t::process_line(const pstring &line)
}
}
+/*-------------------------------------------------
+ Eagle converter
+-------------------------------------------------*/
+
+nl_convert_eagle_t::tokenizer::tokenizer(nl_convert_eagle_t &convert, plib::pistream &strm)
+ : plib::ptokenizer(strm)
+ , m_convert(convert)
+{
+ set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
+ set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
+ char ws[5];
+ ws[0] = ' ';
+ ws[1] = 9;
+ ws[2] = 10;
+ ws[3] = 13;
+ ws[4] = 0;
+ set_whitespace(ws);
+ /* FIXME: gnetlist doesn't print comments */
+ set_comment("/*", "*/", "//");
+ set_string_char('\'');
+ m_tok_ADD = register_token("ADD");
+ m_tok_VALUE = register_token("VALUE");
+ m_tok_SIGNAL = register_token("SIGNAL");
+ m_tok_SEMICOLON = register_token(";");
+ /* currently not used, but required for parsing */
+ register_token(")");
+ register_token("(");
+}
+
+void nl_convert_eagle_t::tokenizer::verror(const pstring &msg, int line_num, const pstring &line)
+{
+ m_convert.out("{} (line {}): {}\n", msg.c_str(), line_num, line.c_str());
+}
+
//FIXME: should accept a stream as well
void nl_convert_eagle_t::convert(const pstring &contents)
{
plib::pistringstream istrm(contents);
- eagle_tokenizer tok(*this, istrm);
+ tokenizer tok(*this, istrm);
out("NETLIST_START(dummy)\n");
add_term("GND", "GND");
add_term("VCC", "VCC");
- eagle_tokenizer::token_t token = tok.get_token();
+ tokenizer::token_t token = tok.get_token();
while (true)
{
- if (token.is_type(eagle_tokenizer::ENDOFFILE))
+ if (token.is_type(tokenizer::ENDOFFILE))
{
dump_nl();
// FIXME: Parameter
@@ -492,6 +539,42 @@ void nl_convert_eagle_t::convert(const pstring &contents)
}
+/*-------------------------------------------------
+ RINF converter
+-------------------------------------------------*/
+
+nl_convert_rinf_t::tokenizer::tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm)
+ : plib::ptokenizer(strm)
+ , m_convert(convert)
+{
+ set_identifier_chars(".abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-");
+ set_number_chars("0123456789", "0123456789eE-."); //FIXME: processing of numbers
+ char ws[5];
+ ws[0] = ' ';
+ ws[1] = 9;
+ ws[2] = 10;
+ ws[3] = 13;
+ ws[4] = 0;
+ set_whitespace(ws);
+ /* FIXME: gnetlist doesn't print comments */
+ set_comment("","","//"); // FIXME:needs to be confirmed
+ set_string_char('"');
+ m_tok_HEA = register_token(".HEA");
+ m_tok_APP = register_token(".APP");
+ m_tok_TIM = register_token(".TIM");
+ m_tok_TYP = register_token(".TYP");
+ m_tok_ADDC = register_token(".ADD_COM");
+ m_tok_ATTC = register_token(".ATT_COM");
+ m_tok_NET = register_token(".ADD_TER");
+ m_tok_TER = register_token(".TER");
+ m_tok_END = register_token(".END");
+}
+
+void nl_convert_rinf_t::tokenizer::verror(const pstring &msg, int line_num, const pstring &line)
+{
+ m_convert.out("{} (line {}): {}\n", msg.c_str(), line_num, line.c_str());
+}
+
/* token_id_t m_tok_HFA;
token_id_t m_tok_APP;
token_id_t m_tok_TIM;
@@ -502,6 +585,7 @@ void nl_convert_eagle_t::convert(const pstring &contents)
token_id_t m_tok_TER;
*
*/
+
void nl_convert_rinf_t::convert(const pstring &contents)
{
plib::pistringstream istrm(contents);
diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h
index 859c5ea1e9c..3536488c766 100644
--- a/src/lib/netlist/tools/nl_convert.h
+++ b/src/lib/netlist/tools/nl_convert.h
@@ -23,13 +23,8 @@ class nl_convert_base_t
{
public:
- nl_convert_base_t() : out(m_buf), m_numberchars("0123456789-+e.") {}
- virtual ~nl_convert_base_t()
- {
- m_nets.clear();
- m_devs.clear();
- m_pins.clear();
- }
+ nl_convert_base_t();
+ virtual ~nl_convert_base_t();
const pstringbuffer &result() { return m_buf.str(); }
@@ -168,32 +163,10 @@ public:
{
}
- class eagle_tokenizer : public plib::ptokenizer
+ class tokenizer : public plib::ptokenizer
{
public:
- eagle_tokenizer(nl_convert_eagle_t &convert, plib::pistream &strm)
- : plib::ptokenizer(strm), m_convert(convert)
- {
- set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
- set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
- char ws[5];
- ws[0] = ' ';
- ws[1] = 9;
- ws[2] = 10;
- ws[3] = 13;
- ws[4] = 0;
- set_whitespace(ws);
- /* FIXME: gnetlist doesn't print comments */
- set_comment("/*", "*/", "//");
- set_string_char('\'');
- m_tok_ADD = register_token("ADD");
- m_tok_VALUE = register_token("VALUE");
- m_tok_SIGNAL = register_token("SIGNAL");
- m_tok_SEMICOLON = register_token(";");
- /* currently not used, but required for parsing */
- register_token(")");
- register_token("(");
- }
+ tokenizer(nl_convert_eagle_t &convert, plib::pistream &strm);
token_id_t m_tok_ADD;
token_id_t m_tok_VALUE;
@@ -202,11 +175,7 @@ public:
protected:
- void verror(const pstring &msg, int line_num, const pstring &line) override
- {
- m_convert.out("{} (line {}): {}\n", msg.c_str(), line_num, line.c_str());
- }
-
+ virtual void verror(const pstring &msg, int line_num, const pstring &line) override;
private:
nl_convert_eagle_t &m_convert;
@@ -233,31 +202,7 @@ public:
class tokenizer : public plib::ptokenizer
{
public:
- tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm)
- : plib::ptokenizer(strm), m_convert(convert)
- {
- set_identifier_chars(".abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-");
- set_number_chars("0123456789", "0123456789eE-."); //FIXME: processing of numbers
- char ws[5];
- ws[0] = ' ';
- ws[1] = 9;
- ws[2] = 10;
- ws[3] = 13;
- ws[4] = 0;
- set_whitespace(ws);
- /* FIXME: gnetlist doesn't print comments */
- set_comment("","","//"); // FIXME:needs to be confirmed
- set_string_char('"');
- m_tok_HEA = register_token(".HEA");
- m_tok_APP = register_token(".APP");
- m_tok_TIM = register_token(".TIM");
- m_tok_TYP = register_token(".TYP");
- m_tok_ADDC = register_token(".ADD_COM");
- m_tok_ATTC = register_token(".ATT_COM");
- m_tok_NET = register_token(".ADD_TER");
- m_tok_TER = register_token(".TER");
- m_tok_END = register_token(".END");
- }
+ tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm);
token_id_t m_tok_HEA;
token_id_t m_tok_APP;
@@ -271,11 +216,7 @@ public:
protected:
- void verror(const pstring &msg, int line_num, const pstring &line) override
- {
- m_convert.out("{} (line {}): {}\n", msg.c_str(), line_num, line.c_str());
- }
-
+ virtual void verror(const pstring &msg, int line_num, const pstring &line) override;
private:
nl_convert_rinf_t &m_convert;