提交 a3838d2b 编写于 作者: J JinYue

recover snapshot function

上级 3a3a0d80
...@@ -123,7 +123,7 @@ Emulator::Emulator(int argc, const char *argv[]): ...@@ -123,7 +123,7 @@ Emulator::Emulator(int argc, const char *argv[]):
// init ram // init ram
init_ram(args.image); init_ram(args.image);
#if (VM_TRACE == 1) #if VM_TRACE == 1
#ifndef EN_FORKWAIT #ifndef EN_FORKWAIT
enable_waveform = args.enable_waveform; enable_waveform = args.enable_waveform;
if (enable_waveform) { if (enable_waveform) {
...@@ -142,6 +142,14 @@ Emulator::Emulator(int argc, const char *argv[]): ...@@ -142,6 +142,14 @@ Emulator::Emulator(int argc, const char *argv[]):
enable_waveform = false; enable_waveform = false;
#endif #endif
#ifdef VM_SAVABLE
if (args.snapshot_path != NULL) {
printf("loading from snapshot `%s`...\n", args.snapshot_path);
snapshot_load(args.snapshot_path);
printf("model cycleCnt = %" PRIu64 "\n", dut_ptr->io_trap_cycleCnt);
}
#endif
// set log time range and log level // set log time range and log level
dut_ptr->io_logCtrl_log_begin = args.log_begin; dut_ptr->io_logCtrl_log_begin = args.log_begin;
dut_ptr->io_logCtrl_log_end = args.log_end; dut_ptr->io_logCtrl_log_end = args.log_end;
...@@ -150,6 +158,15 @@ Emulator::Emulator(int argc, const char *argv[]): ...@@ -150,6 +158,15 @@ Emulator::Emulator(int argc, const char *argv[]):
Emulator::~Emulator() { Emulator::~Emulator() {
ram_finish(); ram_finish();
assert_finish(); assert_finish();
#ifdef VM_SAVABLE
if (args.enable_snapshot && trapCode != STATE_GOODTRAP && trapCode != STATE_LIMIT_EXCEEDED) {
printf("Saving snapshots to file system. Please wait.\n");
snapshot_slot[0].save();
snapshot_slot[1].save();
printf("Please remove unused snapshots manually\n");
}
#endif
} }
inline void Emulator::reset_ncycles(size_t cycles) { inline void Emulator::reset_ncycles(size_t cycles) {
...@@ -271,7 +288,6 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -271,7 +288,6 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
break; break;
} }
} }
// assertions // assertions
if (assert_count > 0) { if (assert_count > 0) {
// for (int i = 0; ) // for (int i = 0; )
...@@ -324,6 +340,22 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -324,6 +340,22 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
} }
if (trapCode != STATE_RUNNING) break; if (trapCode != STATE_RUNNING) break;
#ifdef VM_SAVABLE
static int snapshot_count = 0;
if (args.enable_snapshot && trapCode != STATE_GOODTRAP && t - lasttime_snapshot > 1000 * SNAPSHOT_INTERVAL) {
// save snapshot every 60s
time_t now = time(NULL);
snapshot_save(snapshot_filename(now));
lasttime_snapshot = t;
// dump one snapshot to file every 60 snapshots
snapshot_count++;
if (snapshot_count == 60) {
snapshot_slot[0].save();
snapshot_count = 0;
}
}
#endif
#ifdef EN_FORKWAIT #ifdef EN_FORKWAIT
timer = uptime(); timer = uptime();
if(timer - lasttime_snapshot > 1000 * FORK_INTERVAL && !waitProcess ){ //time out need to fork if(timer - lasttime_snapshot > 1000 * FORK_INTERVAL && !waitProcess ){ //time out need to fork
...@@ -374,9 +406,12 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -374,9 +406,12 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
forkshm.info->resInfo = trapCode; forkshm.info->resInfo = trapCode;
#endif #endif
display_trapinfo();
return cycles; return cycles;
} }
inline char* Emulator::timestamp_filename(time_t t, char *buf) { inline char* Emulator::timestamp_filename(time_t t, char *buf) {
char buf_time[64]; char buf_time[64];
strftime(buf_time, sizeof(buf_time), "%F@%T", localtime(&t)); strftime(buf_time, sizeof(buf_time), "%F@%T", localtime(&t));
...@@ -386,12 +421,21 @@ inline char* Emulator::timestamp_filename(time_t t, char *buf) { ...@@ -386,12 +421,21 @@ inline char* Emulator::timestamp_filename(time_t t, char *buf) {
return buf + len; return buf + len;
} }
#ifdef VM_SAVABLE
inline char* Emulator::snapshot_filename(time_t t) {
static char buf[1024];
char *p = timestamp_filename(t, buf);
strcpy(p, ".snapshot");
return buf;
}
#endif
inline char* Emulator::waveform_filename(time_t t) { inline char* Emulator::waveform_filename(time_t t) {
static char buf[1024]; static char buf[1024];
char *p = timestamp_filename(t, buf); char *p = timestamp_filename(t, buf);
strcpy(p, ".vcd"); strcpy(p, ".vcd");
printf("[%d]dump wave to %s...\n", getpid(), buf); printf("dump wave to %s...\n", buf);
return buf; return buf;
} }
...@@ -497,3 +541,85 @@ void ForkShareMemory::shwait(){ ...@@ -497,3 +541,85 @@ void ForkShareMemory::shwait(){
} }
} }
#endif #endif
#ifdef VM_SAVABLE
void Emulator::snapshot_save(const char *filename) {
static int last_slot = 0;
VerilatedSaveMem &stream = snapshot_slot[last_slot];
last_slot = !last_slot;
stream.init(filename);
stream << *dut_ptr;
stream.flush();
long size = get_ram_size();
stream.unbuf_write(&size, sizeof(size));
stream.unbuf_write(get_ram_start(), size);
uint64_t ref_r[DIFFTEST_NR_REG];
ref_difftest_getregs(&ref_r, 0);
stream.unbuf_write(ref_r, sizeof(ref_r));
uint64_t nemu_this_pc = get_nemu_this_pc(0);
stream.unbuf_write(&nemu_this_pc, sizeof(nemu_this_pc));
char *buf = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
ref_difftest_memcpy_from_ref(buf, 0x80000000, size, 0);
stream.unbuf_write(buf, size);
munmap(buf, size);
struct SyncState sync_mastate;
ref_difftest_get_mastatus(&sync_mastate, 0);
stream.unbuf_write(&sync_mastate, sizeof(struct SyncState));
uint64_t csr_buf[4096];
ref_difftest_get_csr(csr_buf, 0);
stream.unbuf_write(&csr_buf, sizeof(csr_buf));
long sdcard_offset;
if(fp)
sdcard_offset = ftell(fp);
else
sdcard_offset = 0;
stream.unbuf_write(&sdcard_offset, sizeof(sdcard_offset));
// actually write to file in snapshot_finalize()
}
void Emulator::snapshot_load(const char *filename) {
VerilatedRestoreMem stream;
stream.open(filename);
stream >> *dut_ptr;
long size;
stream.read(&size, sizeof(size));
assert(size == get_ram_size());
stream.read(get_ram_start(), size);
uint64_t ref_r[DIFFTEST_NR_REG];
stream.read(ref_r, sizeof(ref_r));
ref_difftest_setregs(&ref_r, 0);
uint64_t nemu_this_pc;
stream.read(&nemu_this_pc, sizeof(nemu_this_pc));
set_nemu_this_pc(nemu_this_pc, 0);
char *buf = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
stream.read(buf, size);
ref_difftest_memcpy_from_dut(0x80000000, buf, size, 0);
munmap(buf, size);
struct SyncState sync_mastate;
stream.read(&sync_mastate, sizeof(struct SyncState));
ref_difftest_set_mastatus(&sync_mastate, 0);
uint64_t csr_buf[4096];
stream.read(&csr_buf, sizeof(csr_buf));
ref_difftest_set_csr(csr_buf, 0);
long sdcard_offset = 0;
stream.read(&sdcard_offset, sizeof(sdcard_offset));
if(fp)
fseek(fp, sdcard_offset, SEEK_SET);
}
#endif
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define SLOT_SIZE 3 #define SLOT_SIZE 3
#define FAIT_EXIT exit(EXIT_FAILURE); #define FAIT_EXIT exit(EXIT_FAILURE);
#define WAIT_INTERVAL 1 #define WAIT_INTERVAL 1
#define SNAPSHOT_INTERVAL 60 // unit: second
typedef struct shinfo{ typedef struct shinfo{
int exitNum; int exitNum;
...@@ -88,6 +89,9 @@ private: ...@@ -88,6 +89,9 @@ private:
VSimTop *dut_ptr; VSimTop *dut_ptr;
VerilatedVcdC* tfp; VerilatedVcdC* tfp;
bool enable_waveform; bool enable_waveform;
#ifdef VM_SAVABLE
VerilatedSaveMem snapshot_slot[2];
#endif
EmuArgs args; EmuArgs args;
#ifdef EN_FORKWAIT #ifdef EN_FORKWAIT
ForkShareMemory forkshm; ForkShareMemory forkshm;
......
...@@ -42,6 +42,12 @@ ifneq ($(EMU_THREADS),0) ...@@ -42,6 +42,12 @@ ifneq ($(EMU_THREADS),0)
VEXTRA_FLAGS += --threads $(EMU_THREADS) --threads-dpi all VEXTRA_FLAGS += --threads $(EMU_THREADS) --threads-dpi all
endif endif
# Verilator savable
EMU_SNAPSHOT ?=
ifeq ($(EMU_SNAPSHOT),1)
VEXTRA_FLAGS += --savable
EMU_CXXFLAGS += -DVM_SAVABLE
# Fork-wait # Fork-wait
EMU_FORKWAIT ?= EMU_FORKWAIT ?=
ifeq ($(EMU_FORKWAIT),1) ifeq ($(EMU_FORKWAIT),1)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册