emu.cpp 17.1 KB
Newer Older
L
LinJiawei 已提交
1
#include "emu.h"
2
#include "sdcard.h"
L
LinJiawei 已提交
3
#include "difftest.h"
4
#include <getopt.h>
5 6
#include<signal.h>
#include<unistd.h>
7
#include "ram.h"
Z
zoujr 已提交
8
#include "zlib.h"
Y
Yinan Xu 已提交
9
#include "compress.h"
L
LinJiawei 已提交
10 11 12 13 14 15

void* get_ram_start();
long get_ram_size();
uint64_t get_nemu_this_pc();
void set_nemu_this_pc(uint64_t pc);

16 17 18 19

static inline void print_help(const char *file) {
  printf("Usage: %s [OPTION...]\n", file);
  printf("\n");
20 21 22 23 24 25
  printf("  -s, --seed=NUM             use this seed\n");
  printf("  -C, --max-cycles=NUM       execute at most NUM cycles\n");
  printf("  -I, --max-instr=NUM        execute at most NUM instructions\n");
  printf("  -i, --image=FILE           run with this image file\n");
  printf("  -b, --log-begin=NUM        display log from NUM th cycle\n");
  printf("  -e, --log-end=NUM          stop display log at NUM th cycle\n");
26
  printf("      --load-snapshot=PATH   load snapshot from PATH\n");
27 28 29
  printf("      --no-snapshot          disable saving snapshots\n");
  printf("      --dump-wave            dump waveform when log is enabled\n");
  printf("  -h, --help                 print program help info\n");
30 31 32 33 34 35 36 37 38
  printf("\n");
}

inline EmuArgs parse_args(int argc, const char *argv[]) {
  EmuArgs args;
  int long_index = 0;
  const struct option long_options[] = {
    { "load-snapshot",  1, NULL,  0  },
    { "dump-wave",      0, NULL,  0  },
39
    { "no-snapshot",    0, NULL,  0  },
40 41
    { "seed",           1, NULL, 's' },
    { "max-cycles",     1, NULL, 'C' },
Y
YikeZhou 已提交
42
    { "max-instr",      1, NULL, 'I' },
43 44 45 46 47 48 49 50 51
    { "image",          1, NULL, 'i' },
    { "log-begin",      1, NULL, 'b' },
    { "log-end",        1, NULL, 'e' },
    { "help",           0, NULL, 'h' },
    { 0,                0, NULL,  0  }
  };

  int o;
  while ( (o = getopt_long(argc, const_cast<char *const*>(argv),
Y
YikeZhou 已提交
52
          "-s:C:I:hi:m:b:e:", long_options, &long_index)) != -1) {
53 54 55 56 57
    switch (o) {
      case 0:
        switch (long_index) {
          case 0: args.snapshot_path = optarg; continue;
          case 1: args.enable_waveform = true; continue;
58
          case 2: args.enable_snapshot = false; continue;
59 60 61 62 63 64 65 66 67 68 69 70
        }
        // fall through
      default:
        print_help(argv[0]);
        exit(0);
      case 's':
        if(std::string(optarg) != "NO_SEED") {
          args.seed = atoll(optarg);
          printf("Using seed = %d\n", args.seed);
        }
        break;
      case 'C': args.max_cycles = atoll(optarg);  break;
Y
YikeZhou 已提交
71
      case 'I': args.max_instr = atoll(optarg);  break;
72 73 74 75 76 77 78 79 80 81 82 83
      case 'i': args.image = optarg; break;
      case 'b': args.log_begin = atoll(optarg);  break;
      case 'e': args.log_end = atoll(optarg); break;
    }
  }

  Verilated::commandArgs(argc, argv); // Prepare extra args for TLMonitor
  return args;
}


Emulator::Emulator(int argc, const char *argv[]):
84
  dut_ptr(new VXSSimSoC),
