From ea25eb32fcbfdadf5c9ff3c8954a9a3548ff751e Mon Sep 17 00:00:00 2001 From: wangkaifan Date: Thu, 21 Oct 2021 15:09:32 +0800 Subject: [PATCH] ecc: integrate ecc to ctrlUnit --- src/main/scala/huancun/BaseMSHR.scala | 1 + src/main/scala/huancun/CtrlUnit.scala | 28 +++++++++++++++--- src/main/scala/huancun/DataStorage.scala | 11 +++++-- src/main/scala/huancun/HuanCun.scala | 12 +++++++- src/main/scala/huancun/Slice.scala | 29 +++++++++++++------ .../scala/huancun/noninclusive/MSHR.scala | 17 +++++++++-- .../huancun/noninclusive/SliceCtrl.scala | 2 ++ src/main/scala/huancun/utils/NoopNode.scala | 21 ++++++++++++++ 8 files changed, 101 insertions(+), 20 deletions(-) create mode 100644 src/main/scala/huancun/utils/NoopNode.scala diff --git a/src/main/scala/huancun/BaseMSHR.scala b/src/main/scala/huancun/BaseMSHR.scala index 894b65b..97dd636 100644 --- a/src/main/scala/huancun/BaseMSHR.scala +++ b/src/main/scala/huancun/BaseMSHR.scala @@ -60,6 +60,7 @@ abstract class BaseMSHRIO[T_RESULT <: BaseDirResult, T_DIR_W <: BaseDirWrite, T_ val dirResult: Valid[T_RESULT] // = Flipped(ValidIO(new DirResult)) val resps = Flipped(new MSHRResps) val nestedwb = Input(new NestedWriteback) + val ecc = Output(new EccInfo) } abstract class BaseMSHR[T_RESULT <: BaseDirResult, T_DIR_W <: BaseDirWrite, T_TAG_W <: BaseTagWrite]( diff --git a/src/main/scala/huancun/CtrlUnit.scala b/src/main/scala/huancun/CtrlUnit.scala index da290d5..135edd9 100644 --- a/src/main/scala/huancun/CtrlUnit.scala +++ b/src/main/scala/huancun/CtrlUnit.scala @@ -27,6 +27,7 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) { val req = IO(DecoupledIO(new CtrlReq())) val resp = IO(Flipped(DecoupledIO(new CtrlResp()))) + val ecc = IO(Flipped(DecoupledIO(new EccInfo()))) val node = wrapper.node val ctlnode = wrapper.ctlnode @@ -66,10 +67,14 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) { val ctl_way = RegInit(0.U(64.W)) val ctl_dir = RegInit(0.U(64.W)) val ctl_data = Seq.fill(cacheParams.blockBytes / 8){ RegInit(0.U(64.W)) } - val ctl_ecc = RegInit(0.U(64.W)) val ctl_client = RegInit(0.U(64.W)) val ctl_cmd = RegInit(0.U(64.W)) + val ecc_code = RegInit(0.U(64.W)) // assume non-zero as ECC error + val ecc_tag = RegInit(0.U(64.W)) + val ecc_set = RegInit(0.U(64.W)) + val ecc_way = RegInit(0.U(64.W)) + val cmd_in_valid = RegInit(false.B) val cmd_in_ready = WireInit(false.B) val cmd_out_valid = RegInit(false.B) @@ -80,8 +85,10 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) { val ctl_config_regs = ( Seq(ctl_tag, ctl_set, ctl_way) ++ - ctl_data ++ Seq(ctl_dir, ctl_ecc, ctl_client) - ).map(reg => RegField(64, reg, RegWriteFn(reg))) + ctl_data ++ + Seq(ctl_dir, ctl_client) ++ + Seq(ecc_code, ecc_tag, ecc_set, ecc_way) + ).map(reg => RegField(64, reg, RegWriteFn(reg))) ctlnode.regmap( 0x000 -> RegFieldGroup( @@ -106,6 +113,7 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) { cmd_out_valid := true.B } resp.ready := !cmd_out_valid + ecc.ready := ecc_code === 0.U // Block multiple ecc req req.valid := cmd_in_valid req.bits.cmd := ctl_cmd req.bits.data.zip(ctl_data).foreach(x => x._1 := x._2) @@ -115,7 +123,7 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) { req.bits.dir := ctl_dir req.bits.client := ctl_client - when(resp.fire()){ + when(resp.fire()) { switch(resp.bits.cmd){ is(CacheCMD.CMD_R_S_TAG){ ctl_tag := resp.bits.data(0) @@ -134,6 +142,10 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) { } } } + + when(ecc.fire()) { + ecc_code := ecc.bits.errCode + } } class CtrlReq() extends Bundle { @@ -151,6 +163,14 @@ class CtrlResp() extends Bundle { val data = Vec(8, UInt(64.W)) } +class EccInfo() extends Bundle { + val errCode = UInt(8.W) + def ERR_NO = 0.U(8.W) + def ERR_SELF_DIR = 1.U(8.W) + def ERR_CLIENT_DIR = 2.U(8.W) + def ERR_DATA = 3.U(8.W) +} + object CacheCMD { def CMD_R_S_TAG = 0.U(8.W) def CMD_R_C_TAG = 1.U(8.W) diff --git a/src/main/scala/huancun/DataStorage.scala b/src/main/scala/huancun/DataStorage.scala index 183b77d..c292dca 100644 --- a/src/main/scala/huancun/DataStorage.scala +++ b/src/main/scala/huancun/DataStorage.scala @@ -36,6 +36,7 @@ class DataStorage(implicit p: Parameters) extends HuanCunModule { val sourceD_wdata = Input(new DSData) val sinkC_waddr = Flipped(DecoupledIO(new DSAddress)) val sinkC_wdata = Input(new DSData) + val ecc = Output(new EccInfo) }) /* Define some internal parameters */ @@ -133,6 +134,7 @@ class DataStorage(implicit p: Parameters) extends HuanCunModule { val outData = Wire(Vec(nrBanks, UInt((8 * bankBytes).W))) val data_en = Wire(Vec(nrBanks, Bool())) + val errVec = Wire(Vec(nrBanks, Bool())) for (i <- 0 until nrBanks) { val en = reqs.map(_.bankEn(i)).reduce(_ || _) && SReg.sren() @@ -151,11 +153,14 @@ class DataStorage(implicit p: Parameters) extends HuanCunModule { data_en(i) := SReg.pipe(en && !selectedReq.wen) val decode = dataCode.decode(bankedData(i).io.r.resp.data(0)) outData(i) := RegEnable(decode.uncorrected, data_en(i)) - when(data_en(i)) { - assert(!decode.error) - } + errVec(i) := decode.error + // when(data_en(i)) { + // assert(!decode.error) + // } } + io.ecc.errCode := Mux(Cat(errVec).orR(), io.ecc.ERR_DATA, io.ecc.ERR_NO) + /* Pack out-data to channels */ val sourceDlatch = RegNext(SReg.pipe(sourceD_rreq.bankEn)) val sourceClatch = RegNext(SReg.pipe(sourceC_req.bankEn)) diff --git a/src/main/scala/huancun/HuanCun.scala b/src/main/scala/huancun/HuanCun.scala index 10e3235..d51f17d 100644 --- a/src/main/scala/huancun/HuanCun.scala +++ b/src/main/scala/huancun/HuanCun.scala @@ -26,6 +26,7 @@ import freechips.rocketchip.diplomacy._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.util.{BundleField, BundleFieldBase, UIntToOH1} import huancun.prefetch._ +import huancun.utils.NoopNode trait HasHuanCunParameters { val p: Parameters @@ -195,6 +196,10 @@ class HuanCun(implicit p: Parameters) extends LazyModule with HasHuanCunParamete val ctrl_unit = cacheParams.ctrl.map(_ => LazyModule(new CtrlUnit(node))) val ctlnode = ctrl_unit.map(_.ctlnode) + if (ctlnode.nonEmpty) { + val noopNode = LazyModule(new NoopNode()) + ctlnode.get := noopNode.clientNode + } lazy val module = new LazyModuleImp(this) { val sizeBytes = cacheParams.sets * cacheParams.ways * cacheParams.blockBytes @@ -277,11 +282,16 @@ class HuanCun(implicit p: Parameters) extends LazyModule with HasHuanCunParamete val arb = Module(new Arbiter(new CtrlResp, slices.size)) arb.io.in <> VecInit(slices.map(_.io.ctl_resp)) c.module.resp <> arb.io.out + + val ecc_arb = Module(new Arbiter(new EccInfo, slices.size)) + ecc_arb.io.in <> VecInit(slices.map(_.io.ctl_ecc)) + c.module.ecc <> ecc_arb.io.out } - if(ctrl_unit.isEmpty){ + if (ctrl_unit.isEmpty) { slices.foreach(_.io.ctl_req <> DontCare) slices.foreach(_.io.ctl_req.valid := false.B) slices.foreach(_.io.ctl_resp.ready := false.B) + slices.foreach(_.io.ctl_ecc.ready := false.B) } node.edges.in.headOption.foreach { n => n.client.clients.zipWithIndex.foreach { diff --git a/src/main/scala/huancun/Slice.scala b/src/main/scala/huancun/Slice.scala index 24f7aa1..f9ef7bc 100644 --- a/src/main/scala/huancun/Slice.scala +++ b/src/main/scala/huancun/Slice.scala @@ -23,6 +23,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util.leftOR import huancun.noninclusive.{MSHR, ProbeHelper, SliceCtrl} import huancun.prefetch._ @@ -33,18 +34,10 @@ class Slice()(implicit p: Parameters) extends HuanCunModule { val prefetch = prefetchOpt.map(_ => Flipped(new PrefetchIO)) val ctl_req = Flipped(DecoupledIO(new CtrlReq())) val ctl_resp = DecoupledIO(new CtrlResp()) + val ctl_ecc = DecoupledIO(new EccInfo()) }) val ctrl = cacheParams.ctrl.map(_ => Module(new SliceCtrl())) - if(ctrl.nonEmpty){ - ctrl.get.io.req <> io.ctl_req - io.ctl_resp <> ctrl.get.io.resp - } else { - io.ctl_req <> DontCare - io.ctl_resp <> DontCare - io.ctl_req.ready := false.B - io.ctl_resp.valid := false.B - } def ctrl_arb[T <: Data](source: DecoupledIO[T], ctrl: Option[DecoupledIO[T]]): DecoupledIO[T] ={ if(ctrl.nonEmpty){ @@ -558,4 +551,22 @@ class Slice()(implicit p: Parameters) extends HuanCunModule { sinkA.io.a_pb_pop <> sourceA.io.pb_pop sinkA.io.a_pb_beat <> sourceA.io.pb_beat + + if (ctrl.nonEmpty) { + ctrl.get.io.req <> io.ctl_req + io.ctl_resp <> ctrl.get.io.resp + io.ctl_ecc <> DontCare + val eccMask = Cat(ms.map(m => m.io.ecc.errCode =/= 0.U && m.io.status.valid)) + val valid_eccMask = ~(leftOR(eccMask) << 1) & eccMask + val ms_errCode = VecInit(ms.map(_.io.ecc.errCode))(OHToUInt(valid_eccMask)) + io.ctl_ecc.bits.errCode := Mux(dataStorage.io.ecc.errCode =/= 0.U, dataStorage.io.ecc.errCode, ms_errCode) + io.ctl_ecc.valid := Cat(eccMask).orR() + } else { + io.ctl_req <> DontCare + io.ctl_resp <> DontCare + io.ctl_ecc <> DontCare + io.ctl_req.ready := false.B + io.ctl_resp.valid := false.B + io.ctl_ecc.valid := false.B + } } diff --git a/src/main/scala/huancun/noninclusive/MSHR.scala b/src/main/scala/huancun/noninclusive/MSHR.scala index 6d13de5..b8c58f5 100644 --- a/src/main/scala/huancun/noninclusive/MSHR.scala +++ b/src/main/scala/huancun/noninclusive/MSHR.scala @@ -694,12 +694,23 @@ class MSHR()(implicit p: Parameters) extends BaseMSHR[DirResult, SelfDirWrite, S }) } + def handleEcc() = { + // assert(!io.dirResult.bits.self.hit || !io.dirResult.bits.self.error) + // io.dirResult.bits.clients.foreach(r => assert(!r.hit || !r.error)) + when(io.dirResult.bits.self.hit && io.dirResult.bits.self.error) { + io.ecc.errCode := io.ecc.ERR_SELF_DIR + } + when(Cat(io.dirResult.bits.clients.map{r => r.hit && r.error}).orR()) { + io.ecc.errCode := io.ecc.ERR_CLIENT_DIR + } + } + + io.ecc.errCode := io.ecc.ERR_NO + when(io.dirResult.valid) { reset_all_flags() - - assert(!io.dirResult.bits.self.hit || !io.dirResult.bits.self.error) - io.dirResult.bits.clients.foreach(r => assert(!r.hit || !r.error)) + handleEcc() when(req.fromC) { c_schedule() diff --git a/src/main/scala/huancun/noninclusive/SliceCtrl.scala b/src/main/scala/huancun/noninclusive/SliceCtrl.scala index 7b2fd14..288322b 100644 --- a/src/main/scala/huancun/noninclusive/SliceCtrl.scala +++ b/src/main/scala/huancun/noninclusive/SliceCtrl.scala @@ -85,6 +85,8 @@ class SliceCtrl()(implicit p: Parameters) extends HuanCunModule { io.dir_read.bits.idOH := Cat(req_reg.way, "b11".U) io.dir_read.bits.tag := req_reg.tag io.dir_read.bits.set := req_reg.set + io.dir_read.bits.way := req_reg.way + io.dir_read.bits.wayMode := false.B // TODO: it seems incorrect io.dir_read.bits.replacerInfo := DontCare io.dir_read.bits.source := DontCare diff --git a/src/main/scala/huancun/utils/NoopNode.scala b/src/main/scala/huancun/utils/NoopNode.scala new file mode 100644 index 0000000..7c6ddcd --- /dev/null +++ b/src/main/scala/huancun/utils/NoopNode.scala @@ -0,0 +1,21 @@ +package huancun.utils + +import chipsalliance.rocketchip.config.Parameters +import chisel3._ +import chisel3.util._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ + +class NoopNode()(implicit p: Parameters) extends LazyModule { + + val clientParameters = TLMasterPortParameters.v1( + Seq(TLMasterParameters.v1( + name = "dcache", + sourceId = IdRange(0, 1) + )) + ) + + val clientNode = TLClientNode(Seq(clientParameters)) + + lazy val module = new LazyModuleImp(this) +} \ No newline at end of file