Netlist now uses the same approach as delegate.h to derive member

function pointers. If the platform doesn't support this approach,
virtual function calls will be used. In addition, this commit contains
modifications for standalone compile. (nw)
This commit is contained in:
couriersud 2015-05-31 00:25:13 +02:00
parent 2f13be3ec5
commit 3a455f75a5
25 changed files with 266 additions and 126 deletions

View File

@ -294,7 +294,7 @@ void netlist_mame_device_t::device_start()
//printf("clock is %d\n", clock());
m_netlist = global_alloc_clear(netlist_mame_t(*this));
m_setup = global_alloc_clear(netlist_setup_t(*m_netlist));
m_setup = global_alloc_clear(netlist_setup_t(m_netlist));
netlist().init_object(*m_netlist, "netlist");
m_setup->init();

View File

@ -15,8 +15,8 @@ class netlist_matrix_solver_direct_t: public netlist_matrix_solver_t
{
public:
netlist_matrix_solver_direct_t(const netlist_solver_parameters_t &params, const int size);
netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t &params, const int size);
netlist_matrix_solver_direct_t(const netlist_solver_parameters_t *params, const int size);
netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t *params, const int size);
virtual ~netlist_matrix_solver_direct_t();
@ -417,7 +417,7 @@ ATTR_HOT inline int netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_
}
template <unsigned m_N, unsigned _storage_N>
netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const netlist_solver_parameters_t &params, const int size)
netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const netlist_solver_parameters_t *params, const int size)
: netlist_matrix_solver_t(GAUSSIAN_ELIMINATION, params)
, m_dim(size)
, m_lp_fact(0)
@ -434,7 +434,7 @@ netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(
}
template <unsigned m_N, unsigned _storage_N>
netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t &params, const int size)
netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t *params, const int size)
: netlist_matrix_solver_t(type, params)
, m_dim(size)
, m_lp_fact(0)

View File

@ -15,7 +15,7 @@ class netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1
{
public:
netlist_matrix_solver_direct1_t(const netlist_solver_parameters_t &params)
netlist_matrix_solver_direct1_t(const netlist_solver_parameters_t *params)
: netlist_matrix_solver_direct_t<1, 1>(params, 1)
{}
ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);

View File

@ -17,7 +17,7 @@ class netlist_matrix_solver_direct2_t: public netlist_matrix_solver_direct_t<2,2
{
public:
netlist_matrix_solver_direct2_t(const netlist_solver_parameters_t &params)
netlist_matrix_solver_direct2_t(const netlist_solver_parameters_t *params)
: netlist_matrix_solver_direct_t<2, 2>(params, 2)
{}
ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);

View File

