summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2017-02-04 01:23:12 +0100
committer couriersud <couriersud@gmx.org>2017-02-05 17:19:53 +0100
commit70051f6c1f009bae411d68a8afa229259504e866 (patch)
tree0c19623b17b546ffe6cba8697aa9ddce687cf00a /src/lib/netlist
parent427cf984dbcab7584f0f75ed6295d97543422a4a (diff)
Netlist: It is now possible to have multiple handlers per device ...
... for updates. This will make device implementation more flexible and faster. A nice side-effect is that there was some minor (<5%) performance increase already. Each input is now assigned a notification handler. Currently this is update, but going forward this may be a custom handler. In addition - fixed MEMPOOL on OSX - removed dead code - avoid bit-rot - added delegate support for emscripten and arm processors - added delegate support for VS 2015 x64 [Couriersud]
Diffstat (limited to 'src/lib/netlist')
-rw-r--r--src/lib/netlist/build/makefile9
-rw-r--r--src/lib/netlist/devices/net_lib.cpp6
-rw-r--r--src/lib/netlist/devices/nld_am2847.cpp7
-rw-r--r--src/lib/netlist/nl_base.cpp151
-rw-r--r--src/lib/netlist/nl_base.h18
-rw-r--r--src/lib/netlist/nl_config.h15
-rw-r--r--src/lib/netlist/nl_lists.h2
-rwxr-xr-x[-rw-r--r--]src/lib/netlist/plib/palloc.cpp23
-rw-r--r--src/lib/netlist/plib/palloc.h10
-rwxr-xr-x[-rw-r--r--]src/lib/netlist/plib/pconfig.h10
-rwxr-xr-x[-rw-r--r--]src/lib/netlist/plib/ppmf.h97
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp1
12 files changed, 233 insertions, 116 deletions
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 670047a421f..d2b1afa6b36 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -172,15 +172,18 @@ maketree: $(sort $(OBJDIRS))
# Special targets
#-------------------------------------------------
-.PHONY: clang mingw doc
+.PHONY: clang clang-5 mingw doc
clang:
- $(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
+ $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
+
+clang-5:
+ $(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-unreachable-code -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
#
# Mostly done: -Wno-weak-vtables -Wno-cast-align
# FIXME: -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors
-#
+# FIXME: -Wunreachable-code : False warnings, this a documented clang bug: https://llvm.org/bugs/show_bug.cgi?id=28994
mingw:
$(MAKE) LDEXTRAFLAGS="-Wl,--subsystem,console" LIBS= MD=@mkdir.exe SHELL=sh.exe
diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp
index bc1d7051b39..3fb47772c45 100644
--- a/src/lib/netlist/devices/net_lib.cpp
+++ b/src/lib/netlist/devices/net_lib.cpp
@@ -15,14 +15,8 @@
#define xstr(s) # s
-#if 0
-#define ENTRY1(nic, name, defparam) factory.register_device<nic>( # name, xstr(nic), defparam );
-#define ENTRY(nic, name, defparam) ENTRY1(NETLIB_NAME(nic), name, defparam)
-#endif
-
#define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip;
-//#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (# name, xstr(nic), defparam) );
#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (pstring(# name), pstring(xstr(nic)), pstring(defparam)) );
#define ENTRYX(nic, name, defparam) { NETLIB_DEVICE_DECL(nic) ENTRYX1(NETLIB_NAME(nic), name, defparam, decl_ ## nic) }
diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp
index be5f75c3774..29a3b2417eb 100644
--- a/src/lib/netlist/devices/nld_am2847.cpp
+++ b/src/lib/netlist/devices/nld_am2847.cpp
@@ -22,6 +22,8 @@ namespace netlist
{
}
+ NETLIB_UPDATEI();
+
public:
void shift();
@@ -109,6 +111,11 @@ namespace netlist
m_last_CP = m_CP();
}
+ NETLIB_UPDATE(Am2847_shifter)
+ {
+ /* do nothing */
+ }
+
inline NETLIB_FUNC_VOID(Am2847_shifter, shift, (void))
{
uint32_t out = m_buffer[0] & 1;
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index dfd07bdd8f2..c2e81ee69a2 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -25,31 +25,35 @@ namespace netlist
{
namespace detail
{
-#if (USE_MEMPOOL)
-static plib::mempool pool(6553600, 64);
-void * object_t::operator new (size_t size)
-{
- return pool.alloc(size);
-}
+ static plib::mempool *pool()
+ {
+ static plib::mempool *s_pool = nullptr;
+ if (s_pool == nullptr)
+ s_pool = new plib::mempool(65536, 16);
+ return s_pool;
+ }
-void object_t::operator delete (void * mem)
-{
- if (mem)
- pool.free(mem);
-}
-#else
-void * object_t::operator new (size_t size)
-{
- return ::operator new(size);
-}
+ void * object_t::operator new (size_t size)
+ {
+ void *ret = nullptr;
+ if ((USE_MEMPOOL))
+ ret = pool()->alloc(size);
+ else
+ ret = ::operator new(size);
+ return ret;
+ }
-void object_t::operator delete (void * mem)
-{
- if (mem)
- ::operator delete(mem);
-}
-#endif
+ void object_t::operator delete (void * mem)
+ {
+ if (mem)
+ {
+ if ((USE_MEMPOOL))
+ pool()->free(mem);
+ else
+ ::operator delete(mem);
+ }
+ }
}
@@ -361,12 +365,6 @@ void netlist_t::start()
/* resolve inputs */
setup().resolve_inputs();
- /* Make sure devices are fully created - now done in register_dev */
-
- log().debug("Setting delegate pointers ...\n");
- for (auto &dev : m_devices)
- dev->set_delegate_pointer();
-
log().verbose("looking for two terms connected to rail nets ...");
for (auto & t : get_device_list<analog::NETLIB_NAME(twoterm)>())
{
@@ -391,6 +389,14 @@ void netlist_t::start()
else
m_solver->post_start();
+ for (auto &n : m_nets)
+ for (auto & term : n->m_core_terms)
+ {
+ //core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
+ core_device_t *dev = &term->device();
+ dev->set_default_delegate(*term);
+ }
+
}
void netlist_t::stop()
@@ -427,6 +433,14 @@ void netlist_t::reset()
//if (m_solver != nullptr)
// m_solver->do_reset();
+ std::unordered_map<core_device_t *, bool> m;
+
+ for (auto &d : m_devices)
+ {
+ m[d.get()] = d->get_hint_deactivate();
+ }
+
+
// Reset all nets once !
for (auto & n : m_nets)
n->reset();
@@ -444,15 +458,66 @@ void netlist_t::reset()
* INFO: The order here affects power up of e.g. breakout. However, such
* variations are explicitly stated in the breakout manual.
*/
-#if 0
- for (std::size_t i = 0; i < m_devices.size(); i++)
+
+ const unsigned startup_strategy = 1; //! \note make this a parameter
+
+ switch (startup_strategy)
{
- m_devices[i]->update_dev();
+ case 0:
+ {
+ std::vector<core_device_t *> d;
+ std::vector<nldelegate *> t;
+ log().verbose("Using default startup strategy");
+ for (auto &n : m_nets)
+ for (auto & term : n->m_core_terms)
+ if (term->m_delegate.has_object())
+ {
+ if (!plib::container::contains(t, &term->m_delegate))
+ {
+ t.push_back(&term->m_delegate);
+ term->m_delegate();
+ }
+ core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
+ if (!plib::container::contains(d, dev))
+ d.push_back(dev);
+ }
+ log().verbose("Call update on devices which need parameter update:");
+ for (auto & dev : m_devices)
+ if (dev->needs_update_after_param_change())
+ {
+ if (!plib::container::contains(d, dev.get()))
+ {
+ d.push_back(dev.get());
+ log().verbose("\t ...{1}", dev->name());
+ dev->update_dev();
+ }
+ }
+ log().verbose("Devices not yet updated:");
+ for (auto &dev : m_devices)
+ if (!plib::container::contains(d, dev.get()))
+ log().verbose("\t ...{1}", dev->name());
+ //x->update_dev();
+ }
+ break;
+ case 1: // brute force backward
+ {
+ std::size_t i = m_devices.size();
+ while (i>0)
+ m_devices[--i]->update_dev();
+ }
+ break;
+ case 2: // brute force forward
+ {
+ for (std::size_t i = 0; i < m_devices.size(); i++)
+ m_devices[i]->update_dev();
+ }
+ break;
}
-#else
- std::size_t i = m_devices.size();
- while (i>0)
- m_devices[--i]->update_dev();
+
+#if 1
+ /* the above may screw up m_active and the list */
+ for (auto &n : m_nets)
+ n->rebuild_list();
#endif
}
@@ -594,9 +659,6 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner)
, m_hint_deactivate(false)
-#if (!NL_USE_PMF_VIRTUAL)
- , m_static_update()
-#endif
{
if (logic_family() == nullptr)
set_logic_family(family_TTL());
@@ -607,9 +669,6 @@ 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_USE_PMF_VIRTUAL)
- , m_static_update()
-#endif
{
set_logic_family(owner.logic_family());
if (logic_family() == nullptr)
@@ -621,11 +680,9 @@ core_device_t::~core_device_t()
{
}
-void core_device_t::set_delegate_pointer()
+void core_device_t::set_default_delegate(detail::core_terminal_t &term)
{
-#if (!NL_USE_PMF_VIRTUAL)
- m_static_update.set_base(&core_device_t::update, this);
-#endif
+ term.m_delegate.set(&core_device_t::update, this);
}
plib::plog_base<NL_DEBUG> &core_device_t::log()
@@ -789,7 +846,7 @@ void detail::net_t::update_devs() NL_NOEXCEPT
{
p.device().m_stat_call_count.inc();
if ((p.state() & mask) != 0)
- p.device().update_dev();
+ p.m_delegate();
}
}
@@ -891,6 +948,8 @@ detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &anam
, m_net(nullptr)
, m_state(*this, "m_state", state)
{
+ //m_delegate.set(&core_device_t::update, &dev);
+ //m_delegate.set(&core_device_t::update_dev, &dev);
}
detail::core_terminal_t::~core_terminal_t()
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index d6e177be9c9..3e06144168d 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -455,6 +455,10 @@ namespace netlist
core_device_t & m_device;
};
+ /*! Delegate type for device notification.
+ *
+ */
+ typedef plib::pmfp<void> nldelegate;
// -----------------------------------------------------------------------------
// core_terminal_t
@@ -509,6 +513,8 @@ namespace netlist
void reset();
+ nldelegate m_delegate;
+
private:
net_t * m_net;
state_var<state_e> m_state;
@@ -1044,14 +1050,16 @@ namespace netlist
void do_reset() { reset(); }
void set_hint_deactivate(bool v) { m_hint_deactivate = v; }
+ bool get_hint_deactivate() { return m_hint_deactivate; }
- void set_delegate_pointer();
+ void set_default_delegate(detail::core_terminal_t &term);
/* stats */
nperftime_t m_stat_total_time;
nperfcount_t m_stat_call_count;
nperfcount_t m_stat_inc_active;
+
protected:
virtual void update() NL_NOEXCEPT { }
@@ -1061,11 +1069,7 @@ namespace netlist
void do_update() NL_NOEXCEPT
{
- #if (NL_USE_PMF_VIRTUAL)
update();
- #else
- m_static_update.call(this);
- #endif
}
plib::plog_base<NL_DEBUG> &log();
@@ -1081,10 +1085,6 @@ namespace netlist
private:
bool m_hint_deactivate;
-
- #if (!NL_USE_PMF_VIRTUAL)
- plib::pmfp_base<void> m_static_update;
- #endif
};
// -----------------------------------------------------------------------------
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index ded567717f9..57b6a03f031 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -95,16 +95,6 @@ using nl_double = double;
* 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
//============================================================
@@ -115,9 +105,4 @@ using nl_double = double;
#endif
#endif
-#ifdef __APPLE__
-#undef USE_MEMPOOL
-#define USE_MEMPOOL (0)
-#endif
-
#endif /* NLCONFIG_H_ */
diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h
index f0789b909a1..a841db1e084 100644
--- a/src/lib/netlist/nl_lists.h
+++ b/src/lib/netlist/nl_lists.h
@@ -54,7 +54,7 @@ namespace netlist
struct entry_t final
{
- constexpr entry_t() { }
+ constexpr entry_t() : m_exec_time(), m_object(nullptr) { }
constexpr entry_t(const Time &t, const Element &o) : m_exec_time(t), m_object(o) { }
constexpr entry_t(const entry_t &e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
constexpr entry_t(entry_t &&e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
diff --git a/src/lib/netlist/plib/palloc.cpp b/src/lib/netlist/plib/palloc.cpp
index ceee5a75904..1377edabde5 100644..100755
--- a/src/lib/netlist/plib/palloc.cpp
+++ b/src/lib/netlist/plib/palloc.cpp
@@ -5,6 +5,8 @@
*
*/
+#include <algorithm>
+
#include "pconfig.h"
#include "palloc.h"
#include "pfmtlog.h"
@@ -27,7 +29,7 @@ mempool::~mempool()
{
fprintf(stderr, "Found block with %d dangling allocations\n", static_cast<int>(b.m_num_alloc));
}
- delete b.data;
+ ::operator delete(b.data);
}
m_blocks.clear();
}
@@ -35,7 +37,7 @@ mempool::~mempool()
size_t mempool::new_block()
{
block b;
- b.data = new char[m_min_alloc];
+ b.data = static_cast<char *>(::operator new(m_min_alloc));
b.cur_ptr = b.data;
b.m_free = m_min_alloc;
b.m_num_alloc = 0;
@@ -43,10 +45,19 @@ size_t mempool::new_block()
return m_blocks.size() - 1;
}
+size_t mempool::mininfosize()
+{
+ size_t sinfo = sizeof(mempool::info);
+ size_t ma = 8;
+#ifdef __APPLE__
+ ma = 16;
+#endif
+ return ((std::max(m_min_align, sinfo) + ma - 1) / ma) * ma;
+}
void *mempool::alloc(size_t size)
{
- size_t rs = (size + sizeof(info) + m_min_align - 1) & ~(m_min_align - 1);
+ size_t rs = (size + mininfosize() + m_min_align - 1) & ~(m_min_align - 1);
for (size_t bn=0; bn < m_blocks.size(); bn++)
{
auto &b = m_blocks[bn];
@@ -56,7 +67,7 @@ void *mempool::alloc(size_t size)
b.m_num_alloc++;
auto i = reinterpret_cast<info *>(b.cur_ptr);
i->m_block = bn;
- auto ret = reinterpret_cast<void *>(b.cur_ptr + sizeof(info));
+ auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize());
b.cur_ptr += rs;
return ret;
}
@@ -68,7 +79,7 @@ void *mempool::alloc(size_t size)
b.m_free = m_min_alloc - rs;
auto i = reinterpret_cast<info *>(b.cur_ptr);
i->m_block = bn;
- auto ret = reinterpret_cast<void *>(b.cur_ptr + sizeof(info));
+ auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize());
b.cur_ptr += rs;
return ret;
}
@@ -78,7 +89,7 @@ void mempool::free(void *ptr)
{
auto p = reinterpret_cast<char *>(ptr);
- auto i = reinterpret_cast<info *>(p - sizeof(info));
+ auto i = reinterpret_cast<info *>(p - mininfosize());
block *b = &m_blocks[i->m_block];
if (b->m_num_alloc == 0)
fprintf(stderr, "Argh .. double free\n");
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index 2e4c2809048..02249f09168 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -144,6 +144,7 @@ private:
};
size_t new_block();
+ size_t mininfosize();
struct info
{
@@ -151,6 +152,11 @@ private:
size_t m_block;
};
+ size_t m_min_alloc;
+ size_t m_min_align;
+
+ std::vector<block> m_blocks;
+
public:
mempool(size_t min_alloc, size_t min_align);
~mempool();
@@ -158,10 +164,6 @@ public:
void *alloc(size_t size);
void free(void *ptr);
- size_t m_min_alloc;
- size_t m_min_align;
-
- std::vector<block> m_blocks;
};
}
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index e3870206cbd..e5a98fb5be8 100644..100755
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -71,13 +71,13 @@ typedef __int128_t INT128;
#define MEMBER_ABI _thiscall
#elif defined(__clang__) && defined(__i386__) && defined(_WIN32)
#define PHAS_PMF_INTERNAL 0
- #elif defined(EMSCRIPTEN)
- #define PHAS_PMF_INTERNAL 0
- #elif defined(__arm__) || defined(__ARMEL__)
- #define PHAS_PMF_INTERNAL 0
+ #elif defined(__arm__) || defined(__ARMEL__) || defined(__aarch64__) || defined(__MIPSEL__) || defined(__mips_isa_rev) || defined(__mips64) || defined(EMSCRIPTEN)
+ #define PHAS_PMF_INTERNAL 2
#else
#define PHAS_PMF_INTERNAL 1
#endif
+#elif defined(_MSC_VER) && defined (_M_X64)
+ #define PHAS_PMF_INTERNAL 3
#else
#define PHAS_PMF_INTERNAL 0
#endif
@@ -87,7 +87,7 @@ typedef __int128_t INT128;
#endif
#ifndef PPMF_TYPE
- #if PHAS_PMF_INTERNAL
+ #if (PHAS_PMF_INTERNAL > 0)
#define PPMF_TYPE PPMF_TYPE_INTERNAL
#else
#define PPMF_TYPE PPMF_TYPE_PMF
diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h
index 03a2a65baa4..a80fbf2ec86 100644..100755
--- a/src/lib/netlist/plib/ppmf.h
+++ b/src/lib/netlist/plib/ppmf.h
@@ -51,44 +51,82 @@ namespace plib {
* It derives a pointer to a member function.
*/
-#if (PHAS_PMF_INTERNAL)
+#if (PHAS_PMF_INTERNAL > 0)
class mfp
{
public:
// construct from any member function pointer
+#ifdef _MSC_VER
+ class __single_inheritance si_generic_class;
+ class generic_class { };
+#else
class generic_class;
+#endif
using generic_function = void (*)();
template<typename MemberFunctionType>
mfp(MemberFunctionType mftp)
- : m_function(0), m_this_delta(0)
+ : m_function(0), m_this_delta(0), m_size(sizeof(mfp))
{
*reinterpret_cast<MemberFunctionType *>(this) = mftp;
}
- template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
- static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
+ template<typename MemberFunctionType, typename FunctionType, typename ObjectType>
+ static void get_mfp(MemberFunctionType mftp, FunctionType &func, ObjectType *&object)
{
mfp mfpo(mftp);
//return mfpo.update_after_bind<FunctionType>(object);
- return reinterpret_cast<FunctionType>(
- mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object)));
+ generic_function rfunc(nullptr);
+ generic_class *robject = reinterpret_cast<generic_class *>(object);
+ mfpo.convert_to_generic(rfunc, robject);
+ func = reinterpret_cast<FunctionType>(rfunc);
+ object = reinterpret_cast<ObjectType *>(robject);
}
private:
// extract the generic function and adjust the object pointer
- generic_function convert_to_generic(generic_class * object) const
+ void convert_to_generic(generic_function &func, generic_class *&object) const
{
- // apply the "this" delta to the object first
- generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+ if (PHAS_PMF_INTERNAL == 1)
+ {
+ // apply the "this" delta to the object first
+ generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+
+ // if the low bit of the vtable index is clear, then it is just a raw function pointer
+ if (!(m_function & 1))
+ func = reinterpret_cast<generic_function>(m_function);
+ else
+ {
+ // otherwise, it is the byte index into the vtable where the actual function lives
+ std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
+ func = *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
+ }
+ object = o_p_delta;
+ }
+ else if (PHAS_PMF_INTERNAL == 2)
+ {
+ if ((m_this_delta & 1) == 0) {
+ object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+ func = reinterpret_cast<generic_function>(m_function);
+ }
+ else
+ {
+ object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object));
+
+ // otherwise, it is the byte index into the vtable where the actual function lives
+ std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object);
+ func = *reinterpret_cast<generic_function *>(vtable_base + m_function + m_this_delta - 1);
+ }
+ }
+ else if (PHAS_PMF_INTERNAL == 3)
+ {
+ const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (generic_class::*)());
+
+ func = reinterpret_cast<generic_function>(m_function);
+ if (m_size == SINGLE_MEMFUNCPTR_SIZE + sizeof(int))
+ object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+ }
- // if the low bit of the vtable index is clear, then it is just a raw function pointer
- if (!(m_function & 1))
- return reinterpret_cast<generic_function>(m_function);
-
- // otherwise, it is the byte index into the vtable where the actual function lives
- std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
- return *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
}
// actual state
@@ -96,6 +134,10 @@ namespace plib {
// if even, it's a pointer to the function
// if odd, it's the byte offset into the vtable
int m_this_delta; // delta to apply to the 'this' pointer
+
+ int m_dummy1; // only used for visual studio x64
+ int m_dummy2;
+ int m_size;
};
#endif
@@ -107,12 +149,18 @@ namespace plib {
class generic_class;
#if defined (__INTEL_COMPILER) && defined (_M_X64) // needed for "Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.2.176 Build 20140130" at least
using generic_function = int [((sizeof(void *) + 4 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)];
-#elif defined(_MSC_VER)// all other cases - for MSVC maximum size is one pointer, plus 3 ints; all other implementations seem to be smaller
- using generic_function = int [((sizeof(void *) + 3 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)];
+#elif defined(_MSC_VER) // all other cases - for MSVC maximum size is one pointer, plus 3 ints; all other implementations seem to be smaller
+ using generic_function = int[((sizeof(void *) + 3 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)];
#else
using generic_function = R (generic_class::*)(Targs...);
#endif
- pmfp_base() {}
+ pmfp_base()
+ {
+ int *p = reinterpret_cast<int *>(&m_func);
+ int *e = p + sizeof(generic_function) / sizeof(int);
+ for (; p < e; p++)
+ *p = 0;
+ }
template<typename MemberFunctionType, typename O>
void set_base(MemberFunctionType mftp, O *object)
@@ -130,6 +178,9 @@ namespace plib {
}
private:
generic_function m_func;
+#if 0 && defined(_MSC_VER)
+ int dummy[4];
+#endif
};
#elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL))
@@ -146,7 +197,9 @@ namespace plib {
{
#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));
+ function_ptr func(nullptr);
+ plib::mfp::get_mfp(mftp, func, object);
+ m_func = reinterpret_cast<generic_function>(func);
#elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
R (O::* pFunc)(Targs...) = mftp;
m_func = reinterpret_cast<generic_function>((object->*pFunc));
@@ -159,6 +212,7 @@ namespace plib {
return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
}
bool is_set() { return m_func != nullptr; }
+ generic_function get_function() const { return m_func; }
private:
generic_function m_func;
};
@@ -188,6 +242,9 @@ namespace plib {
{
return this->call(m_obj, std::forward<Targs>(args)...);
}
+
+ generic_class *object() const { return m_obj; }
+ bool has_object() const { return m_obj != nullptr; }
private:
generic_class *m_obj;
};
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index d2ecf3c5bd2..e769797c42e 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -404,7 +404,6 @@ void NETLIB_NAME(solver)::post_start()
}
// FIXME ...
- ms->set_delegate_pointer();
ms->setup(grp);
log().verbose("Solver {1}", ms->name());