Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

IFU & ICache clock gating #2734

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/main/scala/xiangshan/cache/CacheInstruction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,11 @@ class CSRCacheOpDecoder(decoder_name: String, id: Int)(implicit p: Parameters) e
data_transfer_cnt := 0.U
}

val error = DelayN(io.error, 1)
when(error.report_to_beu) {
val error = Wire(io.error.cloneType)
val (error_valid,error_bits) = DelayNWithValid(io.error, io.error.valid, 1)
error <> error_bits
error.valid := error_valid
when(error.report_to_beu && error.valid) {
io.csr.update.w.bits.addr := (CacheInstrucion.CacheInsRegisterList("CACHE_ERROR")("offset").toInt + Scachebase).U
io.csr.update.w.bits.data := error.asUInt
io.csr.update.w.valid := true.B
Expand Down
29 changes: 17 additions & 12 deletions src/main/scala/xiangshan/frontend/IFU.scala
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class IfuToPredChecker(implicit p: Parameters) extends XSBundle {
val instrValid = Vec(PredictWidth, Bool())
val pds = Vec(PredictWidth, new PreDecodeInfo)
val pc = Vec(PredictWidth, UInt(VAddrBits.W))
val fire_in = Bool()
}

class FetchToIBufferDB extends Bundle {
Expand Down Expand Up @@ -527,7 +528,10 @@ class NewIFU(implicit p: Parameters) extends XSModule
val f3_mmio_to_commit_next = RegNext(f3_mmio_to_commit)
val f3_mmio_can_go = f3_mmio_to_commit && !f3_mmio_to_commit_next

val fromFtqRedirectReg = RegNext(fromFtq.redirect,init = 0.U.asTypeOf(fromFtq.redirect))
// val fromFtqRedirectReg = RegNext(fromFtq.redirect,init = 0.U.asTypeOf(fromFtq.redirect))
val fromFtqRedirectReg = Wire(fromFtq.redirect.cloneType)
fromFtqRedirectReg.bits := RegEnable(fromFtq.redirect.bits, 0.U.asTypeOf(fromFtq.redirect.bits), fromFtq.redirect.valid)
fromFtqRedirectReg.valid := RegNext(fromFtq.redirect.valid, init = false.B)
val mmioF3Flush = RegNext(f3_flush,init = false.B)
val f3_ftq_flush_self = fromFtqRedirectReg.valid && RedirectLevel.flushItself(fromFtqRedirectReg.bits.level)
val f3_ftq_flush_by_older = fromFtqRedirectReg.valid && isBefore(fromFtqRedirectReg.bits.ftqIdx, f3_ftq_req.ftqIdx)
Expand Down Expand Up @@ -677,6 +681,7 @@ class NewIFU(implicit p: Parameters) extends XSModule
checkerIn.instrValid := f3_instr_valid.asTypeOf(Vec(PredictWidth, Bool()))
checkerIn.pds := f3_pd
checkerIn.pc := f3_pc
checkerIn.fire_in := RegNext(f2_fire, init = false.B)

/*** handle half RVI in the last 2 Bytes ***/

Expand Down Expand Up @@ -809,21 +814,21 @@ class NewIFU(implicit p: Parameters) extends XSModule
* - redirect if has false hit last half (last PC is not start + 32 Bytes, but in the midle of an notCFI RVI instruction)
******************************************************************************
*/
val wb_enable = RegNext(f2_fire && !f2_flush) && !f3_req_is_mmio && !f3_flush
val wb_valid = RegNext(wb_enable, init = false.B)
val wb_ftq_req = RegEnable(f3_ftq_req, wb_enable)

val wb_valid = RegNext(RegNext(f2_fire && !f2_flush) && !f3_req_is_mmio && !f3_flush)
val wb_ftq_req = RegNext(f3_ftq_req)

val wb_check_result_stage1 = RegNext(checkerOutStage1)
val wb_check_result_stage1 = RegEnable(checkerOutStage1, wb_enable)
val wb_check_result_stage2 = checkerOutStage2
val wb_instr_range = RegNext(io.toIbuffer.bits.enqEnable)
val wb_pc = RegNext(f3_pc)
val wb_pd = RegNext(f3_pd)
val wb_instr_valid = RegNext(f3_instr_valid)
val wb_instr_range = RegEnable(io.toIbuffer.bits.enqEnable, wb_enable)
val wb_pc = RegEnable(f3_pc, wb_enable)
val wb_pd = RegEnable(f3_pd, wb_enable)
val wb_instr_valid = RegEnable(f3_instr_valid, wb_enable)

/* false hit lastHalf */
val wb_lastIdx = RegNext(f3_last_validIdx)
val wb_false_lastHalf = RegNext(f3_false_lastHalf) && wb_lastIdx =/= (PredictWidth - 1).U
val wb_false_target = RegNext(f3_false_snpc)
val wb_lastIdx = RegEnable(f3_last_validIdx, wb_enable)
val wb_false_lastHalf = RegEnable(f3_false_lastHalf, wb_enable) && wb_lastIdx =/= (PredictWidth - 1).U
val wb_false_target = RegEnable(f3_false_snpc, wb_enable)

val wb_half_flush = wb_false_lastHalf
val wb_half_target = wb_false_target
Expand Down
32 changes: 16 additions & 16 deletions src/main/scala/xiangshan/frontend/PreDecode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -361,31 +361,31 @@ class PredChecker(implicit p: Parameters) extends XSModule with HasPdConst {

//Stage 2: detect target fault
/** target calculation: in the next stage */
val fixedRangeNext = RegNext(fixedRange)
val instrValidNext = RegNext(instrValid)
val takenIdxNext = RegNext(takenIdx)
val predTakenNext = RegNext(predTaken)
val predTargetNext = RegNext(predTarget)
val jumpTargetsNext = RegNext(jumpTargets)
val seqTargetsNext = RegNext(seqTargets)
val pdsNext = RegNext(pds)
val jalFaultVecNext = RegNext(jalFaultVec)
val retFaultVecNext = RegNext(retFaultVec)
val notCFITakenNext = RegNext(notCFITaken)
val invalidTakenNext = RegNext(invalidTaken)
val fixedRangeNext = RegEnable(fixedRange, io.in.fire_in)
val instrValidNext = RegEnable(instrValid, io.in.fire_in)
val takenIdxNext = RegEnable(takenIdx, io.in.fire_in)
val predTakenNext = RegEnable(predTaken, io.in.fire_in)
val predTargetNext = RegEnable(predTarget, io.in.fire_in)
val jumpTargetsNext = RegEnable(jumpTargets, io.in.fire_in)
val seqTargetsNext = RegEnable(seqTargets, io.in.fire_in)
val pdsNext = RegEnable(pds, io.in.fire_in)
val jalFaultVecNext = RegEnable(jalFaultVec, io.in.fire_in)
val retFaultVecNext = RegEnable(retFaultVec, io.in.fire_in)
val notCFITakenNext = RegEnable(notCFITaken, io.in.fire_in)
val invalidTakenNext = RegEnable(invalidTaken, io.in.fire_in)

targetFault := VecInit(pdsNext.zipWithIndex.map{case(pd,i) => fixedRangeNext(i) && instrValidNext(i) && (pd.isJal || pd.isBr) && takenIdxNext === i.U && predTakenNext && (predTargetNext =/= jumpTargetsNext(i))})


io.out.stage2Out.faultType.zipWithIndex.map{case(faultType, i) => faultType.value := Mux(jalFaultVecNext(i) , FaultType.jalFault ,
io.out.stage2Out.faultType.zipWithIndex.foreach{case(faultType, i) => faultType.value := Mux(jalFaultVecNext(i) , FaultType.jalFault ,
Mux(retFaultVecNext(i), FaultType.retFault ,
Mux(targetFault(i), FaultType.targetFault ,
Mux(notCFITakenNext(i) , FaultType.notCFIFault,
Mux(invalidTakenNext(i), FaultType.invalidTaken, FaultType.noFault)))))}

io.out.stage2Out.fixedMissPred.zipWithIndex.map{case(missPred, i ) => missPred := jalFaultVecNext(i) || retFaultVecNext(i) || notCFITakenNext(i) || invalidTakenNext(i) || targetFault(i)}
io.out.stage2Out.fixedTarget.zipWithIndex.map{case(target, i) => target := Mux(jalFaultVecNext(i) || targetFault(i), jumpTargetsNext(i), seqTargetsNext(i) )}
io.out.stage2Out.jalTarget.zipWithIndex.map{case(target, i) => target := jumpTargetsNext(i) }
io.out.stage2Out.fixedMissPred.zipWithIndex.foreach{case(missPred, i ) => missPred := jalFaultVecNext(i) || retFaultVecNext(i) || notCFITakenNext(i) || invalidTakenNext(i) || targetFault(i)}
io.out.stage2Out.fixedTarget.zipWithIndex.foreach{case(target, i) => target := Mux(jalFaultVecNext(i) || targetFault(i), jumpTargetsNext(i), seqTargetsNext(i) )}
io.out.stage2Out.jalTarget.zipWithIndex.foreach{case(target, i) => target := jumpTargetsNext(i) }

}

Expand Down
8 changes: 6 additions & 2 deletions src/main/scala/xiangshan/frontend/icache/ICache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,16 @@ class ICacheMetaArray()(implicit p: Parameters) extends ICacheArray
io.read.ready := !io.write.valid && !io.fencei && tagArrays.map(_.io.r.req.ready).reduce(_&&_)

//Parity Decode
val read_fire_delay1 = RegNext(io.read.fire, init = false.B)
val read_fire_delay2 = RegNext(read_fire_delay1, init = false.B)
val read_metas = Wire(Vec(2,Vec(nWays,new ICacheMetadata())))
for((tagArray,i) <- tagArrays.zipWithIndex){
val read_meta_bits = tagArray.io.r.resp.asTypeOf(Vec(nWays,UInt(metaEntryBits.W)))
val read_meta_decoded = read_meta_bits.map{ way_bits => cacheParams.tagCode.decode(way_bits)}
val read_meta_wrong = read_meta_decoded.map{ way_bits_decoded => way_bits_decoded.error}
val read_meta_corrected = VecInit(read_meta_decoded.map{ way_bits_decoded => way_bits_decoded.corrected})
read_metas(i) := read_meta_corrected.asTypeOf(Vec(nWays,new ICacheMetadata()))
(0 until nWays).map{ w => io.readResp.errors(i)(w) := RegNext(read_meta_wrong(w)) && RegNext(RegNext(io.read.fire))}
(0 until nWays).foreach{ w => io.readResp.errors(i)(w) := RegEnable(read_meta_wrong(w), read_fire_delay1) && read_fire_delay2}
}

//Parity Encode
Expand Down Expand Up @@ -627,7 +629,9 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame

//Parity error port
val errors = mainPipe.io.errors
io.error <> RegNext(Mux1H(errors.map(e => e.valid -> e)))
//io.error <> RegNext(Mux1H(errors.map(e => e.valid -> e)))
io.error <> RegEnable(Mux1H(errors.map(e => e.valid -> e)),errors.map(e => e.valid).reduce(_|_))
io.error.valid := RegNext(errors.map(e => e.valid).reduce(_|_),init = false.B)


mainPipe.io.fetch.req <> io.fetch.req
Expand Down
22 changes: 14 additions & 8 deletions src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
*/
// data/meta parity error
val s2_data_errors = Wire(Vec(PortNumber,Vec(nWays, Bool())))

val s1_fire_delay1 = RegNext(s1_fire,init = false.B)
val s1_fire_delay2 = RegNext(s1_fire_delay1, init = false.B)
val s1_double_line_delay2 = RegNext(RegNext(s1_double_line))

(0 until PortNumber).map{ i =>
val read_datas = s2_data_cacheline(i).asTypeOf(Vec(nWays,Vec(dataCodeUnitNum, UInt(dataCodeUnit.W))))
val read_codes = s2_data_errorBits(i).asTypeOf(Vec(nWays,Vec(dataCodeUnitNum, UInt(dataCodeBits.W))))
Expand All @@ -642,11 +647,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
// register for timing
if(i == 0){
(0 until nWays).map{ w =>
s2_data_errors(i)(w) := RegNext(RegNext(s1_fire)) && RegNext(data_error_wayBits(w)).reduce(_||_)
s2_data_errors(i)(w) := s1_fire_delay2 && RegEnable(data_error_wayBits(w),s1_fire_delay1).reduce(_||_)
}
} else {
(0 until nWays).map{ w =>
s2_data_errors(i)(w) := RegNext(RegNext(s1_fire)) && RegNext(RegNext(s1_double_line)) && RegNext(data_error_wayBits(w)).reduce(_||_)
s2_data_errors(i)(w) := s1_fire_delay2 && s1_double_line_delay2 && RegEnable(data_error_wayBits(w),s1_fire_delay1).reduce(_||_)
}
}
}
Expand All @@ -656,12 +661,13 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
val s2_parity_error = VecInit((0 until PortNumber).map(i => RegNext(s2_parity_meta_error(i)) || s2_parity_data_error(i)))

for(i <- 0 until PortNumber){
io.errors(i).valid := RegNext(s2_parity_error(i) && RegNext(RegNext(s1_fire)))
io.errors(i).report_to_beu := RegNext(s2_parity_error(i) && RegNext(RegNext(s1_fire)))
io.errors(i).paddr := RegNext(RegNext(s2_req_paddr(i)))
val valid = s2_parity_error(i) && s1_fire_delay2
io.errors(i).valid := RegNext(valid)
io.errors(i).report_to_beu := RegNext(valid)
io.errors(i).paddr := RegEnable(RegEnable(s2_req_paddr(i), s1_fire_delay1), valid)
io.errors(i).source := DontCare
io.errors(i).source.tag := RegNext(RegNext(s2_parity_meta_error(i)))
io.errors(i).source.data := RegNext(s2_parity_data_error(i))
io.errors(i).source.tag := RegEnable(RegEnable(s2_parity_meta_error(i), s1_fire_delay1), valid)
io.errors(i).source.data := RegEnable(s2_parity_data_error(i), valid)
io.errors(i).source.l2 := false.B
io.errors(i).opType := DontCare
io.errors(i).opType.fetch := true.B
Expand All @@ -672,7 +678,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
when(RegNext(s2_fire && s2_corrupt(i))){
io.errors(i).valid := true.B
io.errors(i).report_to_beu := false.B // l2 should have report that to bus error unit, no need to do it again
io.errors(i).paddr := RegNext(s2_req_paddr(i))
io.errors(i).paddr := RegEnable(s2_req_paddr(i),s1_fire_delay1)
io.errors(i).source.tag := false.B
io.errors(i).source.data := false.B
io.errors(i).source.l2 := true.B
Expand Down
Loading