L
LinJiawei 已提交
85 86
  cycles(0), hascommit(0), trapCode(STATE_RUNNING)
{
87 88
  args = parse_args(argc, argv);

L
LinJiawei 已提交
89 90 91 92 93
  // srand
  srand(args.seed);
  srand48(args.seed);
  Verilated::randReset(2);

Y
Yinan Xu 已提交
94 95 96
  // init core
  reset_ncycles(10);

L
LinJiawei 已提交
97 98 99 100 101 102 103 104 105
  // init ram
  init_ram(args.image);

  // init device
  extern void init_device(void);
  init_device();

  init_difftest();

106
#if VM_TRACE == 1
L
LinJiawei 已提交
107 108 109 110 111 112 113 114
  enable_waveform = args.enable_waveform;
  if (enable_waveform) {
    Verilated::traceEverOn(true);	// Verilator must compute traced signals
    tfp = new VerilatedVcdC;
    dut_ptr->trace(tfp, 99);	// Trace 99 levels of hierarchy
    time_t now = time(NULL);
    tfp->open(waveform_filename(now));	// Open the dump file
  }
115 116 117
#else
  enable_waveform = false;
#endif
L
LinJiawei 已提交
118

119
#ifdef VM_SAVABLE
L
LinJiawei 已提交
120 121 122
  if (args.snapshot_path != NULL) {
    printf("loading from snapshot `%s`...\n", args.snapshot_path);
    snapshot_load(args.snapshot_path);
123
    printf("model cycleCnt = %" PRIu64 "\n", dut_ptr->io_trap_cycleCnt);
L
LinJiawei 已提交
124 125
    hascommit = 1;
  }
126
#endif
L
LinJiawei 已提交
127 128 129 130 131 132 133

  // set log time range and log level
  dut_ptr->io_logCtrl_log_begin = args.log_begin;
  dut_ptr->io_logCtrl_log_end = args.log_end;
}

Emulator::~Emulator() {
134 135
  ram_finish();

136
#ifdef VM_SAVABLE
137
  if (args.enable_snapshot && trapCode != STATE_GOODTRAP && trapCode != STATE_LIMIT_EXCEEDED) {
138
    printf("Saving snapshots to file system. Please wait.\n");
Y
Yinan Xu 已提交
139 140
    snapshot_slot[0].save();
    snapshot_slot[1].save();
141
    printf("Please remove unused snapshots manually\n");
Y
Yinan Xu 已提交
142
  }
143
#endif
L
LinJiawei 已提交
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
}

inline void Emulator::read_emu_regs(uint64_t *r) {
#define macro(x) r[x] = dut_ptr->io_difftest_r_##x
  macro(0); macro(1); macro(2); macro(3); macro(4); macro(5); macro(6); macro(7);
  macro(8); macro(9); macro(10); macro(11); macro(12); macro(13); macro(14); macro(15);
  macro(16); macro(17); macro(18); macro(19); macro(20); macro(21); macro(22); macro(23);
  macro(24); macro(25); macro(26); macro(27); macro(28); macro(29); macro(30); macro(31);
  macro(32); macro(33); macro(34); macro(35); macro(36); macro(37); macro(38); macro(39);
  macro(40); macro(41); macro(42); macro(43); macro(44); macro(45); macro(46); macro(47);
  macro(48); macro(49); macro(50); macro(51); macro(52); macro(53); macro(54); macro(55);
  macro(56); macro(57); macro(58); macro(59); macro(60); macro(61); macro(62); macro(63);
  r[DIFFTEST_THIS_PC] = dut_ptr->io_difftest_thisPC;
  r[DIFFTEST_MSTATUS] = dut_ptr->io_difftest_mstatus;
  r[DIFFTEST_SSTATUS] = dut_ptr->io_difftest_sstatus;
  r[DIFFTEST_MEPC   ] = dut_ptr->io_difftest_mepc;
  r[DIFFTEST_SEPC   ] = dut_ptr->io_difftest_sepc;
  r[DIFFTEST_MCAUSE ] = dut_ptr->io_difftest_mcause;
  r[DIFFTEST_SCAUSE ] = dut_ptr->io_difftest_scause;
163 164 165 166 167 168 169
  r[DIFFTEST_SATP   ] = dut_ptr->io_difftest_satp;
  r[DIFFTEST_MIP    ] = dut_ptr->io_difftest_mip;
  r[DIFFTEST_MIE    ] = dut_ptr->io_difftest_mie;
  r[DIFFTEST_MSCRATCH]= dut_ptr->io_difftest_mscratch;
  r[DIFFTEST_SSCRATCH]= dut_ptr->io_difftest_sscratch;
  r[DIFFTEST_MIDELEG] = dut_ptr->io_difftest_mideleg;
  r[DIFFTEST_MEDELEG] = dut_ptr->io_difftest_medeleg;
W
William Wang 已提交
170 171 172 173
  r[DIFFTEST_MTVAL]   = dut_ptr->io_difftest_mtval;
  r[DIFFTEST_STVAL]   = dut_ptr->io_difftest_stval;
  r[DIFFTEST_MTVEC]   = dut_ptr->io_difftest_mtvec;
  r[DIFFTEST_STVEC]   = dut_ptr->io_difftest_stvec;
W
William Wang 已提交
174
  r[DIFFTEST_MODE]    = dut_ptr->io_difftest_priviledgeMode;
L
LinJiawei 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188
}

