Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

difftest: lightqs runahead and oraclebp support for xs #108

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

// first valid instruction's address, difftest starts from this instruction
#ifndef FIRST_INST_ADDRESS
#define FIRST_INST_ADDRESS 0x10000000UL
#define FIRST_INST_ADDRESS 0x80000000UL
#endif

// sdcard image to be used in simulation
Expand Down
262 changes: 262 additions & 0 deletions src/test/csrc/common/branch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
#include "common.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

#define RAMSIZE (128 * 1024 * 1024)
#define PRED_WIDTH 16
#define MAX_BR_NUM 20000000

using namespace std;
int reset =1;

#define BRANCH_TYPE_BR 0
#define BRANCH_TYPE_JR 1

typedef struct branch_record {
uint64_t pc;
uint64_t target;
int taken;
int type;
} BR;

BR *record;
BR *record_orig;
void* (*ahead_isa_query_br_log)() = NULL;

inline void output_branch_record(BR rec, int idx) {
printf("br[%d]: pc(0x%lx), target(0x%lx), type(%d), taken(%d)\n", idx, rec.pc, rec.target, rec.type, rec.taken);
}

inline void print_record() {
int idx = 0;
BR *rec = record;
while (rec->pc != 0) {
output_branch_record(*rec, idx);
idx++;
rec++;
}
}

string Trim(string& str)
{
str.erase(0,str.find_first_not_of(" \t\r\n"));
str.erase(str.find_last_not_of(" \t\r\n") + 1);
return str;
}


// reads branch records into global arrays
void init_branch_record(const char *branch, const uint64_t rate) {

#ifndef LIGHTQS
if (branch == NULL) {
printf("Branch trace file not provided, oracle branch should not work!\n");
return ;
}
// assert(branch != NULL);
record_orig = (BR *)(malloc(MAX_BR_NUM * sizeof(BR)));
// initiate the whole buffer to zero
memset((void *) record_orig, 0, MAX_BR_NUM * sizeof(BR));

ifstream fin(branch);
printf("Use %s as the branch golden trace\n",branch);
string line;
int idx = 0;
while (getline(fin, line)) {
istringstream sin(line); //将整行字符串line读入到字符串流istringstream中
vector<string> fields; //声明一个字符串向量
string field;
while (getline(sin, field, ',')) { fields.push_back(field); }
string pc = Trim(fields[0]);
string taken = Trim(fields[1]);
string type = Trim(fields[2]);
string target = Trim(fields[3]);
stringstream ss, ss1;
ss << std::hex << pc;
ss >> record_orig[idx].pc;
ss1 << std::hex << target;
ss1 >> record_orig[idx].target;
record_orig[idx].taken = taken[0] - '0';
record_orig[idx].type = type[0] - '0';
idx++;
}
#endif // LIGHTQS
#ifdef LIGHTQS
record = (BR *)ahead_isa_query_br_log();
#endif // LIGHTQS
#ifndef LIGHTQS
int miss_rate = rate;
// default set to zero
if (miss_rate < 0) miss_rate = 0;
int num_reverted = 0;
if (miss_rate > 0) {
srand( (unsigned)time( NULL ) );
for (int i = 0; i < idx; i++) {
// revert as a rate of miss_rate
if (rand() % 100 < miss_rate) {
record[i].taken = ~record[i].taken;
num_reverted++;
}
}
}
printf("Branch miss rate is set to %d%%, totally %d predictions are reverted\n", miss_rate, num_reverted);
#endif // LIGHTQS
reset = 0;
}

void free_branch_record(){
// free(record);
// do not free array from so
}

// int main() {
// init_branch_record("");
// return 0;
// }

