xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala (revision d6844cf062a1fd51c3173529c32f8318ee4395e7)
17052722fSJay/***************************************************************************************
26c106319Sxu_zh* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC)
36c106319Sxu_zh* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences
47052722fSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory
57052722fSJay*
67052722fSJay* XiangShan is licensed under Mulan PSL v2.
77052722fSJay* You can use this software according to the terms and conditions of the Mulan PSL v2.
87052722fSJay* You may obtain a copy of Mulan PSL v2 at:
97052722fSJay*          http://license.coscl.org.cn/MulanPSL2
107052722fSJay*
117052722fSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
127052722fSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
137052722fSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
147052722fSJay*
157052722fSJay* See the Mulan PSL v2 for more details.
167052722fSJay***************************************************************************************/
177052722fSJay
187052722fSJaypackage xiangshan.frontend.icache
197052722fSJay
207052722fSJayimport chisel3._
217052722fSJayimport chisel3.util._
22cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters
23cf7d6b7aSMuziimport utility._
24cf7d6b7aSMuziimport xiangshan.SoftIfetchPrefetchBundle
257052722fSJayimport xiangshan.cache.mmu._
267052722fSJayimport xiangshan.frontend._
277052722fSJay
287052722fSJayabstract class IPrefetchBundle(implicit p: Parameters) extends ICacheBundle
297052722fSJayabstract class IPrefetchModule(implicit p: Parameters) extends ICacheModule
307052722fSJay
312c9f4a9fSxu_zhclass IPrefetchReq(implicit p: Parameters) extends IPrefetchBundle {
322c9f4a9fSxu_zh  val startAddr:        UInt   = UInt(VAddrBits.W)
332c9f4a9fSxu_zh  val nextlineStart:    UInt   = UInt(VAddrBits.W)
342c9f4a9fSxu_zh  val ftqIdx:           FtqPtr = new FtqPtr
352c9f4a9fSxu_zh  val isSoftPrefetch:   Bool   = Bool()
36fbdb359dSMuzi  val backendException: UInt   = UInt(ExceptionType.width.W)
372c9f4a9fSxu_zh  def crossCacheline:   Bool   = startAddr(blockOffBits - 1) === 1.U
382c9f4a9fSxu_zh
392c9f4a9fSxu_zh  def fromFtqICacheInfo(info: FtqICacheInfo): IPrefetchReq = {
402c9f4a9fSxu_zh    this.startAddr      := info.startAddr
412c9f4a9fSxu_zh    this.nextlineStart  := info.nextlineStart
422c9f4a9fSxu_zh    this.ftqIdx         := info.ftqIdx
432c9f4a9fSxu_zh    this.isSoftPrefetch := false.B
442c9f4a9fSxu_zh    this
452c9f4a9fSxu_zh  }
462c9f4a9fSxu_zh
472c9f4a9fSxu_zh  def fromSoftPrefetch(req: SoftIfetchPrefetchBundle): IPrefetchReq = {
482c9f4a9fSxu_zh    this.startAddr      := req.vaddr
492c9f4a9fSxu_zh    this.nextlineStart  := req.vaddr + (1 << blockOffBits).U
502c9f4a9fSxu_zh    this.ftqIdx         := DontCare
512c9f4a9fSxu_zh    this.isSoftPrefetch := true.B
522c9f4a9fSxu_zh    this
532c9f4a9fSxu_zh  }
542c9f4a9fSxu_zh}
552c9f4a9fSxu_zh
5688895b11Sxu_zhclass IPrefetchIO(implicit p: Parameters) extends IPrefetchBundle {
57b92f8445Sssszwic  // control
58415fcbe2Sxu_zh  val csr_pf_enable: Bool = Input(Bool())
596c106319Sxu_zh  val ecc_enable:    Bool = Input(Bool())
60415fcbe2Sxu_zh  val flush:         Bool = Input(Bool())
6158c354d0Sssszwic
62415fcbe2Sxu_zh  val req:            DecoupledIO[IPrefetchReq]  = Flipped(Decoupled(new IPrefetchReq))
63415fcbe2Sxu_zh  val flushFromBpu:   BpuFlushInfo               = Flipped(new BpuFlushInfo)
64415fcbe2Sxu_zh  val itlb:           Vec[TlbRequestIO]          = Vec(PortNumber, new TlbRequestIO)
65fad7803dSxu_zh  val itlbFlushPipe:  Bool                       = Bool()
66415fcbe2Sxu_zh  val pmp:            Vec[ICachePMPBundle]       = Vec(PortNumber, new ICachePMPBundle)
67415fcbe2Sxu_zh  val metaRead:       ICacheMetaReqBundle        = new ICacheMetaReqBundle
68415fcbe2Sxu_zh  val MSHRReq:        DecoupledIO[ICacheMissReq] = DecoupledIO(new ICacheMissReq)
69415fcbe2Sxu_zh  val MSHRResp:       Valid[ICacheMissResp]      = Flipped(ValidIO(new ICacheMissResp))
70415fcbe2Sxu_zh  val wayLookupWrite: DecoupledIO[WayLookupInfo] = DecoupledIO(new WayLookupInfo)
717052722fSJay}
727052722fSJay
736c106319Sxu_zhclass IPrefetchPipe(implicit p: Parameters) extends IPrefetchModule with HasICacheECCHelper {
7488895b11Sxu_zh  val io: IPrefetchIO = IO(new IPrefetchIO)
757052722fSJay
76415fcbe2Sxu_zh  private val (toITLB, fromITLB) = (io.itlb.map(_.req), io.itlb.map(_.resp))
77415fcbe2Sxu_zh  private val (toPMP, fromPMP)   = (io.pmp.map(_.req), io.pmp.map(_.resp))
78415fcbe2Sxu_zh  private val (toMeta, fromMeta) = (io.metaRead.toIMeta, io.metaRead.fromIMeta)
79415fcbe2Sxu_zh  private val (toMSHR, fromMSHR) = (io.MSHRReq, io.MSHRResp)
80415fcbe2Sxu_zh  private val toWayLookup        = io.wayLookupWrite
817052722fSJay
82415fcbe2Sxu_zh  private val s0_fire, s1_fire, s2_fire            = WireInit(false.B)
83415fcbe2Sxu_zh  private val s1_ready, s2_ready                   = WireInit(false.B)
84415fcbe2Sxu_zh  private val s0_flush, s1_flush, s2_flush         = WireInit(false.B)
85415fcbe2Sxu_zh  private val from_bpu_s0_flush, from_bpu_s1_flush = WireInit(false.B)
867052722fSJay
87cb6e5d3cSssszwic  /**
88cb6e5d3cSssszwic    ******************************************************************************
89cb6e5d3cSssszwic    * IPrefetch Stage 0
90b92f8445Sssszwic    * - 1. receive ftq req
91b92f8445Sssszwic    * - 2. send req to ITLB
92b92f8445Sssszwic    * - 3. send req to Meta SRAM
93cb6e5d3cSssszwic    ******************************************************************************
94cb6e5d3cSssszwic    */
95415fcbe2Sxu_zh  private val s0_valid = io.req.valid
96cb6e5d3cSssszwic
97b92f8445Sssszwic  /**
98b92f8445Sssszwic    ******************************************************************************
99b92f8445Sssszwic    * receive ftq req
100b92f8445Sssszwic    ******************************************************************************
101b92f8445Sssszwic    */
102415fcbe2Sxu_zh  private val s0_req_vaddr        = VecInit(Seq(io.req.bits.startAddr, io.req.bits.nextlineStart))
103415fcbe2Sxu_zh  private val s0_req_ftqIdx       = io.req.bits.ftqIdx
104415fcbe2Sxu_zh  private val s0_isSoftPrefetch   = io.req.bits.isSoftPrefetch
105415fcbe2Sxu_zh  private val s0_doubleline       = io.req.bits.crossCacheline
106415fcbe2Sxu_zh  private val s0_req_vSetIdx      = s0_req_vaddr.map(get_idx)
107415fcbe2Sxu_zh  private val s0_backendException = VecInit(Seq.fill(PortNumber)(io.req.bits.backendException))
1087052722fSJay
1092c9f4a9fSxu_zh  from_bpu_s0_flush := !s0_isSoftPrefetch && (io.flushFromBpu.shouldFlushByStage2(s0_req_ftqIdx) ||
1102c9f4a9fSxu_zh    io.flushFromBpu.shouldFlushByStage3(s0_req_ftqIdx))
111b92f8445Sssszwic  s0_flush := io.flush || from_bpu_s0_flush || s1_flush
1127052722fSJay
113415fcbe2Sxu_zh  private val s0_can_go = s1_ready && toITLB(0).ready && toITLB(1).ready && toMeta.ready
1142c9f4a9fSxu_zh  io.req.ready := s0_can_go
1157052722fSJay
116b92f8445Sssszwic  s0_fire := s0_valid && s0_can_go && !s0_flush
117cb6e5d3cSssszwic
118cb6e5d3cSssszwic  /**
119cb6e5d3cSssszwic    ******************************************************************************
120cb6e5d3cSssszwic    * IPrefetch Stage 1
121b92f8445Sssszwic    * - 1. Receive resp from ITLB
122b92f8445Sssszwic    * - 2. Receive resp from IMeta and check
123b92f8445Sssszwic    * - 3. Monitor the requests from missUnit to write to SRAM.
124415fcbe2Sxu_zh    * - 4. Write wayLookup
125cb6e5d3cSssszwic    ******************************************************************************
126cb6e5d3cSssszwic    */
127415fcbe2Sxu_zh  private val s1_valid =
128415fcbe2Sxu_zh    generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = s1_flush, lastFlush = false.B)
129cb6e5d3cSssszwic
130415fcbe2Sxu_zh  private val s1_req_vaddr        = RegEnable(s0_req_vaddr, 0.U.asTypeOf(s0_req_vaddr), s0_fire)
131415fcbe2Sxu_zh  private val s1_isSoftPrefetch   = RegEnable(s0_isSoftPrefetch, 0.U.asTypeOf(s0_isSoftPrefetch), s0_fire)
132415fcbe2Sxu_zh  private val s1_doubleline       = RegEnable(s0_doubleline, 0.U.asTypeOf(s0_doubleline), s0_fire)
133415fcbe2Sxu_zh  private val s1_req_ftqIdx       = RegEnable(s0_req_ftqIdx, 0.U.asTypeOf(s0_req_ftqIdx), s0_fire)
134415fcbe2Sxu_zh  private val s1_req_vSetIdx      = VecInit(s1_req_vaddr.map(get_idx))
135415fcbe2Sxu_zh  private val s1_backendException = RegEnable(s0_backendException, 0.U.asTypeOf(s0_backendException), s0_fire)
1367052722fSJay
137415fcbe2Sxu_zh  private val m_idle :: m_itlbResend :: m_metaResend :: m_enqWay :: m_enterS2 :: Nil = Enum(5)
138415fcbe2Sxu_zh
139415fcbe2Sxu_zh  private val state      = RegInit(m_idle)
140415fcbe2Sxu_zh  private val next_state = WireDefault(state)
141415fcbe2Sxu_zh  private val s0_fire_r  = RegNext(s0_fire)
142b92f8445Sssszwic  dontTouch(state)
143b92f8445Sssszwic  dontTouch(next_state)
144b92f8445Sssszwic  state := next_state
1457052722fSJay
146b92f8445Sssszwic  /**
147b92f8445Sssszwic    ******************************************************************************
148b92f8445Sssszwic    * resend itlb req if miss
149b92f8445Sssszwic    ******************************************************************************
150b92f8445Sssszwic    */
151415fcbe2Sxu_zh  private val s1_wait_itlb = RegInit(VecInit(Seq.fill(PortNumber)(false.B)))
152b92f8445Sssszwic  (0 until PortNumber).foreach { i =>
153b92f8445Sssszwic    when(s1_flush) {
154b92f8445Sssszwic      s1_wait_itlb(i) := false.B
155b92f8445Sssszwic    }.elsewhen(RegNext(s0_fire) && fromITLB(i).bits.miss) {
156b92f8445Sssszwic      s1_wait_itlb(i) := true.B
157b92f8445Sssszwic    }.elsewhen(s1_wait_itlb(i) && !fromITLB(i).bits.miss) {
158b92f8445Sssszwic      s1_wait_itlb(i) := false.B
159b92f8445Sssszwic    }
160b92f8445Sssszwic  }
161415fcbe2Sxu_zh  private val s1_need_itlb = VecInit(Seq(
162cf7d6b7aSMuzi    (RegNext(s0_fire) || s1_wait_itlb(0)) && fromITLB(0).bits.miss,
163cf7d6b7aSMuzi    (RegNext(s0_fire) || s1_wait_itlb(1)) && fromITLB(1).bits.miss && s1_doubleline
164cf7d6b7aSMuzi  ))
165415fcbe2Sxu_zh  private val tlb_valid_pulse = VecInit(Seq(
166cf7d6b7aSMuzi    (RegNext(s0_fire) || s1_wait_itlb(0)) && !fromITLB(0).bits.miss,
167cf7d6b7aSMuzi    (RegNext(s0_fire) || s1_wait_itlb(1)) && !fromITLB(1).bits.miss && s1_doubleline
168cf7d6b7aSMuzi  ))
169415fcbe2Sxu_zh  private val tlb_valid_latch =
170cf7d6b7aSMuzi    VecInit((0 until PortNumber).map(i => ValidHoldBypass(tlb_valid_pulse(i), s1_fire, flush = s1_flush)))
171415fcbe2Sxu_zh  private val itlb_finish = tlb_valid_latch(0) && (!s1_doubleline || tlb_valid_latch(1))
1727052722fSJay
173415fcbe2Sxu_zh  (0 until PortNumber).foreach { i =>
174b92f8445Sssszwic    toITLB(i).valid             := s1_need_itlb(i) || (s0_valid && (if (i == 0) true.B else s0_doubleline))
175b92f8445Sssszwic    toITLB(i).bits              := DontCare
176b92f8445Sssszwic    toITLB(i).bits.size         := 3.U
177b92f8445Sssszwic    toITLB(i).bits.vaddr        := Mux(s1_need_itlb(i), s1_req_vaddr(i), s0_req_vaddr(i))
178b92f8445Sssszwic    toITLB(i).bits.debug.pc     := Mux(s1_need_itlb(i), s1_req_vaddr(i), s0_req_vaddr(i))
179b92f8445Sssszwic    toITLB(i).bits.cmd          := TlbCmd.exec
180b92f8445Sssszwic    toITLB(i).bits.no_translate := false.B
181b92f8445Sssszwic  }
182b92f8445Sssszwic  fromITLB.foreach(_.ready := true.B)
183b92f8445Sssszwic  io.itlb.foreach(_.req_kill := false.B)
1847052722fSJay
185b92f8445Sssszwic  /**
186b92f8445Sssszwic    ******************************************************************************
187b92f8445Sssszwic    * Receive resp from ITLB
188b92f8445Sssszwic    ******************************************************************************
189b92f8445Sssszwic    */
190415fcbe2Sxu_zh  private val s1_req_paddr_wire = VecInit(fromITLB.map(_.bits.paddr(0)))
191415fcbe2Sxu_zh  private val s1_req_paddr_reg = VecInit((0 until PortNumber).map { i =>
19288895b11Sxu_zh    RegEnable(s1_req_paddr_wire(i), 0.U(PAddrBits.W), tlb_valid_pulse(i))
193415fcbe2Sxu_zh  })
194415fcbe2Sxu_zh  private val s1_req_paddr = VecInit((0 until PortNumber).map { i =>
19588895b11Sxu_zh    Mux(tlb_valid_pulse(i), s1_req_paddr_wire(i), s1_req_paddr_reg(i))
196415fcbe2Sxu_zh  })
197415fcbe2Sxu_zh  private val s1_req_gpaddr_tmp = VecInit((0 until PortNumber).map { i =>
198cf7d6b7aSMuzi    ResultHoldBypass(
199cf7d6b7aSMuzi      valid = tlb_valid_pulse(i),
200dd980d61SXu, Zefan      // NOTE: we dont use GPAddrBits or XLEN here, refer to ICacheMainPipe.scala L43-48 and PR#3795
201dd980d61SXu, Zefan      init = 0.U(PAddrBitsMax.W),
202cf7d6b7aSMuzi      data = fromITLB(i).bits.gpaddr(0)
203cf7d6b7aSMuzi    )
204415fcbe2Sxu_zh  })
205415fcbe2Sxu_zh  private val s1_req_isForVSnonLeafPTE_tmp = VecInit((0 until PortNumber).map { i =>
206cf7d6b7aSMuzi    ResultHoldBypass(
207cf7d6b7aSMuzi      valid = tlb_valid_pulse(i),
208cf7d6b7aSMuzi      init = 0.U.asTypeOf(fromITLB(i).bits.isForVSnonLeafPTE),
209cf7d6b7aSMuzi      data = fromITLB(i).bits.isForVSnonLeafPTE
210cf7d6b7aSMuzi    )
211415fcbe2Sxu_zh  })
212*d6844cf0Sxu_zh  private val s1_itlb_exception_tmp = VecInit((0 until PortNumber).map { i =>
213cf7d6b7aSMuzi    ResultHoldBypass(
214cf7d6b7aSMuzi      valid = tlb_valid_pulse(i),
215cf7d6b7aSMuzi      init = 0.U(ExceptionType.width.W),
216cf7d6b7aSMuzi      data = ExceptionType.fromTlbResp(fromITLB(i).bits)
217cf7d6b7aSMuzi    )
218415fcbe2Sxu_zh  })
219415fcbe2Sxu_zh  private val s1_itlb_pbmt = VecInit((0 until PortNumber).map { i =>
220cf7d6b7aSMuzi    ResultHoldBypass(
221cf7d6b7aSMuzi      valid = tlb_valid_pulse(i),
222cf7d6b7aSMuzi      init = 0.U.asTypeOf(fromITLB(i).bits.pbmt(0)),
223cf7d6b7aSMuzi      data = fromITLB(i).bits.pbmt(0)
224cf7d6b7aSMuzi    )
225415fcbe2Sxu_zh  })
226*d6844cf0Sxu_zh
227*d6844cf0Sxu_zh  // merge backend exception and itlb exception
228*d6844cf0Sxu_zh  // for area concern, we don't have 64 bits vaddr in frontend, but spec asks page fault when high bits are not all 0/1
229*d6844cf0Sxu_zh  // this check is finished in backend, and passed to frontend with redirect, we see it as a part of itlb exception
230*d6844cf0Sxu_zh  private val s1_itlb_exception = ExceptionType.merge(
231*d6844cf0Sxu_zh    s1_backendException,
232*d6844cf0Sxu_zh    s1_itlb_exception_tmp
233*d6844cf0Sxu_zh  )
234*d6844cf0Sxu_zh  // debug
235*d6844cf0Sxu_zh  dontTouch(s1_itlb_exception_tmp)
236*d6844cf0Sxu_zh  dontTouch(s1_itlb_exception)
237*d6844cf0Sxu_zh
238415fcbe2Sxu_zh  private val s1_itlb_exception_gpf = VecInit(s1_itlb_exception.map(_ === ExceptionType.gpf))
239b92f8445Sssszwic
24091946104Sxu_zh  /* Select gpaddr with the first gpf
24191946104Sxu_zh   * Note: the backend wants the base guest physical address of a fetch block
24291946104Sxu_zh   *       for port(i), its base gpaddr is actually (gpaddr - i * blocksize)
24391946104Sxu_zh   *       see GPAMem: https://github.com/OpenXiangShan/XiangShan/blob/344cf5d55568dd40cd658a9ee66047a505eeb504/src/main/scala/xiangshan/backend/GPAMem.scala#L33-L34
24491946104Sxu_zh   *       see also: https://github.com/OpenXiangShan/XiangShan/blob/344cf5d55568dd40cd658a9ee66047a505eeb504/src/main/scala/xiangshan/frontend/IFU.scala#L374-L375
24591946104Sxu_zh   */
246415fcbe2Sxu_zh  private val s1_req_gpaddr = PriorityMuxDefault(
24788895b11Sxu_zh    s1_itlb_exception_gpf zip (0 until PortNumber).map(i => s1_req_gpaddr_tmp(i) - (i << blockOffBits).U),
24891946104Sxu_zh    0.U.asTypeOf(s1_req_gpaddr_tmp(0))
24991946104Sxu_zh  )
25091946104Sxu_zh
251415fcbe2Sxu_zh  private val s1_req_isForVSnonLeafPTE = PriorityMuxDefault(
252ad415ae0SXiaokun-Pei    s1_itlb_exception_gpf zip s1_req_isForVSnonLeafPTE_tmp,
253ad415ae0SXiaokun-Pei    0.U.asTypeOf(s1_req_isForVSnonLeafPTE_tmp(0))
254ad415ae0SXiaokun-Pei  )
255ad415ae0SXiaokun-Pei
256b92f8445Sssszwic  /**
257b92f8445Sssszwic    ******************************************************************************
258b92f8445Sssszwic    * resend metaArray read req when itlb miss finish
259b92f8445Sssszwic    ******************************************************************************
260b92f8445Sssszwic    */
261415fcbe2Sxu_zh  private val s1_need_meta = ((state === m_itlbResend) && itlb_finish) || (state === m_metaResend)
262b92f8445Sssszwic  toMeta.valid             := s1_need_meta || s0_valid
263b92f8445Sssszwic  toMeta.bits              := DontCare
264b92f8445Sssszwic  toMeta.bits.isDoubleLine := Mux(s1_need_meta, s1_doubleline, s0_doubleline)
265b92f8445Sssszwic
266415fcbe2Sxu_zh  (0 until PortNumber).foreach { i =>
267b92f8445Sssszwic    toMeta.bits.vSetIdx(i) := Mux(s1_need_meta, s1_req_vSetIdx(i), s0_req_vSetIdx(i))
268cb6e5d3cSssszwic  }
269cb6e5d3cSssszwic
270cb6e5d3cSssszwic  /**
271cb6e5d3cSssszwic    ******************************************************************************
272b92f8445Sssszwic    * Receive resp from IMeta and check
273cb6e5d3cSssszwic    ******************************************************************************
274cb6e5d3cSssszwic    */
275415fcbe2Sxu_zh  private val s1_req_ptags = VecInit(s1_req_paddr.map(get_phy_tag))
276cb6e5d3cSssszwic
277415fcbe2Sxu_zh  private val s1_meta_ptags  = fromMeta.tags
278415fcbe2Sxu_zh  private val s1_meta_valids = fromMeta.entryValid
2799bba777eSssszwic
280415fcbe2Sxu_zh  private def getWaymask(paddrs: Vec[UInt]): Vec[UInt] = {
28188895b11Sxu_zh    val ptags = paddrs.map(get_phy_tag)
282cf7d6b7aSMuzi    val tag_eq_vec =
283cf7d6b7aSMuzi      VecInit((0 until PortNumber).map(p => VecInit((0 until nWays).map(w => s1_meta_ptags(p)(w) === ptags(p)))))
284415fcbe2Sxu_zh    val tag_match_vec = VecInit((0 until PortNumber).map { k =>
285cf7d6b7aSMuzi      VecInit(tag_eq_vec(k).zipWithIndex.map { case (way_tag_eq, w) => way_tag_eq && s1_meta_valids(k)(w) })
286415fcbe2Sxu_zh    })
287b92f8445Sssszwic    val waymasks = VecInit(tag_match_vec.map(_.asUInt))
288b92f8445Sssszwic    waymasks
289cb6e5d3cSssszwic  }
2909bba777eSssszwic
291415fcbe2Sxu_zh  private val s1_SRAM_waymasks = VecInit((0 until PortNumber).map { port =>
292415fcbe2Sxu_zh    Mux(tlb_valid_pulse(port), getWaymask(s1_req_paddr_wire)(port), getWaymask(s1_req_paddr_reg)(port))
2935ce94708Sxu_zh  })
294b92f8445Sssszwic
2958966a895Sxu_zh  // select ecc code
2968966a895Sxu_zh  /* NOTE:
2978966a895Sxu_zh   * When ECC check fails, s1_waymasks may be corrupted, so this selected meta_codes may be wrong.
2988966a895Sxu_zh   * However, we can guarantee that the request sent to the l2 cache and the response to the IFU are both correct,
2998966a895Sxu_zh   * considering the probability of bit flipping abnormally is very small, consider there's up to 1 bit being wrong:
3008966a895Sxu_zh   * 1. miss -> fake hit: The wrong bit in s1_waymasks was set to true.B, thus selects the wrong meta_codes,
3018966a895Sxu_zh   *                      but we can detect this by checking whether `encodeMetaECC(req_ptags) === meta_codes`.
3028966a895Sxu_zh   * 2. hit -> fake multi-hit: In normal situation, multi-hit never happens, so multi-hit indicates ECC failure,
3038966a895Sxu_zh   *                           we can detect this by checking whether `PopCount(waymasks) <= 1.U`,
3048966a895Sxu_zh   *                           and meta_codes is not important in this situation.
3058966a895Sxu_zh   * 3. hit -> fake miss: We can't detect this, but we can (pre)fetch the correct data from L2 cache, so it's not a problem.
306415fcbe2Sxu_zh   * 4. hit -> hit / miss -> miss: ECC failure happens in an irrelevant way, so we don't care about it this time.
3078966a895Sxu_zh   */
308415fcbe2Sxu_zh  private val s1_SRAM_meta_codes = VecInit((0 until PortNumber).map { port =>
3095ce94708Sxu_zh    Mux1H(s1_SRAM_waymasks(port), fromMeta.codes(port))
3108966a895Sxu_zh  })
3118966a895Sxu_zh
312b92f8445Sssszwic  /**
313b92f8445Sssszwic    ******************************************************************************
3145ce94708Sxu_zh    * update waymasks and meta_codes according to MSHR update data
3155ce94708Sxu_zh    ******************************************************************************
3165ce94708Sxu_zh    */
317415fcbe2Sxu_zh  private def updateMetaInfo(mask: UInt, vSetIdx: UInt, ptag: UInt, code: UInt): (UInt, UInt) = {
3185ce94708Sxu_zh    require(mask.getWidth == nWays)
3195ce94708Sxu_zh    val new_mask  = WireInit(mask)
3205ce94708Sxu_zh    val new_code  = WireInit(code)
3215ce94708Sxu_zh    val valid     = fromMSHR.valid && !fromMSHR.bits.corrupt
3225ce94708Sxu_zh    val vset_same = fromMSHR.bits.vSetIdx === vSetIdx
3235ce94708Sxu_zh    val ptag_same = getPhyTagFromBlk(fromMSHR.bits.blkPaddr) === ptag
3245ce94708Sxu_zh    val way_same  = fromMSHR.bits.waymask === mask
3255ce94708Sxu_zh    when(valid && vset_same) {
3265ce94708Sxu_zh      when(ptag_same) {
3275ce94708Sxu_zh        new_mask := fromMSHR.bits.waymask
3285ce94708Sxu_zh        // also update meta_codes
3295ce94708Sxu_zh        // we have getPhyTagFromBlk(fromMSHR.bits.blkPaddr) === ptag, so we can use ptag directly for better timing
3305ce94708Sxu_zh        new_code := encodeMetaECC(ptag)
3315ce94708Sxu_zh      }.elsewhen(way_same) {
3325ce94708Sxu_zh        new_mask := 0.U
333415fcbe2Sxu_zh        // we don't care about new_code, since it's not used for a missed request
3345ce94708Sxu_zh      }
3355ce94708Sxu_zh    }
3365ce94708Sxu_zh    (new_mask, new_code)
3375ce94708Sxu_zh  }
3385ce94708Sxu_zh
339415fcbe2Sxu_zh  private val s1_SRAM_valid   = s0_fire_r || RegNext(s1_need_meta && toMeta.ready)
340415fcbe2Sxu_zh  private val s1_MSHR_valid   = fromMSHR.valid && !fromMSHR.bits.corrupt
341415fcbe2Sxu_zh  private val s1_waymasks     = WireInit(VecInit(Seq.fill(PortNumber)(0.U(nWays.W))))
342415fcbe2Sxu_zh  private val s1_waymasks_r   = RegEnable(s1_waymasks, 0.U.asTypeOf(s1_waymasks), s1_SRAM_valid || s1_MSHR_valid)
343415fcbe2Sxu_zh  private val s1_meta_codes   = WireInit(VecInit(Seq.fill(PortNumber)(0.U(ICacheMetaCodeBits.W))))
344415fcbe2Sxu_zh  private val s1_meta_codes_r = RegEnable(s1_meta_codes, 0.U.asTypeOf(s1_meta_codes), s1_SRAM_valid || s1_MSHR_valid)
3455ce94708Sxu_zh
3465ce94708Sxu_zh  // update waymasks and meta_codes
3475ce94708Sxu_zh  (0 until PortNumber).foreach { i =>
3485ce94708Sxu_zh    val old_waymask    = Mux(s1_SRAM_valid, s1_SRAM_waymasks(i), s1_waymasks_r(i))
3495ce94708Sxu_zh    val old_meta_codes = Mux(s1_SRAM_valid, s1_SRAM_meta_codes(i), s1_meta_codes_r(i))
350415fcbe2Sxu_zh    val new_info       = updateMetaInfo(old_waymask, s1_req_vSetIdx(i), s1_req_ptags(i), old_meta_codes)
3515ce94708Sxu_zh    s1_waymasks(i)   := new_info._1
3525ce94708Sxu_zh    s1_meta_codes(i) := new_info._2
3535ce94708Sxu_zh  }
3545ce94708Sxu_zh
3555ce94708Sxu_zh  /**
3565ce94708Sxu_zh    ******************************************************************************
357415fcbe2Sxu_zh    * send enqueue req to WayLookup
358b92f8445Sssszwic    ******** **********************************************************************
359b92f8445Sssszwic    */
360b92f8445Sssszwic  // Disallow enqueuing wayLookup when SRAM write occurs.
3612c9f4a9fSxu_zh  toWayLookup.valid := ((state === m_enqWay) || ((state === m_idle) && itlb_finish)) &&
3622c9f4a9fSxu_zh    !s1_flush && !fromMSHR.valid && !s1_isSoftPrefetch // do not enqueue soft prefetch
363b92f8445Sssszwic  toWayLookup.bits.vSetIdx           := s1_req_vSetIdx
364b92f8445Sssszwic  toWayLookup.bits.waymask           := s1_waymasks
365b92f8445Sssszwic  toWayLookup.bits.ptag              := s1_req_ptags
366b92f8445Sssszwic  toWayLookup.bits.gpaddr            := s1_req_gpaddr
367ad415ae0SXiaokun-Pei  toWayLookup.bits.isForVSnonLeafPTE := s1_req_isForVSnonLeafPTE
3688966a895Sxu_zh  toWayLookup.bits.meta_codes        := s1_meta_codes
3691a5af821Sxu_zh  (0 until PortNumber).foreach { i =>
370415fcbe2Sxu_zh    // exception in first line is always valid, in second line is valid iff is doubleline request
371415fcbe2Sxu_zh    val excpValid = if (i == 0) true.B else s1_doubleline
372415fcbe2Sxu_zh    // Send s1_itlb_exception to WayLookup (instead of s1_exception_out) for better timing.
373415fcbe2Sxu_zh    // Will check pmp again in mainPipe
374*d6844cf0Sxu_zh    toWayLookup.bits.itlb_exception(i) := Mux(
375*d6844cf0Sxu_zh      excpValid,
376*d6844cf0Sxu_zh      s1_itlb_exception(i), // includes backend exception
377*d6844cf0Sxu_zh      ExceptionType.none
378*d6844cf0Sxu_zh    )
379002c10a4SYanqin Li    toWayLookup.bits.itlb_pbmt(i) := Mux(excpValid, s1_itlb_pbmt(i), Pbmt.pma)
3801a5af821Sxu_zh  }
381b92f8445Sssszwic
382415fcbe2Sxu_zh  private val s1_waymasks_vec = s1_waymasks.map(_.asTypeOf(Vec(nWays, Bool())))
383b92f8445Sssszwic  when(toWayLookup.fire) {
384cf7d6b7aSMuzi    assert(
385cf7d6b7aSMuzi      PopCount(s1_waymasks_vec(0)) <= 1.U && (PopCount(s1_waymasks_vec(1)) <= 1.U || !s1_doubleline),
386415fcbe2Sxu_zh      "Multi-hit:\nport0: count=%d ptag=0x%x vSet=0x%x vaddr=0x%x\nport1: count=%d ptag=0x%x vSet=0x%x vaddr=0x%x",
387cf7d6b7aSMuzi      PopCount(s1_waymasks_vec(0)) > 1.U,
388cf7d6b7aSMuzi      s1_req_ptags(0),
389cf7d6b7aSMuzi      get_idx(s1_req_vaddr(0)),
390cf7d6b7aSMuzi      s1_req_vaddr(0),
391cf7d6b7aSMuzi      PopCount(s1_waymasks_vec(1)) > 1.U && s1_doubleline,
392cf7d6b7aSMuzi      s1_req_ptags(1),
393cf7d6b7aSMuzi      get_idx(s1_req_vaddr(1)),
394cf7d6b7aSMuzi      s1_req_vaddr(1)
395cf7d6b7aSMuzi    )
396b92f8445Sssszwic  }
397b92f8445Sssszwic
398b92f8445Sssszwic  /**
399b92f8445Sssszwic    ******************************************************************************
400b92f8445Sssszwic    * PMP check
401b92f8445Sssszwic    ******************************************************************************
402b92f8445Sssszwic    */
40388895b11Sxu_zh  toPMP.zipWithIndex.foreach { case (p, i) =>
40488895b11Sxu_zh    // if itlb has exception, paddr can be invalid, therefore pmp check can be skipped
405dd02bc3fSxu_zh    p.valid     := s1_valid // !ExceptionType.hasException(s1_itlb_exception(i))
406b92f8445Sssszwic    p.bits.addr := s1_req_paddr(i)
407415fcbe2Sxu_zh    p.bits.size := 3.U
408b92f8445Sssszwic    p.bits.cmd  := TlbCmd.exec
409b92f8445Sssszwic  }
410415fcbe2Sxu_zh  private val s1_pmp_exception = VecInit(fromPMP.map(ExceptionType.fromPMPResp))
411415fcbe2Sxu_zh  private val s1_pmp_mmio      = VecInit(fromPMP.map(_.mmio))
41288895b11Sxu_zh
4138966a895Sxu_zh  // merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next
4148966a895Sxu_zh  // for timing consideration, meta_corrupt is not merged, and it will NOT cancel prefetch
415415fcbe2Sxu_zh  private val s1_exception_out = ExceptionType.merge(
416*d6844cf0Sxu_zh    s1_itlb_exception, // includes backend exception
4178966a895Sxu_zh    s1_pmp_exception
418f80535c3Sxu_zh  )
419b92f8445Sssszwic
420002c10a4SYanqin Li  // merge pmp mmio and itlb pbmt
421415fcbe2Sxu_zh  private val s1_mmio = VecInit((s1_pmp_mmio zip s1_itlb_pbmt).map { case (mmio, pbmt) =>
422002c10a4SYanqin Li    mmio || Pbmt.isUncache(pbmt)
423002c10a4SYanqin Li  })
424002c10a4SYanqin Li
425b92f8445Sssszwic  /**
426b92f8445Sssszwic    ******************************************************************************
427b92f8445Sssszwic    * state machine
428b92f8445Sssszwic    ******** **********************************************************************
429b92f8445Sssszwic    */
430b92f8445Sssszwic
431b92f8445Sssszwic  switch(state) {
432b92f8445Sssszwic    is(m_idle) {
4332c9f4a9fSxu_zh      when(s1_valid) {
4342c9f4a9fSxu_zh        when(!itlb_finish) {
435b92f8445Sssszwic          next_state := m_itlbResend
4368c57174eSxu_zh        }.elsewhen(!toWayLookup.fire) { // itlb_finish
437b92f8445Sssszwic          next_state := m_enqWay
4388c57174eSxu_zh        }.elsewhen(!s2_ready) { // itlb_finish && toWayLookup.fire
439b92f8445Sssszwic          next_state := m_enterS2
4402c9f4a9fSxu_zh        } // .otherwise { next_state := m_idle }
4412c9f4a9fSxu_zh      }   // .otherwise { next_state := m_idle }  // !s1_valid
442b92f8445Sssszwic    }
443b92f8445Sssszwic    is(m_itlbResend) {
4442c9f4a9fSxu_zh      when(itlb_finish) {
4452c9f4a9fSxu_zh        when(!toMeta.ready) {
446b92f8445Sssszwic          next_state := m_metaResend
4478c57174eSxu_zh        }.otherwise { // toMeta.ready
448b92f8445Sssszwic          next_state := m_enqWay
449b92f8445Sssszwic        }
4502c9f4a9fSxu_zh      } // .otherwise { next_state := m_itlbResend }  // !itlb_finish
451b92f8445Sssszwic    }
452b92f8445Sssszwic    is(m_metaResend) {
453b92f8445Sssszwic      when(toMeta.ready) {
454b92f8445Sssszwic        next_state := m_enqWay
4552c9f4a9fSxu_zh      } // .otherwise { next_state := m_metaResend }  // !toMeta.ready
456b92f8445Sssszwic    }
457b92f8445Sssszwic    is(m_enqWay) {
4588c57174eSxu_zh      when(toWayLookup.fire || s1_isSoftPrefetch) {
4598c57174eSxu_zh        when(!s2_ready) {
460b92f8445Sssszwic          next_state := m_enterS2
4618c57174eSxu_zh        }.otherwise { // s2_ready
462b92f8445Sssszwic          next_state := m_idle
463b92f8445Sssszwic        }
4648c57174eSxu_zh      } // .otherwise { next_state := m_enqWay }
465b92f8445Sssszwic    }
466b92f8445Sssszwic    is(m_enterS2) {
467b92f8445Sssszwic      when(s2_ready) {
468b92f8445Sssszwic        next_state := m_idle
469b92f8445Sssszwic      }
470b92f8445Sssszwic    }
471b92f8445Sssszwic  }
472b92f8445Sssszwic
473b92f8445Sssszwic  when(s1_flush) {
474b92f8445Sssszwic    next_state := m_idle
475b92f8445Sssszwic  }
476b92f8445Sssszwic
477b92f8445Sssszwic  /** Stage 1 control */
4782c9f4a9fSxu_zh  from_bpu_s1_flush := s1_valid && !s1_isSoftPrefetch && io.flushFromBpu.shouldFlushByStage3(s1_req_ftqIdx)
479b92f8445Sssszwic  s1_flush          := io.flush || from_bpu_s1_flush
480fad7803dSxu_zh  // when s1 is flushed, itlb pipeline should also be flushed
481fad7803dSxu_zh  io.itlbFlushPipe := s1_flush
482b92f8445Sssszwic
483b92f8445Sssszwic  s1_ready := next_state === m_idle
484400391a3Sxu_zh  s1_fire  := (next_state === m_idle) && s1_valid && !s1_flush // used to clear s1_valid & itlb_valid_latch
485415fcbe2Sxu_zh  private val s1_real_fire = s1_fire && io.csr_pf_enable // real "s1 fire" that s1 enters s2
486b92f8445Sssszwic
487b92f8445Sssszwic  /**
488b92f8445Sssszwic    ******************************************************************************
489b92f8445Sssszwic    * IPrefetch Stage 2
490b92f8445Sssszwic    * - 1. Monitor the requests from missUnit to write to SRAM.
491b92f8445Sssszwic    * - 2. send req to missUnit
492b92f8445Sssszwic    ******************************************************************************
493b92f8445Sssszwic    */
494415fcbe2Sxu_zh  private val s2_valid =
495cf7d6b7aSMuzi    generatePipeControl(lastFire = s1_real_fire, thisFire = s2_fire, thisFlush = s2_flush, lastFlush = false.B)
496b92f8445Sssszwic
497415fcbe2Sxu_zh  private val s2_req_vaddr      = RegEnable(s1_req_vaddr, 0.U.asTypeOf(s1_req_vaddr), s1_real_fire)
498415fcbe2Sxu_zh  private val s2_isSoftPrefetch = RegEnable(s1_isSoftPrefetch, 0.U.asTypeOf(s1_isSoftPrefetch), s1_real_fire)
499415fcbe2Sxu_zh  private val s2_doubleline     = RegEnable(s1_doubleline, 0.U.asTypeOf(s1_doubleline), s1_real_fire)
500415fcbe2Sxu_zh  private val s2_req_paddr      = RegEnable(s1_req_paddr, 0.U.asTypeOf(s1_req_paddr), s1_real_fire)
501415fcbe2Sxu_zh  private val s2_exception =
502cf7d6b7aSMuzi    RegEnable(s1_exception_out, 0.U.asTypeOf(s1_exception_out), s1_real_fire) // includes itlb/pmp exception
503415fcbe2Sxu_zh  // disabled for timing consideration
504415fcbe2Sxu_zh// private val s2_exception_in =
505415fcbe2Sxu_zh//   RegEnable(s1_exception_out, 0.U.asTypeOf(s1_exception_out), s1_real_fire)
506415fcbe2Sxu_zh  private val s2_mmio     = RegEnable(s1_mmio, 0.U.asTypeOf(s1_mmio), s1_real_fire)
507415fcbe2Sxu_zh  private val s2_waymasks = RegEnable(s1_waymasks, 0.U.asTypeOf(s1_waymasks), s1_real_fire)
508415fcbe2Sxu_zh  // disabled for timing consideration
509415fcbe2Sxu_zh// private val s2_meta_codes   = RegEnable(s1_meta_codes, 0.U.asTypeOf(s1_meta_codes), s1_real_fire)
510b92f8445Sssszwic
511415fcbe2Sxu_zh  private val s2_req_vSetIdx = s2_req_vaddr.map(get_idx)
512415fcbe2Sxu_zh  private val s2_req_ptags   = s2_req_paddr.map(get_phy_tag)
513b92f8445Sssszwic
5148966a895Sxu_zh  // disabled for timing consideration
5158966a895Sxu_zh//  // do metaArray ECC check
5168966a895Sxu_zh//  val s2_meta_corrupt = VecInit((s2_req_ptags zip s2_meta_codes zip s2_waymasks).map{ case ((meta, code), waymask) =>
5178966a895Sxu_zh//    val hit_num = PopCount(waymask)
5188966a895Sxu_zh//    // NOTE: if not hit, encodeMetaECC(meta) =/= code can also be true, but we don't care about it
5198966a895Sxu_zh//    (encodeMetaECC(meta) =/= code && hit_num === 1.U) ||  // hit one way, but parity code does not match, ECC failure
520415fcbe2Sxu_zh//      hit_num > 1.U                                       // hit multi-way, must be an ECC failure
5218966a895Sxu_zh//  })
5228966a895Sxu_zh//
5238966a895Sxu_zh//  // generate exception
5246c106319Sxu_zh//  val s2_meta_exception = VecInit(s2_meta_corrupt.map(ExceptionType.fromECC(io.ecc_enable, _)))
5258966a895Sxu_zh//
5268966a895Sxu_zh//  // merge meta exception and itlb/pmp exception
5278966a895Sxu_zh//  val s2_exception = ExceptionType.merge(s2_exception_in, s2_meta_exception)
5288966a895Sxu_zh
529b92f8445Sssszwic  /**
530b92f8445Sssszwic    ******************************************************************************
531b92f8445Sssszwic    * Monitor the requests from missUnit to write to SRAM
532b92f8445Sssszwic    ******************************************************************************
533b92f8445Sssszwic    */
534b808ac73Sxu_zh
535b808ac73Sxu_zh  /* NOTE: If fromMSHR.bits.corrupt, we should set s2_MSHR_hits to false.B, and send prefetch requests again.
536b808ac73Sxu_zh   * This is the opposite of how mainPipe handles fromMSHR.bits.corrupt,
537b808ac73Sxu_zh   *   in which we should set s2_MSHR_hits to true.B, and send error to ifu.
538b808ac73Sxu_zh   */
539415fcbe2Sxu_zh  private val s2_MSHR_match = VecInit((0 until PortNumber).map { i =>
540b808ac73Sxu_zh    (s2_req_vSetIdx(i) === fromMSHR.bits.vSetIdx) &&
541b92f8445Sssszwic    (s2_req_ptags(i) === getPhyTagFromBlk(fromMSHR.bits.blkPaddr)) &&
542b808ac73Sxu_zh    s2_valid && fromMSHR.valid && !fromMSHR.bits.corrupt
543415fcbe2Sxu_zh  })
544415fcbe2Sxu_zh  private val s2_MSHR_hits = (0 until PortNumber).map(i => ValidHoldBypass(s2_MSHR_match(i), s2_fire || s2_flush))
545b92f8445Sssszwic
546415fcbe2Sxu_zh  private val s2_SRAM_hits = s2_waymasks.map(_.orR)
547415fcbe2Sxu_zh  private val s2_hits      = VecInit((0 until PortNumber).map(i => s2_MSHR_hits(i) || s2_SRAM_hits(i)))
548b808ac73Sxu_zh
549f80535c3Sxu_zh  /* s2_exception includes itlb pf/gpf/af, pmp af and meta corruption (af), neither of which should be prefetched
55088895b11Sxu_zh   * mmio should not be prefetched
551f80535c3Sxu_zh   * also, if previous has exception, latter port should also not be prefetched
55288895b11Sxu_zh   */
553415fcbe2Sxu_zh  private val s2_miss = VecInit((0 until PortNumber).map { i =>
554b808ac73Sxu_zh    !s2_hits(i) && (if (i == 0) true.B else s2_doubleline) &&
555dd02bc3fSxu_zh    !ExceptionType.hasException(s2_exception.take(i + 1)) &&
55688895b11Sxu_zh    s2_mmio.take(i + 1).map(!_).reduce(_ && _)
557b808ac73Sxu_zh  })
558b92f8445Sssszwic
559b92f8445Sssszwic  /**
560b92f8445Sssszwic    ******************************************************************************
561b92f8445Sssszwic    * send req to missUnit
562b92f8445Sssszwic    ******************************************************************************
563b92f8445Sssszwic    */
564415fcbe2Sxu_zh  private val toMSHRArbiter = Module(new Arbiter(new ICacheMissReq, PortNumber))
565b92f8445Sssszwic
566b92f8445Sssszwic  // To avoid sending duplicate requests.
567415fcbe2Sxu_zh  private val has_send = RegInit(VecInit(Seq.fill(PortNumber)(false.B)))
568b92f8445Sssszwic  (0 until PortNumber).foreach { i =>
569400391a3Sxu_zh    when(s1_real_fire) {
570b92f8445Sssszwic      has_send(i) := false.B
571b92f8445Sssszwic    }.elsewhen(toMSHRArbiter.io.in(i).fire) {
572b92f8445Sssszwic      has_send(i) := true.B
573b92f8445Sssszwic    }
574b92f8445Sssszwic  }
575b92f8445Sssszwic
576415fcbe2Sxu_zh  (0 until PortNumber).foreach { i =>
577b92f8445Sssszwic    toMSHRArbiter.io.in(i).valid         := s2_valid && s2_miss(i) && !has_send(i)
578b92f8445Sssszwic    toMSHRArbiter.io.in(i).bits.blkPaddr := getBlkAddr(s2_req_paddr(i))
579b92f8445Sssszwic    toMSHRArbiter.io.in(i).bits.vSetIdx  := s2_req_vSetIdx(i)
580b92f8445Sssszwic  }
581b92f8445Sssszwic
582b92f8445Sssszwic  toMSHR <> toMSHRArbiter.io.out
583b92f8445Sssszwic
584b92f8445Sssszwic  s2_flush := io.flush
585b92f8445Sssszwic
5862196d1caSxu_zh  // toMSHRArbiter.io.in(i).fire is not used here for timing consideration
587415fcbe2Sxu_zh// private val s2_finish =
588415fcbe2Sxu_zh//   (0 until PortNumber).map(i => has_send(i) || !s2_miss(i) || toMSHRArbiter.io.in(i).fire).reduce(_ && _)
589415fcbe2Sxu_zh  private val s2_finish = (0 until PortNumber).map(i => has_send(i) || !s2_miss(i)).reduce(_ && _)
590b92f8445Sssszwic  s2_ready := s2_finish || !s2_valid
591b92f8445Sssszwic  s2_fire  := s2_valid && s2_finish && !s2_flush
5929bba777eSssszwic
593cb6e5d3cSssszwic  /** PerfAccumulate */
5942c9f4a9fSxu_zh  // the number of bpu flush
5952c9f4a9fSxu_zh  XSPerfAccumulate("bpu_s0_flush", from_bpu_s0_flush)
5962c9f4a9fSxu_zh  XSPerfAccumulate("bpu_s1_flush", from_bpu_s1_flush)
5972c9f4a9fSxu_zh  // the number of prefetch request received from ftq or backend (software prefetch)
5982c9f4a9fSxu_zh//  XSPerfAccumulate("prefetch_req_receive", io.req.fire)
5992c9f4a9fSxu_zh  XSPerfAccumulate("prefetch_req_receive_hw", io.req.fire && !io.req.bits.isSoftPrefetch)
6002c9f4a9fSxu_zh  XSPerfAccumulate("prefetch_req_receive_sw", io.req.fire && io.req.bits.isSoftPrefetch)
601b92f8445Sssszwic  // the number of prefetch request sent to missUnit
6022c9f4a9fSxu_zh//  XSPerfAccumulate("prefetch_req_send", toMSHR.fire)
6032c9f4a9fSxu_zh  XSPerfAccumulate("prefetch_req_send_hw", toMSHR.fire && !s2_isSoftPrefetch)
6042c9f4a9fSxu_zh  XSPerfAccumulate("prefetch_req_send_sw", toMSHR.fire && s2_isSoftPrefetch)
605b92f8445Sssszwic  XSPerfAccumulate("to_missUnit_stall", toMSHR.valid && !toMSHR.ready)
606cf7d6b7aSMuzi
607cb6e5d3cSssszwic  /**
608cb6e5d3cSssszwic    * Count the number of requests that are filtered for various reasons.
609cb6e5d3cSssszwic    * The number of prefetch discard in Performance Accumulator may be
610415fcbe2Sxu_zh    * a little larger the number of really discarded. Because there can
611cb6e5d3cSssszwic    * be multiple reasons for a canceled request at the same time.
612cb6e5d3cSssszwic    */
613b92f8445Sssszwic  // discard prefetch request by flush
614b92f8445Sssszwic  // XSPerfAccumulate("fdip_prefetch_discard_by_tlb_except",  p1_discard && p1_tlb_except)
615b92f8445Sssszwic  // // discard prefetch request by hit icache SRAM
616b92f8445Sssszwic  // XSPerfAccumulate("fdip_prefetch_discard_by_hit_cache",   p2_discard && p1_meta_hit)
617415fcbe2Sxu_zh  // // discard prefetch request by hit write SRAM
618415fcbe2Sxu_zh  // XSPerfAccumulate("fdip_prefetch_discard_by_p1_monitor",  p1_discard && p1_monitor_hit)
619b92f8445Sssszwic  // // discard prefetch request by pmp except or mmio
620b92f8445Sssszwic  // XSPerfAccumulate("fdip_prefetch_discard_by_pmp",         p2_discard && p2_pmp_except)
621b92f8445Sssszwic  // // discard prefetch request by hit mainPipe info
622b92f8445Sssszwic  // // XSPerfAccumulate("fdip_prefetch_discard_by_mainPipe",    p2_discard && p2_mainPipe_hit)
6237052722fSJay}
624