@ -20,7 +20,7 @@ class netlist_matrix_solver_SOR_t: public netlist_matrix_solver_direct_t<m_N, _s
{
public:
netlist_matrix_solver_SOR_t(const netlist_solver_parameters_t &params, int size)
netlist_matrix_solver_SOR_t(const netlist_solver_parameters_t *params, int size)
: netlist_matrix_solver_direct_t<m_N, _storage_N>(netlist_matrix_solver_t::GAUSS_SEIDEL, params, size)
, m_lp_fact(0)
, m_gs_fail(0)

View File

@ -20,9 +20,9 @@ class netlist_matrix_solver_SOR_mat_t: public netlist_matrix_solver_direct_t<m_N
{
public:
netlist_matrix_solver_SOR_mat_t(const netlist_solver_parameters_t &params, int size)
netlist_matrix_solver_SOR_mat_t(const netlist_solver_parameters_t *params, int size)
: netlist_matrix_solver_direct_t<m_N, _storage_N>(netlist_matrix_solver_t::GAUSS_SEIDEL, params, size)
, m_omega(params.m_sor)
, m_omega(params->m_sor)
, m_lp_fact(0)
, m_gs_fail(0)
, m_gs_total(0)

View File

@ -64,11 +64,11 @@ ATTR_COLD void terms_t::set_pointers()
// netlist_matrix_solver
// ----------------------------------------------------------------------------------------
ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t &params)
ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t *params)
: m_stat_calculations(0),
m_stat_newton_raphson(0),
m_stat_vsolver_calls(0),
m_params(params),
m_params(*params),
m_cur_ts(0),
m_type(type)
{
@ -399,9 +399,9 @@ template <int m_N, int _storage_N>
netlist_matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const int gs_threshold, const bool use_specific)
{
if (use_specific && m_N == 1)
return palloc(netlist_matrix_solver_direct1_t, m_params);
return palloc(netlist_matrix_solver_direct1_t, &m_params);
else if (use_specific && m_N == 2)
return palloc(netlist_matrix_solver_direct2_t, m_params);
return palloc(netlist_matrix_solver_direct2_t, &m_params);
else
{
if (size >= gs_threshold)
@ -409,18 +409,18 @@ netlist_matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const int
if (USE_MATRIX_GS)
{
typedef netlist_matrix_solver_SOR_mat_t<m_N,_storage_N> solver_mat;
return palloc(solver_mat, m_params, size);
return palloc(solver_mat, &m_params, size);
}
else
{
typedef netlist_matrix_solver_SOR_t<m_N,_storage_N> solver_GS;
return palloc(solver_GS, m_params, size);
return palloc(solver_GS, &m_params, size);
}
}
else
{
typedef netlist_matrix_solver_direct_t<m_N,_storage_N> solver_D;
return palloc(solver_D, m_params, size);
return palloc(solver_D, &m_params, size);
}
}
}

View File

@ -99,7 +99,7 @@ public:
GAUSS_SEIDEL
};
ATTR_COLD netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t &params);
ATTR_COLD netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t *params);
/* ATTR_COLD */ virtual ~netlist_matrix_solver_t();
/* ATTR_COLD */ virtual void vsetup(netlist_analog_net_t::list_t &nets) = 0;

View File

@ -5,6 +5,8 @@
*
*/
#include <algorithm>
#include "nld_twoterm.h"
#include "nld_solver.h"

View File