inline void Emulator::read_wb_info(uint64_t *wpc, uint64_t *wdata, uint32_t *wdst) {
#define dut_ptr_wpc(x)  wpc[x] = dut_ptr->io_difftest_wpc_##x
#define dut_ptr_wdata(x) wdata[x] = dut_ptr->io_difftest_wdata_##x
#define dut_ptr_wdst(x)  wdst[x] = dut_ptr->io_difftest_wdst_##x
  dut_ptr_wpc(0); dut_ptr_wdata(0); dut_ptr_wdst(0); 
  dut_ptr_wpc(1); dut_ptr_wdata(1); dut_ptr_wdst(1); 
  dut_ptr_wpc(2); dut_ptr_wdata(2); dut_ptr_wdst(2); 
  dut_ptr_wpc(3); dut_ptr_wdata(3); dut_ptr_wdst(3); 
  dut_ptr_wpc(4); dut_ptr_wdata(4); dut_ptr_wdst(4); 
  dut_ptr_wpc(5); dut_ptr_wdata(5); dut_ptr_wdst(5); 
}

Y
Yinan Xu 已提交
189 190 191 192 193 194 195 196 197
inline void Emulator::read_store_info(uint64_t *saddr, uint64_t *sdata, uint8_t *smask) {
#define dut_ptr_saddr(x)  saddr[x] = dut_ptr->io_difftest_storeAddr_##x
#define dut_ptr_sdata(x) sdata[x] = dut_ptr->io_difftest_storeData_##x
#define dut_ptr_smask(x) smask[x] = dut_ptr->io_difftest_storeMask_##x
  dut_ptr_saddr(0); dut_ptr_saddr(1);
  dut_ptr_sdata(0); dut_ptr_sdata(1);
  dut_ptr_smask(0); dut_ptr_smask(1);
}

L
LinJiawei 已提交
198 199 200 201 202 203 204 205 206 207 208 209 210
inline void Emulator::reset_ncycles(size_t cycles) {
  for(int i = 0; i < cycles; i++) {
    dut_ptr->reset = 1;
    dut_ptr->clock = 0;
    dut_ptr->eval();
    dut_ptr->clock = 1;
    dut_ptr->eval();
    dut_ptr->reset = 0;
  }
}

