xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/meta/LegacyMetaArray.scala (revision bb2f3f51dd67f6e16e0cc1ffe43368c9fc7e4aef)
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, XSDebug}
24import xiangshan.L1CacheErrorInfo
25
26// basic building blocks for L1 DCache
27class L1Metadata(implicit p: Parameters) extends DCacheBundle {
28  val coh = new ClientMetadata
29  val tag = UInt(tagBits.W)
30}
31
32object L1Metadata {
33  def apply(tag: Bits, coh: ClientMetadata, paddr: UInt)(implicit p: Parameters) = {
34    val meta = Wire(new L1Metadata)
35    meta.tag := tag
36    meta.coh := coh
37    meta
38  }
39}
40
41class L1MetaReadReq(implicit p: Parameters) extends DCacheBundle {
42  val idx = UInt(idxBits.W)
43  val way_en = UInt(nWays.W)
44  val tag = UInt(tagBits.W)
45}
46
47class L1MetaWriteReq(implicit p: Parameters) extends L1MetaReadReq {
48  val data = new L1Metadata
49}
50
51
52class L1MetadataArray(onReset: () => L1Metadata)(implicit p: Parameters) extends DCacheModule {
53  val rstVal = onReset()
54  val metaBits = rstVal.getWidth
55  val encMetaBits = cacheParams.tagCode.width(metaBits)
56
57  val io = IO(new Bundle {
58    val read = Flipped(Decoupled(new L1MetaReadReq))
59    val write = Flipped(Decoupled(new L1MetaWriteReq))
60    val resp = Output(Vec(nWays, UInt(encMetaBits.W)))
61    val error = Output(ValidIO(new L1CacheErrorInfo))
62  })
63  val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W))
64  val rst = rst_cnt < nSets.U
65  val waddr = Mux(rst, rst_cnt, io.write.bits.idx)
66  val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt
67  val wmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.write.bits.way_en.asSInt).asBools
68  val rmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.read.bits.way_en.asSInt).asBools
69  when(rst) {
70    rst_cnt := rst_cnt + 1.U
71  }
72
73  val tag_array = Module(new SRAMTemplate(UInt(encMetaBits.W), set = nSets, way = nWays,
74    shouldReset = false, holdRead = false, singlePort = true))
75
76  // tag write
77  val wen = rst || io.write.valid
78  tag_array.io.w.req.valid := wen
79  tag_array.io.w.req.bits.apply(
80    setIdx = waddr,
81    data = cacheParams.tagCode.encode(wdata),
82    waymask = VecInit(wmask).asUInt)
83
84  // tag read
85  val ren = io.read.fire
86  tag_array.io.r.req.valid := ren
87  tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx)
88  io.resp := tag_array.io.r.resp.data
89  val ecc_errors = tag_array.io.r.resp.data.zipWithIndex.map({ case (d, w) =>
90    cacheParams.tagCode.decode(d).error && RegNext(io.read.bits.way_en(w))
91  })
92  io.error.bits.report_to_beu := RegNext(io.read.fire) && Cat(ecc_errors).orR
93  io.error.bits.paddr := Cat(io.read.bits.idx, 0.U(pgUntagBits.W))
94
95  io.write.ready := !rst
96  io.read.ready := !wen
97
98  def dumpRead() = {
99    when(io.read.fire) {
100      XSDebug("MetaArray Read: idx: %d way_en: %x tag: %x\n",
101        io.read.bits.idx, io.read.bits.way_en, io.read.bits.tag)
102    }
103  }
104
105  def dumpWrite() = {
106    when(io.write.fire) {
107      XSDebug("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
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      when(io.read(w).fire) {
156        XSDebug(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
162  def dumpWrite() = {
163    when(io.write.fire) {
164      XSDebug("MetaArray Write: idx: %d way_en: %x tag: %x new_tag: %x new_coh: %x\n",
165        io.write.bits.idx, io.write.bits.way_en, io.write.bits.tag, io.write.bits.data.tag, io.write.bits.data.coh.state)
166    }
167  }
168
169  // def dumpResp() = {
170  //   (0 until LoadPipelineWidth) map { w =>
171  //     (0 until nWays) map { i =>
172  //       XSDebug(s"MetaArray Resp: channel: $w way: $i tag: %x coh: %x\n",
173  //         io.resp(w)(i).tag, io.resp(w)(i).coh.state)
174  //     }
175  //   }
176  // }
177
178  def dump() = {
179    dumpRead
180    dumpWrite
181    // dumpResp
182  }
183}
184