xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/meta/LegacyMetaArray.scala (revision 94aa21c6009c2f39c5c5dae9c87260c78887efcc)
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, SRAMTemplate, 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    XSDebug(io.read.fire,
101      "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  def dumpWrite = {
106    XSDebug(io.write.fire,
107      "MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n",
108      io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state)
109  }
110
111  // def dumpResp() = {
112  //   (0 until nWays) map { i =>
113  //     XSDebug(s"MetaArray Resp: way: $i tag: %x coh: %x\n",
114  //       io.resp(i).tag, io.resp(i).coh.state)
115  //   }
116  // }
117
118  def dump() = {
119    dumpRead
120    dumpWrite
121    // dumpResp
122  }
123}
124
125class DuplicatedMetaArray(numReadPorts: Int)(implicit p: Parameters) extends DCacheModule {
126  def onReset = L1Metadata(0.U, ClientMetadata.onReset, 0.U)
127
128  val metaBits = onReset.getWidth
129  val encMetaBits = cacheParams.tagCode.width(metaBits)
130
131  val io = IO(new DCacheBundle {
132    val read = Vec(numReadPorts, Flipped(DecoupledIO(new L1MetaReadReq)))
133    val write = Flipped(DecoupledIO(new L1MetaWriteReq))
134    val resp = Output(Vec(numReadPorts, Vec(nWays, UInt(encMetaBits.W))))
135    val errors = Output(Vec(numReadPorts, ValidIO(new L1CacheErrorInfo)))
136  })
137  val meta = Seq.fill(numReadPorts) {
138    Module(new L1MetadataArray(() => onReset))
139  }
140
141  for (w <- 0 until numReadPorts) {
142    // meta(w).io.write <> io.write
143    meta(w).io.write.valid := io.write.valid
144    meta(w).io.write.bits := io.write.bits
145    meta(w).io.read <> io.read(w)
146    io.resp(w) <> meta(w).io.resp
147    io.errors(w) <> meta(w).io.error
148  }
149  // io.write.ready := VecInit(meta.map(_.io.write.ready)).asUInt.andR
150  io.write.ready := true.B
151
152  def dumpRead = {
153    (0 until numReadPorts) map { w =>
154      XSDebug(io.read(w).fire,
155        s"MetaArray Read channel: $w idx: %d way_en: %x tag: %x\n",
156        io.read(w).bits.idx, io.read(w).bits.way_en, io.read(w).bits.tag)
157    }
158  }
159
160  def dumpWrite = {
161    XSDebug(io.write.fire,
162      "MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n",
163      io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state)
164  }
165
166  // def dumpResp() = {
167  //   (0 until LoadPipelineWidth) map { w =>
168  //     (0 until nWays) map { i =>
169  //       XSDebug(s"MetaArray Resp: channel: $w way: $i tag: %x coh: %x\n",
170  //         io.resp(w)(i).tag, io.resp(w)(i).coh.state)
171  //     }
172  //   }
173  // }
174
175  def dump() = {
176    dumpRead
177    dumpWrite
178    // dumpResp
179  }
180}
181