1/*************************************************************************************** 2* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 4* Copyright (c) 2020-2021 Peng Cheng Laboratory 5* 6* XiangShan is licensed under Mulan PSL v2. 7* You can use this software according to the terms and conditions of the Mulan PSL v2. 8* You may obtain a copy of Mulan PSL v2 at: 9* http://license.coscl.org.cn/MulanPSL2 10* 11* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 12* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14* 15* See the Mulan PSL v2 for more details. 16***************************************************************************************/ 17 18package xiangshan.cache 19 20import org.chipsalliance.cde.config.Parameters 21import chisel3._ 22import chisel3.util._ 23import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut} 24import utility.{Code, ParallelOR, ReplacementPolicy, XSDebug} 25import utility.sram.SRAMTemplate 26import xiangshan.L1CacheErrorInfo 27 28// basic building blocks for L1 DCache 29class L1Metadata(implicit p: Parameters) extends DCacheBundle { 30 val coh = new ClientMetadata 31 val tag = UInt(tagBits.W) 32} 33 34object L1Metadata { 35 def apply(tag: Bits, coh: ClientMetadata, paddr: UInt)(implicit p: Parameters) = { 36 val meta = Wire(new L1Metadata) 37 meta.tag := tag 38 meta.coh := coh 39 meta 40 } 41} 42 43class L1MetaReadReq(implicit p: Parameters) extends DCacheBundle { 44 val idx = UInt(idxBits.W) 45 val way_en = UInt(nWays.W) 46 val tag = UInt(tagBits.W) 47} 48 49class L1MetaWriteReq(implicit p: Parameters) extends L1MetaReadReq { 50 val data = new L1Metadata 51} 52 53 54class L1MetadataArray(onReset: () => L1Metadata)(implicit p: Parameters) extends DCacheModule { 55 val rstVal = onReset() 56 val metaBits = rstVal.getWidth 57 val encMetaBits = cacheParams.tagCode.width(metaBits) 58 59 val io = IO(new Bundle { 60 val read = Flipped(Decoupled(new L1MetaReadReq)) 61 val write = Flipped(Decoupled(new L1MetaWriteReq)) 62 val resp = Output(Vec(nWays, UInt(encMetaBits.W))) 63 val error = Output(ValidIO(new L1CacheErrorInfo)) 64 }) 65 val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W)) 66 val rst = rst_cnt < nSets.U 67 val waddr = Mux(rst, rst_cnt, io.write.bits.idx) 68 val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt 69 val wmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.write.bits.way_en.asSInt).asBools 70 val rmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.read.bits.way_en.asSInt).asBools 71 when(rst) { 72 rst_cnt := rst_cnt + 1.U 73 } 74 75 val tag_array = Module(new SRAMTemplate(UInt(encMetaBits.W), set = nSets, way = nWays, 76 shouldReset = false, holdRead = false, singlePort = true)) 77 78 // tag write 79 val wen = rst || io.write.valid 80 tag_array.io.w.req.valid := wen 81 tag_array.io.w.req.bits.apply( 82 setIdx = waddr, 83 data = cacheParams.tagCode.encode(wdata), 84 waymask = VecInit(wmask).asUInt) 85 86 // tag read 87 val ren = io.read.fire 88 tag_array.io.r.req.valid := ren 89 tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx) 90 io.resp := tag_array.io.r.resp.data 91 val ecc_errors = tag_array.io.r.resp.data.zipWithIndex.map({ case (d, w) => 92 cacheParams.tagCode.decode(d).error && RegNext(io.read.bits.way_en(w)) 93 }) 94 io.error.bits.report_to_beu := RegNext(io.read.fire) && Cat(ecc_errors).orR 95 io.error.bits.paddr := Cat(io.read.bits.idx, 0.U(pgUntagBits.W)) 96 97 io.write.ready := !rst 98 io.read.ready := !wen 99 100 def dumpRead = { 101 XSDebug(io.read.fire, 102 "MetaArray Read: idx: %d way_en: %x tag: %x\n", 103 io.read.bits.idx, io.read.bits.way_en, io.read.bits.tag) 104 } 105 106 def dumpWrite = { 107 XSDebug(io.write.fire, 108 "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 // def dumpResp() = { 113 // (0 until nWays) map { i => 114 // XSDebug(s"MetaArray Resp: way: $i tag: %x coh: %x\n", 115 // io.resp(i).tag, io.resp(i).coh.state) 116 // } 117 // } 118 119 def dump() = { 120 dumpRead 121 dumpWrite 122 // dumpResp 123 } 124} 125 126class DuplicatedMetaArray(numReadPorts: Int)(implicit p: Parameters) extends DCacheModule { 127 def onReset = L1Metadata(0.U, ClientMetadata.onReset, 0.U) 128 129 val metaBits = onReset.getWidth 130 val encMetaBits = cacheParams.tagCode.width(metaBits) 131 132 val io = IO(new DCacheBundle { 133 val read = Vec(numReadPorts, Flipped(DecoupledIO(new L1MetaReadReq))) 134 val write = Flipped(DecoupledIO(new L1MetaWriteReq)) 135 val resp = Output(Vec(numReadPorts, Vec(nWays, UInt(encMetaBits.W)))) 136 val errors = Output(Vec(numReadPorts, ValidIO(new L1CacheErrorInfo))) 137 }) 138 val meta = Seq.fill(numReadPorts) { 139 Module(new L1MetadataArray(() => onReset)) 140 } 141 142 for (w <- 0 until numReadPorts) { 143 // meta(w).io.write <> io.write 144 meta(w).io.write.valid := io.write.valid 145 meta(w).io.write.bits := io.write.bits 146 meta(w).io.read <> io.read(w) 147 io.resp(w) <> meta(w).io.resp 148 io.errors(w) <> meta(w).io.error 149 } 150 // io.write.ready := VecInit(meta.map(_.io.write.ready)).asUInt.andR 151 io.write.ready := true.B 152 153 def dumpRead = { 154 (0 until numReadPorts) map { w => 155 XSDebug(io.read(w).fire, 156 s"MetaArray Read channel: $w idx: %d way_en: %x tag: %x\n", 157 io.read(w).bits.idx, io.read(w).bits.way_en, io.read(w).bits.tag) 158 } 159 } 160 161 def dumpWrite = { 162 XSDebug(io.write.fire, 163 "MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n", 164 io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state) 165 } 166 167 // def dumpResp() = { 168 // (0 until LoadPipelineWidth) map { w => 169 // (0 until nWays) map { i => 170 // XSDebug(s"MetaArray Resp: channel: $w way: $i tag: %x coh: %x\n", 171 // io.resp(w)(i).tag, io.resp(w)(i).coh.state) 172 // } 173 // } 174 // } 175 176 def dump() = { 177 dumpRead 178 dumpWrite 179 // dumpResp 180 } 181} 182