提交 89525aa2 编写于 作者: J JinYue

Makefile: add EMU_FORKWAIT option

* Set EMU_FORKWAIT=1 will enable fork-wait function and enable verilator
trace by default.
上级 872ca138
...@@ -27,11 +27,11 @@ ifneq ($(EMU_THREADS),0) ...@@ -27,11 +27,11 @@ ifneq ($(EMU_THREADS),0)
VEXTRA_FLAGS += --threads $(EMU_THREADS) --threads-dpi all VEXTRA_FLAGS += --threads $(EMU_THREADS) --threads-dpi all
endif endif
# Verilator savable # Fork-wait
EMU_SNAPSHOT ?= EMU_FORKWAIT ?=
ifeq ($(EMU_SNAPSHOT),1) ifeq ($(EMU_FORKWAIT),1)
VEXTRA_FLAGS += --savable EMU_CXXFLAGS += -DEN_FROKWAIT
EMU_CXXFLAGS += -DVM_SAVABLE VEXTRA_FLAGS += --trace
endif endif
# Verilator coverage # Verilator coverage
......
...@@ -105,6 +105,25 @@ Emulator::Emulator(int argc, const char *argv[]): ...@@ -105,6 +105,25 @@ Emulator::Emulator(int argc, const char *argv[]):
// init ram // init ram
init_ram(args.image); init_ram(args.image);
#if (VM_TRACE == 1)
#ifndef EN_FORKWAIT
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
}
#else
// VM_TRACE =1 && EN_FORKWAIT
enable_waveform = false;
#endif
#else
// VM_TRACE =0
enable_waveform = false;
#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;
...@@ -151,7 +170,6 @@ inline void Emulator::single_cycle() { ...@@ -151,7 +170,6 @@ inline void Emulator::single_cycle() {
#if VM_TRACE == 1 #if VM_TRACE == 1
if (enable_waveform) { if (enable_waveform) {
//if(cycles % 200 == 0) printf("[%d] dump wave! cycles:%d\n", getpid(),cycles);
auto trap = difftest[0]->get_trap_event(); auto trap = difftest[0]->get_trap_event();
uint64_t cycle = trap->cycleCnt; uint64_t cycle = trap->cycleCnt;
uint64_t begin = dut_ptr->io_logCtrl_log_begin; uint64_t begin = dut_ptr->io_logCtrl_log_begin;
...@@ -187,13 +205,14 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -187,13 +205,14 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
poll_event(); poll_event();
lasttime_poll = t; lasttime_poll = t;
} }
#ifdef EN_FORKWAIT
pid_t pid =-1; pid_t pid =-1;
pid_t originPID = getpid(); pid_t originPID = getpid();
int status = -1; int status = -1;
int slotCnt = 1; int slotCnt = 1;
int waitProcess = 0; int waitProcess = 0;
uint32_t timer = 0; uint32_t timer = 0;
//pid_t pidSlot[SLOT_SIZE] = {-1 , -1, -1};
std::list<pid_t> pidSlot = {}; std::list<pid_t> pidSlot = {};
enable_waveform = false; enable_waveform = false;
...@@ -212,6 +231,7 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -212,6 +231,7 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
forkshm.info->flag = true; forkshm.info->flag = true;
pidSlot.insert(pidSlot.begin(), getpid()); pidSlot.insert(pidSlot.begin(), getpid());
} }
#endif
#if VM_COVERAGE == 1 #if VM_COVERAGE == 1
// we dump coverage into files at the end // we dump coverage into files at the end
...@@ -232,6 +252,7 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -232,6 +252,7 @@ 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; )
...@@ -278,17 +299,13 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -278,17 +299,13 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
trapCode = difftest_state(); trapCode = difftest_state();
if (trapCode != STATE_RUNNING) break; if (trapCode != STATE_RUNNING) break;
//fake error point
// if(cycles == 25535 ){
// trapCode = STATE_BADTRAP;
// }
if (difftest_step()) { if (difftest_step()) {
trapCode = STATE_ABORT; trapCode = STATE_ABORT;
break; break;
} }
if (trapCode != STATE_RUNNING) break; if (trapCode != STATE_RUNNING) break;
#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
lasttime_snapshot = timer; lasttime_snapshot = timer;
...@@ -306,8 +323,6 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -306,8 +323,6 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
} else if(pid != 0) { //father fork and wait. } else if(pid != 0) { //father fork and wait.
waitProcess = 1; waitProcess = 1;
wait(&status); wait(&status);
#if VM_TRACE == 1
//enable_waveform = args.enable_waveform;
enable_waveform = forkshm.info->resInfo != STATE_GOODTRAP; enable_waveform = forkshm.info->resInfo != STATE_GOODTRAP;
if (enable_waveform) { if (enable_waveform) {
Verilated::traceEverOn(true); // Verilator must compute traced signals Verilated::traceEverOn(true); // Verilator must compute traced signals
...@@ -316,13 +331,13 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -316,13 +331,13 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
time_t now = time(NULL); time_t now = time(NULL);
tfp->open(waveform_filename(now)); // Open the dump file tfp->open(waveform_filename(now)); // Open the dump file
} }
#endif
} else { //child insert its pid } else { //child insert its pid
slotCnt++; slotCnt++;
forkshm.info->exitNum++; forkshm.info->exitNum++;
pidSlot.insert(pidSlot.begin(), getpid()); pidSlot.insert(pidSlot.begin(), getpid());
} }
} }
#endif
} }
#if VM_TRACE == 1 #if VM_TRACE == 1
...@@ -333,11 +348,13 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) { ...@@ -333,11 +348,13 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
save_coverage(coverage_start_time); save_coverage(coverage_start_time);
#endif #endif
#ifdef EN_FORKWAIT
if(!waitProcess) display_trapinfo(); if(!waitProcess) display_trapinfo();
else printf("[%d] checkpoint process: dump wave complete, exit.\n",getpid()); else printf("[%d] checkpoint process: dump wave complete, exit.\n",getpid());
forkshm.info->exitNum--; forkshm.info->exitNum--;
forkshm.info->resInfo = trapCode; forkshm.info->resInfo = trapCode;
#endif
return cycles; return cycles;
} }
...@@ -418,6 +435,7 @@ void Emulator::display_trapinfo() { ...@@ -418,6 +435,7 @@ void Emulator::display_trapinfo() {
} }
} }
#ifdef EN_FORKWAIT
ForkShareMemory::ForkShareMemory() { ForkShareMemory::ForkShareMemory() {
if((key_n = ftok(".",'s')<0)) { if((key_n = ftok(".",'s')<0)) {
perror("Fail to ftok\n"); perror("Fail to ftok\n");
...@@ -456,4 +474,4 @@ void ForkShareMemory::shwait(){ ...@@ -456,4 +474,4 @@ void ForkShareMemory::shwait(){
} }
} }
} }
#endif
...@@ -13,10 +13,11 @@ ...@@ -13,10 +13,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#define FORK_INTERVAL 5 // unit: second #define FORK_INTERVAL 10 // unit: second
#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 EN_FORKWAIT
typedef struct shinfo{ typedef struct shinfo{
int exitNum; int exitNum;
...@@ -71,11 +72,10 @@ private: ...@@ -71,11 +72,10 @@ 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
ForkShareMemory forkshm; ForkShareMemory forkshm;
#endif
enum { enum {
STATE_GOODTRAP = 0, STATE_GOODTRAP = 0,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册