inline void Emulator::single_cycle() {
  dut_ptr->clock = 0;
211 212 213
#ifdef WITH_DRAMSIM3
  axi_channel axi;
  axi_copy_from_dut_ptr(dut_ptr, axi);
214 215
  axi.aw.addr -= 0x80000000UL;
  axi.ar.addr -= 0x80000000UL;
216
  dramsim3_helper(axi);
217 218
  axi.aw.addr += 0x80000000UL;
  axi.ar.addr += 0x80000000UL;
219 220 221
  axi_set_dut_ptr(dut_ptr, axi);
#endif

L
LinJiawei 已提交
222 223 224 225 226
  dut_ptr->eval();

  dut_ptr->clock = 1;
  dut_ptr->eval();

227
#if VM_TRACE == 1
L
LinJiawei 已提交
228 229 230 231 232 233 234
  if (enable_waveform) {
    uint64_t cycle = dut_ptr->io_trap_cycleCnt;
    uint64_t begin = dut_ptr->io_logCtrl_log_begin;
    uint64_t end   = dut_ptr->io_logCtrl_log_end;
    bool in_range = (begin <= cycle) && (cycle <= end);
    if (in_range) { tfp->dump(cycle); }
  }
235
#endif
L
LinJiawei 已提交
236 237

  if (dut_ptr->io_uart_out_valid) {
238 239
    printf("%c", dut_ptr->io_uart_out_ch);
    fflush(stdout);
L
LinJiawei 已提交
240 241 242 243 244 245 246 247 248
  }
  if (dut_ptr->io_uart_in_valid) {
    extern uint8_t uart_getc();
    dut_ptr->io_uart_in_ch = uart_getc();
  }

  cycles ++;
}

249 250 251 252 253 254 255 256 257 258
#if VM_COVERAGE == 1
uint64_t *max_cycle_ptr = NULL;
// when interrupted, we set max_cycle to zero
// so that the emulator will stop gracefully
void sig_handler(int signo) {
  if (signo == SIGINT)
    *max_cycle_ptr = 0;
}
#endif

Y
YikeZhou 已提交
259
uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
L
LinJiawei 已提交
260 261 262 263
  extern void poll_event(void);
  extern uint32_t uptime(void);
  uint32_t lasttime_poll = 0;
  uint32_t lasttime_snapshot = 0;
Y
YikeZhou 已提交
264 265
  uint64_t lastcommit = max_cycle;
  uint64_t instr_left_last_cycle = max_instr;
L
linjiawei 已提交
266
  const int stuck_limit = 2000;
L
LinJiawei 已提交
267 268 269 270 271 272 273 274 275 276 277

  uint32_t wdst[DIFFTEST_WIDTH];
  uint64_t wdata[DIFFTEST_WIDTH];
  uint64_t wpc[DIFFTEST_WIDTH];
  uint64_t reg[DIFFTEST_NR_REG];
  DiffState diff;
  diff.reg_scala = reg;
  diff.wpc = wpc;
  diff.wdata = wdata;
  diff.wdst = wdst;

278
#if VM_COVERAGE == 1
279 280 281 282
  // we dump coverage into files at the end
  // since we are not sure when an emu will stop
  // we distinguish multiple dat files by emu start time
  time_t start_time = time(NULL);
283 284 285
  max_cycle_ptr = &max_cycle;
  if (signal(SIGINT, sig_handler) == SIG_ERR)
    printf("\ncan't catch SIGINT\n");
286 287
#endif

