summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2017-02-15 01:01:04 +0100
committer couriersud <couriersud@gmx.org>2017-02-15 01:01:51 +0100
commitcc39da9c83b3a130d160d351e63e9cbde3afea9d (patch)
tree7ebee2f931b76520e69abe91910b1760b5e5143f /src/lib/netlist
parent74e690d654b64cf57e0491d9ae3ed6ae72623ff3 (diff)
Added state saving and loading to nltool.
First step towards regression and unit tests. (nw)
Diffstat (limited to 'src/lib/netlist')
-rw-r--r--src/lib/netlist/plib/poptions.cpp9
-rw-r--r--src/lib/netlist/plib/poptions.h39
-rw-r--r--src/lib/netlist/plib/pstream.h72
-rw-r--r--src/lib/netlist/prg/nltool.cpp89
4 files changed, 183 insertions, 26 deletions
diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp
index fc2793c40f3..9defcf84975 100644
--- a/src/lib/netlist/plib/poptions.cpp
+++ b/src/lib/netlist/plib/poptions.cpp
@@ -31,7 +31,8 @@ namespace plib {
}
option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument)
- : option_base(parent, help), m_short(ashort), m_long(along), m_has_argument(has_argument)
+ : option_base(parent, help), m_short(ashort), m_long(along),
+ m_has_argument(has_argument), m_specified(false)
{
}
@@ -149,13 +150,13 @@ namespace plib {
{
if (has_equal_arg)
{
- if (opt->parse(opt_arg) != 0)
+ if (opt->do_parse(opt_arg) != 0)
return i;
}
else
{
i++; // FIXME: are there more arguments?
- if (opt->parse(pstring(argv[i], pstring::UTF8)) != 0)
+ if (opt->do_parse(pstring(argv[i], pstring::UTF8)) != 0)
return i - 1;
}
}
@@ -163,7 +164,7 @@ namespace plib {
{
if (has_equal_arg)
return i;
- opt->parse("");
+ opt->do_parse("");
}
i++;
}
diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h
index 221a7fa2c8a..6f80938167f 100644
--- a/src/lib/netlist/plib/poptions.h
+++ b/src/lib/netlist/plib/poptions.h
@@ -65,15 +65,25 @@ public:
/* no_argument options will be called with "" argument */
- virtual int parse(const pstring &argument) = 0;
-
pstring short_opt() { return m_short; }
pstring long_opt() { return m_long; }
bool has_argument() { return m_has_argument ; }
+ bool was_specified() { return m_specified; }
+
+ int do_parse(const pstring &argument)
+ {
+ m_specified = true;
+ return parse(argument);
+ }
+
+protected:
+ virtual int parse(const pstring &argument) = 0;
+
private:
pstring m_short;
pstring m_long;
bool m_has_argument;
+ bool m_specified;
};
class option_str : public option
@@ -83,9 +93,11 @@ public:
: option(parent, ashort, along, help, true), m_val(defval)
{}
+ pstring operator ()() { return m_val; }
+
+protected:
virtual int parse(const pstring &argument) override;
- pstring operator ()() { return m_val; }
private:
pstring m_val;
};
@@ -99,11 +111,12 @@ public:
m_limit = plib::psplit(limit, ":");
}
- virtual int parse(const pstring &argument) override;
-
pstring operator ()() { return m_val; }
const std::vector<pstring> &limit() { return m_limit; }
+protected:
+ virtual int parse(const pstring &argument) override;
+
private:
pstring m_val;
std::vector<pstring> m_limit;
@@ -116,9 +129,11 @@ public:
: option(parent, ashort, along, help, false), m_val(false)
{}
+ bool operator ()() { return m_val; }
+
+protected:
virtual int parse(const pstring &argument) override;
- bool operator ()() { return m_val; }
private:
bool m_val;
};
@@ -130,9 +145,11 @@ public:
: option(parent, ashort, along, help, true), m_val(defval)
{}
+ double operator ()() { return m_val; }
+
+protected:
virtual int parse(const pstring &argument) override;
- double operator ()() { return m_val; }
private:
double m_val;
};
@@ -144,9 +161,11 @@ public:
: option(parent, ashort, along, help, true), m_val(defval)
{}
+ long operator ()() { return m_val; }
+
+protected:
virtual int parse(const pstring &argument) override;
- long operator ()() { return m_val; }
private:
long m_val;
};
@@ -158,9 +177,11 @@ public:
: option(parent, ashort, along, help, true)
{}
+ std::vector<pstring> operator ()() { return m_val; }
+
+protected:
virtual int parse(const pstring &argument) override;
- std::vector<pstring> operator ()() { return m_val; }
private:
std::vector<pstring> m_val;
};
diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h
index 83c514da2e1..10b2e9a82a5 100644
--- a/src/lib/netlist/plib/pstream.h
+++ b/src/lib/netlist/plib/pstream.h
@@ -12,6 +12,8 @@
#include "pfmtlog.h"
#include "pexception.h"
+#include <vector>
+
namespace plib {
// -----------------------------------------------------------------------------
// pstream: things common to all streams
@@ -371,6 +373,76 @@ protected:
private:
};
+// -----------------------------------------------------------------------------
+// pbinary_writer_t: writer on top of ostream
+// -----------------------------------------------------------------------------
+
+class pbinary_writer : plib::nocopyassignmove
+{
+public:
+ explicit pbinary_writer(postream &strm) : m_strm(strm) {}
+ virtual ~pbinary_writer() {}
+
+ template <typename T>
+ void write(const T val)
+ {
+ m_strm.write(&val, sizeof(T));
+ }
+
+ void write(const pstring s)
+ {
+ write(s.blen());
+ m_strm.write(s.c_str(), s.blen());
+ }
+
+ template <typename T>
+ void write(const std::vector<T> val)
+ {
+ std::size_t sz = val.size();
+ write(sz);
+ m_strm.write(val.data(), sizeof(T) * sz);
+ }
+
+private:
+ postream &m_strm;
+};
+
+class pbinary_reader : plib::nocopyassignmove
+{
+public:
+ explicit pbinary_reader(pistream &strm) : m_strm(strm) {}
+ virtual ~pbinary_reader() {}
+
+ template <typename T>
+ void read(T &val)
+ {
+ m_strm.read(&val, sizeof(T));
+ }
+
+ void read( pstring &s)
+ {
+ std::size_t sz = 0;
+ read(sz);
+ pstring::mem_t *buf = new pstring::mem_t[sz+1];
+ m_strm.read(buf, sz);
+ buf[sz] = 0;
+ s = pstring(buf, pstring::UTF8);
+ delete [] buf;
+ }
+
+ template <typename T>
+ void read(std::vector<T> &val)
+ {
+ std::size_t sz = 0;
+ read(sz);
+ val.resize(sz);
+ m_strm.read(val.data(), sizeof(T) * sz);
+ }
+
+private:
+ pistream &m_strm;
+};
+
}
#endif /* PSTREAM_H_ */
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index c3cd8edc842..b0e8112b9f5 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -26,7 +26,7 @@ public:
opt_cmd (*this, "c", "cmd", "run", "run:convert:listdevices:static:header:docheader", "run|convert|listdevices|static|header"),
opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
opt_defines(*this, "D", "define", "predefine value as macro, e.g. -Dname=value. If '=value' is omitted predefine it as 1. This option may be specified repeatedly."),
- opt_rfolders(*this, "r", "rom", "where to look for files"),
+ opt_rfolders(*this, "r", "rom", "where to look for data files"),
opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
opt_quiet(*this, "q", "quiet", "be quiet - no warnings"),
opt_version(*this, "", "version", "display version and exit"),
@@ -37,6 +37,8 @@ public:
opt_ttr (*this, "t", "time_to_run", 1.0, "time to run the emulation (seconds)"),
opt_logs(*this, "l", "log" , "define terminal to log. This option may be specified repeatedly."),
opt_inp(*this, "i", "input", "", "input file to process (default is none)"),
+ opt_loadstate(*this,"", "loadstate", "", "load state from file and continue from there"),
+ opt_savestate(*this,"", "savestate", "", "save state to file at end of run"),
opt_grp4(*this, "Options for convert command", "These options are only used by the convert command."),
opt_type(*this, "y", "type", "spice", "spice:eagle:rinf", "type of file to be converted: spice,eagle,rinf"),
@@ -61,6 +63,8 @@ public:
plib::option_double opt_ttr;
plib::option_vec opt_logs;
plib::option_str opt_inp;
+ plib::option_str opt_loadstate;
+ plib::option_str opt_savestate;
plib::option_group opt_grp4;
plib::option_str_limit opt_type;
plib::option_example opt_ex1;
@@ -179,15 +183,16 @@ public:
}
}
- void save_state()
+ template<typename T>
+ std::vector<T> save_state()
{
state().pre_save();
std::size_t size = 0;
for (auto const & s : state().save_list())
- size += ((s->m_dt.size * s->m_count + sizeof(unsigned) - 1) / sizeof(unsigned));
+ size += ((s->m_dt.size * s->m_count + sizeof(T) - 1) / sizeof(T));
- auto buf = plib::palloc_array<unsigned>(size);
- auto p = buf;
+ auto buf = std::vector<T>(size);
+ auto p = buf.data();
for (auto const & s : state().save_list())
{
@@ -196,8 +201,34 @@ public:
std::memcpy(p, s->m_ptr, sz );
else
log().fatal("found unsupported save element {1}\n", s->m_name);
- p += ((sz + sizeof(unsigned) - 1) / sizeof(unsigned));
+ p += ((sz + sizeof(T) - 1) / sizeof(T));
}
+ return buf;
+ }
+
+ template<typename T>
+ void load_state(std::vector<T> &buf)
+ {
+ std::size_t size = 0;
+ for (auto const & s : state().save_list())
+ size += ((s->m_dt.size * s->m_count + sizeof(T) - 1) / sizeof(T));
+
+ if (buf.size() != size)
+ throw netlist::nl_exception("Size different during load state.");
+
+ auto p = buf.data();
+
+ for (auto const & s : state().save_list())
+ {
+ std::size_t sz = s->m_dt.size * s->m_count;
+ if (s->m_dt.is_float || s->m_dt.is_integral)
+ std::memcpy(s->m_ptr, p, sz );
+ else
+ log().fatal("found unsupported save element {1}\n", s->m_name);
+ p += ((sz + sizeof(T) - 1) / sizeof(T));
+ }
+ state().post_load();
+ rebuild_lists();
}
protected:
@@ -295,33 +326,65 @@ void tool_app_t::run()
std::vector<input_t> inps = read_input(nt.setup(), opt_inp());
- double ttr = opt_ttr();
+ netlist::netlist_time ttr = netlist::netlist_time::from_double(opt_ttr());
t.stop();
pout("startup time ==> {1:5.3f}\n", t.as_seconds() );
- pout("runnning ...\n");
t.reset();
t.start();
+ // FIXME: error handling
+ if (opt_loadstate.was_specified())
+ {
+ plib::pifilestream strm(opt_loadstate());
+ plib::pbinary_reader reader(strm);
+ std::vector<char> loadstate;
+ reader.read(loadstate);
+ nt.load_state(loadstate);
+ pout("Loaded state, run will continue at {1:.6f}\n", nt.time().as_double());
+ }
+
unsigned pos = 0;
- netlist::netlist_time nlt = netlist::netlist_time::zero();
+ netlist::netlist_time nlt = nt.time();
- while (pos < inps.size() && inps[pos].m_time < netlist::netlist_time::from_double(ttr))
+
+ while (pos < inps.size()
+ && inps[pos].m_time < ttr
+ && inps[pos].m_time >= nlt)
{
nt.process_queue(inps[pos].m_time - nlt);
inps[pos].setparam();
nlt = inps[pos].m_time;
pos++;
}
- nt.process_queue(netlist::netlist_time::from_double(ttr) - nlt);
- nt.save_state();
+
+ pout("runnning ...\n");
+
+ if (ttr > nlt)
+ nt.process_queue(ttr - nlt);
+ else
+ {
+ pout("end time {1:.6f} less than saved time {2:.6f}\n",
+ ttr.as_double(), nlt.as_double());
+ ttr = nlt;
+ }
+
+ if (opt_savestate.was_specified())
+ {
+ auto savestate = nt.save_state<char>();
+ plib::pofilestream strm(opt_savestate());
+ plib::pbinary_writer writer(strm);
+ writer.write(savestate);
+ }
nt.stop();
t.stop();
double emutime = t.as_seconds();
- pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n", ttr, emutime, ttr/emutime*100.0);
+ pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n",
+ (ttr - nlt).as_double(), emutime,
+ (ttr - nlt).as_double() / emutime * 100.0);
}
void tool_app_t::static_compile()