From 79b191f7a732a04c6a87136318d0988c0db8b7b9 Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 28 Jan 2022 10:24:57 +0800 Subject: [PATCH] ICache : move parity decode to pipeline (#1443) * ICache : move parity decode to pipe * ICacheMainPipe : remove parity af * ReplacePipe : delay error generating --- .../xiangshan/frontend/icache/ICache.scala | 6 +- .../frontend/icache/ICacheBundle.scala | 4 +- .../frontend/icache/ICacheMainPipe.scala | 65 +++++++++++++------ .../frontend/icache/ReplacePipe.scala | 58 +++++++++++------ 4 files changed, 89 insertions(+), 44 deletions(-) diff --git a/src/main/scala/xiangshan/frontend/icache/ICache.scala b/src/main/scala/xiangshan/frontend/icache/ICache.scala index befffeaa4..422180fb3 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICache.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICache.scala @@ -369,11 +369,9 @@ class ICacheDataArray(implicit p: Parameters) extends ICacheArray for(((dataArray,codeArray),i) <- dataArrays.zip(codeArrays).zipWithIndex){ read_datas(i) := dataArray.io.r.resp.asTypeOf(Vec(nWays,UInt(blockBits.W))) read_codes(i) := codeArray.io.r.resp.asTypeOf(Vec(nWays,UInt(dataCodeEntryBits.W))) - val data_full_wayBits = VecInit((0 until nWays).map( w => Cat(read_codes(i)(w), read_datas(i)(w)))) - val data_error_wayBits = VecInit(data_full_wayBits.map(data => cacheParams.dataCode.decode(data).error) ) - (0 until nWays).map{ w => io.readResp.errors(i)(w) := RegNext(io.read.fire()) && data_error_wayBits(w) } } + //Parity Encode val write = io.write.bits val write_data = WireInit(write.data) @@ -382,6 +380,8 @@ class ICacheDataArray(implicit p: Parameters) extends ICacheArray io.readResp.datas(0) := Mux( port_0_read_1_reg, read_datas(1) , read_datas(0)) io.readResp.datas(1) := Mux( port_1_read_0_reg, read_datas(0) , read_datas(1)) + io.readResp.codes(0) := Mux( port_0_read_1_reg, read_codes(1) , read_codes(0)) + io.readResp.codes(1) := Mux( port_1_read_0_reg, read_codes(0) , read_codes(1)) io.write.ready := true.B diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala b/src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala index 2b0727ea4..4cc1ece2c 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala @@ -75,8 +75,8 @@ class ICacheDataWriteBundle(implicit p: Parameters) extends ICacheBundle class ICacheDataRespBundle(implicit p: Parameters) extends ICacheBundle { - val datas = Vec(2,Vec(nWays,UInt(blockBits.W))) - val errors = Vec(2, Vec(nWays ,Bool() )) + val datas = Vec(2, Vec(nWays, UInt(blockBits.W))) + val codes = Vec(2, Vec(nWays , UInt(dataCodeEntryBits.W))) } class ICacheMetaReadBundle(implicit p: Parameters) extends ICacheBundle diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala b/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala index bf4be22c6..552aea62d 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala @@ -263,11 +263,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule val s1_meta_errors = ResultHoldBypass(data = metaResp.errors, valid = RegNext(s0_fire)) val s1_data_cacheline = ResultHoldBypass(data = dataResp.datas, valid = RegNext(s0_fire)) - val s1_data_errors = ResultHoldBypass(data = dataResp.errors, valid = RegNext(s0_fire)) - - val s1_parity_meta_error = VecInit((0 until PortNumber).map(i => s1_meta_errors(i).reduce(_||_) && io.csr_parity_enable)) - val s1_parity_data_error = VecInit((0 until PortNumber).map(i => s1_data_errors(i).reduce(_||_) && io.csr_parity_enable)) - val s1_parity_error = VecInit((0 until PortNumber).map(i => s1_parity_meta_error(i) || s1_parity_data_error(i))) + val s1_data_errorBits = ResultHoldBypass(data = dataResp.codes, valid = RegNext(s0_fire)) val s1_tag_eq_vec = VecInit((0 until PortNumber).map( p => VecInit((0 until nWays).map( w => s1_meta_ptags(p)(w) === s1_req_ptags(p) )))) val s1_tag_match_vec = VecInit((0 until PortNumber).map( k => VecInit(s1_tag_eq_vec(k).zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s1_meta_cohs(k)(w).isValid()}))) @@ -285,18 +281,6 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule assert(PopCount(s1_tag_match_vec(0)) <= 1.U && PopCount(s1_tag_match_vec(1)) <= 1.U, "Multiple hit in main pipe") - for(i <- 0 until PortNumber){ - io.errors(i).valid := RegNext(s1_parity_error(i) && RegNext(s0_fire)) - io.errors(i).report_to_beu := RegNext(s1_parity_error(i) && RegNext(s0_fire)) - io.errors(i).paddr := RegNext(tlbRespPAddr(i)) - io.errors(i).source := DontCare - io.errors(i).source.tag := RegNext(s1_parity_meta_error(i)) - io.errors(i).source.data := RegNext(s1_parity_data_error(i)) - io.errors(i).source.l2 := false.B - io.errors(i).opType := DontCare - io.errors(i).opType.fetch := true.B - } - ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)} val s1_hit_data = VecInit(s1_data_cacheline.zipWithIndex.map { case(bank, i) => @@ -360,6 +344,49 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule val s2_fixed_hit_vec = VecInit((0 until 2).map(i => s2_port_hit(i) || sec_meet_vec(i))) val s2_fixed_hit = (s2_valid && s2_fixed_hit_vec(0) && s2_fixed_hit_vec(1) && s2_double_line) || (s2_valid && s2_fixed_hit_vec(0) && !s2_double_line) + val s2_meta_errors = RegEnable(next = s1_meta_errors, enable = s1_fire) + val s2_data_errorBits = RegEnable(next = s1_data_errorBits, enable = s1_fire) + val s2_data_cacheline = RegEnable(next = s1_data_cacheline, enable = s1_fire) + + val s2_data_errors = Wire(Vec(PortNumber,Vec(nWays, Bool()))) + + (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)))) + val data_full_wayBits = VecInit((0 until nWays).map( w => + VecInit((0 until dataCodeUnitNum).map(u => + Cat(read_codes(w)(u), read_datas(w)(u)))))) + 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 )))) + if(i == 0){ + (0 until nWays).map{ w => + s2_data_errors(i)(w) := RegNext(RegNext(s1_fire)) && RegNext(data_error_wayBits(w)).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(_||_) + } + } + } + + val s2_parity_meta_error = VecInit((0 until PortNumber).map(i => s2_meta_errors(i).reduce(_||_) && io.csr_parity_enable)) + val s2_parity_data_error = VecInit((0 until PortNumber).map(i => s2_data_errors(i).reduce(_||_) && io.csr_parity_enable)) + 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)) + io.errors(i).report_to_beu := RegNext(s2_parity_error(i)) + io.errors(i).paddr := RegNext(RegNext(s2_req_paddr(i))) + 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.l2 := false.B + io.errors(i).opType := DontCare + io.errors(i).opType.fetch := true.B + } + + /** exception and pmp logic **/ //PMP Result val pmpExcpAF = Wire(Vec(PortNumber, Bool())) @@ -367,8 +394,8 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule pmpExcpAF(1) := fromPMP(1).instr && s2_double_line //exception information val s2_except_pf = RegEnable(next =tlbExcpPF, enable = s1_fire) - val s2_except_af = VecInit(RegEnable(next = tlbExcpAF, enable = s1_fire).zip(RegEnable(next = s1_parity_error, enable = s1_fire)).zip(pmpExcpAF).map{ - case((tlbAf, parityError), pmpAf) => tlbAf || parityError || DataHoldBypass(pmpAf, RegNext(s1_fire)).asBool}) + val s2_except_af = VecInit(RegEnable(next = tlbExcpAF, enable = s1_fire).zip(pmpExcpAF).map{ + case(tlbAf, pmpAf) => tlbAf || DataHoldBypass(pmpAf, RegNext(s1_fire)).asBool}) val s2_except = VecInit((0 until 2).map{i => s2_except_pf(i) || s2_except_af(i)}) val s2_has_except = s2_valid && (s2_except_af.reduce(_||_) || s2_except_pf.reduce(_||_)) //MMIO diff --git a/src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala b/src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala index b8e2508d4..d6b3153a8 100644 --- a/src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala +++ b/src/main/scala/xiangshan/frontend/icache/ReplacePipe.scala @@ -69,7 +69,7 @@ class ICacheReplacePipe(implicit p: Parameters) extends ICacheModule{ val (toMeta, metaResp) = (io.meta_read, io.meta_response.metaData(0)) val (toData, dataResp) = (io.data_read, io.data_response.datas(0)) - val (metaError, dataError) = (io.meta_response.errors(0), io.data_response.errors(0)) + val (metaError, codeResp) = (io.meta_response.errors(0), io.data_response.codes(0)) val r0_ready, r1_ready, r2_ready = WireInit(false.B) val r0_fire, r1_fire , r2_fire, r3_fire = WireInit(false.B) @@ -114,13 +114,8 @@ class ICacheReplacePipe(implicit p: Parameters) extends ICacheModule{ val r1_meta_cohs = ResultHoldBypass(data = VecInit(metaResp.map(way => way.coh)),valid = RegNext(r0_fire)) val r1_meta_errors = ResultHoldBypass(data = metaError, valid = RegNext(r0_fire)) - val r1_data_cacheline = ResultHoldBypass(VecInit(dataResp.map(way => way)),valid = RegNext(r0_fire)) - val r1_data_errors = ResultHoldBypass(data = dataError, valid = RegNext(r0_fire)) - - - val r1_parity_meta_error = ResultHoldBypass(data = r1_meta_errors.reduce(_||_) && io.csr_parity_enable, valid = RegNext(r0_fire)) - val r1_parity_data_error = ResultHoldBypass(data = r1_data_errors.reduce(_||_) && io.csr_parity_enable, valid = RegNext(r0_fire)) - val r1_parity_error = ResultHoldBypass(data = r1_meta_errors.reduce(_||_) || r1_data_errors.reduce(_||_), valid = RegNext(r0_fire)) + val r1_data_cacheline = ResultHoldBypass(data = VecInit(dataResp.map(way => way)),valid = RegNext(r0_fire)) + val r1_data_errorBits = ResultHoldBypass(data = VecInit(codeResp.map(way => way)), valid = RegNext(r0_fire)) /*** for Probe hit check ***/ @@ -140,18 +135,6 @@ class ICacheReplacePipe(implicit p: Parameters) extends ICacheModule{ io.status.r1_set.valid := r1_valid io.status.r1_set.bits := r1_req.vidx - io.error.valid := RegNext(r1_parity_error && RegNext(r0_fire)) - io.error.report_to_beu := RegNext(r1_parity_error && RegNext(r0_fire)) - io.error.paddr := RegNext(r1_req.paddr) - io.error.source.tag := r1_parity_meta_error - io.error.source.data := r1_parity_data_error - io.error.source.l2 := false.B - io.error.opType := DontCare - io.error.opType.fetch := true.B - io.error.opType.release := RegNext(r1_req.isRelease) - io.error.opType.probe := RegNext(r1_req.isProbe) - - /** ****************************************************************************** * ReplacePipe Stage 2 @@ -174,6 +157,41 @@ class ICacheReplacePipe(implicit p: Parameters) extends ICacheModule{ val (probe_has_dirty_data, probe_shrink_param, probe_new_coh) = r2_probe_hit_coh.onProbe(r2_req.param) + + + val r2_meta_errors = RegEnable(next = r1_meta_errors, enable = r1_fire) + val r2_data_errorBits = RegEnable(next = r1_data_errorBits, enable = r1_fire) + + val r2_data_errors = Wire(Vec(nWays, Bool())) + + 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)))) + val data_full_wayBits = VecInit((0 until nWays).map( w => + VecInit((0 until dataCodeUnitNum).map(u => + Cat(read_codes(w)(u), read_datas(w)(u)))))) + 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(_||_) } + + 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 ) + io.error.report_to_beu := RegNext(r2_parity_error ) + 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) + io.error.source.l2 := false.B + io.error.opType := DontCare + io.error.opType.fetch := true.B + io.error.opType.release := RegNext(RegNext(r2_req.isRelease)) + io.error.opType.probe := RegNext(RegNext(r2_req.isProbe)) + + + /*** for Release mux ***/ val r2_release_ptag = RegEnable(next = release_tag, enable = r1_fire) val r2_release_coh = RegEnable(next = release_coh, enable = r1_fire) -- GitLab