288
  while (!Verilated::gotFinish() && trapCode == STATE_RUNNING) {
Y
YikeZhou 已提交
289 290 291 292 293
    if (!(max_cycle > 0 && max_instr > 0 && instr_left_last_cycle >= max_instr /* handle overflow */)) {
      trapCode = STATE_LIMIT_EXCEEDED;
      break;
    }

L
LinJiawei 已提交
294
    single_cycle();
Y
YikeZhou 已提交
295
    max_cycle --;
L
LinJiawei 已提交
296 297 298 299

    if (dut_ptr->io_trap_valid) trapCode = dut_ptr->io_trap_code;
    if (trapCode != STATE_RUNNING) break;

Y
YikeZhou 已提交
300
    if (lastcommit - max_cycle > stuck_limit && hascommit) {
L
LinJiawei 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314
      eprintf("No instruction commits for %d cycles, maybe get stuck\n"
          "(please also check whether a fence.i instruction requires more than %d cycles to flush the icache)\n",
          stuck_limit, stuck_limit);
      difftest_display(dut_ptr->io_difftest_priviledgeMode);
      trapCode = STATE_ABORT;
    }

    if (!hascommit && dut_ptr->io_difftest_commit && dut_ptr->io_difftest_thisPC == 0x80000000u) {
      hascommit = 1;
      read_emu_regs(reg);
      void* get_img_start();
      long get_img_size();
      ref_difftest_memcpy_from_dut(0x80000000, get_img_start(), get_img_size());
      ref_difftest_setregs(reg);
315
      printf("The first instruction has commited. Difftest enabled. \n");
L
LinJiawei 已提交
316 317 318 319 320 321 322 323 324 325 326 327 328
    }

    // difftest
    if (dut_ptr->io_difftest_commit && hascommit) {
      read_emu_regs(reg);
      read_wb_info(wpc, wdata, wdst);

      diff.commit = dut_ptr->io_difftest_commit;
      diff.this_inst = dut_ptr->io_difftest_thisINST;
      diff.skip = dut_ptr->io_difftest_skip;
      diff.isRVC = dut_ptr->io_difftest_isRVC;
      diff.wen = dut_ptr->io_difftest_wen;
      diff.intrNO = dut_ptr->io_difftest_intrNO;
329
      diff.cause = dut_ptr->io_difftest_cause;
L
LinJiawei 已提交
330 331
      diff.priviledgeMode = dut_ptr->io_difftest_priviledgeMode;

332
      diff.sync.scFailed = dut_ptr->io_difftest_scFailed;
333

L
LinJiawei 已提交
334 335 336
      if (difftest_step(&diff)) {
        trapCode = STATE_ABORT;
      }
Y
YikeZhou 已提交
337 338 339 340 341
      lastcommit = max_cycle;

      // update instr_cnt
      instr_left_last_cycle = max_instr;
      max_instr -= diff.commit;
L
LinJiawei 已提交
342 343
    }

Y
Yinan Xu 已提交
344 345 346 347 348 349 350 351 352 353 354 355 356 357
    if (dut_ptr->io_difftest_storeCommit) {
      read_store_info(diff.store_addr, diff.store_data, diff.store_mask);

      for (int i = 0; i < dut_ptr->io_difftest_storeCommit; i++) {
        auto addr = diff.store_addr[i];
        auto data = diff.store_data[i];
        auto mask = diff.store_mask[i];
        if (difftest_store_step(&addr, &data, &mask)) {
          difftest_display(dut_ptr->io_difftest_priviledgeMode);
          printf("Mismatch for store commits: \n");
          printf("REF commits addr 0x%lx, data 0x%lx, mask 0x%x\n", addr, data, mask);
          printf("DUT commits addr 0x%lx, data 0x%lx, mask 0x%x\n",
            diff.store_addr[i], diff.store_data[i], diff.store_mask[i]);
          trapCode = STATE_ABORT;
Y
Yinan Xu 已提交
358
          break;
Y
Yinan Xu 已提交
359 360 361 362
        }
      }
    }

L
LinJiawei 已提交
363 364 365 366 367
    uint32_t t = uptime();
    if (t - lasttime_poll > 100) {
      poll_event();
      lasttime_poll = t;
    }
368
#ifdef VM_SAVABLE
369
    static int snapshot_count = 0;
370
    if (args.enable_snapshot && trapCode != STATE_GOODTRAP && t - lasttime_snapshot > 6000 * SNAPSHOT_INTERVAL) {
Y
Yinan Xu 已提交
371
      // save snapshot every 60s
L
LinJiawei 已提交
372 373 374
      time_t now = time(NULL);
      snapshot_save(snapshot_filename(now));
      lasttime_snapshot = t;
375 376
      // dump snapshot to file every 10 minutes
      snapshot_count++;
377
      if (snapshot_count == 60) {
378 379 380
        snapshot_slot[0].save();
        snapshot_count = 0;
      }
L
LinJiawei 已提交
381
    }
382
#endif
L
LinJiawei 已提交
383 384
  }

