summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2017-01-23 21:20:09 +0100
committer couriersud <couriersud@gmx.org>2017-01-25 22:17:47 +0100
commit25152bd69a070aa7ba84248b368b0803e407272a (patch)
tree7a0704f433857e91cbda2cda93dca07e643e075a /src/lib/netlist
parent093bda019317a5a66699b35f8b25ab73802f1f1c (diff)
Netlist refactoring:
- Refactored netlist pmf code. - Small optimization for diode calculations. - Minor refactoring across the board. (nw)
Diffstat (limited to 'src/lib/netlist')
-rw-r--r--src/lib/netlist/analog/nld_twoterm.cpp31
-rw-r--r--src/lib/netlist/analog/nld_twoterm.h35
-rw-r--r--src/lib/netlist/nl_base.cpp14
-rw-r--r--src/lib/netlist/nl_base.h25
-rw-r--r--src/lib/netlist/nl_config.h67
-rw-r--r--src/lib/netlist/plib/pconfig.h139
-rw-r--r--src/lib/netlist/plib/pfunction.cpp2
-rw-r--r--src/lib/netlist/plib/pstring.cpp2
-rw-r--r--src/lib/netlist/plib/pstring.h9
-rw-r--r--src/lib/netlist/prg/nltool.cpp18
10 files changed, 210 insertions, 132 deletions
diff --git a/src/lib/netlist/analog/nld_twoterm.cpp b/src/lib/netlist/analog/nld_twoterm.cpp
index 0e53d77f1f5..d7b0c06392e 100644
--- a/src/lib/netlist/analog/nld_twoterm.cpp
+++ b/src/lib/netlist/analog/nld_twoterm.cpp
@@ -23,6 +23,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 +41,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 +49,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 +59,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/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 6128200fe9a..50ef51827d8 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -578,7 +578,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 +591,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 +607,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
}
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 57d1e197378..e1bb98e3651 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -1082,12 +1082,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 +1102,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
};
@@ -1277,11 +1270,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 +1292,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 */
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/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index 9cd917ceb28..198da5a4cc5 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -63,6 +63,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 +123,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 +156,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 +187,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 004d0f3be86..9c797800650 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -81,7 +81,7 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
}
-int get_prio(pstring v)
+static int get_prio(pstring v)
{
if (v == "(" or v == ")")
return 1;
diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp
index 1a65bb152ff..3fc8ffa6dba 100644
--- a/src/lib/netlist/plib/pstring.cpp
+++ b/src/lib/netlist/plib/pstring.cpp
@@ -371,7 +371,7 @@ void pstringbuffer::pcat(const pstring &s)
* This improves startup performance by 30%.
*/
-#if 0
+#if 1
static std::stack<pstr_t *> *stk = nullptr;
diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h
index 059df4b6376..e3dd475175e 100644
--- a/src/lib/netlist/plib/pstring.h
+++ b/src/lib/netlist/plib/pstring.h
@@ -23,7 +23,7 @@
struct pstr_t
{
- pstr_t(const int alen) { init(alen); }
+ pstr_t(const std::size_t alen) { init(alen); }
void init(const std::size_t alen)
{
m_ref_count = 1;
@@ -169,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:
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 910f9078561..14b7409b95e 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -502,12 +502,30 @@ static const pstring pmf_verbose[] =
};
#endif
+struct tt
+{
+ void test(int a) {printf ("test :%d\n", a);}
+ int test1() { return 1;}
+};
+
+plib::pmfp<void, int> atest;
+plib::pmfp<int> atest1;
int main(int argc, char *argv[])
{
tool_options_t opts;
int ret;
+ tt x;
+
+ atest.set(&tt::test, &x);
+ atest1.set(&tt::test1, &x);
+
+ atest(1);
+ int a = atest1();
+
+ printf("%d\n", a);
+ //return 1 ;
/* make SIGFPE actually deliver signals on supoorted platforms */
plib::fpsignalenabler::global_enable(true);
plib::fpsignalenabler sigen(plib::FP_ALL & ~plib::FP_INEXACT & ~plib::FP_UNDERFLOW);