xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala (revision b92f84459b67a53e82d79920469d5fd6d21aad5e)
17052722fSJay/***************************************************************************************
27052722fSJay  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
37052722fSJay  * Copyright (c) 2020-2021 Peng Cheng Laboratory
47052722fSJay  *
57052722fSJay  * XiangShan is licensed under Mulan PSL v2.
67052722fSJay  * You can use this software according to the terms and conditions of the Mulan PSL v2.
77052722fSJay  * You may obtain a copy of Mulan PSL v2 at:
87052722fSJay  *          http://license.coscl.org.cn/MulanPSL2
97052722fSJay  *
107052722fSJay  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
117052722fSJay  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
127052722fSJay  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
137052722fSJay  *
147052722fSJay  * See the Mulan PSL v2 for more details.
157052722fSJay  ***************************************************************************************/
167052722fSJay
177052722fSJaypackage xiangshan.frontend.icache
187052722fSJay
198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
207052722fSJayimport chisel3._
217052722fSJayimport chisel3.util._
227d45a146SYinan Xuimport difftest._
237052722fSJayimport freechips.rocketchip.tilelink._
247052722fSJayimport utils._
257052722fSJayimport xiangshan.cache.mmu._
267052722fSJayimport xiangshan.frontend._
27d2b20d1aSTang Haojinimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle}
28d2b20d1aSTang Haojinimport huancun.PreferCacheKey
29b92c5693STang Haojinimport xiangshan.XSCoreParamsKey
30b1ded4e8Sguohongyuimport utility._
317052722fSJay
327052722fSJayabstract class IPrefetchBundle(implicit p: Parameters) extends ICacheBundle
337052722fSJayabstract class IPrefetchModule(implicit p: Parameters) extends ICacheModule
347052722fSJay
35cb6e5d3cSssszwicclass IPredfetchIO(implicit p: Parameters) extends IPrefetchBundle {
36*b92f8445Sssszwic  // control
37*b92f8445Sssszwic  val csr_pf_enable     = Input(Bool())
38*b92f8445Sssszwic  val flush             = Input(Bool())
3958c354d0Sssszwic
40*b92f8445Sssszwic  val ftqReq            = Flipped(new FtqToPrefetchIO)
41*b92f8445Sssszwic  val itlb              = Vec(PortNumber, new TlbRequestIO)
42*b92f8445Sssszwic  val pmp               = Vec(PortNumber, new ICachePMPBundle)
43*b92f8445Sssszwic  val metaRead          = new ICacheMetaReqBundle
44*b92f8445Sssszwic  val MSHRReq           = DecoupledIO(new ICacheMissReq)
45*b92f8445Sssszwic  val MSHRResp          = Flipped(ValidIO(new ICacheMissResp))
46*b92f8445Sssszwic  val wayLookupWrite    = DecoupledIO(new WayLookupInfo)
477052722fSJay}
487052722fSJay
497052722fSJayclass IPrefetchPipe(implicit p: Parameters) extends  IPrefetchModule
507052722fSJay{
517052722fSJay  val io = IO(new IPredfetchIO)
527052722fSJay
53cb6e5d3cSssszwic  val fromFtq = io.ftqReq
54*b92f8445Sssszwic  val (toITLB,  fromITLB) = (io.itlb.map(_.req), io.itlb.map(_.resp))
55*b92f8445Sssszwic  val (toPMP,  fromPMP)   = (io.pmp.map(_.req), io.pmp.map(_.resp))
56*b92f8445Sssszwic  val (toMeta,  fromMeta) = (io.metaRead.toIMeta,  io.metaRead.fromIMeta)
57*b92f8445Sssszwic  val (toMSHR, fromMSHR)  = (io.MSHRReq, io.MSHRResp)
58*b92f8445Sssszwic  val toWayLookup = io.wayLookupWrite
597052722fSJay
60*b92f8445Sssszwic  val enableBit = RegInit(false.B)
61*b92f8445Sssszwic  enableBit := io.csr_pf_enable
6258c354d0Sssszwic
63*b92f8445Sssszwic  val s0_fire, s1_fire, s2_fire             = WireInit(false.B)
64*b92f8445Sssszwic  val s0_discard, s2_discard                = WireInit(false.B)
65*b92f8445Sssszwic  val s0_ready, s1_ready, s2_ready          = WireInit(false.B)
66*b92f8445Sssszwic  val s0_flush, s1_flush, s2_flush          = WireInit(false.B)
67*b92f8445Sssszwic  val from_bpu_s0_flush, from_bpu_s1_flush  = WireInit(false.B)
687052722fSJay
69cb6e5d3cSssszwic  /**
70cb6e5d3cSssszwic    ******************************************************************************
71cb6e5d3cSssszwic    * IPrefetch Stage 0
72*b92f8445Sssszwic    * - 1. receive ftq req
73*b92f8445Sssszwic    * - 2. send req to ITLB
74*b92f8445Sssszwic    * - 3. send req to Meta SRAM
75cb6e5d3cSssszwic    ******************************************************************************
76cb6e5d3cSssszwic    */
77*b92f8445Sssszwic  val s0_valid  = fromFtq.req.valid
78cb6e5d3cSssszwic
79*b92f8445Sssszwic  /**
80*b92f8445Sssszwic    ******************************************************************************
81*b92f8445Sssszwic    * receive ftq req
82*b92f8445Sssszwic    ******************************************************************************
83*b92f8445Sssszwic    */
84*b92f8445Sssszwic  val s0_req_vaddr    = VecInit(Seq(fromFtq.req.bits.startAddr, fromFtq.req.bits.nextlineStart))
85*b92f8445Sssszwic  val s0_req_ftqIdx   = fromFtq.req.bits.ftqIdx
86*b92f8445Sssszwic  val s0_doubleline   = fromFtq.req.bits.crossCacheline
87*b92f8445Sssszwic  val s0_req_vSetIdx  = s0_req_vaddr.map(get_idx(_))
887052722fSJay
89*b92f8445Sssszwic  from_bpu_s0_flush := fromFtq.flushFromBpu.shouldFlushByStage2(s0_req_ftqIdx) ||
90*b92f8445Sssszwic                       fromFtq.flushFromBpu.shouldFlushByStage3(s0_req_ftqIdx)
91*b92f8445Sssszwic  s0_flush := io.flush || from_bpu_s0_flush || s1_flush
927052722fSJay
93*b92f8445Sssszwic  val s0_can_go = s1_ready && toITLB(0).ready && toITLB(1).ready && toMeta.ready
94*b92f8445Sssszwic  fromFtq.req.ready := s0_can_go
957052722fSJay
96*b92f8445Sssszwic  s0_fire := s0_valid && s0_can_go && !s0_flush
97cb6e5d3cSssszwic
98cb6e5d3cSssszwic  /**
99cb6e5d3cSssszwic    ******************************************************************************
100cb6e5d3cSssszwic    * IPrefetch Stage 1
101*b92f8445Sssszwic    * - 1. Receive resp from ITLB
102*b92f8445Sssszwic    * - 2. Receive resp from IMeta and check
103*b92f8445Sssszwic    * - 3. Monitor the requests from missUnit to write to SRAM.
104*b92f8445Sssszwic    * - 4. Wirte wayLookup
105cb6e5d3cSssszwic    ******************************************************************************
106cb6e5d3cSssszwic    */
107*b92f8445Sssszwic  val s1_valid = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = s1_flush, lastFlush = false.B)
108cb6e5d3cSssszwic
109*b92f8445Sssszwic  val s1_req_vaddr    = RegEnable(s0_req_vaddr, 0.U.asTypeOf(s0_req_vaddr), s0_fire)
110*b92f8445Sssszwic  val s1_doubleline   = RegEnable(s0_doubleline, 0.U.asTypeOf(s0_doubleline), s0_fire)
111*b92f8445Sssszwic  val s1_req_ftqIdx   = RegEnable(s0_req_ftqIdx, 0.U.asTypeOf(s0_req_ftqIdx), s0_fire)
112*b92f8445Sssszwic  val s1_req_vSetIdx  = VecInit(s1_req_vaddr.map(get_idx(_)))
1137052722fSJay
114*b92f8445Sssszwic  val m_idle :: m_itlbResend :: m_metaResend :: m_enqWay :: m_enterS2 :: Nil = Enum(5)
115*b92f8445Sssszwic  val state = RegInit(m_idle)
116*b92f8445Sssszwic  val next_state = WireDefault(state)
117*b92f8445Sssszwic  val s0_fire_r = RegNext(s0_fire)
118*b92f8445Sssszwic  dontTouch(state)
119*b92f8445Sssszwic  dontTouch(next_state)
120*b92f8445Sssszwic  state := next_state
1217052722fSJay
122*b92f8445Sssszwic  /**
123*b92f8445Sssszwic    ******************************************************************************
124*b92f8445Sssszwic    * resend itlb req if miss
125*b92f8445Sssszwic    ******************************************************************************
126*b92f8445Sssszwic    */
127*b92f8445Sssszwic  val s1_wait_itlb  = RegInit(VecInit(Seq.fill(PortNumber)(false.B)))
128*b92f8445Sssszwic  (0 until PortNumber).foreach { i =>
129*b92f8445Sssszwic    when(s1_flush) {
130*b92f8445Sssszwic      s1_wait_itlb(i) := false.B
131*b92f8445Sssszwic    }.elsewhen(RegNext(s0_fire) && fromITLB(i).bits.miss) {
132*b92f8445Sssszwic      s1_wait_itlb(i) := true.B
133*b92f8445Sssszwic    }.elsewhen(s1_wait_itlb(i) && !fromITLB(i).bits.miss) {
134*b92f8445Sssszwic      s1_wait_itlb(i) := false.B
135*b92f8445Sssszwic    }
136*b92f8445Sssszwic  }
137*b92f8445Sssszwic  val s1_need_itlb    = VecInit(Seq((RegNext(s0_fire) || s1_wait_itlb(0)) && fromITLB(0).bits.miss,
138*b92f8445Sssszwic                                    (RegNext(s0_fire) || s1_wait_itlb(1)) && fromITLB(1).bits.miss && s1_doubleline))
139*b92f8445Sssszwic  val tlb_valid_pulse = VecInit(Seq((RegNext(s0_fire) || s1_wait_itlb(0)) && !fromITLB(0).bits.miss,
140*b92f8445Sssszwic                                    (RegNext(s0_fire) || s1_wait_itlb(1)) && !fromITLB(1).bits.miss && s1_doubleline))
141*b92f8445Sssszwic  val tlb_valid_latch = VecInit((0 until PortNumber).map(i => ValidHoldBypass(tlb_valid_pulse(i), s1_fire, flush=s1_flush)))
142*b92f8445Sssszwic  val itlb_finish     = tlb_valid_latch(0) && (!s1_doubleline || tlb_valid_latch(1))
1437052722fSJay
144*b92f8445Sssszwic  for (i <- 0 until PortNumber) {
145*b92f8445Sssszwic    toITLB(i).valid             := s1_need_itlb(i) || (s0_valid && (if(i == 0) true.B else s0_doubleline))
146*b92f8445Sssszwic    toITLB(i).bits              := DontCare
147*b92f8445Sssszwic    toITLB(i).bits.size         := 3.U
148*b92f8445Sssszwic    toITLB(i).bits.vaddr        := Mux(s1_need_itlb(i), s1_req_vaddr(i), s0_req_vaddr(i))
149*b92f8445Sssszwic    toITLB(i).bits.debug.pc     := Mux(s1_need_itlb(i), s1_req_vaddr(i), s0_req_vaddr(i))
150*b92f8445Sssszwic    toITLB(i).bits.cmd          := TlbCmd.exec
151*b92f8445Sssszwic    toITLB(i).bits.no_translate := false.B
152*b92f8445Sssszwic  }
153*b92f8445Sssszwic  fromITLB.foreach(_.ready := true.B)
154*b92f8445Sssszwic  io.itlb.foreach(_.req_kill := false.B)
1557052722fSJay
156*b92f8445Sssszwic  /**
157*b92f8445Sssszwic    ******************************************************************************
158*b92f8445Sssszwic    * Receive resp from ITLB
159*b92f8445Sssszwic    ******************************************************************************
160*b92f8445Sssszwic    */
161*b92f8445Sssszwic  val s1_req_paddr_wire   = VecInit(fromITLB.map(_.bits.paddr(0)))
162*b92f8445Sssszwic  val s1_req_paddr_reg    = VecInit((0 until PortNumber).map(i =>
163*b92f8445Sssszwic                                RegEnable(s1_req_paddr_wire(i), 0.U(PAddrBits.W), tlb_valid_pulse(i))))
164*b92f8445Sssszwic  val s1_req_paddr        = VecInit((0 until PortNumber).map(i =>
165*b92f8445Sssszwic                                Mux(tlb_valid_pulse(i), s1_req_paddr_wire(i), s1_req_paddr_reg(i))))
166*b92f8445Sssszwic  val s1_req_gpaddr       = VecInit((0 until PortNumber).map(i =>
167*b92f8445Sssszwic                                ResultHoldBypass(valid = tlb_valid_pulse(i), init = 0.U.asTypeOf(fromITLB(i).bits.gpaddr(0)), data = fromITLB(i).bits.gpaddr(0))))
168*b92f8445Sssszwic  val itlbExcpPF          = VecInit((0 until PortNumber).map(i =>
169*b92f8445Sssszwic                                ResultHoldBypass(valid = tlb_valid_pulse(i), init = 0.U.asTypeOf(fromITLB(i).bits.excp(0).pf.instr), data = fromITLB(i).bits.excp(0).pf.instr)))
170*b92f8445Sssszwic  val itlbExcpGPF         = VecInit((0 until PortNumber).map(i =>
171*b92f8445Sssszwic                                ResultHoldBypass(valid = tlb_valid_pulse(i), init = 0.U.asTypeOf(fromITLB(i).bits.excp(0).gpf.instr), data = fromITLB(i).bits.excp(0).gpf.instr)))
172*b92f8445Sssszwic  val itlbExcpAF          = VecInit((0 until PortNumber).map(i =>
173*b92f8445Sssszwic                                ResultHoldBypass(valid = tlb_valid_pulse(i), init = 0.U.asTypeOf(fromITLB(i).bits.excp(0).af.instr), data = fromITLB(i).bits.excp(0).af.instr)))
174*b92f8445Sssszwic  val itlbExcp            = VecInit((0 until PortNumber).map(i => itlbExcpAF(i) || itlbExcpPF(i) || itlbExcpGPF(i)))
175*b92f8445Sssszwic
176*b92f8445Sssszwic  /**
177*b92f8445Sssszwic    ******************************************************************************
178*b92f8445Sssszwic    * resend metaArray read req when itlb miss finish
179*b92f8445Sssszwic    ******************************************************************************
180*b92f8445Sssszwic    */
181*b92f8445Sssszwic  val s1_need_meta = ((state === m_itlbResend) && itlb_finish) || (state === m_metaResend)
182*b92f8445Sssszwic  toMeta.valid              := s1_need_meta || s0_valid
183*b92f8445Sssszwic  toMeta.bits               := DontCare
184*b92f8445Sssszwic  toMeta.bits.isDoubleLine  := Mux(s1_need_meta, s1_doubleline, s0_doubleline)
185*b92f8445Sssszwic
186*b92f8445Sssszwic  for (i <- 0 until PortNumber) {
187*b92f8445Sssszwic    toMeta.bits.vSetIdx(i)  := Mux(s1_need_meta, s1_req_vSetIdx(i), s0_req_vSetIdx(i))
188cb6e5d3cSssszwic  }
189cb6e5d3cSssszwic
190cb6e5d3cSssszwic  /**
191cb6e5d3cSssszwic    ******************************************************************************
192*b92f8445Sssszwic    * Receive resp from IMeta and check
193cb6e5d3cSssszwic    ******************************************************************************
194cb6e5d3cSssszwic    */
195*b92f8445Sssszwic  val s1_req_ptags    = VecInit(s1_req_paddr.map(get_phy_tag(_)))
196cb6e5d3cSssszwic
197*b92f8445Sssszwic  val s1_meta_ptags   = fromMeta.tags
198*b92f8445Sssszwic  val s1_meta_valids  = fromMeta.entryValid
199*b92f8445Sssszwic  val s1_meta_errors = VecInit((0 until PortNumber).map( p =>
200*b92f8445Sssszwic    // If error is found in either way, the tag_eq_vec is unreliable, so we do not use waymask, but directly .orR
201*b92f8445Sssszwic    fromMeta.errors(p).asUInt.orR
202*b92f8445Sssszwic  ))
2039bba777eSssszwic
204*b92f8445Sssszwic  def get_waymask(paddrs: Vec[UInt]): Vec[UInt] = {
205*b92f8445Sssszwic    val ptags         = paddrs.map(get_phy_tag(_))
206*b92f8445Sssszwic    val tag_eq_vec    = VecInit((0 until PortNumber).map( p => VecInit((0 until nWays).map( w => s1_meta_ptags(p)(w) === ptags(p)))))
207*b92f8445Sssszwic    val tag_match_vec = VecInit((0 until PortNumber).map( k => VecInit(tag_eq_vec(k).zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s1_meta_valids(k)(w)})))
208*b92f8445Sssszwic    val waymasks      = VecInit(tag_match_vec.map(_.asUInt))
209*b92f8445Sssszwic    waymasks
210cb6e5d3cSssszwic  }
2119bba777eSssszwic
212*b92f8445Sssszwic  val s1_SRAM_waymasks = VecInit((0 until PortNumber).map(i =>
213*b92f8445Sssszwic                            Mux(tlb_valid_pulse(i), get_waymask(s1_req_paddr_wire)(i), get_waymask(s1_req_paddr_reg)(i))))
214*b92f8445Sssszwic
215*b92f8445Sssszwic  /**
216*b92f8445Sssszwic    ******************************************************************************
217*b92f8445Sssszwic    * update waymask
218*b92f8445Sssszwic    ******************************************************************************
219*b92f8445Sssszwic    */
220*b92f8445Sssszwic  def update_waymask(mask: UInt, vSetIdx: UInt, ptag: UInt): UInt = {
221*b92f8445Sssszwic    require(mask.getWidth == nWays)
222*b92f8445Sssszwic    val new_mask  = WireInit(mask)
223*b92f8445Sssszwic    val vset_same = (fromMSHR.bits.vSetIdx === vSetIdx) && !fromMSHR.bits.corrupt && fromMSHR.valid
224*b92f8445Sssszwic    val ptag_same = getPhyTagFromBlk(fromMSHR.bits.blkPaddr) === ptag
225*b92f8445Sssszwic    val way_same  = fromMSHR.bits.waymask === mask
226*b92f8445Sssszwic    when(vset_same) {
227*b92f8445Sssszwic      when(ptag_same) {
228*b92f8445Sssszwic        new_mask := fromMSHR.bits.waymask
229*b92f8445Sssszwic      }.elsewhen(way_same) {
230*b92f8445Sssszwic        new_mask := 0.U
231cb6e5d3cSssszwic      }
232*b92f8445Sssszwic    }
233*b92f8445Sssszwic    new_mask
234*b92f8445Sssszwic  }
235*b92f8445Sssszwic
236*b92f8445Sssszwic  val s1_waymasks_r = RegInit(VecInit(Seq.fill(PortNumber)(0.U(nWays.W))))
237*b92f8445Sssszwic  val s1_SRAM_valid = s0_fire_r || RegNext(s1_need_meta && toMeta.ready)
238*b92f8445Sssszwic  val s1_waymasks   = Mux(s1_SRAM_valid, s1_SRAM_waymasks, s1_waymasks_r)
239*b92f8445Sssszwic  (0 until PortNumber).foreach{i =>
240*b92f8445Sssszwic    s1_waymasks_r(i) := update_waymask(s1_waymasks(i), s1_req_vSetIdx(i), s1_req_ptags(i))
241*b92f8445Sssszwic  }
242*b92f8445Sssszwic
243*b92f8445Sssszwic  /**
244*b92f8445Sssszwic    ******************************************************************************
245*b92f8445Sssszwic    * send enqueu req to WayLookup
246*b92f8445Sssszwic    ******** **********************************************************************
247*b92f8445Sssszwic    */
248*b92f8445Sssszwic  // Disallow enqueuing wayLookup when SRAM write occurs.
249*b92f8445Sssszwic  toWayLookup.valid             := ((state === m_enqWay) || ((state === m_idle) && itlb_finish)) && !s1_flush && !fromMSHR.valid
250*b92f8445Sssszwic  toWayLookup.bits.vSetIdx      := s1_req_vSetIdx
251*b92f8445Sssszwic  toWayLookup.bits.waymask      := s1_waymasks
252*b92f8445Sssszwic  toWayLookup.bits.ptag         := s1_req_ptags
253*b92f8445Sssszwic  toWayLookup.bits.gpaddr       := s1_req_gpaddr
254*b92f8445Sssszwic  toWayLookup.bits.excp_tlb_af  := itlbExcpAF
255*b92f8445Sssszwic  toWayLookup.bits.excp_tlb_pf  := itlbExcpPF
256*b92f8445Sssszwic  toWayLookup.bits.excp_tlb_gpf := itlbExcpGPF
257*b92f8445Sssszwic  toWayLookup.bits.meta_errors  := s1_meta_errors
258*b92f8445Sssszwic
259*b92f8445Sssszwic  val s1_waymasks_vec = s1_waymasks.map(_.asTypeOf(Vec(nWays, Bool())))
260*b92f8445Sssszwic  when(toWayLookup.fire) {
261*b92f8445Sssszwic    assert(PopCount(s1_waymasks_vec(0)) <= 1.U && (PopCount(s1_waymasks_vec(1)) <= 1.U || !s1_doubleline),
262*b92f8445Sssszwic      "Multiple hit in main pipe, port0:is=%d,ptag=0x%x,vidx=0x%x,vaddr=0x%x port1:is=%d,ptag=0x%x,vidx=0x%x,vaddr=0x%x ",
263*b92f8445Sssszwic      PopCount(s1_waymasks_vec(0)) > 1.U, s1_req_ptags(0), get_idx(s1_req_vaddr(0)), s1_req_vaddr(0),
264*b92f8445Sssszwic      PopCount(s1_waymasks_vec(1)) > 1.U && s1_doubleline, s1_req_ptags(1), get_idx(s1_req_vaddr(1)), s1_req_vaddr(1))
265*b92f8445Sssszwic  }
266*b92f8445Sssszwic
267*b92f8445Sssszwic  /**
268*b92f8445Sssszwic    ******************************************************************************
269*b92f8445Sssszwic    * PMP check
270*b92f8445Sssszwic    ******************************************************************************
271*b92f8445Sssszwic    */
272*b92f8445Sssszwic  toPMP.zipWithIndex.map { case (p, i) =>
273*b92f8445Sssszwic    p.valid     := s1_valid
274*b92f8445Sssszwic    p.bits.addr := s1_req_paddr(i)
275*b92f8445Sssszwic    p.bits.size := 3.U // TODO
276*b92f8445Sssszwic    p.bits.cmd  := TlbCmd.exec
277*b92f8445Sssszwic  }
278*b92f8445Sssszwic  val pmpExcp = VecInit(Seq(fromPMP(0).instr || fromPMP(0).mmio,
279*b92f8445Sssszwic                             fromPMP(0).instr || fromPMP(1).instr || fromPMP(0).mmio))
280*b92f8445Sssszwic
281*b92f8445Sssszwic  /**
282*b92f8445Sssszwic    ******************************************************************************
283*b92f8445Sssszwic    * state machine
284*b92f8445Sssszwic    ******** **********************************************************************
285*b92f8445Sssszwic    */
286*b92f8445Sssszwic
287*b92f8445Sssszwic  switch(state) {
288*b92f8445Sssszwic    is(m_idle) {
289*b92f8445Sssszwic      when(s1_valid && !itlb_finish) {
290*b92f8445Sssszwic        next_state := m_itlbResend
291*b92f8445Sssszwic      }.elsewhen(s1_valid && itlb_finish && !toWayLookup.fire) {
292*b92f8445Sssszwic        next_state := m_enqWay
293*b92f8445Sssszwic      }.elsewhen(s1_valid && itlb_finish && toWayLookup.fire && !s2_ready) {
294*b92f8445Sssszwic        next_state := m_enterS2
295*b92f8445Sssszwic      }
296*b92f8445Sssszwic    }
297*b92f8445Sssszwic    is(m_itlbResend) {
298*b92f8445Sssszwic      when(itlb_finish && !toMeta.ready) {
299*b92f8445Sssszwic        next_state := m_metaResend
300*b92f8445Sssszwic      }.elsewhen(itlb_finish && toMeta.ready) {
301*b92f8445Sssszwic        next_state := m_enqWay
302*b92f8445Sssszwic      }
303*b92f8445Sssszwic    }
304*b92f8445Sssszwic    is(m_metaResend) {
305*b92f8445Sssszwic      when(toMeta.ready) {
306*b92f8445Sssszwic        next_state := m_enqWay
307*b92f8445Sssszwic      }
308*b92f8445Sssszwic    }
309*b92f8445Sssszwic    is(m_enqWay) {
310*b92f8445Sssszwic      when(toWayLookup.fire && !s2_ready) {
311*b92f8445Sssszwic        next_state := m_enterS2
312*b92f8445Sssszwic      }.elsewhen(toWayLookup.fire && s2_ready) {
313*b92f8445Sssszwic        next_state := m_idle
314*b92f8445Sssszwic      }
315*b92f8445Sssszwic    }
316*b92f8445Sssszwic    is(m_enterS2) {
317*b92f8445Sssszwic      when(s2_ready) {
318*b92f8445Sssszwic        next_state := m_idle
319*b92f8445Sssszwic      }
320*b92f8445Sssszwic    }
321*b92f8445Sssszwic  }
322*b92f8445Sssszwic
323*b92f8445Sssszwic  when(s1_flush) {
324*b92f8445Sssszwic    next_state := m_idle
325*b92f8445Sssszwic  }
326*b92f8445Sssszwic
327*b92f8445Sssszwic  /** Stage 1 control */
328*b92f8445Sssszwic  from_bpu_s1_flush := s1_valid && fromFtq.flushFromBpu.shouldFlushByStage3(s1_req_ftqIdx)
329*b92f8445Sssszwic  s1_flush := io.flush || from_bpu_s1_flush
330*b92f8445Sssszwic
331*b92f8445Sssszwic  s1_ready      := next_state === m_idle
332*b92f8445Sssszwic  s1_fire       := (next_state === m_idle) && s1_valid && !s1_flush
333*b92f8445Sssszwic
334*b92f8445Sssszwic  /**
335*b92f8445Sssszwic    ******************************************************************************
336*b92f8445Sssszwic    * IPrefetch Stage 2
337*b92f8445Sssszwic    * - 1. Monitor the requests from missUnit to write to SRAM.
338*b92f8445Sssszwic    * - 2. send req to missUnit
339*b92f8445Sssszwic    ******************************************************************************
340*b92f8445Sssszwic    */
341*b92f8445Sssszwic  val s2_valid  = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = s2_flush, lastFlush = false.B)
342*b92f8445Sssszwic
343*b92f8445Sssszwic  val s2_req_vaddr    = RegEnable(s1_req_vaddr, 0.U.asTypeOf(s1_req_vaddr), s1_fire)
344*b92f8445Sssszwic  val s2_doubleline   = RegEnable(s1_doubleline, 0.U.asTypeOf(s1_doubleline), s1_fire)
345*b92f8445Sssszwic  val s2_req_paddr    = RegEnable(s1_req_paddr, 0.U.asTypeOf(s1_req_paddr), s1_fire)
346*b92f8445Sssszwic
347*b92f8445Sssszwic  val s2_pmpExcp      = RegEnable(pmpExcp, 0.U.asTypeOf(pmpExcp), s1_fire)
348*b92f8445Sssszwic  val s2_itlbExcp     = RegEnable(itlbExcp, 0.U.asTypeOf(itlbExcp), s1_fire)
349*b92f8445Sssszwic  val s2_waymasks     = RegEnable(s1_waymasks, 0.U.asTypeOf(s1_waymasks), s1_fire)
350*b92f8445Sssszwic
351*b92f8445Sssszwic  val s2_req_vSetIdx  = s2_req_vaddr.map(get_idx(_))
352*b92f8445Sssszwic  val s2_req_ptags    = s2_req_paddr.map(get_phy_tag(_))
353*b92f8445Sssszwic
354*b92f8445Sssszwic  /**
355*b92f8445Sssszwic    ******************************************************************************
356*b92f8445Sssszwic    * Monitor the requests from missUnit to write to SRAM
357*b92f8445Sssszwic    ******************************************************************************
358*b92f8445Sssszwic    */
359*b92f8445Sssszwic  val s2_MSHR_match = VecInit((0 until PortNumber).map(i => (s2_req_vSetIdx(i) === fromMSHR.bits.vSetIdx) &&
360*b92f8445Sssszwic                                                            (s2_req_ptags(i) === getPhyTagFromBlk(fromMSHR.bits.blkPaddr)) &&
361*b92f8445Sssszwic                                                            s2_valid && fromMSHR.valid && !fromMSHR.bits.corrupt))
362*b92f8445Sssszwic  val s2_MSHR_hits = (0 until PortNumber).map(i => ValidHoldBypass(s2_MSHR_match(i), s2_fire || s2_flush))
363*b92f8445Sssszwic
364*b92f8445Sssszwic  val s2_hits = s2_waymasks.map(_.orR)
365*b92f8445Sssszwic  val s2_miss = VecInit(Seq(!s2_itlbExcp(0) && !s2_pmpExcp(0) && !s2_hits(0) && !s2_MSHR_hits(0),
366*b92f8445Sssszwic                            !s2_itlbExcp(0) && !s2_pmpExcp(0) && !s2_itlbExcp(1) && s2_pmpExcp(1) && !s2_hits(1) && !s2_MSHR_hits(1) && s2_doubleline))
367*b92f8445Sssszwic
368*b92f8445Sssszwic  /**
369*b92f8445Sssszwic    ******************************************************************************
370*b92f8445Sssszwic    * send req to missUnit
371*b92f8445Sssszwic    ******************************************************************************
372*b92f8445Sssszwic    */
373*b92f8445Sssszwic  val toMSHRArbiter = Module(new Arbiter(new ICacheMissReq, PortNumber))
374*b92f8445Sssszwic
375*b92f8445Sssszwic  // To avoid sending duplicate requests.
376*b92f8445Sssszwic  val has_send = RegInit(VecInit(Seq.fill(2)(false.B)))
377*b92f8445Sssszwic  (0 until PortNumber).foreach{ i =>
378*b92f8445Sssszwic    when(s1_fire) {
379*b92f8445Sssszwic      has_send(i) := false.B
380*b92f8445Sssszwic    }.elsewhen(toMSHRArbiter.io.in(i).fire) {
381*b92f8445Sssszwic      has_send(i) := true.B
382*b92f8445Sssszwic    }
383*b92f8445Sssszwic  }
384*b92f8445Sssszwic
385*b92f8445Sssszwic  (0 until PortNumber).map{ i =>
386*b92f8445Sssszwic    toMSHRArbiter.io.in(i).valid          := s2_valid && s2_miss(i) && !has_send(i)
387*b92f8445Sssszwic    toMSHRArbiter.io.in(i).bits.blkPaddr  := getBlkAddr(s2_req_paddr(i))
388*b92f8445Sssszwic    toMSHRArbiter.io.in(i).bits.vSetIdx   := s2_req_vSetIdx(i)
389*b92f8445Sssszwic  }
390*b92f8445Sssszwic
391*b92f8445Sssszwic  toMSHR <> toMSHRArbiter.io.out
392*b92f8445Sssszwic
393*b92f8445Sssszwic  s2_flush := io.flush
394*b92f8445Sssszwic
395*b92f8445Sssszwic  val s2_finish  = (0 until PortNumber).map(i => has_send(i) || !s2_miss(i) || toMSHRArbiter.io.in(i).fire).reduce(_&&_)
396*b92f8445Sssszwic  s2_ready      := s2_finish || !s2_valid
397*b92f8445Sssszwic  s2_fire       := s2_valid && s2_finish && !s2_flush
3989bba777eSssszwic
399cb6e5d3cSssszwic  /** PerfAccumulate */
400cb6e5d3cSssszwic  // the number of prefetch request received from ftq
401935edac4STang Haojin  XSPerfAccumulate("prefetch_req_receive", fromFtq.req.fire)
402*b92f8445Sssszwic  // the number of prefetch request sent to missUnit
403*b92f8445Sssszwic  XSPerfAccumulate("prefetch_req_send", toMSHR.fire)
404*b92f8445Sssszwic  XSPerfAccumulate("to_missUnit_stall", toMSHR.valid && !toMSHR.ready)
405cb6e5d3cSssszwic  /**
406cb6e5d3cSssszwic    * Count the number of requests that are filtered for various reasons.
407cb6e5d3cSssszwic    * The number of prefetch discard in Performance Accumulator may be
408cb6e5d3cSssszwic    * a littel larger the number of really discarded. Because there can
409cb6e5d3cSssszwic    * be multiple reasons for a canceled request at the same time.
410cb6e5d3cSssszwic    */
411*b92f8445Sssszwic  // discard prefetch request by flush
412*b92f8445Sssszwic  // XSPerfAccumulate("fdip_prefetch_discard_by_tlb_except",  p1_discard && p1_tlb_except)
413*b92f8445Sssszwic  // // discard prefetch request by hit icache SRAM
414*b92f8445Sssszwic  // XSPerfAccumulate("fdip_prefetch_discard_by_hit_cache",   p2_discard && p1_meta_hit)
415*b92f8445Sssszwic  // // discard prefetch request by hit wirte SRAM
416*b92f8445Sssszwic  // XSPerfAccumulate("fdip_prefetch_discard_by_p1_monoitor", p1_discard && p1_monitor_hit)
417*b92f8445Sssszwic  // // discard prefetch request by pmp except or mmio
418*b92f8445Sssszwic  // XSPerfAccumulate("fdip_prefetch_discard_by_pmp",         p2_discard && p2_pmp_except)
419*b92f8445Sssszwic  // // discard prefetch request by hit mainPipe info
420*b92f8445Sssszwic  // // XSPerfAccumulate("fdip_prefetch_discard_by_mainPipe",    p2_discard && p2_mainPipe_hit)
4217052722fSJay}