netlist: bug fix, code maintenance and performance improvement. (nw)

- fixed a code in the netlist creation which caused multiple proxies
  to be created for output->terminal connections. A nice side effect of
  this fix is a performance increase ~9% for kidniki and ~4% for pong.
  Speaking about pong ... maximum is 490%. Dice is running at
  280 FPS/60 FPS = 466%, however without any analog emulation.
- Replaced NL_NOEXCEPT with noexcept. assert is now exception-free.
- cppcheck and lint fixes.
This commit is contained in:
couriersud 2019-11-13 19:29:51 +01:00
parent e00549bcec
commit 43637964a2
15 changed files with 121 additions and 88 deletions

View File

@ -218,7 +218,7 @@ namespace analog
connect(m_DG.m_P, m_SD.m_N);
set_qtype((m_model.type() == "NMOS_DEFAULT") ? FET_NMOS : FET_PMOS);
m_polarity = qtype() == nlconst::magic((FET_NMOS ? 1.0 : -1.0));
m_polarity = nlconst::magic((qtype() == FET_NMOS) ? 1.0 : -1.0);
m_capmod = m_model.m_CAPMOD;
// printf("capmod %d %g %g\n", m_capmod, (nl_fptype)m_model.m_VTO, m_polarity);

View File

@ -34,7 +34,7 @@ namespace netlist
NETLIB_UPDATEI();
public:
void update_outputs(const unsigned cnt) NL_NOEXCEPT
void update_outputs(const unsigned cnt) noexcept
{
static constexpr const std::array<netlist_time, 14> out_delayQn = {
NLTIME_FROM_NS(180), NLTIME_FROM_NS(280),

View File

@ -36,7 +36,7 @@ namespace netlist
NETLIB_UPDATEI();
public:
void update_outputs(unsigned v) NL_NOEXCEPT
void update_outputs(unsigned v) noexcept
{
nl_assert(v<16);
if (v != m_state)

View File

@ -18,12 +18,60 @@ namespace netlist
// -----------------------------------------------------------------------------
nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name,
logic_t *inout_proxied, detail::core_terminal_t *proxy_inout)
: device_t(anetlist, name)
logic_t *inout_proxied, detail::core_terminal_t *proxy_inout)
: device_t(anetlist, name)
, m_tp(nullptr)
, m_tn(nullptr)
, 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;
const std::vector<std::pair<pstring, pstring>> power_syms = { {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}};
bool f = false;
for (auto & pwr_sym : power_syms)
{
pstring devname = inout_proxied->device().name();
auto tp_t = anetlist.setup().find_terminal(devname + "." + pwr_sym.first,
/*detail::terminal_type::INPUT,*/ false);
auto tn_t = anetlist.setup().find_terminal(devname + "." + pwr_sym.second,
/*detail::terminal_type::INPUT,*/ false);
if (f && (tp_t != nullptr && tn_t != nullptr))
log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(inout_proxied->device().name(),
m_tp->name(), m_tn->name(),
tp_t ? tp_t->name() : "",
tn_t ? tn_t->name() : ""));
else if (tp_t != nullptr && tn_t != nullptr)
{
m_tp = tp_t;
m_tn = tn_t;
f = true;
}
}
//FIXME: Use power terminals and change info to warning or error
if (!f)
{
#if 1
if (logic_family()->fixed_V() == nlconst::zero())
log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_2(name, anetlist.setup().de_alias(inout_proxied->device().name())));
else
log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_2(name, anetlist.setup().de_alias(inout_proxied->device().name())));
#endif
m_GNDHack = plib::make_unique<analog_output_t>(*this, "_QGND");
m_VCCHack = plib::make_unique<analog_output_t>(*this, "_QVCC");
m_tp = m_VCCHack.get();
m_tn = m_GNDHack.get();
m_need_hack = true;
}
else
{
log().verbose("D/A Proxy: Found power terminals on device {1}", inout_proxied->device().name());
m_need_hack = false;
}
//printf("vcc: %f\n", logic_family()->fixed_V());
}
// ----------------------------------------------------------------------------------------
@ -52,6 +100,7 @@ namespace netlist
nl_assert(m_logic_family != nullptr);
// FIXME: Variable supply voltage!
nl_fptype supply_V = logic_family()->fixed_V();
// FIXME: bad hack
if (supply_V == nlconst::zero()) supply_V = nlconst::magic(5.0);
if (m_I.Q_Analog() > logic_family()->high_thresh_V(nlconst::zero(), supply_V))
@ -82,45 +131,20 @@ namespace netlist
, m_last_state(*this, "m_last_var", -1)
, m_is_timestep(false)
{
const std::vector<std::pair<pstring, pstring>> power_syms = { {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}};
register_subalias("Q", m_RN.m_P);
bool f = false;
detail::core_terminal_t *tp(nullptr);
detail::core_terminal_t *tn(nullptr);
for (auto & pwr_sym : power_syms)
{
pstring devname = out_proxied->device().name();
auto tp_t = anetlist.setup().find_terminal(devname + "." + pwr_sym.first,
/*detail::terminal_type::INPUT,*/ false);
auto tn_t = anetlist.setup().find_terminal(devname + "." + pwr_sym.second,
/*detail::terminal_type::INPUT,*/ false);
if (f && (tp_t != nullptr && tn_t != nullptr))
log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(out_proxied->device().name(),
tp->name(), tn->name(),
tp_t ? tp_t->name() : "",
tn_t ? tn_t->name() : ""));
else if (tp_t != nullptr && tn_t != nullptr)
{
/* alternative logic */
tp = tp_t;
tn = tn_t;
f = true;
}
}
//FIXME: Use power terminals and change info to warning or error
if (!f)
if (need_hack())
{
#if 1
// FIXME: move to base proxy class
if (logic_family()->fixed_V() == nlconst::zero())
log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(anetlist.setup().de_alias(out_proxied->device().name())));
log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_2(name, anetlist.setup().de_alias(out_proxied->device().name())));
else
log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(anetlist.setup().de_alias(out_proxied->device().name())));
m_GNDHack = plib::make_unique<analog_output_t>(*this, "_QGND");
m_VCCHack = plib::make_unique<analog_output_t>(*this, "_QVCC");
connect(m_RN.m_N, *m_GNDHack);
connect(m_RP.m_P, *m_VCCHack);
log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_2(name, anetlist.setup().de_alias(out_proxied->device().name())));
#endif
connect(m_RN.m_N, *m_tn);
connect(m_RP.m_P, *m_tp);
connect(m_RN.m_P, m_RP.m_N);
}
else
@ -135,8 +159,8 @@ namespace netlist
}
else
{
connect(m_RN.m_N, *tn);
connect(m_RP.m_P, *tp);
connect(m_RN.m_N, *m_tn);
connect(m_RP.m_P, *m_tp);
}
connect(m_RN.m_P, m_RP.m_N);
}
@ -156,10 +180,13 @@ namespace netlist
m_last_state = -1;
m_RN.reset();
m_RP.reset();
if (m_GNDHack)
m_GNDHack->initial(0);
if (m_VCCHack)
m_VCCHack->initial(supply_V);
if (need_hack())
{
if (m_tn)
m_GNDHack->initial(0);
if (m_tp)
m_VCCHack->initial(supply_V);
}
m_is_timestep = m_RN.m_P.net().solver()->has_timestep_devices();
m_RN.set_G_V_I(plib::reciprocal(logic_family()->R_low()),
logic_family()->low_offset_V(), nlconst::zero());

