summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/netlist/analog/nld_twoterm.cpp34
-rw-r--r--src/lib/netlist/analog/nld_twoterm.h35
-rw-r--r--src/lib/netlist/devices/nld_4020.cpp2
-rw-r--r--src/lib/netlist/devices/nld_4066.cpp2
-rw-r--r--src/lib/netlist/devices/nld_4316.cpp2
-rw-r--r--src/lib/netlist/devices/nld_74166.cpp2
-rw-r--r--src/lib/netlist/devices/nld_7493.cpp6
-rw-r--r--src/lib/netlist/devices/nld_9310.cpp29
-rw-r--r--src/lib/netlist/devices/nld_9316.cpp30
-rw-r--r--src/lib/netlist/devices/nld_mm5837.cpp2
-rw-r--r--src/lib/netlist/devices/nld_ne555.cpp2
-rw-r--r--src/lib/netlist/devices/nld_system.cpp4
-rw-r--r--src/lib/netlist/devices/nld_truthtable.cpp3
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp4
-rw-r--r--src/lib/netlist/devices/nlid_system.h2
-rw-r--r--src/lib/netlist/documentation/mainpage.dox.h1
-rw-r--r--src/lib/netlist/nl_base.cpp69
-rw-r--r--src/lib/netlist/nl_base.h152
-rw-r--r--src/lib/netlist/nl_config.h67
-rw-r--r--src/lib/netlist/nl_factory.h15
-rw-r--r--src/lib/netlist/nl_lists.h69
-rw-r--r--src/lib/netlist/nl_setup.cpp20
-rw-r--r--src/lib/netlist/nl_setup.h4
-rw-r--r--src/lib/netlist/nl_time.h69
-rw-r--r--src/lib/netlist/plib/pconfig.h142
-rw-r--r--src/lib/netlist/plib/pfunction.cpp110
-rw-r--r--src/lib/netlist/plib/pfunction.h22
-rw-r--r--src/lib/netlist/plib/plists.h1
-rw-r--r--src/lib/netlist/plib/pstring.cpp21
-rw-r--r--src/lib/netlist/plib/pstring.h36
-rw-r--r--src/lib/netlist/plib/putil.cpp2
-rw-r--r--src/lib/netlist/plib/putil.h2
-rw-r--r--src/lib/netlist/prg/nltool.cpp12
-rw-r--r--src/lib/netlist/prg/nlwav.cpp17
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp34
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h26
-rw-r--r--src/lib/netlist/solver/nld_ms_direct.h2
-rw-r--r--src/lib/netlist/solver/nld_ms_gcr.h83
-rw-r--r--src/lib/netlist/solver/nld_ms_gmres.h2
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp52
-rw-r--r--src/lib/netlist/solver/nld_solver.h4
-rw-r--r--src/lib/util/unicode.cpp2
42 files changed, 707 insertions, 488 deletions
diff --git a/src/lib/netlist/analog/nld_twoterm.cpp b/src/lib/netlist/analog/nld_twoterm.cpp
index 0e53d77f1f5..f676fe928ac 100644
--- a/src/lib/netlist/analog/nld_twoterm.cpp
+++ b/src/lib/netlist/analog/nld_twoterm.cpp
@@ -5,9 +5,10 @@
*
*/
-#include <solver/nld_solver.h>
#include <algorithm>
+#include "solver/nld_solver.h"
+
#include "nld_twoterm.h"
namespace netlist
@@ -23,6 +24,7 @@ generic_diode::generic_diode(device_t &dev, pstring name)
, m_Id(dev, name + ".m_Id", 0.0)
, m_G(dev, name + ".m_G", 1e-15)
, m_Vt(0.0)
+ , m_Vmin(0.0)
, m_Is(0.0)
, m_n(0.0)
, m_gmin(1e-15)
@@ -40,6 +42,7 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
m_gmin = gmin;
m_Vt = 0.0258 * m_n;
+ m_Vmin = -5.0 * m_Vt;
m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2);
m_VtInv = 1.0 / m_Vt;
@@ -47,8 +50,7 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
void generic_diode::update_diode(const nl_double nVd)
{
-#if 1
- if (nVd < NL_FCONST(-5.0) * m_Vt)
+ if (nVd < m_Vmin)
{
m_Vd = nVd;
m_G = m_gmin;
@@ -58,29 +60,19 @@ void generic_diode::update_diode(const nl_double nVd)
{
m_Vd = nVd;
//m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+ //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ m_Id = IseVDVt - m_Is;
+ m_G = IseVDVt * m_VtInv + m_gmin;
}
else
{
-#if 1
- const nl_double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
+ const double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
m_Vd = m_Vd + std::log1p(a) * m_Vt;
-#else
- m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
-#endif
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
-
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+ const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ m_Id = IseVDVt - m_Is;
+ m_G = IseVDVt * m_VtInv + m_gmin;
}
-#else
- m_Vd = m_Vd + 20.0 * m_Vt * std::tanh((nVd - m_Vd) / 20.0 / m_Vt);
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
-#endif
}
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/analog/nld_twoterm.h b/src/lib/netlist/analog/nld_twoterm.h
index 9494ad26520..44b3d29c16e 100644
--- a/src/lib/netlist/analog/nld_twoterm.h
+++ b/src/lib/netlist/analog/nld_twoterm.h
@@ -338,29 +338,30 @@ class generic_diode
public:
generic_diode(device_t &dev, pstring name);
- void update_diode(const nl_double nVd);
+ void update_diode(const double nVd);
- void set_param(const nl_double Is, const nl_double n, nl_double gmin);
+ void set_param(const double Is, const double n, double gmin);
- inline nl_double I() const { return m_Id; }
- inline nl_double G() const { return m_G; }
- inline nl_double Ieq() const { return (m_Id - m_Vd * m_G); }
- inline nl_double Vd() const { return m_Vd; }
+ inline double I() const { return m_Id; }
+ inline double G() const { return m_G; }
+ inline double Ieq() const { return (m_Id - m_Vd * m_G); }
+ inline double Vd() const { return m_Vd; }
/* owning object must save those ... */
private:
- state_var<nl_double> m_Vd;
- state_var<nl_double> m_Id;
- state_var<nl_double> m_G;
-
- nl_double m_Vt;
- nl_double m_Is;
- nl_double m_n;
- nl_double m_gmin;
-
- nl_double m_VtInv;
- nl_double m_Vcrit;
+ state_var<double> m_Vd;
+ state_var<double> m_Id;
+ state_var<double> m_G;
+
+ double m_Vt;
+ double m_Vmin;
+ double m_Is;
+ double m_n;
+ double m_gmin;
+
+ double m_VtInv;
+ double m_Vcrit;
};
/*! Class representing the diode model paramers.
diff --git a/src/lib/netlist/devices/nld_4020.cpp b/src/lib/netlist/devices/nld_4020.cpp
index a147cf3f58f..14459fb3b62 100644
--- a/src/lib/netlist/devices/nld_4020.cpp
+++ b/src/lib/netlist/devices/nld_4020.cpp
@@ -5,7 +5,7 @@
*
*/
-#include <devices/nlid_cmos.h>
+#include "devices/nlid_cmos.h"
#include "nld_4020.h"
namespace netlist
diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp
index f33688b73b7..f93bad59143 100644
--- a/src/lib/netlist/devices/nld_4066.cpp
+++ b/src/lib/netlist/devices/nld_4066.cpp
@@ -5,7 +5,7 @@
*
*/
-#include <devices/nlid_cmos.h>
+#include "devices/nlid_cmos.h"
#include "analog/nld_twoterm.h"
#include "nld_4066.h"
diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp
index 8b9cb0d46ad..1a3b5c77144 100644
--- a/src/lib/netlist/devices/nld_4316.cpp
+++ b/src/lib/netlist/devices/nld_4316.cpp
@@ -5,7 +5,7 @@
*
*/
-#include <devices/nlid_cmos.h>
+#include "devices/nlid_cmos.h"
#include "analog/nld_twoterm.h"
#include "nld_4316.h"
diff --git a/src/lib/netlist/devices/nld_74166.cpp b/src/lib/netlist/devices/nld_74166.cpp
index 5cb7114ee0f..c9e935cb0d1 100644
--- a/src/lib/netlist/devices/nld_74166.cpp
+++ b/src/lib/netlist/devices/nld_74166.cpp
@@ -82,7 +82,7 @@ namespace netlist
netlist_time delay = NLTIME_FROM_NS(26);
if (m_CLRQ())
{
- bool clear_unset = !m_last_CLRQ();
+ bool clear_unset = !m_last_CLRQ;
if (clear_unset)
{
delay = NLTIME_FROM_NS(35);
diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp
index 557d7fa42b6..151e407a210 100644
--- a/src/lib/netlist/devices/nld_7493.cpp
+++ b/src/lib/netlist/devices/nld_7493.cpp
@@ -29,8 +29,8 @@ namespace netlist
logic_input_t m_I;
logic_output_t m_Q;
- state_var_u8 m_reset;
- state_var_u8 m_state;
+ state_var<netlist_sig_t> m_reset;
+ state_var<netlist_sig_t> m_state;
};
NETLIB_OBJECT(7493)
@@ -99,7 +99,7 @@ namespace netlist
NETLIB_UPDATE(7493ff)
{
- constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
+ static constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
if (m_reset)
{
m_state ^= 1;
diff --git a/src/lib/netlist/devices/nld_9310.cpp b/src/lib/netlist/devices/nld_9310.cpp
index 4ddb62af519..c45f3bb1ed2 100644
--- a/src/lib/netlist/devices/nld_9310.cpp
+++ b/src/lib/netlist/devices/nld_9310.cpp
@@ -158,21 +158,22 @@ namespace netlist
{
if (m_loadq)
{
- switch (m_cnt())
+ if (m_cnt < MAXCNT - 1)
{
- case MAXCNT - 1:
- m_cnt = MAXCNT;
- m_RC.push(m_ent, NLTIME_FROM_NS(20));
- m_QA.push(1, NLTIME_FROM_NS(20));
- break;
- case MAXCNT:
- m_RC.push(0, NLTIME_FROM_NS(20));
- m_cnt = 0;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
- default:
- m_cnt++;
- update_outputs(m_cnt);
+ m_cnt++;
+ update_outputs(m_cnt);
+ }
+ else if (m_cnt == MAXCNT - 1)
+ {
+ m_cnt = MAXCNT;
+ m_RC.push(m_ent, NLTIME_FROM_NS(20));
+ m_QA.push(1, NLTIME_FROM_NS(20));
+ }
+ else // MAXCNT
+ {
+ m_RC.push(0, NLTIME_FROM_NS(20));
+ m_cnt = 0;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
}
}
else
diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp
index ea7ca9fc45c..d1a4ae7334b 100644
--- a/src/lib/netlist/devices/nld_9316.cpp
+++ b/src/lib/netlist/devices/nld_9316.cpp
@@ -161,22 +161,22 @@ namespace netlist
{
if (m_loadq)
{
- switch (m_cnt())
+ if (m_cnt < MAXCNT - 1)
{
- case MAXCNT - 1:
- m_cnt = MAXCNT;
- m_RC.push(m_ent, NLTIME_FROM_NS(27));
- m_QA.push(1, NLTIME_FROM_NS(20));
- break;
- case MAXCNT:
- m_RC.push(0, NLTIME_FROM_NS(27));
- m_cnt = 0;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
- default:
- m_cnt++;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
+ m_cnt++;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
+ }
+ else if (m_cnt == MAXCNT - 1)
+ {
+ m_cnt = MAXCNT;
+ m_RC.push(m_ent, NLTIME_FROM_NS(27));
+ m_QA.push(1, NLTIME_FROM_NS(20));
+ }
+ else // MAXCNT
+ {
+ m_RC.push(0, NLTIME_FROM_NS(27));
+ m_cnt = 0;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
}
}
else
diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp
index 256ced2d2a7..6be7d717221 100644
--- a/src/lib/netlist/devices/nld_mm5837.cpp
+++ b/src/lib/netlist/devices/nld_mm5837.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_mm5837.h"
-#include <solver/nld_matrix_solver.h>
+#include "solver/nld_matrix_solver.h"
#include "analog/nld_twoterm.h"
#define R_LOW (1000.0)
diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp
index 3cfd120be30..67b13fd32b3 100644
--- a/src/lib/netlist/devices/nld_ne555.cpp
+++ b/src/lib/netlist/devices/nld_ne555.cpp
@@ -7,7 +7,7 @@
#include "nld_ne555.h"
#include "analog/nld_twoterm.h"
-#include <solver/nld_solver.h>
+#include "solver/nld_solver.h"
#define R_OFF (1E20)
#define R_ON (25) // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2
diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp
index 2a403c070a3..e3585271696 100644
--- a/src/lib/netlist/devices/nld_system.cpp
+++ b/src/lib/netlist/devices/nld_system.cpp
@@ -5,8 +5,8 @@
*
*/
-#include <solver/nld_solver.h>
-#include <solver/nld_matrix_solver.h>
+#include "solver/nld_solver.h"
+#include "solver/nld_matrix_solver.h"
#include "nlid_system.h"
namespace netlist
diff --git a/src/lib/netlist/devices/nld_truthtable.cpp b/src/lib/netlist/devices/nld_truthtable.cpp
index 1e786805eda..e7cedfba13f 100644
--- a/src/lib/netlist/devices/nld_truthtable.cpp
+++ b/src/lib/netlist/devices/nld_truthtable.cpp
@@ -8,6 +8,7 @@
#include "nld_truthtable.h"
#include "plib/plists.h"
#include "nl_setup.h"
+#include "plib/palloc.h"
namespace netlist
{
@@ -272,7 +273,7 @@ netlist_base_factory_truthtable_t::~netlist_base_factory_truthtable_t()
#define ENTRYY(n, m, s) case (n * 100 + m): \
{ using xtype = netlist_factory_truthtable_t<n, m>; \
- ret = new xtype(desc.name, desc.classname, desc.def_param, s); } break
+ ret = plib::palloc<xtype>(desc.name, desc.classname, desc.def_param, s); } break
#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \
ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s)
diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp
index 3edb25f73e2..59f6f39420b 100644
--- a/src/lib/netlist/devices/nlid_proxy.cpp
+++ b/src/lib/netlist/devices/nlid_proxy.cpp
@@ -113,9 +113,9 @@ namespace netlist
{
pstring devname = out_proxied->device().name();
auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0],
- detail::device_object_t::type_t::INPUT, false);
+ detail::core_terminal_t::type_t::INPUT, false);
auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1],
- detail::device_object_t::type_t::INPUT, false);
+ detail::core_terminal_t::type_t::INPUT, false);
if (tp != nullptr && tn != nullptr)
{
/* alternative logic */
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index f2d893c7d28..5c29d40fd94 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -323,7 +323,7 @@ namespace netlist
inps.push_back(n);
m_vals.push_back(0.0);
}
- m_precompiled.compile_postfix(inps, m_func());
+ m_precompiled.compile(inps, m_func());
}
protected:
diff --git a/src/lib/netlist/documentation/mainpage.dox.h b/src/lib/netlist/documentation/mainpage.dox.h
index 75df1a18065..744abe642e6 100644
--- a/src/lib/netlist/documentation/mainpage.dox.h
+++ b/src/lib/netlist/documentation/mainpage.dox.h
@@ -161,5 +161,4 @@ equation solver.
The formal representation of the circuit will stay the same, thus scales.
-
*/
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 6128200fe9a..90149f44e8e 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -25,7 +25,7 @@ namespace netlist
namespace detail
{
#if (USE_MEMPOOL)
-static plib::mempool pool(65536, 8);
+static plib::mempool pool(6553600, 64);
void * object_t::operator new (size_t size)
{
@@ -184,7 +184,7 @@ void detail::queue_t::on_post_load()
detail::net_t *n = netlist().find_net(pstring(m_names[i].m_buf, pstring::UTF8));
//log().debug("Got {1} ==> {2}\n", qtemp[i].m_name, n));
//log().debug("schedule time {1} ({2})\n", n->time().as_double(), netlist_time::from_raw(m_times[i]).as_double()));
- this->push(n, netlist_time::from_raw(m_times[i]));
+ this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
}
}
@@ -216,20 +216,18 @@ detail::device_object_t::device_object_t(core_device_t &dev, const pstring &anam
{
}
-detail::device_object_t::type_t detail::device_object_t::type() const
+detail::core_terminal_t::type_t detail::core_terminal_t::type() const
{
if (dynamic_cast<const terminal_t *>(this) != nullptr)
return type_t::TERMINAL;
- else if (dynamic_cast<const param_t *>(this) != nullptr)
- return param_t::PARAM;
else if (dynamic_cast<const logic_input_t *>(this) != nullptr)
- return param_t::INPUT;
+ return type_t::INPUT;
else if (dynamic_cast<const logic_output_t *>(this) != nullptr)
- return param_t::OUTPUT;
+ return type_t::OUTPUT;
else if (dynamic_cast<const analog_input_t *>(this) != nullptr)
- return param_t::INPUT;
+ return type_t::INPUT;
else if (dynamic_cast<const analog_output_t *>(this) != nullptr)
- return param_t::OUTPUT;
+ return type_t::OUTPUT;
else
{
netlist().log().fatal(MF_1_UNKNOWN_TYPE_FOR_OBJECT, name());
@@ -254,19 +252,16 @@ netlist_t::netlist_t(const pstring &aname)
{
state().save_item(this, static_cast<plib::state_manager_t::callback_t &>(m_queue), "m_queue");
state().save_item(this, m_time, "m_time");
- m_setup = new setup_t(*this);
+ m_setup = plib::make_unique<setup_t>(*this);
/* FIXME: doesn't really belong here */
NETLIST_NAME(base)(*m_setup);
}
netlist_t::~netlist_t()
{
- if (m_setup != nullptr)
- delete m_setup;
m_nets.clear();
m_devices.clear();
- pfree(m_lib);
pstring::resetmem();
}
@@ -356,7 +351,7 @@ void netlist_t::start()
}
pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"}));
- m_lib = plib::palloc<plib::dynlib>(libpath);
+ m_lib = plib::make_unique<plib::dynlib>(libpath);
/* resolve inputs */
setup().resolve_inputs();
@@ -448,7 +443,7 @@ void netlist_t::process_queue(const netlist_time &delta)
{
netlist_time stop(m_time + delta);
- m_queue.push(nullptr, stop);
+ m_queue.push(detail::queue_t::entry_t(stop, nullptr));
m_stat_mainloop.start();
@@ -475,17 +470,20 @@ void netlist_t::process_queue(const netlist_time &delta)
while (m_queue.top().m_exec_time > mc_time)
{
m_time = mc_time;
- mc_time += inc;
mc_net.toggle_new_Q();
mc_net.update_devs();
+ mc_time += inc;
}
const detail::queue_t::entry_t e(m_queue.pop());
m_time = e.m_exec_time;
- if (e.m_object == nullptr)
+ if (e.m_object != nullptr)
+ {
+ e.m_object->update_devs();
+ m_perf_out_processed.inc();
+ }
+ else
break;
- e.m_object->update_devs();
- m_perf_out_processed.inc();
}
mc_net.set_time(mc_time);
}
@@ -578,7 +576,7 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner)
, m_hint_deactivate(false)
-#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{
@@ -591,7 +589,7 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner.netlist())
, m_hint_deactivate(false)
-#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{
@@ -607,14 +605,8 @@ core_device_t::~core_device_t()
void core_device_t::set_delegate_pointer()
{
-#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- void (core_device_t::* pFunc)() = &core_device_t::update;
- m_static_update = pFunc;
-#elif (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
- void (core_device_t::* pFunc)() = &core_device_t::update;
- m_static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
-#elif (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)
- m_static_update = plib::mfp::get_mfp<net_update_delegate>(&core_device_t::update, this);
+#if (!NL_USE_PMF_VIRTUAL)
+ m_static_update.set_base(&core_device_t::update, this);
#endif
}
@@ -692,13 +684,6 @@ detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_
// net_t
// ----------------------------------------------------------------------------------------
-// FIXME: move somewhere central
-
-struct do_nothing_deleter{
- template<typename T> void operator()(T*){}
-};
-
-
detail::net_t::net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr)
: object_t(aname)
, netlist_ref(nl)
@@ -731,7 +716,7 @@ void detail::net_t::inc_active(core_terminal_t &term) NL_NOEXCEPT
if (m_time > netlist().time())
{
m_in_queue = 1; /* pending */
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
else
{
@@ -1106,11 +1091,11 @@ param_double_t::param_double_t(device_t &device, const pstring name, const doubl
m_param = device.setup().get_initial_param_val(this->name(),val);
netlist().save(*this, m_param, "m_param");
}
-
+#if 0
param_double_t::~param_double_t()
{
}
-
+#endif
param_int_t::param_int_t(device_t &device, const pstring name, const int val)
: param_t(device, name)
{
@@ -1118,9 +1103,11 @@ param_int_t::param_int_t(device_t &device, const pstring name, const int val)
netlist().save(*this, m_param, "m_param");
}
+#if 0
param_int_t::~param_int_t()
{
}
+#endif
param_logic_t::param_logic_t(device_t &device, const pstring name, const bool val)
: param_t(device, name)
@@ -1129,9 +1116,11 @@ param_logic_t::param_logic_t(device_t &device, const pstring name, const bool va
netlist().save(*this, m_param, "m_param");
}
+#if 0
param_logic_t::~param_logic_t()
{
}
+#endif
param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
: param_t(device, name)
@@ -1140,9 +1129,11 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
//netlist().save(*this, m_param, "m_param");
}
+#if 0
param_ptr_t::~param_ptr_t()
{
}
+#endif
void param_model_t::changed()
{
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 57d1e197378..b1b4dac9341 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -29,7 +29,7 @@
// ----------------------------------------------------------------------------------------
/*! netlist_sig_t is the type used for logic signals. */
-using netlist_sig_t = std::uint_least32_t;
+using netlist_sig_t = std::uint32_t;
//============================================================
// MACROS / New Syntax
@@ -281,12 +281,12 @@ namespace netlist
public:
logic_family_t() : m_logic_family(nullptr) {}
- ~logic_family_t() { }
const logic_family_desc_t *logic_family() const { return m_logic_family; }
void set_logic_family(const logic_family_desc_t *fam) { m_logic_family = fam; }
protected:
+ ~logic_family_t() { } // prohibit polymorphic destruction
const logic_family_desc_t *m_logic_family;
};
@@ -321,19 +321,15 @@ namespace netlist
//! Move Constructor.
state_var(state_var &&rhs) NL_NOEXCEPT = default;
//! Assignment operator to assign value of a state var.
- state_var &operator=(state_var rhs) { std::swap(rhs.m_value, this->m_value); return *this; }
+ state_var &operator=(const state_var &rhs) { m_value = rhs; return *this; }
//! Assignment operator to assign value of type T.
- state_var &operator=(const T rhs) { m_value = rhs; return *this; }
+ state_var &operator=(const T &rhs) { m_value = rhs; return *this; }
//! Return value of state variable.
operator T & () { return m_value; }
- //! Return value of state variable.
- T & operator()() { return m_value; }
- //! Return const value of state variable.
- operator const T & () const { return m_value; }
//! Return const value of state variable.
- const T & operator()() const { return m_value; }
+ constexpr operator const T & () const { return m_value; }
T * ptr() { return &m_value; }
- const T * ptr() const { return &m_value; }
+ constexpr T * ptr() const { return &m_value; }
private:
T m_value;
};
@@ -346,13 +342,20 @@ namespace netlist
struct state_var<T[N]>
{
public:
- state_var(device_t &dev, const pstring name, const T & value);
+ //! Constructor.
+ template <typename O>
+ state_var(O &owner, //!< owner must have a netlist() method.
+ const pstring name, //!< identifier/name for this state variable
+ const T &value //!< Initial value after construction
+ );
+ //! Copy Constructor.
state_var(const state_var &rhs) NL_NOEXCEPT = default;
+ //! Move Constructor.
state_var(state_var &&rhs) NL_NOEXCEPT = default;
- state_var &operator=(const state_var rhs) { m_value = rhs.m_value; return *this; }
- state_var &operator=(const T rhs) { m_value = rhs; return *this; }
+ state_var &operator=(const state_var &rhs) { m_value = rhs.m_value; return *this; }
+ state_var &operator=(const T &rhs) { m_value = rhs; return *this; }
T & operator[](const std::size_t i) { return m_value[i]; }
- const T & operator[](const std::size_t i) const { return m_value[i]; }
+ constexpr T & operator[](const std::size_t i) const { return m_value[i]; }
private:
T m_value[N];
};
@@ -392,7 +395,6 @@ namespace netlist
* Every class derived from the object_t class must have a name.
*/
object_t(const pstring &aname /*!< string containing name of the object */);
- virtual ~object_t();
/*! return name of the object
*
@@ -404,6 +406,8 @@ namespace netlist
void operator delete (void *ptr, void *) { }
void * operator new (size_t size);
void operator delete (void * mem);
+ protected:
+ ~object_t(); // only childs should be destructible
private:
pstring m_name;
@@ -412,11 +416,13 @@ namespace netlist
struct detail::netlist_ref
{
netlist_ref(netlist_t &nl) : m_netlist(nl) { }
- ~netlist_ref() {}
netlist_t & netlist() { return m_netlist; }
const netlist_t & netlist() const { return m_netlist; }
+ protected:
+ ~netlist_ref() {} // prohibit polymorphic destruction
+
private:
netlist_t & m_netlist;
@@ -435,14 +441,6 @@ namespace netlist
{
P_PREVENT_COPYING(device_object_t)
public:
- /*! Enum specifying the type of object */
- enum type_t {
- TERMINAL = 0, /*!< object is an analog terminal */
- INPUT = 1, /*!< object is an input */
- OUTPUT = 2, /*!< object is an output */
- PARAM = 3, /*!< object is a parameter */
- };
-
/*! Constructor.
*
* \param dev device owning the object.
@@ -454,16 +452,6 @@ namespace netlist
*/
core_device_t &device() const { return m_device; }
- /*! The object type.
- * \returns type of the object
- */
- type_t type() const;
- /*! Checks if object is of specified type.
- * \param atype type to check object against.
- * \returns true if object is of specified type else false.
- */
- bool is_type(const type_t atype) const { return (type() == atype); }
-
/*! The netlist owning the owner of this object.
* \returns reference to netlist object.
*/
@@ -500,9 +488,26 @@ namespace netlist
STATE_BIDIR = 256
};
+ /*! Enum specifying the type of object */
+ enum type_t {
+ TERMINAL = 0, /*!< object is an analog terminal */
+ INPUT = 1, /*!< object is an input */
+ OUTPUT = 2, /*!< object is an output */
+ };
+
core_terminal_t(core_device_t &dev, const pstring &aname, const state_e state);
virtual ~core_terminal_t();
+ /*! The object type.
+ * \returns type of the object
+ */
+ type_t type() const;
+ /*! Checks if object is of specified type.
+ * \param atype type to check object against.
+ * \returns true if object is of specified type else false.
+ */
+ bool is_type(const type_t atype) const { return (type() == atype); }
+
void set_net(net_t *anet);
void clear_net();
bool has_net() const { return (m_net != nullptr); }
@@ -706,12 +711,6 @@ namespace netlist
void reset();
- void add_terminal(core_terminal_t &terminal);
- void remove_terminal(core_terminal_t &terminal);
-
- bool is_logic() const NL_NOEXCEPT;
- bool is_analog() const NL_NOEXCEPT;
-
void toggle_new_Q() { m_new_Q ^= 1; }
void force_queue_execution() { m_new_Q = (m_cur_Q ^ 1); }
@@ -732,6 +731,14 @@ namespace netlist
void inc_active(core_terminal_t &term) NL_NOEXCEPT;
void dec_active(core_terminal_t &term) NL_NOEXCEPT;
+ /* setup stuff */
+
+ void add_terminal(core_terminal_t &terminal);
+ void remove_terminal(core_terminal_t &terminal);
+
+ bool is_logic() const NL_NOEXCEPT;
+ bool is_analog() const NL_NOEXCEPT;
+
void rebuild_list(); /* rebuild m_list after a load */
void move_connections(net_t &dest_net);
@@ -764,7 +771,7 @@ namespace netlist
virtual ~logic_net_t();
netlist_sig_t Q() const { return m_cur_Q; }
- netlist_sig_t new_Q() const { return m_new_Q; }
+ netlist_sig_t new_Q() const { return m_new_Q; }
void initial(const netlist_sig_t val) { m_cur_Q = m_new_Q = val; }
void set_Q(const netlist_sig_t newQ, const netlist_time delay) NL_NOEXCEPT
@@ -789,7 +796,7 @@ namespace netlist
/* internal state support
* FIXME: get rid of this and implement export/import in MAME
*/
- netlist_sig_t &Q_state_ptr() { return m_cur_Q; }
+ netlist_sig_t *Q_state_ptr() { return m_cur_Q.ptr(); }
protected:
private:
@@ -808,7 +815,7 @@ namespace netlist
virtual ~analog_net_t();
nl_double Q_Analog() const { return m_cur_Analog; }
- nl_double &Q_Analog_state_ptr() { return m_cur_Analog; }
+ nl_double *Q_Analog_state_ptr() { return m_cur_Analog.ptr(); }
//FIXME: needed by current solver code
devices::matrix_solver_t *solver() const { return m_solver; }
@@ -874,11 +881,12 @@ namespace netlist
};
param_t(device_t &device, const pstring &name);
- virtual ~param_t();
param_type_t param_type() const;
protected:
+ virtual ~param_t(); /* not intended to be destroyed */
+
void update_param();
template<typename C>
@@ -897,7 +905,6 @@ namespace netlist
{
public:
param_ptr_t(device_t &device, const pstring name, std::uint8_t* val);
- virtual ~param_ptr_t();
std::uint8_t * operator()() const { return m_param; }
void setTo(std::uint8_t *param) { set(m_param, param); }
private:
@@ -908,7 +915,6 @@ namespace netlist
{
public:
param_logic_t(device_t &device, const pstring name, const bool val);
- virtual ~param_logic_t();
bool operator()() const { return m_param; }
void setTo(const bool &param) { set(m_param, param); }
private:
@@ -919,7 +925,6 @@ namespace netlist
{
public:
param_int_t(device_t &device, const pstring name, const int val);
- virtual ~param_int_t();
int operator()() const { return m_param; }
void setTo(const int &param) { set(m_param, param); }
private:
@@ -930,7 +935,6 @@ namespace netlist
{
public:
param_double_t(device_t &device, const pstring name, const double val);
- virtual ~param_double_t();
double operator()() const { return m_param; }
void setTo(const double &param) { set(m_param, param); }
private:
@@ -942,6 +946,7 @@ namespace netlist
public:
param_str_t(device_t &device, const pstring name, const pstring val);
virtual ~param_str_t();
+
const pstring operator()() const { return Value(); }
void setTo(const pstring &param)
{
@@ -1082,12 +1087,10 @@ namespace netlist
void do_update() NL_NOEXCEPT
{
- #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- (this->*m_static_update)();
- #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
- m_static_update(this);
+ #if (NL_USE_PMF_VIRTUAL)
+ update();
#else
- update();
+ m_static_update.call(this);
#endif
}
@@ -1104,14 +1107,9 @@ namespace netlist
private:
bool m_hint_deactivate;
- #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- typedef void (core_device_t::*net_update_delegate)();
- #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
- using net_update_delegate = MEMBER_ABI void (*)(core_device_t *);
- #endif
- #if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
- net_update_delegate m_static_update;
+ #if (!NL_USE_PMF_VIRTUAL)
+ plib::pmfp_base<void> m_static_update;
#endif
};
@@ -1135,7 +1133,7 @@ namespace netlist
template<class C, typename... Args>
void register_sub(const pstring &name, std::unique_ptr<C> &dev, const Args&... args)
{
- dev.reset(new C(*this, name, args...));
+ dev.reset(plib::palloc<C>(*this, name, args...));
}
void register_subalias(const pstring &name, detail::core_terminal_t &term);
@@ -1277,11 +1275,11 @@ namespace netlist
template<typename O, typename C> void save(O &owner, C &state, const pstring &stname)
{
- this->state().save_item(static_cast<void *>(&owner), state, pstring::from_utf8(owner.name()) + pstring(".") + stname);
+ this->state().save_item(static_cast<void *>(&owner), state, from_utf8(owner.name()) + pstring(".") + stname);
}
template<typename O, typename C> void save(O &owner, C *state, const pstring &stname, const std::size_t count)
{
- this->state().save_state_ptr(static_cast<void *>(&owner), pstring::from_utf8(owner.name()) + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
+ this->state().save_state_ptr(static_cast<void *>(&owner), from_utf8(owner.name()) + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
}
void rebuild_lists(); /* must be called after post_load ! */
@@ -1299,6 +1297,10 @@ namespace netlist
private:
+ /* helper for save above */
+ static pstring from_utf8(const char *c) { return pstring(c, pstring::UTF8); }
+ static pstring from_utf8(const pstring &c) { return c; }
+
core_device_t *pget_single_device(const pstring classname, bool (*cc)(core_device_t *));
/* mostly rw */
@@ -1312,9 +1314,9 @@ namespace netlist
devices::NETLIB_NAME(netlistparams) *m_params;
pstring m_name;
- setup_t * m_setup;
+ std::unique_ptr<setup_t> m_setup;
plib::plog_base<NL_DEBUG> m_log;
- plib::dynlib * m_lib; // external lib needs to be loaded as long as netlist exists
+ std::unique_ptr<plib::dynlib> m_lib; // external lib needs to be loaded as long as netlist exists
plib::state_manager_t m_state;
@@ -1424,7 +1426,7 @@ namespace netlist
m_time = netlist().time() + delay;
m_in_queue = (m_active > 0); /* queued ? */
if (m_in_queue)
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
}
@@ -1436,7 +1438,7 @@ namespace netlist
m_time = netlist().time() + delay;
m_in_queue = (m_active > 0); /* queued ? */
if (m_in_queue)
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
inline const analog_net_t & analog_t::net() const NL_NOEXCEPT
@@ -1453,7 +1455,7 @@ namespace netlist
inline logic_net_t & logic_t::net() NL_NOEXCEPT
{
- return *static_cast<logic_net_t *>(&core_terminal_t::net());
+ return static_cast<logic_net_t &>(core_terminal_t::net());
}
inline const logic_net_t & logic_t::net() const NL_NOEXCEPT
@@ -1490,9 +1492,10 @@ namespace netlist
}
template <typename T, std::size_t N>
- state_var<T[N]>::state_var(device_t &dev, const pstring name, const T & value)
+ template <typename O>
+ state_var<T[N]>::state_var(O &owner, const pstring name, const T & value)
{
- dev.netlist().save(dev, m_value, name);
+ owner.netlist().save(owner, m_value, name);
for (std::size_t i=0; i<N; i++)
m_value[i] = value;
}
@@ -1509,5 +1512,14 @@ namespace netlist
}
+namespace plib
+{
+ template<typename X>
+ struct ptype_traits<netlist::state_var<X>> : ptype_traits<X>
+ {
+ };
+}
+
+
#endif /* NLBASE_H_ */
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index 88f240394be..174549410d6 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -18,59 +18,6 @@
// SETUP
//============================================================
-/*
- * The following options determine how object::update is called.
- * NL_PMF_TYPE_VIRTUAL
- * Use stock virtual call
- *
- * NL_PMF_TYPE_GNUC_PMF
- * Use standard pointer to member function syntax
- *
- * NL_PMF_TYPE_GNUC_PMF_CONV
- * Use gnu extension and convert the pmf to a function pointer.
- * This is not standard compliant and needs
- * -Wno-pmf-conversions to compile.
- *
- * NL_PMF_TYPE_INTERNAL
- * Use the same approach as MAME for deriving the function pointer.
- * This is compiler-dependant as well
- *
- * Benchmarks for ./nltool -c run -f src/mame/drivers/nl_pong.c -t 10 -n pong_fast
- *
- * NL_PMF_TYPE_INTERNAL: 215%
- * NL_PMF_TYPE_GNUC_PMF: 163%
- * NL_PMF_TYPE_GNUC_PMF_CONV: 215%
- * NL_PMF_TYPE_VIRTUAL: 213%
- *
- * The whole exercise was done to avoid virtual calls. In prior versions of
- * netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
- * Since than, was removed from functions declared as virtual.
- * This may explain that the recent benchmarks show no difference at all.
- *
- * Disappointing is the GNUC_PMF performance.
- */
-
-// This will be autodetected
-// #define NL_PMF_TYPE 0
-
-#define NL_PMF_TYPE_VIRTUAL 0
-#define NL_PMF_TYPE_GNUC_PMF 1
-#define NL_PMF_TYPE_GNUC_PMF_CONV 2
-#define NL_PMF_TYPE_INTERNAL 3
-
-#ifndef NL_PMF_TYPE
- #if PHAS_PMF_INTERNAL
- #define NL_PMF_TYPE NL_PMF_TYPE_INTERNAL
- #else
- #define NL_PMF_TYPE NL_PMF_TYPE_VIRTUAL
- #endif
-#endif
-
-#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
-#pragma GCC diagnostic ignored "-Wpmf-conversions"
-#endif
-
-
//============================================================
// GENERAL
@@ -156,6 +103,20 @@ using nperfcount_t = plib::chrono::counter<false>;
#define NL_FCONST(x) x
using nl_double = double;
+/* The following option determines how object::update is called.
+ * If set to 1, a virtual call is used. If it is left undefined, the best
+ * approach will be automatically selected.
+ */
+
+//#define NL_USE_PMF_VIRTUAL 1
+
+#ifndef NL_USE_PMF_VIRTUAL
+ #if PPMF_TYPE == PPMF_TYPE_PMF
+ #define NL_USE_PMF_VIRTUAL 1
+ #else
+ #define NL_USE_PMF_VIRTUAL 0
+ #endif
+#endif
//============================================================
// WARNINGS
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index 8c911e2a0bd..f5a38d416da 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -17,12 +17,11 @@
#include "plib/putil.h"
#include "nl_base.h"
-#if 1
#define NETLIB_DEVICE_IMPL(chip) \
static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
const pstring &name, const pstring &classname, const pstring &def_param) \
{ \
- return std::unique_ptr<factory::element_t>(new factory::device_element_t<NETLIB_NAME(chip)>(name, classname, def_param, pstring(__FILE__))); \
+ return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
} \
factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
@@ -30,16 +29,10 @@
static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
const pstring &name, const pstring &classname, const pstring &def_param) \
{ \
- return std::unique_ptr<factory::element_t>(new factory::device_element_t<ns :: NETLIB_NAME(chip)>(name, classname, def_param, pstring(__FILE__))); \
+ return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<ns :: NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
} \
factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
-#else
-#define NETLIB_DEVICE_IMPL(chip) factory::constructor_ptr_t decl_ ## chip = factory::constructor_t< NETLIB_NAME(chip) >;
-#define NETLIB_DEVICE_IMPL_NS(ns, chip) factory::constructor_ptr_t decl_ ## chip = factory::constructor_t< ns :: NETLIB_NAME(chip) >;
-#endif
-
-
namespace netlist { namespace factory
{
// -----------------------------------------------------------------------------
@@ -99,7 +92,7 @@ namespace netlist { namespace factory
void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- register_device(std::unique_ptr<element_t>(new device_element_t<device_class>(name, classname, def_param)));
+ register_device(std::unique_ptr<element_t>(plib::palloc<device_element_t<device_class>>(name, classname, def_param)));
}
void register_device(std::unique_ptr<element_t> factory);
@@ -127,7 +120,7 @@ namespace netlist { namespace factory
std::unique_ptr<element_t> constructor_t(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- return std::unique_ptr<element_t>(new device_element_t<T>(name, classname, def_param));
+ return std::unique_ptr<element_t>(plib::palloc<device_element_t<T>>(name, classname, def_param));
}
// -----------------------------------------------------------------------------
diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h
index 2b378dadf71..9d35adf20ef 100644
--- a/src/lib/netlist/nl_lists.h
+++ b/src/lib/netlist/nl_lists.h
@@ -11,6 +11,8 @@
#define NLLISTS_H_
#include <atomic>
+#include <thread>
+#include <mutex>
#include "nl_config.h"
#include "plib/plists.h"
@@ -26,30 +28,24 @@ namespace netlist
//FIXME: move to an appropriate place
template<bool enabled_ = true>
- class pspin_lock
+ class pspin_mutex
{
public:
- pspin_lock() { }
- void acquire() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
- void release() noexcept { m_lock.clear(std::memory_order_release); }
+ pspin_mutex() noexcept { }
+ void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
+ void unlock() noexcept { m_lock.clear(std::memory_order_release); }
private:
std::atomic_flag m_lock = ATOMIC_FLAG_INIT;
};
template<>
- class pspin_lock<false>
+ class pspin_mutex<false>
{
public:
- void acquire() const noexcept { }
- void release() const noexcept { }
+ void lock() const noexcept { }
+ void unlock() const noexcept { }
};
- #if HAS_OPENMP && USE_OPENMP
- using tqlock = pspin_lock<true>;
- #else
- using tqlock = pspin_lock<false>;
- #endif
-
template <class Element, class Time>
class timed_queue
{
@@ -58,6 +54,18 @@ namespace netlist
struct entry_t
{
+ entry_t() { }
+ entry_t(const Time &t, const Element &o) : m_exec_time(t), m_object(o) { }
+ entry_t(const entry_t &e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
+ entry_t(entry_t &&e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
+
+ entry_t& operator=(entry_t && other)
+ {
+ m_exec_time = other.m_exec_time;
+ m_object = other.m_object;
+ return *this;
+ }
+
Time m_exec_time;
Element m_object;
};
@@ -65,37 +73,35 @@ namespace netlist
timed_queue(unsigned list_size)
: m_list(list_size)
{
- m_lock.acquire();
clear();
- m_lock.release();
}
std::size_t capacity() const { return m_list.size(); }
bool empty() const { return (m_end == &m_list[1]); }
- void push(Element o, const Time t) noexcept
+ void push(entry_t &&e) noexcept
{
/* Lock */
- m_lock.acquire();
+ tqlock lck(m_lock);
entry_t * i = m_end;
- for (; t > (i - 1)->m_exec_time; --i)
+ while (e.m_exec_time > (i - 1)->m_exec_time)
{
- *(i) = *(i-1);
+ *(i) = std::move(*(i-1));
+ --i;
m_prof_sortmove.inc();
}
- *i = { t, o };
+ *i = std::move(e);
++m_end;
m_prof_call.inc();
- m_lock.release();
}
- entry_t pop() noexcept { return *(--m_end); }
- const entry_t &top() const noexcept { return *(m_end-1); }
+ entry_t pop() noexcept { return std::move(*(--m_end)); }
+ const entry_t &top() const noexcept { return std::move(*(m_end-1)); }
void remove(const Element &elem) noexcept
{
/* Lock */
- m_lock.acquire();
+ tqlock lck(m_lock);
for (entry_t * i = m_end - 1; i > &m_list[0]; i--)
{
if (i->m_object == elem)
@@ -103,24 +109,23 @@ namespace netlist
m_end--;
while (i < m_end)
{
- *i = *(i+1);
+ *i = std::move(*(i+1));
++i;
}
- m_lock.release();
return;
}
}
- m_lock.release();
}
void retime(const Element &elem, const Time t) noexcept
{
remove(elem);
- push(elem, t);
+ push(entry_t(t, elem));
}
void clear()
{
+ tqlock lck(m_lock);
m_end = &m_list[0];
/* put an empty element with maximum time into the queue.
* the insert algo above will run into this element and doesn't
@@ -137,8 +142,14 @@ namespace netlist
const entry_t & operator[](const std::size_t index) const { return m_list[ 1 + index]; }
private:
+ #if HAS_OPENMP && USE_OPENMP
+ using tqmutex = pspin_mutex<true>;
+ #else
+ using tqmutex = pspin_mutex<false>;
+ #endif
+ using tqlock = std::lock_guard<tqmutex>;
- tqlock m_lock;
+ tqmutex m_lock;
entry_t * m_end;
std::vector<entry_t> m_list;
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 46f6a92aed1..2fbc4d5f6f5 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -135,7 +135,7 @@ void setup_t::register_dippins_arr(const pstring &terms)
}
}
-pstring setup_t::objtype_as_str(detail::device_object_t &in) const
+pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
{
switch (in.type())
{
@@ -145,8 +145,6 @@ pstring setup_t::objtype_as_str(detail::device_object_t &in) const
return pstring("INPUT");
case terminal_t::OUTPUT:
return pstring("OUTPUT");
- case terminal_t::PARAM:
- return pstring("PARAM");
}
// FIXME: noreturn
log().fatal(MF_1_UNKNOWN_OBJECT_TYPE_1, static_cast<unsigned>(in.type()));
@@ -199,9 +197,9 @@ void setup_t::register_param(pstring name, param_t &param)
void setup_t::register_term(detail::core_terminal_t &term)
{
if (!m_terminals.insert({term.name(), &term}).second)
- log().fatal(MF_2_ADDING_1_2_TO_TERMINAL_LIST, objtype_as_str(term),
+ log().fatal(MF_2_ADDING_1_2_TO_TERMINAL_LIST, termtype_as_str(term),
term.name());
- log().debug("{1} {2}\n", objtype_as_str(term), term.name());
+ log().debug("{1} {2}\n", termtype_as_str(term), term.name());
}
void setup_t::register_link_arr(const pstring &terms)
@@ -340,12 +338,12 @@ detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, bool
}
detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in,
- detail::device_object_t::type_t atype, bool required)
+ detail::core_terminal_t::type_t atype, bool required)
{
const pstring &tname = resolve_alias(terminal_in);
auto ret = m_terminals.find(tname);
/* look for default */
- if (ret == m_terminals.end() && atype == detail::device_object_t::OUTPUT)
+ if (ret == m_terminals.end() && atype == detail::core_terminal_t::OUTPUT)
{
/* look for ".Q" std output */
ret = m_terminals.find(tname + ".Q");
@@ -440,7 +438,6 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
auto ret = new_proxy.get();
-#if 1
/* connect all existing terminals to new net */
if (inp.has_net())
@@ -455,13 +452,6 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
inp.net().m_core_terms.clear(); // clear the list
}
ret->out().net().add_terminal(inp);
-#else
- if (inp.has_net())
- //fatalerror("logic inputs can only belong to one net!\n");
- merge_nets(ret->out().net(), inp.net());
- else
- ret->out().net().add_terminal(inp);
-#endif
netlist().register_dev(std::move(new_proxy));
return ret;
}
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index 06f70623ada..79a21a6815b 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -285,7 +285,7 @@ namespace netlist
std::unordered_map<pstring, detail::core_terminal_t *> m_terminals;
/* needed by proxy */
- detail::core_terminal_t *find_terminal(const pstring &outname_in, detail::device_object_t::type_t atype, bool required = true);
+ detail::core_terminal_t *find_terminal(const pstring &outname_in, detail::core_terminal_t::type_t atype, bool required = true);
private:
@@ -300,7 +300,7 @@ namespace netlist
bool connect_input_input(detail::core_terminal_t &t1, detail::core_terminal_t &t2);
// helpers
- pstring objtype_as_str(detail::device_object_t &in) const;
+ pstring termtype_as_str(detail::core_terminal_t &in) const;
devices::nld_base_proxy *get_d_a_proxy(detail::core_terminal_t &out);
devices::nld_base_proxy *get_a_d_proxy(detail::core_terminal_t &inp);
diff --git a/src/lib/netlist/nl_time.h b/src/lib/netlist/nl_time.h
index 4edc9524a43..6235c195172 100644
--- a/src/lib/netlist/nl_time.h
+++ b/src/lib/netlist/nl_time.h
@@ -45,82 +45,83 @@ namespace netlist
constexpr explicit ptime(const internal_type nom, const internal_type den) noexcept
: m_time(nom * (resolution / den)) { }
- ptime &operator=(const ptime rhs) { m_time = rhs.m_time; return *this; }
+ ptime &operator=(const ptime rhs) noexcept { m_time = rhs.m_time; return *this; }
- ptime &operator+=(const ptime &rhs) { m_time += rhs.m_time; return *this; }
- ptime &operator-=(const ptime &rhs) { m_time -= rhs.m_time; return *this; }
+ ptime &operator+=(const ptime &rhs) noexcept { m_time += rhs.m_time; return *this; }
+ ptime &operator-=(const ptime &rhs) noexcept { m_time -= rhs.m_time; return *this; }
- friend ptime operator-(ptime lhs, const ptime &rhs)
+ friend constexpr ptime operator-(const ptime &lhs, const ptime &rhs) noexcept
{
- lhs -= rhs;
- return lhs;
+ return ptime(lhs.m_time - rhs.m_time);
}
- friend ptime operator+(ptime lhs, const ptime &rhs)
+ friend constexpr ptime operator+(const ptime &lhs, const ptime &rhs) noexcept
{
- lhs += rhs;
- return lhs;
+ return ptime(lhs.m_time + rhs.m_time);
}
- friend ptime operator*(ptime lhs, const mult_type factor)
+ friend constexpr ptime operator*(const ptime &lhs, const mult_type factor) noexcept
{
- lhs.m_time *= static_cast<internal_type>(factor);
- return lhs;
+ return ptime(lhs.m_time * static_cast<internal_type>(factor));
}
- friend mult_type operator/(const ptime &lhs, const ptime &rhs)
+ friend constexpr mult_type operator/(const ptime &lhs, const ptime &rhs) noexcept
{
return static_cast<mult_type>(lhs.m_time / rhs.m_time);
}
- friend bool operator<(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator<(const ptime &lhs, const ptime &rhs) noexcept
{
return (lhs.m_time < rhs.m_time);
}
- friend bool operator>(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator>(const ptime &lhs, const ptime &rhs) noexcept
{
return (rhs < lhs);
}
- friend bool operator<=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator<=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs > rhs);
}
- friend bool operator>=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator>=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs < rhs);
}
- friend bool operator==(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator==(const ptime &lhs, const ptime &rhs) noexcept
{
return lhs.m_time == rhs.m_time;
}
- friend bool operator!=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator!=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs == rhs);
}
- constexpr internal_type as_raw() const { return m_time; }
- constexpr double as_double() const { return static_cast<double>(m_time)
- / static_cast<double>(resolution); }
+ constexpr internal_type as_raw() const noexcept { return m_time; }
+ constexpr double as_double() const noexcept
+ {
+ return static_cast<double>(m_time)
+ / static_cast<double>(resolution);
+ }
// for save states ....
- internal_type *get_internaltype_ptr() { return &m_time; }
-
- static constexpr ptime from_nsec(const internal_type ns) { return ptime(ns, UINT64_C(1000000000)); }
- static constexpr ptime from_usec(const internal_type us) { return ptime(us, UINT64_C(1000000)); }
- static constexpr ptime from_msec(const internal_type ms) { return ptime(ms, UINT64_C(1000)); }
- static constexpr ptime from_hz(const internal_type hz) { return ptime(1 , hz); }
- static constexpr ptime from_raw(const internal_type raw) { return ptime(raw, resolution); }
- static constexpr ptime from_double(const double t) { return ptime(static_cast<internal_type>( t * static_cast<double>(resolution)), resolution); }
-
- static constexpr ptime zero() { return ptime(0, resolution); }
- static constexpr ptime quantum() { return ptime(1, resolution); }
- static constexpr ptime never() { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
+ internal_type *get_internaltype_ptr() noexcept { return &m_time; }
+
+ static constexpr ptime from_nsec(const internal_type ns) noexcept { return ptime(ns, UINT64_C(1000000000)); }
+ static constexpr ptime from_usec(const internal_type us) noexcept { return ptime(us, UINT64_C(1000000)); }
+ static constexpr ptime from_msec(const internal_type ms) noexcept { return ptime(ms, UINT64_C(1000)); }
+ static constexpr ptime from_hz(const internal_type hz) noexcept { return ptime(1 , hz); }
+ static constexpr ptime from_raw(const internal_type raw) noexcept { return ptime(raw); }
+ static constexpr ptime from_double(const double t) noexcept { return ptime(static_cast<internal_type>( t * static_cast<double>(resolution)), resolution); }
+
+ static constexpr ptime zero() noexcept { return ptime(0, resolution); }
+ static constexpr ptime quantum() noexcept { return ptime(1, resolution); }
+ static constexpr ptime never() noexcept { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
private:
+ constexpr explicit ptime(const internal_type time) : m_time(time) {}
internal_type m_time;
};
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index 9cd917ceb28..756130dd190 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -41,6 +41,9 @@ typedef __int128_t INT128;
#endif
#if defined(__GNUC__)
+#ifdef RESTRICT
+#undef RESTRICT
+#endif
#define RESTRICT __restrict__
#define ATTR_UNUSED __attribute__((__unused__))
#else
@@ -63,6 +66,42 @@ typedef __int128_t INT128;
// cut down delegate implementation
//============================================================
+/*
+ *
+ * NL_PMF_TYPE_GNUC_PMF
+ * Use standard pointer to member function syntax C++11
+ *
+ * NL_PMF_TYPE_GNUC_PMF_CONV
+ * Use gnu extension and convert the pmf to a function pointer.
+ * This is not standard compliant and needs
+ * -Wno-pmf-conversions to compile.
+ *
+ * NL_PMF_TYPE_INTERNAL
+ * Use the same approach as MAME for deriving the function pointer.
+ * This is compiler-dependent as well
+ *
+ * Benchmarks for ./nltool -c run -f src/mame/machine/nl_pong.cpp -t 10 -n pong_fast
+ *
+ * NL_PMF_TYPE_INTERNAL: 215% 215%
+ * NL_PMF_TYPE_GNUC_PMF: 163% 196%
+ * NL_PMF_TYPE_GNUC_PMF_CONV: 215% 215%
+ * NL_PMF_TYPE_VIRTUAL: 213% 209%
+ *
+ * The whole exercise was done to avoid virtual calls. In prior versions of
+ * netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
+ * Since than, "hot" was removed from functions declared as virtual.
+ * This may explain that the recent benchmarks show no difference at all.
+ *
+ */
+
+// This will be autodetected
+// #define PPMF_TYPE 1
+
+#define PPMF_TYPE_PMF 0
+#define PPMF_TYPE_GNUC_PMF_CONV 1
+#define PPMF_TYPE_INTERNAL 2
+
+
#if defined(__GNUC__)
/* does not work in versions over 4.7.x of 32bit MINGW */
#if defined(__MINGW32__) && !defined(__x86_64) && defined(__i386__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
@@ -87,6 +126,18 @@ typedef __int128_t INT128;
#define MEMBER_ABI
#endif
+#ifndef PPMF_TYPE
+ #if PHAS_PMF_INTERNAL
+ #define PPMF_TYPE PPMF_TYPE_INTERNAL
+ #else
+ #define PPMF_TYPE PPMF_TYPE_PMF
+ #endif
+#endif
+
+#if (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
+#pragma GCC diagnostic ignored "-Wpmf-conversions"
+#endif
+
namespace plib {
/*
* The following class was derived from the MAME delegate.h code.
@@ -108,18 +159,13 @@ namespace plib {
*reinterpret_cast<MemberFunctionType *>(this) = mftp;
}
- // binding helper
- template<typename FunctionType, typename ObjectType>
- FunctionType update_after_bind(ObjectType *object)
- {
- return reinterpret_cast<FunctionType>(
- convert_to_generic(reinterpret_cast<generic_class *>(object)));
- }
template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
{
mfp mfpo(mftp);
- return mfpo.update_after_bind<FunctionType>(object);
+ //return mfpo.update_after_bind<FunctionType>(object);
+ return reinterpret_cast<FunctionType>(
+ mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object)));
}
private:
@@ -144,9 +190,89 @@ namespace plib {
// if odd, it's the byte offset into the vtable
int m_this_delta; // delta to apply to the 'this' pointer
};
+#endif
+#if (PPMF_TYPE == PPMF_TYPE_PMF)
+ template<typename R, typename... Targs>
+ class pmfp_base
+ {
+ public:
+ class generic_class;
+ using generic_function = R (generic_class::*)(Targs...);
+ pmfp_base() : m_func(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set_base(MemberFunctionType mftp, O *object)
+ {
+ using function_ptr = R (O::*)(Targs...);
+ function_ptr t = mftp;
+ m_func = reinterpret_cast<generic_function>(t);
+ }
+ template<typename O>
+ inline R call(O *obj, Targs... args) const
+ {
+ using function_ptr = R (O::*)(Targs...);
+ function_ptr t = reinterpret_cast<function_ptr>(m_func);
+ return (obj->*t)(std::forward<Targs>(args)...);
+ }
+ private:
+ generic_function m_func;
+ };
+
+#elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL))
+ template<typename R, typename... Targs>
+ class pmfp_base
+ {
+ public:
+ using generic_function = void (*)();
+
+ pmfp_base() : m_func(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set_base(MemberFunctionType mftp, O *object)
+ {
+ #if (PPMF_TYPE == PPMF_TYPE_INTERNAL)
+ using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
+ m_func = reinterpret_cast<generic_function>(plib::mfp::get_mfp<function_ptr>(mftp, object));
+ #elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
+ R (O::* pFunc)(Targs...) = mftp;
+ m_func = reinterpret_cast<generic_function>((object->*pFunc));
+ #endif
+ }
+ template<typename O>
+ inline R call(O *obj, Targs... args) const
+ {
+ using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
+ return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
+ }
+ private:
+ generic_function m_func;
+ };
#endif
+ template<typename R, typename... Targs>
+ class pmfp : public pmfp_base<R, Targs...>
+ {
+ public:
+ class generic_class;
+ pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set(MemberFunctionType mftp, O *object)
+ {
+ this->set_base(mftp, object);
+ m_obj = reinterpret_cast<generic_class *>(object);
+ }
+
+ inline R operator()(Targs... args) const
+ {
+ return this->call(m_obj, std::forward<Targs>(args)...);
+ }
+ private:
+ generic_class *m_obj;
+ };
+
+
}
#endif /* PCONFIG_H_ */
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index c0f3e18a4f2..4736d047bbd 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -6,6 +6,7 @@
*/
#include <cmath>
+#include <stack>
#include "pfunction.h"
#include "pfmtlog.h"
#include "putil.h"
@@ -13,13 +14,27 @@
namespace plib {
+void pfunction::compile(const std::vector<pstring> &inputs, const pstring expr)
+{
+ if (expr.startsWith("rpn:"))
+ compile_postfix(inputs, expr.substr(4));
+ else
+ compile_infix(inputs, expr);
+}
+
void pfunction::compile_postfix(const std::vector<pstring> &inputs, const pstring expr)
{
plib::pstring_vector_t cmds(expr, " ");
+ compile_postfix(inputs, cmds, expr);
+}
+
+void pfunction::compile_postfix(const std::vector<pstring> &inputs,
+ const std::vector<pstring> &cmds, const pstring expr)
+{
m_precompiled.clear();
int stk = 0;
- for (pstring &cmd : cmds)
+ for (const pstring &cmd : cmds)
{
rpn_inst rc;
if (cmd == "+")
@@ -66,6 +81,99 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs, const pstrin
throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
}
+static int get_prio(pstring v)
+{
+ if (v == "(" || v == ")")
+ return 1;
+ else if (v.left(v.begin()+1) >= "a" && v.left(v.begin()+1) <= "z")
+ return 0;
+ else if (v == "*" || v == "/")
+ return 20;
+ else if (v == "+" || v == "-")
+ return 10;
+ else if (v == "^")
+ return 30;
+ else
+ return -1;
+}
+
+static pstring pop_check(std::stack<pstring> &stk, const pstring &expr)
+{
+ if (stk.size() == 0)
+ throw plib::pexception(plib::pfmt("nld_function: stack underflow during infix parsing of: <{1}>")(expr));
+ pstring res = stk.top();
+ stk.pop();
+ return res;
+}
+
+void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring expr)
+{
+ // Shunting-yard infix parsing
+ std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
+ plib::pstring_vector_t sexpr(expr.replace(" ",""), sep);
+ std::stack<pstring> opstk;
+ plib::pstring_vector_t postfix;
+
+ //printf("dbg: %s\n", expr.c_str());
+ for (unsigned i = 0; i < sexpr.size(); i++)
+ {
+ pstring &s = sexpr[i];
+ if (s=="(")
+ opstk.push(s);
+ else if (s==")")
+ {
+ pstring x = pop_check(opstk, expr);
+ while (x != "(")
+ {
+ postfix.push_back(x);
+ x = pop_check(opstk, expr);
+ }
+ if (opstk.size() > 0 && get_prio(opstk.top()) == 0)
+ postfix.push_back(pop_check(opstk, expr));
+ }
+ else if (s==",")
+ {
+ pstring x = pop_check(opstk, expr);
+ while (x != "(")
+ {
+ postfix.push_back(x);
+ x = pop_check(opstk, expr);
+ }
+ opstk.push(x);
+ }
+ else {
+ int p = get_prio(s);
+ if (p>0)
+ {
+ if (opstk.size() == 0)
+ opstk.push(s);
+ else
+ {
+ if (get_prio(opstk.top()) >= get_prio(s))
+ postfix.push_back(pop_check(opstk, expr));
+ opstk.push(s);
+ }
+ }
+ else if (p == 0) // Function or variable
+ {
+ if (sexpr[i+1] == "(")
+ opstk.push(s);
+ else
+ postfix.push_back(s);
+ }
+ else
+ postfix.push_back(s);
+ }
+ }
+ while (opstk.size() > 0)
+ {
+ postfix.push_back(opstk.top());
+ opstk.pop();
+ }
+ compile_postfix(inputs, postfix, expr);
+}
+
+
#define ST1 stack[ptr]
#define ST2 stack[ptr-1]
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
index 2ad32106569..0f4960d4e1c 100644
--- a/src/lib/netlist/plib/pfunction.h
+++ b/src/lib/netlist/plib/pfunction.h
@@ -16,10 +16,10 @@
namespace plib {
//============================================================
- // function evaluation - reverse polish notation
+ // function evaluation
//============================================================
- /*! Class providing support for precompiled rpn expressions
+ /*! Class providing support for evaluating expressions
*
*/
class pfunction
@@ -47,12 +47,26 @@ namespace plib {
{
}
+ /*! Compile an expression
+ *
+ * @param inputs Vector of input variables, e.g. {"A","B"}
+ * @param expr infix or postfix expression. default is infix, postrix
+ * to be prefixed with rpn, e.g. "rpn:A B + 1.3 /"
+ */
+ void compile(const std::vector<pstring> &inputs, const pstring expr);
+
/*! Compile a rpn expression
*
* @param inputs Vector of input variables, e.g. {"A","B"}
* @param expr Reverse polish notation expression, e.g. "A B + 1.3 /"
*/
void compile_postfix(const std::vector<pstring> &inputs, const pstring expr);
+ /*! Compile an infix expression
+ *
+ * @param inputs Vector of input variables, e.g. {"A","B"}
+ * @param expr Infix expression, e.g. "(A+B)/1.3"
+ */
+ void compile_infix(const std::vector<pstring> &inputs, const pstring expr);
/*! Evaluate the expression
*
* @param values for input variables, e.g. {1.1, 2.2}
@@ -61,6 +75,10 @@ namespace plib {
double evaluate(const std::vector<double> &values);
private:
+
+ void compile_postfix(const std::vector<pstring> &inputs,
+ const std::vector<pstring> &cmds, const pstring expr);
+
std::vector<rpn_inst> m_precompiled; //!< precompiled expression
};
diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h
index 37f4e2a1391..fd9aaa5e176 100644
--- a/src/lib/netlist/plib/plists.h
+++ b/src/lib/netlist/plib/plists.h
@@ -56,6 +56,7 @@ public:
template<typename... Args>
void emplace(const std::size_t index, Args&&... args)
{
+ // allocate on buffer
new (&m_buf[index]) C(std::forward<Args>(args)...);
}
diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp
index 7d676f34c0d..baeace1edb9 100644
--- a/src/lib/netlist/plib/pstring.cpp
+++ b/src/lib/netlist/plib/pstring.cpp
@@ -6,17 +6,16 @@
*/
#include <cstring>
-//FIXME:: pstring should be locale free
-#include <cctype>
-#include <cstdlib>
-#include <cstdio>
#include <algorithm>
#include <stack>
+#include <cstdlib>
#include "pstring.h"
#include "palloc.h"
#include "plists.h"
+template <typename F> pstr_t pstring_t<F>::m_zero(0);
+
template<typename F>
pstring_t<F>::~pstring_t()
{
@@ -240,7 +239,7 @@ double pstring_t<F>::as_double(bool *error) const
if (error != nullptr)
*error = false;
- ret = strtod(c_str(), &e);
+ ret = std::strtod(c_str(), &e);
if (*e != 0)
if (error != nullptr)
*error = true;
@@ -256,9 +255,9 @@ long pstring_t<F>::as_long(bool *error) const
if (error != nullptr)
*error = false;
if (startsWith("0x"))
- ret = strtol(substr(2).c_str(), &e, 16);
+ ret = std::strtol(substr(2).c_str(), &e, 16);
else
- ret = strtol(c_str(), &e, 10);
+ ret = std::strtol(c_str(), &e, 10);
if (*e != 0)
if (error != nullptr)
*error = true;
@@ -416,8 +415,8 @@ static inline std::size_t countleadbits(std::size_t x)
template<typename F>
void pstring_t<F>::sfree(pstr_t *s)
{
- s->m_ref_count--;
- if (s->m_ref_count == 0 && s != &m_zero)
+ bool b = s->dec_and_check();
+ if ( b && s != &m_zero)
{
if (stk != nullptr)
{
@@ -472,8 +471,8 @@ void pstring_t<F>::resetmem()
template<typename F>
void pstring_t<F>::sfree(pstr_t *s)
{
- s->m_ref_count--;
- if (s->m_ref_count == 0 && s != &m_zero)
+ bool b = s->dec_and_check();
+ if ( b && s != &m_zero)
{
plib::pfree_array(((char *)s));
}
diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h
index 999bd10ce6b..e3dd475175e 100644
--- a/src/lib/netlist/plib/pstring.h
+++ b/src/lib/netlist/plib/pstring.h
@@ -10,6 +10,7 @@
#include <cstdarg>
#include <cstddef>
#include <iterator>
+#include <exception>
#include "pconfig.h"
@@ -22,27 +23,24 @@
struct pstr_t
{
- //str_t() : m_ref_count(1), m_len(0) { m_str[0] = 0; }
- pstr_t(const std::size_t alen)
- {
- init(alen);
- }
+ pstr_t(const std::size_t alen) { init(alen); }
void init(const std::size_t alen)
{
- m_ref_count = 1;
- m_len = alen;
- m_str[0] = 0;
+ m_ref_count = 1;
+ m_len = alen;
+ m_str[0] = 0;
}
char *str() { return &m_str[0]; }
unsigned char *ustr() { return reinterpret_cast<unsigned char *>(&m_str[0]); }
std::size_t len() const { return m_len; }
- int m_ref_count;
+ void inc() { m_ref_count++; }
+ bool dec_and_check() { --m_ref_count; return m_ref_count == 0; }
private:
+ int m_ref_count;
std::size_t m_len;
char m_str[1];
};
-
template <typename F>
struct pstring_t
{
@@ -75,7 +73,8 @@ public:
pstring_t(C (&string)[N]) : m_ptr(&m_zero) {
static_assert(std::is_same<C, const mem_t>::value, "pstring constructor only accepts const mem_t");
static_assert(N>0,"pstring from array of length 0");
- //static_assert(string[N-1] == 0, "pstring constructor parameter not a string literal");
+ if (string[N-1] != 0)
+ throw std::exception();
init(string);
}
@@ -170,13 +169,6 @@ public:
const pstring_t ucase() const;
- // FIXME: do something with encoding
- // FIXME: belongs into derived class
- // This is only used in state saving to support "owners" whose name() function
- // returns char*.
- static pstring_t from_utf8(const mem_t *c) { return pstring_t(c, UTF8); }
- static pstring_t from_utf8(const pstring_t &c) { return c; }
-
static void resetmem();
protected:
@@ -185,13 +177,13 @@ protected:
private:
void init(const mem_t *string)
{
- m_ptr->m_ref_count++;
+ m_ptr->inc();
if (string != nullptr && *string != 0)
pcopy(string);
}
void init(const pstring_t &string)
{
- m_ptr->m_ref_count++;
+ m_ptr->inc();
pcopy(string);
}
@@ -206,7 +198,7 @@ private:
{
sfree(m_ptr);
m_ptr = from.m_ptr;
- m_ptr->m_ref_count++;
+ m_ptr->inc();
}
void pcat(const mem_t *s);
void pcat(const pstring_t &s);
@@ -217,8 +209,6 @@ private:
static pstr_t m_zero;
};
-template <typename F> pstr_t pstring_t<F>::m_zero(0);
-
struct pu8_traits
{
static const unsigned MAXCODELEN = 1; /* in memory units */
diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp
index b21f945662c..7007c818384 100644
--- a/src/lib/netlist/plib/putil.cpp
+++ b/src/lib/netlist/plib/putil.cpp
@@ -62,7 +62,7 @@ namespace plib
}
}
- pstring_vector_t::pstring_vector_t(const pstring &str, const pstring_vector_t &onstrl)
+ pstring_vector_t::pstring_vector_t(const pstring &str, const std::vector<pstring> &onstrl)
: std::vector<pstring>()
{
pstring col = "";
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index 728a475dd28..e340acbd8ec 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -71,7 +71,7 @@ namespace plib
public:
pstring_vector_t() : std::vector<pstring>() { }
pstring_vector_t(const pstring &str, const pstring &onstr, bool ignore_empty = false);
- pstring_vector_t(const pstring &str, const pstring_vector_t &onstrl);
+ pstring_vector_t(const pstring &str, const std::vector<pstring> &onstrl);
};
}
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index a6513f260b9..f63369839ef 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -320,7 +320,15 @@ static void static_compile(tool_options_t &opts)
opts.opt_logs(),
opts.opt_defines(), opts.opt_rfolders());
- nt.solver()->create_solver_code(pout_strm);
+ plib::putf8_writer w(pout_strm);
+ std::map<pstring, pstring> mp;
+
+ nt.solver()->create_solver_code(mp);
+
+ for (auto &e : mp)
+ {
+ w.write(e.second);
+ }
nt.stop();
@@ -531,7 +539,7 @@ int main(int argc, char *argv[])
{
pout(
"nltool (netlist) 0.1\n"
- "Copyright (C) 2016 Couriersud\n"
+ "Copyright (C) 2017 Couriersud\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n\n"
diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp
index 5a3fdbbfad0..8612469431e 100644
--- a/src/lib/netlist/prg/nlwav.cpp
+++ b/src/lib/netlist/prg/nlwav.cpp
@@ -1,13 +1,12 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
-#include <plib/poptions.h>
#include <cstdio>
#include <cstring>
#include "plib/pstring.h"
#include "plib/plists.h"
#include "plib/pstream.h"
+#include "plib/poptions.h"
#include "nl_setup.h"
-#include <memory>
class nlwav_options_t : public plib::options
{
@@ -143,10 +142,10 @@ private:
static void convert()
{
- plib::postream *fo = (opts.opt_out() == "-" ? &pout_strm : new plib::pofilestream(opts.opt_out()));
- plib::pistream *fin = (opts.opt_inp() == "-" ? &pin_strm : new plib::pifilestream(opts.opt_inp()));
+ plib::postream *fo = (opts.opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opts.opt_out()));
+ plib::pistream *fin = (opts.opt_inp() == "-" ? &pin_strm : plib::palloc<plib::pifilestream>(opts.opt_inp()));
plib::putf8_reader reader(*fin);
- wav_t *wo = new wav_t(*fo, 48000);
+ wav_t *wo = plib::palloc<wav_t>(*fo, 48000U);
double dt = 1.0 / static_cast<double>(wo->sample_rate());
double ct = dt;
@@ -213,11 +212,11 @@ static void convert()
//printf("%f %f\n", t, v);
#endif
}
- delete wo;
+ plib::pfree(wo);
if (opts.opt_inp() != "-")
- delete fin;
+ plib::pfree(fin);
if (opts.opt_out() != "-")
- delete fo;
+ plib::pfree(fo);
if (!opts.opt_quiet())
{
@@ -256,7 +255,7 @@ int main(int argc, char *argv[])
{
pout(
"nlwav (netlist) 0.1\n"
- "Copyright (C) 2016 Couriersud\n"
+ "Copyright (C) 2017 Couriersud\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n\n"
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
index 051fa10a253..71950174a5a 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.cpp
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -91,11 +91,6 @@ matrix_solver_t::matrix_solver_t(netlist_t &anetlist, const pstring &name,
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)
@@ -109,7 +104,7 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
for (auto & net : nets)
{
m_nets.push_back(net);
- m_terms.push_back(plib::palloc<terms_for_net_t>());
+ m_terms.push_back(plib::make_unique<terms_for_net_t>());
m_rails_temp.push_back(plib::palloc<terms_for_net_t>());
}
@@ -164,7 +159,6 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
}
break;
case terminal_t::OUTPUT:
- case terminal_t::PARAM:
log().fatal(MF_1_UNHANDLED_ELEMENT_1_FOUND,
p->name());
break;
@@ -242,7 +236,7 @@ void matrix_solver_t::setup_matrix()
/* create a list of non zero elements. */
for (unsigned k = 0; k < iN; k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
/* pretty brutal */
int *other = t->connected_net_idx();
@@ -264,7 +258,7 @@ void matrix_solver_t::setup_matrix()
*/
for (unsigned k = 0; k < iN; k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
/* pretty brutal */
int *other = t->connected_net_idx();
@@ -294,9 +288,9 @@ void matrix_solver_t::setup_matrix()
* This should reduce cache misses ...
*/
- bool **touched = new bool*[iN];
+ bool **touched = plib::palloc_array<bool *>(iN);
for (unsigned k=0; k<iN; k++)
- touched[k] = new bool[iN];
+ touched[k] = plib::palloc_array<bool>(iN);
for (unsigned k = 0; k < iN; k++)
{
@@ -354,8 +348,8 @@ void matrix_solver_t::setup_matrix()
}
for (unsigned k=0; k<iN; k++)
- delete [] touched[k];
- delete [] touched;
+ plib::pfree_array(touched[k]);
+ plib::pfree_array(touched);
}
void matrix_solver_t::update_inputs()
@@ -499,7 +493,7 @@ netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++)
{
analog_net_t *n = m_nets[k];
- terms_for_net_t *t = m_terms[k];
+ terms_for_net_t *t = m_terms[k].get();
const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
const nl_double hn = cur_ts;
@@ -548,12 +542,12 @@ void matrix_solver_t::log_stats()
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()));
+ 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));
}
}
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index fc7ab7fcbdb..e5f7bcf38b1 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -44,14 +44,14 @@ public:
void add(terminal_t *term, int net_other, bool sorted);
- inline std::size_t count() { return m_terms.size(); }
+ inline std::size_t count() const { return m_terms.size(); }
inline terminal_t **terms() { return m_terms.data(); }
inline int *connected_net_idx() { return m_connected_net_idx.data(); }
inline nl_double *gt() { return m_gt.data(); }
inline nl_double *go() { return m_go.data(); }
inline nl_double *Idr() { return m_Idr.data(); }
- inline nl_double **connected_net_V() { return m_connected_net_V.data(); }
+ inline nl_double * const *connected_net_V() const { return m_connected_net_V.data(); }
void set_pointers();
@@ -135,9 +135,9 @@ public:
virtual void log_stats();
- virtual void create_solver_code(plib::putf8_fmt_writer &strm)
+ virtual std::pair<pstring, pstring> create_solver_code()
{
- strm.writeline(plib::pfmt("/* {1} doesn't support static compile */"));
+ return std::pair<pstring, pstring>("", plib::pfmt("/* {1} doesn't support static compile */"));
}
protected:
@@ -161,7 +161,7 @@ protected:
template <typename T>
void build_LE_RHS();
- std::vector<terms_for_net_t *> m_terms;
+ std::vector<std::unique_ptr<terms_for_net_t>> m_terms;
std::vector<analog_net_t *> m_nets;
std::vector<std::unique_ptr<proxied_analog_output_t>> m_inps;
@@ -226,12 +226,14 @@ void matrix_solver_t::build_LE_A()
const unsigned iN = child.N();
for (unsigned k = 0; k < iN; k++)
{
+ terms_for_net_t *terms = m_terms[k].get();
+
for (unsigned i=0; i < iN; i++)
child.A(k,i) = 0.0;
- const std::size_t terms_count = m_terms[k]->count();
- const std::size_t railstart = m_terms[k]->m_railstart;
- const nl_double * RESTRICT gt = m_terms[k]->gt();
+ const std::size_t terms_count = terms->count();
+ const std::size_t railstart = terms->m_railstart;
+ const nl_double * const RESTRICT gt = terms->gt();
{
nl_double akk = 0.0;
@@ -241,8 +243,8 @@ void matrix_solver_t::build_LE_A()
child.A(k,k) = akk;
}
- const nl_double * RESTRICT go = m_terms[k]->go();
- const int * RESTRICT net_other = m_terms[k]->connected_net_idx();
+ const nl_double * const RESTRICT go = terms->go();
+ int * RESTRICT net_other = terms->connected_net_idx();
for (std::size_t i = 0; i < railstart; i++)
child.A(k,net_other[i]) -= go[i];
@@ -262,8 +264,8 @@ void matrix_solver_t::build_LE_RHS()
nl_double rhsk_b = 0.0;
const std::size_t terms_count = m_terms[k]->count();
- const nl_double * RESTRICT go = m_terms[k]->go();
- const nl_double * RESTRICT Idr = m_terms[k]->Idr();
+ const nl_double * const RESTRICT go = m_terms[k]->go();
+ const nl_double * const RESTRICT Idr = m_terms[k]->Idr();
const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->connected_net_V();
for (std::size_t i = 0; i < terms_count; i++)
diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h
index a5ee5bbf8c1..e7f89a57e67 100644
--- a/src/lib/netlist/solver/nld_ms_direct.h
+++ b/src/lib/netlist/solver/nld_ms_direct.h
@@ -200,7 +200,7 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
/* add RHS element */
for (unsigned k = 0; k < N(); k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
if (!plib::container::contains(t->m_nzrd, N()))
t->m_nzrd.push_back(N());
diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h
index 853cc34d39c..11d71c531fa 100644
--- a/src/lib/netlist/solver/nld_ms_gcr.h
+++ b/src/lib/netlist/solver/nld_ms_gcr.h
@@ -52,7 +52,7 @@ public:
virtual void vsetup(analog_net_t::list_t &nets) override;
virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- virtual void create_solver_code(plib::putf8_fmt_writer &strm) override;
+ virtual std::pair<pstring, pstring> create_solver_code() override;
private:
@@ -60,15 +60,7 @@ private:
using extsolver = void (*)(double * RESTRICT m_A, double * RESTRICT RHS);
- pstring static_compile_name()
- {
- plib::postringstream t;
- plib::putf8_fmt_writer w(t);
- csc_private(w);
- std::hash<pstring> h;
-
- return plib::pfmt("nl_gcr_{1:x}_{2}")(h( t.str() ))(mat.nz_num);
- }
+ pstring static_compile_name();
unsigned m_dim;
std::vector<unsigned> m_term_cr[storage_N];
@@ -96,7 +88,7 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
bool touched[storage_N][storage_N] = { { false } };
for (unsigned k = 0; k < iN; k++)
{
- for (auto & j : this->m_terms[k]->m_nz)
+ for (auto &j : this->m_terms[k]->m_nz)
touched[k][j] = true;
}
@@ -104,32 +96,21 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
unsigned ops = 0;
- const bool static_compile = false;
for (unsigned k = 0; k < iN; k++)
{
ops++; // 1/A(k,k)
- if (static_compile) printf("const double fd%d = 1.0 / A(%d,%d); \n", k, k, k);
for (unsigned row = k + 1; row < iN; row++)
{
if (touched[row][k])
{
ops++;
fc++;
- if (static_compile) printf(" const double f%d = -fd%d * A(%d,%d); \n", fc, k, row, k);
for (unsigned col = k + 1; col < iN; col++)
if (touched[k][col])
{
- if (touched[row][col])
- {
- if (static_compile) printf(" A(%d,%d) += f%d * A(%d,%d); \n", row, col, fc, k, col);
- } else
- {
- if (static_compile) printf(" A(%d,%d) = f%d * A(%d,%d); \n", row, col, fc, k, col);
- }
touched[row][col] = true;
ops += 2;
}
- if (static_compile) printf(" RHS(%d) += f%d * RHS(%d); \n", row, fc, k);
}
}
}
@@ -180,7 +161,7 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
if (m_proc != nullptr)
this->log().verbose("External static solver {1} found ...", symname);
else
- this->log().verbose("External static solver {1} not found ...", symname);
+ this->log().warning("External static solver {1} not found ...", symname);
}
}
@@ -198,7 +179,7 @@ void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &st
unsigned pi = mat.diag[i];
//const nl_double f = 1.0 / m_A[pi++];
- strm("const double f{1} = 1.0 / m_A[{2}];", i,pi);
+ strm("const double f{1} = 1.0 / m_A[{2}];\n", i, pi);
pi++;
const unsigned piie = mat.ia[i+1];
@@ -211,7 +192,7 @@ void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &st
pj++;
//const nl_double f1 = - m_A[pj++] * f;
- strm("\tconst double f{1}_{2} = -f{3} * m_A[{4}];", i, j, i, pj);
+ strm("\tconst double f{1}_{2} = -f{3} * m_A[{4}];\n", i, j, i, pj);
pj++;
// subtract row i from j */
@@ -220,25 +201,40 @@ void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &st
while (mat.ja[pj] < mat.ja[pii])
pj++;
//m_A[pj++] += m_A[pii++] * f1;
- strm("\tm_A[{1}] += m_A[{2}] * f{3}_{4};", pj, pii, i, j);
+ strm("\tm_A[{1}] += m_A[{2}] * f{3}_{4};\n", pj, pii, i, j);
pj++; pii++;
}
//RHS[j] += f1 * RHS[i];
- strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];", j, i, j, i);
+ strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];\n", j, i, j, i);
}
}
}
}
+
+template <unsigned m_N, unsigned storage_N>
+pstring matrix_solver_GCR_t<m_N, storage_N>::static_compile_name()
+{
+ plib::postringstream t;
+ plib::putf8_fmt_writer w(t);
+ csc_private(w);
+ std::hash<pstring> h;
+
+ return plib::pfmt("nl_gcr_{1:x}_{2}")(h( t.str() ))(mat.nz_num);
+}
+
template <unsigned m_N, unsigned storage_N>
-void matrix_solver_GCR_t<m_N, storage_N>::create_solver_code(plib::putf8_fmt_writer &strm)
+std::pair<pstring, pstring> matrix_solver_GCR_t<m_N, storage_N>::create_solver_code()
{
- //const unsigned iN = N();
+ plib::postringstream t;
+ plib::putf8_fmt_writer strm(t);
+ pstring name = static_compile_name();
- strm.writeline(plib::pfmt("extern \"C\" void {1}(double * _restrict m_A, double * _restrict RHS)")(static_compile_name()));
- strm.writeline("{");
+ strm.writeline(plib::pfmt("extern \"C\" void {1}(double * __restrict m_A, double * __restrict RHS)\n")(name));
+ strm.writeline("{\n");
csc_private(strm);
- strm.writeline("}");
+ strm.writeline("}\n");
+ return std::pair<pstring, pstring>(name, t.str());
}
@@ -255,7 +251,7 @@ unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
for (unsigned k = 0; k < iN; k++)
{
- terms_for_net_t *t = this->m_terms[k];
+ terms_for_net_t *t = this->m_terms[k].get();
nl_double gtot_t = 0.0;
nl_double RHS_t = 0.0;
@@ -265,7 +261,9 @@ unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
const nl_double * const RESTRICT go = t->go();
const nl_double * const RESTRICT Idr = t->Idr();
const nl_double * const * RESTRICT other_cur_analog = t->connected_net_V();
+ const unsigned * const RESTRICT tcr = m_term_cr[k].data();
+#if 1
#if (0 ||NL_USE_SSE)
__m128d mg = _mm_set_pd(0.0, 0.0);
__m128d mr = _mm_set_pd(0.0, 0.0);
@@ -298,11 +296,26 @@ unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
m_A[mat.diag[k]] = gtot_t;
for (unsigned i = 0; i < railstart; i++)
+ m_A[tcr[i]] -= go[i];
+ }
+#else
+ for (std::size_t i = 0; i < railstart; i++)
{
- const unsigned pi = m_term_cr[k][i];
- m_A[pi] -= go[i];
+ m_A[tcr[i]] -= go[i];
+ gtot_t = gtot_t + gt[i];
+ RHS_t = RHS_t + Idr[i];
}
+
+ for (std::size_t i = railstart; i < term_count; i++)
+ {
+ RHS_t += (Idr[i] + go[i] * *other_cur_analog[i]);
+ gtot_t += gt[i];
+ }
+
+ RHS[k] = RHS_t;
+ m_A[mat.diag[k]] += gtot_t;
}
+#endif
mat.ia[iN] = mat.nz_num;
/* now solve it */
diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h
index 0c5a5e6228f..baa61723cf9 100644
--- a/src/lib/netlist/solver/nld_ms_gmres.h
+++ b/src/lib/netlist/solver/nld_ms_gmres.h
@@ -81,7 +81,7 @@ void matrix_solver_GMRES_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
for (unsigned k=0; k<iN; k++)
{
- terms_for_net_t * RESTRICT row = this->m_terms[k];
+ terms_for_net_t * RESTRICT row = this->m_terms[k].get();
mat.ia[k] = nz;
for (unsigned j=0; j<row->m_nz.size(); j++)
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 629c7c0173e..cfdf411c553 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -10,23 +10,24 @@
*/
#if 0
-#pragma GCC optimize "-ffast-math"
-#pragma GCC optimize "-fstrict-aliasing"
-#pragma GCC optimize "-ftree-vectorizer-verbose=2"
-#pragma GCC optimize "-fopt-info-vec"
-#pragma GCC optimize "-fopt-info-vec-missed"
-//#pragma GCC optimize "-ftree-parallelize-loops=4"
-#pragma GCC optimize "-funroll-loops"
-#pragma GCC optimize "-funswitch-loops"
-#pragma GCC optimize "-fvariable-expansion-in-unroller"
-#pragma GCC optimize "-funsafe-loop-optimizations"
-#pragma GCC optimize "-fvect-cost-model"
-#pragma GCC optimize "-fvariable-expansion-in-unroller"
-#pragma GCC optimize "-ftree-loop-if-convert-stores"
-#pragma GCC optimize "-ftree-loop-distribution"
-#pragma GCC optimize "-ftree-loop-im"
-#pragma GCC optimize "-ftree-loop-ivcanon"
-#pragma GCC optimize "-fivopts"
+#pragma GCC optimize "fast-math"
+#pragma GCC optimize "strict-aliasing"
+#pragma GCC optimize "tree-vectorize"
+#pragma GCC optimize "tree-vectorizer-verbose=7"
+#pragma GCC optimize "opt-info-vec"
+#pragma GCC optimize "opt-info-vec-missed"
+//#pragma GCC optimize "tree-parallelize-loops=4"
+#pragma GCC optimize "unroll-loops"
+#pragma GCC optimize "unswitch-loops"
+#pragma GCC optimize "variable-expansion-in-unroller"
+#pragma GCC optimize "unsafe-loop-optimizations"
+#pragma GCC optimize "vect-cost-model"
+#pragma GCC optimize "variable-expansion-in-unroller"
+#pragma GCC optimize "tree-loop-if-convert-stores"
+#pragma GCC optimize "tree-loop-distribution"
+#pragma GCC optimize "tree-loop-im"
+#pragma GCC optimize "tree-loop-ivcanon"
+#pragma GCC optimize "ivopts"
#endif
#include <iostream>
@@ -297,12 +298,12 @@ void NETLIB_NAME(solver)::post_start()
switch (net_count)
{
-#if 1
+#if 0
case 1:
- ms = create_solver<1,1>(1, use_specific);
+ ms = create_solver<1,1>(1, false);
break;
case 2:
- ms = create_solver<2,2>(2, use_specific);
+ ms = create_solver<2,2>(2, false);
break;
case 3:
ms = create_solver<3,3>(3, use_specific);
@@ -322,6 +323,9 @@ void NETLIB_NAME(solver)::post_start()
case 8:
ms = create_solver<8,8>(8, use_specific);
break;
+ case 9:
+ ms = create_solver<9,9>(9, use_specific);
+ break;
case 10:
ms = create_solver<10,10>(10, use_specific);
break;
@@ -396,11 +400,13 @@ void NETLIB_NAME(solver)::post_start()
}
}
-void NETLIB_NAME(solver)::create_solver_code(plib::postream &strm)
+void NETLIB_NAME(solver)::create_solver_code(std::map<pstring, pstring> &mp)
{
- plib::putf8_fmt_writer w(strm);
for (auto & s : m_mat_solvers)
- s->create_solver_code(w);
+ {
+ auto r = s->create_solver_code();
+ mp[r.first] = r.second; // automatically overwrites identical names
+ }
}
NETLIB_DEVICE_IMPL(solver)
diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h
index 5430fc4ce28..d982b81ec0c 100644
--- a/src/lib/netlist/solver/nld_solver.h
+++ b/src/lib/netlist/solver/nld_solver.h
@@ -8,6 +8,8 @@
#ifndef NLD_SOLVER_H_
#define NLD_SOLVER_H_
+#include <map>
+
#include "nl_setup.h"
#include "nl_base.h"
#include "plib/pstream.h"
@@ -79,7 +81,7 @@ NETLIB_OBJECT(solver)
inline nl_double gmin() { return m_gmin(); }
- void create_solver_code(plib::postream &strm);
+ void create_solver_code(std::map<pstring, pstring> &mp);
NETLIB_UPDATEI();
NETLIB_RESETI();
diff --git a/src/lib/util/unicode.cpp b/src/lib/util/unicode.cpp
index 8f5295de4af..b48cef44c79 100644
--- a/src/lib/util/unicode.cpp
+++ b/src/lib/util/unicode.cpp
@@ -15,7 +15,7 @@
#define UTF8PROC_DLLEXPORT
#endif
-#include "utf8proc/utf8proc.h"
+#include <utf8proc.h>
#include <codecvt>
#include <locale>