diff options
Diffstat (limited to 'src/lib/netlist/plib')
-rw-r--r-- | src/lib/netlist/plib/pchrono.cpp | 55 | ||||
-rw-r--r-- | src/lib/netlist/plib/pchrono.h | 213 | ||||
-rw-r--r-- | src/lib/netlist/plib/pconfig.h | 43 | ||||
-rw-r--r-- | src/lib/netlist/plib/poptions.cpp | 226 | ||||
-rw-r--r-- | src/lib/netlist/plib/poptions.h | 176 | ||||
-rw-r--r-- | src/lib/netlist/plib/pstring.cpp | 2 |
6 files changed, 549 insertions, 166 deletions
diff --git a/src/lib/netlist/plib/pchrono.cpp b/src/lib/netlist/plib/pchrono.cpp new file mode 100644 index 00000000000..3beb3b2f161 --- /dev/null +++ b/src/lib/netlist/plib/pchrono.cpp @@ -0,0 +1,55 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud + +#include <chrono> + +#include "pchrono.h" + +namespace plib { +namespace chrono { + + +#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)) + +fast_ticks::type fast_ticks::per_second() +{ + static type persec = 0; + if (persec == 0) + { + type x = 0; + system_ticks::type t = system_ticks::start(); + system_ticks::type e; + x = -start(); + do { + e = system_ticks::stop(); + } while (e - t < system_ticks::per_second() / 100 ); + x += stop(); + persec = (type)(double)((double) x * (double) system_ticks::per_second() / double (e - t)); + } + return persec; +} + +#if PUSE_ACCURATE_STATS && PHAS_RDTSCP +exact_ticks::type exact_ticks::per_second() +{ + static type persec = 0; + if (persec == 0) + { + type x = 0; + system_ticks::type t = system_ticks::start(); + system_ticks::type e; + x = -start(); + do { + e = system_ticks::stop(); + } while (e - t < system_ticks::per_second() / 100 ); + x += stop(); + persec = (type)(double)((double) x * (double) system_ticks::per_second() / double (e - t)); + } + return persec; +} +#endif + +#endif + +} +} 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_ */ diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h index 48a7e740a8f..5c1582cdec8 100644 --- a/src/lib/netlist/plib/pconfig.h +++ b/src/lib/netlist/plib/pconfig.h @@ -12,9 +12,22 @@ #include <thread> #include <chrono> -#ifndef PSTANDALONE - #define PSTANDALONE (0) -#endif +/* + * Define this for more accurate measurements if you processor supports + * RDTSCP. + */ +#define PHAS_RDTSCP (1) + +/* + * Define this to use accurate timing measurements. Only works + * if PHAS_RDTSCP == 1 + */ +#define PUSE_ACCURATE_STATS (1) + +/* + * Set this to one if you want to use 128 bit int for ptime. + * This is for tests only. + */ #define PHAS_INT128 (0) @@ -75,30 +88,6 @@ typedef __int128_t INT128; namespace plib { -using ticks_t = int64_t; - -static inline ticks_t ticks() -{ - return std::chrono::high_resolution_clock::now().time_since_epoch().count(); -} -static inline ticks_t ticks_per_second() -{ - return std::chrono::high_resolution_clock::period::den / std::chrono::high_resolution_clock::period::num; -} - -#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)) - -static inline ticks_t profile_ticks() -{ - unsigned hi, lo; - __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); - return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); -} - -#else -static inline ticks_t profile_ticks() { return ticks(); } -#endif - /* * The following class was derived from the MAME delegate.h code. * It derives a pointer to a member function. diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp new file mode 100644 index 00000000000..8b2db8cf19e --- /dev/null +++ b/src/lib/netlist/plib/poptions.cpp @@ -0,0 +1,226 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * poptions.cpp + * + */ + +#include "poptions.h" + +namespace plib { + +/*************************************************************************** + Options +***************************************************************************/ + + option::option() + : m_short(""), m_long(""), m_help(""), m_has_argument(false) + {} + + option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument) + : m_short(ashort), m_long(along), m_help(help), m_has_argument(has_argument) + { + parent.register_option(this); + } + + option::~option() + { + } + + int option_str::parse(pstring argument) + { + m_val = argument; + return 0; + } + + int option_str_limit::parse(pstring argument) + { + if (plib::container::contains(m_limit, argument)) + { + m_val = argument; + return 0; + } + else + return 1; + } + + int option_bool::parse(ATTR_UNUSED pstring argument) + { + m_val = true; + return 0; + } + + int option_double::parse(pstring argument) + { + bool err = false; + m_val = argument.as_double(&err); + return (err ? 1 : 0); + } + + options::options() + { + + } + + options::options(option *o[]) + { + int i=0; + while (o[i] != nullptr) + { + m_opts.push_back(o[i]); + i++; + } + } + + options::~options() + { + m_opts.clear(); + } + + void options::register_option(option *opt) + { + m_opts.push_back(opt); + } + + int options::parse(int argc, char *argv[]) + { + m_app = argv[0]; + + for (int i=1; i<argc; ) + { + pstring arg(argv[i]); + option *opt = nullptr; + pstring opt_arg; + bool has_equal_arg = false; + + if (arg.startsWith("--")) + { + auto v = pstring_vector_t(arg.substr(2),"="); + opt = getopt_long(v[0]); + has_equal_arg = (v.size() > 1); + if (has_equal_arg) opt_arg = v[1]; + } + else if (arg.startsWith("-")) + { + opt = getopt_short(arg.substr(1)); + } + else + return i; + if (opt == nullptr) + return i; + if (opt->has_argument()) + { + if (has_equal_arg) + { + if (opt->parse(opt_arg) != 0) + return i; + } + else + { + i++; // FIXME: are there more arguments? + if (opt->parse(argv[i]) != 0) + return i - 1; + } + } + else + { + if (has_equal_arg) + return i; + opt->parse(""); + } + i++; + } + return argc; + } + + pstring options::split_paragraphs(pstring text, unsigned width, unsigned ident, + unsigned firstline_ident) + { + auto paragraphs = pstring_vector_t(text,"\n"); + pstring ret(""); + + for (auto &p : paragraphs) + { + pstring line = pstring("").rpad(" ", firstline_ident); + for (auto &s : pstring_vector_t(p, " ")) + { + if (line.len() + s.len() > width) + { + ret += line + "\n"; + line = pstring("").rpad(" ", ident); + } + line += s + " "; + } + ret += line + "\n"; + } + return ret; + } + + pstring options::help(pstring description, pstring usage, + unsigned width, unsigned ident) + { + pstring ret; + + ret = split_paragraphs(description, width, 0, 0) + "\n"; + ret += "Usage:\t" + usage + "\n\nOptions:\n"; + + for (auto & opt : m_opts ) + { + pstring line = ""; + if (opt->short_opt() != "") + line += " -" + opt->short_opt(); + if (opt->long_opt() != "") + { + if (line != "") + line += ", "; + else + line = " "; + line += "--" + opt->long_opt(); + if (opt->has_argument()) + { + line += "="; + option_str_limit *ol = dynamic_cast<option_str_limit *>(opt); + if (ol) + { + for (auto &v : ol->limit()) + { + line += v + "|"; + } + line = line.left(line.len() - 1); + } + else + line += "Value"; + } + } + line = line.rpad(" ", 20) + " "; + if (line.len() > 21) + { + ret += line + "\n"; + ret += split_paragraphs(opt->help(), 72, 21, 21); + } + else + ret += split_paragraphs(line + opt->help(), 72, 21, 0); + } + return ret; + } + + option *options::getopt_short(pstring arg) + { + for (auto & opt : m_opts) + { + if (opt->short_opt() == arg) + return opt; + } + return nullptr; + } + option *options::getopt_long(pstring arg) + { + for (auto & opt : m_opts) + { + if (opt->long_opt() == arg) + return opt; + } + return nullptr; + } + +} // namespace plib diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h index 3ab1adb78c6..6ddac682d66 100644 --- a/src/lib/netlist/plib/poptions.h +++ b/src/lib/netlist/plib/poptions.h @@ -27,35 +27,34 @@ class options; class option { public: - option() - : m_short(""), m_long(""), m_help(""), m_has_argument(false) - {} - - option(pstring ashort, pstring along, pstring help, bool has_argument, options *parent = nullptr); + option(); + option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument); - virtual ~option() - { - } + virtual ~option(); /* no_argument options will be called with "" argument */ - virtual int parse(ATTR_UNUSED pstring argument) { return 0; } + virtual int parse(ATTR_UNUSED pstring argument) = 0; + pstring short_opt() { return m_short; } + pstring long_opt() { return m_long; } + pstring help() { return m_help; } + bool has_argument() { return m_has_argument ; } +private: pstring m_short; pstring m_long; pstring m_help; bool m_has_argument; -private: }; class option_str : public option { public: - option_str(pstring ashort, pstring along, pstring defval, pstring help, options *parent = nullptr) - : option(ashort, along, help, true, parent), m_val(defval) + option_str(options &parent, pstring ashort, pstring along, pstring defval, pstring help) + : option(parent, ashort, along, help, true), m_val(defval) {} - virtual int parse(pstring argument) override { m_val = argument; return 0; } + virtual int parse(pstring argument) override; pstring operator ()() { return m_val; } private: @@ -65,22 +64,15 @@ private: class option_str_limit : public option { public: - option_str_limit(pstring ashort, pstring along, pstring defval, pstring limit, pstring help, options *parent = nullptr) - : option(ashort, along, help, true, parent), m_val(defval), m_limit(limit, ":") + option_str_limit(options &parent, pstring ashort, pstring along, pstring defval, pstring limit, pstring help) + : option(parent, ashort, along, help, true), m_val(defval), m_limit(limit, ":") {} - virtual int parse(pstring argument) override - { - if (plib::container::contains(m_limit, argument)) - { - m_val = argument; - return 0; - } - else - return 1; - } + virtual int parse(pstring argument) override; pstring operator ()() { return m_val; } + const plib::pstring_vector_t &limit() { return m_limit; } + private: pstring m_val; plib::pstring_vector_t m_limit; @@ -89,11 +81,11 @@ private: class option_bool : public option { public: - option_bool(pstring ashort, pstring along, pstring help, options *parent = nullptr) - : option(ashort, along, help, false, parent), m_val(false) + option_bool(options &parent, pstring ashort, pstring along, pstring help) + : option(parent, ashort, along, help, false), m_val(false) {} - virtual int parse(ATTR_UNUSED pstring argument) override { m_val = true; return 0; } + virtual int parse(ATTR_UNUSED pstring argument) override; bool operator ()() { return m_val; } private: @@ -103,16 +95,11 @@ private: class option_double : public option { public: - option_double(pstring ashort, pstring along, double defval, pstring help, options *parent = nullptr) - : option(ashort, along, help, true, parent), m_val(defval) + option_double(options &parent, pstring ashort, pstring along, double defval, pstring help) + : option(parent, ashort, along, help, true), m_val(defval) {} - virtual int parse(pstring argument) override - { - bool err = false; - m_val = argument.as_double(&err); - return (err ? 1 : 0); - } + virtual int parse(pstring argument) override; double operator ()() { return m_val; } private: @@ -123,117 +110,30 @@ class options { public: - options() {} - - options(option *o[]) - { - int i=0; - while (o[i] != nullptr) - { - m_opts.push_back(o[i]); - i++; - } - } - - ~options() - { - m_opts.clear(); - } - - void register_option(option *opt) - { - m_opts.push_back(opt); - } - - int parse(int argc, char *argv[]) - { - m_app = argv[0]; - - for (int i=1; i<argc; ) - { - pstring arg(argv[i]); - option *opt = nullptr; - - if (arg.startsWith("--")) - { - opt = getopt_long(arg.substr(2)); - } - else if (arg.startsWith("-")) - { - opt = getopt_short(arg.substr(1)); - } - else - return i; - if (opt == nullptr) - return i; - if (opt->m_has_argument) - { - i++; // FIXME: are there more arguments? - if (opt->parse(argv[i]) != 0) - return i - 1; - } - else - opt->parse(""); - i++; - } - return argc; - } - - pstring help() - { - pstring ret; - - for (auto & opt : m_opts ) - { - pstring line = ""; - if (opt->m_short != "") - line += " -" + opt->m_short; - if (opt->m_long != "") - { - if (line != "") - line += ", "; - else - line = " "; - line += "--" + opt->m_long; - } - line = line.rpad(" ", 20).cat(opt->m_help); - ret = ret + line + "\n"; - } - return ret; - } + options(); + options(option *o[]); + + ~options(); + + void register_option(option *opt); + int parse(int argc, char *argv[]); + + pstring help(pstring description, pstring usage, + unsigned width = 72, unsigned ident = 20); + pstring app() { return m_app; } private: + static pstring split_paragraphs(pstring text, unsigned width, unsigned ident, + unsigned firstline_ident); - option *getopt_short(pstring arg) - { - for (auto & opt : m_opts) - { - if (opt->m_short == arg) - return opt; - } - return nullptr; - } - option *getopt_long(pstring arg) - { - for (auto & opt : m_opts) - { - if (opt->m_long == arg) - return opt; - } - return nullptr; - } + option *getopt_short(pstring arg); + option *getopt_long(pstring arg); std::vector<option *> m_opts; pstring m_app; }; -option::option(pstring ashort, pstring along, pstring help, bool has_argument, options *parent) -: m_short(ashort), m_long(along), m_help(help), m_has_argument(has_argument) -{ - if (parent != nullptr) - parent->register_option(this); -} } diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp index f6dff95fb12..20573f5bfa5 100644 --- a/src/lib/netlist/plib/pstring.cpp +++ b/src/lib/netlist/plib/pstring.cpp @@ -258,7 +258,7 @@ const pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const unsigned cnt) c pstring_t ret(*this); while (ret.len() < cnt) ret += ws; - return pstring_t(ret).substr(0, cnt); + return ret; } |