xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala (revision cf7d6b7a1a781c73aeb87de112de2e7fe5ea3b7c)
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
191d8f4dcbSJayimport chisel3._
201d8f4dcbSJayimport chisel3.util._
21*cf7d6b7aSMuziimport difftest._
221d8f4dcbSJayimport freechips.rocketchip.diplomacy.IdRange
23*cf7d6b7aSMuziimport freechips.rocketchip.tilelink._
241d8f4dcbSJayimport freechips.rocketchip.tilelink.ClientStates._
251d8f4dcbSJayimport freechips.rocketchip.tilelink.TLPermissions._
26*cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters
27*cf7d6b7aSMuziimport utility._
28*cf7d6b7aSMuziimport utils._
291d8f4dcbSJayimport xiangshan._
301d8f4dcbSJayimport xiangshan.cache._
311d8f4dcbSJay
321d8f4dcbSJayabstract class ICacheMissUnitModule(implicit p: Parameters) extends XSModule
331d8f4dcbSJay    with HasICacheParameters
341d8f4dcbSJay
351d8f4dcbSJayabstract class ICacheMissUnitBundle(implicit p: Parameters) extends XSBundle
361d8f4dcbSJay    with HasICacheParameters
371d8f4dcbSJay
38*cf7d6b7aSMuziclass Demultiplexer[T <: Data](val gen: T, val n: Int) extends Module {
391d8f4dcbSJay
40b92f8445Sssszwic  /** Hardware module that is used to sequence 1 producers into n consumer.
41b92f8445Sssszwic    * Priority is given to lower producer.
42b92f8445Sssszwic    */
43b92f8445Sssszwic  require(n >= 2)
44b92f8445Sssszwic  val io = IO(new Bundle {
45b92f8445Sssszwic    val in     = Flipped(DecoupledIO(gen))
46b92f8445Sssszwic    val out    = Vec(n, DecoupledIO(gen))
47b92f8445Sssszwic    val chosen = Output(UInt(log2Ceil(n).W))
48b92f8445Sssszwic  })
49b92f8445Sssszwic
50b92f8445Sssszwic  val grant = false.B +: (1 until n).map(i => (0 until i).map(io.out(_).ready).reduce(_ || _))
51b92f8445Sssszwic  for (i <- 0 until n) {
52b92f8445Sssszwic    io.out(i).bits  := io.in.bits
53b92f8445Sssszwic    io.out(i).valid := !grant(i) && io.in.valid
54b92f8445Sssszwic  }
55b92f8445Sssszwic
56b92f8445Sssszwic  io.in.ready := grant.last || io.out.last.ready
57b92f8445Sssszwic  io.chosen   := PriorityEncoder(VecInit(io.out.map(_.ready)))
581d8f4dcbSJay}
591d8f4dcbSJay
60*cf7d6b7aSMuziclass MuxBundle[T <: Data](val gen: T, val n: Int) extends Module {
61b92f8445Sssszwic  require(n >= 2)
62b92f8445Sssszwic  val io = IO(new Bundle {
63b92f8445Sssszwic    val sel = Input(UInt(log2Ceil(n).W))
64b92f8445Sssszwic    val in  = Flipped(Vec(n, DecoupledIO(gen)))
65b92f8445Sssszwic    val out = DecoupledIO(gen)
66b92f8445Sssszwic  })
67b92f8445Sssszwic
68b92f8445Sssszwic  io.in <> DontCare
69b92f8445Sssszwic  io.out <> DontCare
70b92f8445Sssszwic  for (i <- 0 until n) {
71b92f8445Sssszwic    when(io.sel === i.U) {
72b92f8445Sssszwic      io.out <> io.in(i)
73b92f8445Sssszwic    }
74b92f8445Sssszwic    io.in(i).ready := (io.sel === i.U) && io.out.ready
75b92f8445Sssszwic  }
76b92f8445Sssszwic}
77b92f8445Sssszwic
78b92f8445Sssszwicclass ICacheMissReq(implicit p: Parameters) extends ICacheBundle {
79b92f8445Sssszwic  val blkPaddr = UInt((PAddrBits - blockOffBits).W)
80b92f8445Sssszwic  val vSetIdx  = UInt(idxBits.W)
81b92f8445Sssszwic}
82b92f8445Sssszwic
83b92f8445Sssszwicclass ICacheMissResp(implicit p: Parameters) extends ICacheBundle {
84b92f8445Sssszwic  val blkPaddr = UInt((PAddrBits - blockOffBits).W)
85b92f8445Sssszwic  val vSetIdx  = UInt(idxBits.W)
86b92f8445Sssszwic  val waymask  = UInt(nWays.W)
871d8f4dcbSJay  val data     = UInt(blockBits.W)
8858dbdfc2SJay  val corrupt  = Bool()
891d8f4dcbSJay}
901d8f4dcbSJay
91b92f8445Sssszwicclass LookUpMSHR(implicit p: Parameters) extends ICacheBundle {
92b92f8445Sssszwic  val info = ValidIO(new ICacheMissReq)
93b92f8445Sssszwic  val hit  = Input(Bool())
941d8f4dcbSJay}
951d8f4dcbSJay
96b92f8445Sssszwicclass MSHRResp(implicit p: Parameters) extends ICacheBundle {
97b92f8445Sssszwic  val blkPaddr = UInt((PAddrBits - blockOffBits).W)
98b92f8445Sssszwic  val vSetIdx  = UInt(idxBits.W)
99b92f8445Sssszwic  val waymask  = UInt(log2Ceil(nWays).W)
100b92f8445Sssszwic}
101b92f8445Sssszwic
102b92f8445Sssszwicclass MSHRAcquire(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle {
103b92f8445Sssszwic  val acquire = new TLBundleA(edge.bundle)
104b92f8445Sssszwic  val vSetIdx = UInt(idxBits.W)
105b92f8445Sssszwic}
106b92f8445Sssszwic
107b92f8445Sssszwicclass ICacheMSHR(edge: TLEdgeOut, isFetch: Boolean, ID: Int)(implicit p: Parameters) extends ICacheMissUnitModule {
1081d8f4dcbSJay  val io = IO(new Bundle {
1092a6078bfSguohongyu    val fencei    = Input(Bool())
110b92f8445Sssszwic    val flush     = Input(Bool())
111b92f8445Sssszwic    val invalid   = Input(Bool())
112b92f8445Sssszwic    val req       = Flipped(DecoupledIO(new ICacheMissReq))
113b92f8445Sssszwic    val acquire   = DecoupledIO(new MSHRAcquire(edge))
114b92f8445Sssszwic    val lookUps   = Flipped(Vec(2, new LookUpMSHR))
115b92f8445Sssszwic    val resp      = ValidIO(new MSHRResp)
116b92f8445Sssszwic    val victimWay = Input(UInt(log2Ceil(nWays).W))
1171d8f4dcbSJay  })
1181d8f4dcbSJay
119b92f8445Sssszwic  val valid = RegInit(Bool(), false.B)
120b92f8445Sssszwic  // this MSHR doesn't respones to fetch and sram
121b92f8445Sssszwic  val flush  = RegInit(Bool(), false.B)
122b92f8445Sssszwic  val fencei = RegInit(Bool(), false.B)
123b92f8445Sssszwic  // this MSHR has been issued
124b92f8445Sssszwic  val issue = RegInit(Bool(), false.B)
1251d8f4dcbSJay
126b92f8445Sssszwic  val blkPaddr = RegInit(UInt((PAddrBits - blockOffBits).W), 0.U)
127b92f8445Sssszwic  val vSetIdx  = RegInit(UInt(idxBits.W), 0.U)
128b92f8445Sssszwic  val waymask  = RegInit(UInt(log2Ceil(nWays).W), 0.U)
1291d8f4dcbSJay
130b92f8445Sssszwic  // look up and return result at the same cycle
131*cf7d6b7aSMuzi  val hits = io.lookUps.map(lookup =>
132*cf7d6b7aSMuzi    valid && !fencei && !flush && (lookup.info.bits.vSetIdx === vSetIdx) &&
133*cf7d6b7aSMuzi      (lookup.info.bits.blkPaddr === blkPaddr)
134*cf7d6b7aSMuzi  )
135b92f8445Sssszwic  // Decoupling valid and bits
136*cf7d6b7aSMuzi  (0 until 2).foreach(i => io.lookUps(i).hit := hits(i))
1371d8f4dcbSJay
138b92f8445Sssszwic  // disable wake up when hit MSHR (fencei is low)
139b92f8445Sssszwic  // when(hit) {
140b92f8445Sssszwic  //   flush := false.B
141b92f8445Sssszwic  // }
1422a6078bfSguohongyu
143b92f8445Sssszwic  // invalid when the req hasn't been issued
144b92f8445Sssszwic  when(io.fencei || io.flush) {
145b92f8445Sssszwic    fencei := true.B
146b92f8445Sssszwic    flush  := true.B
147b92f8445Sssszwic    when(!issue) {
148b92f8445Sssszwic      valid := false.B
149b92f8445Sssszwic    }
150b92f8445Sssszwic  }
1511d8f4dcbSJay
152b92f8445Sssszwic  // receive request and register
153b92f8445Sssszwic  io.req.ready := !valid && !io.flush && !io.fencei
154935edac4STang Haojin  when(io.req.fire) {
155b92f8445Sssszwic    valid    := true.B
156b92f8445Sssszwic    flush    := false.B
157b92f8445Sssszwic    issue    := false.B
158b92f8445Sssszwic    fencei   := false.B
159b92f8445Sssszwic    blkPaddr := io.req.bits.blkPaddr
160b92f8445Sssszwic    vSetIdx  := io.req.bits.vSetIdx
1611d8f4dcbSJay  }
1621d8f4dcbSJay
163b92f8445Sssszwic  // send request to L2
164b92f8445Sssszwic  io.acquire.valid := valid && !issue && !io.flush && !io.fencei
16538160951Sguohongyu  val getBlock = edge.Get(
166b92f8445Sssszwic    fromSource = ID.U,
167b92f8445Sssszwic    toAddress = Cat(blkPaddr, 0.U(blockOffBits.W)),
168*cf7d6b7aSMuzi    lgSize = log2Up(cacheParams.blockBytes).U
16938160951Sguohongyu  )._2
170b92f8445Sssszwic  io.acquire.bits.acquire := getBlock
171b92f8445Sssszwic  io.acquire.bits.acquire.user.lift(ReqSourceKey).foreach(_ := MemReqSource.CPUInst.id.U)
172b92f8445Sssszwic  io.acquire.bits.vSetIdx := vSetIdx
17338160951Sguohongyu
174b92f8445Sssszwic  // get victim way when acquire fire
175b92f8445Sssszwic  when(io.acquire.fire) {
176b92f8445Sssszwic    issue   := true.B
177b92f8445Sssszwic    waymask := io.victimWay
178b92f8445Sssszwic  }
1791d8f4dcbSJay
180b92f8445Sssszwic  // invalid request when grant finish
181b92f8445Sssszwic  when(io.invalid) {
182b92f8445Sssszwic    valid := false.B
183b92f8445Sssszwic  }
1842a25dbb4SJay
185b92f8445Sssszwic  // offer the information other than data for write sram and response fetch
186b92f8445Sssszwic  io.resp.valid         := valid && (!flush && !fencei)
187b92f8445Sssszwic  io.resp.bits.blkPaddr := blkPaddr
188b92f8445Sssszwic  io.resp.bits.vSetIdx  := vSetIdx
189b92f8445Sssszwic  io.resp.bits.waymask  := waymask
190b92f8445Sssszwic}
191131aa97cSssszwic
192b92f8445Sssszwicclass ICacheMissBundle(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle {
193b92f8445Sssszwic  // difftest
194b92f8445Sssszwic  val hartId = Input(Bool())
195b92f8445Sssszwic  // control
196b92f8445Sssszwic  val fencei = Input(Bool())
197b92f8445Sssszwic  val flush  = Input(Bool())
198b92f8445Sssszwic  // fetch
199b92f8445Sssszwic  val fetch_req  = Flipped(DecoupledIO(new ICacheMissReq))
200b92f8445Sssszwic  val fetch_resp = ValidIO(new ICacheMissResp)
201b92f8445Sssszwic  // prefetch
202b92f8445Sssszwic  val prefetch_req = Flipped(DecoupledIO(new ICacheMissReq))
203b92f8445Sssszwic  // SRAM Write Req
204b92f8445Sssszwic  val meta_write = DecoupledIO(new ICacheMetaWriteBundle)
205b92f8445Sssszwic  val data_write = DecoupledIO(new ICacheDataWriteBundle)
206b92f8445Sssszwic  // get victim from replacer
207b92f8445Sssszwic  val victim = new ReplacerVictim
208b92f8445Sssszwic  // Tilelink
209b92f8445Sssszwic  val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle))
210b92f8445Sssszwic  val mem_grant   = Flipped(DecoupledIO(new TLBundleD(edge.bundle)))
2111d8f4dcbSJay}
2121d8f4dcbSJay
213*cf7d6b7aSMuziclass ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheMissUnitModule {
214b92f8445Sssszwic  val io = IO(new ICacheMissBundle(edge))
2151d8f4dcbSJay
216b92f8445Sssszwic  /**
217b92f8445Sssszwic    ******************************************************************************
218b92f8445Sssszwic    * fetch have higher priority
219b92f8445Sssszwic    * fetch MSHR: lower index have a higher priority
220b92f8445Sssszwic    * prefetch MSHR: the prefetchMSHRs earlier have a higher priority
221b92f8445Sssszwic    *                 ---------       --------------       -----------
222b92f8445Sssszwic    * ---fetch reg--->| Demux |-----> | fetch MSHR |------>| Arbiter |---acquire--->
223b92f8445Sssszwic    *                 ---------       --------------       -----------
224b92f8445Sssszwic    *                                 | fetch MSHR |            ^
225b92f8445Sssszwic    *                                 --------------            |
226b92f8445Sssszwic    *                                                           |
227b92f8445Sssszwic    *                                -----------------          |
228b92f8445Sssszwic    *                                | prefetch MSHR |          |
229b92f8445Sssszwic    *                 ---------      -----------------     -----------
230b92f8445Sssszwic    * ---fetch reg--->| Demux |----> | prefetch MSHR |---->| Arbiter |
231b92f8445Sssszwic    *                 ---------      -----------------     -----------
232b92f8445Sssszwic    *                                |    .......    |
233b92f8445Sssszwic    *                                -----------------
234b92f8445Sssszwic    ******************************************************************************
235b92f8445Sssszwic    */
2361d8f4dcbSJay
237b92f8445Sssszwic  val fetchDemux    = Module(new Demultiplexer(new ICacheMissReq, nFetchMshr))
238b92f8445Sssszwic  val prefetchDemux = Module(new Demultiplexer(new ICacheMissReq, nPrefetchMshr))
239b92f8445Sssszwic  val prefetchArb   = Module(new MuxBundle(new MSHRAcquire(edge), nPrefetchMshr))
240b92f8445Sssszwic  val acquireArb    = Module(new Arbiter(new MSHRAcquire(edge), nFetchMshr + 1))
241cb6e5d3cSssszwic
242b92f8445Sssszwic  // To avoid duplicate request reception.
243b92f8445Sssszwic  val fetchHit, prefetchHit = Wire(Bool())
244b92f8445Sssszwic  fetchDemux.io.in <> io.fetch_req
245b92f8445Sssszwic  fetchDemux.io.in.valid := io.fetch_req.valid && !fetchHit
246b92f8445Sssszwic  io.fetch_req.ready     := fetchDemux.io.in.ready || fetchHit
247b92f8445Sssszwic  prefetchDemux.io.in <> io.prefetch_req
248b92f8445Sssszwic  prefetchDemux.io.in.valid := io.prefetch_req.valid && !prefetchHit
249b92f8445Sssszwic  io.prefetch_req.ready     := prefetchDemux.io.in.ready || prefetchHit
250b92f8445Sssszwic  acquireArb.io.in.last <> prefetchArb.io.out
2511d8f4dcbSJay
252b92f8445Sssszwic  // mem_acquire connect
253b92f8445Sssszwic  io.mem_acquire.valid    := acquireArb.io.out.valid
254b92f8445Sssszwic  io.mem_acquire.bits     := acquireArb.io.out.bits.acquire
255b92f8445Sssszwic  acquireArb.io.out.ready := io.mem_acquire.ready
2561d8f4dcbSJay
257b92f8445Sssszwic  val fetchMSHRs = (0 until nFetchMshr).map { i =>
258b92f8445Sssszwic    val mshr = Module(new ICacheMSHR(edge, true, i))
259b92f8445Sssszwic    mshr.io.flush  := false.B
260b92f8445Sssszwic    mshr.io.fencei := io.fencei
261b92f8445Sssszwic    mshr.io.req <> fetchDemux.io.out(i)
262b92f8445Sssszwic    mshr.io.lookUps(0).info.valid := io.fetch_req.valid
263b92f8445Sssszwic    mshr.io.lookUps(0).info.bits  := io.fetch_req.bits
264b92f8445Sssszwic    mshr.io.lookUps(1).info.valid := io.prefetch_req.valid
265b92f8445Sssszwic    mshr.io.lookUps(1).info.bits  := io.prefetch_req.bits
266b92f8445Sssszwic    mshr.io.victimWay             := io.victim.way
267b92f8445Sssszwic    acquireArb.io.in(i) <> mshr.io.acquire
268b92f8445Sssszwic    mshr
2691d8f4dcbSJay  }
2701d8f4dcbSJay
271b92f8445Sssszwic  val prefetchMSHRs = (0 until nPrefetchMshr).map { i =>
272b92f8445Sssszwic    val mshr = Module(new ICacheMSHR(edge, false, nFetchMshr + i))
273b92f8445Sssszwic    mshr.io.flush  := io.flush
274b92f8445Sssszwic    mshr.io.fencei := io.fencei
275b92f8445Sssszwic    mshr.io.req <> prefetchDemux.io.out(i)
276b92f8445Sssszwic    mshr.io.lookUps(0).info.valid := io.fetch_req.valid
277b92f8445Sssszwic    mshr.io.lookUps(0).info.bits  := io.fetch_req.bits
278b92f8445Sssszwic    mshr.io.lookUps(1).info.valid := io.prefetch_req.valid
279b92f8445Sssszwic    mshr.io.lookUps(1).info.bits  := io.prefetch_req.bits
280b92f8445Sssszwic    mshr.io.victimWay             := io.victim.way
281b92f8445Sssszwic    prefetchArb.io.in(i) <> mshr.io.acquire
282b92f8445Sssszwic    mshr
2837052722fSJay  }
2847052722fSJay
28558c354d0Sssszwic  /**
28658c354d0Sssszwic    ******************************************************************************
287b92f8445Sssszwic    * MSHR look up
288b92f8445Sssszwic    * - look up all mshr
28958c354d0Sssszwic    ******************************************************************************
29058c354d0Sssszwic    */
291*cf7d6b7aSMuzi  val allMSHRs = fetchMSHRs ++ prefetchMSHRs
292b92f8445Sssszwic  val prefetchHitFetchReq = (io.prefetch_req.bits.blkPaddr === io.fetch_req.bits.blkPaddr) &&
293b92f8445Sssszwic    (io.prefetch_req.bits.vSetIdx === io.fetch_req.bits.vSetIdx) &&
294b92f8445Sssszwic    io.fetch_req.valid
295b92f8445Sssszwic  fetchHit    := allMSHRs.map(mshr => mshr.io.lookUps(0).hit).reduce(_ || _)
296b92f8445Sssszwic  prefetchHit := allMSHRs.map(mshr => mshr.io.lookUps(1).hit).reduce(_ || _) || prefetchHitFetchReq
29758c354d0Sssszwic
298b92f8445Sssszwic  /**
299b92f8445Sssszwic    ******************************************************************************
300b92f8445Sssszwic    * prefetchMSHRs priority
301b92f8445Sssszwic    * - The requests that enter the prefetchMSHRs earlier have a higher priority in issuing.
302b92f8445Sssszwic    * - The order of enqueuing is recorded in FIFO when requset enters MSHRs.
303b92f8445Sssszwic    * - The requests are dispatched in the order they are recorded in FIFO.
304b92f8445Sssszwic    ******************************************************************************
305b92f8445Sssszwic    */
306b92f8445Sssszwic  // When the FIFO is full, enqueue and dequeue operations do not occur at the same cycle.
307b92f8445Sssszwic  // So the depth of the FIFO is set to match the number of MSHRs.
308b92f8445Sssszwic  // val priorityFIFO = Module(new Queue(UInt(log2Ceil(nPrefetchMshr).W), nPrefetchMshr, hasFlush=true))
309b92f8445Sssszwic  val priorityFIFO = Module(new FIFOReg(UInt(log2Ceil(nPrefetchMshr).W), nPrefetchMshr, hasFlush = true))
310b92f8445Sssszwic  priorityFIFO.io.flush.get := io.flush || io.fencei
311b92f8445Sssszwic  priorityFIFO.io.enq.valid := prefetchDemux.io.in.fire
312b92f8445Sssszwic  priorityFIFO.io.enq.bits  := prefetchDemux.io.chosen
313b92f8445Sssszwic  priorityFIFO.io.deq.ready := prefetchArb.io.out.fire
314b92f8445Sssszwic  prefetchArb.io.sel        := priorityFIFO.io.deq.bits
315*cf7d6b7aSMuzi  assert(
316*cf7d6b7aSMuzi    !(priorityFIFO.io.enq.fire ^ prefetchDemux.io.in.fire),
317*cf7d6b7aSMuzi    "priorityFIFO.io.enq and io.prefetch_req must fire at the same cycle"
318*cf7d6b7aSMuzi  )
319*cf7d6b7aSMuzi  assert(
320*cf7d6b7aSMuzi    !(priorityFIFO.io.deq.fire ^ prefetchArb.io.out.fire),
321*cf7d6b7aSMuzi    "priorityFIFO.io.deq and prefetchArb.io.out must fire at the same cycle"
322*cf7d6b7aSMuzi  )
3237052722fSJay
324b92f8445Sssszwic  /**
325b92f8445Sssszwic    ******************************************************************************
326b92f8445Sssszwic    * Tilelink D channel (grant)
327b92f8445Sssszwic    ******************************************************************************
328b92f8445Sssszwic    */
329b92f8445Sssszwic  // cacheline register
330b92f8445Sssszwic  val readBeatCnt = RegInit(UInt(log2Up(refillCycles).W), 0.U)
331b92f8445Sssszwic  val respDataReg = RegInit(VecInit(Seq.fill(refillCycles)(0.U(beatBits.W))))
3321d8f4dcbSJay
333b92f8445Sssszwic  val wait_last = readBeatCnt === (refillCycles - 1).U
334b92f8445Sssszwic  when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits)) {
335b92f8445Sssszwic    respDataReg(readBeatCnt) := io.mem_grant.bits.data
33633a531f0Sxu_zh    readBeatCnt              := Mux(wait_last, 0.U, readBeatCnt + 1.U)
337b92f8445Sssszwic  }
338b92f8445Sssszwic
339b92f8445Sssszwic  // last transition finsh or corrupt
34033a531f0Sxu_zh  val last_fire = io.mem_grant.fire && edge.hasData(io.mem_grant.bits) && wait_last
341b92f8445Sssszwic
342b92f8445Sssszwic  val (_, _, refill_done, _) = edge.addr_inc(io.mem_grant)
343b92f8445Sssszwic  assert(!(refill_done ^ last_fire), "refill not done!")
344b92f8445Sssszwic  io.mem_grant.ready := true.B
345b92f8445Sssszwic
346b92f8445Sssszwic  val last_fire_r = RegNext(last_fire)
347b92f8445Sssszwic  val id_r        = RegNext(io.mem_grant.bits.source)
34833a531f0Sxu_zh
34933a531f0Sxu_zh  // if any beat is corrupt, the whole response (to mainPipe/metaArray/dataArray) is corrupt
35033a531f0Sxu_zh  val corrupt_r = RegInit(false.B)
35133a531f0Sxu_zh  when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits) && io.mem_grant.bits.corrupt) {
35233a531f0Sxu_zh    corrupt_r := true.B
35333a531f0Sxu_zh  }.elsewhen(io.fetch_resp.fire) {
35433a531f0Sxu_zh    corrupt_r := false.B
35533a531f0Sxu_zh  }
356b92f8445Sssszwic
357b92f8445Sssszwic  /**
358b92f8445Sssszwic    ******************************************************************************
359b92f8445Sssszwic    * invalid mshr when finish transition
360b92f8445Sssszwic    ******************************************************************************
361b92f8445Sssszwic    */
362*cf7d6b7aSMuzi  (0 until (nFetchMshr + nPrefetchMshr)).foreach(i => allMSHRs(i).io.invalid := last_fire_r && (id_r === i.U))
363b92f8445Sssszwic
364b92f8445Sssszwic  /**
365b92f8445Sssszwic    ******************************************************************************
366b92f8445Sssszwic    * response fetch and write SRAM
367b92f8445Sssszwic    ******************************************************************************
368b92f8445Sssszwic    */
369b92f8445Sssszwic  // get request information from MSHRs
370b92f8445Sssszwic  val allMSHRs_resp = VecInit(allMSHRs.map(mshr => mshr.io.resp))
371b92f8445Sssszwic  val mshr_resp     = allMSHRs_resp(id_r)
372b92f8445Sssszwic
373b92f8445Sssszwic  // get waymask from replacer when acquire fire
3747a63335aSxu_zh  io.victim.vSetIdx.valid := acquireArb.io.out.fire
375b92f8445Sssszwic  io.victim.vSetIdx.bits  := acquireArb.io.out.bits.vSetIdx
376b92f8445Sssszwic  val waymask = UIntToOH(mshr_resp.bits.waymask)
377adf97c94Sxu_zh  // NOTE: when flush/fencei, missUnit will still send response to mainPipe/prefetchPipe
378adf97c94Sxu_zh  //       this is intentional to fix timing (io.flush -> mainPipe/prefetchPipe s2_miss -> s2_ready -> ftq ready)
379adf97c94Sxu_zh  //       unnecessary response will be dropped by mainPipe/prefetchPipe/wayLookup since their sx_valid is set to false
380adf97c94Sxu_zh  val fetch_resp_valid = mshr_resp.valid && last_fire_r
381adf97c94Sxu_zh  // NOTE: but we should not write meta/dataArray when flush/fencei
382adf97c94Sxu_zh  val write_sram_valid = fetch_resp_valid && !corrupt_r && !io.flush && !io.fencei
383b92f8445Sssszwic
384b92f8445Sssszwic  // write SRAM
385*cf7d6b7aSMuzi  io.meta_write.bits.generate(
386*cf7d6b7aSMuzi    tag = getPhyTagFromBlk(mshr_resp.bits.blkPaddr),
387b92f8445Sssszwic    idx = mshr_resp.bits.vSetIdx,
388b92f8445Sssszwic    waymask = waymask,
389*cf7d6b7aSMuzi    bankIdx = mshr_resp.bits.vSetIdx(0)
390*cf7d6b7aSMuzi  )
391*cf7d6b7aSMuzi  io.data_write.bits.generate(
392*cf7d6b7aSMuzi    data = respDataReg.asUInt,
393b92f8445Sssszwic    idx = mshr_resp.bits.vSetIdx,
394b92f8445Sssszwic    waymask = waymask,
395*cf7d6b7aSMuzi    bankIdx = mshr_resp.bits.vSetIdx(0)
396*cf7d6b7aSMuzi  )
397b92f8445Sssszwic
398b92f8445Sssszwic  io.meta_write.valid := write_sram_valid
399b92f8445Sssszwic  io.data_write.valid := write_sram_valid
400b92f8445Sssszwic
401b92f8445Sssszwic  // response fetch
402b92f8445Sssszwic  io.fetch_resp.valid         := fetch_resp_valid
403b92f8445Sssszwic  io.fetch_resp.bits.blkPaddr := mshr_resp.bits.blkPaddr
404b92f8445Sssszwic  io.fetch_resp.bits.vSetIdx  := mshr_resp.bits.vSetIdx
405b92f8445Sssszwic  io.fetch_resp.bits.waymask  := waymask
406b92f8445Sssszwic  io.fetch_resp.bits.data     := respDataReg.asUInt
407b92f8445Sssszwic  io.fetch_resp.bits.corrupt  := corrupt_r
408b92f8445Sssszwic
409b92f8445Sssszwic  /**
410b92f8445Sssszwic    ******************************************************************************
411b92f8445Sssszwic    * performance counter
412b92f8445Sssszwic    ******************************************************************************
413b92f8445Sssszwic    */
414b92f8445Sssszwic  // Duplicate requests will be excluded.
415b92f8445Sssszwic  XSPerfAccumulate("enq_fetch_req", fetchDemux.io.in.fire)
416b92f8445Sssszwic  XSPerfAccumulate("enq_prefetch_req", prefetchDemux.io.in.fire)
417b92f8445Sssszwic
418b92f8445Sssszwic  /**
419b92f8445Sssszwic    ******************************************************************************
420b92f8445Sssszwic    * ChiselDB: record ICache SRAM write log
421b92f8445Sssszwic    ******************************************************************************
422b92f8445Sssszwic    */
423b92f8445Sssszwic  class ICacheSRAMDB(implicit p: Parameters) extends ICacheBundle {
424b92f8445Sssszwic    val blkPaddr = UInt((PAddrBits - blockOffBits).W)
425b92f8445Sssszwic    val vSetIdx  = UInt(idxBits.W)
426b92f8445Sssszwic    val waymask  = UInt(log2Ceil(nWays).W)
427b92f8445Sssszwic  }
428b92f8445Sssszwic
429*cf7d6b7aSMuzi  val isWriteICacheSRAMTable =
430*cf7d6b7aSMuzi    WireInit(Constantin.createRecord("isWriteICacheSRAMTable" + p(XSCoreParamsKey).HartId.toString))
431b92f8445Sssszwic  val ICacheSRAMTable = ChiselDB.createTable("ICacheSRAMTable" + p(XSCoreParamsKey).HartId.toString, new ICacheSRAMDB)
432b92f8445Sssszwic
433b92f8445Sssszwic  val ICacheSRAMDBDumpData = Wire(new ICacheSRAMDB)
434b92f8445Sssszwic  ICacheSRAMDBDumpData.blkPaddr := mshr_resp.bits.blkPaddr
435b92f8445Sssszwic  ICacheSRAMDBDumpData.vSetIdx  := mshr_resp.bits.vSetIdx
436b92f8445Sssszwic  ICacheSRAMDBDumpData.waymask  := OHToUInt(waymask)
437b92f8445Sssszwic  ICacheSRAMTable.log(
438b92f8445Sssszwic    data = ICacheSRAMDBDumpData,
439b92f8445Sssszwic    en = write_sram_valid,
440b92f8445Sssszwic    clock = clock,
441b92f8445Sssszwic    reset = reset
442b92f8445Sssszwic  )
443b92f8445Sssszwic
444b92f8445Sssszwic  /**
445b92f8445Sssszwic    ******************************************************************************
446b92f8445Sssszwic    * Difftest
447b92f8445Sssszwic    ******************************************************************************
448b92f8445Sssszwic    */
449afa866b1Sguohongyu  if (env.EnableDifftest) {
450a0c65233SYinan Xu    val difftest = DifftestModule(new DiffRefillEvent, dontCare = true)
4517d45a146SYinan Xu    difftest.coreid := io.hartId
4527d45a146SYinan Xu    difftest.index  := 0.U
453b92f8445Sssszwic    difftest.valid  := write_sram_valid
454b92f8445Sssszwic    difftest.addr   := Cat(mshr_resp.bits.blkPaddr, 0.U(blockOffBits.W))
455b92f8445Sssszwic    difftest.data   := respDataReg.asTypeOf(difftest.data)
456935edac4STang Haojin    difftest.idtfr  := DontCare
45741cb8b61SJenius  }
4581d8f4dcbSJay}
459