summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/pchrono.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/pchrono.h')
-rw-r--r--src/lib/netlist/plib/pchrono.h447
1 files changed, 243 insertions, 204 deletions
diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h
index 711e8908dfd..1c2e4b13057 100644
--- a/src/lib/netlist/plib/pchrono.h
+++ b/src/lib/netlist/plib/pchrono.h
@@ -1,239 +1,278 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
-/*
- * pchrono.h
- *
- */
#ifndef PCHRONO_H_
#define PCHRONO_H_
+///
+/// \file pchrono.h
+///
+
#include "pconfig.h"
+#include "pgsl.h"
#include "ptypes.h"
#include <chrono>
-//#include <cstdint>
namespace plib {
-namespace chrono {
- template <typename T>
- 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<std::chrono::high_resolution_clock>;
- using steady_ticks = sys_ticks<std::chrono::steady_clock>;
- using system_ticks = sys_ticks<std::chrono::system_clock>;
-
- #if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
-
- #if PHAS_RDTSCP
- struct fast_ticks
- {
- typedef int64_t type;
- static inline type start()
- {
- 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()
- {
- return start();
- }
- static type per_second();
- };
-
- #else
- struct fast_ticks
- {
- typedef int64_t type;
- static inline type start()
+ namespace chrono {
+ template <typename T>
+ struct sys_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()
+ using type = typename T::rep;
+ static constexpr type start() noexcept { return T::now().time_since_epoch().count(); }
+ static constexpr type stop() noexcept { return T::now().time_since_epoch().count(); }
+ static constexpr type per_second() noexcept { return T::period::den / T::period::num; }
+ };
+
+ using hires_ticks = sys_ticks<std::chrono::high_resolution_clock>;
+ using steady_ticks = sys_ticks<std::chrono::steady_clock>;
+ using system_ticks = sys_ticks<std::chrono::system_clock>;
+
+ #if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+
+ template <typename T, typename R>
+ struct base_ticks
{
- return start();
- }
- static type per_second();
- };
-
- #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
- {
- typedef int64_t type;
-
- static inline type start()
+ using ret_type = R;
+ static ret_type per_second() noexcept
+ {
+ static ret_type per_second = 0;
+ if (per_second == 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();
+ per_second = (ret_type)(double)((double) x * (double) system_ticks::per_second() / double (e - t));
+ }
+ return per_second;
+ }
+ };
+
+
+ #if PHAS_RDTSCP
+ struct fast_ticks : public base_ticks<fast_ticks, int64_t>
{
- 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()
+ 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<fast_ticks, int64_t>
{
- 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;
- }
-
- static type per_second();
- };
- #else
- using exact_ticks = fast_ticks;
- #endif
-
-
- #else
- using fast_ticks = hires_ticks;
- using exact_ticks = fast_ticks;
- #endif
-
- template<bool enabled_>
- 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<false>
- {
- 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
+ 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();
+ }
+ };
+
+ #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<exact_ticks, int64_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; }
+ 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
+
- COPYASSIGNMOVE(guard_t, default)
+ #else
+ using fast_ticks = hires_ticks;
+ using exact_ticks = fast_ticks;
+ #endif
+ template<bool enabled_>
+ struct counter
+ {
+ constexpr counter() : m_count(0) { }
+ using type = uint_least64_t;
+ constexpr type operator()() const noexcept { return m_count; }
+ constexpr void inc() noexcept { ++m_count; }
+ constexpr void reset() noexcept { m_count = 0; }
+ constexpr static bool enabled = enabled_;
private:
- timer &m_m;
+ type m_count;
};
- friend struct guard_t;
+ template<>
+ struct counter<false>
+ {
+ using type = uint_least64_t;
+ constexpr type operator()() const noexcept { return 0; }
+ constexpr void inc() const noexcept { }
+ constexpr void reset() const noexcept { }
+ 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 const bool enabled = enabled_;
+
+ struct guard_t
+ {
+ guard_t() = delete;
+ explicit constexpr guard_t(timer &m) noexcept : m_m(&m) { m_m->m_time -= T::start(); }
+ ~guard_t() noexcept { m_m->m_time += T::stop(); ++m_m->m_count; }
- timer() : m_time(0), m_count(0) { }
+ constexpr guard_t(const guard_t &) = default;
+ constexpr guard_t &operator=(const guard_t &) = default;
+ constexpr guard_t(guard_t &&) noexcept = default;
+ constexpr guard_t &operator=(guard_t &&) noexcept = default;
- type operator()() const { return m_time; }
+ private:
+ timer *m_m;
+ };
- 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; }
+ constexpr timer() : m_time(0), m_count(0) { }
- double as_seconds() const { return static_cast<double>(total())
- / static_cast<double>(T::per_second()); }
+ constexpr type operator()() const { return m_time; }
- guard_t guard() { return guard_t(*this); }
- private:
- type m_time;
- ctype m_count;
- };
+ constexpr void reset() noexcept { m_time = 0; m_count = 0; }
+ constexpr type average() const noexcept { return (m_count == 0) ? 0 : m_time / m_count; }
+ constexpr type total() const noexcept { return m_time; }
+ constexpr ctype count() const noexcept { return m_count; }
- template<typename T>
- struct timer<T, false>
- {
- using type = typename T::type;
- using ctype = uint_least64_t;
+ template <typename S>
+ constexpr S as_seconds() const noexcept { return narrow_cast<S>(total())
+ / narrow_cast<S>(T::per_second()); }
- struct guard_t
+ constexpr guard_t guard() noexcept { return guard_t(*this); }
+
+ void stop() noexcept { m_time += T::stop(); }
+ void start() noexcept { m_time -= T::start(); }
+
+
+ private:
+ type m_time;
+ ctype m_count;
+ };
+
+ template<typename T>
+ struct timer<T, false>
{
- 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 = typename T::type;
+ using ctype = uint_least64_t;
+
+ struct guard_t
+ {
+ constexpr guard_t() = default;
+
+ constexpr guard_t(const guard_t &) = default;
+ constexpr guard_t &operator=(const guard_t &) = default;
+ constexpr guard_t(guard_t &&) noexcept = default;
+ constexpr guard_t &operator=(guard_t &&) noexcept = default;
+
+ // using default constructor will trigger warning on
+ // unused local variable.
+
+ // NOLINTNEXTLINE(modernize-use-equals-default)
+ ~guard_t() noexcept { }
+ };
+
+ constexpr type operator()() const noexcept { return 0; }
+ void reset() const noexcept { }
+ constexpr type average() const noexcept { return 0; }
+ constexpr type total() const noexcept { return 0; }
+ constexpr ctype count() const noexcept { return 0; }
+ template <typename S>
+ constexpr S as_seconds() const noexcept { return narrow_cast<S>(0); }
+ constexpr static bool enabled = false;
+ guard_t guard() { return 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 <bool enabled_>
+ using pperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, enabled_>;
- } // namespace chrono
+ template <bool enabled_>
+ using pperfcount_t = plib::chrono::counter<enabled_>;
} // namespace plib
-#endif /* PCHRONO_H_ */
+#endif // PCHRONO_H_