@ -261,12 +261,12 @@ private:
class nld_base_proxy : public netlist_device_t
{
public:
ATTR_COLD nld_base_proxy(netlist_logic_t &inout_proxied, netlist_core_terminal_t &proxy_inout)
ATTR_COLD nld_base_proxy(netlist_logic_t *inout_proxied, netlist_core_terminal_t *proxy_inout)
: netlist_device_t()
{
m_logic_family = inout_proxied.logic_family();
m_term_proxied = &inout_proxied;
m_proxy_term = &proxy_inout;
m_logic_family = inout_proxied->logic_family();
m_term_proxied = inout_proxied;
m_proxy_term = proxy_inout;
}
/* ATTR_COLD */ virtual ~nld_base_proxy() {}
@ -294,8 +294,8 @@ private:
class nld_a_to_d_proxy : public nld_base_proxy
{
public:
ATTR_COLD nld_a_to_d_proxy(netlist_logic_input_t &in_proxied)
: nld_base_proxy(in_proxied, m_I)
ATTR_COLD nld_a_to_d_proxy(netlist_logic_input_t *in_proxied)
: nld_base_proxy(in_proxied, &m_I)
{
}
@ -336,7 +336,7 @@ private:
class nld_base_d_to_a_proxy : public nld_base_proxy
{
public:
ATTR_COLD nld_base_d_to_a_proxy(netlist_logic_output_t &out_proxied, netlist_core_terminal_t &proxy_out)
ATTR_COLD nld_base_d_to_a_proxy(netlist_logic_output_t *out_proxied, netlist_core_terminal_t *proxy_out)
: nld_base_proxy(out_proxied, proxy_out)
{
}
@ -359,8 +359,8 @@ private:
class nld_d_to_a_proxy : public nld_base_d_to_a_proxy
{
public:
ATTR_COLD nld_d_to_a_proxy(netlist_logic_output_t &out_proxied)
: nld_base_d_to_a_proxy(out_proxied, m_RV.m_P)
ATTR_COLD nld_d_to_a_proxy(netlist_logic_output_t *out_proxied)
: nld_base_d_to_a_proxy(out_proxied, &m_RV.m_P)
, m_RV(TWOTERM)
, m_last_state(-1)
, m_is_timestep(false)

View File

@ -6,6 +6,7 @@
*/
#include <cstring>
#include <algorithm>
#include "plib/palloc.h"
@ -51,7 +52,7 @@ public:
m_R_low = 1.0;
m_R_high = 130.0;
}
virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t &proxied) const
virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t *proxied) const
{
return palloc(nld_d_to_a_proxy , proxied);
}
@ -71,7 +72,7 @@ public:
m_R_low = 1.0;
m_R_high = 130.0;
}
virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t &proxied) const
virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t *proxied) const
{
return palloc(nld_d_to_a_proxy , proxied);
}
@ -419,15 +420,15 @@ ATTR_COLD void netlist_core_device_t::init(netlist_base_t &anetlist, const pstri
set_logic_family(this->default_logic_family());
init_object(anetlist, name);
#if USE_PMFDELEGATES
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
void (netlist_core_device_t::* pFunc)() = &netlist_core_device_t::update;
#if NO_USE_PMFCONVERSION
static_update = pFunc;
#else
#elif (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
void (netlist_core_device_t::* pFunc)() = &netlist_core_device_t::update;
static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
#elif (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)
static_update = pmfp::get_mfp<net_update_delegate>(&netlist_core_device_t::update, this);
#endif
#endif
}
ATTR_COLD netlist_core_device_t::~netlist_core_device_t()
@ -665,7 +666,7 @@ ATTR_COLD void netlist_net_t::save_register()
netlist_object_t::save_register();
}
ATTR_HOT inline void netlist_core_terminal_t::update_dev(const UINT32 mask)
ATTR_HOT /* inline */ void netlist_core_terminal_t::update_dev(const UINT32 mask)
{
inc_stat(netdev().stat_call_count);
if ((state() & mask) != 0)
@ -674,7 +675,7 @@ ATTR_HOT inline void netlist_core_terminal_t::update_dev(const UINT32 mask)
}
}
ATTR_HOT inline void netlist_net_t::update_devs()
ATTR_HOT /* inline */ void netlist_net_t::update_devs()
{
//assert(m_num_cons != 0);
nl_assert(this->isRailNet());
@ -1056,7 +1057,7 @@ ATTR_COLD nl_double netlist_param_model_t::model_value(const pstring &entity, co
// mainclock
// ----------------------------------------------------------------------------------------
ATTR_HOT inline void NETLIB_NAME(mainclock)::mc_update(netlist_logic_net_t &net)
ATTR_HOT /* inline */ void NETLIB_NAME(mainclock)::mc_update(netlist_logic_net_t &net)
{
net.toggle_new_Q();
net.update_devs();

View File

@ -170,13 +170,11 @@
class netlist_core_device_t;
#if USE_PMFDELEGATES
#if NO_USE_PMFCONVERSION
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
typedef void (netlist_core_device_t::*net_update_delegate)();
#else
#elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
typedef void (*net_update_delegate)(netlist_core_device_t *);
#endif
#endif
//============================================================
// MACROS / netlist devices
@ -312,7 +310,7 @@ class netlist_logic_family_desc_t
{
public:
virtual ~netlist_logic_family_desc_t() {}
virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t &proxied) const = 0;
virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t *proxied) const = 0;
nl_double m_low_thresh_V;
nl_double m_high_thresh_V;
@ -482,7 +480,7 @@ public:
}
ATTR_HOT inline void update_dev(const UINT32 mask);
ATTR_HOT /* inline */ void update_dev(const UINT32 mask);
protected:
/* ATTR_COLD */ virtual void save_register()
@ -1016,12 +1014,11 @@ public:
{
begin_timing(stat_total_time);
inc_stat(stat_update_count);
#if USE_PMFDELEGATES
#if NO_USE_PMFCONVERSION
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
(this->*static_update)();
#else
#elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
static_update(this);
#endif
#else
update();
#endif
@ -1059,8 +1056,6 @@ public:
ATTR_HOT virtual void step_time(ATTR_UNUSED const nl_double st) { }
ATTR_HOT virtual void update_terminals() { }
#if (NL_KEEP_STATISTICS)
/* stats */
osd_ticks_t stat_total_time;
@ -1068,10 +1063,6 @@ public:
INT32 stat_call_count;
#endif
#if USE_PMFDELEGATES
net_update_delegate static_update;
#endif
protected:
ATTR_HOT virtual void update() { }
@ -1083,6 +1074,9 @@ protected:
}
private:
#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
net_update_delegate static_update;
#endif
};

