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 org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut} 23import utility.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate} 24import utils.XSDebug 25import xiangshan.L1CacheErrorInfo 26 27// basic building blocks for L1 DCache 28class L1Metadata(implicit p: Parameters) extends DCacheBundle { 29 val coh = new ClientMetadata 30 val tag = UInt(tagBits.W) 31} 32 33object L1Metadata { 34 def apply(tag: Bits, coh: ClientMetadata, paddr: UInt)(implicit p: Parameters) = { 35 val meta = Wire(new L1Metadata) 36 meta.tag := tag 37 meta.coh := coh 38 meta 39 } 40} 41 42class L1MetaReadReq(implicit p: Parameters) extends DCacheBundle { 43 val idx = UInt(idxBits.W) 44 val way_en = UInt(nWays.W) 45 val tag = UInt(tagBits.W) 46} 47 48class L1MetaWriteReq(implicit p: Parameters) extends L1MetaReadReq { 49 val data = new L1Metadata 50} 51 52 53class L1MetadataArray(onReset: () => L1Metadata)(implicit p: Parameters) extends DCacheModule { 54 val rstVal = onReset() 55 val metaBits = rstVal.getWidth 56 val encMetaBits = cacheParams.tagCode.width(metaBits) 57 58 val io = IO(new Bundle { 59 val read = Flipped(Decoupled(new L1MetaReadReq)) 60 val write = Flipped(Decoupled(new L1MetaWriteReq)) 61 val resp = Output(Vec(nWays, UInt(encMetaBits.W))) 62 val error = Output(ValidIO(new L1CacheErrorInfo)) 63 }) 64 val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W)) 65 val rst = rst_cnt < nSets.U 66 val waddr = Mux(rst, rst_cnt, io.write.bits.idx) 67 val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt 68 val wmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.write.bits.way_en.asSInt).asBools 69 val rmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.read.bits.way_en.asSInt).asBools 70 when(rst) { 71 rst_cnt := rst_cnt + 1.U 72 } 73 74 val tag_array = Module(new SRAMTemplate(UInt(encMetaBits.W), set = nSets, way = nWays, 75 shouldReset = false, holdRead = false, singlePort = true)) 76 77 // tag write 78 val wen = rst || io.write.valid 79 tag_array.io.w.req.valid := wen 80 tag_array.io.w.req.bits.apply( 81 setIdx = waddr, 82 data = cacheParams.tagCode.encode(wdata), 83 waymask = VecInit(wmask).asUInt) 84 85 // tag read 86 val ren = io.read.fire 87 tag_array.io.r.req.valid := ren 88 tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx) 89 io.resp := tag_array.io.r.resp.data 90 val ecc_errors = tag_array.io.r.resp.data.zipWithIndex.map({ case (d, w) => 91 cacheParams.tagCode.decode(d).error && RegNext(io.read.bits.way_en(w)) 92 }) 93 io.error.bits.report_to_beu := RegNext(io.read.fire) && Cat(ecc_errors).orR 94 io.error.bits.paddr := Cat(io.read.bits.idx, 0.U(pgUntagBits.W)) 95 96 io.write.ready := !rst 97 io.read.ready := !wen 98 99 def dumpRead() = { 100 when(io.read.fire) { 101 XSDebug("MetaArray Read: idx: %d way_en: %x tag: %x\n", 102 io.read.bits.idx, io.read.bits.way_en, io.read.bits.tag) 103 } 104 } 105 106 def dumpWrite() = { 107 when(io.write.fire) { 108 XSDebug("MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n", 109 io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state) 110 } 111 } 112 113 // def dumpResp() = { 114 // (0 until nWays) map { i => 115 // XSDebug(s"MetaArray Resp: way: $i tag: %x coh: %x\n", 116 // io.resp(i).tag, io.resp(i).coh.state) 117 // } 118 // } 119 120 def dump() = { 121 dumpRead 122 dumpWrite 123 // dumpResp 124 } 125} 126 127class DuplicatedMetaArray(numReadPorts: Int)(implicit p: Parameters) extends DCacheModule { 128 def onReset = L1Metadata(0.U, ClientMetadata.onReset, 0.U) 129 130 val metaBits = onReset.getWidth 131 val encMetaBits = cacheParams.tagCode.width(metaBits) 132 133 val io = IO(new DCacheBundle { 134 val read = Vec(numReadPorts, Flipped(DecoupledIO(new L1MetaReadReq))) 135 val write = Flipped(DecoupledIO(new L1MetaWriteReq)) 136 val resp = Output(Vec(numReadPorts, Vec(nWays, UInt(encMetaBits.W)))) 137 val errors = Output(Vec(numReadPorts, ValidIO(new L1CacheErrorInfo))) 138 }) 139 val meta = Seq.fill(numReadPorts) { 140 Module(new L1MetadataArray(onReset _)) 141 } 142 143 for (w <- 0 until numReadPorts) { 144 // meta(w).io.write <> io.write 145 meta(w).io.write.valid := io.write.valid 146 meta(w).io.write.bits := io.write.bits 147 meta(w).io.read <> io.read(w) 148 io.resp(w) <> meta(w).io.resp 149 io.errors(w) <> meta(w).io.error 150 } 151 // io.write.ready := VecInit(meta.map(_.io.write.ready)).asUInt.andR 152 io.write.ready := true.B 153 154 def dumpRead() = { 155 (0 until numReadPorts) map { w => 156 when(io.read(w).fire) { 157 XSDebug(s"MetaArray Read channel: $w idx: %d way_en: %x tag: %x\n", 158 io.read(w).bits.idx, io.read(w).bits.way_en, io.read(w).bits.tag) 159 } 160 } 161 } 162 163 def dumpWrite() = { 164 when(io.write.fire) { 165 XSDebug("MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n", 166 io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state) 167 } 168 } 169 170 // def dumpResp() = { 171 // (0 until LoadPipelineWidth) map { w => 172 // (0 until nWays) map { i => 173 // XSDebug(s"MetaArray Resp: channel: $w way: $i tag: %x coh: %x\n", 174 // io.resp(w)(i).tag, io.resp(w)(i).coh.state) 175 // } 176 // } 177 // } 178 179 def dump() = { 180 dumpRead 181 dumpWrite 182 // dumpResp 183 } 184} 185