fix: resolve OoO simulation timeout
This commit is contained in:
@@ -1,23 +1,180 @@
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class ICache(p: CoreParams = CoreParams()) extends Module {
|
||||
private val lineInsts = p.fetchWidth
|
||||
private val lineBytes = lineInsts * 4
|
||||
private val sets = p.iCacheBytes / (p.iCacheWays * lineBytes)
|
||||
private val setBits = log2Ceil(sets)
|
||||
private val instBits = log2Ceil(lineInsts)
|
||||
private val offsetBits = log2Ceil(lineBytes)
|
||||
|
||||
val io = IO(new Bundle {
|
||||
val reqValid = Input(Bool())
|
||||
val reqAddr = Input(UInt(p.xlen.W))
|
||||
val reqPc = Input(UInt(p.xlen.W))
|
||||
val flush = Input(Bool())
|
||||
val respReady = Input(Bool())
|
||||
val memReqValid = Output(Bool())
|
||||
val memReqAddr = Output(UInt(p.xlen.W))
|
||||
val memRespValid = Input(Bool())
|
||||
val memRespBits = Input(Vec(p.fetchWidth, UInt(32.W)))
|
||||
val respValid = Output(Bool())
|
||||
val resp = Output(new FetchPacket(p))
|
||||
val miss = Output(Bool())
|
||||
})
|
||||
|
||||
io.memReqValid := io.reqValid
|
||||
io.memReqAddr := io.reqAddr
|
||||
io.respValid := io.memRespValid
|
||||
io.resp.pc := io.reqAddr
|
||||
io.resp.inst := io.memRespBits
|
||||
io.resp.predictedTaken := false.B
|
||||
io.resp.predictedTarget := io.reqAddr + (4 * p.fetchWidth).U
|
||||
}
|
||||
def setIndex(addr: UInt): UInt = addr(offsetBits + setBits - 1, offsetBits)
|
||||
def instIndex(addr: UInt): UInt = addr(offsetBits - 1, 2)
|
||||
def tag(addr: UInt): UInt = addr(p.xlen - 1, offsetBits + setBits)
|
||||
def alignedFetchAddr(addr: UInt): UInt = Cat(addr(p.xlen - 1, offsetBits), 0.U(offsetBits.W))
|
||||
|
||||
val valid = RegInit(VecInit(Seq.fill(sets)(VecInit(Seq.fill(p.iCacheWays)(
|
||||
VecInit(Seq.fill(lineInsts)(false.B)))))))
|
||||
val tags = SyncReadMem(sets, Vec(p.iCacheWays, UInt((p.xlen - offsetBits - setBits).W)))
|
||||
val data = SyncReadMem(sets, Vec(p.iCacheWays, Vec(lineInsts, UInt(32.W))))
|
||||
val repl = RegInit(VecInit(Seq.fill(sets)(0.U(log2Ceil(p.iCacheWays).W))))
|
||||
|
||||
val sIdle :: sLookup :: sResp :: sMiss :: Nil = Enum(4)
|
||||
val state = RegInit(sIdle)
|
||||
|
||||
val lookupAddr = Reg(UInt(p.xlen.W))
|
||||
val lookupPc = Reg(UInt(p.xlen.W))
|
||||
val lookupSet = Reg(UInt(setBits.W))
|
||||
val lookupInst = Reg(UInt(instBits.W))
|
||||
val lookupValidRow = Reg(Vec(p.iCacheWays, Vec(lineInsts, Bool())))
|
||||
|
||||
val missAddr = Reg(UInt(p.xlen.W))
|
||||
val missPc = Reg(UInt(p.xlen.W))
|
||||
val missSet = Reg(UInt(setBits.W))
|
||||
val missInst = Reg(UInt(instBits.W))
|
||||
val missWay = Reg(UInt(log2Ceil(p.iCacheWays).W))
|
||||
val missRefillExisting = Reg(Bool())
|
||||
val missTagRow = Reg(Vec(p.iCacheWays, UInt((p.xlen - offsetBits - setBits).W)))
|
||||
val missDataRow = Reg(Vec(p.iCacheWays, Vec(lineInsts, UInt(32.W))))
|
||||
val missValidRow = Reg(Vec(p.iCacheWays, Vec(lineInsts, Bool())))
|
||||
val missReqSent = RegInit(false.B)
|
||||
|
||||
val respReg = Reg(new FetchPacket(p))
|
||||
|
||||
val reqSet = setIndex(io.reqAddr)
|
||||
val reqInst = instIndex(io.reqAddr)
|
||||
val readFire = state === sIdle && io.reqValid && !io.flush
|
||||
val readTags = tags.read(reqSet, readFire)
|
||||
val readData = data.read(reqSet, readFire)
|
||||
|
||||
val tagHitVec = VecInit((0 until p.iCacheWays).map(w => lookupValidRow(w).asUInt.orR && readTags(w) === tag(lookupAddr)))
|
||||
val hitVec = VecInit((0 until p.iCacheWays).map(w => tagHitVec(w) && lookupValidRow(w)(lookupInst)))
|
||||
val hit = hitVec.asUInt.orR
|
||||
val hitWay = OHToUInt(hitVec)
|
||||
val tagHit = tagHitVec.asUInt.orR
|
||||
val tagHitWay = OHToUInt(tagHitVec)
|
||||
val lastInst = (lineInsts - 1).U(instBits.W)
|
||||
val nextInst = lookupInst + 1.U
|
||||
val lookupCanFetchPair = lookupInst =/= lastInst
|
||||
val lookupLane1Valid = lookupCanFetchPair && lookupValidRow(hitWay)(nextInst)
|
||||
|
||||
val lookupResp = WireDefault(0.U.asTypeOf(new FetchPacket(p)))
|
||||
lookupResp.pc := lookupPc
|
||||
lookupResp.inst(0) := readData(hitWay)(lookupInst)
|
||||
lookupResp.inst(1) := Mux(lookupLane1Valid, readData(hitWay)(nextInst), 0.U)
|
||||
lookupResp.laneValid(0) := true.B
|
||||
lookupResp.laneValid(1) := lookupLane1Valid
|
||||
lookupResp.predictedTaken := false.B
|
||||
lookupResp.predictedTarget := lookupPc + (4 * p.fetchWidth).U
|
||||
|
||||
val missCanFetchPair = missInst =/= lastInst
|
||||
val missResp = WireDefault(0.U.asTypeOf(new FetchPacket(p)))
|
||||
missResp.pc := missPc
|
||||
missResp.inst(0) := io.memRespBits(0)
|
||||
missResp.inst(1) := Mux(missCanFetchPair, io.memRespBits(1), 0.U)
|
||||
missResp.laneValid(0) := true.B
|
||||
missResp.laneValid(1) := missCanFetchPair
|
||||
missResp.predictedTaken := false.B
|
||||
missResp.predictedTarget := missPc + (4 * p.fetchWidth).U
|
||||
|
||||
io.memReqValid := state === sMiss && !missReqSent
|
||||
io.memReqAddr := Mux(state === sMiss,
|
||||
Mux(missCanFetchPair, alignedFetchAddr(missAddr), missAddr),
|
||||
Mux(reqInst =/= lastInst, alignedFetchAddr(io.reqAddr), io.reqAddr))
|
||||
io.respValid := (state === sLookup && hit) || state === sResp || (state === sMiss && io.memRespValid)
|
||||
io.resp := Mux(state === sResp, respReg,
|
||||
Mux(state === sMiss && io.memRespValid, missResp, lookupResp))
|
||||
io.miss := state === sLookup && !hit || state === sMiss
|
||||
|
||||
when(io.flush) {
|
||||
state := sIdle
|
||||
missReqSent := false.B
|
||||
}.elsewhen(state === sIdle) {
|
||||
when(io.reqValid) {
|
||||
lookupAddr := io.reqAddr
|
||||
lookupPc := io.reqPc
|
||||
lookupSet := reqSet
|
||||
lookupInst := reqInst
|
||||
lookupValidRow := valid(reqSet)
|
||||
state := sLookup
|
||||
}
|
||||
}.elsewhen(state === sLookup) {
|
||||
when(hit) {
|
||||
repl(lookupSet) := hitWay
|
||||
when(io.respReady) {
|
||||
state := sIdle
|
||||
}.otherwise {
|
||||
respReg := lookupResp
|
||||
state := sResp
|
||||
}
|
||||
}.otherwise {
|
||||
missAddr := lookupAddr
|
||||
missPc := lookupPc
|
||||
missSet := lookupSet
|
||||
missInst := lookupInst
|
||||
missWay := Mux(tagHit, tagHitWay, repl(lookupSet))
|
||||
missRefillExisting := tagHit
|
||||
missTagRow := readTags
|
||||
missDataRow := readData
|
||||
missValidRow := lookupValidRow
|
||||
missReqSent := false.B
|
||||
state := sMiss
|
||||
}
|
||||
}.elsewhen(state === sResp) {
|
||||
when(io.respReady) {
|
||||
state := sIdle
|
||||
}
|
||||
}.elsewhen(state === sMiss) {
|
||||
when(!missReqSent) {
|
||||
missReqSent := true.B
|
||||
}
|
||||
when(io.memRespValid) {
|
||||
val tagWrite = Wire(Vec(p.iCacheWays, UInt((p.xlen - offsetBits - setBits).W)))
|
||||
val dataWrite = Wire(Vec(p.iCacheWays, Vec(lineInsts, UInt(32.W))))
|
||||
val validWrite = Wire(Vec(p.iCacheWays, Vec(lineInsts, Bool())))
|
||||
tagWrite := missTagRow
|
||||
dataWrite := missDataRow
|
||||
validWrite := missValidRow
|
||||
tagWrite(missWay) := tag(missAddr)
|
||||
when(!missRefillExisting) {
|
||||
for (i <- 0 until lineInsts) {
|
||||
validWrite(missWay)(i) := false.B
|
||||
}
|
||||
}
|
||||
dataWrite(missWay)(missInst) := io.memRespBits(0)
|
||||
validWrite(missWay)(missInst) := true.B
|
||||
when(missCanFetchPair) {
|
||||
dataWrite(missWay)(missInst + 1.U) := io.memRespBits(1)
|
||||
validWrite(missWay)(missInst + 1.U) := true.B
|
||||
}
|
||||
valid(missSet) := validWrite
|
||||
tags.write(missSet, tagWrite)
|
||||
data.write(missSet, dataWrite)
|
||||
when(!missRefillExisting) {
|
||||
repl(missSet) := missWay + 1.U
|
||||
}
|
||||
when(io.respReady) {
|
||||
state := sIdle
|
||||
}.otherwise {
|
||||
respReg := missResp
|
||||
state := sResp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user