13af6aa6eSWilliam Wang/*************************************************************************************** 2e3da8badSTang Haojin* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3e3da8badSTang Haojin* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 43af6aa6eSWilliam Wang* Copyright (c) 2020-2021 Peng Cheng Laboratory 53af6aa6eSWilliam Wang* 63af6aa6eSWilliam Wang* XiangShan is licensed under Mulan PSL v2. 73af6aa6eSWilliam Wang* You can use this software according to the terms and conditions of the Mulan PSL v2. 83af6aa6eSWilliam Wang* You may obtain a copy of Mulan PSL v2 at: 93af6aa6eSWilliam Wang* http://license.coscl.org.cn/MulanPSL2 103af6aa6eSWilliam Wang* 113af6aa6eSWilliam Wang* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 123af6aa6eSWilliam Wang* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 133af6aa6eSWilliam Wang* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 143af6aa6eSWilliam Wang* 153af6aa6eSWilliam Wang* See the Mulan PSL v2 for more details. 163af6aa6eSWilliam Wang***************************************************************************************/ 173af6aa6eSWilliam Wang 183af6aa6eSWilliam Wangpackage xiangshan.cache 193af6aa6eSWilliam Wang 208891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 213af6aa6eSWilliam Wangimport chisel3._ 223af6aa6eSWilliam Wangimport chisel3.util._ 233af6aa6eSWilliam Wangimport freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut} 24*11269ca7STang Haojinimport utility.{Code, ParallelOR, ReplacementPolicy, XSDebug} 25*11269ca7STang Haojinimport utility.sram.SRAMTemplate 263af6aa6eSWilliam Wangimport xiangshan.L1CacheErrorInfo 273af6aa6eSWilliam Wang 283af6aa6eSWilliam Wang// basic building blocks for L1 DCache 293af6aa6eSWilliam Wangclass L1Metadata(implicit p: Parameters) extends DCacheBundle { 303af6aa6eSWilliam Wang val coh = new ClientMetadata 313af6aa6eSWilliam Wang val tag = UInt(tagBits.W) 323af6aa6eSWilliam Wang} 333af6aa6eSWilliam Wang 343af6aa6eSWilliam Wangobject L1Metadata { 353af6aa6eSWilliam Wang def apply(tag: Bits, coh: ClientMetadata, paddr: UInt)(implicit p: Parameters) = { 363af6aa6eSWilliam Wang val meta = Wire(new L1Metadata) 373af6aa6eSWilliam Wang meta.tag := tag 383af6aa6eSWilliam Wang meta.coh := coh 393af6aa6eSWilliam Wang meta 403af6aa6eSWilliam Wang } 413af6aa6eSWilliam Wang} 423af6aa6eSWilliam Wang 433af6aa6eSWilliam Wangclass L1MetaReadReq(implicit p: Parameters) extends DCacheBundle { 443af6aa6eSWilliam Wang val idx = UInt(idxBits.W) 453af6aa6eSWilliam Wang val way_en = UInt(nWays.W) 463af6aa6eSWilliam Wang val tag = UInt(tagBits.W) 473af6aa6eSWilliam Wang} 483af6aa6eSWilliam Wang 493af6aa6eSWilliam Wangclass L1MetaWriteReq(implicit p: Parameters) extends L1MetaReadReq { 503af6aa6eSWilliam Wang val data = new L1Metadata 513af6aa6eSWilliam Wang} 523af6aa6eSWilliam Wang 533af6aa6eSWilliam Wang 543af6aa6eSWilliam Wangclass L1MetadataArray(onReset: () => L1Metadata)(implicit p: Parameters) extends DCacheModule { 553af6aa6eSWilliam Wang val rstVal = onReset() 563af6aa6eSWilliam Wang val metaBits = rstVal.getWidth 573af6aa6eSWilliam Wang val encMetaBits = cacheParams.tagCode.width(metaBits) 583af6aa6eSWilliam Wang 593af6aa6eSWilliam Wang val io = IO(new Bundle { 603af6aa6eSWilliam Wang val read = Flipped(Decoupled(new L1MetaReadReq)) 613af6aa6eSWilliam Wang val write = Flipped(Decoupled(new L1MetaWriteReq)) 623af6aa6eSWilliam Wang val resp = Output(Vec(nWays, UInt(encMetaBits.W))) 630184a80eSYanqin Li val error = Output(ValidIO(new L1CacheErrorInfo)) 643af6aa6eSWilliam Wang }) 653af6aa6eSWilliam Wang val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W)) 663af6aa6eSWilliam Wang val rst = rst_cnt < nSets.U 673af6aa6eSWilliam Wang val waddr = Mux(rst, rst_cnt, io.write.bits.idx) 683af6aa6eSWilliam Wang val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt 693af6aa6eSWilliam Wang val wmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.write.bits.way_en.asSInt).asBools 703af6aa6eSWilliam Wang val rmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.read.bits.way_en.asSInt).asBools 713af6aa6eSWilliam Wang when(rst) { 723af6aa6eSWilliam Wang rst_cnt := rst_cnt + 1.U 733af6aa6eSWilliam Wang } 743af6aa6eSWilliam Wang 753af6aa6eSWilliam Wang val tag_array = Module(new SRAMTemplate(UInt(encMetaBits.W), set = nSets, way = nWays, 763af6aa6eSWilliam Wang shouldReset = false, holdRead = false, singlePort = true)) 773af6aa6eSWilliam Wang 783af6aa6eSWilliam Wang // tag write 793af6aa6eSWilliam Wang val wen = rst || io.write.valid 803af6aa6eSWilliam Wang tag_array.io.w.req.valid := wen 813af6aa6eSWilliam Wang tag_array.io.w.req.bits.apply( 823af6aa6eSWilliam Wang setIdx = waddr, 833af6aa6eSWilliam Wang data = cacheParams.tagCode.encode(wdata), 843af6aa6eSWilliam Wang waymask = VecInit(wmask).asUInt) 853af6aa6eSWilliam Wang 863af6aa6eSWilliam Wang // tag read 87935edac4STang Haojin val ren = io.read.fire 883af6aa6eSWilliam Wang tag_array.io.r.req.valid := ren 893af6aa6eSWilliam Wang tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx) 903af6aa6eSWilliam Wang io.resp := tag_array.io.r.resp.data 913af6aa6eSWilliam Wang val ecc_errors = tag_array.io.r.resp.data.zipWithIndex.map({ case (d, w) => 923af6aa6eSWilliam Wang cacheParams.tagCode.decode(d).error && RegNext(io.read.bits.way_en(w)) 933af6aa6eSWilliam Wang }) 940184a80eSYanqin Li io.error.bits.report_to_beu := RegNext(io.read.fire) && Cat(ecc_errors).orR 950184a80eSYanqin Li io.error.bits.paddr := Cat(io.read.bits.idx, 0.U(pgUntagBits.W)) 963af6aa6eSWilliam Wang 973af6aa6eSWilliam Wang io.write.ready := !rst 983af6aa6eSWilliam Wang io.read.ready := !wen 993af6aa6eSWilliam Wang 100e3da8badSTang Haojin def dumpRead = { 1018b33cd30Sklin02 XSDebug(io.read.fire, 1028b33cd30Sklin02 "MetaArray Read: idx: %d way_en: %x tag: %x\n", 1033af6aa6eSWilliam Wang io.read.bits.idx, io.read.bits.way_en, io.read.bits.tag) 1043af6aa6eSWilliam Wang } 1053af6aa6eSWilliam Wang 106e3da8badSTang Haojin def dumpWrite = { 1078b33cd30Sklin02 XSDebug(io.write.fire, 1088b33cd30Sklin02 "MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n", 1093af6aa6eSWilliam Wang io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state) 1103af6aa6eSWilliam Wang } 1113af6aa6eSWilliam Wang 1123af6aa6eSWilliam Wang // def dumpResp() = { 1133af6aa6eSWilliam Wang // (0 until nWays) map { i => 1143af6aa6eSWilliam Wang // XSDebug(s"MetaArray Resp: way: $i tag: %x coh: %x\n", 1153af6aa6eSWilliam Wang // io.resp(i).tag, io.resp(i).coh.state) 1163af6aa6eSWilliam Wang // } 1173af6aa6eSWilliam Wang // } 1183af6aa6eSWilliam Wang 1193af6aa6eSWilliam Wang def dump() = { 1203af6aa6eSWilliam Wang dumpRead 1213af6aa6eSWilliam Wang dumpWrite 1223af6aa6eSWilliam Wang // dumpResp 1233af6aa6eSWilliam Wang } 1243af6aa6eSWilliam Wang} 1253af6aa6eSWilliam Wang 1263af6aa6eSWilliam Wangclass DuplicatedMetaArray(numReadPorts: Int)(implicit p: Parameters) extends DCacheModule { 1273af6aa6eSWilliam Wang def onReset = L1Metadata(0.U, ClientMetadata.onReset, 0.U) 1283af6aa6eSWilliam Wang 1293af6aa6eSWilliam Wang val metaBits = onReset.getWidth 1303af6aa6eSWilliam Wang val encMetaBits = cacheParams.tagCode.width(metaBits) 1313af6aa6eSWilliam Wang 1323af6aa6eSWilliam Wang val io = IO(new DCacheBundle { 1333af6aa6eSWilliam Wang val read = Vec(numReadPorts, Flipped(DecoupledIO(new L1MetaReadReq))) 1343af6aa6eSWilliam Wang val write = Flipped(DecoupledIO(new L1MetaWriteReq)) 1353af6aa6eSWilliam Wang val resp = Output(Vec(numReadPorts, Vec(nWays, UInt(encMetaBits.W)))) 1360184a80eSYanqin Li val errors = Output(Vec(numReadPorts, ValidIO(new L1CacheErrorInfo))) 1373af6aa6eSWilliam Wang }) 1383af6aa6eSWilliam Wang val meta = Seq.fill(numReadPorts) { 139e3da8badSTang Haojin Module(new L1MetadataArray(() => onReset)) 1403af6aa6eSWilliam Wang } 1413af6aa6eSWilliam Wang 1423af6aa6eSWilliam Wang for (w <- 0 until numReadPorts) { 1433af6aa6eSWilliam Wang // meta(w).io.write <> io.write 1443af6aa6eSWilliam Wang meta(w).io.write.valid := io.write.valid 1453af6aa6eSWilliam Wang meta(w).io.write.bits := io.write.bits 1463af6aa6eSWilliam Wang meta(w).io.read <> io.read(w) 1473af6aa6eSWilliam Wang io.resp(w) <> meta(w).io.resp 1483af6aa6eSWilliam Wang io.errors(w) <> meta(w).io.error 1493af6aa6eSWilliam Wang } 1503af6aa6eSWilliam Wang // io.write.ready := VecInit(meta.map(_.io.write.ready)).asUInt.andR 1513af6aa6eSWilliam Wang io.write.ready := true.B 1523af6aa6eSWilliam Wang 153e3da8badSTang Haojin def dumpRead = { 1543af6aa6eSWilliam Wang (0 until numReadPorts) map { w => 1558b33cd30Sklin02 XSDebug(io.read(w).fire, 1568b33cd30Sklin02 s"MetaArray Read channel: $w idx: %d way_en: %x tag: %x\n", 1573af6aa6eSWilliam Wang io.read(w).bits.idx, io.read(w).bits.way_en, io.read(w).bits.tag) 1583af6aa6eSWilliam Wang } 1593af6aa6eSWilliam Wang } 1603af6aa6eSWilliam Wang 161e3da8badSTang Haojin def dumpWrite = { 1628b33cd30Sklin02 XSDebug(io.write.fire, 1638b33cd30Sklin02 "MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n", 1643af6aa6eSWilliam Wang io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state) 1653af6aa6eSWilliam Wang } 1663af6aa6eSWilliam Wang 1673af6aa6eSWilliam Wang // def dumpResp() = { 1683af6aa6eSWilliam Wang // (0 until LoadPipelineWidth) map { w => 1693af6aa6eSWilliam Wang // (0 until nWays) map { i => 1703af6aa6eSWilliam Wang // XSDebug(s"MetaArray Resp: channel: $w way: $i tag: %x coh: %x\n", 1713af6aa6eSWilliam Wang // io.resp(w)(i).tag, io.resp(w)(i).coh.state) 1723af6aa6eSWilliam Wang // } 1733af6aa6eSWilliam Wang // } 1743af6aa6eSWilliam Wang // } 1753af6aa6eSWilliam Wang 1763af6aa6eSWilliam Wang def dump() = { 1773af6aa6eSWilliam Wang dumpRead 1783af6aa6eSWilliam Wang dumpWrite 1793af6aa6eSWilliam Wang // dumpResp 1803af6aa6eSWilliam Wang } 1813af6aa6eSWilliam Wang} 182