summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib')
-rw-r--r--src/lib/netlist/plib/pchrono.cpp55
-rw-r--r--src/lib/netlist/plib/pchrono.h213
-rw-r--r--src/lib/netlist/plib/pconfig.h43
-rw-r--r--src/lib/netlist/plib/poptions.cpp226
-rw-r--r--src/lib/netlist/plib/poptions.h176
-rw-r--r--src/lib/netlist/plib/pstring.cpp2
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;
}