View File

@ -16,8 +16,8 @@
namespace netlist
{
namespace devices
{
namespace devices
{
// -----------------------------------------------------------------------------
// nld_base_proxy
@ -33,10 +33,17 @@ namespace netlist
detail::core_terminal_t &proxy_term() const { return *m_proxy_term; }
protected:
detail::core_terminal_t *m_tp;
detail::core_terminal_t *m_tn;
plib::unique_ptr<analog_output_t> m_GNDHack; // FIXME: Long term, we need to connect proxy gnd to device gnd
plib::unique_ptr<analog_output_t> m_VCCHack; // FIXME: Long term, we need to connect proxy gnd to device gnd
bool need_hack() const noexcept { return m_need_hack; }
private:
logic_t *m_term_proxied;
detail::core_terminal_t *m_proxy_term;
bool m_need_hack;
};
// -----------------------------------------------------------------------------
@ -106,15 +113,13 @@ namespace netlist
static constexpr const nl_fptype G_OFF = nlconst::magic(1e-9);
plib::unique_ptr<analog_output_t> m_GNDHack; // FIXME: Long term, we need to connect proxy gnd to device gnd
plib::unique_ptr<analog_output_t> m_VCCHack; // FIXME: Long term, we need to connect proxy gnd to device gnd
analog::NETLIB_NAME(twoterm) m_RP;
analog::NETLIB_NAME(twoterm) m_RN;
state_var<int> m_last_state;
bool m_is_timestep;
};
};
} //namespace devices
} // namespace devices
} // namespace netlist
#endif /* NLD_PROXY_H_ */

