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 197052722fSJayimport chipsalliance.rocketchip.config.Parameters 207052722fSJayimport chisel3._ 217052722fSJayimport chisel3.util._ 227052722fSJayimport freechips.rocketchip.tilelink._ 237052722fSJayimport utils._ 247052722fSJayimport xiangshan.cache.mmu._ 257052722fSJayimport xiangshan.frontend._ 26*b1ded4e8Sguohongyuimport utility._ 277052722fSJay 287052722fSJay 297052722fSJayabstract class IPrefetchBundle(implicit p: Parameters) extends ICacheBundle 307052722fSJayabstract class IPrefetchModule(implicit p: Parameters) extends ICacheModule 317052722fSJay 32*b1ded4e8Sguohongyu//TODO: remove this 33*b1ded4e8Sguohongyuobject DebugFlags { 34*b1ded4e8Sguohongyu val fdip = false 357052722fSJay} 367052722fSJay 37*b1ded4e8Sguohongyuclass PIQReq(implicit p: Parameters) extends IPrefetchBundle { 38*b1ded4e8Sguohongyu val paddr = UInt(PAddrBits.W) 39*b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 40*b1ded4e8Sguohongyu} 41*b1ded4e8Sguohongyu 42*b1ded4e8Sguohongyuclass PIQData(implicit p: Parameters) extends IPrefetchBundle { 43*b1ded4e8Sguohongyu val ptage = UInt(tagBits.W) 44*b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 45*b1ded4e8Sguohongyu val cacheline = UInt(blockBits.W) 46*b1ded4e8Sguohongyu val writeBack = Bool() 47*b1ded4e8Sguohongyu} 48*b1ded4e8Sguohongyu 49*b1ded4e8Sguohongyuclass PIQToMainPipe(implicit p: Parameters) extends IPrefetchBundle{ 50*b1ded4e8Sguohongyu val info = DecoupledIO(new PIQData) 51*b1ded4e8Sguohongyu} 52*b1ded4e8Sguohongyu/* need change name */ 53*b1ded4e8Sguohongyuclass MainPipeToPrefetchPipe(implicit p: Parameters) extends IPrefetchBundle { 54*b1ded4e8Sguohongyu val ptage = UInt(tagBits.W) 55*b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 56*b1ded4e8Sguohongyu} 57*b1ded4e8Sguohongyu 58*b1ded4e8Sguohongyuclass MainPipeMissInfo(implicit p: Parameters) extends IPrefetchBundle { 59*b1ded4e8Sguohongyu val s1_already_check_ipf = Output(Bool()) 60*b1ded4e8Sguohongyu val s2_miss_info = Vec(PortNumber, ValidIO(new MainPipeToPrefetchPipe)) 61*b1ded4e8Sguohongyu} 627052722fSJay 637052722fSJayclass IPrefetchToMissUnit(implicit p: Parameters) extends IPrefetchBundle{ 647052722fSJay val enqReq = DecoupledIO(new PIQReq) 657052722fSJay} 667052722fSJay 677052722fSJayclass IPredfetchIO(implicit p: Parameters) extends IPrefetchBundle { 687052722fSJay val fromFtq = Flipped(new FtqPrefechBundle) 69f1fe8698SLemover val iTLBInter = new TlbRequestIO 7061e1db30SJay val pmp = new ICachePMPBundle 71*b1ded4e8Sguohongyu val toIMeta = Decoupled(new ICacheReadBundle) 727052722fSJay val fromIMeta = Input(new ICacheMetaRespBundle) 737052722fSJay val toMissUnit = new IPrefetchToMissUnit 74*b1ded4e8Sguohongyu val freePIQEntry = Input(UInt(log2Ceil(nPrefetchEntries).W)) 7500240ba6SJay val fromMSHR = Flipped(Vec(PortNumber,ValidIO(UInt(PAddrBits.W)))) 76*b1ded4e8Sguohongyu val IPFBufferRead = Flipped(new IPFBufferFilterRead) 77*b1ded4e8Sguohongyu /** icache main pipe to prefetch pipe*/ 78*b1ded4e8Sguohongyu val fromMainPipe = Flipped(Vec(PortNumber,ValidIO(new MainPipeToPrefetchPipe))) 79a108d429SJay 80a108d429SJay val prefetchEnable = Input(Bool()) 81a108d429SJay val prefetchDisable = Input(Bool()) 82*b1ded4e8Sguohongyu val fencei = Input(Bool()) 83*b1ded4e8Sguohongyu} 84*b1ded4e8Sguohongyu 85*b1ded4e8Sguohongyu/** Prefetch Buffer **/ 86*b1ded4e8Sguohongyu 87*b1ded4e8Sguohongyu 88*b1ded4e8Sguohongyuclass PrefetchBuffer(implicit p: Parameters) extends IPrefetchModule 89*b1ded4e8Sguohongyu{ 90*b1ded4e8Sguohongyu val io = IO(new Bundle{ 91*b1ded4e8Sguohongyu val read = new IPFBufferRead 92*b1ded4e8Sguohongyu val filter_read = new IPFBufferFilterRead 93*b1ded4e8Sguohongyu val write = Flipped(ValidIO(new IPFBufferWrite)) 94*b1ded4e8Sguohongyu /** to ICache replacer */ 95*b1ded4e8Sguohongyu val replace = new IPFBufferMove 96*b1ded4e8Sguohongyu /** move & move filter port */ 97*b1ded4e8Sguohongyu val mainpipe_missinfo = Flipped(new MainPipeMissInfo) 98*b1ded4e8Sguohongyu val meta_filter_read = new ICacheMetaReqBundle 99*b1ded4e8Sguohongyu val move = new Bundle() { 100*b1ded4e8Sguohongyu val meta_write = DecoupledIO(new ICacheMetaWriteBundle) 101*b1ded4e8Sguohongyu val data_write = DecoupledIO(new ICacheDataWriteBundle) 102*b1ded4e8Sguohongyu } 103*b1ded4e8Sguohongyu val fencei = Input(Bool()) 104*b1ded4e8Sguohongyu }) 105*b1ded4e8Sguohongyu 106*b1ded4e8Sguohongyu class IPFBufferEntryMeta(implicit p: Parameters) extends IPrefetchBundle 107*b1ded4e8Sguohongyu { 108*b1ded4e8Sguohongyu val tag = UInt(tagBits.W) 109*b1ded4e8Sguohongyu val index = UInt(idxBits.W) 110*b1ded4e8Sguohongyu val paddr = UInt(PAddrBits.W) 111*b1ded4e8Sguohongyu val valid = Bool() 112*b1ded4e8Sguohongyu val confidence = UInt(log2Ceil(maxIPFMoveConf + 1).W) 113*b1ded4e8Sguohongyu val move = Bool() 114*b1ded4e8Sguohongyu } 115*b1ded4e8Sguohongyu 116*b1ded4e8Sguohongyu class IPFBufferEntryData(implicit p: Parameters) extends IPrefetchBundle 117*b1ded4e8Sguohongyu { 118*b1ded4e8Sguohongyu val cachline = UInt(blockBits.W) 119*b1ded4e8Sguohongyu } 120*b1ded4e8Sguohongyu 121*b1ded4e8Sguohongyu def InitQueue[T <: Data](entry: T, size: Int): Vec[T] ={ 122*b1ded4e8Sguohongyu return RegInit(VecInit(Seq.fill(size)(0.U.asTypeOf(entry.cloneType)))) 123*b1ded4e8Sguohongyu } 124*b1ded4e8Sguohongyu 125*b1ded4e8Sguohongyu val meta_buffer = InitQueue(new IPFBufferEntryMeta, size = nIPFBufferSize) 126*b1ded4e8Sguohongyu val data_buffer = InitQueue(new IPFBufferEntryData, size = nIPFBufferSize) 127*b1ded4e8Sguohongyu 128*b1ded4e8Sguohongyu /** filter read logic */ 129*b1ded4e8Sguohongyu val fr_vidx = io.filter_read.req.vSetIdx 130*b1ded4e8Sguohongyu val fr_ptag = get_phy_tag(io.filter_read.req.paddr) 131*b1ded4e8Sguohongyu 132*b1ded4e8Sguohongyu val fr_hit_in_buffer = meta_buffer.map(e => e.valid && (e.tag === fr_ptag) && (e.index === fr_vidx)).reduce(_||_) 133*b1ded4e8Sguohongyu val fr_hit_in_s1, fr_hit_in_s2, fr_hit_in_s3 = Wire(Bool()) 134*b1ded4e8Sguohongyu 135*b1ded4e8Sguohongyu io.filter_read.resp.ipf_hit := fr_hit_in_buffer || fr_hit_in_s1 || fr_hit_in_s2 || fr_hit_in_s3 136*b1ded4e8Sguohongyu 137*b1ded4e8Sguohongyu /** read logic */ 138*b1ded4e8Sguohongyu (0 until PortNumber).foreach(i => io.read.req(i).ready := true.B) 139*b1ded4e8Sguohongyu val r_valid = VecInit((0 until PortNumber).map( i => io.read.req(i).valid)).reduce(_||_) 140*b1ded4e8Sguohongyu val r_vidx = VecInit((0 until PortNumber).map(i => get_idx(io.read.req(i).bits.vaddr))) 141*b1ded4e8Sguohongyu val r_ptag = VecInit((0 until PortNumber).map(i => get_phy_tag(io.read.req(i).bits.paddr))) 142*b1ded4e8Sguohongyu val r_hit_oh = VecInit((0 until PortNumber).map(i => 143*b1ded4e8Sguohongyu VecInit(meta_buffer.map(entry => 144*b1ded4e8Sguohongyu io.read.req(i).valid && // need this condition 145*b1ded4e8Sguohongyu entry.valid && 146*b1ded4e8Sguohongyu entry.tag === r_ptag(i) && 147*b1ded4e8Sguohongyu entry.index === r_vidx(i) 148*b1ded4e8Sguohongyu )))) 149*b1ded4e8Sguohongyu val r_buffer_hit = VecInit(r_hit_oh.map(_.reduce(_||_))) 150*b1ded4e8Sguohongyu val r_buffer_hit_idx = VecInit(r_hit_oh.map(PriorityEncoder(_))) 151*b1ded4e8Sguohongyu val r_buffer_hit_data = VecInit((0 until PortNumber).map(i => Mux1H(r_hit_oh(i), data_buffer.map(_.cachline)))) 152*b1ded4e8Sguohongyu 153*b1ded4e8Sguohongyu /** "read" also check data in move pipeline */ 154*b1ded4e8Sguohongyu val r_moves1pipe_hit_s1, r_moves1pipe_hit_s2, r_moves1pipe_hit_s3 = WireInit(VecInit(Seq.fill(PortNumber)(false.B))) 155*b1ded4e8Sguohongyu val s1_move_data_cacheline, s2_move_data_cacheline, s3_move_data_cacheline = Wire(UInt(blockBits.W)) 156*b1ded4e8Sguohongyu 157*b1ded4e8Sguohongyu (0 until PortNumber).foreach{ i => 158*b1ded4e8Sguohongyu io.read.resp(i).valid := io.read.req(i).valid 159*b1ded4e8Sguohongyu io.read.resp(i).bits.ipf_hit := r_buffer_hit(i) || r_moves1pipe_hit_s1(i) || r_moves1pipe_hit_s2(i) || r_moves1pipe_hit_s3(i) 160*b1ded4e8Sguohongyu io.read.resp(i).bits.cacheline := Mux(r_buffer_hit(i), r_buffer_hit_data(i), 161*b1ded4e8Sguohongyu Mux(r_moves1pipe_hit_s1(i), s1_move_data_cacheline, 162*b1ded4e8Sguohongyu Mux(r_moves1pipe_hit_s2(i), s2_move_data_cacheline, s3_move_data_cacheline))) 163*b1ded4e8Sguohongyu } 164*b1ded4e8Sguohongyu 165*b1ded4e8Sguohongyu /** move logic */ 166*b1ded4e8Sguohongyu val r_buffer_hit_s2 = RegNext(r_buffer_hit, init=0.U.asTypeOf(r_buffer_hit.cloneType)) 167*b1ded4e8Sguohongyu val r_buffer_hit_idx_s2 = RegNext(r_buffer_hit_idx) 168*b1ded4e8Sguohongyu val r_rvalid_s2 = RegNext(r_valid, init=false.B) 169*b1ded4e8Sguohongyu 170*b1ded4e8Sguohongyu val s2_move_valid_0 = r_rvalid_s2 && r_buffer_hit_s2(0) 171*b1ded4e8Sguohongyu val s2_move_valid_1 = r_rvalid_s2 && r_buffer_hit_s2(1) 172*b1ded4e8Sguohongyu 173*b1ded4e8Sguohongyu XSPerfAccumulate("prefetch_hit_bank_0", r_rvalid_s2 && r_buffer_hit_s2(0)) 174*b1ded4e8Sguohongyu XSPerfAccumulate("prefetch_hit_bank_1", r_rvalid_s2 && r_buffer_hit_s2(1)) 175*b1ded4e8Sguohongyu 176*b1ded4e8Sguohongyu val move_queue = RegInit(VecInit(Seq.fill(nIPFBufferSize)(0.U.asTypeOf(r_buffer_hit_idx_s2(0))))) 177*b1ded4e8Sguohongyu 178*b1ded4e8Sguohongyu val curr_move_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 179*b1ded4e8Sguohongyu val curr_hit_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 180*b1ded4e8Sguohongyu 181*b1ded4e8Sguohongyu val s2_move_conf_full_0 = meta_buffer(r_buffer_hit_idx_s2(0)).confidence === (maxIPFMoveConf).U 182*b1ded4e8Sguohongyu val s2_move_conf_full_1 = meta_buffer(r_buffer_hit_idx_s2(1)).confidence === (maxIPFMoveConf).U 183*b1ded4e8Sguohongyu 184*b1ded4e8Sguohongyu val move_repeat_0 = meta_buffer(r_buffer_hit_idx_s2(0)).move 185*b1ded4e8Sguohongyu val move_repeat_1 = meta_buffer(r_buffer_hit_idx_s2(1)).move || (r_buffer_hit_idx_s2(0) === r_buffer_hit_idx_s2(1)) 186*b1ded4e8Sguohongyu 187*b1ded4e8Sguohongyu val s2_move_0 = s2_move_valid_0 && !move_repeat_0 188*b1ded4e8Sguohongyu val s2_move_1 = s2_move_valid_1 && !move_repeat_1 189*b1ded4e8Sguohongyu 190*b1ded4e8Sguohongyu val s2_move_enqueue_0 = s2_move_0 && s2_move_conf_full_0 191*b1ded4e8Sguohongyu val s2_move_enqueue_1 = s2_move_1 && s2_move_conf_full_1 192*b1ded4e8Sguohongyu 193*b1ded4e8Sguohongyu when(s2_move_0) { 194*b1ded4e8Sguohongyu when(s2_move_conf_full_0) { 195*b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(0)).move := true.B 196*b1ded4e8Sguohongyu }.otherwise { 197*b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(0)).confidence := meta_buffer(r_buffer_hit_idx_s2(0)).confidence + 1.U 198*b1ded4e8Sguohongyu } 199*b1ded4e8Sguohongyu } 200*b1ded4e8Sguohongyu when(s2_move_1) { 201*b1ded4e8Sguohongyu when(s2_move_conf_full_1) { 202*b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(1)).move := true.B 203*b1ded4e8Sguohongyu }.otherwise { 204*b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(1)).confidence := meta_buffer(r_buffer_hit_idx_s2(1)).confidence + 1.U 205*b1ded4e8Sguohongyu } 206*b1ded4e8Sguohongyu } 207*b1ded4e8Sguohongyu 208*b1ded4e8Sguohongyu when(s2_move_enqueue_0 && !s2_move_enqueue_1) { 209*b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0) 210*b1ded4e8Sguohongyu 211*b1ded4e8Sguohongyu when((curr_hit_ptr + 1.U) =/= curr_move_ptr){ 212*b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 213*b1ded4e8Sguohongyu } 214*b1ded4e8Sguohongyu }.elsewhen(!s2_move_enqueue_0 && s2_move_enqueue_1) { 215*b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(1) 216*b1ded4e8Sguohongyu 217*b1ded4e8Sguohongyu when((curr_hit_ptr + 1.U) =/= curr_move_ptr){ 218*b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 219*b1ded4e8Sguohongyu } 220*b1ded4e8Sguohongyu }.elsewhen(s2_move_enqueue_0 && s2_move_enqueue_1) { 221*b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0) 222*b1ded4e8Sguohongyu move_queue(curr_hit_ptr + 1.U) := r_buffer_hit_idx_s2(1) 223*b1ded4e8Sguohongyu when((curr_hit_ptr + 2.U) =/= curr_move_ptr){ 224*b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 2.U 225*b1ded4e8Sguohongyu }.otherwise{ 226*b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 227*b1ded4e8Sguohongyu } 228*b1ded4e8Sguohongyu } 229*b1ded4e8Sguohongyu 230*b1ded4e8Sguohongyu val move_queue_empty = curr_move_ptr === curr_hit_ptr 231*b1ded4e8Sguohongyu /** pipeline control signal */ 232*b1ded4e8Sguohongyu val s1_ready, s2_ready, s3_ready = Wire(Bool()) 233*b1ded4e8Sguohongyu val s0_fire, s1_fire, s2_fire, s3_fire = Wire(Bool()) 234*b1ded4e8Sguohongyu 235*b1ded4e8Sguohongyu /** stage 0 */ 236*b1ded4e8Sguohongyu val s0_valid = !move_queue_empty && meta_buffer(move_queue(curr_move_ptr)).move 237*b1ded4e8Sguohongyu 238*b1ded4e8Sguohongyu val s0_move_idx = move_queue(curr_move_ptr) 239*b1ded4e8Sguohongyu val s0_move_meta = meta_buffer(s0_move_idx) 240*b1ded4e8Sguohongyu val s0_move_data = data_buffer(s0_move_idx) 241*b1ded4e8Sguohongyu io.replace.vsetIdx := meta_buffer(s0_move_idx).index 242*b1ded4e8Sguohongyu val s0_waymask = io.replace.waymask 243*b1ded4e8Sguohongyu 244*b1ded4e8Sguohongyu s0_fire := s0_valid && s1_ready 245*b1ded4e8Sguohongyu 246*b1ded4e8Sguohongyu /** curr_move_ptr control logic */ 247*b1ded4e8Sguohongyu val s0_move_jump = !move_queue_empty && !meta_buffer(move_queue(curr_move_ptr)).move 248*b1ded4e8Sguohongyu when (s0_fire) { 249*b1ded4e8Sguohongyu curr_move_ptr := curr_move_ptr + 1.U 250*b1ded4e8Sguohongyu meta_buffer(s0_move_idx).valid := false.B 251*b1ded4e8Sguohongyu meta_buffer(s0_move_idx).move := false.B 252*b1ded4e8Sguohongyu meta_buffer(s0_move_idx).confidence := 0.U 253*b1ded4e8Sguohongyu }.elsewhen(s0_move_jump) { 254*b1ded4e8Sguohongyu curr_move_ptr := curr_move_ptr + 1.U 255*b1ded4e8Sguohongyu } 256*b1ded4e8Sguohongyu 257*b1ded4e8Sguohongyu /** stage 1 : send req to metaArray */ 258*b1ded4e8Sguohongyu val s1_valid = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = io.fencei, lastFlush = false.B) 259*b1ded4e8Sguohongyu 260*b1ded4e8Sguohongyu val s1_move_idx = RegEnable(s0_move_idx, s0_fire) 261*b1ded4e8Sguohongyu val s1_move_meta = RegEnable(s0_move_meta, s0_fire) 262*b1ded4e8Sguohongyu val s1_move_data = RegEnable(s0_move_data, s0_fire) 263*b1ded4e8Sguohongyu val s1_waymask = RegEnable(s0_waymask, s0_fire) 264*b1ded4e8Sguohongyu 265*b1ded4e8Sguohongyu io.meta_filter_read.toIMeta.valid := s1_valid 266*b1ded4e8Sguohongyu io.meta_filter_read.toIMeta.bits.isDoubleLine := false.B 267*b1ded4e8Sguohongyu io.meta_filter_read.toIMeta.bits.vSetIdx(0) := s1_move_meta.index // just use port 0 268*b1ded4e8Sguohongyu io.meta_filter_read.toIMeta.bits.vSetIdx(1) := DontCare 269*b1ded4e8Sguohongyu 270*b1ded4e8Sguohongyu s1_ready := !s1_valid || s1_fire 271*b1ded4e8Sguohongyu s1_fire := s1_valid && io.meta_filter_read.toIMeta.ready && s2_ready 272*b1ded4e8Sguohongyu 273*b1ded4e8Sguohongyu fr_hit_in_s1 := s1_valid && s1_move_meta.index === fr_vidx && s1_move_meta.tag === fr_ptag 274*b1ded4e8Sguohongyu r_moves1pipe_hit_s1 := VecInit((0 until PortNumber).map(i => s1_valid && r_ptag(i) === s1_move_meta.tag && r_vidx(i) === s1_move_meta.index)) 275*b1ded4e8Sguohongyu s1_move_data_cacheline := s1_move_data.cachline 276*b1ded4e8Sguohongyu 277*b1ded4e8Sguohongyu /** stage 2 : collect message from metaArray and mainPipe to filter */ 278*b1ded4e8Sguohongyu val s2_valid = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = io.fencei, lastFlush = false.B) 279*b1ded4e8Sguohongyu 280*b1ded4e8Sguohongyu val s2_move_idx = RegEnable(s1_move_idx, s1_fire) 281*b1ded4e8Sguohongyu val s2_move_meta = RegEnable(s1_move_meta, s1_fire) 282*b1ded4e8Sguohongyu val s2_move_data = RegEnable(s1_move_data, s1_fire) 283*b1ded4e8Sguohongyu val s2_waymask = RegEnable(s1_waymask, s1_fire) 284*b1ded4e8Sguohongyu 285*b1ded4e8Sguohongyu val s2_meta_ptags = ResultHoldBypass(data = io.meta_filter_read.fromIMeta.tags, valid = RegNext(s1_fire)) 286*b1ded4e8Sguohongyu val s2_meta_valids = ResultHoldBypass(data = io.meta_filter_read.fromIMeta.entryValid, valid = RegNext(s1_fire)) 287*b1ded4e8Sguohongyu 288*b1ded4e8Sguohongyu val s2_tag_eq_vec = VecInit((0 until nWays).map(w => s2_meta_ptags(0)(w) === s2_move_meta.tag)) // just use port 0 289*b1ded4e8Sguohongyu val s2_tag_match_vec = VecInit(s2_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s2_meta_valids(0)(w)}) 290*b1ded4e8Sguohongyu val s2_hit_in_meta_array = ParallelOR(s2_tag_match_vec) 291*b1ded4e8Sguohongyu 292*b1ded4e8Sguohongyu val main_s2_missinfo = io.mainpipe_missinfo.s2_miss_info 293*b1ded4e8Sguohongyu val s2_hit_main_s2_missreq = VecInit((0 until PortNumber).map(i => 294*b1ded4e8Sguohongyu main_s2_missinfo(i).valid && s2_move_meta.index === main_s2_missinfo(i).bits.vSetIdx 295*b1ded4e8Sguohongyu && s2_move_meta.tag === main_s2_missinfo(i).bits.ptage)).reduce(_||_) 296*b1ded4e8Sguohongyu 297*b1ded4e8Sguohongyu val s2_discard = s2_hit_in_meta_array || s2_hit_main_s2_missreq // || s2_hit_main_s1_missreq 298*b1ded4e8Sguohongyu val s2_discard_latch = holdReleaseLatch(valid = s2_discard, release = s2_fire, flush = io.fencei) 299*b1ded4e8Sguohongyu if(DebugFlags.fdip){ 300*b1ded4e8Sguohongyu when (s2_fire && s2_discard_latch) { 301*b1ded4e8Sguohongyu printf("<%d> IPrefetchBuffer: s2_discard : hit_in_meta_array=%d,hit_in_main_s2=%d, ptag=0x%x\n", 302*b1ded4e8Sguohongyu GTimer(), s2_hit_in_meta_array, s2_hit_main_s2_missreq, s2_move_meta.tag) 303*b1ded4e8Sguohongyu } 304*b1ded4e8Sguohongyu } 305*b1ded4e8Sguohongyu 306*b1ded4e8Sguohongyu s2_ready := !s2_valid || s2_fire 307*b1ded4e8Sguohongyu s2_fire := s2_valid && s3_ready && io.mainpipe_missinfo.s1_already_check_ipf 308*b1ded4e8Sguohongyu 309*b1ded4e8Sguohongyu fr_hit_in_s2 := s2_valid && s2_move_meta.index === fr_vidx && s2_move_meta.tag === fr_ptag 310*b1ded4e8Sguohongyu r_moves1pipe_hit_s2 := VecInit((0 until PortNumber).map(i => s2_valid && r_ptag(i) === s2_move_meta.tag && r_vidx(i) === s2_move_meta.index)) 311*b1ded4e8Sguohongyu s2_move_data_cacheline := s2_move_data.cachline 312*b1ded4e8Sguohongyu 313*b1ded4e8Sguohongyu /** stage 3 : move data to metaArray and dataArray */ 314*b1ded4e8Sguohongyu val s3_valid = generatePipeControl(lastFire = s2_fire, thisFire = s3_fire, thisFlush = io.fencei, lastFlush = false.B) 315*b1ded4e8Sguohongyu 316*b1ded4e8Sguohongyu val s3_move_idx = RegEnable(s2_move_idx, s2_fire) 317*b1ded4e8Sguohongyu val s3_move_meta = RegEnable(s2_move_meta, s2_fire) 318*b1ded4e8Sguohongyu val s3_move_data = RegEnable(s2_move_data, s2_fire) 319*b1ded4e8Sguohongyu val s3_waymask = RegEnable(s2_waymask, s2_fire) 320*b1ded4e8Sguohongyu val s3_discard = RegEnable(s2_discard_latch, s2_fire) 321*b1ded4e8Sguohongyu 322*b1ded4e8Sguohongyu io.move.meta_write.valid := s3_valid && !s3_discard && !io.fencei 323*b1ded4e8Sguohongyu io.move.data_write.valid := s3_valid && !s3_discard && !io.fencei 324*b1ded4e8Sguohongyu io.move.meta_write.bits.generate( 325*b1ded4e8Sguohongyu tag = s3_move_meta.tag, 326*b1ded4e8Sguohongyu idx = s3_move_meta.index, 327*b1ded4e8Sguohongyu waymask = s3_waymask, 328*b1ded4e8Sguohongyu bankIdx = s3_move_meta.index(0)) 329*b1ded4e8Sguohongyu io.move.data_write.bits.generate( 330*b1ded4e8Sguohongyu data = s3_move_data.cachline, 331*b1ded4e8Sguohongyu idx = s3_move_meta.index, 332*b1ded4e8Sguohongyu waymask = s3_waymask, 333*b1ded4e8Sguohongyu bankIdx = s3_move_meta.index(0), 334*b1ded4e8Sguohongyu paddr = s3_move_meta.paddr) 335*b1ded4e8Sguohongyu 336*b1ded4e8Sguohongyu s3_ready := !s3_valid || s3_fire 337*b1ded4e8Sguohongyu s3_fire := io.move.meta_write.fire && io.move.data_write.fire || s3_discard || io.fencei 338*b1ded4e8Sguohongyu assert((io.move.meta_write.fire && io.move.data_write.fire) || (!io.move.meta_write.fire && !io.move.data_write.fire), 339*b1ded4e8Sguohongyu "meta and data array need fire at same time") 340*b1ded4e8Sguohongyu 341*b1ded4e8Sguohongyu fr_hit_in_s3 := s3_valid && s3_move_meta.index === fr_vidx && s3_move_meta.tag === fr_ptag 342*b1ded4e8Sguohongyu r_moves1pipe_hit_s3 := VecInit((0 until PortNumber).map(i => s3_valid && r_ptag(i) === s3_move_meta.tag && r_vidx(i) === s3_move_meta.index)) 343*b1ded4e8Sguohongyu s3_move_data_cacheline := s3_move_data.cachline 344*b1ded4e8Sguohongyu 345*b1ded4e8Sguohongyu if (DebugFlags.fdip) { 346*b1ded4e8Sguohongyu when(io.move.meta_write.fire) { 347*b1ded4e8Sguohongyu printf("<%d> IPrefetchBuffer: move data to meta sram:ptag=0x%x,vidx=0x%x,waymask=0x%x\n", 348*b1ded4e8Sguohongyu GTimer(), s3_move_meta.tag,s3_move_meta.index,s3_waymask ) 349*b1ded4e8Sguohongyu } 350*b1ded4e8Sguohongyu } 351*b1ded4e8Sguohongyu 352*b1ded4e8Sguohongyu /** write logic */ 353*b1ded4e8Sguohongyu val replacer = ReplacementPolicy.fromString(Some("random"), nIPFBufferSize) 354*b1ded4e8Sguohongyu val curr_write_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 355*b1ded4e8Sguohongyu val victim_way = curr_write_ptr + 1.U//replacer.way 356*b1ded4e8Sguohongyu 357*b1ded4e8Sguohongyu when(io.write.valid) { 358*b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).tag := io.write.bits.meta.tag 359*b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).index := io.write.bits.meta.index 360*b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).paddr := io.write.bits.meta.paddr 361*b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).valid := true.B 362*b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).move := false.B 363*b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).confidence := 0.U 364*b1ded4e8Sguohongyu 365*b1ded4e8Sguohongyu data_buffer(curr_write_ptr).cachline := io.write.bits.data 366*b1ded4e8Sguohongyu 367*b1ded4e8Sguohongyu //update replacer 368*b1ded4e8Sguohongyu replacer.access(curr_write_ptr) 369*b1ded4e8Sguohongyu curr_write_ptr := victim_way 370*b1ded4e8Sguohongyu 371*b1ded4e8Sguohongyu } 372*b1ded4e8Sguohongyu 373*b1ded4e8Sguohongyu /** fencei: invalid all entries */ 374*b1ded4e8Sguohongyu when(io.fencei) { 375*b1ded4e8Sguohongyu meta_buffer.foreach{ 376*b1ded4e8Sguohongyu case b => 377*b1ded4e8Sguohongyu b.valid := false.B 378*b1ded4e8Sguohongyu b.move := false.B 379*b1ded4e8Sguohongyu b.confidence := 0.U 380*b1ded4e8Sguohongyu } 381*b1ded4e8Sguohongyu } 382*b1ded4e8Sguohongyu 3837052722fSJay} 3847052722fSJay 3857052722fSJayclass IPrefetchPipe(implicit p: Parameters) extends IPrefetchModule 3867052722fSJay{ 3877052722fSJay val io = IO(new IPredfetchIO) 3887052722fSJay 389a108d429SJay val enableBit = RegInit(false.B) 390*b1ded4e8Sguohongyu val maxPrefetchCounter = RegInit(0.U(log2Ceil(nPrefetchEntries + 1).W)) 391a108d429SJay 392*b1ded4e8Sguohongyu val reachMaxSize = maxPrefetchCounter === nPrefetchEntries.U 393a108d429SJay 394*b1ded4e8Sguohongyu // when(io.prefetchEnable){ 395*b1ded4e8Sguohongyu // enableBit := true.B 396*b1ded4e8Sguohongyu // }.elsewhen((enableBit && io.prefetchDisable) || (enableBit && reachMaxSize)){ 397*b1ded4e8Sguohongyu // enableBit := false.B 398*b1ded4e8Sguohongyu // } 399*b1ded4e8Sguohongyu // ignore prefetchEnable from ICacheMainPipe 400a108d429SJay enableBit := true.B 401a108d429SJay 402a108d429SJay class PrefetchDir(implicit p: Parameters) extends IPrefetchBundle 403a108d429SJay { 404a108d429SJay val valid = Bool() 405a108d429SJay val paddr = UInt(PAddrBits.W) 406a108d429SJay } 407a108d429SJay 408a108d429SJay val prefetch_dir = RegInit(VecInit(Seq.fill(nPrefetchEntries)(0.U.asTypeOf(new PrefetchDir)))) 409a108d429SJay 4107052722fSJay val fromFtq = io.fromFtq 411*b1ded4e8Sguohongyu val fromMainPipe = io.fromMainPipe 4127052722fSJay val (toITLB, fromITLB) = (io.iTLBInter.req, io.iTLBInter.resp) 413c3b763d0SYinan Xu io.iTLBInter.req_kill := false.B 414*b1ded4e8Sguohongyu val (toIMeta, fromIMeta, fromIMetaValid) = (io.toIMeta, io.fromIMeta.metaData(0), io.fromIMeta.entryValid(0)) 415*b1ded4e8Sguohongyu val (toIPFBuffer, fromIPFBuffer) = (io.IPFBufferRead.req, io.IPFBufferRead.resp) 4167052722fSJay val (toPMP, fromPMP) = (io.pmp.req, io.pmp.resp) 4177052722fSJay val toMissUnit = io.toMissUnit 4187052722fSJay 4197052722fSJay val p0_fire, p1_fire, p2_fire, p3_fire = WireInit(false.B) 420*b1ded4e8Sguohongyu val p0_discard, p1_discard, p2_discard, p3_discard = WireInit(false.B) 4217052722fSJay val p0_ready, p1_ready, p2_ready, p3_ready = WireInit(false.B) 4227052722fSJay 4237052722fSJay /** Prefetch Stage 0: req from Ftq */ 4247052722fSJay val p0_valid = fromFtq.req.valid 425d6b06a99SJay val p0_vaddr = addrAlign(fromFtq.req.bits.target, blockBytes, VAddrBits) 426*b1ded4e8Sguohongyu val p0_vaddr_reg = RegEnable(p0_vaddr, fromFtq.req.fire()) 4277052722fSJay 428*b1ded4e8Sguohongyu /* Cancel request when prefetch not enable 429*b1ded4e8Sguohongyu * or the request from FTQ is same as last time */ 430*b1ded4e8Sguohongyu val p0_req_cancel = !enableBit || (p0_vaddr === p0_vaddr_reg) || io.fencei 431*b1ded4e8Sguohongyu p0_fire := p0_valid && p1_ready && toITLB.fire() && !fromITLB.bits.miss && toIMeta.ready && enableBit && !p0_req_cancel 432*b1ded4e8Sguohongyu p0_discard := p0_valid && p0_req_cancel 433*b1ded4e8Sguohongyu 434*b1ded4e8Sguohongyu toIMeta.valid := p0_valid && !p0_discard 435afed18b5SJenius toIMeta.bits.vSetIdx(0) := get_idx(p0_vaddr) 436*b1ded4e8Sguohongyu 437afed18b5SJenius toIMeta.bits.vSetIdx(1) := DontCare 438afed18b5SJenius toIMeta.bits.isDoubleLine := false.B 4397052722fSJay 440*b1ded4e8Sguohongyu toITLB.valid := p0_valid && !p0_discard 4417052722fSJay toITLB.bits.size := 3.U // TODO: fix the size 4427052722fSJay toITLB.bits.vaddr := p0_vaddr 4437052722fSJay toITLB.bits.debug.pc := p0_vaddr 4447052722fSJay 445f1fe8698SLemover toITLB.bits.kill := DontCare 4467052722fSJay toITLB.bits.cmd := TlbCmd.exec 447f1fe8698SLemover toITLB.bits.debug.robIdx := DontCare 4487052722fSJay toITLB.bits.debug.isFirstIssue := DontCare 449*b1ded4e8Sguohongyu toITLB.bits.memidx := DontCare 450*b1ded4e8Sguohongyu toITLB.bits.no_translate := false.B 4517052722fSJay 4527052722fSJay fromITLB.ready := true.B 4537052722fSJay 454*b1ded4e8Sguohongyu fromFtq.req.ready := !p0_valid || p0_fire || p0_discard 4557052722fSJay 4567052722fSJay /** Prefetch Stage 1: cache probe filter */ 4577052722fSJay val p1_valid = generatePipeControl(lastFire = p0_fire, thisFire = p1_fire || p1_discard, thisFlush = false.B, lastFlush = false.B) 4587052722fSJay 459005e809bSJiuyang Liu val p1_vaddr = RegEnable(p0_vaddr, p0_fire) 460*b1ded4e8Sguohongyu // TODO: tlb is none blocked ,when tlb miss, p1 req need cancle. Now there seemes has bug 4617052722fSJay //tlb resp 462de7689fcSJay val tlb_resp_valid = RegInit(false.B) 463de7689fcSJay when(p0_fire) {tlb_resp_valid := true.B} 464de7689fcSJay .elsewhen(tlb_resp_valid && (p1_fire || p1_discard)) {tlb_resp_valid := false.B} 4657052722fSJay 46603efd994Shappy-lx val tlb_resp_paddr = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.paddr(0)) 46703efd994Shappy-lx val tlb_resp_pf = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).pf.instr && tlb_resp_valid) 46803efd994Shappy-lx val tlb_resp_af = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).af.instr && tlb_resp_valid) 4697052722fSJay 4707052722fSJay val p1_exception = VecInit(Seq(tlb_resp_pf, tlb_resp_af)) 4717052722fSJay val p1_has_except = p1_exception.reduce(_ || _) 472*b1ded4e8Sguohongyu val p1_paddr = tlb_resp_paddr 4737052722fSJay 474*b1ded4e8Sguohongyu val p1_ptag = get_phy_tag(p1_paddr) 4757052722fSJay 4767052722fSJay val p1_meta_ptags = ResultHoldBypass(data = VecInit(fromIMeta.map(way => way.tag)),valid = RegNext(p0_fire)) 477*b1ded4e8Sguohongyu val p1_meta_valids = ResultHoldBypass(data = fromIMetaValid,valid = RegNext(p0_fire)) 478*b1ded4e8Sguohongyu 4797052722fSJay val p1_tag_eq_vec = VecInit(p1_meta_ptags.map(_ === p1_ptag )) 480*b1ded4e8Sguohongyu val p1_tag_match_vec = VecInit(p1_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && p1_meta_valids(w)}) 4817052722fSJay val p1_tag_match = ParallelOR(p1_tag_match_vec) 482*b1ded4e8Sguohongyu 483*b1ded4e8Sguohongyu val p1_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p1_paddr, blockBytes, PAddrBits))).reduce(_||_) 484*b1ded4e8Sguohongyu 485*b1ded4e8Sguohongyu val (p1_hit, p1_miss) = (p1_valid && (p1_tag_match || p1_check_in_mshr) && !p1_has_except , p1_valid && !p1_tag_match && !p1_has_except && !p1_check_in_mshr) 486*b1ded4e8Sguohongyu 4877052722fSJay 4887052722fSJay //overriding the invalid req 489*b1ded4e8Sguohongyu val p1_req_cancle = (p1_hit || (tlb_resp_valid && p1_exception.reduce(_ || _)) || io.fencei) && p1_valid 4907052722fSJay val p1_req_accept = p1_valid && tlb_resp_valid && p1_miss 4917052722fSJay 4927052722fSJay p1_ready := p1_fire || p1_req_cancle || !p1_valid 493a108d429SJay p1_fire := p1_valid && p1_req_accept && p2_ready && enableBit 4947052722fSJay p1_discard := p1_valid && p1_req_cancle 4957052722fSJay 4967052722fSJay /** Prefetch Stage 2: filtered req PIQ enqueue */ 4977052722fSJay val p2_valid = generatePipeControl(lastFire = p1_fire, thisFire = p2_fire || p2_discard, thisFlush = false.B, lastFlush = false.B) 498*b1ded4e8Sguohongyu val p2_pmp_fire = p2_valid 499*b1ded4e8Sguohongyu val pmpExcpAF = fromPMP.instr 5007052722fSJay 501*b1ded4e8Sguohongyu val p2_paddr = RegEnable(p1_paddr, p1_fire) 502*b1ded4e8Sguohongyu val p2_except_pf = RegEnable(tlb_resp_pf, p1_fire) 503*b1ded4e8Sguohongyu val p2_except_af = DataHoldBypass(pmpExcpAF, p2_pmp_fire) || RegEnable(tlb_resp_af, p1_fire) 504*b1ded4e8Sguohongyu val p2_mmio = DataHoldBypass(io.pmp.resp.mmio && !p2_except_af && !p2_except_pf, p2_pmp_fire) 505*b1ded4e8Sguohongyu val p2_vaddr = RegEnable(p1_vaddr, p1_fire) 506*b1ded4e8Sguohongyu 5077052722fSJay 50800240ba6SJay /*when a prefetch req meet with a miss req in MSHR cancle the prefetch req */ 50900240ba6SJay val p2_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p2_paddr, blockBytes, PAddrBits))).reduce(_||_) 51000240ba6SJay 5117052722fSJay //TODO wait PMP logic 512*b1ded4e8Sguohongyu val p2_exception = VecInit(Seq(pmpExcpAF, p2_mmio)).reduce(_||_) 513*b1ded4e8Sguohongyu 514*b1ded4e8Sguohongyu io.pmp.req.valid := p2_pmp_fire 515*b1ded4e8Sguohongyu io.pmp.req.bits.addr := p2_paddr 516*b1ded4e8Sguohongyu io.pmp.req.bits.size := 3.U 517*b1ded4e8Sguohongyu io.pmp.req.bits.cmd := TlbCmd.exec 5187052722fSJay 5197052722fSJay p2_ready := p2_fire || p2_discard || !p2_valid 520*b1ded4e8Sguohongyu p2_fire := p2_valid && !p2_exception && p3_ready && p2_pmp_fire 521*b1ded4e8Sguohongyu p2_discard := p2_valid && (p2_exception && p2_pmp_fire || io.fencei) 5227052722fSJay 5237052722fSJay /** Prefetch Stage 2: filtered req PIQ enqueue */ 524a108d429SJay val p3_valid = generatePipeControl(lastFire = p2_fire, thisFire = p3_fire || p3_discard, thisFlush = false.B, lastFlush = false.B) 5257052722fSJay 526*b1ded4e8Sguohongyu val p3_paddr = RegEnable(p2_paddr, p2_fire) 527*b1ded4e8Sguohongyu val p3_check_in_mshr = RegEnable(p2_check_in_mshr, p2_fire) 528*b1ded4e8Sguohongyu val p3_vaddr = RegEnable(p2_vaddr, p2_fire) 529*b1ded4e8Sguohongyu val p3_vidx = get_idx(p3_vaddr) 530*b1ded4e8Sguohongyu // check in prefetch buffer 531*b1ded4e8Sguohongyu toIPFBuffer.vSetIdx := p3_vidx 532*b1ded4e8Sguohongyu toIPFBuffer.paddr := p3_paddr 533*b1ded4e8Sguohongyu val p3_buffer_hit = fromIPFBuffer.ipf_hit 5347052722fSJay 535a108d429SJay val p3_hit_dir = VecInit((0 until nPrefetchEntries).map(i => prefetch_dir(i).valid && prefetch_dir(i).paddr === p3_paddr )).reduce(_||_) 536*b1ded4e8Sguohongyu //Cache miss handling by main pipe 537*b1ded4e8Sguohongyu val p3_hit_mp_miss = VecInit((0 until PortNumber).map(i => fromMainPipe(i).valid && (fromMainPipe(i).bits.ptage === get_phy_tag(p3_paddr) && 538*b1ded4e8Sguohongyu (fromMainPipe(i).bits.vSetIdx === p3_vidx)))).reduce(_||_) 539*b1ded4e8Sguohongyu val p3_req_cancel = p3_hit_dir || p3_check_in_mshr || !enableBit || p3_hit_mp_miss || p3_buffer_hit || io.fencei 540*b1ded4e8Sguohongyu p3_discard := p3_valid && p3_req_cancel 541a108d429SJay 542*b1ded4e8Sguohongyu toMissUnit.enqReq.valid := p3_valid && !p3_req_cancel 5437052722fSJay toMissUnit.enqReq.bits.paddr := p3_paddr 544*b1ded4e8Sguohongyu toMissUnit.enqReq.bits.vSetIdx := p3_vidx 5457052722fSJay 546*b1ded4e8Sguohongyu when(io.fencei){ 547*b1ded4e8Sguohongyu maxPrefetchCounter := 0.U 548a108d429SJay 549a108d429SJay prefetch_dir.foreach(_.valid := false.B) 550a108d429SJay }.elsewhen(toMissUnit.enqReq.fire()){ 551*b1ded4e8Sguohongyu when(reachMaxSize){ 552*b1ded4e8Sguohongyu prefetch_dir(io.freePIQEntry).paddr := p3_paddr 553*b1ded4e8Sguohongyu }.otherwise { 554*b1ded4e8Sguohongyu maxPrefetchCounter := maxPrefetchCounter + 1.U 555a108d429SJay 556*b1ded4e8Sguohongyu prefetch_dir(maxPrefetchCounter).valid := true.B 557*b1ded4e8Sguohongyu prefetch_dir(maxPrefetchCounter).paddr := p3_paddr 558*b1ded4e8Sguohongyu } 559a108d429SJay } 560a108d429SJay 561a108d429SJay p3_ready := toMissUnit.enqReq.ready || !enableBit 5627052722fSJay p3_fire := toMissUnit.enqReq.fire() 5637052722fSJay 5647052722fSJay} 5657052722fSJay 566*b1ded4e8Sguohongyuclass PIQEntry(edge: TLEdgeOut, id: Int)(implicit p: Parameters) extends IPrefetchModule 5677052722fSJay{ 5687052722fSJay val io = IO(new Bundle{ 569*b1ded4e8Sguohongyu val id = Input(UInt((log2Ceil(nPrefetchEntries + PortNumber)).W)) 5707052722fSJay 5717052722fSJay val req = Flipped(DecoupledIO(new PIQReq)) 5727052722fSJay 573*b1ded4e8Sguohongyu val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 574*b1ded4e8Sguohongyu val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 5757052722fSJay 576*b1ded4e8Sguohongyu //write back to Prefetch Buffer 577*b1ded4e8Sguohongyu val piq_write_ipbuffer = DecoupledIO(new IPFBufferWrite) 578*b1ded4e8Sguohongyu 579*b1ded4e8Sguohongyu //TODO: fencei flush instructions 580*b1ded4e8Sguohongyu val fencei = Input(Bool()) 581*b1ded4e8Sguohongyu 582*b1ded4e8Sguohongyu val prefetch_entry_data = DecoupledIO(new PIQData) 5837052722fSJay }) 5847052722fSJay 585*b1ded4e8Sguohongyu val s_idle :: s_memReadReq :: s_memReadResp :: s_write_back :: s_finish:: Nil = Enum(5) 5867052722fSJay val state = RegInit(s_idle) 5877052722fSJay 588*b1ded4e8Sguohongyu //req register 589*b1ded4e8Sguohongyu val req = Reg(new PIQReq) 590*b1ded4e8Sguohongyu val req_idx = req.vSetIdx //virtual index 591*b1ded4e8Sguohongyu val req_tag = get_phy_tag(req.paddr) //physical tag 592*b1ded4e8Sguohongyu 593*b1ded4e8Sguohongyu val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant) 594*b1ded4e8Sguohongyu 595*b1ded4e8Sguohongyu //8 for 64 bits bus and 2 for 256 bits 596*b1ded4e8Sguohongyu val readBeatCnt = Reg(UInt(log2Up(refillCycles).W)) 597*b1ded4e8Sguohongyu val respDataReg = Reg(Vec(refillCycles,UInt(beatBits.W))) 598*b1ded4e8Sguohongyu 599*b1ded4e8Sguohongyu //to main pipe s1 600*b1ded4e8Sguohongyu io.prefetch_entry_data.valid := state =/= s_idle 601*b1ded4e8Sguohongyu io.prefetch_entry_data.bits.vSetIdx := req_idx 602*b1ded4e8Sguohongyu io.prefetch_entry_data.bits.ptage := req_tag 603*b1ded4e8Sguohongyu io.prefetch_entry_data.bits.cacheline := respDataReg.asUInt 604*b1ded4e8Sguohongyu io.prefetch_entry_data.bits.writeBack := state === s_write_back 605*b1ded4e8Sguohongyu 606*b1ded4e8Sguohongyu //initial 607*b1ded4e8Sguohongyu io.mem_acquire.bits := DontCare 608*b1ded4e8Sguohongyu io.mem_grant.ready := true.B 609*b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits:= DontCare 610*b1ded4e8Sguohongyu 611*b1ded4e8Sguohongyu io.req.ready := state === s_idle 612*b1ded4e8Sguohongyu io.mem_acquire.valid := state === s_memReadReq 613*b1ded4e8Sguohongyu 614*b1ded4e8Sguohongyu val needFlushReg = RegInit(false.B) 615*b1ded4e8Sguohongyu when(state === s_idle || state === s_finish){ 616*b1ded4e8Sguohongyu needFlushReg := false.B 617*b1ded4e8Sguohongyu } 618*b1ded4e8Sguohongyu when((state === s_memReadReq || state === s_memReadResp || state === s_write_back) && io.fencei){ 619*b1ded4e8Sguohongyu needFlushReg := true.B 620*b1ded4e8Sguohongyu } 621*b1ded4e8Sguohongyu val needFlush = needFlushReg || io.fencei 6227052722fSJay 6237052722fSJay //state change 6247052722fSJay switch(state){ 6257052722fSJay is(s_idle){ 6267052722fSJay when(io.req.fire()){ 627*b1ded4e8Sguohongyu readBeatCnt := 0.U 628*b1ded4e8Sguohongyu state := s_memReadReq 6297052722fSJay req := io.req.bits 6307052722fSJay } 6317052722fSJay } 6327052722fSJay 6337052722fSJay // memory request 634*b1ded4e8Sguohongyu is(s_memReadReq){ 635*b1ded4e8Sguohongyu when(io.mem_acquire.fire()){ 636*b1ded4e8Sguohongyu state := s_memReadResp 637*b1ded4e8Sguohongyu } 638*b1ded4e8Sguohongyu } 639*b1ded4e8Sguohongyu 640*b1ded4e8Sguohongyu is(s_memReadResp){ 641*b1ded4e8Sguohongyu when (edge.hasData(io.mem_grant.bits)) { 642*b1ded4e8Sguohongyu when (io.mem_grant.fire()) { 643*b1ded4e8Sguohongyu readBeatCnt := readBeatCnt + 1.U 644*b1ded4e8Sguohongyu respDataReg(readBeatCnt) := io.mem_grant.bits.data 645*b1ded4e8Sguohongyu when (readBeatCnt === (refillCycles - 1).U) { 646*b1ded4e8Sguohongyu assert(refill_done, "refill not done!") 647*b1ded4e8Sguohongyu state := s_write_back 648*b1ded4e8Sguohongyu } 649*b1ded4e8Sguohongyu } 650*b1ded4e8Sguohongyu } 651*b1ded4e8Sguohongyu } 652*b1ded4e8Sguohongyu 653*b1ded4e8Sguohongyu is(s_write_back){ 654*b1ded4e8Sguohongyu state := Mux(io.piq_write_ipbuffer.fire() || needFlush, s_finish, s_write_back) 655*b1ded4e8Sguohongyu } 656*b1ded4e8Sguohongyu 657*b1ded4e8Sguohongyu is(s_finish){ 6587052722fSJay state := s_idle 6597052722fSJay } 6607052722fSJay } 6617052722fSJay 662*b1ded4e8Sguohongyu //refill write and meta write 663*b1ded4e8Sguohongyu //WARNING: Maybe could not finish refill in 1 cycle 664*b1ded4e8Sguohongyu io.piq_write_ipbuffer.valid := (state === s_write_back) && !needFlush 665*b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.tag := req_tag 666*b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.index := req_idx 667*b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.paddr := req.paddr 668*b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.data := respDataReg.asUInt 669*b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.buffIdx := io.id - PortNumber.U 6707052722fSJay 6717052722fSJay XSPerfAccumulate("PrefetchEntryReq" + Integer.toString(id, 10), io.req.fire()) 6727052722fSJay 673*b1ded4e8Sguohongyu //mem request 674*b1ded4e8Sguohongyu io.mem_acquire.bits := edge.Get( 675*b1ded4e8Sguohongyu fromSource = io.id, 676*b1ded4e8Sguohongyu toAddress = Cat(req.paddr(PAddrBits - 1, log2Ceil(blockBytes)), 0.U(log2Ceil(blockBytes).W)), 677*b1ded4e8Sguohongyu lgSize = (log2Up(cacheParams.blockBytes)).U)._2 678*b1ded4e8Sguohongyu 6797052722fSJay} 680