xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/meta/AsynchronousMetaArray.scala (revision 08b0bc306dc55249d4b6f985ded955c9f4ca8d54)
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 org.chipsalliance.cde.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 MetaReadReq(implicit p: Parameters) extends DCacheBundle {
39  val idx = UInt(idxBits.W)
40  val way_en = UInt(nWays.W)
41}
42
43class CohMetaWriteReq(implicit p: Parameters) extends MetaReadReq {
44  val meta = new Meta
45}
46
47class FlagMetaWriteReq(implicit p: Parameters) extends MetaReadReq {
48  val flag = Bool()
49}
50
51class L1CohMetaArray(readPorts: Int, writePorts: Int, bypassRead: Boolean = false)(implicit p: Parameters) extends DCacheModule {
52  val io = IO(new Bundle() {
53    val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq)))
54    val resp = Output(Vec(readPorts, Vec(nWays, new Meta)))
55    val write = Vec(writePorts, Flipped(DecoupledIO(new CohMetaWriteReq)))
56  })
57
58  val meta_array = RegInit(
59    VecInit(Seq.fill(nSets)(
60      VecInit(Seq.fill(nWays)(0.U.asTypeOf(new Meta)))
61    ))
62  )
63
64  val s0_way_wen = Wire(Vec(nWays, Vec(writePorts, Bool())))
65  val s1_way_wen = Wire(Vec(nWays, Vec(writePorts, Bool())))
66  val s1_way_waddr = Wire(Vec(nWays, Vec(writePorts, UInt(idxBits.W))))
67  val s1_way_wdata = Wire(Vec(nWays, Vec(writePorts, new Meta)))
68
69  (io.read.zip(io.resp)).zipWithIndex.foreach {
70    case ((read, resp), i) =>
71      read.ready := true.B
72      (0 until nWays).map(way => {
73        val read_way_bypass = WireInit(false.B)
74        val bypass_data = Wire(new Meta)
75        bypass_data := DontCare
76        (0 until writePorts).map(wport =>
77          when(s1_way_wen(way)(wport) && s1_way_waddr(way)(wport) === read.bits.idx){
78            read_way_bypass := true.B
79            bypass_data := s1_way_wdata(way)(wport)
80          }
81        )
82        if (bypassRead) {
83          resp(way) := Mux(
84            RegEnable(read_way_bypass, read.valid),
85            RegEnable(bypass_data, read_way_bypass),
86            RegEnable(meta_array(read.bits.idx)(way), read.valid)
87          )
88        } else {
89          resp(way) := meta_array(RegEnable(read.bits.idx, read.valid))(way)
90        }
91      })
92  }
93
94  io.write.zipWithIndex.foreach {
95    case (write, wport) =>
96      write.ready := true.B
97      write.bits.way_en.asBools.zipWithIndex.foreach {
98        case (wen, way) =>
99          s0_way_wen(way)(wport) := write.valid && wen
100          s1_way_wen(way)(wport) := RegNext(s0_way_wen(way)(wport))
101          s1_way_waddr(way)(wport) := RegEnable(write.bits.idx, s0_way_wen(way)(wport))
102          s1_way_wdata(way)(wport) := RegEnable(write.bits.meta, s0_way_wen(way)(wport))
103          when (s1_way_wen(way)(wport)) {
104            meta_array(s1_way_waddr(way)(wport))(way) := s1_way_wdata(way)(wport)
105          }
106      }
107  }
108}
109
110class L1FlagMetaArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
111  val io = IO(new Bundle() {
112    val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq)))
113    val resp = Output(Vec(readPorts, Vec(nWays, Bool())))
114    val write = Vec(writePorts, Flipped(DecoupledIO(new FlagMetaWriteReq)))
115    // customized cache op port
116    // val cacheOp = Flipped(new L1CacheInnerOpIO)
117  })
118
119  val meta_array = RegInit(
120    VecInit(Seq.fill(nSets)(
121      VecInit(Seq.fill(nWays)(0.U.asTypeOf(false.B)))
122    ))
123  )
124
125  val s0_way_wen = Wire(Vec(nWays, Vec(writePorts, Bool())))
126  val s1_way_wen = Wire(Vec(nWays, Vec(writePorts, Bool())))
127  val s1_way_waddr = Wire(Vec(nWays, Vec(writePorts, UInt(idxBits.W))))
128  val s1_way_wdata = Wire(Vec(nWays, Vec(writePorts, Bool())))
129
130  (io.read.zip(io.resp)).zipWithIndex.foreach {
131    case ((read, resp), i) =>
132      read.ready := true.B
133      (0 until nWays).map(way => {
134        val read_way_bypass = WireInit(false.B)
135        val bypass_data = Wire(Bool())
136        bypass_data := DontCare
137        (0 until writePorts).map(wport =>
138          when(s1_way_wen(way)(wport) && s1_way_waddr(way)(wport) === read.bits.idx){
139            read_way_bypass := true.B
140            bypass_data := s1_way_wdata(way)(wport)
141          }
142        )
143        resp(way) := Mux(
144          RegEnable(read_way_bypass, read.valid),
145          RegEnable(bypass_data, read_way_bypass),
146          meta_array(RegEnable(read.bits.idx, read.valid))(way)
147        )
148      })
149  }
150
151  io.write.zipWithIndex.foreach {
152    case (write, wport) =>
153      write.ready := true.B
154      write.bits.way_en.asBools.zipWithIndex.foreach {
155        case (wen, way) =>
156          s0_way_wen(way)(wport) := write.valid && wen
157          s1_way_wen(way)(wport) := RegNext(s0_way_wen(way)(wport))
158          s1_way_waddr(way)(wport) := RegEnable(write.bits.idx, s0_way_wen(way)(wport))
159          s1_way_wdata(way)(wport) := RegEnable(write.bits.flag, s0_way_wen(way)(wport))
160          when (s1_way_wen(way)(wport)) {
161            meta_array(s1_way_waddr(way)(wport))(way) := s1_way_wdata(way)(wport)
162          }
163      }
164  }
165}
166
167class SourceMetaWriteReq(implicit p: Parameters) extends MetaReadReq {
168  val source = UInt(L1PfSourceBits.W)
169}
170
171class L1PrefetchSourceArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
172  val io = IO(new Bundle() {
173    val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq)))
174    val resp = Output(Vec(readPorts, Vec(nWays, UInt(L1PfSourceBits.W))))
175    val write = Vec(writePorts, Flipped(DecoupledIO(new SourceMetaWriteReq)))
176  })
177
178  val meta_array = RegInit(
179    VecInit(Seq.fill(nSets)(
180      VecInit(Seq.fill(nWays)(0.U(L1PfSourceBits.W)))
181    ))
182  )
183
184  val s0_way_wen = Wire(Vec(nWays, Vec(writePorts, Bool())))
185  val s1_way_wen = Wire(Vec(nWays, Vec(writePorts, Bool())))
186  val s1_way_waddr = Wire(Vec(nWays, Vec(writePorts, UInt(idxBits.W))))
187  val s1_way_wdata = Wire(Vec(nWays, Vec(writePorts, UInt(L1PfSourceBits.W))))
188
189  (io.read.zip(io.resp)).zipWithIndex.foreach {
190    case ((read, resp), i) =>
191      read.ready := true.B
192      (0 until nWays).map(way => {
193        val read_way_bypass = WireInit(false.B)
194        val bypass_data = Wire(UInt(L1PfSourceBits.W))
195        bypass_data := DontCare
196        (0 until writePorts).map(wport =>
197          when(s1_way_wen(way)(wport) && s1_way_waddr(way)(wport) === read.bits.idx){
198            read_way_bypass := true.B
199            bypass_data := s1_way_wdata(way)(wport)
200          }
201        )
202        resp(way) := Mux(
203          RegEnable(read_way_bypass, read.valid),
204          RegEnable(bypass_data, read_way_bypass),
205          meta_array(RegEnable(read.bits.idx, read.valid))(way)
206        )
207      })
208  }
209
210  io.write.zipWithIndex.foreach {
211    case (write, wport) =>
212      write.ready := true.B
213      write.bits.way_en.asBools.zipWithIndex.foreach {
214        case (wen, way) =>
215          s0_way_wen(way)(wport) := write.valid && wen
216          s1_way_wen(way)(wport) := RegNext(s0_way_wen(way)(wport))
217          s1_way_waddr(way)(wport) := RegEnable(write.bits.idx, s0_way_wen(way)(wport))
218          s1_way_wdata(way)(wport) := RegEnable(write.bits.source, s0_way_wen(way)(wport))
219          when (s1_way_wen(way)(wport)) {
220            meta_array(s1_way_waddr(way)(wport))(way) := s1_way_wdata(way)(wport)
221          }
222      }
223  }
224}
225