vcs: support track pc

when the commit PC is same value as the tracking PC, print the clock cycle.
Sometimes the result is inaccurate for branch instruction and fused instruction.
When multiple instructions are committed in a single cycle, the commit PC is
inferred from the dut->commit[0].pc at the beginning of each cycle and the number
of instructions has been committed in the current cycle.
This commit is contained in:
szw_kaixin 2024-04-08 12:14:37 +08:00 committed by ssszwic
parent ca81bef78a
commit c7d8b9e637
4 changed files with 45 additions and 0 deletions

View File

@ -50,6 +50,15 @@ int init_nemuproxy(size_t ramsize = 0) {
return 0;
}
void set_diff_track_pc(uint64_t track_pc) {
for (int i = 0; i < NUM_CORES; i++) {
if (track_pc != 0) {
difftest[i]->enable_track_pc = true;
difftest[i]->track_pc = track_pc;
}
}
}
int difftest_state() {
for (int i = 0; i < NUM_CORES; i++) {
if (difftest[i]->get_trap_valid()) {
@ -302,6 +311,11 @@ int Difftest::step() {
#endif
num_commit = 0; // reset num_commit this cycle to 0
#ifdef BASIC_DIFFTEST_ONLY
uint64_t commit_pc = proxy->pc;
#else
uint64_t commit_pc = dut->commit[i].pc;
#endif
if (dut->event.valid) {
// interrupt has a higher priority than exception
dut->event.interrupt ? do_interrupt() : do_exception();
@ -315,6 +329,16 @@ int Difftest::step() {
}
dut->commit[i].valid = 0;
num_commit += 1 + dut->commit[i].nFused;
// when the tracking PC is set to the same value as the commit PC, print the clock cycle.
// Sometimes the result is inaccurate for branch instruction and fused instruction.
// When multiple instructions are committed in a single cycle, the commit PC is inferred
// from the dut->commit[0].pc at the beginning of each cycle and the number of instructions
// has been committed in the current cycle.
if (commit_pc == track_pc && enable_track_pc) {
printf("tick: %ld, pc: %lx frequency: %d\n", ticks, track_pc, frequency);
++frequency;
}
commit_pc += dut->commit[i].isRVC ? 2 : 4;
}
}
}

View File

@ -238,6 +238,10 @@ public:
}
}
uint64_t track_pc{0};
bool enable_track_pc{false};
int frequency{1};
// Difftest public APIs for dut: called from DPI-C functions (or testbench)
// These functions generally do nothing but copy the information to core_state.
inline DifftestTrapEvent *get_trap_event() {
@ -406,6 +410,8 @@ void difftest_trace_write(int step);
int init_nemuproxy(size_t);
void set_diff_track_pc(uint64_t track_pc);
#ifdef CONFIG_DIFFTEST_SQUASH
extern "C" void set_squash_scope();
extern "C" void difftest_squash_enable(int enable);

View File

@ -37,6 +37,7 @@ static bool enable_difftest = true;
static uint64_t max_instrs = 0;
static char *workload_list = NULL;
static uint64_t overwrite_nbytes = 0xe00;
static uint64_t track_pc = 0;
enum {
SIMV_RUN,
@ -65,6 +66,11 @@ extern "C" void set_max_instrs(uint64_t mc) {
max_instrs = mc;
}
extern "C" void set_track_pc(uint64_t pc) {
printf("set track pc: %lx\n", pc);
track_pc = pc;
}
extern const char *difftest_ref_so;
extern "C" void set_diff_ref_so(char *s) {
printf("diff-test ref so:%s\n", s);
@ -122,6 +128,7 @@ extern "C" uint8_t simv_init() {
init_flash(flash_bin_file);
difftest_init();
set_diff_track_pc(track_pc);
init_device();
if (enable_difftest) {
init_goldenmem();

View File

@ -25,6 +25,7 @@ import "DPI-C" function void set_diff_ref_so(string diff_so);
import "DPI-C" function void set_no_diff();
import "DPI-C" function byte simv_init();
import "DPI-C" function void set_max_instrs(longint mc);
import "DPI-C" function void set_track_pc(longint pc);
`ifdef WITH_DRAMSIM3
import "DPI-C" function void simv_tick();
`endif // WITH_DRAMSIM3
@ -76,6 +77,8 @@ wire workload_switch;
reg [63:0] max_instrs;
reg [63:0] max_cycles;
reg [63:0] track_pc;
initial begin
`ifndef WIRE_CLK
clock = 0;
@ -142,6 +145,11 @@ initial begin
if ($test$plusargs("no-diff")) begin
set_no_diff();
end
// set track pc
if ($test$plusargs("track-pc")) begin
$value$plusargs("track-pc=%h", track_pc);
set_track_pc(track_pc);
end
`ifdef ENABLE_WORKLOAD_SWITCH
// set exit instrs const
if ($test$plusargs("max-instrs")) begin