提交 d0e78cc9 编写于 作者: Fa_wang's avatar Fa_wang

Merge remote-tracking branch 'origin/master' into opt-sbuffer-timing

......@@ -56,7 +56,7 @@ $(SIM_TOP_V): $(SCALA_FILE) $(TEST_FILE)
date -R
mill XiangShan.test.runMain $(SIMTOP) -X verilog -td $(@D) --full-stacktrace --output-file $(@F) $(SIM_ARGS)
sed -i '/module XSSimTop/,/endmodule/d' $(SIM_TOP_V)
sed -i -e 's/$$fatal/$$finish/g' $(SIM_TOP_V)
sed -i -e 's/$$fatal/xs_assert(`__LINE__)/g' $(SIM_TOP_V)
date -R
EMU_TOP = XSSimSoC
......@@ -80,7 +80,7 @@ endif
# Verilator multi-thread support
EMU_THREADS ?= 1
ifneq ($(EMU_THREADS),1)
VEXTRA_FLAGS += --threads $(EMU_THREADS) --threads-dpi none
VEXTRA_FLAGS += --threads $(EMU_THREADS) --threads-dpi all
endif
# Verilator savable
......
Subproject commit 147bdcc4a26c74e5d7a47e3d667d456699d6d11f
Subproject commit 9cf18f1173443e2542990c090a69bdd62d26228d
......@@ -597,58 +597,92 @@ class CSR extends FunctionUnit with HasCSRConst
tlbBundle.priv.imode := priviledgeMode
tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
val hasInstrPageFault = csrio.exception.bits.cf.exceptionVec(instrPageFault) && csrio.exception.valid
val hasLoadPageFault = csrio.exception.bits.cf.exceptionVec(loadPageFault) && csrio.exception.valid
val hasStorePageFault = csrio.exception.bits.cf.exceptionVec(storePageFault) && csrio.exception.valid
val hasStoreAddrMisaligned = csrio.exception.bits.cf.exceptionVec(storeAddrMisaligned) && csrio.exception.valid
val hasLoadAddrMisaligned = csrio.exception.bits.cf.exceptionVec(loadAddrMisaligned) && csrio.exception.valid
// Branch control
val retTarget = Wire(UInt(VAddrBits.W))
val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
csrio.redirectOut.valid := valid && func === CSROpType.jmp && !isEcall
csrio.redirectOut.bits := retTarget
flushPipe := resetSatp
XSDebug(csrio.redirectOut.valid, "redirect to %x, pc=%x\n", csrio.redirectOut.bits, cfIn.pc)
// mtval write logic
val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
val tval = Mux(
hasInstrPageFault,
Mux(
csrio.exception.bits.cf.crossPageIPFFix,
SignExt(csrio.exception.bits.cf.pc + 2.U, XLEN),
SignExt(csrio.exception.bits.cf.pc, XLEN)
),
memExceptionAddr
)
when(priviledgeMode === ModeM){
mtval := tval
}.otherwise{
stval := tval
}
retTarget := DontCare
// val illegalEret = TODO
when (valid && isMret) {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
mstatusNew.ie.m := mstatusOld.pie.m
priviledgeMode := mstatusOld.mpp
mstatusNew.pie.m := true.B
mstatusNew.mpp := ModeU
mstatusNew.mprv := 0.U
mstatus := mstatusNew.asUInt
// lr := false.B
retTarget := mepc(VAddrBits-1, 0)
}
when(hasLoadAddrMisaligned || hasStoreAddrMisaligned)
{
mtval := memExceptionAddr
when (valid && isSret && !illegalSModeSret) {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
mstatusNew.ie.s := mstatusOld.pie.s
priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
mstatusNew.pie.s := true.B
mstatusNew.spp := ModeU
mstatus := mstatusNew.asUInt
mstatusNew.mprv := 0.U
// lr := false.B
retTarget := sepc(VAddrBits-1, 0)
}
// Exception and Intr
when (valid && isUret) {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
// mstatusNew.mpp.m := ModeU //TODO: add mode U
mstatusNew.ie.u := mstatusOld.pie.u
priviledgeMode := ModeU
mstatusNew.pie.u := true.B
mstatus := mstatusNew.asUInt
retTarget := uepc(VAddrBits-1, 0)
}
// interrupts
XSDebug(csrio.redirectOut.valid,
"Rediret %x isSret:%d retTarget:%x sepc:%x cfInpc:%x valid:%d\n",
csrio.redirectOut.bits, isSret, retTarget, sepc, cfIn.pc, valid
)
io.in.ready := true.B
io.out.valid := valid
/**
* Exception and Intr
*/
val ideleg = (mideleg & mip.asUInt)
def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
// send interrupt information to ROQ
val intrVecEnable = Wire(Vec(12, Bool()))
intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
val intrBitSet = intrVec.orR()
csrio.interrupt := intrBitSet
val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
val raiseIntr = intrBitSet && csrio.exception.valid && csrio.isInterrupt
XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.cf.pc, intrNO)
mipWire.t.m := csrio.externalInterrupt.mtip
mipWire.s.m := csrio.externalInterrupt.msip
mipWire.e.m := csrio.externalInterrupt.meip
// interrupts
val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
val raiseIntr = csrio.exception.valid && csrio.isInterrupt
XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.cf.pc, intrNO)
// exceptions
val raiseException = csrio.exception.valid && !csrio.isInterrupt
val hasInstrPageFault = csrio.exception.bits.cf.exceptionVec(instrPageFault) && raiseException
val hasLoadPageFault = csrio.exception.bits.cf.exceptionVec(loadPageFault) && raiseException
val hasStorePageFault = csrio.exception.bits.cf.exceptionVec(storePageFault) && raiseException
val hasStoreAddrMisaligned = csrio.exception.bits.cf.exceptionVec(storeAddrMisaligned) && raiseException
val hasLoadAddrMisaligned = csrio.exception.bits.cf.exceptionVec(loadAddrMisaligned) && raiseException
val csrExceptionVec = Wire(Vec(16, Bool()))
csrExceptionVec.map(_ := false.B)
csrExceptionVec(breakPoint) := io.in.valid && isEbreak
......@@ -676,14 +710,6 @@ class CSR extends FunctionUnit with HasCSRConst
// }
val raiseExceptionIntr = csrio.exception.valid
val retTarget = Wire(UInt(VAddrBits.W))
val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
csrio.redirectOut.valid := valid && func === CSROpType.jmp && !isEcall
csrio.redirectOut.bits := retTarget
flushPipe := resetSatp
XSDebug(csrio.redirectOut.valid, "redirect to %x, pc=%x\n", csrio.redirectOut.bits, cfIn.pc)
XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
csrio.exception.bits.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
)
......@@ -696,53 +722,35 @@ class CSR extends FunctionUnit with HasCSRConst
priviledgeMode
)
// Branch control
// mtval write logic
val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
val tval = Mux(
hasInstrPageFault,
Mux(
csrio.exception.bits.cf.crossPageIPFFix,
SignExt(csrio.exception.bits.cf.pc + 2.U, XLEN),
SignExt(csrio.exception.bits.cf.pc, XLEN)
),
memExceptionAddr
)
when(priviledgeMode === ModeM){
mtval := tval
}.otherwise{
stval := tval
}
}
when(hasLoadAddrMisaligned || hasStoreAddrMisaligned)
{
mtval := memExceptionAddr
}
val deleg = Mux(raiseIntr, mideleg , medeleg)
// val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
csrio.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
retTarget := DontCare
// val illegalEret = TODO
when (valid && isMret) {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
mstatusNew.ie.m := mstatusOld.pie.m
priviledgeMode := mstatusOld.mpp
mstatusNew.pie.m := true.B
mstatusNew.mpp := ModeU
mstatusNew.mprv := 0.U
mstatus := mstatusNew.asUInt
// lr := false.B
retTarget := mepc(VAddrBits-1, 0)
}
when (valid && isSret && !illegalSModeSret) {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
mstatusNew.ie.s := mstatusOld.pie.s
priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
mstatusNew.pie.s := true.B
mstatusNew.spp := ModeU
mstatus := mstatusNew.asUInt
mstatusNew.mprv := 0.U
// lr := false.B
retTarget := sepc(VAddrBits-1, 0)
}
when (valid && isUret) {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
// mstatusNew.mpp.m := ModeU //TODO: add mode U
mstatusNew.ie.u := mstatusOld.pie.u
priviledgeMode := ModeU
mstatusNew.pie.u := true.B
mstatus := mstatusNew.asUInt
retTarget := uepc(VAddrBits-1, 0)
}
when (raiseExceptionIntr) {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
......@@ -771,40 +779,17 @@ class CSR extends FunctionUnit with HasCSRConst
mstatus := mstatusNew.asUInt
}
io.in.ready := true.B
io.out.valid := valid
XSDebug(csrio.redirectOut.valid,
"Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d\n",
csrio.redirectOut.bits,
raiseExceptionIntr,
isSret,
retTarget,
sepc,
delegS,
deleg,
cfIn.pc,
valid
)
XSDebug(raiseExceptionIntr && delegS,
"Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d\n",
csrio.redirectOut.valid,
csrio.redirectOut.bits,
raiseExceptionIntr,
isSret,
retTarget,
sepc,
delegS,
deleg,
cfIn.pc,
valid
"Red(%d, %x) raiseExcepIntr:%d isSret:%d sepc:%x delegs:%d deleg:%x\n",
csrio.redirectOut.valid, csrio.redirectOut.bits, raiseExceptionIntr,
isSret, sepc, delegS, deleg
)
XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
// perfcnt
/**
* Performance counters
*/
val perfCntList = Map(
// "Mcycle" -> (0xb00, "perfCntCondMcycle" ),
// "Minstret" -> (0xb02, "perfCntCondMinstret" ),
......
......@@ -167,32 +167,56 @@ class ReservationStationCtrl
}
// redirect and feedback
// redirect and feedback && wakeup
//
for (i <- 0 until iqSize) {
val cnt = cntQueue(idxQueue(i))
when (!(deqIdx === i.U && deqValid)) {
if (i != 0) { // TODO: combine the two case
val nextIdx = i.U - moveMask(i-1)
// cnt
when (stateQueue(i)===s_replay) {
when (cnt===0.U) { stateQueue(nextIdx) := s_valid }
.otherwise { cnt := cnt - 1.U }
}
// feedback
when (fbMatchVec(i)) {
stateQueue(nextIdx) := Mux(fbHit, s_idle, s_replay)
cnt := Mux(fbHit, cnt, (replayDelay-1).U)
}
// redirect
when (redHitVec(i)) { stateQueue(nextIdx) := s_idle }
// wakeup
val hitVec = io.data.srcUpdate(idxQueue(i))
for (j <- 0 until srcNum) {
when (hitVec(j) && validQueue(i)) {
srcQueue(nextIdx)(j) := true.B
XSDebug(p"srcHit: i:${i.U} j:${j.U} moveMask(${i.U}):${moveMask(i)} nextIdx:${nextIdx}")
}
}
} else { when (!moveMask(i)) {
val nextIdx = i
// cnt
when (stateQueue(i)===s_replay) {
when (cnt===0.U) { stateQueue(nextIdx) := s_valid }
.otherwise { cnt := cnt - 1.U }
}
// feedback
when (fbMatchVec(i)) {
stateQueue(nextIdx) := Mux(fbHit, s_idle, s_replay)
cnt := Mux(fbHit, cnt, (replayDelay-1).U)
}
// redirect
when (redHitVec(i)) { stateQueue(nextIdx) := s_idle }
// wakeup
val hitVec = io.data.srcUpdate(idxQueue(i))
for (j <- 0 until srcNum) {
when (hitVec(j) && validQueue(i)) {
srcQueue(nextIdx)(j) := true.B
XSDebug(p"srcHit: i:${i.U} j:${j.U} moveMask(${i.U}):${moveMask(i)} nextIdx:${nextIdx}")
}
}
}}
}
}
......@@ -235,17 +259,6 @@ class ReservationStationCtrl
p"type:${srcTypeSeq(2)}\n")
}
// wakeup
for(i <- 0 until IssQueSize) {
val hitVec = io.data.srcUpdate(idxQueue(i))
for(j <- 0 until srcNum) {
when (hitVec(j) && validQueue(i)) {
srcQueue(i.U - moveMask(i))(j) := true.B
XSDebug(p"srcHit: i:${i.U} j:${j.U}\n")
}
}
}
// other to Data
io.data.enqPtr := idxQueue(Mux(tailPtr.flag, deqIdx, tailPtr.value))
io.data.deqPtr.valid := selValid
......
......@@ -49,7 +49,7 @@ class FreeList extends XSModule with HasFreeListConsts with HasCircularQueuePtrH
// do checkpoints
// val cpReqs = Vec(RenameWidth, Flipped(ValidIO(new BrqPtr)))
val walk = Flipped(ValidIO(UInt(log2Up(RenameWidth).W)))
val walk = Flipped(ValidIO(UInt(log2Up(CommitWidth + 1).W)))
// dealloc phy regs
val deallocReqs = Input(Vec(CommitWidth, Bool()))
......
......@@ -40,17 +40,17 @@ class Rename extends XSModule {
printRenameInfo(x, y)
}
val fpFreeList, intFreeList = Module(new FreeList).io
val fpRat = Module(new RenameTable(float = true)).io
val intFreeList, fpFreeList = Module(new FreeList).io
val intRat = Module(new RenameTable(float = false)).io
val fpRat = Module(new RenameTable(float = true)).io
val allPhyResource = Seq((intRat, intFreeList, false), (fpRat, fpFreeList, true))
fpFreeList.redirect := io.redirect
intFreeList.redirect := io.redirect
fpRat.redirect := io.redirect
intRat.redirect := io.redirect
fpRat.walkWen := io.roqCommits.isWalk
intRat.walkWen := io.roqCommits.isWalk
allPhyResource.map{ case (rat, freelist, _) =>
rat.redirect := io.redirect
rat.walkWen := io.roqCommits.isWalk
freelist.redirect := io.redirect
freelist.walk.valid := io.roqCommits.isWalk
}
def needDestReg[T <: CfCtrl](fp: Boolean, x: T): Bool = {
{if(fp) x.ctrl.fpWen else x.ctrl.rfWen && (x.ctrl.ldest =/= 0.U)}
......@@ -58,14 +58,15 @@ class Rename extends XSModule {
def needDestRegCommit[T <: RoqCommitInfo](fp: Boolean, x: T): Bool = {
{if(fp) x.fpWen else x.rfWen && (x.ldest =/= 0.U)}
}
fpFreeList.walk.valid := io.roqCommits.isWalk
intFreeList.walk.valid := io.roqCommits.isWalk
fpFreeList.walk.bits := PopCount((0 until CommitWidth).map(i => io.roqCommits.valid(i) && needDestRegCommit(true, io.roqCommits.info(i))))
intFreeList.walk.bits := PopCount((0 until CommitWidth).map(i => io.roqCommits.valid(i) && needDestRegCommit(false, io.roqCommits.info(i))))
fpFreeList.walk.bits := PopCount(io.roqCommits.valid.zip(io.roqCommits.info).map{case (v, i) => v && needDestRegCommit(true, i)})
intFreeList.walk.bits := PopCount(io.roqCommits.valid.zip(io.roqCommits.info).map{case (v, i) => v && needDestRegCommit(false, i)})
// walk has higher priority than allocation and thus we don't use isWalk here
fpFreeList.req.doAlloc := intFreeList.req.canAlloc && io.out(0).ready
intFreeList.req.doAlloc := fpFreeList.req.canAlloc && io.out(0).ready
/**
* Rename: allocate free physical register and update rename table
*/
val uops = Wire(Vec(RenameWidth, new MicroOp))
uops.foreach( uop => {
......@@ -84,7 +85,7 @@ class Rename extends XSModule {
val needIntDest = Wire(Vec(RenameWidth, Bool()))
val hasValid = Cat(io.in.map(_.valid)).orR
val canOut = io.out(0).ready && fpFreeList.req.canAlloc && intFreeList.req.canAlloc && !io.roqCommits.isWalk
for(i <- 0 until RenameWidth) {
for (i <- 0 until RenameWidth) {
uops(i).cf := io.in(i).bits.cf
uops(i).ctrl := io.in(i).bits.ctrl
uops(i).brTag := io.in(i).bits.brTag
......@@ -116,42 +117,17 @@ class Rename extends XSModule {
io.out(i).valid := io.in(i).valid && intFreeList.req.canAlloc && fpFreeList.req.canAlloc && !io.roqCommits.isWalk
io.out(i).bits := uops(i)
// write rename table
def writeRat(fp: Boolean) = {
val rat = if(fp) fpRat else intRat
val freeList = if(fp) fpFreeList else intFreeList
// speculative inst write
val specWen = freeList.req.allocReqs(i) && freeList.req.canAlloc && freeList.req.doAlloc && !io.roqCommits.isWalk
// walk back write
val commitDestValid = io.roqCommits.valid(i) && needDestRegCommit(fp, io.roqCommits.info(i))
val walkWen = commitDestValid && io.roqCommits.isWalk
rat.specWritePorts(i).wen := specWen || walkWen
rat.specWritePorts(i).addr := Mux(specWen, uops(i).ctrl.ldest, io.roqCommits.info(i).ldest)
rat.specWritePorts(i).wdata := Mux(specWen, freeList.req.pdests(i), io.roqCommits.info(i).old_pdest)
XSInfo(walkWen,
{if(fp) p"fp" else p"int "} + p"walk: " +
p" ldest:${rat.specWritePorts(i).addr} old_pdest:${rat.specWritePorts(i).wdata}\n"
)
rat.archWritePorts(i).wen := commitDestValid && !io.roqCommits.isWalk
rat.archWritePorts(i).addr := io.roqCommits.info(i).ldest
rat.archWritePorts(i).wdata := io.roqCommits.info(i).pdest
XSInfo(rat.archWritePorts(i).wen,
{if(fp) p"fp" else p"int "} + p" rat arch: ldest:${rat.archWritePorts(i).addr}" +
p" pdest:${rat.archWritePorts(i).wdata}\n"
)
// write speculative rename table
allPhyResource.map{ case (rat, freelist, _) =>
val specWen = freelist.req.allocReqs(i) && freelist.req.canAlloc && freelist.req.doAlloc && !io.roqCommits.isWalk
freeList.deallocReqs(i) := rat.archWritePorts(i).wen
freeList.deallocPregs(i) := io.roqCommits.info(i).old_pdest
rat.specWritePorts(i).wen := specWen
rat.specWritePorts(i).addr := uops(i).ctrl.ldest
rat.specWritePorts(i).wdata := freelist.req.pdests(i)
freelist.deallocReqs(i) := specWen
}
writeRat(fp = false)
writeRat(fp = true)
// read rename table
def readRat(lsrcList: List[UInt], ldest: UInt, fp: Boolean) = {
val rat = if(fp) fpRat else intRat
......@@ -204,4 +180,42 @@ class Rename extends XSModule {
(fpMatch || intMatch) && io.in(j).bits.ctrl.ldest === io.in(i).bits.ctrl.ldest
}).reverse)
}
/**
* Instructions commit: update freelist and rename table
*/
for (i <- 0 until CommitWidth) {
if (i >= RenameWidth) {
allPhyResource.map{ case (rat, _, _) =>
rat.specWritePorts(i).wen := false.B
rat.specWritePorts(i).addr := DontCare
rat.specWritePorts(i).wdata := DontCare
}
}
allPhyResource.map{ case (rat, freelist, fp) =>
// walk back write
val commitDestValid = io.roqCommits.valid(i) && needDestRegCommit(fp, io.roqCommits.info(i))
when (commitDestValid && io.roqCommits.isWalk) {
rat.specWritePorts(i).wen := true.B
rat.specWritePorts(i).addr := io.roqCommits.info(i).ldest
rat.specWritePorts(i).wdata := io.roqCommits.info(i).old_pdest
XSInfo({if(fp) p"fp" else p"int "} + p"walk: " +
p" ldest:${rat.specWritePorts(i).addr} old_pdest:${rat.specWritePorts(i).wdata}\n")
}
rat.archWritePorts(i).wen := commitDestValid && !io.roqCommits.isWalk
rat.archWritePorts(i).addr := io.roqCommits.info(i).ldest
rat.archWritePorts(i).wdata := io.roqCommits.info(i).pdest
XSInfo(rat.archWritePorts(i).wen,
{if(fp) p"fp" else p"int "} + p" rat arch: ldest:${rat.archWritePorts(i).addr}" +
p" pdest:${rat.archWritePorts(i).wdata}\n"
)
freelist.deallocReqs(i) := rat.archWritePorts(i).wen
freelist.deallocPregs(i) := io.roqCommits.info(i).old_pdest
}
}
}
......@@ -20,7 +20,7 @@ class RenameTable(float: Boolean) extends XSModule {
val redirect = Flipped(ValidIO(new Redirect))
val walkWen = Input(Bool())
val readPorts = Vec({if(float) 4 else 3} * RenameWidth, new RatReadPort)
val specWritePorts = Vec(RenameWidth, new RatWritePort)
val specWritePorts = Vec(CommitWidth, new RatWritePort)
val archWritePorts = Vec(CommitWidth, new RatWritePort)
})
......
......@@ -161,6 +161,46 @@ class RoqEnqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
}
// class RoqStateWrapper extends XSModule with HasCircularQueuePtrHelper {
// val io = IO(new Bundle {
// val redirect = ValidIO(new Redirect)
// val raddr = Vec(CommitWidth, Input(UInt(log2Up(numEntries).W)))
// val wen = Vec(RenameWidth, Input(Bool()))
// val waddr = Vec(RenameWidth)
// })
// val valid = Mme(RoqSize, Bool())
// val flagBkup = RegInit(VecInit(List.fill(RoqSize)(false.B)))
// for (i <- 0 until RoqSize) {
// when (reset.asBool || io.redirectOut.valid) {
// valid(i) := false.B
// }.elsewhen (io.redirectOut.valid)
// }
// when (reset.asBool) {
// valid(i)
// }
// // enqueue logic writes 6 valid
// for (i <- 0 until RenameWidth) {
// when (canEnqueue(i) && !io.redirect.valid) {
// valid(enqPtrVec(i).value) := true.B
// }
// }
// // dequeue/walk logic writes 6 valid, dequeue and walk will not happen at the same time
// for (i <- 0 until CommitWidth) {
// when (io.commits.valid(i) && state =/= s_extrawalk) {
// valid(commitReadAddr(i)) := false.B
// }
// }
// // reset: when exception, reset all valid to false
// when (io.redirectOut.valid) {
// for (i <- 0 until RoqSize) {
// valid(i) := false.B
// }
// }
// }
class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val io = IO(new Bundle() {
val redirect = Input(Valid(new Redirect))
......@@ -176,11 +216,14 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
})
// instvalid field
val valid = RegInit(VecInit(List.fill(RoqSize)(false.B)))
// val valid = RegInit(VecInit(List.fill(RoqSize)(false.B)))
val valid = Mem(RoqSize, Bool())
// writeback status
val writebacked = Reg(Vec(RoqSize, Bool()))
// val writebacked = Reg(Vec(RoqSize, Bool()))
val writebacked = Mem(RoqSize, Bool())
// data for redirect, exception, etc.
val flagBkup = RegInit(VecInit(List.fill(RoqSize)(false.B)))
// val flagBkup = RegInit(VecInit(List.fill(RoqSize)(false.B)))
val flagBkup = Mem(RoqSize, Bool())
// data for debug
// Warn: debug_* prefix should not exist in generated verilog.
......@@ -221,16 +264,20 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
* (2) write: write back from exe units
*/
val dispatchData = Module(new DataModuleTemplate(new RoqDispatchData, RoqSize, CommitWidth, RenameWidth))
val dispatchDataRead = dispatchData.io.rdata
val writebackData = Module(new DataModuleTemplate(new RoqWbData, RoqSize, CommitWidth, numWbPorts))
val writebackDataRead = writebackData.io.rdata
def mergeExceptionVec(dpData: RoqDispatchData, wbData: RoqWbData) = {
// these exceptions can be determined before dispatch.
// by default, let all exceptions be determined by dispatch.
// mergeVec(instrAddrMisaligned) := dpData(instrAddrMisaligned)
// mergeVec(instrAccessFault) := dpData(instrAccessFault)
// mergeVec(illegalInstr) := dpData(illegalInstr)
// mergeVec(instrPageFault) := dpData(instrPageFault)
val mergeVec = WireInit(dpData.exceptionVec)
// these exceptions are determined in execution units
mergeVec(illegalInstr) := wbData.exceptionVec(illegalInstr)
mergeVec(breakPoint) := wbData.exceptionVec(breakPoint)
mergeVec(loadAddrMisaligned) := wbData.exceptionVec(loadAddrMisaligned)
mergeVec(loadAccessFault) := wbData.exceptionVec(loadAccessFault)
......@@ -310,21 +357,20 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
/**
* RedirectOut: Interrupt and Exceptions
*/
val deqDispatchData = dispatchData.io.rdata(0)
val deqWritebackData = writebackData.io.rdata(0)
val deqDispatchData = dispatchDataRead(0)
val deqWritebackData = writebackDataRead(0)
val debug_deqUop = debug_microOp(deqPtr.value)
val deqPtrWritebacked = writebacked(deqPtr.value) && valid(deqPtr.value)
val deqExceptionVec = mergeExceptionVec(deqDispatchData, deqWritebackData)
// For MMIO instructions, they should not trigger interrupts since they may be sent to lower level before it writes back.
// However, we cannot determine whether a load/store instruction is MMIO.
// Thus, we don't allow load/store instructions to trigger an interrupt.
val intrBitSetReg = RegNext(io.csr.intrBitSet)
val intrEnable = intrBitSetReg && valid(deqPtr.value) && !hasNoSpecExec && !CommitType.isLoadStore(deqDispatchData.commitType)
val exceptionEnable = deqPtrWritebacked && Cat(deqExceptionVec).orR()
val isFlushPipe = deqPtrWritebacked && deqWritebackData.flushPipe
val intrEnable = intrBitSetReg && !hasNoSpecExec && !CommitType.isLoadStore(deqDispatchData.commitType)
val exceptionEnable = writebacked(deqPtr.value) && Cat(deqExceptionVec).orR()
val isFlushPipe = writebacked(deqPtr.value) && deqWritebackData.flushPipe
io.redirectOut := DontCare
io.redirectOut.valid := (state === s_idle) && (intrEnable || exceptionEnable || isFlushPipe)
io.redirectOut.valid := (state === s_idle) && valid(deqPtr.value) && (intrEnable || exceptionEnable || isFlushPipe)
io.redirectOut.bits.level := Mux(isFlushPipe, RedirectLevel.flushAll, RedirectLevel.exception)
io.redirectOut.bits.interrupt := intrEnable
io.redirectOut.bits.target := Mux(isFlushPipe, deqDispatchData.pc + 4.U, io.csr.trapTarget)
......@@ -352,8 +398,9 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val walkFinished = walkCounter <= CommitWidth.U
// extra space is used when roq has no enough space, but mispredict recovery needs such info to walk regmap
val needExtraSpaceForMPR = VecInit((0 until CommitWidth).map(i => io.redirect.valid && io.enq.needAlloc(i)))
val extraSpaceForMPR = Reg(Vec(RenameWidth, new RoqCommitInfo))
require(RenameWidth <= CommitWidth)
val needExtraSpaceForMPR = VecInit((0 until RenameWidth).map(i => io.redirect.valid && io.enq.needAlloc(i)))
val extraSpaceForMPR = Reg(Vec(RenameWidth, new RoqDispatchData))
val usedSpaceForMPR = Reg(Vec(RenameWidth, Bool()))
// wiring to csr
......@@ -363,25 +410,26 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
io.commits.isWalk := state =/= s_idle
val commit_v = Mux(state === s_idle, VecInit(deqPtrVec.map(ptr => valid(ptr.value))), VecInit(walkPtrVec.map(ptr => valid(ptr.value))))
val commit_w = VecInit(deqPtrVec.map(ptr => writebacked(ptr.value)))
val commit_exception = dispatchData.io.rdata.zip(writebackData.io.rdata).map{ case (d, w) => mergeExceptionVec(d, w).asUInt.orR }
val commit_block = VecInit((0 until CommitWidth).map(i => !commit_w(i) || commit_exception(i) || writebackData.io.rdata(i).flushPipe))
val commit_exception = dispatchDataRead.zip(writebackDataRead).map{ case (d, w) => mergeExceptionVec(d, w).asUInt.orR }
val commit_block = VecInit((0 until CommitWidth).map(i => !commit_w(i) || commit_exception(i) || writebackDataRead(i).flushPipe))
for (i <- 0 until CommitWidth) {
// defaults: state === s_idle and instructions commit
val isBlocked = if (i != 0) Cat(commit_block.take(i)).orR || intrEnable else false.B
// when intrBitSetReg, allow only one instruction to commit at each clock cycle
val isBlocked = if (i != 0) Cat(commit_block.take(i)).orR || intrBitSetReg else intrEnable
io.commits.valid(i) := commit_v(i) && commit_w(i) && !isBlocked && !commit_exception(i)
io.commits.info(i) := dispatchData.io.rdata(i)
io.commits.info(i) := dispatchDataRead(i)
when (state === s_idle) {
when (io.commits.valid(i) && writebackData.io.rdata(i).fflags.asUInt.orR()) {
fflags := writebackData.io.rdata(i).fflags
when (io.commits.valid(i) && writebackDataRead(i).fflags.asUInt.orR()) {
fflags := writebackDataRead(i).fflags
}
}
when (state === s_walk) {
io.commits.valid(i) := commit_v(i) && shouldWalkVec(i)
}.elsewhen(state === s_extrawalk) {
io.commits.valid(i) := usedSpaceForMPR(RenameWidth-i-1)
io.commits.info(i) := extraSpaceForMPR(RenameWidth-i-1)
io.commits.valid(i) := (if (i < RenameWidth) usedSpaceForMPR(RenameWidth-i-1) else false.B)
io.commits.info(i) := (if (i < RenameWidth) extraSpaceForMPR(RenameWidth-i-1) else DontCare)
state := s_walk
}
......@@ -393,7 +441,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
io.commits.info(i).pdest,
io.commits.info(i).old_pdest,
debug_exuData(deqPtrVec(i).value),
writebackData.io.rdata(i).fflags.asUInt
writebackDataRead(i).fflags.asUInt
)
XSInfo(state === s_walk && io.commits.valid(i), "walked pc %x wen %d ldst %d data %x\n",
debug_microOp(walkPtrVec(i).value).cf.pc,
......@@ -406,6 +454,9 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
io.commits.info(i).ldest
)
}
if (!env.FPGAPlatform) {
io.commits.info.map(info => dontTouch(info.pc))
}
io.csr.fflags := fflags
io.csr.dirty_fs := dirty_fs
......@@ -481,8 +532,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
deqPtrGenModule.io.state := state
deqPtrGenModule.io.deq_v := commit_v
deqPtrGenModule.io.deq_w := commit_w
deqPtrGenModule.io.deq_exceptionVec := VecInit(dispatchData.io.rdata.zip(writebackData.io.rdata).map{ case (d, w) => mergeExceptionVec(d, w).asUInt })
deqPtrGenModule.io.deq_flushPipe := writebackData.io.rdata.map(_.flushPipe)
deqPtrGenModule.io.deq_exceptionVec := VecInit(dispatchDataRead.zip(writebackDataRead).map{ case (d, w) => mergeExceptionVec(d, w).asUInt })
deqPtrGenModule.io.deq_flushPipe := writebackDataRead.map(_.flushPipe)
deqPtrGenModule.io.intrBitSetReg := intrBitSetReg
deqPtrGenModule.io.hasNoSpecExec := hasNoSpecExec
deqPtrGenModule.io.commitType := deqDispatchData.commitType
......@@ -493,7 +544,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
enqPtrGenModule.io.deq_v := commit_v(0)
enqPtrGenModule.io.deq_w := commit_w(0)
enqPtrGenModule.io.deq_exceptionVec := deqExceptionVec.asUInt
enqPtrGenModule.io.deq_flushPipe := writebackData.io.rdata(0).flushPipe
enqPtrGenModule.io.deq_flushPipe := writebackDataRead(0).flushPipe
enqPtrGenModule.io.intrBitSetReg := intrBitSetReg
enqPtrGenModule.io.hasNoSpecExec := hasNoSpecExec
enqPtrGenModule.io.commitType := deqDispatchData.commitType
......@@ -570,6 +621,11 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
valid(i) := false.B
}
}
when (reset.asBool) {
for (i <- 0 until RoqSize) {
valid(i) := false.B
}
}
// status field: writebacked
// enqueue logic set 6 writebacked to false
......
......@@ -387,7 +387,7 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
// reset pf when pf hit
val pfHitReset = ParallelOR(widthMap{i => Mux(resp(i).fire(), VecInit(pfHitVecVec(i)).asUInt, 0.U) })
val pfHitRefill = ParallelOR(pfHitReset.asBools)
val pfHitRefill = false.B//ParallelOR(pfHitReset.asBools)
// pf update
when (refill) {
......
......@@ -267,8 +267,8 @@ class BPUStage3 extends BPUStage {
val pdLastHalf = s3IO.predecode.lastHalf
val pds = s3IO.predecode.pd
val btbResp = inLatch.resp.btb
val btbHits = btbResp.hits.asUInt
val btbResp = WireInit(inLatch.resp.btb)
val btbHits = WireInit(btbResp.hits.asUInt)
val bimTakens = VecInit(inLatch.resp.bim.ctrs.map(_(1)))
val brs = pdMask & Reverse(Cat(pds.map(_.isBr)))
......@@ -287,6 +287,8 @@ class BPUStage3 extends BPUStage {
val prevHalfTakenMask = prevHalfTaken.asUInt
val brTakens = ((brs & brPred | prevHalfTakenMask) & ~loopRes)
// VecInit((0 until PredictWidth).map(i => brs(i) && (brPred(i) || (if (i == 0) prevHalfTaken else false.B)) && !loopRes(i)))
// we should provide btb resp as well
btbHits := btbResp.hits.asUInt | prevHalfTakenMask
// predict taken only if btb has a target, jal targets will be provided by IFU
takens := VecInit((0 until PredictWidth).map(i => (brTakens(i) || jalrs(i)) && btbHits(i) || jals(i)))
......
......@@ -108,9 +108,9 @@ class BIM extends BasePredictor with BimParams {
when (needToUpdate) {
when (wrbypass_hit) {
wrbypass_ctrs(wrbypass_hit_idx)(updateBank) := newCtr
wrbypass_ctr_valids(wrbypass_enq_idx)(updateBank) := true.B
wrbypass_ctr_valids(wrbypass_hit_idx)(updateBank) := true.B
} .otherwise {
wrbypass_ctrs(wrbypass_hit_idx)(updateBank) := newCtr
wrbypass_ctrs(wrbypass_enq_idx)(updateBank) := newCtr
(0 until BimBanks).foreach(b => wrbypass_ctr_valids(wrbypass_enq_idx)(b) := false.B) // reset valid bits
wrbypass_ctr_valids(wrbypass_enq_idx)(updateBank) := true.B
wrbypass_rows(wrbypass_enq_idx) := updateRow
......
......@@ -92,7 +92,8 @@ class PrevHalfInstr extends XSBundle {
val target = UInt(VAddrBits.W)
val instr = UInt(16.W)
val ipf = Bool()
val newPtr = UInt(log2Up(ExtHistoryLength).W)
val meta = new BpuMeta
// val newPtr = UInt(log2Up(ExtHistoryLength).W)
}
@chiselName
......@@ -200,9 +201,11 @@ class IFU extends XSModule with HasIFUConst
// set to invalid once consumed or redirect from backend
val if3_prevHalfConsumed = if3_prevHalfInstrMet && if3_fire
val if3_prevHalfFlush = if4_flush
when (hasPrevHalfInstrReq && !if3_prevHalfFlush) {
when (if3_prevHalfFlush) {
if3_prevHalfInstr.valid := false.B
}.elsewhen (hasPrevHalfInstrReq) {
if3_prevHalfInstr.valid := true.B
}.elsewhen (if3_prevHalfConsumed || if3_prevHalfFlush) {
}.elsewhen (if3_prevHalfConsumed) {
if3_prevHalfInstr.valid := false.B
}
when (hasPrevHalfInstrReq) {
......@@ -280,9 +283,9 @@ class IFU extends XSModule with HasIFUConst
val if4_bp = Wire(new BranchPrediction)
if4_bp := bpu.io.out(2)
if4_bp.takens := bpu.io.out(2).takens & if4_mask
if4_bp.brMask := bpu.io.out(2).brMask & if4_mask
if4_bp.jalMask := bpu.io.out(2).jalMask & if4_mask
// if4_bp.takens := bpu.io.out(2).takens & if4_mask
// if4_bp.brMask := bpu.io.out(2).brMask & if4_mask
// if4_bp.jalMask := bpu.io.out(2).jalMask & if4_mask
if4_predicted_gh := if4_gh.update(if4_bp.hasNotTakenBrs, if4_bp.takenOnBr)
......@@ -311,9 +314,11 @@ class IFU extends XSModule with HasIFUConst
val if4_prevHalfFlush = if4_flush
val if4_takenPrevHalf = WireInit(if4_prevHalfInstrMet && if4_prevHalfInstr.bits.taken)
when (if3_prevHalfConsumed) {
when (if4_prevHalfFlush) {
if4_prevHalfInstr.valid := false.B
}.elsewhen (if3_prevHalfConsumed) {
if4_prevHalfInstr.valid := if3_prevHalfInstr.valid
}.elsewhen (if4_prevHalfConsumed || if4_prevHalfFlush) {
}.elsewhen (if4_prevHalfConsumed) {
if4_prevHalfInstr.valid := false.B
}
......@@ -327,7 +332,6 @@ class IFU extends XSModule with HasIFUConst
// this is result of the last half RVI
prevHalfInstrReq.bits.taken := if4_bp.lastHalfRVITaken
prevHalfInstrReq.bits.ghInfo := if4_gh
prevHalfInstrReq.bits.newPtr := DontCare
prevHalfInstrReq.bits.fetchpc := if4_pc
prevHalfInstrReq.bits.idx := idx
prevHalfInstrReq.bits.pc := if4_pd.pc(idx)
......@@ -335,6 +339,7 @@ class IFU extends XSModule with HasIFUConst
prevHalfInstrReq.bits.target := if4_bp.lastHalfRVITarget
prevHalfInstrReq.bits.instr := if4_pd.instrs(idx)(15, 0)
prevHalfInstrReq.bits.ipf := if4_ipf
prevHalfInstrReq.bits.meta := bpu.io.bpuMeta(idx)
def if4_nextValidPCNotEquals(pc: UInt) = if3_valid && if3_pc =/= pc ||
!if3_valid && (if2_valid && if2_pc =/= pc) ||
......@@ -462,6 +467,10 @@ class IFU extends XSModule with HasIFUConst
fetchPacketWire.pnpc(if4_bp.jmpIdx) := if4_bp.target
}
fetchPacketWire.bpuMeta := bpu.io.bpuMeta
// save it for update
when (if4_pendingPrevHalfInstr) {
fetchPacketWire.bpuMeta(0) := if4_prevHalfInstr.bits.meta
}
(0 until PredictWidth).foreach(i => {
val meta = fetchPacketWire.bpuMeta(i)
meta.hist := final_gh
......
......@@ -52,24 +52,33 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
}
// Ibuffer define
val ibuf = Mem(IBufSize, new IBufEntry)
val ibuf = Reg(Vec(IBufSize, new IBufEntry))
val head_ptr = RegInit(IbufPtr(false.B, 0.U))
val tail_ptr = RegInit(IbufPtr(false.B, 0.U))
val tail_vec = RegInit(VecInit((0 until PredictWidth).map(_.U.asTypeOf(new IbufPtr))))
val tail_ptr = tail_vec(0)
val validEntries = distanceBetween(tail_ptr, head_ptr) // valid entries
// val validEntries = distanceBetween(tail_ptr, head_ptr) // valid entries
val validEntries = RegInit(0.U(log2Up(IBufSize + 1).W))// valid entries
val allowEnq = RegInit(true.B)
val enqValid = IBufSize.U - PredictWidth.U >= validEntries
// val enqValid = (IBufSize.U - PredictWidth.U) >= validEntries
val deqValid = validEntries > 0.U
val numEnq = Mux(io.in.fire, PopCount(io.in.bits.mask), 0.U)
val numDeq = Mux(deqValid, PopCount(io.out.map(_.fire)), 0.U)
validEntries := validEntries + numEnq - numDeq
allowEnq := (IBufSize.U - PredictWidth.U) >= (validEntries + numEnq)
// Enque
io.in.ready := enqValid
io.in.ready := allowEnq
val enq_vec = Wire(Vec(PredictWidth, UInt(log2Up(IBufSize).W)))
val offset = Wire(Vec(PredictWidth, UInt(log2Up(PredictWidth).W)))
for(i <- 0 until PredictWidth) {
if (i == 0) {
enq_vec(i) := tail_ptr.value
offset(i) := 0.U
} else {
enq_vec(i) := tail_ptr.value + PopCount(io.in.bits.pdmask(i-1, 0))
offset(i) := PopCount(io.in.bits.pdmask(i-1, 0))
}
}
......@@ -87,11 +96,11 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
inWire.ipf := io.in.bits.ipf
inWire.acf := io.in.bits.acf
inWire.crossPageIPFFix := io.in.bits.crossPageIPFFix
ibuf(enq_vec(i)) := inWire
ibuf(tail_vec(offset(i)).value) := inWire
}
}
tail_ptr := tail_ptr + PopCount(io.in.bits.mask)
tail_vec := VecInit(tail_vec.map(_ + PopCount(io.in.bits.mask)))
}
// Deque
......@@ -125,10 +134,11 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
// Flush
when(io.flush) {
validEntries := 0.U
allowEnq := true.B
head_ptr.value := 0.U
head_ptr.flag := false.B
tail_ptr.value := 0.U
tail_ptr.flag := false.B
tail_vec := VecInit((0 until PredictWidth).map(_.U.asTypeOf(new IbufPtr)))
}
// Debug info
......@@ -164,7 +174,7 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
// )
// }
XSDebug(p"last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n")
XSDebug(p"validEntries=$validEntries, last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n")
for(i <- 0 until IBufSize/8) {
XSDebug("%x | %x | %x | %x | %x | %x | %x | %x\n",
ibuf(i*8+0).inst,
......
#include "common.h"
#include "emu.h"
int assert_count = 0;
static pthread_mutex_t assert_mutex;
void assert_init() {
pthread_mutex_init(&assert_mutex, 0);
}
void assert_finish() {
pthread_mutex_destroy(&assert_mutex);
}
extern "C" void xs_assert(long long line) {
pthread_mutex_lock(&assert_mutex);
printf("Assertion failed at line %lld\n.", line);
assert_count++;
pthread_mutex_unlock(&assert_mutex);
}
......@@ -6,6 +6,7 @@
#include <cstdlib>
#include <stdint.h>
#include <assert.h>
#include <pthread.h>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
......@@ -21,4 +22,8 @@
#include "cosimulation.h"
#endif
extern int assert_count;
void assert_init();
void assert_finish();
#endif // __COMMON_H
......@@ -180,7 +180,7 @@ int difftest_step(DiffState *s) {
// ref_difftest_exec(1);//TODO
}
else {
assert(s->commit > 0 && s->commit <= 6);
assert(s->commit > 0 && s->commit <= DIFFTEST_WIDTH);
for(int i = 0; i < s->commit; i++){
pc_wb_queue[wb_pointer] = s->wpc[i];
wen_wb_queue[wb_pointer] = selectBit(s->wen, i);
......
......@@ -5,6 +5,8 @@
#include <assert.h>
#include <string.h>
#define DIFFTEST_WIDTH 6
typedef uint64_t rtlreg_t;
typedef uint64_t paddr_t;
......@@ -96,4 +98,7 @@ int difftest_step(DiffState *s);
int difftest_store_step(uint64_t *saddr, uint64_t *sdata, uint8_t *smask);
void difftest_display(uint8_t mode);
uint64_t get_nemu_this_pc();
void set_nemu_this_pc(uint64_t pc);
#endif
......@@ -2,18 +2,12 @@
#include "sdcard.h"
#include "difftest.h"
#include <getopt.h>
#include<signal.h>
#include<unistd.h>
#include <signal.h>
#include <unistd.h>
#include "ram.h"
#include "zlib.h"
#include "compress.h"
void* get_ram_start();
long get_ram_size();
uint64_t get_nemu_this_pc();
void set_nemu_this_pc(uint64_t pc);
static inline void print_help(const char *file) {
printf("Usage: %s [OPTION...]\n", file);
printf("\n");
......@@ -90,6 +84,7 @@ Emulator::Emulator(int argc, const char *argv[]):
srand(args.seed);
srand48(args.seed);
Verilated::randReset(2);
assert_init();
// init core
reset_ncycles(10);
......@@ -132,6 +127,7 @@ Emulator::Emulator(int argc, const char *argv[]):
Emulator::~Emulator() {
ram_finish();
assert_finish();
#ifdef VM_SAVABLE
if (args.enable_snapshot && trapCode != STATE_GOODTRAP && trapCode != STATE_LIMIT_EXCEEDED) {
......@@ -178,21 +174,45 @@ inline void Emulator::read_wb_info(uint64_t *wpc, uint64_t *wdata, uint32_t *wds
#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);
#define dut_ptr_read_wb(x) dut_ptr_wpc(x); dut_ptr_wdata(x); dut_ptr_wdst(x);
#if DIFFTEST_WIDTH >= 13 || DIFFTEST_WIDTH < 6
#error "not supported difftest width"
#endif
dut_ptr_read_wb(0);
dut_ptr_read_wb(1);
dut_ptr_read_wb(2);
dut_ptr_read_wb(3);
dut_ptr_read_wb(4);
dut_ptr_read_wb(5);
#if DIFFTEST_WIDTH >= 7
dut_ptr_read_wb(6);
#endif
#if DIFFTEST_WIDTH >= 8
dut_ptr_read_wb(7);
#endif
#if DIFFTEST_WIDTH >= 9
dut_ptr_read_wb(8);
#endif
#if DIFFTEST_WIDTH >= 10
dut_ptr_read_wb(9);
#endif
#if DIFFTEST_WIDTH >= 11
dut_ptr_read_wb(10);
#endif
#if DIFFTEST_WIDTH >= 12
dut_ptr_read_wb(11);
#endif
}
inline void Emulator::read_store_info(uint64_t *saddr, uint64_t *sdata, uint8_t *smask) {
#define dut_ptr_saddr(x) saddr[x] = dut_ptr->io_difftest_storeAddr_##x
#define dut_ptr_sdata(x) sdata[x] = dut_ptr->io_difftest_storeData_##x
#define dut_ptr_smask(x) smask[x] = dut_ptr->io_difftest_storeMask_##x
dut_ptr_saddr(0); dut_ptr_saddr(1);
dut_ptr_sdata(0); dut_ptr_sdata(1);
dut_ptr_smask(0); dut_ptr_smask(1);
#define dut_ptr_read_store(x) dut_ptr_saddr(x); dut_ptr_sdata(x); dut_ptr_smask(x);
dut_ptr_read_store(0);
dut_ptr_read_store(1);
}
inline void Emulator::reset_ncycles(size_t cycles) {
......@@ -295,6 +315,11 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
max_cycle --;
if (dut_ptr->io_trap_valid) trapCode = dut_ptr->io_trap_code;
if (assert_count > 0) {
difftest_display(dut_ptr->io_difftest_priviledgeMode);
eprintf("The simulation stopped. There might be some assertion failed.\n");
trapCode = STATE_ABORT;
}
if (trapCode != STATE_RUNNING) break;
if (lastcommit - max_cycle > stuck_limit && hascommit) {
......@@ -367,12 +392,12 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
}
#ifdef VM_SAVABLE
static int snapshot_count = 0;
if (args.enable_snapshot && trapCode != STATE_GOODTRAP && t - lasttime_snapshot > 6000 * SNAPSHOT_INTERVAL) {
if (args.enable_snapshot && trapCode != STATE_GOODTRAP && t - lasttime_snapshot > 1000 * SNAPSHOT_INTERVAL) {
// save snapshot every 60s
time_t now = time(NULL);
snapshot_save(snapshot_filename(now));
lasttime_snapshot = t;
// dump snapshot to file every 10 minutes
// dump one snapshot to file every 60 snapshots
snapshot_count++;
if (snapshot_count == 60) {
snapshot_slot[0].save();
......@@ -382,12 +407,6 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
#endif
}
if (Verilated::gotFinish()) {
difftest_display(dut_ptr->io_difftest_priviledgeMode);
eprintf("The simulation stopped. There might be some assertion failed.\n");
trapCode = STATE_ABORT;
}
#if VM_TRACE == 1
if (enable_waveform) tfp->close();
#endif
......@@ -465,8 +484,8 @@ void Emulator::display_trapinfo() {
}
double ipc = (double)instrCnt / (cycleCnt-500);
eprintf(ANSI_COLOR_MAGENTA "total guest instructions = %" PRIu64 "\n" ANSI_COLOR_RESET, instrCnt);
eprintf(ANSI_COLOR_MAGENTA "instrCnt = %" PRIu64 ", cycleCnt = %" PRIu64 ", IPC = %lf\n" ANSI_COLOR_RESET,
eprintf(ANSI_COLOR_MAGENTA "total guest instructions = %'" PRIu64 "\n" ANSI_COLOR_RESET, instrCnt);
eprintf(ANSI_COLOR_MAGENTA "instrCnt = %'" PRIu64 ", cycleCnt = %'" PRIu64 ", IPC = %lf\n" ANSI_COLOR_RESET,
instrCnt, cycleCnt, ipc);
}
......
......@@ -3,8 +3,7 @@
#include "VXSSimSoC.h"
#include <verilated_vcd_c.h> // Trace file format header
#define DIFFTEST_WIDTH 6
#define SNAPSHOT_INTERVAL 10 // unit: second
#define SNAPSHOT_INTERVAL 60 // unit: second
struct EmuArgs {
uint32_t seed;
......
#include "emu.h"
#include <functional>
#include <locale.h>
static char mybuf[BUFSIZ];
......@@ -12,6 +13,9 @@ int main(int argc, const char** argv) {
setbuf(stderr, mybuf);
// enable thousands separator for printf()
setlocale(LC_NUMERIC, "");
auto emu = new Emulator(argc, argv);
get_sc_time_stamp = [&emu]() -> double {
......@@ -27,9 +31,9 @@ int main(int argc, const char** argv) {
extern uint32_t uptime(void);
uint32_t ms = uptime();
eprintf(ANSI_COLOR_BLUE "Seed=%d Guest cycle spent: %" PRIu64
eprintf(ANSI_COLOR_BLUE "Seed=%d Guest cycle spent: %'" PRIu64
" (this will be different from cycleCnt if emu loads a snapshot)\n" ANSI_COLOR_RESET, args.seed, cycles);
eprintf(ANSI_COLOR_BLUE "Host time spent: %dms\n" ANSI_COLOR_RESET, ms);
eprintf(ANSI_COLOR_BLUE "Host time spent: %'dms\n" ANSI_COLOR_RESET, ms);
// return !is_good_trap;
return trapcode;
......
......@@ -12,6 +12,8 @@ CoDRAMsim3 *dram = NULL;
static uint64_t *ram;
static long img_size = 0;
static pthread_mutex_t ram_mutex;
void* get_img_start() { return &ram[0]; }
long get_img_size() { return img_size; }
void* get_ram_start() { return &ram[0]; }
......@@ -155,6 +157,8 @@ void init_ram(const char *img) {
dram = new CoDRAMsim3(DRAMSIM3_CONFIG, DRAMSIM3_OUTDIR);
#endif
pthread_mutex_init(&ram_mutex, 0);
}
void ram_finish() {
......@@ -162,13 +166,18 @@ void ram_finish() {
#ifdef WITH_DRAMSIM3
dramsim3_finish();
#endif
pthread_mutex_destroy(&ram_mutex);
}
extern "C" uint64_t ram_read_helper(uint8_t en, uint64_t rIdx) {
if (en && rIdx >= EMU_RAM_SIZE / sizeof(uint64_t)) {
rIdx %= EMU_RAM_SIZE / sizeof(uint64_t);
}
return (en) ? ram[rIdx] : 0;
pthread_mutex_lock(&ram_mutex);
uint64_t rdata = (en) ? ram[rIdx] : 0;
pthread_mutex_unlock(&ram_mutex);
return rdata;
}
extern "C" void ram_write_helper(uint64_t wIdx, uint64_t wdata, uint64_t wmask, uint8_t wen) {
......@@ -177,7 +186,9 @@ extern "C" void ram_write_helper(uint64_t wIdx, uint64_t wdata, uint64_t wmask,
printf("ERROR: ram wIdx = 0x%lx out of bound!\n", wIdx);
assert(wIdx < EMU_RAM_SIZE / sizeof(uint64_t));
}
pthread_mutex_lock(&ram_mutex);
ram[wIdx] = (ram[wIdx] & ~wmask) | (wdata & wmask);
pthread_mutex_unlock(&ram_mutex);
}
}
......
......@@ -8,6 +8,8 @@
void init_ram(const char *img);
void ram_finish();
void* get_ram_start();
long get_ram_size();
#ifdef WITH_DRAMSIM3
// 4*64 bits
......
import "DPI-C" function void xs_assert
(
input longint line
);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册