diff --git a/bus.cpp b/bus.cpp index c69d1dd..3af1f5f 100644 --- a/bus.cpp +++ b/bus.cpp @@ -43,7 +43,7 @@ bus::~bus() } #if IS_POSIX -json_t *bus::serialize() +json_t *bus::serialize() const { json_t *j_out = json_object(); @@ -59,12 +59,15 @@ json_t *bus::serialize() if (mmu_) json_object_set(j_out, "mmu", mmu_->serialize()); - // TODO: cpu, rl02, rk05, tm11 + if (c) + json_object_set(j_out, "cpu", c->serialize()); + + // TODO: rl02, rk05, tm11 return j_out; } -bus *bus::deserialize(const json_t *const j, console *const cnsl) +bus *bus::deserialize(const json_t *const j, console *const cnsl, std::atomic_uint32_t *const event) { bus *b = new bus(); @@ -94,7 +97,13 @@ bus *bus::deserialize(const json_t *const j, console *const cnsl) b->add_mmu(mmu_); } - // TODO: mmu, cpu, rl02, rk05, tm11 + temp = json_object_get(j, "cpu"); + if (temp) { + cpu *cpu_ = cpu::deserialize(temp, b, event); + b->add_cpu(cpu_); + } + + // TODO: rl02, rk05, tm11 return b; } diff --git a/bus.h b/bus.h index d1312ba..b0ae4c8 100644 --- a/bus.h +++ b/bus.h @@ -91,8 +91,8 @@ public: ~bus(); #if IS_POSIX - json_t *serialize(); - static bus *deserialize(const json_t *const j, console *const cnsl); + json_t *serialize() const; + static bus *deserialize(const json_t *const j, console *const cnsl, std::atomic_uint32_t *const event); #endif void reset(); diff --git a/cpu.cpp b/cpu.cpp index d5e9582..8f55edd 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -2395,3 +2395,66 @@ void cpu::step() DOLOG(debug, false, "bus-trap during execution of command (%d)", exception_nr); } } + +#if IS_POSIX +json_t *cpu::serialize() +{ + json_t *j = json_object(); + + for(int set=0; set<2; set++) { + for(int regnr=0; regnr<6; regnr++) + json_object_set(j, format("register-%d-%d", set, regnr).c_str(), json_integer(regs0_5[set][regnr])); + } + + for(int spnr=0; spnr<4; spnr++) + json_object_set(j, format("sp-%d", spnr).c_str(), json_integer(sp[spnr])); + + json_object_set(j, "pc", json_integer(pc)); + json_object_set(j, "instruction_start", json_integer(instruction_start)); + json_object_set(j, "psw", json_integer(psw)); + json_object_set(j, "fpsr", json_integer(fpsr)); + json_object_set(j, "stackLimitRegister", json_integer(stackLimitRegister)); + json_object_set(j, "processing_trap_depth", json_integer(processing_trap_depth)); + json_object_set(j, "instruction_count", json_integer(instruction_count)); + json_object_set(j, "running_since", json_integer(running_since)); + json_object_set(j, "wait_time", json_integer(wait_time)); + json_object_set(j, "it_is_a_trap", json_boolean(it_is_a_trap)); + json_object_set(j, "debug_mode", json_boolean(debug_mode)); + if (trap_delay.has_value()) + json_object_set(j, "trap_delay", json_integer(trap_delay.value())); + + return j; +} + +cpu *cpu::deserialize(const json_t *const j, bus *const b, std::atomic_uint32_t *const event) +{ + cpu *c = new cpu(b, event); + + for(int set=0; set<2; set++) { + for(int regnr=0; regnr<6; regnr++) + c->regs0_5[set][regnr] = json_integer_value(json_object_get(j, format("register-%d-%d", set, regnr).c_str())); + } + + for(int spnr=0; spnr<4; spnr++) + c->sp[spnr] = json_integer_value(json_object_get(j, format("sp-%d", spnr).c_str())); + + c->pc = json_integer_value(json_object_get(j, "pc")); + c->instruction_start = json_integer_value(json_object_get(j, "instruction_start")); + c->psw = json_integer_value(json_object_get(j, "psw")); + c->fpsr = json_integer_value(json_object_get(j, "fpsr")); + c->stackLimitRegister = json_integer_value(json_object_get(j, "stackLimitRegister")); + c->processing_trap_depth = json_integer_value(json_object_get(j, "processing_trap_depth")); + c->instruction_count = json_integer_value(json_object_get(j, "instruction_count")); + c->running_since = get_us(); + c->wait_time = 0; + c->it_is_a_trap = json_boolean_value(json_object_get(j, "it_is_a_trap")); + c->debug_mode = json_boolean_value(json_object_get(j, "debug_mode")); + json_t *temp = json_object_get(j, "trap_delay"); + if (temp) + c->trap_delay = json_integer_value(temp); + else + c->trap_delay.reset(); + + return c; +} +#endif diff --git a/cpu.h b/cpu.h index c968ca2..e5aeab4 100644 --- a/cpu.h +++ b/cpu.h @@ -14,6 +14,7 @@ #include "breakpoint.h" #include "bus.h" +#include "gen.h" constexpr const int initial_trap_delay = 8; @@ -111,6 +112,11 @@ public: explicit cpu(bus *const b, std::atomic_uint32_t *const event); ~cpu(); +#if IS_POSIX + json_t *serialize(); + static cpu *deserialize(const json_t *const j, bus *const b, std::atomic_uint32_t *const event); +#endif + std::optional check_breakpoint(); int set_breakpoint(breakpoint *const bp); bool remove_breakpoint(const int bp_id); diff --git a/debugger.cpp b/debugger.cpp index 7c50e2c..378f75c 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -722,6 +722,25 @@ void show_queued_interrupts(console *const cnsl, cpu *const c) } } +void serialize_state(console *const cnsl, const bus *const b, const std::string & filename) +{ + json_t *j = b->serialize(); + + bool ok = false; + + FILE *fh = fopen(filename.c_str(), "w"); + if (fh) { + if (json_dumpf(j, fh, 0) == 0) + ok = true; + + fclose(fh); + } + + json_decref(j); + + cnsl->put_string_lf(format("Serialize to %s: %s", filename.c_str(), ok ? "OK" : "failed")); +} + void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const stop_event, const bool tracing_in) { int32_t trace_start_addr = -1; @@ -1069,6 +1088,10 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto continue; } + else if (parts[0] == "ser" && parts.size() == 2) { + serialize_state(cnsl, b, parts.at(1)); + continue; + } else if (parts[0] == "setsl" && parts.size() == 3) { setloghost(parts.at(1).c_str(), parse_ll(parts[2])); @@ -1130,6 +1153,10 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto "stats - show run statistics", "ramsize - set ram size (page count (8 kB))", "bl - set bootload (rl02 or rk05)", +#if IS_POSIX + "ser - serialize state to a file", + "dser - deserialize state from a file", +#endif #if defined(ESP32) "cfgnet - configure network (e.g. WiFi)", "startnet - start network", diff --git a/memory.cpp b/memory.cpp index 9761814..ed6b3f5 100644 --- a/memory.cpp +++ b/memory.cpp @@ -29,7 +29,7 @@ void memory::reset() } #if IS_POSIX -json_t *memory::serialize() +json_t *memory::serialize() const { json_t *j = json_object(); @@ -50,7 +50,7 @@ memory *memory::deserialize(const json_t *const j) json_t *ja = json_object_get(j, "contents"); for(size_t i=0; iwriteByte(i, json_integer_value(json_array_get(ja, i))); + m->m[i] = json_integer_value(json_array_get(ja, i)); return m; } diff --git a/memory.h b/memory.h index 265b805..1a5dcbc 100644 --- a/memory.h +++ b/memory.h @@ -20,7 +20,7 @@ public: void reset(); #if IS_POSIX - json_t *serialize(); + json_t *serialize() const; static memory *deserialize(const json_t *const j); #endif diff --git a/mmu.cpp b/mmu.cpp index f3eaa7e..5e42949 100644 --- a/mmu.cpp +++ b/mmu.cpp @@ -222,7 +222,7 @@ void mmu::writeByte(const uint16_t a, const uint8_t value) } #if IS_POSIX -void mmu::add_par_pdr(json_t *const target, const int run_mode, const bool is_d, const std::string & name) +void mmu::add_par_pdr(json_t *const target, const int run_mode, const bool is_d, const std::string & name) const { json_t *j = json_object(); @@ -239,7 +239,7 @@ void mmu::add_par_pdr(json_t *const target, const int run_mode, const bool is_d, json_object_set(target, name.c_str(), j); } -json_t *mmu::serialize() +json_t *mmu::serialize() const { json_t *j = json_object(); diff --git a/mmu.h b/mmu.h index 3a80c0b..e78a5da 100644 --- a/mmu.h +++ b/mmu.h @@ -41,7 +41,7 @@ private: uint16_t PIR { 0 }; uint16_t CSR { 0 }; - void add_par_pdr(json_t *const target, const int run_mode, const bool is_d, const std::string & name); + void add_par_pdr(json_t *const target, const int run_mode, const bool is_d, const std::string & name) const; void set_par_pdr(const json_t *const j_in, const int run_mode, const bool is_d, const std::string & name); public: @@ -49,7 +49,7 @@ public: virtual ~mmu(); #if IS_POSIX - json_t *serialize(); + json_t *serialize() const; static mmu *deserialize(const json_t *const j); #endif