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