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 ErrorWriteReq(implicit p: Parameters) extends MetaReadReq { 68 val error = Bool() 69} 70 71class AsynchronousECCArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule { 72 def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U) 73 74 // enc bits encode both tag and meta, but is saved in meta array 75 val metaAndTagBits = metaAndTagOnReset.getWidth 76 val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits) 77 val encMetaBits = encMetaAndTagBits - tagBits 78 val encBits = encMetaAndTagBits - metaAndTagBits 79 80 val io = IO(new Bundle() { 81 val read = Vec(readPorts, Flipped(ValidIO(new ECCReadReq))) 82 val resp = Output(Vec(readPorts, Vec(nWays, UInt(encBits.W)))) 83 val write = Vec(writePorts, Flipped(ValidIO(new ECCWriteReq))) 84 val cacheOp = Flipped(new L1CacheInnerOpIO) 85 }) 86 87 val ecc_array = Reg(Vec(nSets, Vec(nWays, UInt(encBits.W)))) 88 when (reset.asBool()) { 89 ecc_array := 0.U.asTypeOf(ecc_array.cloneType) 90 } 91 92 io.read.zip(io.resp).foreach { 93 case (read, resp) => 94 resp := RegEnable(ecc_array(read.bits.idx), read.valid) 95 } 96 97 io.write.foreach { 98 case write => 99 write.bits.way_en.asBools.zipWithIndex.foreach { 100 case (wen, i) => 101 when (write.valid && wen) { 102 ecc_array(write.bits.idx)(i) := write.bits.ecc 103 } 104 } 105 } 106 107 // deal with customized cache op 108 val cacheOpShouldResp = WireInit(false.B) 109 when (io.cacheOp.req.valid) { 110 when (isReadTagECC(io.cacheOp.req.bits.opCode)) { 111 cacheOpShouldResp := true.B 112 } 113 when (isWriteTagECC(io.cacheOp.req.bits.opCode)) { 114 ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0)) := 115 io.cacheOp.req.bits.write_tag_ecc 116 cacheOpShouldResp := true.B 117 } 118 } 119 io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) 120 io.cacheOp.resp.bits := DontCare 121 io.cacheOp.resp.bits.read_tag_ecc := Mux( 122 io.cacheOp.resp.valid, 123 RegNext(ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0))), 124 0.U 125 ) 126} 127 128class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule { 129 def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U) 130 131 // enc bits encode both tag and meta, but is saved in meta array 132 val metaAndTagBits = metaAndTagOnReset.getWidth 133 val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits) 134 val encMetaBits = encMetaAndTagBits - tagBits 135 val encBits = encMetaAndTagBits - metaAndTagBits 136 137 val io = IO(new Bundle() { 138 val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq))) 139 val resp = Output(Vec(readPorts, Vec(nWays, UInt(encMetaBits.W)))) 140 val write = Vec(writePorts, Flipped(DecoupledIO(new MetaWriteReq))) 141 // customized cache op port 142 val cacheOp = Flipped(new L1CacheInnerOpIO) 143 }) 144 145 val meta_array = Reg(Vec(nSets, Vec(nWays, new Meta))) 146 val ecc_array = Module(new AsynchronousECCArray(readPorts, writePorts)) 147 when (reset.asBool()) { 148 meta_array := 0.U.asTypeOf(meta_array.cloneType) 149 } 150 151 (io.read.zip(io.resp)).zipWithIndex.foreach { 152 case ((read, resp), i) => 153 read.ready := true.B 154 ecc_array.io.read(i).valid := read.fire() 155 ecc_array.io.read(i).bits := read.bits 156 resp := VecInit(RegEnable(meta_array(read.bits.idx), read.valid).zip( 157 ecc_array.io.resp(i) 158 ).map { case (m, ecc) => Cat(ecc, m.asUInt) }) 159 } 160 161 io.write.zip(ecc_array.io.write).foreach { 162 case (write, ecc_write) => 163 write.ready := true.B 164 val ecc = cacheParams.tagCode.encode(MetaAndTag(write.bits.meta.coh, write.bits.tag).asUInt)(encMetaAndTagBits - 1, metaAndTagBits) 165 ecc_write.valid := write.fire() 166 ecc_write.bits.idx := write.bits.idx 167 ecc_write.bits.way_en := write.bits.way_en 168 ecc_write.bits.ecc := ecc 169 write.bits.way_en.asBools.zipWithIndex.foreach { 170 case (wen, i) => 171 when (write.valid && wen) { 172 meta_array(write.bits.idx)(i) := write.bits.meta 173 } 174 } 175 } 176 177 ecc_array.io.cacheOp <> io.cacheOp 178} 179 180class ErrorArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule { 181 val io = IO(new Bundle() { 182 val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq))) 183 val resp = Output(Vec(readPorts, Vec(nWays, Bool()))) 184 val write = Vec(writePorts, Flipped(DecoupledIO(new ErrorWriteReq))) 185 // customized cache op port 186 // val cacheOp = Flipped(new L1CacheInnerOpIO) 187 }) 188 189 val meta_array = Reg(Vec(nSets, Vec(nWays, Bool()))) 190 when (reset.asBool()) { 191 meta_array := 0.U.asTypeOf(meta_array.cloneType) 192 } 193 194 io.read.zip(io.resp).foreach { 195 case (read, resp) => 196 read.ready := true.B 197 resp := RegEnable(meta_array(read.bits.idx), read.valid) 198 } 199 200 io.write.foreach { 201 case write => 202 write.ready := true.B 203 write.bits.way_en.asBools.zipWithIndex.foreach { 204 case (wen, i) => 205 when (write.valid && wen) { 206 meta_array(write.bits.idx)(i) := write.bits.error 207 } 208 } 209 } 210} 211