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