// TODO: read branch record arrays using idx, and give pc for validation
// read rNum records from array starting at rIdx
// the management of rIdx is left to BPU
// we don't need rNum because we always want to read records in order
extern "C" void branch_prediction_helper(
uint64_t rIdx,
uint64_t *target1, uint64_t *target2,
uint64_t *target3, uint64_t *target4,
uint64_t *target5, uint64_t *target6,
uint64_t *target7, uint64_t *target8,
uint64_t *target9, uint64_t *target10,
uint64_t *target11, uint64_t *target12,
uint64_t *target13, uint64_t *target14,
uint64_t *target15, uint64_t *target16,
uint64_t *pc1, uint64_t *pc2,
uint64_t *pc3, uint64_t *pc4,
uint64_t *pc5, uint64_t *pc6,
uint64_t *pc7, uint64_t *pc8,
uint64_t *pc9, uint64_t *pc10,
uint64_t *pc11, uint64_t *pc12,
uint64_t *pc13, uint64_t *pc14,
uint64_t *pc15, uint64_t *pc16,
uint8_t *taken1, uint8_t *taken2,
uint8_t *taken3, uint8_t *taken4,
uint8_t *taken5, uint8_t *taken6,
uint8_t *taken7, uint8_t *taken8,
uint8_t *taken9, uint8_t *taken10,
uint8_t *taken11, uint8_t *taken12,
uint8_t *taken13, uint8_t *taken14,
uint8_t *taken15, uint8_t *taken16,
uint8_t *type1, uint8_t *type2,
uint8_t *type3, uint8_t *type4,
uint8_t *type5, uint8_t *type6,
uint8_t *type7, uint8_t *type8,
uint8_t *type9, uint8_t *type10,
uint8_t *type11, uint8_t *type12,
uint8_t *type13, uint8_t *type14,
uint8_t *type15, uint8_t *type16,
uint64_t redirectIdx,
uint64_t *redirectpc1, uint64_t *redirectpc2, uint64_t *redirectpc3, uint64_t *redirectpc4, uint64_t *redirectpc5, uint64_t *redirectpc6, uint64_t *redirectpc7, uint64_t *redirectpc8,
uint64_t *redirectpc9, uint64_t *redirectpc10, uint64_t *redirectpc11, uint64_t *redirectpc12, uint64_t *redirectpc13, uint64_t *redirectpc14, uint64_t *redirectpc15, uint64_t *redirectpc16
) {
static uint64_t last = 0, pre_last = 0;
if (rIdx - pre_last == 30) {
// consecutive miss
printf("Miss rIdx = %llu last = %llu\n", rIdx, last);
// exit(-1);
}
pre_last = last;
last = rIdx;

if (reset) return;

if (rIdx >= MAX_BR_NUM) {
printf("ERROR: branch record idx = %ld out of bound!\n", rIdx);
return;
}
if (redirectIdx >= MAX_BR_NUM) {
printf("Error: branch redirect record idx = %ld out of bound!\n", redirectIdx);
return;
}
//printf("-- rIdx :%ld pc: %lx taken:%d\n",rIdx,record[rIdx].pc,record[rIdx].taken);
*taken1 = record[rIdx].taken;
*taken2 = record[rIdx + 1].taken;
*taken3 = record[rIdx + 2].taken;
*taken4 = record[rIdx + 3].taken;
*taken5 = record[rIdx + 4].taken;
*taken6 = record[rIdx + 5].taken;
*taken7 = record[rIdx + 6].taken;
*taken8 = record[rIdx + 7].taken;
*taken9 = record[rIdx + 8].taken;
*taken10 = record[rIdx + 9].taken;
*taken11 = record[rIdx + 10].taken;
*taken12 = record[rIdx + 11].taken;
*taken13 = record[rIdx + 12].taken;
*taken14 = record[rIdx + 13].taken;
*taken15 = record[rIdx + 14].taken;
*taken16 = record[rIdx + 15].taken;
*pc1 = record[rIdx].pc;
*pc2 = record[rIdx + 1].pc;
*pc3 = record[rIdx + 2].pc;
*pc4 = record[rIdx + 3].pc;
*pc5 = record[rIdx + 4].pc;
*pc6 = record[rIdx + 5].pc;
*pc7 = record[rIdx + 6].pc;
*pc8 = record[rIdx + 7].pc;
*pc9 = record[rIdx + 8].pc;
*pc10 = record[rIdx + 9].pc;
*pc11 = record[rIdx + 10].pc;
*pc12 = record[rIdx + 11].pc;
*pc13 = record[rIdx + 12].pc;
*pc14 = record[rIdx + 13].pc;
*pc15 = record[rIdx + 14].pc;
*pc16 = record[rIdx + 15].pc;
*target1 = record[rIdx].target;
*target2 = record[rIdx + 1].target;
*target3 = record[rIdx + 2].target;
*target4 = record[rIdx + 3].target;
*target5 = record[rIdx + 4].target;
*target6 = record[rIdx + 5].target;
*target7 = record[rIdx + 6].target;
*target8 = record[rIdx + 7].target;
*target9 = record[rIdx + 8].target;
*target10 = record[rIdx + 9].target;
*target11 = record[rIdx + 10].target;
*target12 = record[rIdx + 11].target;
*target13 = record[rIdx + 12].target;
*target14 = record[rIdx + 13].target;
*target15 = record[rIdx + 14].target;
*target16 = record[rIdx + 15].target;
*type1 = record[rIdx].type;
*type2 = record[rIdx + 1].type;
*type3 = record[rIdx + 2].type;
*type4 = record[rIdx + 3].type;
*type5 = record[rIdx + 4].type;
*type6 = record[rIdx + 5].type;
*type7 = record[rIdx + 6].type;
*type8 = record[rIdx + 7].type;
*type9 = record[rIdx + 8].type;
*type10 = record[rIdx + 9].type;
*type11 = record[rIdx + 10].type;
*type12 = record[rIdx + 11].type;
*type13 = record[rIdx + 12].type;
*type14 = record[rIdx + 13].type;
*type15 = record[rIdx + 14].type;
*type16 = record[rIdx + 15].type;
*redirectpc1 = record[redirectIdx].pc;
*redirectpc2 = record[redirectIdx + 1].pc;
*redirectpc3 = record[redirectIdx + 2].pc;
*redirectpc4 = record[redirectIdx + 3].pc;
*redirectpc5 = record[redirectIdx + 4].pc;
*redirectpc6 = record[redirectIdx + 5].pc;
*redirectpc7 = record[redirectIdx + 6].pc;
*redirectpc8 = record[redirectIdx + 7].pc;
*redirectpc9 = record[redirectIdx + 8].pc;
*redirectpc10 = record[redirectIdx + 9].pc;
*redirectpc11 = record[redirectIdx + 10].pc;
*redirectpc12 = record[redirectIdx + 11].pc;
*redirectpc13 = record[redirectIdx + 12].pc;
*redirectpc14 = record[redirectIdx + 13].pc;
*redirectpc15 = record[redirectIdx + 14].pc;
*redirectpc16 = record[redirectIdx + 15].pc;
}
45 changes: 45 additions & 0 deletions src/test/csrc/difftest/difftest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,11 @@ int Difftest::step() {
do_instr_commit(i);
dut.commit[i].valid = 0;
num_commit++;
++total_commit;
// TODO: let do_instr_commit return number of instructions in this uop
if (dut.commit[i].fused) {
num_commit++;
++total_commit;
}
}
}
Expand Down Expand Up @@ -205,6 +207,9 @@ int Difftest::step() {
void Difftest::do_interrupt() {
state->record_abnormal_inst(dut.event.exceptionPC, dut.event.exceptionInst, RET_INT, dut.event.interrupt);
proxy->raise_intr(dut.event.interrupt | (1ULL << 63));
#ifdef LIGHTQS
proxy->ahead_raise_intr(dut.event.interrupt | (1ULL << 64), total_commit);
#endif // LIGHTQS
progress = true;
}

Expand All @@ -213,12 +218,24 @@ void Difftest::do_exception() {
if (dut.event.exception == 12 || dut.event.exception == 13 || dut.event.exception == 15) {
// printf("exception cause: %d\n", dut.event.exception);
struct ExecutionGuide guide;
#ifdef LIGHTQS
struct ExecutionGuide ahead_guide;
#endif // LIGHTQS
guide.force_raise_exception = true;
guide.exception_num = dut.event.exception;
guide.mtval = dut.csr.mtval;
guide.stval = dut.csr.stval;
guide.force_set_jump_target = false;
proxy->guided_exec(&guide);

#ifdef LIGHTQS
ahead_guide.force_raise_exception = true;
ahead_guide.exception_num = dut.event.exception;
ahead_guide.mtval = dut.csr.mtval;
ahead_guide.stval = dut.csr.stval;
ahead_guide.force_set_jump_target = false;
proxy->ahead_guided_exec(&ahead_guide, total_commit);
#endif // LIGHTQS
} else {
#ifdef DEBUG_MODE_DIFF
if(DEBUG_MEM_REGION(true, dut.event.exceptionPC)){
Expand All @@ -227,6 +244,9 @@ void Difftest::do_exception() {
}
#endif
proxy->exec(1);
#ifdef LIGHTQS
proxy->ahead_exec(1);
#endif // LIGHTQS
}
progress = true;
}
Expand Down Expand Up @@ -262,6 +282,9 @@ void Difftest::do_instr_commit(int i) {
struct SyncState sync;
sync.lrscValid = dut.lrsc.success;
proxy->uarchstatus_cpy((uint64_t*)&sync, DUT_TO_REF); // sync lr/sc microarchitectural regs
#ifdef LIGHTQS
proxy->ahead_uarchstatus_cpy((uint64_t*)&sync, DUT_TO_REF, total_commit);
#endif // LIGHTQS
// clear SC instruction valid bit
dut.lrsc.valid = 0;
}
Expand All @@ -279,16 +302,29 @@ void Difftest::do_instr_commit(int i) {
ref_regs_ptr[dut.commit[i].wdest] = get_commit_data(i);
// printf("Debug Mode? %x is ls? %x\n", DEBUG_MEM_REGION(dut.commit[i].valid, dut.commit[i].pc), IS_LOAD_STORE(dut.commit[i].inst));
// printf("skip %x %x %x %x %x\n", dut.commit[i].pc, dut.commit[i].inst, get_commit_data(i), dut.commit[i].wpdest, dut.commit[i].wdest);
#ifdef LIGHTQS_DEBUG
printf("total commit %d, skip pc == %lx\n", total_commit, dut.commit[i].pc);
#endif // LIGHTQS_DEBUG
#ifdef LIGHTQS
proxy->ahead_regcpy(ref_regs_ptr, DIFFTEST_TO_REF, true, total_commit);
#endif // LIGHTQS
}
proxy->regcpy(ref_regs_ptr, DIFFTEST_TO_REF);
return;
}

// single step exec
proxy->exec(1);
#ifdef LIGHTQS
proxy->ahead_exec(1);
#endif // LIGHTQS
// printf("intentionally ahead exec\n");
// when there's a fused instruction, let proxy execute one more instruction.
if (dut.commit[i].fused) {
proxy->exec(1);
#ifdef LIGHTQS
proxy->ahead_exec(1);
#endif // LIGHTQS
}

// Handle load instruction carefully for SMP
Expand Down Expand Up @@ -384,6 +420,15 @@ void Difftest::do_first_instr_commit() {
// If this is main sim thread, simulator has its own initial config
// If this process is checkpoint wakeuped, simulator's config has already been updated,
// do not override it.


// run ahead part
#ifdef LIGHTQS
proxy->ahead_load_flash_bin(get_flash_path(), get_flash_size());
proxy->ahead_memcpy(0x80000000, get_img_start(), get_img_size(), DIFFTEST_TO_REF);
proxy->ahead_regcpy(dut_regs_ptr, DIFFTEST_TO_REF, false, 0);
proxy->ahead_runahead_init();
#endif // LIGHTQS
}
}

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 @@ -310,6 +310,7 @@ class Difftest {
// Initialize difftest environments
Difftest(int coreid);
DIFF_PROXY *proxy = NULL;
uint64_t total_commit = 0;
uint32_t num_commit = 0; // # of commits if made progress
bool has_commit = false;
// Trigger a difftest checking procdure
Expand Down
Loading