xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala (revision 7a63335a24ddb1291e0ee7322a418aad5318c113)
11d8f4dcbSJay/***************************************************************************************
21d8f4dcbSJay* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
31d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory
41d8f4dcbSJay*
51d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2.
61d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2.
71d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at:
81d8f4dcbSJay*          http://license.coscl.org.cn/MulanPSL2
91d8f4dcbSJay*
101d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
111d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
121d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
131d8f4dcbSJay*
141d8f4dcbSJay* See the Mulan PSL v2 for more details.
151d8f4dcbSJay***************************************************************************************/
161d8f4dcbSJay
171d8f4dcbSJaypackage xiangshan.frontend.icache
181d8f4dcbSJay
198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
201d8f4dcbSJayimport chisel3._
211d8f4dcbSJayimport chisel3.util._
221d8f4dcbSJayimport freechips.rocketchip.diplomacy.IdRange
231d8f4dcbSJayimport freechips.rocketchip.tilelink.ClientStates._
241d8f4dcbSJayimport freechips.rocketchip.tilelink.TLPermissions._
251d8f4dcbSJayimport freechips.rocketchip.tilelink._
261d8f4dcbSJayimport xiangshan._
271d8f4dcbSJayimport xiangshan.cache._
281d8f4dcbSJayimport utils._
293c02ee8fSwakafaimport utility._
3041cb8b61SJeniusimport difftest._
311d8f4dcbSJay
321d8f4dcbSJay
331d8f4dcbSJayabstract class ICacheMissUnitModule(implicit p: Parameters) extends XSModule
341d8f4dcbSJay  with HasICacheParameters
351d8f4dcbSJay
361d8f4dcbSJayabstract class ICacheMissUnitBundle(implicit p: Parameters) extends XSBundle
371d8f4dcbSJay  with HasICacheParameters
381d8f4dcbSJay
391d8f4dcbSJay
40b92f8445Sssszwicclass Demultiplexer[T <: Data](val gen: T, val n: Int) extends Module
41b92f8445Sssszwic{
42b92f8445Sssszwic  /** Hardware module that is used to sequence 1 producers into n consumer.
43b92f8445Sssszwic    * Priority is given to lower producer.
44b92f8445Sssszwic    */
45b92f8445Sssszwic  require(n >= 2)
46b92f8445Sssszwic  val io = IO(new Bundle {
47b92f8445Sssszwic    val in      = Flipped(DecoupledIO(gen))
48b92f8445Sssszwic    val out     = Vec(n, DecoupledIO(gen))
49b92f8445Sssszwic    val chosen  = Output(UInt(log2Ceil(n).W))
50b92f8445Sssszwic  })
51b92f8445Sssszwic
52b92f8445Sssszwic  val grant = false.B +: (1 until n).map(i=> (0 until i).map(io.out(_).ready).reduce(_||_))
53b92f8445Sssszwic  for (i <- 0 until n) {
54b92f8445Sssszwic    io.out(i).bits := io.in.bits
55b92f8445Sssszwic    io.out(i).valid := !grant(i) && io.in.valid
56b92f8445Sssszwic  }
57b92f8445Sssszwic
58b92f8445Sssszwic  io.in.ready := grant.last || io.out.last.ready
59b92f8445Sssszwic  io.chosen := PriorityEncoder(VecInit(io.out.map(_.ready)))
601d8f4dcbSJay}
611d8f4dcbSJay
621d8f4dcbSJay
63b92f8445Sssszwicclass MuxBundle[T <: Data](val gen: T, val n: Int) extends Module
641d8f4dcbSJay{
65b92f8445Sssszwic  require(n >= 2)
66b92f8445Sssszwic  val io = IO(new Bundle {
67b92f8445Sssszwic    val sel     = Input(UInt(log2Ceil(n).W))
68b92f8445Sssszwic    val in      = Flipped(Vec(n, DecoupledIO(gen)))
69b92f8445Sssszwic    val out     = DecoupledIO(gen)
70b92f8445Sssszwic  })
71b92f8445Sssszwic
72b92f8445Sssszwic  io.in   <> DontCare
73b92f8445Sssszwic  io.out  <> DontCare
74b92f8445Sssszwic  for (i <- 0 until n) {
75b92f8445Sssszwic    when(io.sel === i.U) {
76b92f8445Sssszwic      io.out <> io.in(i)
77b92f8445Sssszwic    }
78b92f8445Sssszwic    io.in(i).ready := (io.sel === i.U) && io.out.ready
79b92f8445Sssszwic  }
80b92f8445Sssszwic}
81b92f8445Sssszwic
82b92f8445Sssszwic
83b92f8445Sssszwicclass ICacheMissReq(implicit p: Parameters) extends ICacheBundle {
84b92f8445Sssszwic  val blkPaddr  = UInt((PAddrBits - blockOffBits).W)
85b92f8445Sssszwic  val vSetIdx   = UInt(idxBits.W)
86b92f8445Sssszwic}
87b92f8445Sssszwic
88b92f8445Sssszwic
89b92f8445Sssszwicclass ICacheMissResp(implicit p: Parameters) extends ICacheBundle {
90b92f8445Sssszwic  val blkPaddr  = UInt((PAddrBits - blockOffBits).W)
91b92f8445Sssszwic  val vSetIdx   = UInt(idxBits.W)
92b92f8445Sssszwic  val waymask   = UInt(nWays.W)
931d8f4dcbSJay  val data      = UInt(blockBits.W)
9458dbdfc2SJay  val corrupt   = Bool()
951d8f4dcbSJay}
961d8f4dcbSJay
97b92f8445Sssszwic
98b92f8445Sssszwicclass LookUpMSHR(implicit p: Parameters) extends ICacheBundle {
99b92f8445Sssszwic  val info  = ValidIO(new ICacheMissReq)
100b92f8445Sssszwic  val hit   = Input(Bool())
1011d8f4dcbSJay}
1021d8f4dcbSJay
1031d8f4dcbSJay
104b92f8445Sssszwicclass MSHRResp(implicit p: Parameters) extends ICacheBundle {
105b92f8445Sssszwic  val blkPaddr  = UInt((PAddrBits - blockOffBits).W)
106b92f8445Sssszwic  val vSetIdx   = UInt(idxBits.W)
107b92f8445Sssszwic  val waymask   = UInt(log2Ceil(nWays).W)
108b92f8445Sssszwic}
109b92f8445Sssszwic
110b92f8445Sssszwic
111b92f8445Sssszwicclass MSHRAcquire(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle {
112b92f8445Sssszwic  val acquire = new TLBundleA(edge.bundle)
113b92f8445Sssszwic  val vSetIdx = UInt(idxBits.W)
114b92f8445Sssszwic}
115b92f8445Sssszwic
116b92f8445Sssszwicclass ICacheMSHR(edge: TLEdgeOut, isFetch: Boolean, ID: Int)(implicit p: Parameters) extends ICacheMissUnitModule {
1171d8f4dcbSJay  val io = IO(new Bundle {
1182a6078bfSguohongyu    val fencei      = Input(Bool())
119b92f8445Sssszwic    val flush       = Input(Bool())
120b92f8445Sssszwic    val invalid     = Input(Bool())
121b92f8445Sssszwic    val req         = Flipped(DecoupledIO(new ICacheMissReq))
122b92f8445Sssszwic    val acquire     = DecoupledIO(new MSHRAcquire(edge))
123b92f8445Sssszwic    val lookUps     = Flipped(Vec(2, new LookUpMSHR))
124b92f8445Sssszwic    val resp        = ValidIO(new MSHRResp)
125b92f8445Sssszwic    val victimWay   = Input(UInt(log2Ceil(nWays).W))
1261d8f4dcbSJay  })
1271d8f4dcbSJay
128b92f8445Sssszwic  val valid     = RegInit(Bool(), false.B)
129b92f8445Sssszwic  // this MSHR doesn't respones to fetch and sram
130b92f8445Sssszwic  val flush     = RegInit(Bool(), false.B)
131b92f8445Sssszwic  val fencei    = RegInit(Bool(), false.B)
132b92f8445Sssszwic  // this MSHR has been issued
133b92f8445Sssszwic  val issue     = RegInit(Bool(), false.B)
1341d8f4dcbSJay
135b92f8445Sssszwic  val blkPaddr  = RegInit(UInt((PAddrBits - blockOffBits).W), 0.U)
136b92f8445Sssszwic  val vSetIdx   = RegInit(UInt(idxBits.W), 0.U)
137b92f8445Sssszwic  val waymask   = RegInit(UInt(log2Ceil(nWays).W), 0.U)
1381d8f4dcbSJay
139b92f8445Sssszwic  // look up and return result at the same cycle
140b92f8445Sssszwic  val hits = io.lookUps.map(lookup => valid && !fencei && !flush && (lookup.info.bits.vSetIdx === vSetIdx) &&
141b92f8445Sssszwic                                      (lookup.info.bits.blkPaddr === blkPaddr))
142b92f8445Sssszwic  // Decoupling valid and bits
143b92f8445Sssszwic  (0 until 2).foreach { i =>
144b92f8445Sssszwic    io.lookUps(i).hit := hits(i)
145b92f8445Sssszwic  }
1461d8f4dcbSJay
147b92f8445Sssszwic  // disable wake up when hit MSHR (fencei is low)
148b92f8445Sssszwic  // when(hit) {
149b92f8445Sssszwic  //   flush := false.B
150b92f8445Sssszwic  // }
1512a6078bfSguohongyu
152b92f8445Sssszwic  // invalid when the req hasn't been issued
153b92f8445Sssszwic  when(io.fencei || io.flush) {
154b92f8445Sssszwic    fencei  := true.B
155b92f8445Sssszwic    flush   := true.B
156b92f8445Sssszwic    when(!issue) {
157b92f8445Sssszwic      valid := false.B
158b92f8445Sssszwic    }
159b92f8445Sssszwic  }
1601d8f4dcbSJay
161b92f8445Sssszwic  // receive request and register
162b92f8445Sssszwic  io.req.ready := !valid && !io.flush && !io.fencei
163935edac4STang Haojin  when(io.req.fire) {
164b92f8445Sssszwic    valid     := true.B
165b92f8445Sssszwic    flush     := false.B
166b92f8445Sssszwic    issue     := false.B
167b92f8445Sssszwic    fencei    := false.B
168b92f8445Sssszwic    blkPaddr  := io.req.bits.blkPaddr
169b92f8445Sssszwic    vSetIdx   := io.req.bits.vSetIdx
1701d8f4dcbSJay  }
1711d8f4dcbSJay
172b92f8445Sssszwic  // send request to L2
173b92f8445Sssszwic  io.acquire.valid := valid && !issue && !io.flush && !io.fencei
17438160951Sguohongyu  val getBlock = edge.Get(
175b92f8445Sssszwic    fromSource  = ID.U,
176b92f8445Sssszwic    toAddress   = Cat(blkPaddr, 0.U(blockOffBits.W)),
17738160951Sguohongyu    lgSize      = (log2Up(cacheParams.blockBytes)).U
17838160951Sguohongyu  )._2
179b92f8445Sssszwic  io.acquire.bits.acquire := getBlock
180b92f8445Sssszwic  io.acquire.bits.acquire.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPUInst.id.U)
181b92f8445Sssszwic  io.acquire.bits.vSetIdx := vSetIdx
18238160951Sguohongyu
183b92f8445Sssszwic  // get victim way when acquire fire
184b92f8445Sssszwic  when(io.acquire.fire) {
185b92f8445Sssszwic    issue   := true.B
186b92f8445Sssszwic    waymask := io.victimWay
187b92f8445Sssszwic  }
1881d8f4dcbSJay
189b92f8445Sssszwic  // invalid request when grant finish
190b92f8445Sssszwic  when(io.invalid) {
191b92f8445Sssszwic    valid := false.B
192b92f8445Sssszwic  }
1932a25dbb4SJay
194b92f8445Sssszwic  // offer the information other than data for write sram and response fetch
195b92f8445Sssszwic  io.resp.valid         := valid && (!flush && !fencei)
196b92f8445Sssszwic  io.resp.bits.blkPaddr := blkPaddr
197b92f8445Sssszwic  io.resp.bits.vSetIdx  := vSetIdx
198b92f8445Sssszwic  io.resp.bits.waymask  := waymask
199b92f8445Sssszwic}
200131aa97cSssszwic
201b92f8445Sssszwicclass ICacheMissBundle(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle{
202b92f8445Sssszwic  // difftest
203b92f8445Sssszwic  val hartId      = Input(Bool())
204b92f8445Sssszwic  // control
205b92f8445Sssszwic  val fencei      = Input(Bool())
206b92f8445Sssszwic  val flush       = Input(Bool())
207b92f8445Sssszwic  // fetch
208b92f8445Sssszwic  val fetch_req     = Flipped(DecoupledIO(new ICacheMissReq))
209b92f8445Sssszwic  val fetch_resp    = ValidIO(new ICacheMissResp)
210b92f8445Sssszwic  // prefetch
211b92f8445Sssszwic  val prefetch_req      = Flipped(DecoupledIO(new ICacheMissReq))
212b92f8445Sssszwic  // SRAM Write Req
213b92f8445Sssszwic  val meta_write    = DecoupledIO(new ICacheMetaWriteBundle)
214b92f8445Sssszwic  val data_write    = DecoupledIO(new ICacheDataWriteBundle)
215b92f8445Sssszwic  // get victim from replacer
216b92f8445Sssszwic  val victim        = new ReplacerVictim
217b92f8445Sssszwic  // Tilelink
218b92f8445Sssszwic  val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle))
219b92f8445Sssszwic  val mem_grant   = Flipped(DecoupledIO(new TLBundleD(edge.bundle)))
2201d8f4dcbSJay}
2211d8f4dcbSJay
2221d8f4dcbSJay
2231d8f4dcbSJayclass ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheMissUnitModule
2241d8f4dcbSJay{
225b92f8445Sssszwic  val io = IO(new ICacheMissBundle(edge))
2261d8f4dcbSJay
227b92f8445Sssszwic  /**
228b92f8445Sssszwic    ******************************************************************************
229b92f8445Sssszwic    * fetch have higher priority
230b92f8445Sssszwic    * fetch MSHR: lower index have a higher priority
231b92f8445Sssszwic    * prefetch MSHR: the prefetchMSHRs earlier have a higher priority
232b92f8445Sssszwic    *                 ---------       --------------       -----------
233b92f8445Sssszwic    * ---fetch reg--->| Demux |-----> | fetch MSHR |------>| Arbiter |---acquire--->
234b92f8445Sssszwic    *                 ---------       --------------       -----------
235b92f8445Sssszwic    *                                 | fetch MSHR |            ^
236b92f8445Sssszwic    *                                 --------------            |
237b92f8445Sssszwic    *                                                           |
238b92f8445Sssszwic    *                                -----------------          |
239b92f8445Sssszwic    *                                | prefetch MSHR |          |
240b92f8445Sssszwic    *                 ---------      -----------------     -----------
241b92f8445Sssszwic    * ---fetch reg--->| Demux |----> | prefetch MSHR |---->| Arbiter |
242b92f8445Sssszwic    *                 ---------      -----------------     -----------
243b92f8445Sssszwic    *                                |    .......    |
244b92f8445Sssszwic    *                                -----------------
245b92f8445Sssszwic    ******************************************************************************
246b92f8445Sssszwic    */
2471d8f4dcbSJay
248b92f8445Sssszwic  val fetchDemux    = Module(new Demultiplexer(new ICacheMissReq, nFetchMshr))
249b92f8445Sssszwic  val prefetchDemux = Module(new Demultiplexer(new ICacheMissReq, nPrefetchMshr))
250b92f8445Sssszwic  val prefetchArb   = Module(new MuxBundle(new MSHRAcquire(edge), nPrefetchMshr))
251b92f8445Sssszwic  val acquireArb    = Module(new Arbiter(new MSHRAcquire(edge), nFetchMshr + 1))
252cb6e5d3cSssszwic
253b92f8445Sssszwic  // To avoid duplicate request reception.
254b92f8445Sssszwic  val fetchHit, prefetchHit   = Wire(Bool())
255b92f8445Sssszwic  fetchDemux.io.in            <> io.fetch_req
256b92f8445Sssszwic  fetchDemux.io.in.valid      := io.fetch_req.valid && !fetchHit
257b92f8445Sssszwic  io.fetch_req.ready          := fetchDemux.io.in.ready || fetchHit
258b92f8445Sssszwic  prefetchDemux.io.in         <> io.prefetch_req
259b92f8445Sssszwic  prefetchDemux.io.in.valid   := io.prefetch_req.valid && !prefetchHit
260b92f8445Sssszwic  io.prefetch_req.ready       := prefetchDemux.io.in.ready || prefetchHit
261b92f8445Sssszwic  acquireArb.io.in.last       <> prefetchArb.io.out
2621d8f4dcbSJay
263b92f8445Sssszwic  // mem_acquire connect
264b92f8445Sssszwic  io.mem_acquire.valid        := acquireArb.io.out.valid
265b92f8445Sssszwic  io.mem_acquire.bits         := acquireArb.io.out.bits.acquire
266b92f8445Sssszwic  acquireArb.io.out.ready     := io.mem_acquire.ready
2671d8f4dcbSJay
268b92f8445Sssszwic  val fetchMSHRs = (0 until nFetchMshr).map { i =>
269b92f8445Sssszwic    val mshr = Module(new ICacheMSHR(edge, true, i))
270b92f8445Sssszwic    mshr.io.flush   := false.B
271b92f8445Sssszwic    mshr.io.fencei  := io.fencei
272b92f8445Sssszwic    mshr.io.req <> fetchDemux.io.out(i)
273b92f8445Sssszwic    mshr.io.lookUps(0).info.valid := io.fetch_req.valid
274b92f8445Sssszwic    mshr.io.lookUps(0).info.bits  := io.fetch_req.bits
275b92f8445Sssszwic    mshr.io.lookUps(1).info.valid := io.prefetch_req.valid
276b92f8445Sssszwic    mshr.io.lookUps(1).info.bits  := io.prefetch_req.bits
277b92f8445Sssszwic    mshr.io.victimWay             := io.victim.way
278b92f8445Sssszwic    acquireArb.io.in(i) <> mshr.io.acquire
279b92f8445Sssszwic    mshr
2801d8f4dcbSJay  }
2811d8f4dcbSJay
282b92f8445Sssszwic  val prefetchMSHRs = (0 until nPrefetchMshr).map { i =>
283b92f8445Sssszwic    val mshr = Module(new ICacheMSHR(edge, false, nFetchMshr + i))
284b92f8445Sssszwic    mshr.io.flush := io.flush
285b92f8445Sssszwic    mshr.io.fencei  := io.fencei
286b92f8445Sssszwic    mshr.io.req <> prefetchDemux.io.out(i)
287b92f8445Sssszwic    mshr.io.lookUps(0).info.valid := io.fetch_req.valid
288b92f8445Sssszwic    mshr.io.lookUps(0).info.bits  := io.fetch_req.bits
289b92f8445Sssszwic    mshr.io.lookUps(1).info.valid := io.prefetch_req.valid
290b92f8445Sssszwic    mshr.io.lookUps(1).info.bits  := io.prefetch_req.bits
291b92f8445Sssszwic    mshr.io.victimWay             := io.victim.way
292b92f8445Sssszwic    prefetchArb.io.in(i) <> mshr.io.acquire
293b92f8445Sssszwic    mshr
2947052722fSJay  }
2957052722fSJay
29658c354d0Sssszwic  /**
29758c354d0Sssszwic    ******************************************************************************
298b92f8445Sssszwic    * MSHR look up
299b92f8445Sssszwic    * - look up all mshr
30058c354d0Sssszwic    ******************************************************************************
30158c354d0Sssszwic    */
302b92f8445Sssszwic  val allMSHRs = (fetchMSHRs ++ prefetchMSHRs)
303b92f8445Sssszwic  val prefetchHitFetchReq = (io.prefetch_req.bits.blkPaddr === io.fetch_req.bits.blkPaddr) &&
304b92f8445Sssszwic                            (io.prefetch_req.bits.vSetIdx === io.fetch_req.bits.vSetIdx) &&
305b92f8445Sssszwic                            io.fetch_req.valid
306b92f8445Sssszwic  fetchHit    := allMSHRs.map(mshr => mshr.io.lookUps(0).hit).reduce(_||_)
307b92f8445Sssszwic  prefetchHit := allMSHRs.map(mshr => mshr.io.lookUps(1).hit).reduce(_||_) || prefetchHitFetchReq
30858c354d0Sssszwic
309b92f8445Sssszwic  /**
310b92f8445Sssszwic    ******************************************************************************
311b92f8445Sssszwic    * prefetchMSHRs priority
312b92f8445Sssszwic    * - The requests that enter the prefetchMSHRs earlier have a higher priority in issuing.
313b92f8445Sssszwic    * - The order of enqueuing is recorded in FIFO when requset enters MSHRs.
314b92f8445Sssszwic    * - The requests are dispatched in the order they are recorded in FIFO.
315b92f8445Sssszwic    ******************************************************************************
316b92f8445Sssszwic    */
317b92f8445Sssszwic  // When the FIFO is full, enqueue and dequeue operations do not occur at the same cycle.
318b92f8445Sssszwic  // So the depth of the FIFO is set to match the number of MSHRs.
319b92f8445Sssszwic  // val priorityFIFO = Module(new Queue(UInt(log2Ceil(nPrefetchMshr).W), nPrefetchMshr, hasFlush=true))
320b92f8445Sssszwic  val priorityFIFO = Module(new FIFOReg(UInt(log2Ceil(nPrefetchMshr).W), nPrefetchMshr, hasFlush=true))
321b92f8445Sssszwic  priorityFIFO.io.flush.get := io.flush || io.fencei
322b92f8445Sssszwic  priorityFIFO.io.enq.valid := prefetchDemux.io.in.fire
323b92f8445Sssszwic  priorityFIFO.io.enq.bits  := prefetchDemux.io.chosen
324b92f8445Sssszwic  priorityFIFO.io.deq.ready := prefetchArb.io.out.fire
325b92f8445Sssszwic  prefetchArb.io.sel        := priorityFIFO.io.deq.bits
326b92f8445Sssszwic  assert(!(priorityFIFO.io.enq.fire ^ prefetchDemux.io.in.fire), "priorityFIFO.io.enq and io.prefetch_req must fire at the same cycle")
327b92f8445Sssszwic  assert(!(priorityFIFO.io.deq.fire ^ prefetchArb.io.out.fire), "priorityFIFO.io.deq and prefetchArb.io.out must fire at the same cycle")
3287052722fSJay
329b92f8445Sssszwic  /**
330b92f8445Sssszwic    ******************************************************************************
331b92f8445Sssszwic    * Tilelink D channel (grant)
332b92f8445Sssszwic    ******************************************************************************
333b92f8445Sssszwic    */
334b92f8445Sssszwic  //cacheline register
335b92f8445Sssszwic  val readBeatCnt = RegInit(UInt(log2Up(refillCycles).W), 0.U)
336b92f8445Sssszwic  val respDataReg = RegInit(VecInit(Seq.fill(refillCycles)(0.U(beatBits.W))))
3371d8f4dcbSJay
338b92f8445Sssszwic  val wait_last = readBeatCnt === (refillCycles - 1).U
339b92f8445Sssszwic  when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits)) {
340b92f8445Sssszwic    respDataReg(readBeatCnt) := io.mem_grant.bits.data
341b92f8445Sssszwic    readBeatCnt := Mux(wait_last || io.mem_grant.bits.corrupt, 0.U, readBeatCnt + 1.U)
342b92f8445Sssszwic  }
343b92f8445Sssszwic
344b92f8445Sssszwic  // last transition finsh or corrupt
345b92f8445Sssszwic  val last_fire = io.mem_grant.fire && edge.hasData(io.mem_grant.bits) &&
346b92f8445Sssszwic                  (wait_last || io.mem_grant.bits.corrupt)
347b92f8445Sssszwic
348b92f8445Sssszwic  val (_, _, refill_done, _) = edge.addr_inc(io.mem_grant)
349b92f8445Sssszwic  assert(!(refill_done ^ last_fire), "refill not done!")
350b92f8445Sssszwic  io.mem_grant.ready := true.B
351b92f8445Sssszwic
352b92f8445Sssszwic  val last_fire_r = RegNext(last_fire)
353b92f8445Sssszwic  val id_r        = RegNext(io.mem_grant.bits.source)
354b92f8445Sssszwic  val corrupt_r   = RegNext(io.mem_grant.bits.corrupt)
355b92f8445Sssszwic
356b92f8445Sssszwic  /**
357b92f8445Sssszwic    ******************************************************************************
358b92f8445Sssszwic    * invalid mshr when finish transition
359b92f8445Sssszwic    ******************************************************************************
360b92f8445Sssszwic    */
361b92f8445Sssszwic  (0 until (nFetchMshr + nPrefetchMshr)).foreach{ i =>
362b92f8445Sssszwic    allMSHRs(i).io.invalid := last_fire_r && (id_r === i.U)
363b92f8445Sssszwic  }
364b92f8445Sssszwic
365b92f8445Sssszwic  /**
366b92f8445Sssszwic    ******************************************************************************
367b92f8445Sssszwic    * response fetch and write SRAM
368b92f8445Sssszwic    ******************************************************************************
369b92f8445Sssszwic    */
370b92f8445Sssszwic  // get request information from MSHRs
371b92f8445Sssszwic  val allMSHRs_resp = VecInit(allMSHRs.map(mshr => mshr.io.resp))
372b92f8445Sssszwic  val mshr_resp = allMSHRs_resp(id_r)
373b92f8445Sssszwic
374b92f8445Sssszwic  // get waymask from replacer when acquire fire
375*7a63335aSxu_zh  io.victim.vSetIdx.valid := acquireArb.io.out.fire
376b92f8445Sssszwic  io.victim.vSetIdx.bits  := acquireArb.io.out.bits.vSetIdx
377b92f8445Sssszwic  val waymask = UIntToOH(mshr_resp.bits.waymask)
378b92f8445Sssszwic  val fetch_resp_valid = mshr_resp.valid && last_fire_r && !io.flush && !io.fencei
379b92f8445Sssszwic  val write_sram_valid = fetch_resp_valid && !corrupt_r
380b92f8445Sssszwic
381b92f8445Sssszwic  // write SRAM
382b92f8445Sssszwic  io.meta_write.bits.generate(tag     = getPhyTagFromBlk(mshr_resp.bits.blkPaddr),
383b92f8445Sssszwic                              idx     = mshr_resp.bits.vSetIdx,
384b92f8445Sssszwic                              waymask = waymask,
385b92f8445Sssszwic                              bankIdx = mshr_resp.bits.vSetIdx(0))
386b92f8445Sssszwic  io.data_write.bits.generate(data    = respDataReg.asUInt,
387b92f8445Sssszwic                              idx     = mshr_resp.bits.vSetIdx,
388b92f8445Sssszwic                              waymask = waymask,
389b92f8445Sssszwic                              bankIdx = mshr_resp.bits.vSetIdx(0))
390b92f8445Sssszwic
391b92f8445Sssszwic  io.meta_write.valid := write_sram_valid
392b92f8445Sssszwic  io.data_write.valid := write_sram_valid
393b92f8445Sssszwic
394b92f8445Sssszwic  // response fetch
395b92f8445Sssszwic  io.fetch_resp.valid         := fetch_resp_valid
396b92f8445Sssszwic  io.fetch_resp.bits.blkPaddr := mshr_resp.bits.blkPaddr
397b92f8445Sssszwic  io.fetch_resp.bits.vSetIdx  := mshr_resp.bits.vSetIdx
398b92f8445Sssszwic  io.fetch_resp.bits.waymask  := waymask
399b92f8445Sssszwic  io.fetch_resp.bits.data     := respDataReg.asUInt
400b92f8445Sssszwic  io.fetch_resp.bits.corrupt  := corrupt_r
401b92f8445Sssszwic
402b92f8445Sssszwic  /**
403b92f8445Sssszwic    ******************************************************************************
404b92f8445Sssszwic    * performance counter
405b92f8445Sssszwic    ******************************************************************************
406b92f8445Sssszwic    */
407b92f8445Sssszwic  // Duplicate requests will be excluded.
408b92f8445Sssszwic  XSPerfAccumulate("enq_fetch_req",     fetchDemux.io.in.fire)
409b92f8445Sssszwic  XSPerfAccumulate("enq_prefetch_req",  prefetchDemux.io.in.fire)
410b92f8445Sssszwic
411b92f8445Sssszwic  /**
412b92f8445Sssszwic    ******************************************************************************
413b92f8445Sssszwic    * ChiselDB: record ICache SRAM write log
414b92f8445Sssszwic    ******************************************************************************
415b92f8445Sssszwic    */
416b92f8445Sssszwic  class ICacheSRAMDB(implicit p: Parameters) extends ICacheBundle{
417b92f8445Sssszwic    val blkPaddr  = UInt((PAddrBits - blockOffBits).W)
418b92f8445Sssszwic    val vSetIdx   = UInt(idxBits.W)
419b92f8445Sssszwic    val waymask   = UInt(log2Ceil(nWays).W)
420b92f8445Sssszwic  }
421b92f8445Sssszwic
422b92f8445Sssszwic  val isWriteICacheSRAMTable = WireInit(Constantin.createRecord("isWriteICacheSRAMTable" + p(XSCoreParamsKey).HartId.toString))
423b92f8445Sssszwic  val ICacheSRAMTable = ChiselDB.createTable("ICacheSRAMTable" + p(XSCoreParamsKey).HartId.toString, new ICacheSRAMDB)
424b92f8445Sssszwic
425b92f8445Sssszwic  val ICacheSRAMDBDumpData = Wire(new ICacheSRAMDB)
426b92f8445Sssszwic  ICacheSRAMDBDumpData.blkPaddr  := mshr_resp.bits.blkPaddr
427b92f8445Sssszwic  ICacheSRAMDBDumpData.vSetIdx   := mshr_resp.bits.vSetIdx
428b92f8445Sssszwic  ICacheSRAMDBDumpData.waymask   := OHToUInt(waymask)
429b92f8445Sssszwic  ICacheSRAMTable.log(
430b92f8445Sssszwic    data  = ICacheSRAMDBDumpData,
431b92f8445Sssszwic    en    = write_sram_valid,
432b92f8445Sssszwic    clock = clock,
433b92f8445Sssszwic    reset = reset
434b92f8445Sssszwic  )
435b92f8445Sssszwic
436b92f8445Sssszwic  /**
437b92f8445Sssszwic    ******************************************************************************
438b92f8445Sssszwic    * Difftest
439b92f8445Sssszwic    ******************************************************************************
440b92f8445Sssszwic    */
441afa866b1Sguohongyu  if (env.EnableDifftest) {
442a0c65233SYinan Xu    val difftest = DifftestModule(new DiffRefillEvent, dontCare = true)
4437d45a146SYinan Xu    difftest.coreid := io.hartId
4447d45a146SYinan Xu    difftest.index  := 0.U
445b92f8445Sssszwic    difftest.valid  := write_sram_valid
446b92f8445Sssszwic    difftest.addr   := Cat(mshr_resp.bits.blkPaddr, 0.U(blockOffBits.W))
447b92f8445Sssszwic    difftest.data   := respDataReg.asTypeOf(difftest.data)
448935edac4STang Haojin    difftest.idtfr  := DontCare
44941cb8b61SJenius  }
4501d8f4dcbSJay}