xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/meta/AsynchronousMetaArray.scala (revision a4e57ea3a91431261d57a58df4810c0d9f0366ef)
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 freechips.rocketchip.tilelink.ClientMetadata
20import chipsalliance.rocketchip.config.Parameters
21import chisel3._
22import chisel3.util._
23import xiangshan.L1CacheErrorInfo
24import xiangshan.cache.CacheInstrucion._
25
26class Meta(implicit p: Parameters) extends DCacheBundle {
27  val coh = new ClientMetadata
28}
29
30object Meta {
31  def apply(meta: UInt)(implicit p: Parameters) = {
32    val m = Wire(new Meta)
33    m.coh := meta.asTypeOf(new ClientMetadata)
34    m
35  }
36}
37
38class MetaAndTag(implicit p: Parameters) extends DCacheBundle {
39  val meta = new Meta
40  val tag = UInt(tagBits.W)
41}
42
43object MetaAndTag {
44  def apply(coh: ClientMetadata, tag: UInt)(implicit p: Parameters) = {
45    val x = Wire(new MetaAndTag)
46    x.meta.coh := coh
47    x.tag := tag
48    x
49  }
50}
51
52class MetaReadReq(implicit p: Parameters) extends DCacheBundle {
53  val idx = UInt(idxBits.W)
54  val way_en = UInt(nWays.W)
55}
56
57class MetaWriteReq(implicit p: Parameters) extends MetaReadReq {
58  val meta = new Meta
59  val tag = UInt(tagBits.W) // used to calculate ecc
60}
61
62class ECCReadReq(implicit p: Parameters) extends MetaReadReq
63class ECCWriteReq(implicit p: Parameters) extends ECCReadReq {
64  val ecc = UInt()
65}
66
67class ErrorWriteReq(implicit p: Parameters) extends MetaReadReq {
68  val error = Bool()
69}
70
71class AsynchronousECCArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
72  def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U)
73
74  // enc bits encode both tag and meta, but is saved in meta array
75  val metaAndTagBits = metaAndTagOnReset.getWidth
76  val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits)
77  val encMetaBits = encMetaAndTagBits - tagBits
78  val encBits = encMetaAndTagBits - metaAndTagBits
79
80  val io = IO(new Bundle() {
81    val read = Vec(readPorts, Flipped(ValidIO(new ECCReadReq)))
82    val resp = Output(Vec(readPorts, Vec(nWays, UInt(encBits.W))))
83    val write = Vec(writePorts, Flipped(ValidIO(new ECCWriteReq)))
84    val cacheOp = Flipped(new L1CacheInnerOpIO)
85  })
86
87  val ecc_array = Reg(Vec(nSets, Vec(nWays, UInt(encBits.W))))
88  when (reset.asBool()) {
89    ecc_array := 0.U.asTypeOf(ecc_array.cloneType)
90  }
91
92  io.read.zip(io.resp).foreach {
93    case (read, resp) =>
94      resp := RegEnable(ecc_array(read.bits.idx), read.valid)
95  }
96
97  io.write.foreach {
98    case write =>
99      write.bits.way_en.asBools.zipWithIndex.foreach {
100        case (wen, i) =>
101          when (write.valid && wen) {
102            ecc_array(write.bits.idx)(i) := write.bits.ecc
103          }
104      }
105  }
106
107  // deal with customized cache op
108  val cacheOpShouldResp = WireInit(false.B)
109  when (io.cacheOp.req.valid) {
110    when (isReadTagECC(io.cacheOp.req.bits.opCode)) {
111      cacheOpShouldResp := true.B
112    }
113    when (isWriteTagECC(io.cacheOp.req.bits.opCode)) {
114      ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0)) :=
115        io.cacheOp.req.bits.write_tag_ecc
116      cacheOpShouldResp := true.B
117    }
118  }
119  io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp)
120  io.cacheOp.resp.bits := DontCare
121  io.cacheOp.resp.bits.read_tag_ecc := Mux(
122    io.cacheOp.resp.valid,
123    RegNext(ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0))),
124    0.U
125  )
126}
127
128class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
129  def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U)
130
131  // enc bits encode both tag and meta, but is saved in meta array
132  val metaAndTagBits = metaAndTagOnReset.getWidth
133  val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits)
134  val encMetaBits = encMetaAndTagBits - tagBits
135  val encBits = encMetaAndTagBits - metaAndTagBits
136
137  val io = IO(new Bundle() {
138    val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq)))
139    val resp = Output(Vec(readPorts, Vec(nWays, UInt(encMetaBits.W))))
140    val write = Vec(writePorts, Flipped(DecoupledIO(new MetaWriteReq)))
141    // customized cache op port
142    val cacheOp = Flipped(new L1CacheInnerOpIO)
143  })
144
145  val meta_array = Reg(Vec(nSets, Vec(nWays, new Meta)))
146  val ecc_array = Module(new AsynchronousECCArray(readPorts, writePorts))
147  when (reset.asBool()) {
148    meta_array := 0.U.asTypeOf(meta_array.cloneType)
149  }
150
151  (io.read.zip(io.resp)).zipWithIndex.foreach {
152    case ((read, resp), i) =>
153      read.ready := true.B
154      ecc_array.io.read(i).valid := read.fire()
155      ecc_array.io.read(i).bits := read.bits
156      resp := VecInit(RegEnable(meta_array(read.bits.idx), read.valid).zip(
157        ecc_array.io.resp(i)
158      ).map { case (m, ecc) => Cat(ecc, m.asUInt) })
159  }
160
161  io.write.zip(ecc_array.io.write).foreach {
162    case (write, ecc_write) =>
163      write.ready := true.B
164      val ecc = cacheParams.tagCode.encode(MetaAndTag(write.bits.meta.coh, write.bits.tag).asUInt)(encMetaAndTagBits - 1, metaAndTagBits)
165      ecc_write.valid := write.fire()
166      ecc_write.bits.idx := write.bits.idx
167      ecc_write.bits.way_en := write.bits.way_en
168      ecc_write.bits.ecc := ecc
169      write.bits.way_en.asBools.zipWithIndex.foreach {
170        case (wen, i) =>
171          when (write.valid && wen) {
172            meta_array(write.bits.idx)(i) := write.bits.meta
173          }
174      }
175  }
176
177  ecc_array.io.cacheOp <> io.cacheOp
178}
179
180class ErrorArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
181  val io = IO(new Bundle() {
182    val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq)))
183    val resp = Output(Vec(readPorts, Vec(nWays, Bool())))
184    val write = Vec(writePorts, Flipped(DecoupledIO(new ErrorWriteReq)))
185    // customized cache op port
186    // val cacheOp = Flipped(new L1CacheInnerOpIO)
187  })
188
189  val meta_array = Reg(Vec(nSets, Vec(nWays, Bool())))
190  when (reset.asBool()) {
191    meta_array := 0.U.asTypeOf(meta_array.cloneType)
192  }
193
194  io.read.zip(io.resp).foreach {
195    case (read, resp) =>
196      read.ready := true.B
197      resp := RegEnable(meta_array(read.bits.idx), read.valid)
198  }
199
200  io.write.foreach {
201    case write =>
202      write.ready := true.B
203      write.bits.way_en.asBools.zipWithIndex.foreach {
204        case (wen, i) =>
205          when (write.valid && wen) {
206            meta_array(write.bits.idx)(i) := write.bits.error
207          }
208      }
209  }
210}
211