Skip to content

Commit

Permalink
ICache: Clock gating optimization #0. Static clock gating rate is now…
Browse files Browse the repository at this point in the history
… 99.80%.
  • Loading branch information
Siudya committed Aug 15, 2022
1 parent c0daceb commit 1de1aa1
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 21 deletions.
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 @@ -197,14 +197,16 @@ class ICacheMetaArray()(implicit p: Parameters) extends ICacheArray
io.read.ready := !io.write.valid && 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 @@ -610,7 +612,9 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame

//Parity error port
val errors = mainPipe.io.errors ++ Seq(replacePipe.io.error)
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)


/** Block set-conflict request */
Expand Down
23 changes: 14 additions & 9 deletions src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule

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 @@ -437,11 +441,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
cacheParams.dataCode.decode(data_full_wayBits(w)(u)).error ))))
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 @@ -451,12 +455,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), enable = s1_fire_delay1), enable = 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), enable = s1_fire_delay1), enable = valid)
io.errors(i).source.data := RegEnable(s2_parity_data_error(i), enable = valid)
io.errors(i).source.l2 := false.B
io.errors(i).opType := DontCare
io.errors(i).opType.fetch := true.B
Expand All @@ -483,7 +488,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
val s2_mmio = DataHoldBypass(io.pmp(0).resp.mmio && !s2_except_tlb_af(0) && !s2_except_pmp_af(0) && !s2_except_pf(0), RegNext(s1_fire)).asBool() && s2_valid

//send physical address to PMP
io.pmp.zipWithIndex.map { case (p, i) =>
io.pmp.zipWithIndex.foreach { case (p, i) =>
p.req.valid := s2_valid && !missSwitchBit
p.req.bits.addr := s2_req_paddr(i)
p.req.bits.size := 3.U // TODO
Expand Down Expand Up @@ -813,7 +818,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
when(RegNext(s2_fire && missSlot(i).m_corrupt)){
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
22 changes: 12 additions & 10 deletions src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ class ICacheReplacePipe(implicit p: Parameters) extends ICacheModule{
val r2_data_errorBits = RegEnable(next = r1_data_errorBits, enable = r1_fire)

val r2_data_errors = Wire(Vec(nWays, Bool()))
val r1_fire_delay1 = RegNext(r1_fire, init = false.B)
val r1_fire_delay2 = RegNext(r1_fire_delay1, init = false.B)

val read_datas = r2_data_cacheline.asTypeOf(Vec(nWays,Vec(dataCodeUnitNum, UInt(dataCodeUnit.W))))
val read_codes = r2_data_errorBits.asTypeOf(Vec(nWays,Vec(dataCodeUnitNum, UInt(dataCodeBits.W))))
Expand All @@ -184,23 +186,23 @@ class ICacheReplacePipe(implicit p: Parameters) extends ICacheModule{
val data_error_wayBits = VecInit((0 until nWays).map( w =>
VecInit((0 until dataCodeUnitNum).map(u =>
cacheParams.dataCode.decode(data_full_wayBits(w)(u)).error ))))
(0 until nWays).map{ w => r2_data_errors(w) := RegNext(RegNext(r1_fire)) && RegNext(data_error_wayBits(w)).reduce(_||_) }
(0 until nWays).foreach{ w => r2_data_errors(w) := r1_fire_delay2 && RegEnable(data_error_wayBits(w), r1_fire_delay1).reduce(_||_) }

val r2_parity_meta_error = r2_meta_errors.reduce(_||_) && io.csr_parity_enable
val r2_parity_data_error = r2_data_errors.reduce(_||_) && io.csr_parity_enable
val r2_parity_error = RegNext(r2_parity_meta_error) || r2_parity_data_error


io.error.valid := RegNext(r2_parity_error && RegNext(RegNext(r1_fire)))
io.error.report_to_beu := RegNext(r2_parity_error && RegNext(RegNext(r1_fire)))
io.error.paddr := RegNext(RegNext(r2_req.paddr))
io.error.source.tag := RegNext(RegNext(r2_parity_meta_error))
io.error.source.data := RegNext(r2_parity_data_error)
val valid = r2_parity_error && r1_fire_delay2
io.error.valid := RegNext(valid)
io.error.report_to_beu := RegNext(valid)
io.error.paddr := RegEnable(RegEnable(r2_req.paddr, enable = r1_fire_delay1), enable = valid)
io.error.source.tag := RegEnable(RegEnable(r2_parity_meta_error, enable = r1_fire_delay1), enable = valid)
io.error.source.data := RegEnable(r2_parity_data_error, enable = valid)
io.error.source.l2 := false.B
io.error.opType := DontCare
io.error.opType.fetch := true.B
io.error.opType.release := RegNext(RegNext(!r2_req_is_probe_dup_1))
io.error.opType.probe := RegNext(RegNext(r2_req_is_probe_dup_1))
io.error.opType.release := RegEnable(RegEnable(!r2_req_is_probe_dup_1, enable = r1_fire_delay1), enable = valid)
io.error.opType.probe := RegEnable(RegEnable(r2_req_is_probe_dup_1, enable = r1_fire_delay1), enable = valid)

XSError(r2_parity_error && RegNext(RegNext(r1_fire)), "ICache has parity error in ReplacePipe!")

Expand Down Expand Up @@ -257,7 +259,7 @@ class ICacheReplacePipe(implicit p: Parameters) extends ICacheModule{
val r3_release_need_send = RegEnable(next = release_need_send, enable = r2_fire && r2_req.isRelease)

r3_ready := r3_fire || !r3_valid
r3_fire := (r3_valid && RegNext(io.release_finish) && r3_release_need_send) || (r3_valid && !r3_release_need_send)
r3_fire := (r3_valid && RegNext(io.release_finish) && r3_release_need_send) || (r3_valid && !r3_release_need_send)

val r3_req = RegEnable(next = r2_req, enable = r2_fire && r2_req.isRelease)

Expand Down

0 comments on commit 1de1aa1

Please sign in to comment.