提交 8f60341d 编写于 作者: L LinJiawei

Merge remote-tracking branch 'origin/master' into fix-brq

......@@ -9,6 +9,7 @@ import xiangshan.utils._
import xiangshan.backend.regfile.RfWritePort
import utils._
import bus.simplebus._
import noop.AddressSpace
object LSUOpType {
def lb = "b000000".U
......@@ -149,7 +150,7 @@ class Lsu extends Exu(
io.out.bits.uop <> io.in.bits.uop
io.out.bits.data := Mux(partialLoad, rdataPartialLoad, rdata)
// io.out.bits.debug.isMMIO := AddressSpace.isMMIO(addr) && io.out.valid
io.out.bits.debug.isMMIO := false.B //for debug
io.out.bits.debug.isMMIO := AddressSpace.isMMIO(addr) //for debug
// if store, add it to store queue
val stqEnqueue = valid && isStore && !stqFull
......
......@@ -82,55 +82,60 @@ class Roq(implicit val p: XSConfig) extends XSModule {
}
// Commit uop to Rename
val shouldWalkVec = Wire(Vec(CommitWidth, Bool()))
shouldWalkVec(0) := ringBufferWalk =/= ringBufferWalkTarget
(1 until CommitWidth).map(i => shouldWalkVec(i) := (ringBufferWalk + i.U) =/= ringBufferWalkTarget && shouldWalkVec(i - 1))
val walkFinished = (0 until CommitWidth).map(i => (ringBufferWalk + i.U) === ringBufferWalkTarget).reduce(_||_) //FIXIT!!!!!!
for(i <- 0 until CommitWidth){
when(state === s_idle){
val canCommit = if(i!=0) io.commits(i-1).valid else true.B
io.commits(i).valid := valid(ringBufferTail+i.U) && writebacked(ringBufferTail+i.U) && canCommit
io.commits(i).bits.uop := microOp(ringBufferTail+i.U)
when(io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.rfWen){ archRF(microOp(ringBufferTail+i.U).ctrl.ldest) := exuData(ringBufferTail+i.U) }
when(io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.rfWen && microOp(ringBufferTail+i.U).ctrl.ldest =/= 0.U){
archRF(microOp(ringBufferTail+i.U).ctrl.ldest) := exuData(ringBufferTail+i.U)
} // for difftest
when(io.commits(i).valid){valid(ringBufferTail+i.U) := false.B}
XSInfo(io.commits(i).valid, "retired pc %x wen %d ldst %d data %x\n", microOp(ringBufferTail+i.U).cf.pc, microOp(ringBufferTail+i.U).ctrl.rfWen, microOp(ringBufferTail+i.U).ctrl.ldest, exuData(ringBufferTail+i.U))
}.otherwise{//state === s_walk
io.commits(i).valid := valid(ringBufferWalk+i.U)
io.commits(i).valid := valid(ringBufferWalk+i.U) && shouldWalkVec(i)
io.commits(i).bits.uop := microOp(ringBufferWalk+i.U)
valid(ringBufferWalk+i.U) := false.B
when(shouldWalkVec(i)){
valid(ringBufferWalk+i.U) := false.B
}
XSInfo(io.commits(i).valid && shouldWalkVec(i), "walked pc %x wen %d ldst %d data %x\n", microOp(ringBufferTail+i.U).cf.pc, microOp(ringBufferTail+i.U).ctrl.rfWen, microOp(ringBufferTail+i.U).ctrl.ldest, exuData(ringBufferTail+i.U))
}
io.commits(i).bits.isWalk := state === s_walk
}
for(i <- 0 until CommitWidth){
XSInfo(io.commits(i).valid && state =/= s_walk, "retired pc %x wen %d ldst %d data %x\n", microOp(ringBufferTail+i.U).cf.pc, microOp(ringBufferTail+i.U).ctrl.rfWen, microOp(ringBufferTail+i.U).ctrl.ldest, exuData(ringBufferTail+i.U))
}
for(i <- 0 until CommitWidth){
XSInfo(io.commits(i).valid && state === s_walk, "walked pc %x wen %d ldst %d data %x\n", microOp(ringBufferTail+i.U).cf.pc, microOp(ringBufferTail+i.U).ctrl.rfWen, microOp(ringBufferTail+i.U).ctrl.ldest, exuData(ringBufferTail+i.U))
when(state===s_walk) {
//exit walk state when all roq entry is commited
when(walkFinished) {
state := s_idle
}
ringBufferWalkExtended := ringBufferWalkExtended + CommitWidth.U
XSInfo("rolling back: head %d tail %d walk %d\n", ringBufferHead, ringBufferTail, ringBufferWalk)
}
// move tail ptr
val validCommit = VecInit((0 until CommitWidth).map(i => io.commits(i).valid)).asUInt
when(state === s_idle){
ringBufferTailExtended := ringBufferTailExtended + PopCount(validCommit)
}
val retireCounter = Mux(state === s_idle, PopCount(validCommit), 0.U)
// commit store
val validScommit = WireInit(VecInit((0 until CommitWidth).map(i => io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.fuType === FuType.ldu && microOp(ringBufferTail+i.U).ctrl.fuOpType(3)))) //FIXIT
io.scommit := PopCount(validScommit.asUInt)
XSInfo(retireCounter > 0.U, "retired %d insts\n", retireCounter)
for(i <- 0 until CommitWidth) {
XSInfo(io.commits(i).valid, "retired pc at commmit(%d) is: %d 0x%x\n",
i.U, ringBufferTail+i.U, microOp(ringBufferTail+i.U).cf.pc)
XSInfo(io.commits(i).valid && exuDebug(ringBufferTail+i.U).isMMIO, "difftest skiped pc0x%x\n", microOp(ringBufferTail+i.U).cf.pc)
}
//TODO: add walkFin Vec, io.commits(i).valid depends on it
val walkFinished = (0 until CommitWidth).map(i => (ringBufferWalk + i.U) === ringBufferWalkTarget).reduce(_||_) //FIXIT!!!!!!
when(state===s_walk) {
//exit walk state when all roq entry is commited
when(walkFinished) {
state := s_idle
}
ringBufferWalkExtended := ringBufferWalkExtended + CommitWidth.U
XSInfo("rolling back: head %d tail %d walk %d\n", ringBufferHead, ringBufferTail, ringBufferWalk)
}
// commit store to lsu
val validScommit = WireInit(VecInit((0 until CommitWidth).map(i => io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.fuType === FuType.ldu && microOp(ringBufferTail+i.U).ctrl.fuOpType(3)))) //FIXIT
io.scommit := PopCount(validScommit.asUInt)
// when redirect, walk back roq entries
val newHead = io.brqRedirect.bits.roqIdx + 1.U
when(io.brqRedirect.valid){
state := s_walk
......@@ -170,13 +175,31 @@ class Roq(implicit val p: XSConfig) extends XSModule {
val firstValidCommit = ringBufferTail + PriorityMux(validCommit, VecInit(List.tabulate(CommitWidth)(_.U)))
val emptyCsr = WireInit(0.U(64.W))
val skip = Wire(Vec(CommitWidth, Bool()))
val wen = Wire(Vec(CommitWidth, Bool()))
val wdata = Wire(Vec(CommitWidth, UInt(XLEN.W)))
val wdst = Wire(Vec(CommitWidth, UInt(32.W)))
val wpc = Wire(Vec(CommitWidth, UInt(VAddrBits.W)))
for(i <- 0 until CommitWidth){
// io.commits(i).valid
skip(i) := exuDebug(ringBufferTail+i.U).isMMIO && io.commits(i).valid
wen(i) := io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.rfWen && microOp(ringBufferTail+i.U).ctrl.ldest =/= 0.U
wdata(i) := exuData(ringBufferTail+i.U)
wdst(i) := microOp(ringBufferTail+i.U).ctrl.ldest
wpc(i) := microOp(ringBufferTail+i.U).cf.pc
}
if(!p.FPGAPlatform){
BoringUtils.addSource(RegNext(retireCounter), "difftestCommit")
BoringUtils.addSource(RegNext(microOp(firstValidCommit).cf.pc), "difftestThisPC")//first valid PC
BoringUtils.addSource(RegNext(microOp(firstValidCommit).cf.instr), "difftestThisINST")//first valid inst
BoringUtils.addSource(archRF, "difftestRegs")//arch RegFile
BoringUtils.addSource(RegNext(false.B), "difftestSkip")//SKIP
BoringUtils.addSource(RegNext(skip.asUInt), "difftestSkip")
BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
BoringUtils.addSource(RegNext(wen.asUInt), "difftestWen")
BoringUtils.addSource(RegNext(wpc), "difftestWpc")
BoringUtils.addSource(RegNext(wdata), "difftestWdata")
BoringUtils.addSource(RegNext(wdst), "difftestWdst")
BoringUtils.addSource(RegNext(0.U), "difftestIntrNO")
//TODO: skip insts that commited in the same cycle ahead of exception
......
......@@ -9,6 +9,9 @@
#endif
#define printCSR(x) printf(""#x": 0x%016lx ", x)
#define selectBit(src, x) (src & (1 << x))
#define _str(x) #x
#define micro2str(x) _str(x)
void (*ref_difftest_memcpy_from_dut)(paddr_t dest, void *src, size_t n) = NULL;
void (*ref_difftest_getregs)(void *c) = NULL;
......@@ -39,6 +42,7 @@ void difftest_skip_dut() {
void init_difftest(uint64_t *reg) {
void *handle;
handle = dlopen(REF_SO, RTLD_LAZY | RTLD_DEEPBIND);
printf("Using %s for difftest\n", micro2str(REF_SO));
assert(handle);
ref_difftest_memcpy_from_dut = (void (*)(paddr_t, void *, size_t))dlsym(handle, "difftest_memcpy_from_dut");
......@@ -84,10 +88,11 @@ static const char *reg_name[DIFFTEST_NR_REG] = {
};
int difftest_step(int commit, uint64_t *reg_scala, uint32_t this_inst,
int skip, int isRVC, uint64_t intrNO, int priviledgeMode) {
int skip, int isRVC, uint64_t *wpc, uint64_t *wdata, uint32_t *wdst, int wen, uint64_t intrNO, int priviledgeMode) {
assert(!skip && !isRVC && intrNO == 0);
assert(!isRVC && intrNO == 0);
#define DEBUG_RETIRE_TRACE_SIZE 16
#define DEBUG_WB_TRACE_SIZE 16
uint64_t ref_r[DIFFTEST_NR_REG];
uint64_t this_pc = reg_scala[DIFFTEST_THIS_PC];
......@@ -97,21 +102,26 @@ int difftest_step(int commit, uint64_t *reg_scala, uint32_t this_inst,
static uint64_t pc_retire_queue[DEBUG_RETIRE_TRACE_SIZE] = {0};
static uint32_t inst_retire_queue[DEBUG_RETIRE_TRACE_SIZE] = {0};
static uint32_t retire_cnt_queue[DEBUG_RETIRE_TRACE_SIZE] = {0};
static int pc_retire_pointer = 7;
if (skip) {
// printf("diff pc: %x isRVC %x\n", this_pc, isRVC);
// MMIO accessing should not be a branch or jump, just +2/+4 to get the next pc
reg_scala[DIFFTEST_THIS_PC] += isRVC ? 2 : 4;
nemu_this_pc += isRVC ? 2 : 4;
// to skip the checking of an instruction, just copy the reg state to reference design
ref_difftest_setregs(reg_scala);
pc_retire_pointer = (pc_retire_pointer+1) % DEBUG_RETIRE_TRACE_SIZE;
pc_retire_queue[pc_retire_pointer] = this_pc;
inst_retire_queue[pc_retire_pointer] = this_inst;
retire_cnt_queue[pc_retire_pointer] = commit;
return 0;
}
static int pc_retire_pointer = DEBUG_RETIRE_TRACE_SIZE-1;
static uint64_t pc_wb_queue[DEBUG_WB_TRACE_SIZE] = {0};
static uint64_t wen_wb_queue[DEBUG_WB_TRACE_SIZE] = {0};
static uint32_t wdst_wb_queue[DEBUG_WB_TRACE_SIZE] = {0};
static uint64_t wdata_wb_queue[DEBUG_WB_TRACE_SIZE] = {0};
static int wb_pointer = 0;
// if (skip) {
// // printf("diff pc: %x isRVC %x\n", this_pc, isRVC);
// // MMIO accessing should not be a branch or jump, just +2/+4 to get the next pc
// reg_scala[DIFFTEST_THIS_PC] += isRVC ? 2 : 4;
// nemu_this_pc += isRVC ? 2 : 4;
// // to skip the checking of an instruction, just copy the reg state to reference design
// ref_difftest_setregs(reg_scala);
// pc_retire_pointer = (pc_retire_pointer+1) % DEBUG_RETIRE_TRACE_SIZE;
// pc_retire_queue[pc_retire_pointer] = this_pc;
// inst_retire_queue[pc_retire_pointer] = this_inst;
// retire_cnt_queue[pc_retire_pointer] = commit;
// return 0;
// }
if (intrNO) {
ref_difftest_raise_intr(intrNO);
......@@ -119,7 +129,26 @@ int difftest_step(int commit, uint64_t *reg_scala, uint32_t this_inst,
}
assert(commit > 0 && commit <= 6);
ref_difftest_exec(commit);
for(int i = 0; i < commit; i++){
pc_wb_queue[wb_pointer] = wpc[i];
wen_wb_queue[wb_pointer] = selectBit(wen, i);
wdst_wb_queue[wb_pointer] = wdst[i];
wdata_wb_queue[wb_pointer] = wdata[i];
wb_pointer = (wb_pointer+1) % DEBUG_WB_TRACE_SIZE;
if(selectBit(skip, i)){
// MMIO accessing should not be a branch or jump, just +2/+4 to get the next pc
printf("SKIP %d\n", i);
// to skip the checking of an instruction, just copy the reg state to reference design
ref_difftest_getregs(&ref_r);
ref_r[DIFFTEST_THIS_PC] += 4; //TODO: RVC
if(selectBit(wen, i)){
ref_r[wdst[i]] = wdata[i];
}
ref_difftest_setregs(ref_r);
}else{
ref_difftest_exec(1);
}
}
ref_difftest_getregs(&ref_r);
uint64_t next_pc = ref_r[DIFFTEST_THIS_PC];
......@@ -151,6 +180,10 @@ int difftest_step(int commit, uint64_t *reg_scala, uint32_t this_inst,
for(j = 0; j < DEBUG_RETIRE_TRACE_SIZE; j++){
printf("retire trace [%x]: pc %010lx inst %08x cmtcnt %d %s\n", j, pc_retire_queue[j], inst_retire_queue[j], retire_cnt_queue[j], (j==pc_retire_pointer)?"<--":"");
}
printf("\n============== WB Trace ==============\n");
for(j = 0; j < DEBUG_WB_TRACE_SIZE; j++){
printf("wb trace [%x]: pc %010lx wen %x dst %08x data %016lx %s\n", j, pc_wb_queue[j], wen_wb_queue[j]!=0, wdst_wb_queue[j], wdata_wb_queue[j], (j==((wb_pointer-1)%DEBUG_WB_TRACE_SIZE))?"<--":"");
}
printf("\n============== Reg Diff ==============\n");
ref_isa_reg_display();
printCSR(priviledgeMode);
......
......@@ -13,6 +13,7 @@
#include <verilated_vcd_c.h> // Trace file format header
#endif
#define DIFFTEST_WIDTH 6
class Emulator {
const char *image;
......@@ -51,6 +52,19 @@ class Emulator {
r[DIFFTEST_SCAUSE ] = dut_ptr->io_difftest_scause;
}
void 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);
return;
}
public:
// argv decay to the secondary pointer
Emulator(int argc, const char *argv[]):
......@@ -119,6 +133,10 @@ class Emulator {
uint64_t lastcommit = n;
int hascommit = 0;
const int stuck_limit = 2000;
static uint32_t wdst[DIFFTEST_WIDTH];
static uint64_t wdata[DIFFTEST_WIDTH];
static uint64_t wpc[DIFFTEST_WIDTH];
#if VM_TRACE
Verilated::traceEverOn(true); // Verilator must compute traced signals
......@@ -156,11 +174,13 @@ class Emulator {
if (dut_ptr->io_difftest_commit && hascommit) {
uint64_t reg[DIFFTEST_NR_REG];
read_emu_regs(reg);
read_wb_info(wpc, wdata, wdst);
extern int difftest_step(int commit, uint64_t *reg_scala, uint32_t this_inst,
int skip, int isRVC, uint64_t intrNO, int priviledgeMode);
int skip, int isRVC, uint64_t *wpc, uint64_t *wdata, uint32_t *wdst, int wen, uint64_t intrNO, int priviledgeMode);
if (difftest_step(dut_ptr->io_difftest_commit, reg, dut_ptr->io_difftest_thisINST,
dut_ptr->io_difftest_skip, dut_ptr->io_difftest_isRVC,
wpc, wdata, wdst, dut_ptr->io_difftest_wen,
dut_ptr->io_difftest_intrNO, dut_ptr->io_difftest_priviledgeMode)) {
#if VM_TRACE
tfp->close();
......
......@@ -14,7 +14,11 @@ class DiffTestIO extends Bundle {
val commit = Output(UInt(32.W))
val thisPC = Output(UInt(64.W))
val thisINST = Output(UInt(32.W))
val skip = Output(Bool())
val skip = Output(UInt(32.W))
val wen = Output(UInt(32.W))
val wdata = Output(Vec(6, UInt(64.W))) // set difftest width to 6
val wdst = Output(Vec(6, UInt(32.W))) // set difftest width to 6
val wpc = Output(Vec(6, UInt(39.W))) // set difftest width to 6
val isRVC = Output(Bool())
val intrNO = Output(UInt(64.W))
......@@ -62,6 +66,10 @@ class XSSimTop extends Module {
BoringUtils.addSink(difftest.thisINST, "difftestThisINST")
BoringUtils.addSink(difftest.skip, "difftestSkip")
BoringUtils.addSink(difftest.isRVC, "difftestIsRVC")
BoringUtils.addSink(difftest.wen, "difftestWen")
BoringUtils.addSink(difftest.wdata, "difftestWdata")
BoringUtils.addSink(difftest.wdst, "difftestWdst")
BoringUtils.addSink(difftest.wpc, "difftestWpc")
BoringUtils.addSink(difftest.intrNO, "difftestIntrNO")
BoringUtils.addSink(difftest.r, "difftestRegs")
BoringUtils.addSink(difftest.priviledgeMode, "difftestMode")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册