提交 4fcc0784 编写于 作者: Y Yinan Xu

Merge remote-tracking branch 'origin/master' into opt-roq

Subproject commit 147bdcc4a26c74e5d7a47e3d667d456699d6d11f
Subproject commit 9cf18f1173443e2542990c090a69bdd62d26228d
......@@ -6,6 +6,7 @@ import chisel3.util._
object PipelineConnect {
def apply[T <: Data](left: DecoupledIO[T], right: DecoupledIO[T], rightOutFire: Bool, isFlush: Bool) = {
val valid = RegInit(false.B)
valid.suggestName("pipeline_valid")
when (rightOutFire) { valid := false.B }
when (left.valid && right.ready) { valid := true.B }
when (isFlush) { valid := false.B }
......
......@@ -34,7 +34,7 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
val tailPtr = RegInit(VecInit((0 until enqnum).map(_.U.asTypeOf(new CircularQueuePtr(size)))))
val tailPtrMask = UIntToMask(tailPtr(0).value, size)
// valid entries counter
val validCounter = RegInit(0.U(log2Ceil(size).W))
val validCounter = RegInit(0.U(log2Ceil(size + 1).W))
val allowEnqueue = RegInit(true.B)
val isTrueEmpty = ~Cat((0 until size).map(i => stateEntries(i) === s_valid)).orR
......
......@@ -140,6 +140,7 @@ class DivSqrt extends FPUSubModule {
// 53 + 2 + 2 = 57 bits are needed, but 57 % log2(4) != 0, use 58 bits instead
val mantDivSqrt = Module(new MantDivSqrt(D_MANT_WIDTH+2+2+1))
mantDivSqrt.io.kill := kill
mantDivSqrt.io.out.ready := true.B
mantDivSqrt.io.in.valid := state === s_start
mantDivSqrt.io.in.bits.a := Mux(isDivReg || aIsOddExp, Cat(aMantReg, 0.U(5.W)), Cat(0.U(1.W), aMantReg, 0.U(4.W)))
......
......@@ -11,6 +11,7 @@ class MantDivSqrt(len: Int) extends Module{
val a, b = UInt(len.W)
val isDiv = Bool()
}))
val kill = Input(Bool())
val out = DecoupledIO(new Bundle() {
val quotient = UInt(len.W)
val isZeroRem = Bool()
......@@ -45,6 +46,7 @@ class MantDivSqrt(len: Int) extends Module{
when(io.out.fire()){ state := s_idle }
}
}
when(io.kill){ state := s_idle }
val ws, wc = Reg(UInt((len+4).W))
......
......@@ -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
......
......@@ -237,7 +237,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val deqPtrVec = Wire(Vec(CommitWidth, new RoqPtr))
val walkPtrVec = Reg(Vec(CommitWidth, new RoqPtr))
val validCounter = RegInit(0.U(log2Ceil(RoqSize).W))
val validCounter = RegInit(0.U(log2Ceil(RoqSize + 1).W))
val allowEnqueue = RegInit(true.B)
val enqPtrVec = VecInit((0 until RenameWidth).map(i => enqPtr + PopCount(io.enq.needAlloc.take(i))))
......@@ -274,10 +274,10 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// 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)
......@@ -305,7 +305,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// To reduce registers usage, for hasBlockBackward cases, we allow enqueue after ROB is empty.
when (isEmpty) { hasBlockBackward:= false.B }
// When any instruction commits, hasNoSpecExec should be set to false.B
when (io.commits.valid.asUInt.orR) { hasNoSpecExec:= false.B }
when (io.commits.valid.asUInt.orR && state =/= s_extrawalk) { hasNoSpecExec:= false.B }
io.enq.canAccept := allowEnqueue && !hasBlockBackward
io.enq.isEmpty := isEmpty
......@@ -361,17 +361,16 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
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)
......@@ -414,7 +413,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
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) := dispatchDataRead(i)
......
......@@ -116,7 +116,7 @@ trait ICacheBase extends HasICacheParameters
//----------------------------
// Stage 1
//----------------------------
val s1_valid = WireInit(false.B)
// val s1_valid = WireInit(false.B)
val s1_req_pc = Wire(UInt(VAddrBits.W))
val s1_req_mask = Wire(UInt(PredictWidth.W))
val s1_fire = WireInit(false.B)
......@@ -267,6 +267,8 @@ class ICache extends ICacheModule
val io = IO(new ICacheIO)
val s2_flush = io.flush(0)
val s3_flush = io.flush(1)
//----------------------------
// Memory Part
//----------------------------
......@@ -278,21 +280,21 @@ class ICache extends ICacheModule
//----------------------------
// Stage 1
//----------------------------
s1_valid := io.req.fire()
s1_fire := io.req.valid
s1_req_pc := io.req.bits.addr
s1_req_mask := io.req.bits.mask
s2_ready := WireInit(false.B)
s1_fire := s1_valid && (s2_ready || io.flush(0))
// s1_fire := s1_valid && (s2_ready || s2_flush)
// SRAM(Meta and Data) read request
val s1_idx = get_idx(s1_req_pc)
metaArray.io.read.valid := s1_valid
metaArray.io.read.valid := s1_fire
metaArray.io.read.bits :=s1_idx
dataArray.io.read.valid := s1_valid
dataArray.io.read.valid := s1_fire
dataArray.io.read.bits :=s1_idx
XSDebug("[Stage 1] v : r : f (%d %d %d) request pc: 0x%x mask: %b\n",s1_valid,s2_ready,s1_fire,s1_req_pc,s1_req_mask)
XSDebug("[Stage 1] r : f (%d %d) request pc: 0x%x mask: %b\n",s2_ready,s1_fire,s1_req_pc,s1_req_mask)
XSDebug("[Stage 1] index: %d\n",s1_idx)
......@@ -304,10 +306,11 @@ class ICache extends ICacheModule
val s2_tag = get_tag(s2_tlb_resp.paddr)
val s2_hit = WireInit(false.B)
val s2_access_fault = WireInit(false.B)
s2_fire := s2_valid && s3_ready && !io.flush(0) && io.tlb.resp.fire()
when(io.flush(0)) {s2_valid := s1_fire}
.elsewhen(s1_fire) { s2_valid := s1_valid}
.elsewhen(s2_fire) { s2_valid := false.B}
val s2_allValid = s2_valid && io.tlb.resp.valid
s2_fire := s2_allValid && s3_ready
when(s1_fire) { s2_valid := true.B }
.elsewhen(s2_flush) { s2_valid := false.B }
.elsewhen(s2_fire) { s2_valid := false.B }
//physical address < 0x80000000
//TODO: May have bugs
......@@ -329,7 +332,7 @@ class ICache extends ICacheModule
val waymask = Mux(s2_hit, hitVec.asUInt, Mux(hasInvalidWay, refillInvalidWaymask, victimWayMask))
s2_hit := ParallelOR(hitVec) || s2_tlb_resp.excp.pf.instr || s2_access_fault
s2_ready := s2_fire || !s2_valid || io.flush(0)
s2_ready := s3_ready && io.tlb.resp.valid || !s2_valid
XSDebug("[Stage 2] v : r : f (%d %d %d) pc: 0x%x mask: %b acf:%d\n",s2_valid,s3_ready,s2_fire,s2_req_pc,s2_req_mask,s2_access_fault)
XSDebug(p"[Stage 2] tlb req: v ${io.tlb.req.valid} r ${io.tlb.req.ready} ${io.tlb.req.bits}\n")
......@@ -349,9 +352,9 @@ class ICache extends ICacheModule
val s3_miss = s3_valid && !s3_hit
val s3_idx = get_idx(s3_req_pc)
val s3_access_fault = RegEnable(s2_access_fault,init=false.B,enable=s2_fire)
when(io.flush(1)) { s3_valid := false.B }
.elsewhen(s2_fire) { s3_valid := s2_valid }
.elsewhen(io.resp.fire()) { s3_valid := false.B }
when(s3_flush) { s3_valid := false.B }
.elsewhen(s2_fire && !s2_flush) { s3_valid := true.B }
.elsewhen(io.resp.fire()) { s3_valid := false.B }
val refillDataReg = Reg(Vec(refillCycles,UInt(beatBits.W)))
// icache hit
......@@ -373,15 +376,15 @@ class ICache extends ICacheModule
val icacheMissQueue = Module(new IcacheMissQueue)
val blocking = RegInit(false.B)
val isICacheResp = icacheMissQueue.io.resp.valid && icacheMissQueue.io.resp.bits.clientID === cacheID.U(2.W)
icacheMissQueue.io.req.valid := s3_miss && !io.flush(1) && !blocking//TODO: specificate flush condition
icacheMissQueue.io.req.valid := s3_miss && !s3_flush && !blocking//TODO: specificate flush condition
icacheMissQueue.io.req.bits.apply(missAddr=groupPC(s3_tlb_resp.paddr),missIdx=s3_idx,missWaymask=s3_wayMask,source=cacheID.U(2.W))
icacheMissQueue.io.resp.ready := io.resp.ready
icacheMissQueue.io.flush := io.flush(1)
icacheMissQueue.io.flush := s3_flush
when(icacheMissQueue.io.req.fire()){blocking := true.B}
.elsewhen(blocking && ((icacheMissQueue.io.resp.fire() && isICacheResp) || io.flush(1)) ){blocking := false.B}
.elsewhen(blocking && ((icacheMissQueue.io.resp.fire() && isICacheResp) || s3_flush) ){blocking := false.B}
XSDebug(blocking && io.flush(1),"check for icache non-blocking")
XSDebug(blocking && s3_flush,"check for icache non-blocking")
//cache flush register
val icacheFlush = io.fencei
val cacheflushed = RegInit(false.B)
......@@ -419,7 +422,7 @@ class ICache extends ICacheModule
val refillDataVec = icacheMissQueue.io.resp.bits.data.asTypeOf(Vec(blockWords,UInt(wordBits.W)))
val refillDataOut = cutHelper(refillDataVec, s3_req_pc(5,1),s3_req_mask )
s3_ready := ((io.resp.fire() || !s3_valid) && !blocking) || (blocking && icacheMissQueue.io.resp.fire())
s3_ready := ((io.resp.ready && s3_hit || !s3_valid) && !blocking) || (blocking && icacheMissQueue.io.resp.valid && io.resp.ready)
//TODO: coherence
XSDebug("[Stage 3] valid:%d pc: 0x%x mask: %b ipf:%d acf:%d \n",s3_valid,s3_req_pc,s3_req_mask,s3_tlb_resp.excp.pf.instr,s3_access_fault)
......@@ -439,7 +442,7 @@ class ICache extends ICacheModule
// Out Put
//----------------------------
//icache request
io.req.ready := metaArray.io.read.ready && dataArray.io.read.ready && s2_ready
io.req.ready := s2_ready
//icache response: to pre-decoder
io.resp.valid := s3_valid && (s3_hit || icacheMissQueue.io.resp.valid)
......@@ -450,7 +453,7 @@ class ICache extends ICacheModule
io.resp.bits.acf := s3_access_fault
//to itlb
io.tlb.resp.ready := s3_ready
io.tlb.resp.ready := true.B // DontCare
io.tlb.req.valid := s2_valid
io.tlb.req.bits.vaddr := s2_req_pc
io.tlb.req.bits.cmd := TlbCmd.exec
......@@ -463,7 +466,7 @@ class ICache extends ICacheModule
io.l1plusflush := icacheFlush
XSDebug("[flush] flush_0:%d flush_1:%d\n",io.flush(0),io.flush(1))
XSDebug("[flush] flush_0:%d flush_1:%d\n",s2_flush,s3_flush)
//Performance Counter
if (!env.FPGAPlatform ) {
......
......@@ -501,11 +501,11 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
} .otherwise {
when (sfence.bits.rs2) {
// specific leaf of addr && all asid
tlbv := tlbv & ~UIntToOH(sfence.bits.addr(log2Up(TlbL2EntrySize)-1+offLen, 0+offLen))
tlbg := tlbg & ~UIntToOH(sfence.bits.addr(log2Up(TlbL2EntrySize)-1+offLen, 0+offLen))
tlbv := tlbv & ~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
tlbg := tlbg & ~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
} .otherwise {
// specific leaf of addr && specific asid
tlbv := tlbv & (~UIntToOH(sfence.bits.addr(log2Up(TlbL2EntrySize)-1+offLen, 0+offLen)) | tlbg)
tlbv := tlbv & (~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))| tlbg)
}
}
}
......
......@@ -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
......
......@@ -21,35 +21,29 @@ class Frontend extends XSModule {
val ifu = Module(new IFU)
val ibuffer = Module(new Ibuffer)
val icache = Module(new ICache)
val needFlush = io.backend.redirect.valid
//backend
// from backend
ifu.io.redirect <> io.backend.redirect
ifu.io.cfiUpdateInfo <> io.backend.cfiUpdateInfo
// ifu.io.cfiUpdateInfo <> io.backend.cfiUpdateInfo
//icache
ifu.io.icacheResp <> icache.io.resp
icache.io.req <> ifu.io.icacheReq
icache.io.flush <> ifu.io.icacheFlush
icache.io.fencei := io.fencei
io.l1plusFlush := icache.io.l1plusflush
io.icacheMemAcq <> icache.io.mem_acquire
icache.io.mem_grant <> io.icacheMemGrant
//itlb to ptw
io.ptw <> TLB(
in = Seq(icache.io.tlb),
sfence = io.sfence,
csr = io.tlbCsr,
width = 1,
isDtlb = false,
shouldBlock = true
)
//ibuffer
// to icache
ifu.io.icacheMemGrant <> io.icacheMemGrant
ifu.io.fencei := io.fencei
// to tlb
ifu.io.sfence := io.sfence
ifu.io.tlbCsr := io.tlbCsr
// from icache
io.l1plusFlush := ifu.io.l1plusFlush
io.icacheMemAcq <> ifu.io.icacheMemAcq
// itlb to ptw
io.ptw <> ifu.io.ptw
// ifu to ibuffer
ibuffer.io.in <> ifu.io.fetchPacket
// backend to ibuffer
ibuffer.io.flush := needFlush
// ibuffer to backend
io.backend.cfVec <> ibuffer.io.out
// for(out <- ibuffer.io.out){
......
......@@ -28,13 +28,9 @@ trait HasIFUConst extends HasXSParameter {
// each 1 bit in mask stands for 2 Bytes
// 8 bits, in which only the first 7 bits could be 0
def maskFirstHalf(pc: UInt): UInt = ((~(0.U(bankWidth.W))) >> offsetInBank(pc))(bankWidth-1,0)
// when in loop(buffer), we need to make use of the full packet
// and get the real mask in iCacheResp from loop buffer
// we may make predictions on more instructions than we could get from loop buffer
// and this will be handled in if4
def maskLastHalf(pc: UInt, inLoop: Bool = false.B): UInt = Mux(isInLastBank(pc) && !inLoop, 0.U(bankWidth.W), ~0.U(bankWidth.W))
def mask(pc: UInt, inLoop: Bool = false.B): UInt = Reverse(Cat(maskFirstHalf(pc), maskLastHalf(pc, inLoop)))
def snpc(pc: UInt, inLoop: Bool = false.B): UInt = pc + (PopCount(mask(pc, inLoop)) << 1)
def maskLastHalf(pc: UInt): UInt = Mux(isInLastBank(pc), 0.U(bankWidth.W), ~0.U(bankWidth.W))
def mask(pc: UInt): UInt = Reverse(Cat(maskFirstHalf(pc), maskLastHalf(pc)))
def snpc(pc: UInt): UInt = bankAligned(pc) + Mux(isInLastBank(pc), bankBytes.U, (bankBytes*2).U)
val enableGhistRepair = true
val IFUDebug = true
......@@ -68,14 +64,22 @@ class GlobalHistory extends XSBundle {
class IFUIO extends XSBundle
{
// to ibuffer
val fetchPacket = DecoupledIO(new FetchPacket)
// from backend
val redirect = Flipped(ValidIO(UInt(VAddrBits.W)))
// val cfiUpdateInfo = Flipped(ValidIO(new CfiUpdateInfo))
val cfiUpdateInfo = Flipped(ValidIO(new CfiUpdateInfo))
val icacheReq = DecoupledIO(new ICacheReq)
val icacheResp = Flipped(DecoupledIO(new ICacheResp))
val icacheFlush = Output(UInt(2.W))
// val loopBufPar = Flipped(new LoopBufferParameters)
// to icache
val icacheMemGrant = Flipped(DecoupledIO(new L1plusCacheResp))
val fencei = Input(Bool())
// from icache
val icacheMemAcq = DecoupledIO(new L1plusCacheReq)
val l1plusFlush = Output(Bool())
// to tlb
val sfence = Input(new SfenceBundle)
val tlbCsr = Input(new TlbCsrBundle)
// from tlb
val ptw = new TlbPtwIO
}
class PrevHalfInstr extends XSBundle {
......@@ -88,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
......@@ -96,29 +101,34 @@ class IFU extends XSModule with HasIFUConst
{
val io = IO(new IFUIO)
val bpu = BPU(EnableBPU)
val icache = Module(new ICache)
val pd = Module(new PreDecode)
val loopBuffer = if(EnableLB) { Module(new LoopBuffer) } else { Module(new FakeLoopBuffer) }
io.ptw <> TLB(
in = Seq(icache.io.tlb),
sfence = io.sfence,
csr = io.tlbCsr,
width = 1,
isDtlb = false,
shouldBlock = true
)
val if2_redirect, if3_redirect, if4_redirect = WireInit(false.B)
val if1_flush, if2_flush, if3_flush, if4_flush = WireInit(false.B)
val loopBufPar = loopBuffer.io.loopBufPar
val inLoop = WireInit(loopBuffer.io.out.valid)
val icacheResp = WireInit(Mux(inLoop, loopBuffer.io.out.bits, io.icacheResp.bits))
val icacheResp = icache.io.resp.bits
if4_flush := io.redirect.valid || loopBufPar.LBredirect.valid
if4_flush := io.redirect.valid
if3_flush := if4_flush || if4_redirect
if2_flush := if3_flush || if3_redirect
if1_flush := if2_flush || if2_redirect
loopBuffer.io.flush := io.redirect.valid
//********************** IF1 ****************************//
val if1_valid = !reset.asBool && GTimer() > 500.U
val if1_npc = WireInit(0.U(VAddrBits.W))
val if2_ready = WireInit(false.B)
val if2_allReady = WireInit(if2_ready && (inLoop || io.icacheReq.ready))
val if1_fire = if1_valid && (if2_allReady || if1_flush)
val if2_allReady = WireInit(if2_ready && icache.io.req.ready)
val if1_fire = if1_valid && (if2_allReady || if2_flush)
// val if2_newPtr, if3_newPtr, if4_newPtr = Wire(UInt(log2Up(ExtHistoryLength).W))
......@@ -131,12 +141,13 @@ class IFU extends XSModule with HasIFUConst
//********************** IF2 ****************************//
val if2_valid = RegInit(init = false.B)
val if2_allValid = if2_valid && icache.io.tlb.resp.valid
val if3_ready = WireInit(false.B)
val if2_fire = if2_valid && if3_ready
val if2_fire = if2_allValid && if3_ready
val if2_pc = RegEnable(next = if1_npc, init = resetVector.U, enable = if1_fire)
val if2_snpc = snpc(if2_pc, inLoop)
val if2_snpc = snpc(if2_pc)
val if2_predHist = RegEnable(if1_gh.predHist, enable=if1_fire)
if2_ready := if3_ready || !if2_valid
if2_ready := if3_ready && icache.io.tlb.resp.valid || !if2_valid
when (if1_fire) { if2_valid := true.B }
.elsewhen (if2_flush) { if2_valid := false.B }
.elsewhen (if2_fire) { if2_valid := false.B }
......@@ -157,11 +168,11 @@ class IFU extends XSModule with HasIFUConst
// if3 should wait for instructions resp to arrive
val if3_valid = RegInit(init = false.B)
val if4_ready = WireInit(false.B)
val if3_allValid = if3_valid && (inLoop || io.icacheResp.valid)
val if3_allValid = if3_valid && icache.io.resp.valid
val if3_fire = if3_allValid && if4_ready
val if3_pc = RegEnable(if2_pc, if2_fire)
val if3_predHist = RegEnable(if2_predHist, enable=if2_fire)
if3_ready := if4_ready && (inLoop || io.icacheResp.valid) || !if3_valid
if3_ready := if4_ready && icache.io.resp.valid || !if3_valid
when (if3_flush) {
if3_valid := false.B
}.elsewhen (if2_fire && !if2_flush) {
......@@ -190,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) {
......@@ -205,7 +218,7 @@ class IFU extends XSModule with HasIFUConst
val if3_prevHalfMetRedirect = if3_pendingPrevHalfInstr && if3_prevHalfInstrMet && if3_prevHalfInstr.bits.taken && if3_nextValidPCNotEquals(if3_prevHalfInstr.bits.target)
val if3_prevHalfNotMetRedirect = if3_pendingPrevHalfInstr && !if3_prevHalfInstrMet && if3_nextValidPCNotEquals(if3_prevHalfInstr.bits.npc)
val if3_predTakenRedirect = !if3_pendingPrevHalfInstr && if3_bp.taken && if3_nextValidPCNotEquals(if3_bp.target)
val if3_predNotTakenRedirect = !if3_pendingPrevHalfInstr && !if3_bp.taken && if3_nextValidPCNotEquals(snpc(if3_pc, inLoop))
val if3_predNotTakenRedirect = !if3_pendingPrevHalfInstr && !if3_bp.taken && if3_nextValidPCNotEquals(snpc(if3_pc))
// when pendingPrevHalfInstr, if3_GHInfo is set to the info of last prev half instr
// val if3_ghInfoNotIdenticalRedirect = !if3_pendingPrevHalfInstr && if3_GHInfo =/= if3_lastGHInfo && enableGhistRepair.B
......@@ -252,9 +265,9 @@ class IFU extends XSModule with HasIFUConst
val if4_valid = RegInit(false.B)
val if4_fire = if4_valid && io.fetchPacket.ready
val if4_pc = RegEnable(if3_pc, if3_fire)
// This is the real mask given from icache or loop buffer
// This is the real mask given from icache
val if4_mask = RegEnable(icacheResp.mask, if3_fire)
val if4_snpc = Mux(inLoop, if4_pc + (PopCount(if4_mask) << 1), snpc(if4_pc))
val if4_snpc = snpc(if4_pc)
val if4_predHist = RegEnable(if3_predHist, enable=if3_fire)
......@@ -270,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)
......@@ -301,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
}
......@@ -317,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)
......@@ -325,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) ||
......@@ -385,35 +400,21 @@ class IFU extends XSModule with HasIFUConst
flush_final_gh := true.B
}
npcGen.register(loopBufPar.LBredirect.valid, loopBufPar.LBredirect.bits)
npcGen.register(io.redirect.valid, io.redirect.bits)
npcGen.register(RegNext(reset.asBool) && !reset.asBool, resetVector.U(VAddrBits.W))
if1_npc := npcGen()
when(inLoop) {
io.icacheReq.valid := if4_flush
}.otherwise {
io.icacheReq.valid := if1_valid && (if2_ready || if1_flush)
}
io.icacheResp.ready := if4_ready
io.icacheReq.bits.addr := if1_npc
// when(if4_bp.taken) {
// when(if4_bp.saveHalfRVI) {
// io.loopBufPar.LBReq := snpc(if4_pc)
// }.otherwise {
// io.loopBufPar.LBReq := if4_bp.target
// }
// }.otherwise {
// io.loopBufPar.LBReq := snpc(if4_pc)
// XSDebug(p"snpc(if4_pc)=${Hexadecimal(snpc(if4_pc))}\n")
// }
loopBufPar.fetchReq := if3_pc
io.icacheReq.bits.mask := mask(if1_npc)
io.icacheFlush := Cat(if3_flush, if2_flush)
icache.io.req.valid := if1_valid && (if2_ready || if2_flush)
icache.io.resp.ready := if4_ready
icache.io.req.bits.addr := if1_npc
icache.io.req.bits.mask := mask(if1_npc)
icache.io.flush := Cat(if3_flush, if2_flush)
icache.io.mem_grant <> io.icacheMemGrant
icache.io.fencei := io.fencei
io.icacheMemAcq <> icache.io.mem_acquire
io.l1plusFlush := icache.io.l1plusflush
bpu.io.cfiUpdateInfo <> io.cfiUpdateInfo
......@@ -435,13 +436,6 @@ class IFU extends XSModule with HasIFUConst
bpu.io.prevHalf := if4_prevHalfInstr
pd.io.in := icacheResp
when(inLoop) {
pd.io.in.mask := loopBuffer.io.out.bits.mask // TODO: Maybe this is unnecessary
// XSDebug("Fetch from LB\n")
// XSDebug(p"pc=${Hexadecimal(io.loopBufPar.LBResp.pc)}\n")
// XSDebug(p"data=${Hexadecimal(io.loopBufPar.LBResp.data)}\n")
// XSDebug(p"mask=${Hexadecimal(io.loopBufPar.LBResp.mask)}\n")
}
pd.io.prev.valid := if3_prevHalfInstrMet
pd.io.prev.bits := if3_prevHalfInstr.bits.instr
......@@ -459,12 +453,6 @@ class IFU extends XSModule with HasIFUConst
when (icacheResp.ipf && !if3_prevHalfInstr.bits.ipf) { crossPageIPF := true.B } // higher 16 bits page fault
}
//Performance Counter
// if (!env.FPGAPlatform ) {
// ExcitingUtils.addSource(io.fetchPacket.fire && !inLoop, "CntFetchFromICache", Perf)
// ExcitingUtils.addSource(io.fetchPacket.fire && inLoop, "CntFetchFromLoopBuffer", Perf)
// }
val fetchPacketValid = if4_valid && !io.redirect.valid
val fetchPacketWire = Wire(new FetchPacket)
......@@ -473,13 +461,16 @@ class IFU extends XSModule with HasIFUConst
fetchPacketWire.mask := if4_pd.mask & (Fill(PredictWidth, !if4_bp.taken) | (Fill(PredictWidth, 1.U(1.W)) >> (~if4_bp.jmpIdx)))
fetchPacketWire.pdmask := if4_pd.mask
loopBufPar.noTakenMask := if4_pd.mask
fetchPacketWire.pc := if4_pd.pc
(0 until PredictWidth).foreach(i => fetchPacketWire.pnpc(i) := if4_pd.pc(i) + Mux(if4_pd.pd(i).isRVC, 2.U, 4.U))
when (if4_bp.taken) {
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
......@@ -494,30 +485,28 @@ class IFU extends XSModule with HasIFUConst
// predTaken Vec
fetchPacketWire.predTaken := if4_bp.taken
loopBuffer.io.in.bits := fetchPacketWire
io.fetchPacket.bits := fetchPacketWire
io.fetchPacket.valid := fetchPacketValid
loopBuffer.io.in.valid := io.fetchPacket.fire
// debug info
if (IFUDebug) {
XSDebug(RegNext(reset.asBool) && !reset.asBool, "Reseting...\n")
XSDebug(io.icacheFlush(0).asBool, "Flush icache stage2...\n")
XSDebug(io.icacheFlush(1).asBool, "Flush icache stage3...\n")
XSDebug(icache.io.flush(0).asBool, "Flush icache stage2...\n")
XSDebug(icache.io.flush(1).asBool, "Flush icache stage3...\n")
XSDebug(io.redirect.valid, p"Redirect from backend! target=${Hexadecimal(io.redirect.bits)}\n")
XSDebug("[IF1] v=%d fire=%d flush=%d pc=%x mask=%b\n", if1_valid, if1_fire, if1_flush, if1_npc, mask(if1_npc))
XSDebug("[IF2] v=%d r=%d fire=%d redirect=%d flush=%d pc=%x snpc=%x\n", if2_valid, if2_ready, if2_fire, if2_redirect, if2_flush, if2_pc, if2_snpc)
XSDebug("[IF3] v=%d r=%d fire=%d redirect=%d flush=%d pc=%x crossPageIPF=%d sawNTBrs=%d\n", if3_valid, if3_ready, if3_fire, if3_redirect, if3_flush, if3_pc, crossPageIPF, if3_bp.hasNotTakenBrs)
XSDebug("[IF4] v=%d r=%d fire=%d redirect=%d flush=%d pc=%x crossPageIPF=%d sawNTBrs=%d\n", if4_valid, if4_ready, if4_fire, if4_redirect, if4_flush, if4_pc, if4_crossPageIPF, if4_bp.hasNotTakenBrs)
XSDebug("[IF1][icacheReq] v=%d r=%d addr=%x\n", io.icacheReq.valid, io.icacheReq.ready, io.icacheReq.bits.addr)
XSDebug("[IF1][icacheReq] v=%d r=%d addr=%x\n", icache.io.req.valid, icache.io.req.ready, icache.io.req.bits.addr)
XSDebug("[IF1][ghr] hist=%b\n", if1_gh.asUInt)
XSDebug("[IF1][ghr] extHist=%b\n\n", if1_gh.asUInt)
XSDebug("[IF2][bp] taken=%d jmpIdx=%d hasNTBrs=%d target=%x saveHalfRVI=%d\n\n", if2_bp.taken, if2_bp.jmpIdx, if2_bp.hasNotTakenBrs, if2_bp.target, if2_bp.saveHalfRVI)
if2_gh.debug("if2")
XSDebug("[IF3][icacheResp] v=%d r=%d pc=%x mask=%b\n", io.icacheResp.valid, io.icacheResp.ready, io.icacheResp.bits.pc, io.icacheResp.bits.mask)
XSDebug("[IF3][icacheResp] v=%d r=%d pc=%x mask=%b\n", icache.io.resp.valid, icache.io.resp.ready, icache.io.resp.bits.pc, icache.io.resp.bits.mask)
XSDebug("[IF3][bp] taken=%d jmpIdx=%d hasNTBrs=%d target=%x saveHalfRVI=%d\n", if3_bp.taken, if3_bp.jmpIdx, if3_bp.hasNotTakenBrs, if3_bp.target, if3_bp.saveHalfRVI)
XSDebug("[IF3][redirect]: v=%d, prevMet=%d, prevNMet=%d, predT=%d, predNT=%d\n", if3_redirect, if3_prevHalfMetRedirect, if3_prevHalfNotMetRedirect, if3_predTakenRedirect, if3_predNotTakenRedirect)
// XSDebug("[IF3][prevHalfInstr] v=%d redirect=%d fetchpc=%x idx=%d tgt=%x taken=%d instr=%x\n\n",
......
......@@ -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,
......
......@@ -62,7 +62,7 @@ class LoadQueue extends XSModule with HasDCacheParameters with HasCircularQueueP
val enqPtrExt = RegInit(VecInit((0 until RenameWidth).map(_.U.asTypeOf(new LqPtr))))
val deqPtrExt = RegInit(0.U.asTypeOf(new LqPtr))
val validCounter = RegInit(0.U(log2Ceil(LoadQueueSize).W))
val validCounter = RegInit(0.U(log2Ceil(LoadQueueSize + 1).W))
val allowEnqueue = RegInit(true.B)
val enqPtr = enqPtrExt(0).value
......
......@@ -58,7 +58,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
require(StoreQueueSize > RenameWidth)
val enqPtrExt = RegInit(VecInit((0 until RenameWidth).map(_.U.asTypeOf(new SqPtr))))
val deqPtrExt = RegInit(VecInit((0 until StorePipelineWidth).map(_.U.asTypeOf(new SqPtr))))
val validCounter = RegInit(0.U(log2Ceil(LoadQueueSize).W))
val validCounter = RegInit(0.U(log2Ceil(LoadQueueSize + 1).W))
val allowEnqueue = RegInit(true.B)
val enqPtr = enqPtrExt(0).value
......
......@@ -367,12 +367,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();
......@@ -422,6 +422,7 @@ inline char* Emulator::waveform_filename(time_t t) {
static char buf[1024];
char *p = timestamp_filename(t, buf);
strcpy(p, ".vcd");
printf("dump wave to %s...\n", buf);
return buf;
}
......
......@@ -4,7 +4,7 @@
#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;
......
package xiangshan.frontend
// package xiangshan.frontend
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.must.Matchers
// import chisel3._
// import chiseltest._
// import org.scalatest.flatspec.AnyFlatSpec
// import org.scalatest.matchers.must.Matchers
class IFUTest extends AnyFlatSpec with ChiselScalatestTester with Matchers {
behavior of "IFU Test"
// class IFUTest extends AnyFlatSpec with ChiselScalatestTester with Matchers {
// behavior of "IFU Test"
it should "test IFU pipeline" in {
test(new IFU) { c =>
//-----------------
//Cycle 0
//-----------------
//c.io.icacheReq.ready.poke(true.B)
c.io.icacheReq.ready.poke(false.B)
c.io.fetchPacket.ready.poke(true.B)
c.clock.step()
//-----------------
//Cycle 1
//-----------------
c.clock.step()
c.clock.step()
c.clock.step()
//-----------------
// Cycle 2
//-----------------
c.io.icacheReq.ready.poke(true.B)
c.clock.step()
//-----------------
// Cycle 3
//-----------------
c.clock.step()
//-----------------
// Cycle 4
//-----------------
c.io.icacheResp.valid.poke(true.B)
c.clock.step()
//-----------------
// Cycle 5
//-----------------
c.io.redirect.valid.poke(true.B)
c.io.redirect.bits.poke("h80002800".U)
c.clock.step()
//-----------------
// Cycle 6
//-----------------
c.io.redirect.valid.poke(false.B)
c.clock.step()
//-----------------
// Cycle 7
//-----------------
c.clock.step()
}
}
}
// it should "test IFU pipeline" in {
// test(new IFU) { c =>
// //-----------------
// //Cycle 0
// //-----------------
// //c.io.icacheReq.ready.poke(true.B)
// c.io.icacheReq.ready.poke(false.B)
// c.io.fetchPacket.ready.poke(true.B)
// c.clock.step()
// //-----------------
// //Cycle 1
// //-----------------
// c.clock.step()
// c.clock.step()
// c.clock.step()
// //-----------------
// // Cycle 2
// //-----------------
// c.io.icacheReq.ready.poke(true.B)
// c.clock.step()
// //-----------------
// // Cycle 3
// //-----------------
// c.clock.step()
// //-----------------
// // Cycle 4
// //-----------------
// c.io.icacheResp.valid.poke(true.B)
// c.clock.step()
// //-----------------
// // Cycle 5
// //-----------------
// c.io.redirect.valid.poke(true.B)
// c.io.redirect.bits.poke("h80002800".U)
// c.clock.step()
// //-----------------
// // Cycle 6
// //-----------------
// c.io.redirect.valid.poke(false.B)
// c.clock.step()
// //-----------------
// // Cycle 7
// //-----------------
// c.clock.step()
// }
// }
// }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册