View File

@ -438,8 +438,8 @@ namespace devices
}
// FIXME: this will seg-fault if force_analog_input = false
nl_fptype VCC() const NL_NOEXCEPT { return m_VCC->Q_Analog(); }
nl_fptype GND() const NL_NOEXCEPT { return m_GND->Q_Analog(); }
nl_fptype VCC() const noexcept { return m_VCC->Q_Analog(); }
nl_fptype GND() const noexcept { return m_GND->Q_Analog(); }
private:
void noop() { }

View File

@ -14,6 +14,7 @@
#include "plib/palloc.h" // owned_ptr
#include "plib/pdynlib.h"
#include "plib/pexception.h"
#include "plib/pfmtlog.h"
#include "plib/pfunction.h"
#include "plib/plists.h"
@ -23,7 +24,6 @@
#include "plib/pstonum.h"
#include "plib/pstream.h"
#include "plib/ptime.h"
#include "plib/pexception.h"
#include "nl_errstr.h"
#include "nltypes.h"
@ -153,15 +153,15 @@ class NETLIB_NAME(name) : public device_t
#define NETLIB_DELEGATE(chip, name) nldelegate(&NETLIB_NAME(chip) :: name, this)
#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() noexcept override
#define NETLIB_HANDLERI(name) virtual void name() NL_NOEXCEPT
#define NETLIB_UPDATEI() virtual void update() NL_NOEXCEPT override
#define NETLIB_HANDLERI(name) virtual void name() noexcept
#define NETLIB_UPDATEI() virtual void update() noexcept override
#define NETLIB_UPDATE_PARAMI() virtual void update_param() noexcept override
#define NETLIB_RESETI() virtual void reset() override
#define NETLIB_SUB(chip) nld_ ## chip
#define NETLIB_SUB_UPTR(ns, chip) unique_pool_ptr< ns :: nld_ ## chip >
#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip) :: name() NL_NOEXCEPT
#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip) :: name() noexcept
#define NETLIB_UPDATE(chip) NETLIB_HANDLER(chip, update)
#define NETLIB_RESET(chip) void NETLIB_NAME(chip) :: reset(void)
@ -170,19 +170,6 @@ class NETLIB_NAME(name) : public device_t
#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals() noexcept
//============================================================
// Asserts
//============================================================
#if defined(MAME_DEBUG) || (NL_DEBUG == true)
#define nl_assert(x) passert_always(x);
#define NL_NOEXCEPT
#else
#define nl_assert(x) do { } while (0)
#define NL_NOEXCEPT noexcept
#endif
#define nl_assert_always(x, msg) passert_always_msg(x, msg)
//============================================================
// Namespace starts
//============================================================
@ -271,7 +258,8 @@ namespace netlist
virtual unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name,
logic_input_t *proxied) const = 0;
nl_fptype fixed_V() const noexcept{ return m_fixed_V; }
// FIXME: remove fixed_V()
nl_fptype fixed_V() const noexcept{return m_fixed_V; }
nl_fptype low_thresh_V(nl_fptype VN, nl_fptype VP) const noexcept{ return VN + (VP - VN) * m_low_thresh_PCNT; }
nl_fptype high_thresh_V(nl_fptype VN, nl_fptype VP) const noexcept{ return VN + (VP - VN) * m_high_thresh_PCNT; }
nl_fptype low_offset_V() const noexcept{ return m_low_VO; }
@ -678,7 +666,7 @@ namespace netlist
bool is_queued() const noexcept { return m_in_queue == queue_status::QUEUED; }
template <bool KEEP_STATS>
void update_devs() NL_NOEXCEPT;
void update_devs() noexcept;
netlist_time next_scheduled_time() const noexcept { return m_next_scheduled_time; }
void set_next_scheduled_time(netlist_time ntime) noexcept { m_next_scheduled_time = ntime; }
@ -874,7 +862,7 @@ namespace netlist
logic_input_t(core_device_t &dev, const pstring &aname,
nldelegate delegate = nldelegate());
netlist_sig_t operator()() const NL_NOEXCEPT
netlist_sig_t operator()() const noexcept
{
return Q();
}
@ -884,7 +872,7 @@ namespace netlist
void activate_hl() noexcept;
void activate_lh() noexcept;
private:
netlist_sig_t Q() const NL_NOEXCEPT;
netlist_sig_t Q() const noexcept;
};
// -----------------------------------------------------------------------------
@ -1048,7 +1036,7 @@ namespace netlist
unique_pool_ptr<stats_t> m_stats;
virtual void update() NL_NOEXCEPT { }
virtual void update() noexcept { }
virtual void reset() { }
protected:
@ -1946,7 +1934,7 @@ namespace netlist
return static_cast<const logic_net_t &>(core_terminal_t::net());
}
inline netlist_sig_t logic_input_t::Q() const NL_NOEXCEPT
inline netlist_sig_t logic_input_t::Q() const noexcept
{
nl_assert(terminal_state() != STATE_INP_PASSIVE);
//if (net().Q() != m_Q)
@ -2056,7 +2044,7 @@ namespace netlist
}
template <bool KEEP_STATS>
inline void detail::net_t::update_devs() NL_NOEXCEPT
inline void detail::net_t::update_devs() noexcept
{
nl_assert(this->isRailNet());

View File

@ -8,6 +8,7 @@
#define NLCONFIG_H_
#include "plib/pconfig.h"
#include "plib/pexception.h"
/// \addtogroup compiledefine
/// \{
@ -225,4 +226,15 @@ namespace netlist
#endif
} // namespace netlist
//============================================================
// Asserts
//============================================================
#if defined(MAME_DEBUG) || (NL_DEBUG == true)
#define nl_assert(x) passert_always(x);
#else
#define nl_assert(x) do { } while (0)
#endif
#define nl_assert_always(x, msg) passert_always_msg(x, msg)
#endif // NLCONFIG_H_

