xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/meta/AsynchronousMetaArray.scala (revision 89c0fb0a81a0456c88c9eca2d22f0570d2b70cf3)
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 AsynchronousECCArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
68  def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U)
69
70  // enc bits encode both tag and meta, but is saved in meta array
71  val metaAndTagBits = metaAndTagOnReset.getWidth
72  val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits)
73  val encMetaBits = encMetaAndTagBits - tagBits
74  val encBits = encMetaAndTagBits - metaAndTagBits
75
76  val io = IO(new Bundle() {
77    val read = Vec(readPorts, Flipped(ValidIO(new ECCReadReq)))
78    val resp = Output(Vec(readPorts, Vec(nWays, UInt(encBits.W))))
79    val write = Vec(writePorts, Flipped(ValidIO(new ECCWriteReq)))
80    val cacheOp = Flipped(new DCacheInnerOpIO)
81  })
82
83  val ecc_array = Reg(Vec(nSets, Vec(nWays, UInt(encBits.W))))
84  when (reset.asBool()) {
85    ecc_array := 0.U.asTypeOf(ecc_array.cloneType)
86  }
87
88  io.read.zip(io.resp).foreach {
89    case (read, resp) =>
90      resp := RegEnable(ecc_array(read.bits.idx), read.valid)
91  }
92
93  io.write.foreach {
94    case write =>
95      write.bits.way_en.asBools.zipWithIndex.foreach {
96        case (wen, i) =>
97          when (write.valid && wen) {
98            ecc_array(write.bits.idx)(i) := write.bits.ecc
99          }
100      }
101  }
102
103  // deal with customized cache op
104  val cacheOpShouldResp = WireInit(false.B)
105  when (io.cacheOp.req.valid) {
106    when (isReadTagECC(io.cacheOp.req.bits.opCode)) {
107      cacheOpShouldResp := true.B
108    }
109    when (isWriteTagECC(io.cacheOp.req.bits.opCode)) {
110      ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0)) :=
111        io.cacheOp.req.bits.write_tag_ecc
112      cacheOpShouldResp := true.B
113    }
114  }
115  io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp)
116  io.cacheOp.resp.bits := DontCare
117  io.cacheOp.resp.bits.read_tag_ecc := Mux(
118    io.cacheOp.resp.valid,
119    RegNext(ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0))),
120    0.U
121  )
122}
123
124class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
125  def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U)
126
127  // enc bits encode both tag and meta, but is saved in meta array
128  val metaAndTagBits = metaAndTagOnReset.getWidth
129  val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits)
130  val encMetaBits = encMetaAndTagBits - tagBits
131  val encBits = encMetaAndTagBits - metaAndTagBits
132
133  val io = IO(new Bundle() {
134    val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq)))
135    val resp = Output(Vec(readPorts, Vec(nWays, UInt(encMetaBits.W))))
136    val write = Vec(writePorts, Flipped(DecoupledIO(new MetaWriteReq)))
137    // customized cache op port
138    val cacheOp = Flipped(new DCacheInnerOpIO)
139  })
140
141  val meta_array = Reg(Vec(nSets, Vec(nWays, new Meta)))
142  val ecc_array = Module(new AsynchronousECCArray(readPorts, writePorts))
143  when (reset.asBool()) {
144    meta_array := 0.U.asTypeOf(meta_array.cloneType)
145  }
146
147  (io.read.zip(io.resp)).zipWithIndex.foreach {
148    case ((read, resp), i) =>
149      read.ready := true.B
150      ecc_array.io.read(i).valid := read.fire()
151      ecc_array.io.read(i).bits := read.bits
152      resp := VecInit(RegEnable(meta_array(read.bits.idx), read.valid).zip(
153        ecc_array.io.resp(i)
154      ).map { case (m, ecc) => Cat(ecc, m.asUInt) })
155  }
156
157  io.write.zip(ecc_array.io.write).foreach {
158    case (write, ecc_write) =>
159      write.ready := true.B
160      val ecc = cacheParams.tagCode.encode(MetaAndTag(write.bits.meta.coh, write.bits.tag).asUInt)(encMetaAndTagBits - 1, metaAndTagBits)
161      ecc_write.valid := write.fire()
162      ecc_write.bits.idx := write.bits.idx
163      ecc_write.bits.way_en := write.bits.way_en
164      ecc_write.bits.ecc := ecc
165      write.bits.way_en.asBools.zipWithIndex.foreach {
166        case (wen, i) =>
167          when (write.valid && wen) {
168            meta_array(write.bits.idx)(i) := write.bits.meta
169          }
170      }
171  }
172
173  ecc_array.io.cacheOp <> io.cacheOp
174}