diff --git a/src/main/scala/xiangshan/cache/CacheInstruction.scala b/src/main/scala/xiangshan/cache/CacheInstruction.scala index 2d12f4825feb523d27b507e8b84a93f4a191fd05..34481559e9e4beb40e1a56f0fc1bde07f05f904b 100644 --- a/src/main/scala/xiangshan/cache/CacheInstruction.scala +++ b/src/main/scala/xiangshan/cache/CacheInstruction.scala @@ -180,7 +180,7 @@ class CSRCacheOpDecoder(decoder_name: String, id: Int)(implicit p: Parameters) e update_cache_req_when_write("CACHE_BANK_NUM", translated_cache_req.bank_num) update_cache_req_when_write("CACHE_TAG_HIGH", translated_cache_req.write_tag_high) update_cache_req_when_write("CACHE_TAG_LOW", translated_cache_req.write_tag_low) - update_cache_req_when_write("CACHE_DATA_ECC", translated_cache_req.write_tag_ecc) + update_cache_req_when_write("CACHE_TAG_ECC", translated_cache_req.write_tag_ecc) update_cache_req_when_write("CACHE_DATA_0", translated_cache_req.write_data_vec(0)) update_cache_req_when_write("CACHE_DATA_1", translated_cache_req.write_data_vec(1)) update_cache_req_when_write("CACHE_DATA_2", translated_cache_req.write_data_vec(2)) @@ -239,13 +239,13 @@ class CSRCacheOpDecoder(decoder_name: String, id: Int)(implicit p: Parameters) e when(schedule_csr_op_resp_data){ io.csr.update.w.bits.addr := Mux1H(List( isReadTagECC -> (CacheInstrucion.CacheInsRegisterList("CACHE_TAG_ECC")("offset").toInt + Scachebase).U, - isReadDataECC -> (CacheInstrucion.CacheInsRegisterList("CACHE_BANK_NUM")("offset").toInt + Scachebase).U, + isReadDataECC -> (CacheInstrucion.CacheInsRegisterList("CACHE_DATA_ECC")("offset").toInt + Scachebase).U, isReadTag -> ((CacheInstrucion.CacheInsRegisterList("CACHE_TAG_LOW")("offset").toInt + Scachebase).U + data_transfer_cnt), isReadData -> ((CacheInstrucion.CacheInsRegisterList("CACHE_DATA_0")("offset").toInt + Scachebase).U + data_transfer_cnt), )) io.csr.update.w.bits.data := Mux1H(List( isReadTagECC -> raw_cache_resp.read_tag_ecc, - isReadDataECC -> raw_cache_resp.read_tag_ecc, + isReadDataECC -> raw_cache_resp.read_data_ecc, isReadTag -> raw_cache_resp.read_tag_low, isReadData -> raw_cache_resp.read_data_vec(data_transfer_cnt), )) diff --git a/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala b/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala index 0b01f5aebd78a6f7890c965a2c6e0a26a16c4fbd..0e78bf189a2a4aa6ecb3bbc402451b54e01f27a4 100644 --- a/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala +++ b/src/main/scala/xiangshan/cache/dcache/data/BankedDataArray.scala @@ -372,12 +372,10 @@ class BankedDataArray(implicit p: Parameters) extends AbstractBankedDataArray { // deal with customized cache op require(nWays <= 32) io.cacheOp.resp.bits := DontCare - val cacheOpShouldResp = WireInit(false.B) + val cacheOpShouldResp = WireInit(false.B) + val eccReadResult = Wire(Vec(DCacheBanks, UInt(eccBits.W))) when(io.cacheOp.req.valid){ - when( - CacheInstrucion.isReadData(io.cacheOp.req.bits.opCode) || - CacheInstrucion.isReadDataECC(io.cacheOp.req.bits.opCode) - ){ + when (CacheInstrucion.isReadData(io.cacheOp.req.bits.opCode)) { for (bank_index <- 0 until DCacheBanks) { val data_bank = data_banks(bank_index) data_bank.io.r.en := true.B @@ -386,6 +384,14 @@ class BankedDataArray(implicit p: Parameters) extends AbstractBankedDataArray { } cacheOpShouldResp := true.B } + when (CacheInstrucion.isReadDataECC(io.cacheOp.req.bits.opCode)) { + for (bank_index <- 0 until DCacheBanks) { + val ecc_bank = ecc_banks(bank_index) + ecc_bank.io.r.req.valid := true.B + ecc_bank.io.r.req.bits.setIdx := io.cacheOp.req.bits.index + } + cacheOpShouldResp := true.B + } when(CacheInstrucion.isWriteData(io.cacheOp.req.bits.opCode)){ for (bank_index <- 0 until DCacheBanks) { val data_bank = data_banks(bank_index) @@ -412,9 +418,10 @@ class BankedDataArray(implicit p: Parameters) extends AbstractBankedDataArray { io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) for (bank_index <- 0 until DCacheBanks) { io.cacheOp.resp.bits.read_data_vec(bank_index) := bank_result(bank_index).raw_data + eccReadResult(bank_index) := ecc_banks(bank_index).io.r.resp.data(RegNext(io.cacheOp.req.bits.wayNum(4, 0))) } io.cacheOp.resp.bits.read_data_ecc := Mux(io.cacheOp.resp.valid, - bank_result(io.cacheOp.req.bits.bank_num).ecc, + eccReadResult(RegNext(io.cacheOp.req.bits.bank_num)), 0.U ) } diff --git a/src/main/scala/xiangshan/cache/dcache/meta/AsynchronousMetaArray.scala b/src/main/scala/xiangshan/cache/dcache/meta/AsynchronousMetaArray.scala index 1ec1d803633157f20284e2a40226e222114d5a7a..de0c28aea5bea4bbb91a0f59879ba4b1be385673 100644 --- a/src/main/scala/xiangshan/cache/dcache/meta/AsynchronousMetaArray.scala +++ b/src/main/scala/xiangshan/cache/dcache/meta/AsynchronousMetaArray.scala @@ -21,6 +21,7 @@ import chipsalliance.rocketchip.config.Parameters import chisel3._ import chisel3.util._ import xiangshan.L1CacheErrorInfo +import xiangshan.cache.CacheInstrucion._ class Meta(implicit p: Parameters) extends DCacheBundle { val coh = new ClientMetadata @@ -58,6 +59,68 @@ class MetaWriteReq(implicit p: Parameters) extends MetaReadReq { val tag = UInt(tagBits.W) // used to calculate ecc } +class ECCReadReq(implicit p: Parameters) extends MetaReadReq +class ECCWriteReq(implicit p: Parameters) extends ECCReadReq { + val ecc = UInt() +} + +class AsynchronousECCArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule { + def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U) + + // enc bits encode both tag and meta, but is saved in meta array + val metaAndTagBits = metaAndTagOnReset.getWidth + val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits) + val encMetaBits = encMetaAndTagBits - tagBits + val encBits = encMetaAndTagBits - metaAndTagBits + + val io = IO(new Bundle() { + val read = Vec(readPorts, Flipped(ValidIO(new ECCReadReq))) + val resp = Output(Vec(readPorts, Vec(nWays, UInt(encBits.W)))) + val write = Vec(writePorts, Flipped(ValidIO(new ECCWriteReq))) + val cacheOp = Flipped(new DCacheInnerOpIO) + }) + + val ecc_array = Reg(Vec(nSets, Vec(nWays, UInt(encBits.W)))) + when (reset.asBool()) { + ecc_array := 0.U.asTypeOf(ecc_array.cloneType) + } + + io.read.zip(io.resp).foreach { + case (read, resp) => + resp := RegEnable(ecc_array(read.bits.idx), read.valid) + } + + io.write.foreach { + case write => + write.bits.way_en.asBools.zipWithIndex.foreach { + case (wen, i) => + when (write.valid && wen) { + ecc_array(write.bits.idx)(i) := write.bits.ecc + } + } + } + + // deal with customized cache op + val cacheOpShouldResp = WireInit(false.B) + when (io.cacheOp.req.valid) { + when (isReadTagECC(io.cacheOp.req.bits.opCode)) { + cacheOpShouldResp := true.B + } + when (isWriteTagECC(io.cacheOp.req.bits.opCode)) { + ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0)) := + io.cacheOp.req.bits.write_tag_ecc + cacheOpShouldResp := true.B + } + } + io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) + io.cacheOp.resp.bits := DontCare + io.cacheOp.resp.bits.read_tag_ecc := Mux( + io.cacheOp.resp.valid, + RegNext(ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0))), + 0.U + ) +} + class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule { def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U) @@ -65,44 +128,47 @@ class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Paramet val metaAndTagBits = metaAndTagOnReset.getWidth val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits) val encMetaBits = encMetaAndTagBits - tagBits + val encBits = encMetaAndTagBits - metaAndTagBits val io = IO(new Bundle() { - // TODO: this is made of regs, so we don't need to use DecoupledIO val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq))) val resp = Output(Vec(readPorts, Vec(nWays, UInt(encMetaBits.W)))) val write = Vec(writePorts, Flipped(DecoupledIO(new MetaWriteReq))) - // customized cache op port + // customized cache op port val cacheOp = Flipped(new DCacheInnerOpIO) }) -// val meta_array = VecInit(Seq.fill(nSets)( -// VecInit(Seq.fill(nWays)( -// RegInit(0.U(encMetaBits.W)))) -// )) - val meta_array = Reg(Vec(nSets, Vec(nWays, UInt(encMetaBits.W)))) + val meta_array = Reg(Vec(nSets, Vec(nWays, new Meta))) + val ecc_array = Module(new AsynchronousECCArray(readPorts, writePorts)) when (reset.asBool()) { meta_array := 0.U.asTypeOf(meta_array.cloneType) } - io.read.zip(io.resp).foreach { - case (read, resp) => + (io.read.zip(io.resp)).zipWithIndex.foreach { + case ((read, resp), i) => read.ready := true.B - resp := RegEnable(meta_array(read.bits.idx), read.valid) + ecc_array.io.read(i).valid := read.fire() + ecc_array.io.read(i).bits := read.bits + resp := VecInit(RegEnable(meta_array(read.bits.idx), read.valid).zip( + ecc_array.io.resp(i) + ).map { case (m, ecc) => Cat(ecc, m.asUInt) }) } - io.write.foreach { - case write => + + io.write.zip(ecc_array.io.write).foreach { + case (write, ecc_write) => write.ready := true.B val ecc = cacheParams.tagCode.encode(MetaAndTag(write.bits.meta.coh, write.bits.tag).asUInt)(encMetaAndTagBits - 1, metaAndTagBits) - val encMeta = Cat(ecc, write.bits.meta.asUInt) - require(encMeta.getWidth == encMetaBits) + ecc_write.valid := write.fire() + ecc_write.bits.idx := write.bits.idx + ecc_write.bits.way_en := write.bits.way_en + ecc_write.bits.ecc := ecc write.bits.way_en.asBools.zipWithIndex.foreach { case (wen, i) => when (write.valid && wen) { - meta_array(write.bits.idx)(i) := encMeta + meta_array(write.bits.idx)(i) := write.bits.meta } } } - // deal with customized cache op - io.cacheOp.resp := DontCare // TODO -} + ecc_array.io.cacheOp <> io.cacheOp +} \ No newline at end of file diff --git a/src/main/scala/xiangshan/cache/dcache/meta/TagArray.scala b/src/main/scala/xiangshan/cache/dcache/meta/TagArray.scala index 939b1efdff96ba6abb39fb47c80f239d67033940..6f1b89e15664d24e8cca74936c7858131589483a 100644 --- a/src/main/scala/xiangshan/cache/dcache/meta/TagArray.scala +++ b/src/main/scala/xiangshan/cache/dcache/meta/TagArray.scala @@ -39,8 +39,8 @@ class TagArray(implicit p: Parameters) extends DCacheModule { val read = Flipped(DecoupledIO(new TagReadReq)) val resp = Output(Vec(nWays, UInt(tagBits.W))) val write = Flipped(DecoupledIO(new TagWriteReq)) - val ecc_write = Flipped(DecoupledIO(new TagEccWriteReq)) - val ecc_resp = Output(Vec(nWays, UInt(eccTagBits.W))) +// val ecc_write = Flipped(DecoupledIO(new TagEccWriteReq)) +// val ecc_resp = Output(Vec(nWays, UInt(eccTagBits.W))) }) // TODO: reset is unnecessary? val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W)) @@ -57,8 +57,8 @@ class TagArray(implicit p: Parameters) extends DCacheModule { val tag_array = Module(new SRAMTemplate(UInt(tagBits.W), set = nSets, way = nWays, shouldReset = false, holdRead = false, singlePort = true)) - val ecc_array = Module(new SRAMTemplate(UInt(eccTagBits.W), set = nSets, way = nWays, - shouldReset = false, holdRead = false, singlePort = true)) +// val ecc_array = Module(new SRAMTemplate(UInt(eccTagBits.W), set = nSets, way = nWays, +// shouldReset = false, holdRead = false, singlePort = true)) // tag write def getECCFromEncTag(encTag: UInt) = { @@ -73,12 +73,12 @@ class TagArray(implicit p: Parameters) extends DCacheModule { data = wdata, waymask = VecInit(wmask).asUInt() ) - ecc_array.io.w.req.valid := wen - ecc_array.io.w.req.bits.apply( - setIdx = waddr, - data = getECCFromEncTag(cacheParams.tagCode.encode(wdata)), - waymask = VecInit(wmask).asUInt() - ) +// ecc_array.io.w.req.valid := wen +// ecc_array.io.w.req.bits.apply( +// setIdx = waddr, +// data = getECCFromEncTag(cacheParams.tagCode.encode(wdata)), +// waymask = VecInit(wmask).asUInt() +// ) // tag read val ren = io.read.fire() @@ -87,23 +87,23 @@ class TagArray(implicit p: Parameters) extends DCacheModule { tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx) io.resp := tag_array.io.r.resp.data - ecc_array.io.r.req.valid := ren - ecc_array.io.r.req.bits.apply(setIdx = io.read.bits.idx) - io.ecc_resp := ecc_array.io.r.resp.data - - // cache op tag ecc write - val ecc_force_wen = io.ecc_write.valid - ecc_array.io.w.req.valid := ecc_force_wen - when(ecc_force_wen){ - ecc_array.io.w.req.bits.apply( - setIdx = io.ecc_write.bits.idx, - data = io.ecc_write.bits.ecc, - waymask = io.ecc_write.bits.way_en - ) - } +// ecc_array.io.r.req.valid := ren +// ecc_array.io.r.req.bits.apply(setIdx = io.read.bits.idx) +// io.ecc_resp := ecc_array.io.r.resp.data +// +// // cache op tag ecc write +// val ecc_force_wen = io.ecc_write.valid +// ecc_array.io.w.req.valid := ecc_force_wen +// when(ecc_force_wen){ +// ecc_array.io.w.req.bits.apply( +// setIdx = io.ecc_write.bits.idx, +// data = io.ecc_write.bits.ecc, +// waymask = io.ecc_write.bits.way_en +// ) +// } io.write.ready := !rst - io.ecc_write.ready := !rst +// io.ecc_write.ready := !rst io.read.ready := !wen } @@ -125,8 +125,8 @@ class DuplicatedTagArray(readPorts: Int)(implicit p: Parameters) extends DCacheM array(i).io.read <> io.read(i) io.resp(i) <> array(i).io.resp // extra ports for cache op - array(i).io.ecc_write.valid := false.B - array(i).io.ecc_write.bits := DontCare +// array(i).io.ecc_write.valid := false.B +// array(i).io.ecc_write.bits := DontCare } io.write.ready := true.B @@ -136,8 +136,8 @@ class DuplicatedTagArray(readPorts: Int)(implicit p: Parameters) extends DCacheM val cacheOpShouldResp = WireInit(false.B) when(io.cacheOp.req.valid){ when( - CacheInstrucion.isReadTag(io.cacheOp.req.bits.opCode) || - CacheInstrucion.isReadTagECC(io.cacheOp.req.bits.opCode) + CacheInstrucion.isReadTag(io.cacheOp.req.bits.opCode)/* || + CacheInstrucion.isReadTagECC(io.cacheOp.req.bits.opCode)*/ ){ for (i <- 0 until readPorts) { array(i).io.read.valid := true.B @@ -155,18 +155,18 @@ class DuplicatedTagArray(readPorts: Int)(implicit p: Parameters) extends DCacheM } cacheOpShouldResp := true.B } - when(CacheInstrucion.isWriteTagECC(io.cacheOp.req.bits.opCode)){ - for (i <- 0 until readPorts) { - array(i).io.ecc_write.valid := true.B - array(i).io.ecc_write.bits.idx := io.cacheOp.req.bits.index - array(i).io.ecc_write.bits.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) - array(i).io.ecc_write.bits.ecc := io.cacheOp.req.bits.write_tag_ecc - } - cacheOpShouldResp := true.B - } +// when(CacheInstrucion.isWriteTagECC(io.cacheOp.req.bits.opCode)){ +// for (i <- 0 until readPorts) { +// array(i).io.ecc_write.valid := true.B +// array(i).io.ecc_write.bits.idx := io.cacheOp.req.bits.index +// array(i).io.ecc_write.bits.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) +// array(i).io.ecc_write.bits.ecc := io.cacheOp.req.bits.write_tag_ecc +// } +// cacheOpShouldResp := true.B +// } } io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) io.cacheOp.resp.bits.read_tag_low := Mux(io.cacheOp.resp.valid, array(0).io.resp(io.cacheOp.req.bits.wayNum), 0.U) - io.cacheOp.resp.bits.read_tag_ecc := Mux(io.cacheOp.resp.valid, array(0).io.ecc_resp(io.cacheOp.req.bits.wayNum), 0.U) +// io.cacheOp.resp.bits.read_tag_ecc := Mux(io.cacheOp.resp.valid, array(0).io.ecc_resp(io.cacheOp.req.bits.wayNum), 0.U) // TODO: deal with duplicated array }