View File

@ -19,7 +19,7 @@
#define PERRMSGV(name, narg, str) \
struct name \
{ \
template<typename... Args> name(Args&&... args) \
template<typename... Args> explicit name(Args&&... args) \
: m_m(plib::pfmt(str)(std::forward<Args>(args)...)) \
{ static_assert(narg == sizeof...(args), "Argument count mismatch"); } \
operator pstring() const noexcept { return m_m; } \
@ -116,7 +116,7 @@ namespace netlist
// nlid_proxy.cpp
PERRMSGV(MI_NO_POWER_TERMINALS_ON_DEVICE_1, 1, "D/A Proxy: Found no valid combination of power terminals on device {1}")
PERRMSGV(MI_NO_POWER_TERMINALS_ON_DEVICE_2, 2, "D/A Proxy {1}: Found no valid combination of power terminals on device {2}")
PERRMSGV(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE, 5, "D/A Proxy: Found multiple power terminals on device {1}: {2} {3} {4} {5}")
// nld_matrix_solver.cpp

View File

@ -590,9 +590,10 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(detail::core_terminal_t &out)
out.net().core_terms().clear(); // clear the list
out.net().add_terminal(new_proxy->in());
out_cast.set_proxy(proxy);
//out_cast.set_proxy(proxy); - Wrong!
proxy = new_proxy.get();
out_cast.set_proxy(proxy);
m_nlstate.register_device(new_proxy->name(), std::move(new_proxy));
}

View File

@ -205,7 +205,7 @@ namespace plib {
//~arena_allocator() noexcept = default;
arena_allocator(arena_type & a) noexcept : m_a(a)
explicit arena_allocator(const arena_type & a) noexcept : m_a(a)
{
}

View File

@ -8,8 +8,8 @@
/// \file pmempool.h
///
#include "pconfig.h"
#include "palloc.h"
#include "pconfig.h"
#include "pstream.h"
#include "pstring.h"
#include "ptypes.h"
@ -63,13 +63,13 @@ namespace plib {
//::operator delete(b->m_data);
}
}
#if 0
static inline mempool &instance()
{
static mempool s_mempool;
return s_mempool;
}
#endif
void *allocate(size_t align, size_t size)
{
block *b = nullptr;

View File

@ -12,7 +12,7 @@ namespace plib {
// A simple tokenizer
// ----------------------------------------------------------------------------------------
pstring ptokenizer::currentline_str()
pstring ptokenizer::currentline_str() const
{
return m_cur_line;
}

View File

@ -94,7 +94,7 @@ namespace plib {
pstring m_token;
};
pstring currentline_str();
pstring currentline_str() const;
// tokenizer stuff follows ...

View File

@ -361,7 +361,7 @@ namespace solver
m_last_step = netlist_time::zero();
}
void matrix_solver_t::update() NL_NOEXCEPT
void matrix_solver_t::update() noexcept
{
const netlist_time new_timestep = solve(exec().time());
update_inputs();