Skip to content

Commit

Permalink
Replay: clear buffered queue, ensure least error report
Browse files Browse the repository at this point in the history
When squashQueue enabled, load/store event may be submitted ahead
and buffered in queue before squashed instrs commit along with replay
info. So when we recover snapshot and start replaying, we need clear
queue, submit and process load/store again.

Note in squashed, we will set trace_info to invalid when only submit
load/store queue event, reducing num of snapshots for better
performance.

This change also ensure least report of squashed error before replay,
and check if DUT run out of replay range. Also, seperate original
step() logic to private do_step(), keep same call interface
  • Loading branch information
klin02 committed Nov 25, 2024
1 parent 4233651 commit c6fba26
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 17 deletions.
61 changes: 44 additions & 17 deletions src/test/csrc/difftest/difftest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,14 @@ void Difftest::update_nemuproxy(int coreid, size_t ram_size = 0) {
#ifdef CONFIG_DIFFTEST_REPLAY
bool Difftest::can_replay() {
auto info = dut->trace_info;
return !info.in_replay && info.trace_size > 1;
return info.valid && !info.in_replay && info.trace_size > 1;
}

bool Difftest::in_replay_range() {
if (dut->trace_info.trace_size > 1)
auto info = dut->trace_info;
if (!info.valid || !info.in_replay || info.trace_size > 1)
return false;
int pos = dut->trace_info.trace_head;
int pos = info.trace_head;
int head = replay_status.trace_head;
int tail = (head + replay_status.trace_size - 1) % CONFIG_DIFFTEST_REPLAY_SIZE;
if (tail < head) { // consider ring queue
Expand All @@ -225,33 +226,65 @@ void Difftest::replay_snapshot() {
}

void Difftest::do_replay() {
auto info = dut->trace_info;
replay_status.in_replay = true;
replay_status.trace_head = dut->trace_info.trace_head;
replay_status.trace_size = dut->trace_info.trace_size;
replay_status.trace_head = info.trace_head;
replay_status.trace_size = info.trace_size;
memcpy(state, state_ss, sizeof(DiffState));
memcpy(&proxy->regs_int, proxy_reg_ss, proxy_reg_size);
proxy->ref_regcpy(&proxy->regs_int, DUT_TO_REF, false);
proxy->ref_csrcpy(squash_csr_buf, DUT_TO_REF);
proxy->ref_store_log_restore();
goldenmem_store_log_restore();
difftest_replay_head(dut->trace_info.trace_head);
difftest_replay_head(info.trace_head);
// clear buffered queue
#ifdef CONFIG_DIFFTEST_STOREEVENT
while (!store_event_queue.empty())
store_event_queue.pop();
#endif // CONFIG_DIFFTEST_STOREEVENT
#if defined(CONFIG_DIFFTEST_LOADEVENT) && defined(CONFIG_DIFFTEST_SQUASH)
while (!load_event_queue.empty())
load_event_queue.pop();
#endif
}
#endif // CONFIG_DIFFTEST_REPLAY

int Difftest::step() {
progress = false;

#ifdef CONFIG_DIFFTEST_REPLAY
if (replay_status.in_replay && !in_replay_range()) {
return 0;
static int replay_step = 0;
if (replay_status.in_replay) {
if (!in_replay_range()) {
return 0;
} else {
replay_step++;
if (replay_step > replay_status.trace_size) {
Info("*** DUT run out of replay range, failed to get error location ***\n");
return 1;
}
}
}
if (can_replay()) {
bool canReplay = can_replay();
if (canReplay) {
replay_snapshot();
} else {
proxy->set_store_log(false);
goldenmem_set_store_log(false);
}
int ret = do_step();
if (ret && canReplay) {
Info("\n**** Start replay for more accurate error location ****\n");
do_replay();
return 0;
} else {
return ret;
}
#else
return do_step();
#endif // CONFIG_DIFFTEST_REPLAY
}

inline int Difftest::do_step() {
progress = false;

if (check_timeout()) {
return 1;
Expand Down Expand Up @@ -391,12 +424,6 @@ int Difftest::step() {
return 0;
}
#endif
#ifdef CONFIG_DIFFTEST_REPLAY
if (can_replay()) {
do_replay();
return 0;
}
#endif // CONFIG_DIFFTEST_REPLAY
display();
proxy->display(dut);
#ifdef FUZZER_LIB
Expand Down
1 change: 1 addition & 0 deletions src/test/csrc/difftest/difftest.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ class Difftest {
last_commit = get_trap_event()->cycleCnt;
}
int check_timeout();
int do_step();
void do_first_instr_commit();
void do_interrupt();
void do_exception();
Expand Down

0 comments on commit c6fba26

Please sign in to comment.