1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.cache 18 19import freechips.rocketchip.tilelink.ClientMetadata 20import chipsalliance.rocketchip.config.Parameters 21import chisel3._ 22import chisel3.util._ 23import xiangshan.L1CacheErrorInfo 24import xiangshan.cache.CacheInstrucion._ 25 26class Meta(implicit p: Parameters) extends DCacheBundle { 27 val coh = new ClientMetadata 28} 29 30object Meta { 31 def apply(meta: UInt)(implicit p: Parameters) = { 32 val m = Wire(new Meta) 33 m.coh := meta.asTypeOf(new ClientMetadata) 34 m 35 } 36} 37 38class MetaAndTag(implicit p: Parameters) extends DCacheBundle { 39 val meta = new Meta 40 val tag = UInt(tagBits.W) 41} 42 43object MetaAndTag { 44 def apply(coh: ClientMetadata, tag: UInt)(implicit p: Parameters) = { 45 val x = Wire(new MetaAndTag) 46 x.meta.coh := coh 47 x.tag := tag 48 x 49 } 50} 51 52class MetaReadReq(implicit p: Parameters) extends DCacheBundle { 53 val idx = UInt(idxBits.W) 54 val way_en = UInt(nWays.W) 55} 56 57class MetaWriteReq(implicit p: Parameters) extends MetaReadReq { 58 val meta = new Meta 59 val tag = UInt(tagBits.W) // used to calculate ecc 60} 61 62class ECCReadReq(implicit p: Parameters) extends MetaReadReq 63class ECCWriteReq(implicit p: Parameters) extends ECCReadReq { 64 val ecc = UInt() 65} 66 67class AsynchronousECCArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule { 68 def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U) 69 70 // enc bits encode both tag and meta, but is saved in meta array 71 val metaAndTagBits = metaAndTagOnReset.getWidth 72 val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits) 73 val encMetaBits = encMetaAndTagBits - tagBits 74 val encBits = encMetaAndTagBits - metaAndTagBits 75 76 val io = IO(new Bundle() { 77 val read = Vec(readPorts, Flipped(ValidIO(new ECCReadReq))) 78 val resp = Output(Vec(readPorts, Vec(nWays, UInt(encBits.W)))) 79 val write = Vec(writePorts, Flipped(ValidIO(new ECCWriteReq))) 80 val cacheOp = Flipped(new DCacheInnerOpIO) 81 }) 82 83 val ecc_array = Reg(Vec(nSets, Vec(nWays, UInt(encBits.W)))) 84 when (reset.asBool()) { 85 ecc_array := 0.U.asTypeOf(ecc_array.cloneType) 86 } 87 88 io.read.zip(io.resp).foreach { 89 case (read, resp) => 90 resp := RegEnable(ecc_array(read.bits.idx), read.valid) 91 } 92 93 io.write.foreach { 94 case write => 95 write.bits.way_en.asBools.zipWithIndex.foreach { 96 case (wen, i) => 97 when (write.valid && wen) { 98 ecc_array(write.bits.idx)(i) := write.bits.ecc 99 } 100 } 101 } 102 103 // deal with customized cache op 104 val cacheOpShouldResp = WireInit(false.B) 105 when (io.cacheOp.req.valid) { 106 when (isReadTagECC(io.cacheOp.req.bits.opCode)) { 107 cacheOpShouldResp := true.B 108 } 109 when (isWriteTagECC(io.cacheOp.req.bits.opCode)) { 110 ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0)) := 111 io.cacheOp.req.bits.write_tag_ecc 112 cacheOpShouldResp := true.B 113 } 114 } 115 io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) 116 io.cacheOp.resp.bits := DontCare 117 io.cacheOp.resp.bits.read_tag_ecc := Mux( 118 io.cacheOp.resp.valid, 119 RegNext(ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0))), 120 0.U 121 ) 122} 123 124class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule { 125 def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U) 126 127 // enc bits encode both tag and meta, but is saved in meta array 128 val metaAndTagBits = metaAndTagOnReset.getWidth 129 val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits) 130 val encMetaBits = encMetaAndTagBits - tagBits 131 val encBits = encMetaAndTagBits - metaAndTagBits 132 133 val io = IO(new Bundle() { 134 val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq))) 135 val resp = Output(Vec(readPorts, Vec(nWays, UInt(encMetaBits.W)))) 136 val write = Vec(writePorts, Flipped(DecoupledIO(new MetaWriteReq))) 137 // customized cache op port 138 val cacheOp = Flipped(new DCacheInnerOpIO) 139 }) 140 141 val meta_array = Reg(Vec(nSets, Vec(nWays, new Meta))) 142 val ecc_array = Module(new AsynchronousECCArray(readPorts, writePorts)) 143 when (reset.asBool()) { 144 meta_array := 0.U.asTypeOf(meta_array.cloneType) 145 } 146 147 (io.read.zip(io.resp)).zipWithIndex.foreach { 148 case ((read, resp), i) => 149 read.ready := true.B 150 ecc_array.io.read(i).valid := read.fire() 151 ecc_array.io.read(i).bits := read.bits 152 resp := VecInit(RegEnable(meta_array(read.bits.idx), read.valid).zip( 153 ecc_array.io.resp(i) 154 ).map { case (m, ecc) => Cat(ecc, m.asUInt) }) 155 } 156 157 io.write.zip(ecc_array.io.write).foreach { 158 case (write, ecc_write) => 159 write.ready := true.B 160 val ecc = cacheParams.tagCode.encode(MetaAndTag(write.bits.meta.coh, write.bits.tag).asUInt)(encMetaAndTagBits - 1, metaAndTagBits) 161 ecc_write.valid := write.fire() 162 ecc_write.bits.idx := write.bits.idx 163 ecc_write.bits.way_en := write.bits.way_en 164 ecc_write.bits.ecc := ecc 165 write.bits.way_en.asBools.zipWithIndex.foreach { 166 case (wen, i) => 167 when (write.valid && wen) { 168 meta_array(write.bits.idx)(i) := write.bits.meta 169 } 170 } 171 } 172 173 ecc_array.io.cacheOp <> io.cacheOp 174}