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.h213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h
new file mode 100644
index 00000000000..805842007f2
--- /dev/null
+++ b/src/lib/netlist/plib/pchrono.h
@@ -0,0 +1,213 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * pchrono.h
+ *
+ */
+
+#ifndef PCHRONO_H_
+#define PCHRONO_H_
+
+#include <cstdint>
+#include <thread>
+#include <chrono>
+
+#include "pconfig.h"
+
+namespace plib {
+namespace chrono {
+ template <typename T>
+ struct sys_ticks
+ {
+ typedef typename T::rep type;
+ 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()
+ {
+ int64_t v;
+ __asm__ __volatile__ (
+ "rdtsc;"
+ "shl $32, %%rdx;"
+ "or %%rdx, %%rax;"
+ : "=a"(v) /* outputs */
+ : /* inputs */
+ : "%rdx" /* clobbers */
+ );
+ return v;
+ }
+ static inline type stop()
+ {
+ 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()
+ {
+ 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;
+ }
+
+ 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) { }
+ typedef uint_least64_t type;
+ 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>
+ {
+ typedef uint_least64_t type;
+ 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
+ {
+ typedef typename T::type type;
+ typedef uint_least64_t ctype;
+
+ timer() : m_time(0), m_count(0) { }
+
+ type operator()() const { return m_time; }
+
+ void start() { m_time -= T::start(); }
+ void stop() { m_time += T::stop(); ++m_count; }
+ 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 (double) total() / (double) T::per_second(); }
+
+ constexpr static bool enabled = enabled_;
+ private:
+ type m_time;
+ ctype m_count;
+ };
+
+ template<typename T>
+ struct timer<T, false>
+ {
+ typedef typename T::type type;
+ typedef uint_least64_t ctype;
+ constexpr type operator()() const { return 0; }
+ void start() const { }
+ void stop() const { }
+ 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;
+ };
+
+ } // namespace chrono
+} // namespace plib
+
+#endif /* PCHRONO_H_ */