diff --git a/3rdparty/bgfx/src/renderer_gl.cpp b/3rdparty/bgfx/src/renderer_gl.cpp index 3fe8afcba0f..c990e635350 100644 --- a/3rdparty/bgfx/src/renderer_gl.cpp +++ b/3rdparty/bgfx/src/renderer_gl.cpp @@ -5579,7 +5579,10 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); version = 0 == bx::strCmp(code, "#version 430", 12) ? 430 : version; - bx::write(&writer, &err, "#version %d\n", version); + if (version < 130) + bx::write(&writer, &err, "#version %d\n", 130); + else + bx::write(&writer, &err, "#version %d\n", version); if (430 > version && usesTextureLod) { diff --git a/3rdparty/bgfx/src/renderer_vk.cpp b/3rdparty/bgfx/src/renderer_vk.cpp index 579b6c146b8..a4ec5f31435 100644 --- a/3rdparty/bgfx/src/renderer_vk.cpp +++ b/3rdparty/bgfx/src/renderer_vk.cpp @@ -3935,8 +3935,8 @@ VK_IMPORT_DEVICE { attachments[mrt].colorAttachment = mrt; attachments[mrt].aspectMask = 0; - attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_DEPTH ) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0; - attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_STENCIL) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0; + //attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_DEPTH ) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0; + //attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_STENCIL) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0; attachments[mrt].clearValue.depthStencil.stencil = _clear.m_stencil; attachments[mrt].clearValue.depthStencil.depth = _clear.m_depth; diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index 930e8712e4f..6d4c8c909f9 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -43,7 +43,6 @@ project "netlist" MAME_DIR .. "src/lib/netlist/nl_dice_compat.h", MAME_DIR .. "src/lib/netlist/nl_factory.cpp", MAME_DIR .. "src/lib/netlist/nl_factory.h", - MAME_DIR .. "src/lib/netlist/nl_lists.h", MAME_DIR .. "src/lib/netlist/nl_parser.cpp", MAME_DIR .. "src/lib/netlist/nl_parser.h", MAME_DIR .. "src/lib/netlist/nl_setup.cpp", diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index 6f75a1d9612..189a486aff6 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -23,10 +23,9 @@ TIDY_FLAGSX += -cppcoreguidelines-avoid-magic-numbers, TIDY_FLAGSX += -cppcoreguidelines-macro-usage, TIDY_FLAGSX += -cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes, TIDY_FLAGSX += -bugprone-macro-parentheses,-misc-macro-parentheses, -TIDY_FLAGSX += -modernize-use-trailing-return-type -TIDY_FLAGSX += -bugprone-too-small-loop-variable +TIDY_FLAGSX += -bugprone-too-small-loop-variable, +TIDY_FLAGSX += -modernize-use-trailing-return-type, TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay -TIDY_FLAGSX += -modernize-use-trailing-return-type space := space += @@ -60,7 +59,7 @@ LD = @g++ MD = @mkdir RM = @rm DOXYGEN = @doxygen -CLANG_TIDY = clang-tidy-10 +CLANG_TIDY = clang-tidy-9 TARGETS = nltool nlwav diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index 034422792cd..39cdd685608 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -26,1026 +26,904 @@ namespace netlist { -// ---------------------------------------------------------------------------------------- -// logic_family_ttl_t -// ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // logic_family_ttl_t + // ---------------------------------------------------------------------------------------- -// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init, modernize-use-equals-default) -logic_family_desc_t::logic_family_desc_t() -{ -} - -class logic_family_ttl_t : public logic_family_desc_t -{ -public: - logic_family_ttl_t() : logic_family_desc_t() + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init, modernize-use-equals-default) + logic_family_desc_t::logic_family_desc_t() { - m_fixed_V = 5.0; - m_low_thresh_PCNT = 0.8 / 5.0; - m_high_thresh_PCNT = 2.0 / 5.0; - // m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications. - m_low_VO = 0.1; - m_high_VO = 1.0; // 4.0 - m_R_low = 1.0; - m_R_high = 130.0; } - unique_pool_ptr create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override; - unique_pool_ptr create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override; -}; -unique_pool_ptr logic_family_ttl_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const -{ - return pool().make_unique(anetlist, name, proxied); -} -unique_pool_ptr logic_family_ttl_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const -{ - return pool().make_unique(anetlist, name, proxied); -} - -class logic_family_cd4xxx_t : public logic_family_desc_t -{ -public: - logic_family_cd4xxx_t() : logic_family_desc_t() + class logic_family_ttl_t : public logic_family_desc_t { - m_fixed_V = 0.0; - m_low_thresh_PCNT = 1.5 / 5.0; - m_high_thresh_PCNT = 3.5 / 5.0; - // m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications. - m_low_VO = 0.05; - m_high_VO = 0.05; // 4.95 - m_R_low = 10.0; - m_R_high = 10.0; - } - unique_pool_ptr create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override; - unique_pool_ptr create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override; -}; - -unique_pool_ptr logic_family_cd4xxx_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const -{ - return pool().make_unique(anetlist, name, proxied); -} - -unique_pool_ptr logic_family_cd4xxx_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const -{ - return pool().make_unique(anetlist, name, proxied); -} - -const logic_family_desc_t *family_TTL() -{ - static logic_family_ttl_t obj; - return &obj; -} -const logic_family_desc_t *family_CD4XXX() -{ - static logic_family_cd4xxx_t obj; - return &obj; -} - - -// ---------------------------------------------------------------------------------------- -// queue_t -// ---------------------------------------------------------------------------------------- - -detail::queue_t::queue_t(netlist_state_t &nl) - : timed_queue, false>(512) - , netlist_ref(nl) - , m_qsize(0) - , m_times(512) - , m_net_ids(512) -{ -} - -void detail::queue_t::register_state(plib::state_manager_t &manager, const pstring &module) -{ - //state().log().debug("register_state\n"); - manager.save_item(this, m_qsize, module + "." + "qsize"); - manager.save_item(this, &m_times[0], module + "." + "times", m_times.size()); - manager.save_item(this, &m_net_ids[0], module + "." + "names", m_net_ids.size()); -} - -void detail::queue_t::on_pre_save(plib::state_manager_t &manager) -{ - plib::unused_var(manager); - m_qsize = this->size(); - for (std::size_t i = 0; i < m_qsize; i++ ) - { - m_times[i] = this->listptr()[i].m_exec_time.as_raw(); - m_net_ids[i] = state().find_net_id(this->listptr()[i].m_object); - } -} - - -void detail::queue_t::on_post_load(plib::state_manager_t &manager) -{ - plib::unused_var(manager); - this->clear(); - for (std::size_t i = 0; i < m_qsize; i++ ) - { - detail::net_t *n = state().nets()[m_net_ids[i]].get(); - this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n)); - } -} - -// ---------------------------------------------------------------------------------------- -// netlist_ref_t -// ---------------------------------------------------------------------------------------- - -detail::netlist_ref::netlist_ref(netlist_state_t &nl) -: m_netlist(nl.exec()) { } - -// ---------------------------------------------------------------------------------------- -// device_object_t -// ---------------------------------------------------------------------------------------- - -detail::device_object_t::device_object_t(core_device_t &dev, const pstring &aname) -: object_t(aname) -, m_device(dev) -{ -} - -detail::terminal_type detail::core_terminal_t::type() const -{ - if (dynamic_cast(this) != nullptr) - return terminal_type::TERMINAL; - else if (dynamic_cast(this) != nullptr - || dynamic_cast(this) != nullptr) - return terminal_type::INPUT; - else if (dynamic_cast(this) != nullptr - || dynamic_cast(this) != nullptr) - return terminal_type::OUTPUT; - else - { - state().log().fatal(MF_UNKNOWN_TYPE_FOR_OBJECT(name())); - return terminal_type::TERMINAL; // please compiler - } -} - -// ---------------------------------------------------------------------------------------- -// netlist_t -// ---------------------------------------------------------------------------------------- - -netlist_t::netlist_t(const pstring &aname, plib::unique_ptr callbacks) - : m_state(plib::make_unique(aname, *this, std::move(callbacks))) - , m_solver(nullptr) - , m_time(netlist_time::zero()) - , m_mainclock(nullptr) - , m_queue(*m_state) - , m_use_stats(false) -{ - devices::initialize_factory(nlstate().setup().factory()); - NETLIST_NAME(base)(nlstate().setup()); - run_state_manager().save_item(this, static_cast(m_queue), "m_queue"); - run_state_manager().save_item(this, m_time, "m_time"); -} - -// ---------------------------------------------------------------------------------------- -// netlist_t -// ---------------------------------------------------------------------------------------- - -netlist_state_t::netlist_state_t(const pstring &aname, - netlist_t & anetlist, - plib::unique_ptr &&callbacks) -: m_name(aname) -, m_netlist(anetlist) -, m_state() -, m_callbacks(std::move(callbacks)) // Order is important here -, m_log(*m_callbacks) -, m_setup(plib::make_unique(*this)) -{ - pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"})); - m_lib = plib::make_unique(libpath); -} - - -void netlist_t::stop() -{ - log().debug("Printing statistics ...\n"); - print_stats(); - log().debug("Stopping solver device ...\n"); - if (m_solver != nullptr) - m_solver->stop(); -} - -detail::net_t *netlist_state_t::find_net(const pstring &name) const -{ - for (auto & net : m_nets) - if (net->name() == name) - return net.get(); - - return nullptr; -} - -std::size_t netlist_state_t::find_net_id(const detail::net_t *net) const -{ - for (std::size_t i = 0; i < m_nets.size(); i++) - if (m_nets[i].get() == net) - return i; - return std::numeric_limits::max(); -} - - - -void netlist_state_t::rebuild_lists() -{ - for (auto & net : m_nets) - net->rebuild_list(); -} - - -void netlist_state_t::compile_defines(std::vector> &defs) -{ -//#define ENTRY(x) { #x, PSTRINGIFY(x) } -#define ENTRY(x) std::pair(#x, PSTRINGIFY(x)) - defs.emplace_back(ENTRY(PHAS_RDTSCP)); - defs.emplace_back(ENTRY(PUSE_ACCURATE_STATS)); - defs.emplace_back(ENTRY(PHAS_INT128)); - defs.emplace_back(ENTRY(USE_ALIGNED_OPTIMIZATIONS)); - defs.emplace_back(ENTRY(NVCCBUILD)); - defs.emplace_back(ENTRY(USE_MEMPOOL)); - defs.emplace_back(ENTRY(USE_QUEUE_STATS)); - defs.emplace_back(ENTRY(USE_COPY_INSTEAD_OF_REFERENCE)); - defs.emplace_back(ENTRY(USE_TRUTHTABLE_7448)); - defs.emplace_back(ENTRY(NL_DEBUG)); - defs.emplace_back(ENTRY(HAS_OPENMP)); - defs.emplace_back(ENTRY(USE_OPENMP)); - - defs.emplace_back(ENTRY(PPMF_TYPE)); - defs.emplace_back(ENTRY(PHAS_PMF_INTERNAL)); - -#undef ENTRY -} - -void netlist_t::reset() -{ - log().debug("Searching for mainclock\n"); - m_mainclock = m_state->get_single_device("mainclock"); - - log().debug("Searching for solver\n"); - m_solver = m_state->get_single_device("solver"); - - m_time = netlist_time::zero(); - m_queue.clear(); - if (m_mainclock != nullptr) - m_mainclock->m_Q.net().set_next_scheduled_time(netlist_time::zero()); - //if (m_solver != nullptr) - // m_solver->reset(); - - m_state->reset(); -} - -void netlist_state_t::reset() -{ - //FIXME: never used ??? - std::unordered_map m; - - // Reset all nets once ! - log().verbose("Call reset on all nets:"); - for (auto & n : nets()) - n->reset(); - - // Reset all devices once ! - log().verbose("Call reset on all devices:"); - for (auto & dev : m_devices) - dev.second->reset(); - - // Make sure everything depending on parameters is set - // Currently analog input and logic input also - // push their outputs to queue. - - log().verbose("Call update_param on all devices:"); - for (auto & dev : m_devices) - dev.second->update_param(); - - // Step all devices once ! - /* - * INFO: The order here affects power up of e.g. breakout. However, such - * variations are explicitly stated in the breakout manual. - */ - - auto *netlist_params = get_single_device("parameter"); - - switch (netlist_params->m_startup_strategy()) - { - case 0: + public: + logic_family_ttl_t() : logic_family_desc_t() { - std::vector d; - std::vector t; - log().verbose("Using default startup strategy"); - for (auto &n : m_nets) - for (auto & term : n->core_terms()) - if (term->m_delegate.has_object()) - { - if (!plib::container::contains(t, &term->m_delegate)) - { - t.push_back(&term->m_delegate); - term->m_delegate(); - } - auto *dev = reinterpret_cast(term->m_delegate.object()); - if (!plib::container::contains(d, dev)) - d.push_back(dev); - } - log().verbose("Devices not yet updated:"); - for (auto &dev : m_devices) - if (!plib::container::contains(d, dev.second.get())) - { - log().verbose("\t ...{1}", dev.second->name()); - dev.second->update(); - } + m_fixed_V = 5.0; + m_low_thresh_PCNT = 0.8 / 5.0; + m_high_thresh_PCNT = 2.0 / 5.0; + // m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications. + m_low_VO = 0.1; + m_high_VO = 1.0; // 4.0 + m_R_low = 1.0; + m_R_high = 130.0; } - break; - case 1: // brute force backward - { - log().verbose("Using brute force backward startup strategy"); + unique_pool_ptr create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override; + unique_pool_ptr create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override; + }; - for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1 - n->update_inputs(); - - std::size_t i = m_devices.size(); - while (i>0) - m_devices[--i].second->update(); - - for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1 - n->update_inputs(); - - } - break; - case 2: // brute force forward - { - log().verbose("Using brute force forward startup strategy"); - for (auto &d : m_devices) - d.second->update(); - } - break; + unique_pool_ptr logic_family_ttl_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const + { + return pool().make_unique(anetlist, name, proxied); + } + unique_pool_ptr logic_family_ttl_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const + { + return pool().make_unique(anetlist, name, proxied); } -#if 1 - /* the above may screw up m_active and the list */ - rebuild_lists(); -#endif -} - -void netlist_t::process_queue(const netlist_time delta) NL_NOEXCEPT -{ - if (!m_use_stats) - process_queue_stats(delta); - else + class logic_family_cd4xxx_t : public logic_family_desc_t { - auto sm_guard(m_stat_mainloop.guard()); - process_queue_stats(delta); - } -} - -template -void netlist_t::process_queue_stats(const netlist_time delta) NL_NOEXCEPT -{ - netlist_time stop(m_time + delta); - - qpush(detail::queue_t::entry_t(stop, nullptr)); - - if (m_mainclock == nullptr) - { - detail::queue_t::entry_t e(m_queue.pop()); - m_time = e.m_exec_time; - while (e.m_object != nullptr) + public: + logic_family_cd4xxx_t() : logic_family_desc_t() { - e.m_object->template update_devs(); - if (KEEP_STATS) - m_perf_out_processed.inc(); - e = m_queue.pop(); - m_time = e.m_exec_time; + m_fixed_V = 0.0; + m_low_thresh_PCNT = 1.5 / 5.0; + m_high_thresh_PCNT = 3.5 / 5.0; + // m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications. + m_low_VO = 0.05; + m_high_VO = 0.05; // 4.95 + m_R_low = 10.0; + m_R_high = 10.0; + } + unique_pool_ptr create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override; + unique_pool_ptr create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override; + }; + + unique_pool_ptr logic_family_cd4xxx_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const + { + return pool().make_unique(anetlist, name, proxied); + } + + unique_pool_ptr logic_family_cd4xxx_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const + { + return pool().make_unique(anetlist, name, proxied); + } + + const logic_family_desc_t *family_TTL() + { + static logic_family_ttl_t obj; + return &obj; + } + const logic_family_desc_t *family_CD4XXX() + { + static logic_family_cd4xxx_t obj; + return &obj; + } + + + // ---------------------------------------------------------------------------------------- + // queue_t + // ---------------------------------------------------------------------------------------- + + detail::queue_t::queue_t(netlist_state_t &nl) + : timed_queue, false>(512) + , netlist_ref(nl) + , m_qsize(0) + , m_times(512) + , m_net_ids(512) + { + } + + void detail::queue_t::register_state(plib::state_manager_t &manager, const pstring &module) + { + //state().log().debug("register_state\n"); + manager.save_item(this, m_qsize, module + "." + "qsize"); + manager.save_item(this, &m_times[0], module + "." + "times", m_times.size()); + manager.save_item(this, &m_net_ids[0], module + "." + "names", m_net_ids.size()); + } + + void detail::queue_t::on_pre_save(plib::state_manager_t &manager) + { + plib::unused_var(manager); + m_qsize = this->size(); + for (std::size_t i = 0; i < m_qsize; i++ ) + { + m_times[i] = this->listptr()[i].m_exec_time.as_raw(); + m_net_ids[i] = state().find_net_id(this->listptr()[i].m_object); } } - else + + + void detail::queue_t::on_post_load(plib::state_manager_t &manager) { - logic_net_t &mc_net(m_mainclock->m_Q.net()); - const netlist_time inc(m_mainclock->m_inc); - netlist_time mc_time(mc_net.next_scheduled_time()); - - do + plib::unused_var(manager); + this->clear(); + for (std::size_t i = 0; i < m_qsize; i++ ) { - while (m_queue.top().m_exec_time > mc_time) - { - m_time = mc_time; - mc_net.toggle_new_Q(); - mc_net.update_devs(); - mc_time += inc; - } - - detail::queue_t::entry_t e(m_queue.pop()); - m_time = e.m_exec_time; - if (e.m_object != nullptr) - { - e.m_object->template update_devs(); - if (KEEP_STATS) - m_perf_out_processed.inc(); - } - else - break; - } while (true); //while (e.m_object != nullptr); - mc_net.set_next_scheduled_time(mc_time); - } -} - -void netlist_t::print_stats() const -{ - if (m_use_stats) - { - std::vector index; - for (size_t i=0; i < m_state->m_devices.size(); i++) - index.push_back(i); - - std::sort(index.begin(), index.end(), - [&](size_t i1, size_t i2) { return m_state->m_devices[i1].second->m_stats->m_stat_total_time.total() < m_state->m_devices[i2].second->m_stats->m_stat_total_time.total(); }); - - nperftime_t::type total_time(0); - nperftime_t::ctype total_count(0); - - for (auto & j : index) - { - auto entry = m_state->m_devices[j].second.get(); - auto stats = m_state->m_devices[j].second.get()->m_stats.get(); - log().verbose("Device {1:20} : {2:12} {3:12} {4:15} {5:12}", entry->name(), - stats->m_stat_call_count(), stats->m_stat_total_time.count(), - stats->m_stat_total_time.total(), stats->m_stat_inc_active()); - total_time += stats->m_stat_total_time.total(); - total_count += stats->m_stat_total_time.count(); - } - - log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count, - total_time, total_time / static_cast(total_count ? total_count : 1)); - - log().verbose("Total loop {1:15}", m_stat_mainloop()); - log().verbose("Total time {1:15}", total_time); - - // FIXME: clang complains about unreachable code without - const auto clang_workaround_unreachable_code = USE_QUEUE_STATS; - if (clang_workaround_unreachable_code) - { - /* Only one serialization should be counted in total time */ - /* But two are contained in m_stat_mainloop */ - nperftime_t overhead; - nperftime_t test; - { - auto overhead_guard(overhead.guard()); - for (int j=0; j<100000;j++) - { - auto test_guard(test.guard()); - } - } - - nperftime_t::type total_overhead = overhead() - * static_cast::type>(total_count) - / static_cast::type>(200000); - - log().verbose("Queue Pushes {1:15}", m_queue.m_prof_call()); - log().verbose("Queue Moves {1:15}", m_queue.m_prof_sortmove()); - log().verbose("Queue Removes {1:15}", m_queue.m_prof_remove()); - log().verbose("Queue Retimes {1:15}", m_queue.m_prof_retime()); - log().verbose(""); - - log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation."); - log().verbose("Total overhead {1:15}", total_overhead); - nperftime_t::type overhead_per_pop = (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead)) - / static_cast::type>(m_queue.m_prof_call()); - log().verbose("Overhead per pop {1:11}", overhead_per_pop ); - log().verbose(""); - } - - auto trigger = total_count * 200 / 1000000; // 200 ppm - for (auto &entry : m_state->m_devices) - { - auto ep = entry.second.get(); - auto stats = ep->m_stats.get(); - // Factor of 3 offers best performace increase - if (stats->m_stat_inc_active() > 3 * stats->m_stat_total_time.count() - && stats->m_stat_inc_active() > trigger) - log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(), - static_cast(stats->m_stat_inc_active()) / static_cast(stats->m_stat_total_time.count()), - stats->m_stat_inc_active(), stats->m_stat_total_time.count()); + detail::net_t *n = state().nets()[m_net_ids[i]].get(); + this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n)); } } -} -core_device_t *netlist_state_t::get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const -{ - core_device_t *ret = nullptr; - for (auto &d : m_devices) - { - if (cc(d.second.get())) - { - if (ret != nullptr) - m_log.fatal(MF_MORE_THAN_ONE_1_DEVICE_FOUND(classname)); - else - ret = d.second.get(); - } - } - return ret; -} + // ---------------------------------------------------------------------------------------- + // netlist_ref_t + // ---------------------------------------------------------------------------------------- + detail::netlist_ref::netlist_ref(netlist_state_t &nl) + : m_netlist(nl.exec()) { } -// ---------------------------------------------------------------------------------------- -// core_device_t -// ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // device_object_t + // ---------------------------------------------------------------------------------------- -core_device_t::core_device_t(netlist_state_t &owner, const pstring &name) - : object_t(name) - , logic_family_t() - , netlist_ref(owner) - , m_hint_deactivate(false) - , m_active_outputs(*this, "m_active_outputs", 1) -{ - if (logic_family() == nullptr) - set_logic_family(family_TTL()); - if (exec().stats_enabled()) - m_stats = pool().make_unique(); -} - -core_device_t::core_device_t(core_device_t &owner, const pstring &name) - : object_t(owner.name() + "." + name) - , logic_family_t() - , netlist_ref(owner.state()) - , m_hint_deactivate(false) - , m_active_outputs(*this, "m_active_outputs", 1) -{ - set_logic_family(owner.logic_family()); - if (logic_family() == nullptr) - set_logic_family(family_TTL()); - state().register_device(this->name(), owned_pool_ptr(this, false)); - if (exec().stats_enabled()) - m_stats = pool().make_unique(); -} - -void core_device_t::set_default_delegate(detail::core_terminal_t &term) -{ - if (!term.m_delegate.is_set()) - term.m_delegate.set(&core_device_t::update, this); -} - -log_type & core_device_t::log() -{ - return state().log(); -} - -// ---------------------------------------------------------------------------------------- -// device_t -// ---------------------------------------------------------------------------------------- - -device_t::device_t(netlist_state_t &owner, const pstring &name) -: core_device_t(owner, name) -{ -} - -device_t::device_t(core_device_t &owner, const pstring &name) -: core_device_t(owner, name) -{ -} - -setup_t &device_t::setup() -{ - return state().setup(); -} - -const setup_t &device_t::setup() const -{ - return state().setup(); -} - -void device_t::register_subalias(const pstring &name, detail::core_terminal_t &term) -{ - pstring alias = this->name() + "." + name; - - // everything already fully qualified - setup().register_alias_nofqn(alias, term.name()); -} - -void device_t::register_subalias(const pstring &name, const pstring &aliased) -{ - pstring alias = this->name() + "." + name; - pstring aliased_fqn = this->name() + "." + aliased; - - // everything already fully qualified - setup().register_alias_nofqn(alias, aliased_fqn); -} - -void device_t::connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2) -{ - setup().register_link_fqn(t1.name(), t2.name()); -} - -void device_t::connect(const pstring &t1, const pstring &t2) -{ - setup().register_link_fqn(name() + "." + t1, name() + "." + t2); -} - -/* FIXME: this is only used by solver code since matrix solvers are started in - * post_start. - */ -void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_terminal_t &t2) -{ - if (!setup().connect(t1, t2)) - log().fatal(MF_ERROR_CONNECTING_1_TO_2(t1.name(), t2.name())); -} - - -// ----------------------------------------------------------------------------- -// family_setter_t -// ----------------------------------------------------------------------------- - -// NOLINTNEXTLINE(modernize-use-equals-default) -detail::family_setter_t::family_setter_t() -{ -} - -detail::family_setter_t::family_setter_t(core_device_t &dev, const pstring &desc) -{ - dev.set_logic_family(dev.setup().family_from_model(desc)); -} - -detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_desc_t *desc) -{ - dev.set_logic_family(desc); -} - -// ---------------------------------------------------------------------------------------- -// net_t -// ---------------------------------------------------------------------------------------- - -detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *mr) + detail::device_object_t::device_object_t(core_device_t &dev, const pstring &aname) : object_t(aname) - , netlist_ref(nl) - , m_new_Q(*this, "m_new_Q", 0) - , m_cur_Q (*this, "m_cur_Q", 0) - , m_in_queue(*this, "m_in_queue", queue_status::DELIVERED) - , m_next_scheduled_time(*this, "m_time", netlist_time::zero()) - , m_railterminal(mr) -{ -} - -void detail::net_t::rebuild_list() -{ - /* rebuild m_list */ - - m_list_active.clear(); - for (auto & term : m_core_terms) - if (term->terminal_state() != logic_t::STATE_INP_PASSIVE) - { - m_list_active.push_back(term); - term->set_copied_input(m_cur_Q); - } -} - -template -void detail::net_t::process(const T mask, netlist_sig_t sig) -{ - m_cur_Q = sig; - - if (KEEP_STATS) + , m_device(dev) { - for (auto & p : m_list_active) + } + + detail::terminal_type detail::core_terminal_t::type() const + { + if (dynamic_cast(this) != nullptr) + return terminal_type::TERMINAL; + else if (dynamic_cast(this) != nullptr + || dynamic_cast(this) != nullptr) + return terminal_type::INPUT; + else if (dynamic_cast(this) != nullptr + || dynamic_cast(this) != nullptr) + return terminal_type::OUTPUT; + else { - p.set_copied_input(sig); - auto *stats = p.device().m_stats.get(); - stats->m_stat_call_count.inc(); - if ((p.terminal_state() & mask)) + state().log().fatal(MF_UNKNOWN_TYPE_FOR_OBJECT(name())); + return terminal_type::TERMINAL; // please compiler + } + } + + // ---------------------------------------------------------------------------------------- + // netlist_t + // ---------------------------------------------------------------------------------------- + + netlist_t::netlist_t(const pstring &aname, plib::unique_ptr callbacks) + : m_state(plib::make_unique(aname, *this, std::move(callbacks))) + , m_solver(nullptr) + , m_time(netlist_time::zero()) + , m_mainclock(nullptr) + , m_queue(*m_state) + , m_use_stats(false) + { + devices::initialize_factory(nlstate().setup().factory()); + NETLIST_NAME(base)(nlstate().setup()); + run_state_manager().save_item(this, static_cast(m_queue), "m_queue"); + run_state_manager().save_item(this, m_time, "m_time"); + } + + // ---------------------------------------------------------------------------------------- + // netlist_t + // ---------------------------------------------------------------------------------------- + + netlist_state_t::netlist_state_t(const pstring &aname, + netlist_t & anetlist, + plib::unique_ptr &&callbacks) + : m_name(aname) + , m_netlist(anetlist) + , m_state() + , m_callbacks(std::move(callbacks)) // Order is important here + , m_log(*m_callbacks) + , m_setup(plib::make_unique(*this)) + { + pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"})); + m_lib = plib::make_unique(libpath); + } + + + void netlist_t::stop() + { + log().debug("Printing statistics ...\n"); + print_stats(); + log().debug("Stopping solver device ...\n"); + if (m_solver != nullptr) + m_solver->stop(); + } + + detail::net_t *netlist_state_t::find_net(const pstring &name) const + { + for (auto & net : m_nets) + if (net->name() == name) + return net.get(); + + return nullptr; + } + + std::size_t netlist_state_t::find_net_id(const detail::net_t *net) const + { + for (std::size_t i = 0; i < m_nets.size(); i++) + if (m_nets[i].get() == net) + return i; + return std::numeric_limits::max(); + } + + + + void netlist_state_t::rebuild_lists() + { + for (auto & net : m_nets) + net->rebuild_list(); + } + + + void netlist_state_t::compile_defines(std::vector> &defs) + { + //#define ENTRY(x) { #x, PSTRINGIFY(x) } + #define ENTRY(x) std::pair(#x, PSTRINGIFY(x)) + defs.emplace_back(ENTRY(PHAS_RDTSCP)); + defs.emplace_back(ENTRY(PUSE_ACCURATE_STATS)); + defs.emplace_back(ENTRY(PHAS_INT128)); + defs.emplace_back(ENTRY(USE_ALIGNED_OPTIMIZATIONS)); + defs.emplace_back(ENTRY(NVCCBUILD)); + defs.emplace_back(ENTRY(USE_MEMPOOL)); + defs.emplace_back(ENTRY(USE_QUEUE_STATS)); + defs.emplace_back(ENTRY(USE_COPY_INSTEAD_OF_REFERENCE)); + defs.emplace_back(ENTRY(USE_TRUTHTABLE_7448)); + defs.emplace_back(ENTRY(NL_DEBUG)); + defs.emplace_back(ENTRY(HAS_OPENMP)); + defs.emplace_back(ENTRY(USE_OPENMP)); + + defs.emplace_back(ENTRY(PPMF_TYPE)); + defs.emplace_back(ENTRY(PHAS_PMF_INTERNAL)); + + #undef ENTRY + } + + void netlist_t::reset() + { + log().debug("Searching for mainclock\n"); + m_mainclock = m_state->get_single_device("mainclock"); + + log().debug("Searching for solver\n"); + m_solver = m_state->get_single_device("solver"); + + m_time = netlist_time::zero(); + m_queue.clear(); + if (m_mainclock != nullptr) + m_mainclock->m_Q.net().set_next_scheduled_time(netlist_time::zero()); + //if (m_solver != nullptr) + // m_solver->reset(); + + m_state->reset(); + } + + void netlist_state_t::reset() + { + //FIXME: never used ??? + std::unordered_map m; + + // Reset all nets once ! + log().verbose("Call reset on all nets:"); + for (auto & n : nets()) + n->reset(); + + // Reset all devices once ! + log().verbose("Call reset on all devices:"); + for (auto & dev : m_devices) + dev.second->reset(); + + // Make sure everything depending on parameters is set + // Currently analog input and logic input also + // push their outputs to queue. + + log().verbose("Call update_param on all devices:"); + for (auto & dev : m_devices) + dev.second->update_param(); + + // Step all devices once ! + /* + * INFO: The order here affects power up of e.g. breakout. However, such + * variations are explicitly stated in the breakout manual. + */ + + auto *netlist_params = get_single_device("parameter"); + + switch (netlist_params->m_startup_strategy()) + { + case 0: { - auto g(stats->m_stat_total_time.guard()); - p.m_delegate(); + std::vector d; + std::vector t; + log().verbose("Using default startup strategy"); + for (auto &n : m_nets) + for (auto & term : n->core_terms()) + if (term->m_delegate.has_object()) + { + if (!plib::container::contains(t, &term->m_delegate)) + { + t.push_back(&term->m_delegate); + term->m_delegate(); + } + auto *dev = reinterpret_cast(term->m_delegate.object()); + if (!plib::container::contains(d, dev)) + d.push_back(dev); + } + log().verbose("Devices not yet updated:"); + for (auto &dev : m_devices) + if (!plib::container::contains(d, dev.second.get())) + { + log().verbose("\t ...{1}", dev.second->name()); + dev.second->update(); + } + } + break; + case 1: // brute force backward + { + log().verbose("Using brute force backward startup strategy"); + + for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1 + n->update_inputs(); + + std::size_t i = m_devices.size(); + while (i>0) + m_devices[--i].second->update(); + + for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1 + n->update_inputs(); + + } + break; + case 2: // brute force forward + { + log().verbose("Using brute force forward startup strategy"); + for (auto &d : m_devices) + d.second->update(); + } + break; + } + + #if 1 + /* the above may screw up m_active and the list */ + rebuild_lists(); + #endif + } + + + void netlist_t::print_stats() const NL_NOEXCEPT + { + if (m_use_stats) + { + std::vector index; + for (size_t i=0; i < m_state->m_devices.size(); i++) + index.push_back(i); + + std::sort(index.begin(), index.end(), + [&](size_t i1, size_t i2) { return m_state->m_devices[i1].second->m_stats->m_stat_total_time.total() < m_state->m_devices[i2].second->m_stats->m_stat_total_time.total(); }); + + plib::pperftime_t::type total_time(0); + plib::pperftime_t::ctype total_count(0); + + for (auto & j : index) + { + auto entry = m_state->m_devices[j].second.get(); + auto stats = m_state->m_devices[j].second.get()->m_stats.get(); + log().verbose("Device {1:20} : {2:12} {3:12} {4:15} {5:12}", entry->name(), + stats->m_stat_call_count(), stats->m_stat_total_time.count(), + stats->m_stat_total_time.total(), stats->m_stat_inc_active()); + total_time += stats->m_stat_total_time.total(); + total_count += stats->m_stat_total_time.count(); + } + + log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count, + total_time, total_time / static_cast(total_count ? total_count : 1)); + + log().verbose("Total loop {1:15}", m_stat_mainloop()); + log().verbose("Total time {1:15}", total_time); + + // FIXME: clang complains about unreachable code without + const auto clang_workaround_unreachable_code = USE_QUEUE_STATS; + if (clang_workaround_unreachable_code) + { + /* Only one serialization should be counted in total time */ + /* But two are contained in m_stat_mainloop */ + plib::pperftime_t overhead; + plib::pperftime_t test; + { + auto overhead_guard(overhead.guard()); + for (int j=0; j<100000;j++) + { + auto test_guard(test.guard()); + } + } + + plib::pperftime_t::type total_overhead = overhead() + * static_cast::type>(total_count) + / static_cast::type>(200000); + + log().verbose("Queue Pushes {1:15}", m_queue.m_prof_call()); + log().verbose("Queue Moves {1:15}", m_queue.m_prof_sortmove()); + log().verbose("Queue Removes {1:15}", m_queue.m_prof_remove()); + log().verbose("Queue Retimes {1:15}", m_queue.m_prof_retime()); + log().verbose(""); + + log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation."); + log().verbose("Total overhead {1:15}", total_overhead); + plib::pperftime_t::type overhead_per_pop = (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead)) + / static_cast::type>(m_queue.m_prof_call()); + log().verbose("Overhead per pop {1:11}", overhead_per_pop ); + log().verbose(""); + } + + auto trigger = total_count * 200 / 1000000; // 200 ppm + for (auto &entry : m_state->m_devices) + { + auto ep = entry.second.get(); + auto stats = ep->m_stats.get(); + // Factor of 3 offers best performace increase + if (stats->m_stat_inc_active() > 3 * stats->m_stat_total_time.count() + && stats->m_stat_inc_active() > trigger) + log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(), + static_cast(stats->m_stat_inc_active()) / static_cast(stats->m_stat_total_time.count()), + stats->m_stat_inc_active(), stats->m_stat_total_time.count()); } } } - else + + core_device_t *netlist_state_t::get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const { - for (auto & p : m_list_active) + core_device_t *ret = nullptr; + for (auto &d : m_devices) { - p.set_copied_input(sig); - if ((p.terminal_state() & mask)) - p.m_delegate(); + if (cc(d.second.get())) + { + if (ret != nullptr) + m_log.fatal(MF_MORE_THAN_ONE_1_DEVICE_FOUND(classname)); + else + ret = d.second.get(); + } + } + return ret; + } + + + // ---------------------------------------------------------------------------------------- + // core_device_t + // ---------------------------------------------------------------------------------------- + + core_device_t::core_device_t(netlist_state_t &owner, const pstring &name) + : object_t(name) + , logic_family_t() + , netlist_ref(owner) + , m_hint_deactivate(false) + , m_active_outputs(*this, "m_active_outputs", 1) + { + if (logic_family() == nullptr) + set_logic_family(family_TTL()); + if (exec().stats_enabled()) + m_stats = pool().make_unique(); + } + + core_device_t::core_device_t(core_device_t &owner, const pstring &name) + : object_t(owner.name() + "." + name) + , logic_family_t() + , netlist_ref(owner.state()) + , m_hint_deactivate(false) + , m_active_outputs(*this, "m_active_outputs", 1) + { + set_logic_family(owner.logic_family()); + if (logic_family() == nullptr) + set_logic_family(family_TTL()); + state().register_device(this->name(), owned_pool_ptr(this, false)); + if (exec().stats_enabled()) + m_stats = pool().make_unique(); + } + + void core_device_t::set_default_delegate(detail::core_terminal_t &term) + { + if (!term.m_delegate.is_set()) + term.m_delegate.set(&core_device_t::update, this); + } + + log_type & core_device_t::log() + { + return state().log(); + } + + // ---------------------------------------------------------------------------------------- + // device_t + // ---------------------------------------------------------------------------------------- + + device_t::device_t(netlist_state_t &owner, const pstring &name) + : core_device_t(owner, name) + { + } + + device_t::device_t(core_device_t &owner, const pstring &name) + : core_device_t(owner, name) + { + } + + setup_t &device_t::setup() noexcept + { + return state().setup(); + } + + const setup_t &device_t::setup() const noexcept + { + return state().setup(); + } + + void device_t::register_subalias(const pstring &name, detail::core_terminal_t &term) + { + pstring alias = this->name() + "." + name; + + // everything already fully qualified + setup().register_alias_nofqn(alias, term.name()); + } + + void device_t::register_subalias(const pstring &name, const pstring &aliased) + { + pstring alias = this->name() + "." + name; + pstring aliased_fqn = this->name() + "." + aliased; + + // everything already fully qualified + setup().register_alias_nofqn(alias, aliased_fqn); + } + + void device_t::connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2) + { + setup().register_link_fqn(t1.name(), t2.name()); + } + + void device_t::connect(const pstring &t1, const pstring &t2) + { + setup().register_link_fqn(name() + "." + t1, name() + "." + t2); + } + + /* FIXME: this is only used by solver code since matrix solvers are started in + * post_start. + */ + void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_terminal_t &t2) + { + if (!setup().connect(t1, t2)) + log().fatal(MF_ERROR_CONNECTING_1_TO_2(t1.name(), t2.name())); + } + + + // ----------------------------------------------------------------------------- + // family_setter_t + // ----------------------------------------------------------------------------- + + // NOLINTNEXTLINE(modernize-use-equals-default) + detail::family_setter_t::family_setter_t() + { + } + + detail::family_setter_t::family_setter_t(core_device_t &dev, const pstring &desc) + { + dev.set_logic_family(dev.setup().family_from_model(desc)); + } + + detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_desc_t *desc) + { + dev.set_logic_family(desc); + } + + // ---------------------------------------------------------------------------------------- + // net_t + // ---------------------------------------------------------------------------------------- + + detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *mr) + : object_t(aname) + , netlist_ref(nl) + , m_new_Q(*this, "m_new_Q", 0) + , m_cur_Q (*this, "m_cur_Q", 0) + , m_in_queue(*this, "m_in_queue", queue_status::DELIVERED) + , m_next_scheduled_time(*this, "m_time", netlist_time::zero()) + , m_railterminal(mr) + { + } + + void detail::net_t::rebuild_list() + { + /* rebuild m_list */ + + m_list_active.clear(); + for (auto & term : m_core_terms) + if (term->terminal_state() != logic_t::STATE_INP_PASSIVE) + { + m_list_active.push_back(term); + term->set_copied_input(m_cur_Q); + } + } + + + void detail::net_t::reset() + { + m_next_scheduled_time = netlist_time::zero(); + m_in_queue = queue_status::DELIVERED; + + m_new_Q = 0; + m_cur_Q = 0; + + auto *p = dynamic_cast(this); + + if (p != nullptr) + p->m_cur_Analog = 0.0; + + /* rebuild m_list and reset terminals to active or analog out state */ + + m_list_active.clear(); + for (core_terminal_t *ct : m_core_terms) + { + ct->reset(); + if (ct->terminal_state() != logic_t::STATE_INP_PASSIVE) + m_list_active.push_back(ct); + ct->set_copied_input(m_cur_Q); } } -} -template -void detail::net_t::update_devs() NL_NOEXCEPT -{ -#if 0 - nl_assert(this->isRailNet()); - - const unsigned int new_Q(m_new_Q); - - const unsigned int mask((new_Q << core_terminal_t::INP_LH_SHIFT) - | (m_cur_Q << core_terminal_t::INP_HL_SHIFT)); - - m_in_queue = queue_status::DELIVERED; /* mark as taken ... */ - switch (mask) + void detail::net_t::add_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT { - case core_terminal_t::STATE_INP_HL: - case core_terminal_t::STATE_INP_LH: - process(mask, new_Q); - break; - default: - /* do nothing */ - break; + for (auto &t : m_core_terms) + if (t == &terminal) + state().log().fatal(MF_NET_1_DUPLICATE_TERMINAL_2(name(), t->name())); + + terminal.set_net(this); + + m_core_terms.push_back(&terminal); } -#else - nl_assert(this->isRailNet()); - m_in_queue = queue_status::DELIVERED; /* mark as taken ... */ - if (m_new_Q ^ m_cur_Q) - process((m_new_Q << core_terminal_t::INP_LH_SHIFT) - | (m_cur_Q << core_terminal_t::INP_HL_SHIFT), m_new_Q); -#endif -} - -void detail::net_t::reset() -{ - m_next_scheduled_time = netlist_time::zero(); - m_in_queue = queue_status::DELIVERED; - - m_new_Q = 0; - m_cur_Q = 0; - - auto *p = dynamic_cast(this); - - if (p != nullptr) - p->m_cur_Analog = 0.0; - - /* rebuild m_list and reset terminals to active or analog out state */ - - m_list_active.clear(); - for (core_terminal_t *ct : m_core_terms) + void detail::net_t::remove_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT { - ct->reset(); - if (ct->terminal_state() != logic_t::STATE_INP_PASSIVE) - m_list_active.push_back(ct); - ct->set_copied_input(m_cur_Q); + if (plib::container::contains(m_core_terms, &terminal)) + { + terminal.set_net(nullptr); + plib::container::remove(m_core_terms, &terminal); + } + else + state().log().fatal(MF_REMOVE_TERMINAL_1_FROM_NET_2(terminal.name(), this->name())); } -} -void detail::net_t::add_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT -{ - for (auto &t : m_core_terms) - if (t == &terminal) - state().log().fatal(MF_NET_1_DUPLICATE_TERMINAL_2(name(), t->name())); - - terminal.set_net(this); - - m_core_terms.push_back(&terminal); -} - -void detail::net_t::remove_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT -{ - if (plib::container::contains(m_core_terms, &terminal)) + void detail::net_t::move_connections(detail::net_t &dest_net) { - terminal.set_net(nullptr); - plib::container::remove(m_core_terms, &terminal); + for (auto &ct : m_core_terms) + dest_net.add_terminal(*ct); + m_core_terms.clear(); } - else - state().log().fatal(MF_REMOVE_TERMINAL_1_FROM_NET_2(terminal.name(), this->name())); -} -void detail::net_t::move_connections(detail::net_t &dest_net) -{ - for (auto &ct : m_core_terms) - dest_net.add_terminal(*ct); - m_core_terms.clear(); -} + // ---------------------------------------------------------------------------------------- + // logic_net_t + // ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// logic_net_t -// ---------------------------------------------------------------------------------------- + logic_net_t::logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr) + : net_t(nl, aname, mr) + { + } -logic_net_t::logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr) - : net_t(nl, aname, mr) -{ -} + // ---------------------------------------------------------------------------------------- + // analog_net_t + // ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// analog_net_t -// ---------------------------------------------------------------------------------------- + analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr) + : net_t(nl, aname, mr) + , m_cur_Analog(*this, "m_cur_Analog", 0.0) + , m_solver(nullptr) + { + } -analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr) - : net_t(nl, aname, mr) - , m_cur_Analog(*this, "m_cur_Analog", 0.0) - , m_solver(nullptr) -{ -} + // ---------------------------------------------------------------------------------------- + // core_terminal_t + // ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// core_terminal_t -// ---------------------------------------------------------------------------------------- + detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &aname, + const state_e state, nldelegate delegate) + : device_object_t(dev, dev.name() + "." + aname) + , plib::linkedlist_t::element_t() + , m_delegate(delegate) + #if USE_COPY_INSTEAD_OF_REFERENCE + , m_Q(*this, "m_Q", 0) + #endif + , m_net(nullptr) + , m_state(*this, "m_state", state) + { + } -detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &aname, - const state_e state, nldelegate delegate) -: device_object_t(dev, dev.name() + "." + aname) -, plib::linkedlist_t::element_t() -, m_delegate(delegate) -#if USE_COPY_INSTEAD_OF_REFERENCE -, m_Q(*this, "m_Q", 0) -#endif -, m_net(nullptr) -, m_state(*this, "m_state", state) -{ -} - -analog_t::analog_t(core_device_t &dev, const pstring &aname, const state_e state, - nldelegate delegate) -: core_terminal_t(dev, aname, state, delegate) -{ -} - -logic_t::logic_t(core_device_t &dev, const pstring &aname, const state_e state, + analog_t::analog_t(core_device_t &dev, const pstring &aname, const state_e state, nldelegate delegate) : core_terminal_t(dev, aname, state, delegate) - , logic_family_t() - , m_proxy(nullptr) -{ -} - -// ---------------------------------------------------------------------------------------- -// terminal_t -// ---------------------------------------------------------------------------------------- - -terminal_t::terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm) -: analog_t(dev, aname, STATE_BIDIR) -, m_Idr1(nullptr) -, m_go1(nullptr) -, m_gt1(nullptr) -, m_connected_terminal(otherterm) -{ - state().setup().register_term(*this); -} - -void terminal_t::solve_now() -{ - // Nets may belong to railnets which do not have a solver attached - if (this->has_net()) - if (net().solver() != nullptr) - net().solver()->update_forced(); -} - -void terminal_t::schedule_solve_after(const netlist_time after) -{ - // Nets may belong to railnets which do not have a solver attached - if (this->has_net()) - if (net().solver() != nullptr) - net().solver()->update_after(after); -} - -// ---------------------------------------------------------------------------------------- -// net_input_t -// ---------------------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------------------- -// net_output_t -// ---------------------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------------------- -// logic_output_t -// ---------------------------------------------------------------------------------------- - -logic_output_t::logic_output_t(core_device_t &dev, const pstring &aname) - : logic_t(dev, aname, STATE_OUT) - , m_my_net(dev.state(), name() + ".net", this) -{ - this->set_net(&m_my_net); - state().register_net(owned_pool_ptr(&m_my_net, false)); - set_logic_family(dev.logic_family()); - state().setup().register_term(*this); -} - -void logic_output_t::initial(const netlist_sig_t val) -{ - if (has_net()) - net().initial(val); -} - -// ---------------------------------------------------------------------------------------- -// analog_input_t -// ---------------------------------------------------------------------------------------- - -analog_input_t::analog_input_t(core_device_t &dev, const pstring &aname, - nldelegate delegate) -: analog_t(dev, aname, STATE_INP_ACTIVE, delegate) -{ - state().setup().register_term(*this); -} - -// ---------------------------------------------------------------------------------------- -// analog_output_t -// ---------------------------------------------------------------------------------------- - -analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname) - : analog_t(dev, aname, STATE_OUT) - , m_my_net(dev.state(), name() + ".net", this) -{ - state().register_net(owned_pool_ptr(&m_my_net, false)); - this->set_net(&m_my_net); - - //net().m_cur_Analog = NL_FCONST(0.0); - state().setup().register_term(*this); -} - -void analog_output_t::initial(const nl_double val) -{ - net().set_Q_Analog(val); -} - -// ----------------------------------------------------------------------------- -// logic_input_t -// ----------------------------------------------------------------------------- - -logic_input_t::logic_input_t(core_device_t &dev, const pstring &aname, - nldelegate delegate) - : logic_t(dev, aname, STATE_INP_ACTIVE, delegate) -{ - set_logic_family(dev.logic_family()); - state().setup().register_term(*this); -} - -// ---------------------------------------------------------------------------------------- -// Parameters ... -// ---------------------------------------------------------------------------------------- - -param_t::param_t(device_t &device, const pstring &name) - : device_object_t(device, device.name() + "." + name) -{ - device.setup().register_param_t(this->name(), *this); -} - -param_t::param_type_t param_t::param_type() const -{ - if (dynamic_cast(this) != nullptr) - return STRING; - else if (dynamic_cast(this) != nullptr) - return DOUBLE; - else if (dynamic_cast(this) != nullptr) - return INTEGER; - else if (dynamic_cast(this) != nullptr) - return LOGIC; - else if (dynamic_cast(this) != nullptr) - return POINTER; - else { - state().log().fatal(MF_UNKNOWN_PARAM_TYPE(name())); - return POINTER; /* Please compiler */ } -} + + logic_t::logic_t(core_device_t &dev, const pstring &aname, const state_e state, + nldelegate delegate) + : core_terminal_t(dev, aname, state, delegate) + , logic_family_t() + , m_proxy(nullptr) + { + } + + // ---------------------------------------------------------------------------------------- + // terminal_t + // ---------------------------------------------------------------------------------------- + + terminal_t::terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm) + : analog_t(dev, aname, STATE_BIDIR) + , m_Idr1(nullptr) + , m_go1(nullptr) + , m_gt1(nullptr) + , m_connected_terminal(otherterm) + { + state().setup().register_term(*this); + } + + void terminal_t::solve_now() + { + // Nets may belong to railnets which do not have a solver attached + if (this->has_net()) + if (net().solver() != nullptr) + net().solver()->update_forced(); + } + + void terminal_t::schedule_solve_after(const netlist_time after) + { + // Nets may belong to railnets which do not have a solver attached + if (this->has_net()) + if (net().solver() != nullptr) + net().solver()->update_after(after); + } + + // ---------------------------------------------------------------------------------------- + // net_input_t + // ---------------------------------------------------------------------------------------- + + // ---------------------------------------------------------------------------------------- + // net_output_t + // ---------------------------------------------------------------------------------------- + + // ---------------------------------------------------------------------------------------- + // logic_output_t + // ---------------------------------------------------------------------------------------- + + logic_output_t::logic_output_t(core_device_t &dev, const pstring &aname) + : logic_t(dev, aname, STATE_OUT) + , m_my_net(dev.state(), name() + ".net", this) + { + this->set_net(&m_my_net); + state().register_net(owned_pool_ptr(&m_my_net, false)); + set_logic_family(dev.logic_family()); + state().setup().register_term(*this); + } + + void logic_output_t::initial(const netlist_sig_t val) + { + if (has_net()) + net().initial(val); + } + + // ---------------------------------------------------------------------------------------- + // analog_input_t + // ---------------------------------------------------------------------------------------- + + analog_input_t::analog_input_t(core_device_t &dev, const pstring &aname, + nldelegate delegate) + : analog_t(dev, aname, STATE_INP_ACTIVE, delegate) + { + state().setup().register_term(*this); + } + + // ---------------------------------------------------------------------------------------- + // analog_output_t + // ---------------------------------------------------------------------------------------- + + analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname) + : analog_t(dev, aname, STATE_OUT) + , m_my_net(dev.state(), name() + ".net", this) + { + state().register_net(owned_pool_ptr(&m_my_net, false)); + this->set_net(&m_my_net); + + //net().m_cur_Analog = NL_FCONST(0.0); + state().setup().register_term(*this); + } + + void analog_output_t::initial(const nl_double val) + { + net().set_Q_Analog(val); + } + + // ----------------------------------------------------------------------------- + // logic_input_t + // ----------------------------------------------------------------------------- + + logic_input_t::logic_input_t(core_device_t &dev, const pstring &aname, + nldelegate delegate) + : logic_t(dev, aname, STATE_INP_ACTIVE, delegate) + { + set_logic_family(dev.logic_family()); + state().setup().register_term(*this); + } + + // ---------------------------------------------------------------------------------------- + // Parameters ... + // ---------------------------------------------------------------------------------------- + + param_t::param_t(device_t &device, const pstring &name) + : device_object_t(device, device.name() + "." + name) + { + device.setup().register_param_t(this->name(), *this); + } + + param_t::param_type_t param_t::param_type() const + { + if (dynamic_cast(this) != nullptr) + return STRING; + else if (dynamic_cast(this) != nullptr) + return DOUBLE; + else if (dynamic_cast(this) != nullptr) + return INTEGER; + else if (dynamic_cast(this) != nullptr) + return LOGIC; + else if (dynamic_cast(this) != nullptr) + return POINTER; + else + { + state().log().fatal(MF_UNKNOWN_PARAM_TYPE(name())); + return POINTER; /* Please compiler */ + } + } -void param_t::update_param() NL_NOEXCEPT -{ - device().update_param(); -} + void param_t::update_param() NL_NOEXCEPT + { + device().update_param(); + } -pstring param_t::get_initial(const device_t &dev, bool *found) -{ - pstring res = dev.setup().get_initial_param_val(this->name(), ""); - *found = (res != ""); - return res; -} + pstring param_t::get_initial(const device_t &dev, bool *found) + { + pstring res = dev.setup().get_initial_param_val(this->name(), ""); + *found = (res != ""); + return res; + } -const pstring param_model_t::type() -{ - return state().setup().models().type(str()); -} + const pstring param_model_t::type() + { + return state().setup().models().type(str()); + } -param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &val) -: param_t(device, name) -{ - m_param = device.setup().get_initial_param_val(this->name(),val); -} + param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &val) + : param_t(device, name) + { + m_param = device.setup().get_initial_param_val(this->name(),val); + } -void param_str_t::changed() -{ -} + void param_str_t::changed() + { + } -param_ptr_t::param_ptr_t(device_t &device, const pstring &name, uint8_t * val) -: param_t(device, name) -{ - m_param = val; //device.setup().get_initial_param_val(this->name(),val); - //netlist().save(*this, m_param, "m_param"); -} + param_ptr_t::param_ptr_t(device_t &device, const pstring &name, uint8_t * val) + : param_t(device, name) + { + m_param = val; //device.setup().get_initial_param_val(this->name(),val); + //netlist().save(*this, m_param, "m_param"); + } -void param_model_t::changed() -{ - state().log().fatal(MF_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME(name())); -} + void param_model_t::changed() + { + state().log().fatal(MF_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME(name())); + } -const pstring param_model_t::value_str(const pstring &entity) -{ - return state().setup().models().value_str(str(), entity); -} + const pstring param_model_t::value_str(const pstring &entity) + { + return state().setup().models().value_str(str(), entity); + } -nl_double param_model_t::value(const pstring &entity) -{ - return state().setup().models().value(str(), entity); -} + nl_double param_model_t::value(const pstring &entity) + { + return state().setup().models().value(str(), entity); + } -plib::unique_ptr param_data_t::stream() -{ - return device().setup().get_data_stream(str()); -} + plib::unique_ptr param_data_t::stream() + { + return device().setup().get_data_stream(str()); + } bool detail::core_terminal_t::is_logic() const NL_NOEXCEPT { @@ -1088,5 +966,15 @@ plib::unique_ptr param_data_t::stream() return dynamic_cast(this) != nullptr; } + void netlist_t::process_queue(const netlist_time delta) NL_NOEXCEPT + { + if (!m_use_stats) + process_queue_stats(delta, m_mainclock); + else + { + auto sm_guard(m_stat_mainloop.guard()); + process_queue_stats(delta, m_mainclock); + } + } } // namespace netlist diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index e3868944d7d..9518705c2c6 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -16,15 +16,15 @@ #include "plib/palloc.h" // owned_ptr #include "plib/pdynlib.h" #include "plib/pfmtlog.h" +#include "plib/plists.h" #include "plib/pmempool.h" #include "plib/ppmf.h" #include "plib/pstate.h" #include "plib/pstream.h" +#include "plib/ptime.h" #include "nl_errstr.h" -#include "nl_lists.h" #include "nltypes.h" -#include "plib/ptime.h" #include #include @@ -311,7 +311,6 @@ namespace netlist * state_var m_var; * } */ - template struct state_var { @@ -591,14 +590,14 @@ namespace netlist nldelegate m_delegate; #if USE_COPY_INSTEAD_OF_REFERENCE - void set_copied_input(netlist_sig_t val) + void set_copied_input(netlist_sig_t val) noexcept { m_Q = val; } state_var_sig m_Q; #else - void set_copied_input(netlist_sig_t val) const { plib::unused_var(val); } + void set_copied_input(netlist_sig_t val) const noexcept { plib::unused_var(val); } #endif private: @@ -669,13 +668,13 @@ namespace netlist std::vector &core_terms() { return m_core_terms; } #if USE_COPY_INSTEAD_OF_REFERENCE - void update_inputs() + void update_inputs() noexcept { for (auto & term : m_core_terms) term->m_Q = m_cur_Q; } #else - void update_inputs() const + void update_inputs() const noexcept { /* nothing needs to be done */ } @@ -810,9 +809,9 @@ namespace netlist logic_t(core_device_t &dev, const pstring &aname, const state_e state, nldelegate delegate = nldelegate()); - bool has_proxy() const { return (m_proxy != nullptr); } - devices::nld_base_proxy *get_proxy() const { return m_proxy; } - void set_proxy(devices::nld_base_proxy *proxy) { m_proxy = proxy; } + bool has_proxy() const noexcept { return (m_proxy != nullptr); } + devices::nld_base_proxy *get_proxy() const noexcept { return m_proxy; } + void set_proxy(devices::nld_base_proxy *proxy) noexcept { m_proxy = proxy; } logic_net_t & net() NL_NOEXCEPT; const logic_net_t & net() const NL_NOEXCEPT; @@ -901,13 +900,13 @@ namespace netlist analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr); - nl_double Q_Analog() const NL_NOEXCEPT { return m_cur_Analog; } - void set_Q_Analog(const nl_double v) NL_NOEXCEPT { m_cur_Analog = v; } + nl_double Q_Analog() const noexcept { return m_cur_Analog; } + void set_Q_Analog(const nl_double v) noexcept { m_cur_Analog = v; } nl_double *Q_Analog_state_ptr() NL_NOEXCEPT { return m_cur_Analog.ptr(); } //FIXME: needed by current solver code - devices::matrix_solver_t *solver() const NL_NOEXCEPT { return m_solver; } - void set_solver(devices::matrix_solver_t *solver) NL_NOEXCEPT { m_solver = solver; } + devices::matrix_solver_t *solver() const noexcept { return m_solver; } + void set_solver(devices::matrix_solver_t *solver) noexcept { m_solver = solver; } private: state_var m_cur_Analog; @@ -1200,9 +1199,9 @@ namespace netlist struct stats_t { // NL_KEEP_STATISTICS - nperftime_t m_stat_total_time; - nperfcount_t m_stat_call_count; - nperfcount_t m_stat_inc_active; + plib::pperftime_t m_stat_total_time; + plib::pperfcount_t m_stat_call_count; + plib::pperfcount_t m_stat_inc_active; }; unique_pool_ptr m_stats; @@ -1245,8 +1244,8 @@ namespace netlist ~device_t() noexcept override = default; - setup_t &setup(); - const setup_t &setup() const; + setup_t &setup() noexcept; + const setup_t &setup() const noexcept; template void create_and_register_subdevice(const pstring &name, unique_pool_ptr &dev, Args&&... args) @@ -1283,6 +1282,16 @@ namespace netlist family_setter_t(core_device_t &dev, const logic_family_desc_t *desc); }; + template + using timed_queue = plib::timed_queue_linear; + + /* Use timed_queue_heap to use stdc++ heap functions instead of linear processing. + * This slows down processing by about 25% on a Kaby Lake. + */ + + //template + //using timed_queue = timed_queue_heap; + // ----------------------------------------------------------------------------- // queue_t // ----------------------------------------------------------------------------- @@ -1292,13 +1301,13 @@ namespace netlist */ class detail::queue_t : //public timed_queue, false, NL_KEEP_STATISTICS>, - public timed_queue, false>, + public timed_queue, false>, public detail::netlist_ref, public plib::state_manager_t::callback_t { public: - using base_queue = timed_queue, false>; - using entry_t = pqentry_t; + using base_queue = timed_queue, false>; + using entry_t = plib::pqentry_t; explicit queue_t(netlist_state_t &nl); virtual ~queue_t() noexcept = default; @@ -1342,7 +1351,7 @@ namespace netlist friend class netlist_t; // allow access to private members template - static bool check_class(core_device_t *p) + static bool check_class(core_device_t *p) noexcept { return dynamic_cast(p) != nullptr; } @@ -1385,12 +1394,12 @@ namespace netlist /* logging and name */ - pstring name() const { return m_name; } + pstring name() const noexcept { return m_name; } - log_type & log() { return m_log; } - const log_type &log() const { return m_log; } + log_type & log() noexcept { return m_log; } + const log_type &log() const noexcept { return m_log; } - plib::dynlib &lib() { return *m_lib; } + plib::dynlib &lib() const noexcept { return *m_lib; } netlist_t &exec() { return m_netlist; } const netlist_t &exec() const { return m_netlist; } @@ -1486,16 +1495,19 @@ namespace netlist } } - setup_t &setup() NL_NOEXCEPT { return *m_setup; } - const setup_t &setup() const NL_NOEXCEPT { return *m_setup; } + setup_t &setup() noexcept { return *m_setup; } + const setup_t &setup() const noexcept { return *m_setup; } // FIXME: make a postload member and include code there void rebuild_lists(); /* must be called after post_load ! */ static void compile_defines(std::vector> &defs); - nets_collection_type & nets() { return m_nets; } - devices_collection_type & devices() { return m_devices; } + nets_collection_type & nets() noexcept { return m_nets; } + const nets_collection_type & nets() const noexcept { return m_nets; } + + devices_collection_type & devices() noexcept { return m_devices; } + const devices_collection_type & devices() const noexcept { return m_devices; } /* sole use is to manage lifetime of family objects */ std::unordered_map> m_family_cache; @@ -1549,12 +1561,13 @@ namespace netlist const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; } - void qpush(detail::queue_t::entry_t && e) noexcept + template + void qpush(E && e) noexcept { if (!USE_QUEUE_STATS || !m_use_stats) - m_queue.push(std::move(e)); // NOLINT(performance-move-const-arg) + m_queue.push(std::forward(e)); // NOLINT(performance-move-const-arg) else - m_queue.push(std::move(e)); // NOLINT(performance-move-const-arg) + m_queue.push(std::forward(e)); // NOLINT(performance-move-const-arg) } template @@ -1573,10 +1586,10 @@ namespace netlist /* state handling */ - plib::state_manager_t &run_state_manager() { return m_state->run_state_manager(); } + plib::state_manager_t &run_state_manager() noexcept { return m_state->run_state_manager(); } /* only used by nltool to create static c-code */ - devices::NETLIB_NAME(solver) *solver() const NL_NOEXCEPT { return m_solver; } + devices::NETLIB_NAME(solver) *solver() const noexcept { return m_solver; } /* force late type resolution */ template @@ -1586,21 +1599,21 @@ namespace netlist return static_cast(m_solver)->gmin(); } - netlist_state_t &nlstate() NL_NOEXCEPT { return *m_state; } - const netlist_state_t &nlstate() const { return *m_state; } + netlist_state_t &nlstate() noexcept { return *m_state; } + const netlist_state_t &nlstate() const noexcept { return *m_state; } - log_type & log() { return m_state->log(); } - const log_type &log() const { return m_state->log(); } + log_type & log() NL_NOEXCEPT { return m_state->log(); } + const log_type &log() const NL_NOEXCEPT { return m_state->log(); } - void print_stats() const; + void print_stats() const NL_NOEXCEPT; - bool stats_enabled() const { return m_use_stats; } - void enable_stats(bool val) { m_use_stats = val; } + bool stats_enabled() const noexcept { return m_use_stats; } + void enable_stats(bool val) noexcept { m_use_stats = val; } private: - template - void process_queue_stats(netlist_time delta) NL_NOEXCEPT; + template + void process_queue_stats(netlist_time delta, MCT *mainclock) NL_NOEXCEPT; plib::unique_ptr m_state; devices::NETLIB_NAME(solver) * m_solver; @@ -1615,8 +1628,8 @@ namespace netlist bool m_use_stats; // performance - nperftime_t m_stat_mainloop; - nperfcount_t m_perf_out_processed; + plib::pperftime_t m_stat_mainloop; + plib::pperfcount_t m_perf_out_processed; }; // ----------------------------------------------------------------------------- @@ -1782,7 +1795,7 @@ namespace netlist if (m_next_scheduled_time > exec().time()) { m_in_queue = queue_status::QUEUED; /* pending */ - exec().qpush({m_next_scheduled_time, this}); + exec().qpush(detail::queue_t::entry_t(m_next_scheduled_time, this)); } else { @@ -1904,6 +1917,106 @@ namespace netlist for (std::size_t i=0; i + inline void detail::net_t::process(const T mask, netlist_sig_t sig) + { + m_cur_Q = sig; + + if (KEEP_STATS) + { + for (auto & p : m_list_active) + { + p.set_copied_input(sig); + auto *stats = p.device().m_stats.get(); + stats->m_stat_call_count.inc(); + if ((p.terminal_state() & mask)) + { + auto g(stats->m_stat_total_time.guard()); + p.m_delegate(); + } + } + } + else + { + for (auto &p : m_list_active) + { + p.set_copied_input(sig); + if ((p.terminal_state() & mask)) + p.m_delegate(); + } + } + } + + template + inline void detail::net_t::update_devs() NL_NOEXCEPT + { + nl_assert(this->isRailNet()); + + m_in_queue = queue_status::DELIVERED; /* mark as taken ... */ + if (m_new_Q ^ m_cur_Q) + process((m_new_Q << core_terminal_t::INP_LH_SHIFT) + | (m_cur_Q << core_terminal_t::INP_HL_SHIFT), m_new_Q); + } + + template + inline void netlist_t::process_queue_stats(const netlist_time delta, MCT *mainclock) NL_NOEXCEPT + { + netlist_time stop(m_time + delta); + + qpush(detail::queue_t::entry_t(stop, nullptr)); + + if (m_mainclock == nullptr) + { + detail::queue_t::entry_t e(m_queue.pop()); + m_time = e.m_exec_time; + while (e.m_object != nullptr) + { + e.m_object->template update_devs(); + if (KEEP_STATS) + m_perf_out_processed.inc(); + e = m_queue.pop(); + m_time = e.m_exec_time; + } + } + else + { + logic_net_t &mc_net(mainclock->m_Q.net()); + const netlist_time inc(mainclock->m_inc); + netlist_time mc_time(mc_net.next_scheduled_time()); + + do + { + while (m_queue.top().m_exec_time > mc_time) + { + m_time = mc_time; + mc_net.toggle_new_Q(); + mc_net.update_devs(); + mc_time += inc; + } + + detail::queue_t::entry_t e(m_queue.pop()); + m_time = e.m_exec_time; + if (e.m_object != nullptr) + { + e.m_object->template update_devs(); + if (KEEP_STATS) + m_perf_out_processed.inc(); + } + else + break; + } while (true); //while (e.m_object != nullptr); + mc_net.set_next_scheduled_time(mc_time); + } + } + + } // namespace netlist namespace plib diff --git a/src/lib/netlist/nl_errstr.h b/src/lib/netlist/nl_errstr.h index 12cf72769a9..4681d027d79 100644 --- a/src/lib/netlist/nl_errstr.h +++ b/src/lib/netlist/nl_errstr.h @@ -14,7 +14,7 @@ #define PERRMSG(name, str) \ struct name \ { \ - operator pstring() const { return str; } \ + operator pstring() const noexcept { return str; } \ }; #define PERRMSGV(name, narg, str) \ @@ -23,7 +23,7 @@ template name(Args&&... args) \ : m_m(plib::pfmt(str)(std::forward(args)...)) \ { static_assert(narg == sizeof...(args), "Argument count mismatch"); } \ - operator pstring() const { return m_m; } \ + operator pstring() const noexcept { return m_m; } \ pstring m_m; \ }; diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h deleted file mode 100644 index 30c73062fd0..00000000000 --- a/src/lib/netlist/nl_lists.h +++ /dev/null @@ -1,335 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nllists.h - * - */ - -#pragma once - -#ifndef NLLISTS_H_ -#define NLLISTS_H_ - -#include "plib/pchrono.h" -#include "plib/plists.h" -#include "plib/ptypes.h" -#include "plib/parray.h" - -#include "nl_config.h" -#include "nltypes.h" - -#include -#include -#include -#include -#include - - -// ---------------------------------------------------------------------------------------- -// timed queue -// ---------------------------------------------------------------------------------------- - -namespace netlist -{ - //FIXME: move to an appropriate place - template - class pspin_mutex - { - public: - pspin_mutex() noexcept = default; - void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } } - void unlock() noexcept { m_lock.clear(std::memory_order_release); } - private: - PALIGNAS_CACHELINE() - std::atomic_flag m_lock = ATOMIC_FLAG_INIT; - }; - - template<> - class pspin_mutex - { - public: - void lock() const noexcept { } - void unlock() const noexcept { } - }; - - template - struct pqentry_t final - { - constexpr pqentry_t() noexcept : m_exec_time(), m_object(nullptr) { } - constexpr pqentry_t(const Time t, const Element o) noexcept : m_exec_time(t), m_object(o) { } -#if 0 - ~pqentry_t() = default; - constexpr pqentry_t(const pqentry_t &e) noexcept = default; - constexpr pqentry_t(pqentry_t &&e) noexcept = default; - pqentry_t& operator=(pqentry_t && other) noexcept = default; - pqentry_t& operator=(const pqentry_t &other) noexcept = default; - - void swap(pqentry_t &other) noexcept - { - std::swap(m_exec_time, other.m_exec_time); - std::swap(m_object, other.m_object); - } -#endif - inline bool operator ==(const pqentry_t &rhs) const noexcept - { - return m_object == rhs.m_object; - } - - inline bool operator ==(const Element &rhs) const noexcept - { - return m_object == rhs; - } - - inline bool operator <=(const pqentry_t &rhs) const noexcept - { - return (m_exec_time <= rhs.m_exec_time); - } - - inline bool operator <(const pqentry_t &rhs) const noexcept - { - return (m_exec_time < rhs.m_exec_time); - } - - inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); } - - Time m_exec_time; - Element m_object; - }; - - /* Use TS = true for a threadsafe queue */ - template - class timed_queue_linear : plib::nocopyassignmove - { - public: - - explicit timed_queue_linear(const std::size_t list_size) - : m_list(list_size) - { - clear(); - } - - std::size_t capacity() const noexcept { return m_list.capacity() - 1; } - bool empty() const noexcept { return (m_end == &m_list[1]); } - - template - void push(T && e) noexcept - { - /* Lock */ - lock_guard_type lck(m_lock); - T * i(m_end-1); - for (; *i < e; --i) - { - *(i+1) = *(i); - if (KEEPSTAT) - m_prof_sortmove.inc(); - } - *(i+1) = std::move(e); - ++m_end; - if (KEEPSTAT) - m_prof_call.inc(); - } - - T pop() noexcept { return *(--m_end); } - const T &top() const noexcept { return *(m_end-1); } - - template - void remove(const R &elem) noexcept - { - /* Lock */ - lock_guard_type lck(m_lock); - if (KEEPSTAT) - m_prof_remove.inc(); - for (T * i = m_end - 1; i > &m_list[0]; --i) - { - // == operator ignores time! - if (*i == elem) - { - std::copy(i+1, m_end--, i); - return; - } - } - } - - template - void retime(R && elem) noexcept - { - /* Lock */ - lock_guard_type lck(m_lock); - if (KEEPSTAT) - m_prof_retime.inc(); - - for (R * i = m_end - 1; i > &m_list[0]; --i) - { - if (*i == elem) // partial equal! - { - *i = std::move(elem); - while (*(i-1) < *i) - { - std::swap(*(i-1), *i); - --i; - } - while (i < m_end && *i < *(i+1)) - { - std::swap(*(i+1), *i); - ++i; - } - return; - } - } - } - - void clear() noexcept - { - lock_guard_type 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 - * need a comparison with queue start. - */ - m_list[0] = T::never(); - m_end++; - } - - // save state support & mame disasm - - const T *listptr() const noexcept { return &m_list[1]; } - std::size_t size() const noexcept { return static_cast(m_end - &m_list[1]); } - const T & operator[](const std::size_t index) const noexcept { return m_list[ 1 + index]; } - private: - using mutex_type = pspin_mutex; - using lock_guard_type = std::lock_guard; - - mutex_type m_lock; - PALIGNAS_CACHELINE() - T * m_end; - plib::aligned_vector m_list; - - public: - // profiling - nperfcount_t m_prof_sortmove; - nperfcount_t m_prof_call; - nperfcount_t m_prof_remove; - nperfcount_t m_prof_retime; - }; - - template - class timed_queue_heap : plib::nocopyassignmove - { - public: - - struct compare - { - constexpr bool operator()(const T &a, const T &b) const { return b <= a; } - }; - - explicit timed_queue_heap(const std::size_t list_size) - : m_list(list_size) - { - clear(); - } - - std::size_t capacity() const noexcept { return m_list.capacity(); } - bool empty() const noexcept { return &m_list[0] == m_end; } - - template - void push(T &&e) noexcept - { - /* Lock */ - lock_guard_type lck(m_lock); - *m_end++ = e; - std::push_heap(&m_list[0], m_end, compare()); - if (KEEPSTAT) - m_prof_call.inc(); - } - - T pop() noexcept - { - T ret(m_list[0]); - std::pop_heap(&m_list[0], m_end, compare()); - m_end--; - return ret; - } - - const T &top() const noexcept { return m_list[0]; } - - template - void remove(const R &elem) noexcept - { - /* Lock */ - lock_guard_type lck(m_lock); - if (KEEPSTAT) - m_prof_remove.inc(); - for (T * i = m_end - 1; i >= &m_list[0]; i--) - { - if (*i == elem) - { - m_end--; - for (;i < m_end; i++) - *i = std::move(*(i+1)); - std::make_heap(&m_list[0], m_end, compare()); - return; - } - } - } - - template - void retime(const T &elem) noexcept - { - /* Lock */ - lock_guard_type lck(m_lock); - if (KEEPSTAT) - m_prof_retime.inc(); - for (T * i = m_end - 1; i >= &m_list[0]; i--) - { - if (*i == elem) // partial equal! - { - *i = elem; - std::make_heap(&m_list[0], m_end, compare()); - return; - } - } - } - - void clear() - { - lock_guard_type lck(m_lock); - m_list.clear(); - m_end = &m_list[0]; - } - - // save state support & mame disasm - - constexpr const T *listptr() const { return &m_list[0]; } - constexpr std::size_t size() const noexcept { return m_list.size(); } - constexpr const T & operator[](const std::size_t index) const { return m_list[ 0 + index]; } - private: - using mutex_type = pspin_mutex; - using lock_guard_type = std::lock_guard; - - mutex_type m_lock; - std::vector m_list; - T *m_end; - - public: - // profiling - nperfcount_t m_prof_sortmove; - nperfcount_t m_prof_call; - nperfcount_t m_prof_remove; - nperfcount_t m_prof_retime; - }; - - template - using timed_queue = timed_queue_linear; - - /* - * Use timed_queue_heap to use stdc++ heap functions instead of linear processing. - * - * This slows down processing by about 25% on a Kaby Lake. - */ - - //template - //using timed_queue = timed_queue_heap; - -} // namespace netlist - -#endif /* NLLISTS_H_ */ diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index 3fb78d5e35b..453b0bb4adf 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -68,17 +68,6 @@ namespace netlist using log_type = plib::plog_base; - - //============================================================ - // Performance tracking - //============================================================ - - template - using nperftime_t = plib::chrono::timer; - - template - using nperfcount_t = plib::chrono::counter; - //============================================================ // Types needed by various includes //============================================================ diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index ad42d14c690..5b7d2f59c2d 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -34,8 +34,10 @@ namespace plib { { //using arena_storage_type = P *; using arena_storage_type = typename std::conditional::type; + template typename std::enable_if::type getref(X *x) { return *x;} + template typename std::enable_if::type::is_stateless, X&>::type getref(X &x, Y y = nullptr) @@ -44,13 +46,18 @@ namespace plib { return x; } - constexpr arena_deleter(arena_storage_type a = arena_storage_type()) noexcept + constexpr arena_deleter(arena_storage_type a = arena_storage_type()) : m_a(a) { } +#if 1 + template::value>::type> + arena_deleter(const arena_deleter &rhs) : m_a(rhs.m_a) { } +#else template::value>::type> - arena_deleter(const arena_deleter &rhs) noexcept : m_a(rhs.m_a) { } - + arena_deleter(const arena_deleter &rhs) : m_a(rhs.m_a) { } +#endif void operator()(T *p) //const { /* call destructor */ @@ -80,11 +87,11 @@ namespace plib { template friend class owned_ptr; - owned_ptr(pointer p, bool owned) noexcept + owned_ptr(pointer p, bool owned) : m_ptr(p), m_deleter(), m_is_owned(owned) { } - owned_ptr(pointer p, bool owned, D deleter) noexcept + owned_ptr(pointer p, bool owned, D deleter) : m_ptr(p), m_deleter(deleter), m_is_owned(owned) { } @@ -93,7 +100,7 @@ namespace plib { owned_ptr & operator =(owned_ptr &r) = delete; template - owned_ptr & operator =(owned_ptr &&r) + owned_ptr & operator =(owned_ptr &&r) noexcept { if (m_is_owned && (m_ptr != nullptr)) //delete m_ptr; @@ -122,7 +129,7 @@ namespace plib { m_deleter(m_ptr); m_is_owned = r.m_is_owned; m_ptr = r.m_ptr; - m_deleter = std::move(r.m_deleter); + m_deleter = r.m_deleter; r.m_is_owned = false; r.m_ptr = nullptr; return *this; @@ -197,18 +204,12 @@ namespace plib { ~arena_allocator() noexcept = default; - arena_allocator(const arena_allocator &rhs) noexcept = default; - arena_allocator& operator=(const arena_allocator&) noexcept = delete; - - arena_allocator(arena_allocator&&) noexcept = default; - arena_allocator& operator=(arena_allocator&&) = delete; - arena_allocator(arena_type & a) noexcept : m_a(a) { } template - arena_allocator(const arena_allocator& rhs) noexcept + arena_allocator(const arena_allocator& rhs) : m_a(rhs.m_a) { } @@ -223,7 +224,7 @@ namespace plib { return reinterpret_cast(m_a.allocate(ALIGN, sizeof(T) * n)); } - void deallocate(T* p, std::size_t n) noexcept + void deallocate(T* p, std::size_t n) { unused_var(n); m_a.deallocate(p); diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h index 65251a02002..d8f7a441f6f 100644 --- a/src/lib/netlist/plib/parray.h +++ b/src/lib/netlist/plib/parray.h @@ -32,6 +32,7 @@ namespace plib { struct sizeabs { static constexpr std::size_t ABS() { return 0; } + //using container = typename std::vector>; using container = typename std::vector>; }; @@ -75,6 +76,15 @@ namespace plib { { } + // osx clang doesn't like COPYASSIGNMOVE(parray, default) + // it will generate some weird error messages about move assignment + // constructor having a different noexcept status. + + parray(const parray &rhs) : m_a(rhs.m_a), m_size(rhs.m_size) {} + parray(parray &&rhs) noexcept : m_a(std::move(rhs.m_a)), m_size(std::move(rhs.m_size)) {} + parray &operator=(const parray &rhs) { m_a = rhs.m_a; m_size = rhs.m_size; return *this; } + parray &operator=(parray &&rhs) noexcept { std::swap(m_a,rhs.m_a); std::swap(m_size, rhs.m_size); return *this; } + template parray(size_type size, typename std::enable_if<(X != 0), int>::type = 0) : m_size(size) @@ -125,6 +135,8 @@ namespace plib { (*this)[i] = parray(size2); } } + + COPYASSIGNMOVE(parray2D, default) }; } // namespace plib diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h index d6e98134f47..4e0bb071431 100644 --- a/src/lib/netlist/plib/pchrono.h +++ b/src/lib/netlist/plib/pchrono.h @@ -15,245 +15,253 @@ //#include namespace plib { -namespace chrono { - template - struct sys_ticks - { - using type = typename T::rep; - static inline type start() { return T::now().time_since_epoch().count(); } - static inline type stop() { return T::now().time_since_epoch().count(); } - static inline constexpr type per_second() { return T::period::den / T::period::num; } - }; - - using hires_ticks = sys_ticks; - using steady_ticks = sys_ticks; - using system_ticks = sys_ticks; - - #if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)) - - template - struct base_ticks - { - using ret_type = R; - static ret_type per_second() + namespace chrono { + template + struct sys_ticks { - static ret_type persec = 0; - if (persec == 0) + using type = typename T::rep; + static inline constexpr type start() noexcept { return T::now().time_since_epoch().count(); } + static inline constexpr type stop() noexcept { return T::now().time_since_epoch().count(); } + static inline constexpr type per_second() noexcept { return T::period::den / T::period::num; } + }; + + using hires_ticks = sys_ticks; + using steady_ticks = sys_ticks; + using system_ticks = sys_ticks; + + #if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)) + + template + struct base_ticks + { + using ret_type = R; + static ret_type per_second() { - ret_type x = 0; - system_ticks::type t = system_ticks::start(); - system_ticks::type e; - x = - T :: start(); - do { - e = system_ticks::stop(); - } while (e - t < system_ticks::per_second() / 100 ); - x += T :: stop(); - persec = (ret_type)(double)((double) x * (double) system_ticks::per_second() / double (e - t)); + static ret_type persec = 0; + if (persec == 0) + { + ret_type x = 0; + system_ticks::type t = system_ticks::start(); + system_ticks::type e; + x = - T :: start(); + do { + e = system_ticks::stop(); + } while (e - t < system_ticks::per_second() / 100 ); + x += T :: stop(); + persec = (ret_type)(double)((double) x * (double) system_ticks::per_second() / double (e - t)); + } + return persec; } - return persec; - } - }; + }; - #if PHAS_RDTSCP - struct fast_ticks : public base_ticks - { - typedef int64_t type; - static inline type start() + #if PHAS_RDTSCP + struct fast_ticks : public base_ticks { - int64_t v; - __asm__ __volatile__ ( - "rdtscp;" - "shl $32, %%rdx;" - "or %%rdx, %%rax;" - : "=a"(v) /* outputs */ - : /* inputs */ - : "%rcx", "%rdx" /* clobbers */ - ); - return v; - } - static inline type stop() + typedef int64_t type; + static inline type start() noexcept + { + int64_t v; + __asm__ __volatile__ ( + "rdtscp;" + "shl $32, %%rdx;" + "or %%rdx, %%rax;" + : "=a"(v) /* outputs */ + : /* inputs */ + : "%rcx", "%rdx" /* clobbers */ + ); + return v; + } + static inline type stop() noexcept + { + return start(); + } + }; + + #else + struct fast_ticks : public base_ticks { - return start(); - } - }; + typedef int64_t type; + static inline type start() noexcept + { + int64_t v; + __asm__ __volatile__ ( + "rdtsc;" + "shl $32, %%rdx;" + "or %%rdx, %%rax;" + : "=a"(v) /* outputs */ + : /* inputs */ + : "%rdx" /* clobbers */ + ); + return v; + } + static inline type stop() noexcept + { + return start(); + } + }; - #else - struct fast_ticks : public base_ticks - { - typedef int64_t type; - static inline type start() + #endif + + + /* Based on "How to Benchmark Code Execution Times on Intel?? IA-32 and IA-64 + * Instruction Set Architectures", Intel, 2010 + * + */ + #if PUSE_ACCURATE_STATS && PHAS_RDTSCP + /* + * kills performance completely, but is accurate + * cpuid serializes, but clobbers ebx and ecx + * + */ + + struct exact_ticks : public base_ticks { - int64_t v; - __asm__ __volatile__ ( - "rdtsc;" - "shl $32, %%rdx;" - "or %%rdx, %%rax;" - : "=a"(v) /* outputs */ - : /* inputs */ - : "%rdx" /* clobbers */ - ); - return v; - } - static inline type stop() + typedef int64_t type; + + static inline type start() noexcept + { + int64_t v; + __asm__ __volatile__ ( + "cpuid;" + //"xor %%eax, %%eax\n\t" + "rdtsc;" + "shl $32, %%rdx;" + "or %%rdx, %%rax;" + : "=a"(v) /* outputs */ + : "a"(0x0) /* inputs */ + : "%ebx", "%ecx", "%rdx" /* clobbers*/ + ); + return v; + } + static inline type stop() noexcept + { + int64_t v; + __asm__ __volatile__ ( + "rdtscp;" + "shl $32, %%rdx;" + "or %%rax, %%rdx;" + "mov %%rdx, %%r10;" + "xor %%eax, %%eax\n\t" + "cpuid;" + "mov %%r10, %%rax;" + : "=a" (v) + : + : "%ebx", "%ecx", "%rdx", "%r10" + ); + return v; + } + }; + #else + using exact_ticks = fast_ticks; + #endif + + + #else + using fast_ticks = hires_ticks; + using exact_ticks = fast_ticks; + #endif + + template + struct counter { - return start(); - } - }; - - #endif - - - /* Based on "How to Benchmark Code Execution Times on Intel?? IA-32 and IA-64 - * Instruction Set Architectures", Intel, 2010 - * - */ - #if PUSE_ACCURATE_STATS && PHAS_RDTSCP - /* - * kills performance completely, but is accurate - * cpuid serializes, but clobbers ebx and ecx - * - */ - - struct exact_ticks : public base_ticks - { - typedef int64_t type; - - static inline type start() - { - int64_t v; - __asm__ __volatile__ ( - "cpuid;" - //"xor %%eax, %%eax\n\t" - "rdtsc;" - "shl $32, %%rdx;" - "or %%rdx, %%rax;" - : "=a"(v) /* outputs */ - : "a"(0x0) /* inputs */ - : "%ebx", "%ecx", "%rdx" /* clobbers*/ - ); - return v; - } - static inline type stop() - { - int64_t v; - __asm__ __volatile__ ( - "rdtscp;" - "shl $32, %%rdx;" - "or %%rax, %%rdx;" - "mov %%rdx, %%r10;" - "xor %%eax, %%eax\n\t" - "cpuid;" - "mov %%r10, %%rax;" - : "=a" (v) - : - : "%ebx", "%ecx", "%rdx", "%r10" - ); - return v; - } - }; - #else - using exact_ticks = fast_ticks; - #endif - - - #else - using fast_ticks = hires_ticks; - using exact_ticks = fast_ticks; - #endif - - template - struct counter - { - counter() : m_count(0) { } - using type = uint_least64_t; - type operator()() const { return m_count; } - void inc() { ++m_count; } - void reset() { m_count = 0; } - constexpr static bool enabled = enabled_; - private: - type m_count; - }; - - template<> - struct counter - { - using type = uint_least64_t; - constexpr type operator()() const { return 0; } - void inc() const { } - void reset() const { } - constexpr static bool enabled = false; - }; - - - template< typename T, bool enabled_ = true> - struct timer - { - using type = typename T::type; - using ctype = uint_least64_t; - constexpr static bool enabled = enabled_; - - struct guard_t - { - guard_t() = delete; - guard_t(timer &m) noexcept : m_m(m) { m_m.m_time -= T::start(); } - ~guard_t() { m_m.m_time += T::stop(); ++m_m.m_count; } - - COPYASSIGNMOVE(guard_t, default) - + counter() : m_count(0) { } + using type = uint_least64_t; + type operator()() const noexcept { return m_count; } + void inc() noexcept { ++m_count; } + void reset() noexcept { m_count = 0; } + constexpr static bool enabled = enabled_; private: - timer &m_m; + type m_count; }; - friend struct guard_t; - - timer() : m_time(0), m_count(0) { } - - type operator()() const { return m_time; } - - void reset() { m_time = 0; m_count = 0; } - type average() const { return (m_count == 0) ? 0 : m_time / m_count; } - type total() const { return m_time; } - ctype count() const { return m_count; } - - double as_seconds() const { return static_cast(total()) - / static_cast(T::per_second()); } - - guard_t guard() { return guard_t(*this); } - private: - type m_time; - ctype m_count; - }; - - template - struct timer - { - using type = typename T::type; - using ctype = uint_least64_t; - - struct guard_t + template<> + struct counter { - guard_t() = default; - COPYASSIGNMOVE(guard_t, default) - /* using default constructor will trigger warning on - * unused local variable. - */ - // NOLINTNEXTLINE(modernize-use-equals-default) - ~guard_t() { } + using type = uint_least64_t; + constexpr type operator()() const { return 0; } + void inc() const { } + void reset() const { } + constexpr static bool enabled = false; }; - constexpr type operator()() const { return 0; } - void reset() const { } - constexpr type average() const { return 0; } - constexpr type total() const { return 0; } - constexpr ctype count() const { return 0; } - constexpr double as_seconds() const { return 0.0; } - constexpr static bool enabled = false; - guard_t guard() { return guard_t(); } - }; + template< typename T, bool enabled_ = true> + struct timer + { + using type = typename T::type; + using ctype = uint_least64_t; + constexpr static bool enabled = enabled_; + + struct guard_t + { + guard_t() = delete; + guard_t(timer &m) noexcept : m_m(m) { m_m.m_time -= T::start(); } + ~guard_t() { m_m.m_time += T::stop(); ++m_m.m_count; } + + COPYASSIGNMOVE(guard_t, default) + + private: + timer &m_m; + }; + + friend struct guard_t; + + timer() : m_time(0), m_count(0) { } + + type operator()() const { return m_time; } + + void reset() { m_time = 0; m_count = 0; } + type average() const { return (m_count == 0) ? 0 : m_time / m_count; } + type total() const { return m_time; } + ctype count() const { return m_count; } + + double as_seconds() const { return static_cast(total()) + / static_cast(T::per_second()); } + + guard_t guard() { return guard_t(*this); } + private: + type m_time; + ctype m_count; + }; + + template + struct timer + { + using type = typename T::type; + using ctype = uint_least64_t; + + struct guard_t + { + guard_t() = default; + COPYASSIGNMOVE(guard_t, default) + /* using default constructor will trigger warning on + * unused local variable. + */ + // NOLINTNEXTLINE(modernize-use-equals-default) + ~guard_t() { } + }; + + constexpr type operator()() const { return 0; } + void reset() const { } + constexpr type average() const { return 0; } + constexpr type total() const { return 0; } + constexpr ctype count() const { return 0; } + constexpr double as_seconds() const { return 0.0; } + constexpr static bool enabled = false; + guard_t guard() { return guard_t(); } + }; } // namespace chrono + //============================================================ + // Performance tracking + //============================================================ + + template + using pperftime_t = plib::chrono::timer; + + template + using pperfcount_t = plib::chrono::counter; } // namespace plib #endif /* PCHRONO_H_ */ diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp index 990c8a78e94..ca7ec88e2e3 100644 --- a/src/lib/netlist/plib/pfmtlog.cpp +++ b/src/lib/netlist/plib/pfmtlog.cpp @@ -1,7 +1,7 @@ // license:GPL-2.0+ // copyright-holders:Couriersud /* - * nl_string.c + * pfm_log.cpp * */ diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h index 727dad5d936..d6c37eaf5ca 100644 --- a/src/lib/netlist/plib/plists.h +++ b/src/lib/netlist/plib/plists.h @@ -10,283 +10,506 @@ #ifndef PLISTS_H_ #define PLISTS_H_ +#include "palloc.h" +#include "pchrono.h" #include "pstring.h" +#include #include +#include +#include #include +#include #include namespace plib { -/* ---------------------------------------------------------------------------------------- - * uninitialised_array_t: - * fixed size array allowing to override constructor and initialize - * members by placement new. - * - * Use with care. This template is provided to improve locality of storage - * in high frequency applications. It should not be used for anything else. - * ---------------------------------------------------------------------------------------- */ -template -class uninitialised_array_t -{ -public: - - using iterator = C *; - using const_iterator = const C *; - - //uninitialised_array_t() noexcept = default; - uninitialised_array_t() noexcept - : m_initialized(0) - { - } - - COPYASSIGNMOVE(uninitialised_array_t, delete) - ~uninitialised_array_t() noexcept - { - if (m_initialized>=N) - for (std::size_t i=0; i(&m_buf[index]); - } - - const C& operator[](const std::size_t &index) const noexcept - { - return *reinterpret_cast(&m_buf[index]); - } - - template - void emplace(const std::size_t index, Args&&... args) - { - m_initialized++; - // allocate on buffer - new (&m_buf[index]) C(std::forward(args)...); - } - - iterator begin() const noexcept { return reinterpret_cast(&m_buf[0]); } - iterator end() const noexcept { return reinterpret_cast(&m_buf[N]); } - - iterator begin() noexcept { return reinterpret_cast(&m_buf[0]); } - iterator end() noexcept { return reinterpret_cast(&m_buf[N]); } - - const_iterator cbegin() const noexcept { return reinterpret_cast(&m_buf[0]); } - const_iterator cend() const noexcept { return reinterpret_cast(&m_buf[N]); } - -protected: - -private: - - /* ensure proper alignment */ - PALIGNAS_VECTOROPT() - std::array::type, N> m_buf; - unsigned m_initialized; -}; - -// ---------------------------------------------------------------------------------------- -// plinkedlist_t: a simple linked list -// the list allows insertions / deletions if used properly -// ---------------------------------------------------------------------------------------- - -#if 0 -template -class linkedlist_t -{ -public: - - struct element_t + /**! fixed size array allowing to override constructor and initialize members by placement new. + * + * Use with care. This template is provided to improve locality of storage + * in high frequency applications. It should not be used for anything else. + * + */ + template + class uninitialised_array_t { public: - friend class linkedlist_t; + using iterator = C *; + using const_iterator = const C *; - constexpr element_t() : m_next(nullptr) {} - constexpr element_t(const element_t &rhs) = delete; - constexpr element_t(element_t &&rhs) = delete; + //uninitialised_array_t() noexcept = default; + uninitialised_array_t() noexcept + : m_initialized(0) + { + } - constexpr LC *next() const noexcept { return m_next; } + COPYASSIGNMOVE(uninitialised_array_t, delete) + ~uninitialised_array_t() noexcept + { + if (m_initialized>=N) + for (std::size_t i=0; i(&m_buf[index]); + } + + const C& operator[](const std::size_t &index) const noexcept + { + return *reinterpret_cast(&m_buf[index]); + } + + template + void emplace(const std::size_t index, Args&&... args) + { + m_initialized++; + // allocate on buffer + new (&m_buf[index]) C(std::forward(args)...); + } + + iterator begin() const noexcept { return reinterpret_cast(&m_buf[0]); } + iterator end() const noexcept { return reinterpret_cast(&m_buf[N]); } + + iterator begin() noexcept { return reinterpret_cast(&m_buf[0]); } + iterator end() noexcept { return reinterpret_cast(&m_buf[N]); } + + const_iterator cbegin() const noexcept { return reinterpret_cast(&m_buf[0]); } + const_iterator cend() const noexcept { return reinterpret_cast(&m_buf[N]); } protected: - ~element_t() = default; + private: - LC * m_next; + + /* ensure proper alignment */ + PALIGNAS_VECTOROPT() + std::array::type, N> m_buf; + unsigned m_initialized; }; - struct iter_t final : public std::iterator - { - private: - LC* p; - public: - explicit constexpr iter_t(LC* x) noexcept : p(x) { } - explicit constexpr iter_t(const iter_t &rhs) noexcept : p(rhs.p) { } - iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); } - iter_t& operator=(const iter_t &rhs) { iter_t t(rhs); std::swap(*this, t); return *this; } - iter_t& operator=(iter_t &&rhs) { std::swap(*this, rhs); return *this; } - iter_t& operator++() noexcept {p = p->next();return *this;} - iter_t operator++(int) noexcept {iter_t tmp(*this); operator++(); return tmp;} - constexpr bool operator==(const iter_t& rhs) const noexcept {return p == rhs.p;} - constexpr bool operator!=(const iter_t& rhs) const noexcept {return p != rhs.p;} - /* constexpr */ LC& operator*() noexcept {return *p;} - /* constexpr */ LC* operator->() noexcept {return p;} - - constexpr LC& operator*() const noexcept {return *p;} - constexpr LC* operator->() const noexcept {return p;} - }; - - constexpr linkedlist_t() : m_head(nullptr) {} - - constexpr iter_t begin() const noexcept { return iter_t(m_head); } - constexpr iter_t end() const noexcept { return iter_t(nullptr); } - - void push_front(LC *elem) noexcept - { - elem->m_next = m_head; - m_head = elem; - } - - void push_back(LC *elem) noexcept - { - LC **p = &m_head; - while (*p != nullptr) - { - p = &((*p)->m_next); - } - *p = elem; - elem->m_next = nullptr; - } - - void remove(const LC *elem) noexcept - { - auto p = &m_head; - while(*p != elem) - { - //nl_assert(*p != nullptr); - p = &((*p)->m_next); - } - (*p) = elem->m_next; - } - - LC *front() const noexcept { return m_head; } - void clear() noexcept { m_head = nullptr; } - constexpr bool empty() const noexcept { return (m_head == nullptr); } - -private: - LC *m_head; -}; -#else -template -class linkedlist_t -{ -public: - - struct element_t + /**! a simple linked list. + * + * the list allows insertions deletions whilst being processed. + */ + template + class linkedlist_t { public: - friend class linkedlist_t; + struct element_t + { + public: + friend class linkedlist_t; - constexpr element_t() : m_next(nullptr), m_prev(nullptr) {} - ~element_t() noexcept = default; + constexpr element_t() : m_next(nullptr), m_prev(nullptr) {} + ~element_t() noexcept = default; - COPYASSIGNMOVE(element_t, delete) + COPYASSIGNMOVE(element_t, delete) + + constexpr LC *next() const noexcept { return m_next; } + constexpr LC *prev() const noexcept { return m_prev; } + private: + LC * m_next; + LC * m_prev; + }; + + struct iter_t final : public std::iterator + { + private: + LC* p; + public: + explicit constexpr iter_t(LC* x) noexcept : p(x) { } + constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { } + iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); } + iter_t& operator=(const iter_t &rhs) noexcept { if (this != &rhs) p = rhs.p; return *this; } + iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; } + ~iter_t() = default; + + iter_t& operator++() noexcept { p = p->next();return *this; } + // NOLINTNEXTLINE(cert-dcl21-cpp) + iter_t operator++(int) & noexcept { const iter_t tmp(*this); operator++(); return tmp; } + + constexpr bool operator==(const iter_t& rhs) const noexcept { return p == rhs.p; } + constexpr bool operator!=(const iter_t& rhs) const noexcept { return p != rhs.p; } + C14CONSTEXPR LC& operator*() noexcept { return *p; } + C14CONSTEXPR LC* operator->() noexcept { return p; } + + C14CONSTEXPR LC& operator*() const noexcept { return *p; } + C14CONSTEXPR LC* operator->() const noexcept { return p; } + }; + + constexpr linkedlist_t() : m_head(nullptr) {} + + constexpr iter_t begin() const noexcept { return iter_t(m_head); } + constexpr iter_t end() const noexcept { return iter_t(nullptr); } + + void push_front(LC *elem) noexcept + { + elem->m_next = m_head; + elem->m_prev = nullptr; + if (m_head) + m_head->m_prev = elem; + m_head = elem; + } + + void push_back(LC *elem) noexcept + { + LC ** p(&m_head); + LC * prev(nullptr); + while (*p != nullptr) + { + prev = *p; + p = &((*p)->m_next); + } + *p = elem; + elem->m_prev = prev; + elem->m_next = nullptr; + } + + void remove(const LC *elem) noexcept + { + if (elem->m_prev) + elem->m_prev->m_next = elem->m_next; + else + m_head = elem->m_next; + if (elem->m_next) + elem->m_next->m_prev = elem->m_prev; + else + { + /* update tail */ + } + } + + LC *front() const noexcept { return m_head; } + constexpr bool empty() const noexcept { return (m_head == nullptr); } + void clear() noexcept + { + LC *p(m_head); + while (p != nullptr) + { + LC *n(p->m_next); + p->m_next = nullptr; + p->m_prev = nullptr; + p = n; + } + m_head = nullptr; + } - constexpr LC *next() const noexcept { return m_next; } - constexpr LC *prev() const noexcept { return m_prev; } private: - LC * m_next; - LC * m_prev; + LC *m_head; }; - struct iter_t final : public std::iterator + // ---------------------------------------------------------------------------------------- + // FIXME: Move elsewhere + // ---------------------------------------------------------------------------------------- + + template + class pspin_mutex { - private: - LC* p; public: - explicit constexpr iter_t(LC* x) noexcept : p(x) { } - constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { } - iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); } - iter_t& operator=(const iter_t &rhs) noexcept { p = rhs.p; return *this; } - iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; } - iter_t& operator++() noexcept {p = p->next();return *this;} - // NOLINTNEXTLINE(cert-dcl21-cpp) - iter_t operator++(int) & noexcept {const iter_t tmp(*this); operator++(); return tmp;} - - ~iter_t() = default; - - constexpr bool operator==(const iter_t& rhs) const noexcept {return p == rhs.p;} - constexpr bool operator!=(const iter_t& rhs) const noexcept {return p != rhs.p;} - constexpr LC& operator*() noexcept {return *p;} - constexpr LC* operator->() noexcept {return p;} - - constexpr LC& operator*() const noexcept {return *p;} - constexpr LC* operator->() const noexcept {return p;} + pspin_mutex() noexcept = default; + void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } } + void unlock() noexcept { m_lock.clear(std::memory_order_release); } + private: + PALIGNAS_CACHELINE() + std::atomic_flag m_lock = ATOMIC_FLAG_INIT; }; - constexpr linkedlist_t() : m_head(nullptr) {} - - constexpr iter_t begin() const noexcept { return iter_t(m_head); } - constexpr iter_t end() const noexcept { return iter_t(nullptr); } - - void push_front(LC *elem) noexcept + template<> + class pspin_mutex { - if (m_head) - m_head->m_prev = elem; - elem->m_next = m_head; - elem->m_prev = nullptr; - m_head = elem; - } + public: + void lock() const noexcept { } + void unlock() const noexcept { } + }; - void push_back(LC *elem) noexcept + // ---------------------------------------------------------------------------------------- + // timed queue + // ---------------------------------------------------------------------------------------- + + template + struct pqentry_t final { - LC ** p(&m_head); - LC * prev(nullptr); - while (*p != nullptr) + constexpr pqentry_t() noexcept : m_exec_time(), m_object(nullptr) { } + constexpr pqentry_t(const Time t, const Element o) noexcept : m_exec_time(t), m_object(o) { } +#if 0 + ~pqentry_t() = default; + constexpr pqentry_t(const pqentry_t &e) noexcept = default; + constexpr pqentry_t(pqentry_t &&e) noexcept = default; + pqentry_t& operator=(pqentry_t && other) noexcept = default; + pqentry_t& operator=(const pqentry_t &other) noexcept = default; + + void swap(pqentry_t &other) noexcept { - prev = *p; - p = &((*p)->m_next); + std::swap(m_exec_time, other.m_exec_time); + std::swap(m_object, other.m_object); } - *p = elem; - elem->m_prev = prev; - elem->m_next = nullptr; - } - - void remove(const LC *elem) noexcept - { - if (elem->m_prev) - elem->m_prev->m_next = elem->m_next; - else - m_head = elem->m_next; - if (elem->m_next) - elem->m_next->m_prev = elem->m_prev; - else - { - /* update tail */ - } - } - - LC *front() const noexcept { return m_head; } - constexpr bool empty() const noexcept { return (m_head == nullptr); } - void clear() noexcept - { - LC *p(m_head); - while (p != nullptr) - { - LC *n(p->m_next); - p->m_next = nullptr; - p->m_prev = nullptr; - p = n; - } - m_head = nullptr; - } - -private: - LC *m_head; -}; #endif + inline bool operator ==(const pqentry_t &rhs) const noexcept + { + return m_object == rhs.m_object; + } + + inline bool operator ==(const Element &rhs) const noexcept + { + return m_object == rhs; + } + + inline bool operator <=(const pqentry_t &rhs) const noexcept + { + return (m_exec_time <= rhs.m_exec_time); + } + + inline bool operator <(const pqentry_t &rhs) const noexcept + { + return (m_exec_time < rhs.m_exec_time); + } + + inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); } + + Time m_exec_time; + Element m_object; + }; + + /* Use TS = true for a threadsafe queue */ + template + class timed_queue_linear : nocopyassignmove + { + public: + + explicit timed_queue_linear(const std::size_t list_size) + : m_list(list_size) + { + clear(); + } + + std::size_t capacity() const noexcept { return m_list.capacity() - 1; } + bool empty() const noexcept { return (m_end == &m_list[1]); } + + template + void push(T && e) noexcept + { +#if 0 + /* Lock */ + lock_guard_type lck(m_lock); + T * i(m_end-1); + for (; *i < e; --i) + { + *(i+1) = *(i); + if (KEEPSTAT) + m_prof_sortmove.inc(); + } + *(i+1) = std::move(e); + ++m_end; +#else + /* Lock */ + lock_guard_type lck(m_lock); + T * i(m_end++); + *i = std::move(e); + for (; *(i-1) < *i; --i) + { + std::swap(*(i-1), *(i)); + if (KEEPSTAT) + m_prof_sortmove.inc(); + } +#endif + if (KEEPSTAT) + m_prof_call.inc(); + } + + T pop() noexcept { return *(--m_end); } + const T &top() const noexcept { return *(m_end-1); } + + template + void remove(const R &elem) noexcept + { + /* Lock */ + lock_guard_type lck(m_lock); + if (KEEPSTAT) + m_prof_remove.inc(); + for (T * i = m_end - 1; i > &m_list[0]; --i) + { + // == operator ignores time! + if (*i == elem) + { + std::copy(i+1, m_end--, i); + return; + } + } + } + + template + void retime(R && elem) noexcept + { + /* Lock */ + lock_guard_type lck(m_lock); + if (KEEPSTAT) + m_prof_retime.inc(); + + for (R * i = m_end - 1; i > &m_list[0]; --i) + { + if (*i == elem) // partial equal! + { + *i = std::forward(elem); + while (*(i-1) < *i) + { + std::swap(*(i-1), *i); + --i; + } + while (i < m_end && *i < *(i+1)) + { + std::swap(*(i+1), *i); + ++i; + } + return; + } + } + } + + void clear() noexcept + { + lock_guard_type 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 + * need a comparison with queue start. + */ + m_list[0] = T::never(); + m_end++; + } + + // save state support & mame disasm + + const T *listptr() const noexcept { return &m_list[1]; } + std::size_t size() const noexcept { return static_cast(m_end - &m_list[1]); } + const T & operator[](const std::size_t index) const noexcept { return m_list[ 1 + index]; } + private: + using mutex_type = pspin_mutex; + using lock_guard_type = std::lock_guard; + + mutex_type m_lock; + PALIGNAS_CACHELINE() + T * m_end; + aligned_vector m_list; + + public: + // profiling + pperfcount_t m_prof_sortmove; + pperfcount_t m_prof_call; + pperfcount_t m_prof_remove; + pperfcount_t m_prof_retime; + }; + + template + class timed_queue_heap : nocopyassignmove + { + public: + + struct compare + { + constexpr bool operator()(const T &a, const T &b) const { return b <= a; } + }; + + explicit timed_queue_heap(const std::size_t list_size) + : m_list(list_size) + { + clear(); + } + + std::size_t capacity() const noexcept { return m_list.capacity(); } + bool empty() const noexcept { return &m_list[0] == m_end; } + + template + void push(T &&e) noexcept + { + /* Lock */ + lock_guard_type lck(m_lock); + *m_end++ = e; + std::push_heap(&m_list[0], m_end, compare()); + if (KEEPSTAT) + m_prof_call.inc(); + } + + T pop() noexcept + { + T ret(m_list[0]); + std::pop_heap(&m_list[0], m_end, compare()); + m_end--; + return ret; + } + + const T &top() const noexcept { return m_list[0]; } + + template + void remove(const R &elem) noexcept + { + /* Lock */ + lock_guard_type lck(m_lock); + if (KEEPSTAT) + m_prof_remove.inc(); + for (T * i = m_end - 1; i >= &m_list[0]; i--) + { + if (*i == elem) + { + m_end--; + for (;i < m_end; i++) + *i = std::move(*(i+1)); + std::make_heap(&m_list[0], m_end, compare()); + return; + } + } + } + + template + void retime(const T &elem) noexcept + { + /* Lock */ + lock_guard_type lck(m_lock); + if (KEEPSTAT) + m_prof_retime.inc(); + for (T * i = m_end - 1; i >= &m_list[0]; i--) + { + if (*i == elem) // partial equal! + { + *i = elem; + std::make_heap(&m_list[0], m_end, compare()); + return; + } + } + } + + void clear() + { + lock_guard_type lck(m_lock); + m_list.clear(); + m_end = &m_list[0]; + } + + // save state support & mame disasm + + constexpr const T *listptr() const { return &m_list[0]; } + constexpr std::size_t size() const noexcept { return m_list.size(); } + constexpr const T & operator[](const std::size_t index) const { return m_list[ 0 + index]; } + private: + using mutex_type = pspin_mutex; + using lock_guard_type = std::lock_guard; + + mutex_type m_lock; + std::vector m_list; + T *m_end; + + public: + // profiling + pperfcount_t m_prof_sortmove; + pperfcount_t m_prof_call; + pperfcount_t m_prof_remove; + pperfcount_t m_prof_retime; + }; + } // namespace plib #endif /* PLISTS_H_ */ diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h index 7a59097afe3..a4ac4fd393f 100644 --- a/src/lib/netlist/plib/pmempool.h +++ b/src/lib/netlist/plib/pmempool.h @@ -123,6 +123,12 @@ namespace plib { } } + static inline mempool &instance() + { + static mempool s_mempool; + return s_mempool; + } + void *allocate(size_t align, size_t size) { block *b = nullptr; @@ -220,6 +226,8 @@ namespace plib { } } + bool operator ==(const mempool &rhs) { return this == &rhs; } + }; } // namespace plib diff --git a/src/lib/netlist/plib/pparser.cpp b/src/lib/netlist/plib/pparser.cpp index 796a18d8d26..74d0b137829 100644 --- a/src/lib/netlist/plib/pparser.cpp +++ b/src/lib/netlist/plib/pparser.cpp @@ -261,8 +261,8 @@ ptokenizer::token_t ptokenizer::get_token_internal() ppreprocessor::ppreprocessor(defines_map_type *defines) : std::istream(new readbuffer(this)) -, m_ifflag(0) -, m_level(0) +, m_if_flag(0) +, m_if_level(0) , m_lineno(0) , m_pos(0) , m_state(PROCESS) @@ -473,34 +473,34 @@ pstring ppreprocessor::process_line(pstring line) std::vector lti(psplit(lt, " ", true)); if (lti[0] == "#if") { - m_level++; + m_if_level++; std::size_t start = 0; lt = replace_macros(lt); std::vector t(psplit(replace_all(lt.substr(3), " ", ""), m_expr_sep)); auto val = static_cast(expr(t, start, 255)); if (val == 0) - m_ifflag |= (1 << m_level); + m_if_flag |= (1 << m_if_level); } else if (lti[0] == "#ifdef") { - m_level++; + m_if_level++; if (get_define(lti[1]) == nullptr) - m_ifflag |= (1 << m_level); + m_if_flag |= (1 << m_if_level); } else if (lti[0] == "#ifndef") { - m_level++; + m_if_level++; if (get_define(lti[1]) != nullptr) - m_ifflag |= (1 << m_level); + m_if_flag |= (1 << m_if_level); } else if (lti[0] == "#else") { - m_ifflag ^= (1 << m_level); + m_if_flag ^= (1 << m_if_level); } else if (lti[0] == "#endif") { - m_ifflag &= ~(1 << m_level); - m_level--; + m_if_flag &= ~(1 << m_if_level); + m_if_level--; } else if (lti[0] == "#include") { @@ -508,7 +508,7 @@ pstring ppreprocessor::process_line(pstring line) } else if (lti[0] == "#pragma") { - if (m_ifflag == 0 && lti.size() > 3 && lti[1] == "NETLIST") + if (m_if_flag == 0 && lti.size() > 3 && lti[1] == "NETLIST") { if (lti[2] == "warning") error("NETLIST: " + catremainder(lti, 3, " ")); @@ -516,7 +516,7 @@ pstring ppreprocessor::process_line(pstring line) } else if (lti[0] == "#define") { - if (m_ifflag == 0) + if (m_if_flag == 0) { if (lti.size() < 2) error("PREPRO: define needs at least one argument: " + line); @@ -534,14 +534,14 @@ pstring ppreprocessor::process_line(pstring line) } else { - if (m_ifflag == 0) + if (m_if_flag == 0) error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(replace_macros(line))); } } else { lt = replace_macros(lt); - if (m_ifflag == 0) + if (m_if_flag == 0) ret += lt; } return ret; diff --git a/src/lib/netlist/plib/pparser.h b/src/lib/netlist/plib/pparser.h index 3d4f18b3eb1..5332ee2518c 100644 --- a/src/lib/netlist/plib/pparser.h +++ b/src/lib/netlist/plib/pparser.h @@ -190,7 +190,7 @@ public: { m_lineno++; line = process_line(line); - m_buf += decltype(m_buf)(line.c_str()) + static_cast(10); + m_outbuf += decltype(m_outbuf)(line.c_str()) + static_cast(10); } return *this; } @@ -202,10 +202,10 @@ public: : std::istream(new readbuffer(this)) , m_defines(std::move(s.m_defines)) , m_expr_sep(std::move(s.m_expr_sep)) - , m_ifflag(s.m_ifflag) - , m_level(s.m_level) + , m_if_flag(s.m_if_flag) + , m_if_level(s.m_if_level) , m_lineno(s.m_lineno) - , m_buf(std::move(s.m_buf)) + , m_outbuf(std::move(s.m_outbuf)) , m_pos(s.m_pos) , m_state(s.m_state) , m_comment(s.m_comment) @@ -225,15 +225,14 @@ protected: int_type underflow() override { - //printf("here\n"); if (this->gptr() == this->egptr()) { /* clang reports sign error - weird */ - std::size_t bytes = pstring_mem_t_size(m_strm->m_buf) - static_cast(m_strm->m_pos); + std::size_t bytes = pstring_mem_t_size(m_strm->m_outbuf) - static_cast(m_strm->m_pos); if (bytes > m_buf.size()) bytes = m_buf.size(); - std::copy(m_strm->m_buf.c_str() + m_strm->m_pos, m_strm->m_buf.c_str() + m_strm->m_pos + bytes, m_buf.data()); + std::copy(m_strm->m_outbuf.c_str() + m_strm->m_pos, m_strm->m_outbuf.c_str() + m_strm->m_pos + bytes, m_buf.data()); //printf("%ld\n", (long int)bytes); this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes); @@ -268,10 +267,10 @@ private: defines_map_type m_defines; std::vector m_expr_sep; - std::uint_least64_t m_ifflag; // 31 if levels - int m_level; + std::uint_least64_t m_if_flag; // 31 if levels + int m_if_level; int m_lineno; - pstring_t m_buf; + pstring_t m_outbuf; std::istream::pos_type m_pos; state_e m_state; pstring m_line; diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h index 4ff49911d63..035606bb984 100644 --- a/src/lib/netlist/plib/ppmf.h +++ b/src/lib/netlist/plib/ppmf.h @@ -15,24 +15,24 @@ /* * - * NL_PMF_TYPE_GNUC_PMF + * PMF_TYPE_GNUC_PMF * Use standard pointer to member function syntax C++11 * - * NL_PMF_TYPE_GNUC_PMF_CONV + * 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 + * 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% + * PMF_TYPE_INTERNAL: 215% 215% + * PMF_TYPE_GNUC_PMF: 163% 196% + * PMF_TYPE_GNUC_PMF_CONV: 215% 215% + * 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. diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp index 2eedc6b0371..359b61e247f 100644 --- a/src/lib/netlist/plib/pstring.cpp +++ b/src/lib/netlist/plib/pstring.cpp @@ -1,7 +1,7 @@ // license:GPL-2.0+ // copyright-holders:Couriersud /* - * nl_string.c + * pstring.cpp * */ diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h index c3c1c5fc7c6..adaa6a2b2fd 100644 --- a/src/lib/netlist/plib/ptypes.h +++ b/src/lib/netlist/plib/ptypes.h @@ -17,9 +17,9 @@ // noexcept on move operator -> issue with macosx clang #define COPYASSIGNMOVE(name, def) \ name(const name &) = def; \ - name(name &&) /*noexcept*/ = def; \ + name(name &&) noexcept = def; \ name &operator=(const name &) = def; \ - name &operator=(name &&) /*noexcept*/ = def; + name &operator=(name &&) noexcept = def; #define COPYASSIGN(name, def) \ name(const name &) = def; \ @@ -36,14 +36,14 @@ namespace plib template<> struct is_integral { static constexpr bool value = true; }; template<> struct numeric_limits { - static constexpr UINT128 max() + static constexpr UINT128 max() noexcept { return ~((UINT128)0); } }; template<> struct numeric_limits { - static constexpr INT128 max() + static constexpr INT128 max() noexcept { return (~((UINT128)0)) >> 1; } @@ -80,7 +80,7 @@ namespace plib // Avoid unused variable warnings //============================================================ template - inline void unused_var(Ts&&...) {} + inline void unused_var(Ts&&...) noexcept {} //============================================================ // is_pow2 @@ -100,7 +100,7 @@ namespace plib template constexpr typename std::enable_if::value && std::is_signed::value, T>::type - abs(T v) + abs(T v) noexcept { return v < 0 ? -v : v; } @@ -108,14 +108,14 @@ namespace plib template constexpr typename std::enable_if::value && std::is_unsigned::value, T>::type - abs(T v) + abs(T v) noexcept { return v; } template constexpr typename std::common_type::type - gcd(M m, N n) + gcd(M m, N n) noexcept { static_assert(std::is_integral::value, "gcd: M must be an integer"); static_assert(std::is_integral::value, "gcd: N must be an integer"); @@ -127,7 +127,7 @@ namespace plib template constexpr typename std::common_type::type - lcm(M m, N n) + lcm(M m, N n) noexcept { static_assert(std::is_integral::value, "lcm: M must be an integer"); static_assert(std::is_integral::value, "lcm: N must be an integer"); diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 0692824b97c..ad2432647ec 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -31,7 +31,6 @@ #pragma GCC optimize "ivopts" #endif -#include "netlist/nl_lists.h" #include "netlist/nl_factory.h" #include "nld_matrix_solver.h" #include "nld_ms_direct.h"