385
  if (Verilated::gotFinish()) {
Y
Yinan Xu 已提交
386
    difftest_display(dut_ptr->io_difftest_priviledgeMode);
387 388 389 390
    eprintf("The simulation stopped. There might be some assertion failed.\n");
    trapCode = STATE_ABORT;
  }

391
#if VM_TRACE == 1
L
LinJiawei 已提交
392
  if (enable_waveform) tfp->close();
393
#endif
A
Allen 已提交
394

Y
Yinan Xu 已提交
395
#if VM_COVERAGE == 1
396
  save_coverage(start_time);
A
Allen 已提交
397 398
#endif

L
LinJiawei 已提交
399 400 401 402 403 404 405 406 407 408 409 410 411
  display_trapinfo();
  return cycles;
}

inline char* Emulator::timestamp_filename(time_t t, char *buf) {
  char buf_time[64];
  strftime(buf_time, sizeof(buf_time), "%F@%T", localtime(&t));
  char *noop_home = getenv("NOOP_HOME");
  assert(noop_home != NULL);
  int len = snprintf(buf, 1024, "%s/build/%s", noop_home, buf_time);
  return buf + len;
}

412
#ifdef VM_SAVABLE
Y
Yinan Xu 已提交
413 414 415 416 417 418
inline char* Emulator::snapshot_filename(time_t t) {
  static char buf[1024];
  char *p = timestamp_filename(t, buf);
  strcpy(p, ".snapshot");
  return buf;
}
419
#endif
L
LinJiawei 已提交
420 421 422 423 424

inline char* Emulator::waveform_filename(time_t t) {
  static char buf[1024];
  char *p = timestamp_filename(t, buf);
  strcpy(p, ".vcd");
425
  printf("dump wave to %s...\n", buf);
L
LinJiawei 已提交
426 427 428
  return buf;
}

A
Allen 已提交
429

Y
Yinan Xu 已提交
430
#if VM_COVERAGE == 1
431 432 433 434 435 436
inline char* Emulator::coverage_filename(time_t t) {
  static char buf[1024];
  char *p = timestamp_filename(t, buf);
  strcpy(p, ".coverage.dat");
  return buf;
}
A
Allen 已提交
437

438 439 440
inline void Emulator::save_coverage(time_t t) {
  char *p = coverage_filename(t);
  VerilatedCov::write(p);
A
Allen 已提交
441
}
A
Allen 已提交
442
#endif
A
Allen 已提交
443 444


