diff options
Diffstat (limited to 'src/lib')
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 ¶m) { 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 ¶m) { 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 ¶m) { 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 ¶m) { @@ -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 ¶m) 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> |