View File

@ -15,30 +15,55 @@
//============================================================
/*
* The next options needs -Wno-pmf-conversions to compile and gcc
* There is quite some significant speed-up of up to 20% involved.
* NO_USE_PMFCONVERSION is for illustrative purposes only. Using PMFs
* has some overhead in comparison to calling a virtual function.
* The following options determine how object::update is called.
* NL_PMF_TYPE_VIRTUAL
* Use stock virtual call
*
* To get a performance increase we need the GCC extension.
* NL_PMF_TYPE_GNUC_PMF
* Use standard pointer to member function syntax
*
* Todo: This doesn't work with current (4.8+) mingw 32bit builds.
* Therefore disabled for now for i386 builds.
* 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, ATTR_COLD 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.
*/
#ifndef USE_PMFDELEGATES
#if defined(__clang__) || defined(__APPLE__) || (defined(__GNUC__) && defined(__i386__))
#define USE_PMFDELEGATES (0)
#define NO_USE_PMFCONVERSION (1)
#elif defined(__GNUC__)
#define USE_PMFDELEGATES (0)
#define NO_USE_PMFCONVERSION (0)
#pragma GCC diagnostic ignored "-Wpmf-conversions"
#else
#define USE_PMFDELEGATES (0)
#define NO_USE_PMFCONVERSION (1)
// This will be autodetected
// #define NL_PMF_TYPE 3
#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
/*
@ -69,7 +94,6 @@
#define NETLIST_GMIN_DEFAULT (1e-9)
//#define nl_double float
//#define NL_FCONST(x) (x ## f)

View File

@ -34,11 +34,11 @@ NETLIST_END()
// netlist_setup_t
// ----------------------------------------------------------------------------------------
netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
netlist_setup_t::netlist_setup_t(netlist_base_t *netlist)
: m_netlist(netlist)
, m_proxy_cnt(0)
{
netlist.set_setup(this);
netlist->set_setup(this);
m_factory = palloc(netlist_factory_list_t);
}
@ -394,7 +394,7 @@ nld_base_proxy *netlist_setup_t::get_d_a_proxy(netlist_core_terminal_t &out)
if (proxy == NULL)
{
// create a new one ...
nld_base_d_to_a_proxy *new_proxy = out_cast.logic_family()->create_d_a_proxy(out_cast);
nld_base_d_to_a_proxy *new_proxy = out_cast.logic_family()->create_d_a_proxy(&out_cast);
pstring x = pstring::sprintf("proxy_da_%s_%d", out.name().cstr(), m_proxy_cnt);
m_proxy_cnt++;
@ -425,7 +425,7 @@ void netlist_setup_t::connect_input_output(netlist_core_terminal_t &in, netlist_
if (out.isFamily(netlist_terminal_t::ANALOG) && in.isFamily(netlist_terminal_t::LOGIC))
{
netlist_logic_input_t &incast = dynamic_cast<netlist_logic_input_t &>(in);
nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, incast);
nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, &incast);
incast.set_proxy(proxy);
pstring x = pstring::sprintf("proxy_ad_%s_%d", in.name().cstr(), m_proxy_cnt);
m_proxy_cnt++;
@ -464,7 +464,7 @@ void netlist_setup_t::connect_terminal_input(netlist_terminal_t &term, netlist_c
{
netlist_logic_input_t &incast = dynamic_cast<netlist_logic_input_t &>(inp);
NL_VERBOSE_OUT(("connect_terminal_input: connecting proxy\n"));
nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, incast);
nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, &incast);
incast.set_proxy(proxy);
pstring x = pstring::sprintf("proxy_ad_%s_%d", inp.name().cstr(), m_proxy_cnt);
m_proxy_cnt++;
@ -745,13 +745,13 @@ void netlist_setup_t::resolve_inputs()
netlist().log("initialize solver ...\n");
if (m_netlist.solver() == NULL)
if (netlist().solver() == NULL)
{
if (has_twoterms)
netlist().error("No solver found for this net although analog elements are present\n");
}
else
m_netlist.solver()->post_start();
netlist().solver()->post_start();
}

View File

@ -107,13 +107,13 @@ public:
typedef pnamedlist_t<netlist_core_terminal_t *> tagmap_terminal_t;
typedef plist_t<link_t> tagmap_link_t;
netlist_setup_t(netlist_base_t &netlist);
netlist_setup_t(netlist_base_t *netlist);
~netlist_setup_t();
void init();
netlist_base_t &netlist() { return m_netlist; }
const netlist_base_t &netlist() const { return m_netlist; }
netlist_base_t &netlist() { return *m_netlist; }
const netlist_base_t &netlist() const { return *m_netlist; }
pstring build_fqn(const pstring &obj_name) const;
@ -159,7 +159,7 @@ protected:
private:
netlist_base_t &m_netlist;
netlist_base_t *m_netlist;
tagmap_nstring_t m_alias;
tagmap_param_t m_params;

View File

@ -31,44 +31,44 @@ public:
static const INTERNALTYPE RESOLUTION = NETLIST_INTERNAL_RES;
ATTR_HOT inline netlist_time() : m_time(0) {}
ATTR_HOT /* inline */ netlist_time() : m_time(0) {}
ATTR_HOT friend inline const netlist_time operator-(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend inline const netlist_time operator+(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend inline const netlist_time operator*(const netlist_time &left, const UINT32 factor);
ATTR_HOT friend inline UINT32 operator/(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend inline bool operator>(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend inline bool operator<(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend inline bool operator>=(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend inline bool operator<=(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend inline bool operator!=(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend /* inline */ const netlist_time operator-(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend /* inline */ const netlist_time operator+(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend /* inline */ const netlist_time operator*(const netlist_time &left, const UINT32 factor);
ATTR_HOT friend /* inline */ UINT32 operator/(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend /* inline */ bool operator>(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend /* inline */ bool operator<(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend /* inline */ bool operator>=(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend /* inline */ bool operator<=(const netlist_time &left, const netlist_time &right);
ATTR_HOT friend /* inline */ bool operator!=(const netlist_time &left, const netlist_time &right);
ATTR_HOT inline const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
ATTR_HOT inline const netlist_time &operator=(const double &right) { m_time = (INTERNALTYPE) ( right * (double) RESOLUTION); return *this; }
ATTR_HOT /* inline */ const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
ATTR_HOT /* inline */ const netlist_time &operator=(const double &right) { m_time = (INTERNALTYPE) ( right * (double) RESOLUTION); return *this; }
// issues with ISO C++ standard
//ATTR_HOT inline operator double() const { return as_double(); }
//ATTR_HOT /* inline */ operator double() const { return as_double(); }
ATTR_HOT inline const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
ATTR_HOT /* inline */ const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
ATTR_HOT inline INTERNALTYPE as_raw() const { return m_time; }
ATTR_HOT inline double as_double() const { return (double) m_time / (double) RESOLUTION; }
ATTR_HOT /* inline */ INTERNALTYPE as_raw() const { return m_time; }
ATTR_HOT /* inline */ double as_double() const { return (double) m_time / (double) RESOLUTION; }
// for save states ....
ATTR_HOT inline INTERNALTYPE *get_internaltype_ptr() { return &m_time; }
ATTR_HOT /* inline */ INTERNALTYPE *get_internaltype_ptr() { return &m_time; }
ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }
ATTR_HOT static inline const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); }
ATTR_HOT static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
ATTR_HOT static inline const netlist_time from_double(const double t) { return netlist_time((INTERNALTYPE) ( t * (double) RESOLUTION)); }
ATTR_HOT static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
ATTR_HOT static /* inline */ const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
ATTR_HOT static /* inline */ const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }
ATTR_HOT static /* inline */ const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); }
ATTR_HOT static /* inline */ const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
ATTR_HOT static /* inline */ const netlist_time from_double(const double t) { return netlist_time((INTERNALTYPE) ( t * (double) RESOLUTION)); }
ATTR_HOT static /* inline */ const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
static const netlist_time zero;
protected:
ATTR_HOT inline netlist_time(const INTERNALTYPE val) : m_time(val) {}
ATTR_HOT /* inline */ netlist_time(const INTERNALTYPE val) : m_time(val) {}
private:
INTERNALTYPE m_time;

View File

@ -10,6 +10,7 @@
#include <cmath>
#include <cstring>
#include <cstdlib>
#include "plib/pstring.h"
#include "plib/plists.h"

View File

@ -40,28 +40,28 @@ inline T *palloc_t()
}
template<typename T, typename P1>
inline T *palloc_t(P1 &p1)
inline T *palloc_t(P1 p1)
{
void *p = palloc_raw(sizeof(T));
return new (p) T(p1);
}
template<typename T, typename P1, typename P2>
inline T *palloc_t(P1 &p1, P2 &p2)
inline T *palloc_t(P1 p1, P2 p2)
{
void *p = palloc_raw(sizeof(T));
return new (p) T(p1, p2);
}
template<typename T, typename P1, typename P2, typename P3>
inline T *palloc_t(P1 &p1, P2 &p2, P3 &p3)
inline T *palloc_t(P1 p1, P2 p2, P3 p3)
{
void *p = palloc_raw(sizeof(T));
return new (p) T(p1, p2, p3);
}
template<typename T, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
inline T *palloc_t(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7)
inline T *palloc_t(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
{
void *p = palloc_raw(sizeof(T));
return new (p) T(p1, p2, p3, p4, p5, p6, p7);
@ -87,9 +87,13 @@ inline void pfree_array_t(T *p)
delete[] p;
}
#if 1
#define palloc(T, ...) palloc_t<T>(__VA_ARGS__)
#define pfree(_ptr) pfree_t(_ptr)
#else
#define palloc(T, ...) new T(__VA_ARGS__)
#define pfree(_ptr) delete(_ptr)
#endif
#define palloc_array(T, N) palloc_array_t<T>(N)
#define pfree_array(_ptr) pfree_array_t(_ptr)

View File

@ -12,24 +12,56 @@
#define PSTANDALONE (0)
#endif
//============================================================
// Compiling standalone
//============================================================
// Compiling without mame ?
#include <algorithm>
#include <cstdarg>
#if !(PSTANDALONE)
#include "osdcore.h"
#include "eminline.h"
#undef ATTR_COLD
#define ATTR_COLD
#ifndef assert
#define assert(x) do {} while (0)
#endif
#include "delegate.h"
#else
#include <stdint.h>
#include <cstddef>
#endif
//============================================================
// Compiling standalone
//============================================================
#if !(PSTANDALONE)
#undef ATTR_COLD
#define ATTR_COLD
/* use MAME */
#if (USE_DELEGATE_TYPE == DELEGATE_TYPE_INTERNAL)
#define PHAS_PMF_INTERNAL 1
#else
#define PHAS_PMF_INTERNAL 0
#endif
#else
/* determine PMF approach */
#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)))
#define PHAS_PMF_INTERNAL 0
#elif defined(EMSCRIPTEN)
#define PHAS_PMF_INTERNAL 0
#elif defined(__arm__) || defined(__ARMEL__)
#define PHAS_PMF_INTERNAL 0
#else
#define PHAS_PMF_INTERNAL 1
#endif
#else
#define USE_DELEGATE_TYPE PHAS_PMF_INTERNAL 0
#endif
/* not supported in GCC prior to 4.4.x */
/* ATTR_HOT and ATTR_COLD cause performance degration in 5.1 */
@ -97,4 +129,66 @@ typedef int64_t INT64;
#endif
/*
* The following class was derived from the MAME delegate.h code.
* It derives a pointer to a member function.
*/
#if (PHAS_PMF_INTERNAL)
class pmfp
{
public:
// construct from any member function pointer
class generic_class;
typedef void (*generic_function)();
#if (PSTANDALONE)
typedef std::size_t FPTR;
#endif
template<typename _MemberFunctionType>
pmfp(_MemberFunctionType mfp)
: m_function(0), m_this_delta(0)
{
*reinterpret_cast<_MemberFunctionType *>(this) = mfp;
}
// 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 mfp, _ObjectType *object)
{
pmfp mfpo(mfp);
return mfpo.update_after_bind<_FunctionType>(object);
}
private:
// extract the generic function and adjust the object pointer
generic_function convert_to_generic(generic_class * object) const
{
// apply the "this" delta to the object first
generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<UINT8 *>(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
UINT8 *vtable_base = *reinterpret_cast<UINT8 **>(o_p_delta);
return *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
}
// actual state
FPTR m_function; // first item can be one of two things:
// 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
};
#endif
#endif /* PCONFIG_H_ */

View File

@ -6,6 +6,7 @@
*/
#include <cstdio>
#include <cstdarg>
#include "pparser.h"

View File

@ -71,6 +71,7 @@ NETLIST_SAVE_TYPE(INT32, DT_INT);
NETLIST_SAVE_TYPE(UINT16, DT_INT16);
NETLIST_SAVE_TYPE(INT16, DT_INT16);
//NETLIST_SAVE_TYPE(netlist_time::INTERNALTYPE, DT_INT64);
//NETLIST_SAVE_TYPE(std::size_t, DT_INT64);
class pstate_manager_t;

View File

@ -5,12 +5,12 @@
*
*/
#include <new>
#include <cstdio>
#include <cstring>
//FIXME:: pstring should be locale free
#include <cctype>
#include <cstdlib>
#include <algorithm>
#include "pstring.h"
#include "palloc.h"

View File

@ -7,6 +7,8 @@
#ifndef _PSTRING_H_
#define _PSTRING_H_
#include <cstdarg>
#include "pconfig.h"
// ----------------------------------------------------------------------------------------

View File

@ -11,6 +11,7 @@
#define NL_CONVERT_H_
#include <cstddef>
#include <cstdarg>
#include "plib/pstring.h"
#include "plib/plists.h"
@ -462,7 +463,7 @@ public:
void verror(pstring msg, int line_num, pstring line)
{
m_convert.out("abc");
m_convert.out("%s (line %d): %s\n", msg.cstr(), line_num, line.cstr());
}

View File

@ -183,7 +183,7 @@ public:
void init()
{
m_setup = palloc(netlist_setup_t, *this);
m_setup = palloc(netlist_setup_t, this);
this->init_object(*this, "netlist");
m_setup->init();
}
@ -349,16 +349,29 @@ static void listdevices()
main - primary entry point
-------------------------------------------------*/
#if (!PSTANDALONE)
#include "corealloc.h"
#endif
static const char *pmf_verbose[] =
{
"NL_PMF_TYPE_VIRTUAL",
"NL_PMF_TYPE_GNUC_PMF",
"NL_PMF_TYPE_GNUC_PMF_CONV",
"NL_PMF_TYPE_INTERNAL"
};
int main(int argc, char *argv[])
{
#if (!PSTANDALONE)
track_memory(true);
{
#endif
tool_options_t opts;
int ret;
fprintf(stderr, "%s", "WARNING: This is Work In Progress! - It may fail anytime\n");
fprintf(stderr, "Update dispatching using method %s\n", pmf_verbose[NL_PMF_TYPE]);
if ((ret = opts.parse(argc, argv)) != argc)
{
fprintf(stderr, "Error parsing %s\n", argv[ret]);
@ -396,7 +409,9 @@ int main(int argc, char *argv[])
usage(opts);
return 1;
}
#if (!PSTANDALONE)
}
dump_unfreed_mem();
#endif
return 0;
}