L
LinJiawei 已提交
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
void Emulator::display_trapinfo() {
  uint64_t pc = dut_ptr->io_trap_pc;
  uint64_t instrCnt = dut_ptr->io_trap_instrCnt;
  uint64_t cycleCnt = dut_ptr->io_trap_cycleCnt;

  switch (trapCode) {
    case STATE_GOODTRAP:
      eprintf(ANSI_COLOR_GREEN "HIT GOOD TRAP at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, pc);
      break;
    case STATE_BADTRAP:
      eprintf(ANSI_COLOR_RED "HIT BAD TRAP at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, pc);
      break;
    case STATE_ABORT:
      eprintf(ANSI_COLOR_RED "ABORT at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, pc);
      break;
Y
YikeZhou 已提交
460 461 462
    case STATE_LIMIT_EXCEEDED:
      eprintf(ANSI_COLOR_YELLOW "EXCEEDING CYCLE/INSTR LIMIT at pc = 0x%" PRIx64 "\n" ANSI_COLOR_RESET, pc);
      break;
L
LinJiawei 已提交
463 464 465 466 467 468 469 470 471 472
    default:
      eprintf(ANSI_COLOR_RED "Unknown trap code: %d\n", trapCode);
  }

  double ipc = (double)instrCnt / (cycleCnt-500);
  eprintf(ANSI_COLOR_MAGENTA "total guest instructions = %" PRIu64 "\n" ANSI_COLOR_RESET, instrCnt);
  eprintf(ANSI_COLOR_MAGENTA "instrCnt = %" PRIu64 ", cycleCnt = %" PRIu64 ", IPC = %lf\n" ANSI_COLOR_RESET,
      instrCnt, cycleCnt, ipc);
}

473
#ifdef VM_SAVABLE
Y
Yinan Xu 已提交
474 475 476 477 478 479 480 481 482
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();

Z
zoujr 已提交
483
  long size = get_ram_size();
Y
Yinan Xu 已提交
484
  stream.unbuf_write(&size, sizeof(size));
Z
zoujr 已提交
485
  stream.unbuf_write(get_ram_start(), size);
Y
Yinan Xu 已提交
486 487 488 489 490 491 492 493

  uint64_t ref_r[DIFFTEST_NR_REG];
  ref_difftest_getregs(&ref_r);
  stream.unbuf_write(ref_r, sizeof(ref_r));

  uint64_t nemu_this_pc = get_nemu_this_pc();
  stream.unbuf_write(&nemu_this_pc, sizeof(nemu_this_pc));

Y
Yinan Xu 已提交
494
  char *buf = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
Y
Yinan Xu 已提交
495 496
  ref_difftest_memcpy_from_ref(buf, 0x80000000, size);
  stream.unbuf_write(buf, size);
Y
Yinan Xu 已提交
497
  munmap(buf, size);
Y
Yinan Xu 已提交
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515

  struct SyncState sync_mastate;
  ref_difftest_get_mastatus(&sync_mastate);
  stream.unbuf_write(&sync_mastate, sizeof(struct SyncState));

  uint64_t csr_buf[4096];
  ref_difftest_get_csr(csr_buf);
  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()
}
L
LinJiawei 已提交
516

Y
Yinan Xu 已提交
517
void Emulator::snapshot_load(const char *filename) {
518
  VerilatedRestoreMem stream;
Y
Yinan Xu 已提交
519 520 521 522 523
  stream.open(filename);
  stream >> *dut_ptr;

  long size;
  stream.read(&size, sizeof(size));
Z
zoujr 已提交
524 525
  assert(size == get_ram_size());
  stream.read(get_ram_start(), size);
Y
Yinan Xu 已提交
526 527 528 529 530 531 532 533 534

  uint64_t ref_r[DIFFTEST_NR_REG];
  stream.read(ref_r, sizeof(ref_r));
  ref_difftest_setregs(&ref_r);

  uint64_t nemu_this_pc;
  stream.read(&nemu_this_pc, sizeof(nemu_this_pc));
  set_nemu_this_pc(nemu_this_pc);

Y
Yinan Xu 已提交
535
  char *buf = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
Y
Yinan Xu 已提交
536 537
  stream.read(buf, size);
  ref_difftest_memcpy_from_dut(0x80000000, buf, size);
Y
Yinan Xu 已提交
538
  munmap(buf, size);
Y
Yinan Xu 已提交
539 540 541 542 543 544 545 546 547 548 549 550 551 552

  struct SyncState sync_mastate;
  stream.read(&sync_mastate, sizeof(struct SyncState));
  ref_difftest_set_mastatus(&sync_mastate);

  uint64_t csr_buf[4096];
  stream.read(&csr_buf, sizeof(csr_buf));
  ref_difftest_set_csr(csr_buf);

  long sdcard_offset = 0;
  stream.read(&sdcard_offset, sizeof(sdcard_offset));
  if(fp)
    fseek(fp, sdcard_offset, SEEK_SET);
}
553
#endif