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._ 26b1ded4e8Sguohongyuimport utility._ 277052722fSJay 287052722fSJay 297052722fSJayabstract class IPrefetchBundle(implicit p: Parameters) extends ICacheBundle 307052722fSJayabstract class IPrefetchModule(implicit p: Parameters) extends ICacheModule 317052722fSJay 32b1ded4e8Sguohongyu//TODO: remove this 33b1ded4e8Sguohongyuobject DebugFlags { 34b1ded4e8Sguohongyu val fdip = false 357052722fSJay} 367052722fSJay 37b1ded4e8Sguohongyuclass PIQReq(implicit p: Parameters) extends IPrefetchBundle { 38b1ded4e8Sguohongyu val paddr = UInt(PAddrBits.W) 39b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 40b1ded4e8Sguohongyu} 41b1ded4e8Sguohongyu 42b1ded4e8Sguohongyuclass PIQData(implicit p: Parameters) extends IPrefetchBundle { 43b1ded4e8Sguohongyu val ptage = UInt(tagBits.W) 44b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 45b1ded4e8Sguohongyu val cacheline = UInt(blockBits.W) 46b1ded4e8Sguohongyu val writeBack = Bool() 47b1ded4e8Sguohongyu} 48b1ded4e8Sguohongyu 49b1ded4e8Sguohongyuclass PIQToMainPipe(implicit p: Parameters) extends IPrefetchBundle{ 50b1ded4e8Sguohongyu val info = DecoupledIO(new PIQData) 51b1ded4e8Sguohongyu} 52b1ded4e8Sguohongyu/* need change name */ 53b1ded4e8Sguohongyuclass MainPipeToPrefetchPipe(implicit p: Parameters) extends IPrefetchBundle { 54b1ded4e8Sguohongyu val ptage = UInt(tagBits.W) 55b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 56b1ded4e8Sguohongyu} 57b1ded4e8Sguohongyu 58b1ded4e8Sguohongyuclass MainPipeMissInfo(implicit p: Parameters) extends IPrefetchBundle { 59b1ded4e8Sguohongyu val s1_already_check_ipf = Output(Bool()) 60b1ded4e8Sguohongyu val s2_miss_info = Vec(PortNumber, ValidIO(new MainPipeToPrefetchPipe)) 61b1ded4e8Sguohongyu} 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 71b1ded4e8Sguohongyu val toIMeta = Decoupled(new ICacheReadBundle) 727052722fSJay val fromIMeta = Input(new ICacheMetaRespBundle) 737052722fSJay val toMissUnit = new IPrefetchToMissUnit 74b1ded4e8Sguohongyu val freePIQEntry = Input(UInt(log2Ceil(nPrefetchEntries).W)) 7500240ba6SJay val fromMSHR = Flipped(Vec(PortNumber,ValidIO(UInt(PAddrBits.W)))) 76b1ded4e8Sguohongyu val IPFBufferRead = Flipped(new IPFBufferFilterRead) 77b1ded4e8Sguohongyu /** icache main pipe to prefetch pipe*/ 78b1ded4e8Sguohongyu val fromMainPipe = Flipped(Vec(PortNumber,ValidIO(new MainPipeToPrefetchPipe))) 79a108d429SJay 80a108d429SJay val prefetchEnable = Input(Bool()) 81a108d429SJay val prefetchDisable = Input(Bool()) 82b1ded4e8Sguohongyu val fencei = Input(Bool()) 83b1ded4e8Sguohongyu} 84b1ded4e8Sguohongyu 85b1ded4e8Sguohongyu/** Prefetch Buffer **/ 86b1ded4e8Sguohongyu 87b1ded4e8Sguohongyu 88b1ded4e8Sguohongyuclass PrefetchBuffer(implicit p: Parameters) extends IPrefetchModule 89b1ded4e8Sguohongyu{ 90b1ded4e8Sguohongyu val io = IO(new Bundle{ 91b1ded4e8Sguohongyu val read = new IPFBufferRead 92b1ded4e8Sguohongyu val filter_read = new IPFBufferFilterRead 93b1ded4e8Sguohongyu val write = Flipped(ValidIO(new IPFBufferWrite)) 94b1ded4e8Sguohongyu /** to ICache replacer */ 95b1ded4e8Sguohongyu val replace = new IPFBufferMove 96b1ded4e8Sguohongyu /** move & move filter port */ 97b1ded4e8Sguohongyu val mainpipe_missinfo = Flipped(new MainPipeMissInfo) 98b1ded4e8Sguohongyu val meta_filter_read = new ICacheMetaReqBundle 99b1ded4e8Sguohongyu val move = new Bundle() { 100b1ded4e8Sguohongyu val meta_write = DecoupledIO(new ICacheMetaWriteBundle) 101b1ded4e8Sguohongyu val data_write = DecoupledIO(new ICacheDataWriteBundle) 102b1ded4e8Sguohongyu } 103b1ded4e8Sguohongyu val fencei = Input(Bool()) 104b1ded4e8Sguohongyu }) 105b1ded4e8Sguohongyu 106b1ded4e8Sguohongyu class IPFBufferEntryMeta(implicit p: Parameters) extends IPrefetchBundle 107b1ded4e8Sguohongyu { 108b1ded4e8Sguohongyu val tag = UInt(tagBits.W) 109b1ded4e8Sguohongyu val index = UInt(idxBits.W) 110b1ded4e8Sguohongyu val paddr = UInt(PAddrBits.W) 111b1ded4e8Sguohongyu val valid = Bool() 112b1ded4e8Sguohongyu val confidence = UInt(log2Ceil(maxIPFMoveConf + 1).W) 113b1ded4e8Sguohongyu val move = Bool() 114*d4112e88Sguohongyu val has_been_hit = Bool() 115b1ded4e8Sguohongyu } 116b1ded4e8Sguohongyu 117b1ded4e8Sguohongyu class IPFBufferEntryData(implicit p: Parameters) extends IPrefetchBundle 118b1ded4e8Sguohongyu { 119b1ded4e8Sguohongyu val cachline = UInt(blockBits.W) 120b1ded4e8Sguohongyu } 121b1ded4e8Sguohongyu 122b1ded4e8Sguohongyu def InitQueue[T <: Data](entry: T, size: Int): Vec[T] ={ 123b1ded4e8Sguohongyu return RegInit(VecInit(Seq.fill(size)(0.U.asTypeOf(entry.cloneType)))) 124b1ded4e8Sguohongyu } 125b1ded4e8Sguohongyu 126b1ded4e8Sguohongyu val meta_buffer = InitQueue(new IPFBufferEntryMeta, size = nIPFBufferSize) 127b1ded4e8Sguohongyu val data_buffer = InitQueue(new IPFBufferEntryData, size = nIPFBufferSize) 128b1ded4e8Sguohongyu 129b1ded4e8Sguohongyu /** filter read logic */ 130b1ded4e8Sguohongyu val fr_vidx = io.filter_read.req.vSetIdx 131b1ded4e8Sguohongyu val fr_ptag = get_phy_tag(io.filter_read.req.paddr) 132b1ded4e8Sguohongyu 133b1ded4e8Sguohongyu val fr_hit_in_buffer = meta_buffer.map(e => e.valid && (e.tag === fr_ptag) && (e.index === fr_vidx)).reduce(_||_) 134b1ded4e8Sguohongyu val fr_hit_in_s1, fr_hit_in_s2, fr_hit_in_s3 = Wire(Bool()) 135b1ded4e8Sguohongyu 136b1ded4e8Sguohongyu io.filter_read.resp.ipf_hit := fr_hit_in_buffer || fr_hit_in_s1 || fr_hit_in_s2 || fr_hit_in_s3 137b1ded4e8Sguohongyu 138b1ded4e8Sguohongyu /** read logic */ 139b1ded4e8Sguohongyu (0 until PortNumber).foreach(i => io.read.req(i).ready := true.B) 140b1ded4e8Sguohongyu val r_valid = VecInit((0 until PortNumber).map( i => io.read.req(i).valid)).reduce(_||_) 141b1ded4e8Sguohongyu val r_vidx = VecInit((0 until PortNumber).map(i => get_idx(io.read.req(i).bits.vaddr))) 142b1ded4e8Sguohongyu val r_ptag = VecInit((0 until PortNumber).map(i => get_phy_tag(io.read.req(i).bits.paddr))) 143b1ded4e8Sguohongyu val r_hit_oh = VecInit((0 until PortNumber).map(i => 144b1ded4e8Sguohongyu VecInit(meta_buffer.map(entry => 145b1ded4e8Sguohongyu io.read.req(i).valid && // need this condition 146b1ded4e8Sguohongyu entry.valid && 147b1ded4e8Sguohongyu entry.tag === r_ptag(i) && 148b1ded4e8Sguohongyu entry.index === r_vidx(i) 149b1ded4e8Sguohongyu )))) 150b1ded4e8Sguohongyu val r_buffer_hit = VecInit(r_hit_oh.map(_.reduce(_||_))) 151b1ded4e8Sguohongyu val r_buffer_hit_idx = VecInit(r_hit_oh.map(PriorityEncoder(_))) 152b1ded4e8Sguohongyu val r_buffer_hit_data = VecInit((0 until PortNumber).map(i => Mux1H(r_hit_oh(i), data_buffer.map(_.cachline)))) 153b1ded4e8Sguohongyu 154b1ded4e8Sguohongyu /** "read" also check data in move pipeline */ 155b1ded4e8Sguohongyu val r_moves1pipe_hit_s1, r_moves1pipe_hit_s2, r_moves1pipe_hit_s3 = WireInit(VecInit(Seq.fill(PortNumber)(false.B))) 156b1ded4e8Sguohongyu val s1_move_data_cacheline, s2_move_data_cacheline, s3_move_data_cacheline = Wire(UInt(blockBits.W)) 157b1ded4e8Sguohongyu 158b1ded4e8Sguohongyu (0 until PortNumber).foreach{ i => 159b1ded4e8Sguohongyu io.read.resp(i).valid := io.read.req(i).valid 160b1ded4e8Sguohongyu 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) 161b1ded4e8Sguohongyu io.read.resp(i).bits.cacheline := Mux(r_buffer_hit(i), r_buffer_hit_data(i), 162b1ded4e8Sguohongyu Mux(r_moves1pipe_hit_s1(i), s1_move_data_cacheline, 163b1ded4e8Sguohongyu Mux(r_moves1pipe_hit_s2(i), s2_move_data_cacheline, s3_move_data_cacheline))) 164b1ded4e8Sguohongyu } 165b1ded4e8Sguohongyu 166*d4112e88Sguohongyu (0 until PortNumber).foreach { i => 167*d4112e88Sguohongyu when(r_valid(i) && r_hit_oh(i).reduce(_ || _)) { 168*d4112e88Sguohongyu meta_buffer(r_buffer_hit_idx(i)).has_been_hit := true.B 169*d4112e88Sguohongyu } 170*d4112e88Sguohongyu XSPerfAccumulate("ipf_entry_first_hit_by_port_" + i, r_valid(i) && r_hit_oh(i).reduce(_ || _) && 171*d4112e88Sguohongyu meta_buffer(r_buffer_hit_idx(i)).has_been_hit === false.B) 172*d4112e88Sguohongyu } 173*d4112e88Sguohongyu 174*d4112e88Sguohongyu 175b1ded4e8Sguohongyu /** move logic */ 176b1ded4e8Sguohongyu val r_buffer_hit_s2 = RegNext(r_buffer_hit, init=0.U.asTypeOf(r_buffer_hit.cloneType)) 177b1ded4e8Sguohongyu val r_buffer_hit_idx_s2 = RegNext(r_buffer_hit_idx) 178b1ded4e8Sguohongyu val r_rvalid_s2 = RegNext(r_valid, init=false.B) 179b1ded4e8Sguohongyu 180b1ded4e8Sguohongyu val s2_move_valid_0 = r_rvalid_s2 && r_buffer_hit_s2(0) 181b1ded4e8Sguohongyu val s2_move_valid_1 = r_rvalid_s2 && r_buffer_hit_s2(1) 182b1ded4e8Sguohongyu 183b1ded4e8Sguohongyu XSPerfAccumulate("prefetch_hit_bank_0", r_rvalid_s2 && r_buffer_hit_s2(0)) 184b1ded4e8Sguohongyu XSPerfAccumulate("prefetch_hit_bank_1", r_rvalid_s2 && r_buffer_hit_s2(1)) 185b1ded4e8Sguohongyu 186b1ded4e8Sguohongyu val move_queue = RegInit(VecInit(Seq.fill(nIPFBufferSize)(0.U.asTypeOf(r_buffer_hit_idx_s2(0))))) 187b1ded4e8Sguohongyu 188b1ded4e8Sguohongyu val curr_move_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 189b1ded4e8Sguohongyu val curr_hit_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 190b1ded4e8Sguohongyu 191b1ded4e8Sguohongyu val s2_move_conf_full_0 = meta_buffer(r_buffer_hit_idx_s2(0)).confidence === (maxIPFMoveConf).U 192b1ded4e8Sguohongyu val s2_move_conf_full_1 = meta_buffer(r_buffer_hit_idx_s2(1)).confidence === (maxIPFMoveConf).U 193b1ded4e8Sguohongyu 194b1ded4e8Sguohongyu val move_repeat_0 = meta_buffer(r_buffer_hit_idx_s2(0)).move 195b1ded4e8Sguohongyu 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)) 196b1ded4e8Sguohongyu 197b1ded4e8Sguohongyu val s2_move_0 = s2_move_valid_0 && !move_repeat_0 198b1ded4e8Sguohongyu val s2_move_1 = s2_move_valid_1 && !move_repeat_1 199b1ded4e8Sguohongyu 200b1ded4e8Sguohongyu val s2_move_enqueue_0 = s2_move_0 && s2_move_conf_full_0 201b1ded4e8Sguohongyu val s2_move_enqueue_1 = s2_move_1 && s2_move_conf_full_1 202b1ded4e8Sguohongyu 203b1ded4e8Sguohongyu when(s2_move_0) { 204b1ded4e8Sguohongyu when(s2_move_conf_full_0) { 205b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(0)).move := true.B 206b1ded4e8Sguohongyu }.otherwise { 207b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(0)).confidence := meta_buffer(r_buffer_hit_idx_s2(0)).confidence + 1.U 208b1ded4e8Sguohongyu } 209b1ded4e8Sguohongyu } 210b1ded4e8Sguohongyu when(s2_move_1) { 211b1ded4e8Sguohongyu when(s2_move_conf_full_1) { 212b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(1)).move := true.B 213b1ded4e8Sguohongyu }.otherwise { 214b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(1)).confidence := meta_buffer(r_buffer_hit_idx_s2(1)).confidence + 1.U 215b1ded4e8Sguohongyu } 216b1ded4e8Sguohongyu } 217b1ded4e8Sguohongyu 218b1ded4e8Sguohongyu when(s2_move_enqueue_0 && !s2_move_enqueue_1) { 219b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0) 220b1ded4e8Sguohongyu 221b1ded4e8Sguohongyu when((curr_hit_ptr + 1.U) =/= curr_move_ptr){ 222b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 223b1ded4e8Sguohongyu } 224b1ded4e8Sguohongyu }.elsewhen(!s2_move_enqueue_0 && s2_move_enqueue_1) { 225b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(1) 226b1ded4e8Sguohongyu 227b1ded4e8Sguohongyu when((curr_hit_ptr + 1.U) =/= curr_move_ptr){ 228b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 229b1ded4e8Sguohongyu } 230b1ded4e8Sguohongyu }.elsewhen(s2_move_enqueue_0 && s2_move_enqueue_1) { 231b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0) 232b1ded4e8Sguohongyu move_queue(curr_hit_ptr + 1.U) := r_buffer_hit_idx_s2(1) 233b1ded4e8Sguohongyu when((curr_hit_ptr + 2.U) =/= curr_move_ptr){ 234b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 2.U 235b1ded4e8Sguohongyu }.otherwise{ 236b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 237b1ded4e8Sguohongyu } 238b1ded4e8Sguohongyu } 239b1ded4e8Sguohongyu 240b1ded4e8Sguohongyu val move_queue_empty = curr_move_ptr === curr_hit_ptr 241b1ded4e8Sguohongyu /** pipeline control signal */ 242b1ded4e8Sguohongyu val s1_ready, s2_ready, s3_ready = Wire(Bool()) 243b1ded4e8Sguohongyu val s0_fire, s1_fire, s2_fire, s3_fire = Wire(Bool()) 244b1ded4e8Sguohongyu 245b1ded4e8Sguohongyu /** stage 0 */ 246b1ded4e8Sguohongyu val s0_valid = !move_queue_empty && meta_buffer(move_queue(curr_move_ptr)).move 247b1ded4e8Sguohongyu 248b1ded4e8Sguohongyu val s0_move_idx = move_queue(curr_move_ptr) 249b1ded4e8Sguohongyu val s0_move_meta = meta_buffer(s0_move_idx) 250b1ded4e8Sguohongyu val s0_move_data = data_buffer(s0_move_idx) 251b1ded4e8Sguohongyu io.replace.vsetIdx := meta_buffer(s0_move_idx).index 252b1ded4e8Sguohongyu val s0_waymask = io.replace.waymask 253b1ded4e8Sguohongyu 254b1ded4e8Sguohongyu s0_fire := s0_valid && s1_ready 255b1ded4e8Sguohongyu 256b1ded4e8Sguohongyu /** curr_move_ptr control logic */ 257b1ded4e8Sguohongyu val s0_move_jump = !move_queue_empty && !meta_buffer(move_queue(curr_move_ptr)).move 258b1ded4e8Sguohongyu when (s0_fire) { 259b1ded4e8Sguohongyu curr_move_ptr := curr_move_ptr + 1.U 260b1ded4e8Sguohongyu meta_buffer(s0_move_idx).valid := false.B 261b1ded4e8Sguohongyu meta_buffer(s0_move_idx).move := false.B 262b1ded4e8Sguohongyu meta_buffer(s0_move_idx).confidence := 0.U 263b1ded4e8Sguohongyu }.elsewhen(s0_move_jump) { 264b1ded4e8Sguohongyu curr_move_ptr := curr_move_ptr + 1.U 265b1ded4e8Sguohongyu } 266b1ded4e8Sguohongyu 267b1ded4e8Sguohongyu /** stage 1 : send req to metaArray */ 268b1ded4e8Sguohongyu val s1_valid = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = io.fencei, lastFlush = false.B) 269b1ded4e8Sguohongyu 270b1ded4e8Sguohongyu val s1_move_idx = RegEnable(s0_move_idx, s0_fire) 271b1ded4e8Sguohongyu val s1_move_meta = RegEnable(s0_move_meta, s0_fire) 272b1ded4e8Sguohongyu val s1_move_data = RegEnable(s0_move_data, s0_fire) 273b1ded4e8Sguohongyu val s1_waymask = RegEnable(s0_waymask, s0_fire) 274b1ded4e8Sguohongyu 275b1ded4e8Sguohongyu io.meta_filter_read.toIMeta.valid := s1_valid 276b1ded4e8Sguohongyu io.meta_filter_read.toIMeta.bits.isDoubleLine := false.B 277b1ded4e8Sguohongyu io.meta_filter_read.toIMeta.bits.vSetIdx(0) := s1_move_meta.index // just use port 0 278b1ded4e8Sguohongyu io.meta_filter_read.toIMeta.bits.vSetIdx(1) := DontCare 279b1ded4e8Sguohongyu 280b1ded4e8Sguohongyu s1_ready := !s1_valid || s1_fire 281b1ded4e8Sguohongyu s1_fire := s1_valid && io.meta_filter_read.toIMeta.ready && s2_ready 282b1ded4e8Sguohongyu 283b1ded4e8Sguohongyu fr_hit_in_s1 := s1_valid && s1_move_meta.index === fr_vidx && s1_move_meta.tag === fr_ptag 284b1ded4e8Sguohongyu 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)) 285b1ded4e8Sguohongyu s1_move_data_cacheline := s1_move_data.cachline 286b1ded4e8Sguohongyu 287b1ded4e8Sguohongyu /** stage 2 : collect message from metaArray and mainPipe to filter */ 288b1ded4e8Sguohongyu val s2_valid = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = io.fencei, lastFlush = false.B) 289b1ded4e8Sguohongyu 290b1ded4e8Sguohongyu val s2_move_idx = RegEnable(s1_move_idx, s1_fire) 291b1ded4e8Sguohongyu val s2_move_meta = RegEnable(s1_move_meta, s1_fire) 292b1ded4e8Sguohongyu val s2_move_data = RegEnable(s1_move_data, s1_fire) 293b1ded4e8Sguohongyu val s2_waymask = RegEnable(s1_waymask, s1_fire) 294b1ded4e8Sguohongyu 295b1ded4e8Sguohongyu val s2_meta_ptags = ResultHoldBypass(data = io.meta_filter_read.fromIMeta.tags, valid = RegNext(s1_fire)) 296b1ded4e8Sguohongyu val s2_meta_valids = ResultHoldBypass(data = io.meta_filter_read.fromIMeta.entryValid, valid = RegNext(s1_fire)) 297b1ded4e8Sguohongyu 298b1ded4e8Sguohongyu val s2_tag_eq_vec = VecInit((0 until nWays).map(w => s2_meta_ptags(0)(w) === s2_move_meta.tag)) // just use port 0 299b1ded4e8Sguohongyu 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)}) 300b1ded4e8Sguohongyu val s2_hit_in_meta_array = ParallelOR(s2_tag_match_vec) 301b1ded4e8Sguohongyu 302b1ded4e8Sguohongyu val main_s2_missinfo = io.mainpipe_missinfo.s2_miss_info 303b1ded4e8Sguohongyu val s2_hit_main_s2_missreq = VecInit((0 until PortNumber).map(i => 304b1ded4e8Sguohongyu main_s2_missinfo(i).valid && s2_move_meta.index === main_s2_missinfo(i).bits.vSetIdx 305b1ded4e8Sguohongyu && s2_move_meta.tag === main_s2_missinfo(i).bits.ptage)).reduce(_||_) 306b1ded4e8Sguohongyu 307b1ded4e8Sguohongyu val s2_discard = s2_hit_in_meta_array || s2_hit_main_s2_missreq // || s2_hit_main_s1_missreq 308b1ded4e8Sguohongyu val s2_discard_latch = holdReleaseLatch(valid = s2_discard, release = s2_fire, flush = io.fencei) 309b1ded4e8Sguohongyu if(DebugFlags.fdip){ 310b1ded4e8Sguohongyu when (s2_fire && s2_discard_latch) { 311b1ded4e8Sguohongyu printf("<%d> IPrefetchBuffer: s2_discard : hit_in_meta_array=%d,hit_in_main_s2=%d, ptag=0x%x\n", 312b1ded4e8Sguohongyu GTimer(), s2_hit_in_meta_array, s2_hit_main_s2_missreq, s2_move_meta.tag) 313b1ded4e8Sguohongyu } 314b1ded4e8Sguohongyu } 315b1ded4e8Sguohongyu 316b1ded4e8Sguohongyu s2_ready := !s2_valid || s2_fire 317b1ded4e8Sguohongyu s2_fire := s2_valid && s3_ready && io.mainpipe_missinfo.s1_already_check_ipf 318b1ded4e8Sguohongyu 319b1ded4e8Sguohongyu fr_hit_in_s2 := s2_valid && s2_move_meta.index === fr_vidx && s2_move_meta.tag === fr_ptag 320b1ded4e8Sguohongyu 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)) 321b1ded4e8Sguohongyu s2_move_data_cacheline := s2_move_data.cachline 322b1ded4e8Sguohongyu 323b1ded4e8Sguohongyu /** stage 3 : move data to metaArray and dataArray */ 324b1ded4e8Sguohongyu val s3_valid = generatePipeControl(lastFire = s2_fire, thisFire = s3_fire, thisFlush = io.fencei, lastFlush = false.B) 325b1ded4e8Sguohongyu 326b1ded4e8Sguohongyu val s3_move_idx = RegEnable(s2_move_idx, s2_fire) 327b1ded4e8Sguohongyu val s3_move_meta = RegEnable(s2_move_meta, s2_fire) 328b1ded4e8Sguohongyu val s3_move_data = RegEnable(s2_move_data, s2_fire) 329b1ded4e8Sguohongyu val s3_waymask = RegEnable(s2_waymask, s2_fire) 330b1ded4e8Sguohongyu val s3_discard = RegEnable(s2_discard_latch, s2_fire) 331b1ded4e8Sguohongyu 332b1ded4e8Sguohongyu io.move.meta_write.valid := s3_valid && !s3_discard && !io.fencei 333b1ded4e8Sguohongyu io.move.data_write.valid := s3_valid && !s3_discard && !io.fencei 334b1ded4e8Sguohongyu io.move.meta_write.bits.generate( 335b1ded4e8Sguohongyu tag = s3_move_meta.tag, 336b1ded4e8Sguohongyu idx = s3_move_meta.index, 337b1ded4e8Sguohongyu waymask = s3_waymask, 338b1ded4e8Sguohongyu bankIdx = s3_move_meta.index(0)) 339b1ded4e8Sguohongyu io.move.data_write.bits.generate( 340b1ded4e8Sguohongyu data = s3_move_data.cachline, 341b1ded4e8Sguohongyu idx = s3_move_meta.index, 342b1ded4e8Sguohongyu waymask = s3_waymask, 343b1ded4e8Sguohongyu bankIdx = s3_move_meta.index(0), 344b1ded4e8Sguohongyu paddr = s3_move_meta.paddr) 345b1ded4e8Sguohongyu 346b1ded4e8Sguohongyu s3_ready := !s3_valid || s3_fire 347b1ded4e8Sguohongyu s3_fire := io.move.meta_write.fire && io.move.data_write.fire || s3_discard || io.fencei 348b1ded4e8Sguohongyu assert((io.move.meta_write.fire && io.move.data_write.fire) || (!io.move.meta_write.fire && !io.move.data_write.fire), 349b1ded4e8Sguohongyu "meta and data array need fire at same time") 350b1ded4e8Sguohongyu 351b1ded4e8Sguohongyu fr_hit_in_s3 := s3_valid && s3_move_meta.index === fr_vidx && s3_move_meta.tag === fr_ptag 352b1ded4e8Sguohongyu 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)) 353b1ded4e8Sguohongyu s3_move_data_cacheline := s3_move_data.cachline 354b1ded4e8Sguohongyu 355b1ded4e8Sguohongyu if (DebugFlags.fdip) { 356b1ded4e8Sguohongyu when(io.move.meta_write.fire) { 357b1ded4e8Sguohongyu printf("<%d> IPrefetchBuffer: move data to meta sram:ptag=0x%x,vidx=0x%x,waymask=0x%x\n", 358b1ded4e8Sguohongyu GTimer(), s3_move_meta.tag,s3_move_meta.index,s3_waymask ) 359b1ded4e8Sguohongyu } 360b1ded4e8Sguohongyu } 361b1ded4e8Sguohongyu 362b1ded4e8Sguohongyu /** write logic */ 363b1ded4e8Sguohongyu val replacer = ReplacementPolicy.fromString(Some("random"), nIPFBufferSize) 364b1ded4e8Sguohongyu val curr_write_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 365b1ded4e8Sguohongyu val victim_way = curr_write_ptr + 1.U//replacer.way 366b1ded4e8Sguohongyu 367b1ded4e8Sguohongyu when(io.write.valid) { 368b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).tag := io.write.bits.meta.tag 369b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).index := io.write.bits.meta.index 370b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).paddr := io.write.bits.meta.paddr 371b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).valid := true.B 372b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).move := false.B 373b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).confidence := 0.U 374*d4112e88Sguohongyu meta_buffer(curr_write_ptr).has_been_hit := false.B 375b1ded4e8Sguohongyu 376b1ded4e8Sguohongyu data_buffer(curr_write_ptr).cachline := io.write.bits.data 377b1ded4e8Sguohongyu 378b1ded4e8Sguohongyu //update replacer 379b1ded4e8Sguohongyu replacer.access(curr_write_ptr) 380b1ded4e8Sguohongyu curr_write_ptr := victim_way 381b1ded4e8Sguohongyu 382b1ded4e8Sguohongyu } 383b1ded4e8Sguohongyu 384b1ded4e8Sguohongyu /** fencei: invalid all entries */ 385b1ded4e8Sguohongyu when(io.fencei) { 386b1ded4e8Sguohongyu meta_buffer.foreach{ 387b1ded4e8Sguohongyu case b => 388b1ded4e8Sguohongyu b.valid := false.B 389b1ded4e8Sguohongyu b.move := false.B 390b1ded4e8Sguohongyu b.confidence := 0.U 391b1ded4e8Sguohongyu } 392b1ded4e8Sguohongyu } 393b1ded4e8Sguohongyu 3947052722fSJay} 3957052722fSJay 3967052722fSJayclass IPrefetchPipe(implicit p: Parameters) extends IPrefetchModule 3977052722fSJay{ 3987052722fSJay val io = IO(new IPredfetchIO) 3997052722fSJay 400a108d429SJay val enableBit = RegInit(false.B) 401b1ded4e8Sguohongyu val maxPrefetchCounter = RegInit(0.U(log2Ceil(nPrefetchEntries + 1).W)) 402a108d429SJay 403b1ded4e8Sguohongyu val reachMaxSize = maxPrefetchCounter === nPrefetchEntries.U 404a108d429SJay 405b1ded4e8Sguohongyu // when(io.prefetchEnable){ 406b1ded4e8Sguohongyu // enableBit := true.B 407b1ded4e8Sguohongyu // }.elsewhen((enableBit && io.prefetchDisable) || (enableBit && reachMaxSize)){ 408b1ded4e8Sguohongyu // enableBit := false.B 409b1ded4e8Sguohongyu // } 410b1ded4e8Sguohongyu // ignore prefetchEnable from ICacheMainPipe 411a108d429SJay enableBit := true.B 412a108d429SJay 413a108d429SJay class PrefetchDir(implicit p: Parameters) extends IPrefetchBundle 414a108d429SJay { 415a108d429SJay val valid = Bool() 416a108d429SJay val paddr = UInt(PAddrBits.W) 417a108d429SJay } 418a108d429SJay 419a108d429SJay val prefetch_dir = RegInit(VecInit(Seq.fill(nPrefetchEntries)(0.U.asTypeOf(new PrefetchDir)))) 420a108d429SJay 4217052722fSJay val fromFtq = io.fromFtq 422b1ded4e8Sguohongyu val fromMainPipe = io.fromMainPipe 4237052722fSJay val (toITLB, fromITLB) = (io.iTLBInter.req, io.iTLBInter.resp) 424c3b763d0SYinan Xu io.iTLBInter.req_kill := false.B 425b1ded4e8Sguohongyu val (toIMeta, fromIMeta, fromIMetaValid) = (io.toIMeta, io.fromIMeta.metaData(0), io.fromIMeta.entryValid(0)) 426b1ded4e8Sguohongyu val (toIPFBuffer, fromIPFBuffer) = (io.IPFBufferRead.req, io.IPFBufferRead.resp) 4277052722fSJay val (toPMP, fromPMP) = (io.pmp.req, io.pmp.resp) 4287052722fSJay val toMissUnit = io.toMissUnit 4297052722fSJay 4307052722fSJay val p0_fire, p1_fire, p2_fire, p3_fire = WireInit(false.B) 431b1ded4e8Sguohongyu val p0_discard, p1_discard, p2_discard, p3_discard = WireInit(false.B) 4327052722fSJay val p0_ready, p1_ready, p2_ready, p3_ready = WireInit(false.B) 4337052722fSJay 4347052722fSJay /** Prefetch Stage 0: req from Ftq */ 4357052722fSJay val p0_valid = fromFtq.req.valid 436d6b06a99SJay val p0_vaddr = addrAlign(fromFtq.req.bits.target, blockBytes, VAddrBits) 437b1ded4e8Sguohongyu val p0_vaddr_reg = RegEnable(p0_vaddr, fromFtq.req.fire()) 4387052722fSJay 439b1ded4e8Sguohongyu /* Cancel request when prefetch not enable 440b1ded4e8Sguohongyu * or the request from FTQ is same as last time */ 441b1ded4e8Sguohongyu val p0_req_cancel = !enableBit || (p0_vaddr === p0_vaddr_reg) || io.fencei 442b1ded4e8Sguohongyu p0_fire := p0_valid && p1_ready && toITLB.fire() && !fromITLB.bits.miss && toIMeta.ready && enableBit && !p0_req_cancel 443b1ded4e8Sguohongyu p0_discard := p0_valid && p0_req_cancel 444b1ded4e8Sguohongyu 445b1ded4e8Sguohongyu toIMeta.valid := p0_valid && !p0_discard 446afed18b5SJenius toIMeta.bits.vSetIdx(0) := get_idx(p0_vaddr) 447b1ded4e8Sguohongyu 448afed18b5SJenius toIMeta.bits.vSetIdx(1) := DontCare 449afed18b5SJenius toIMeta.bits.isDoubleLine := false.B 4507052722fSJay 451b1ded4e8Sguohongyu toITLB.valid := p0_valid && !p0_discard 4527052722fSJay toITLB.bits.size := 3.U // TODO: fix the size 4537052722fSJay toITLB.bits.vaddr := p0_vaddr 4547052722fSJay toITLB.bits.debug.pc := p0_vaddr 4557052722fSJay 456f1fe8698SLemover toITLB.bits.kill := DontCare 4577052722fSJay toITLB.bits.cmd := TlbCmd.exec 458f1fe8698SLemover toITLB.bits.debug.robIdx := DontCare 4597052722fSJay toITLB.bits.debug.isFirstIssue := DontCare 460b1ded4e8Sguohongyu toITLB.bits.memidx := DontCare 461b1ded4e8Sguohongyu toITLB.bits.no_translate := false.B 4627052722fSJay 4637052722fSJay fromITLB.ready := true.B 4647052722fSJay 465b1ded4e8Sguohongyu fromFtq.req.ready := !p0_valid || p0_fire || p0_discard 4667052722fSJay 4677052722fSJay /** Prefetch Stage 1: cache probe filter */ 4687052722fSJay val p1_valid = generatePipeControl(lastFire = p0_fire, thisFire = p1_fire || p1_discard, thisFlush = false.B, lastFlush = false.B) 4697052722fSJay 470005e809bSJiuyang Liu val p1_vaddr = RegEnable(p0_vaddr, p0_fire) 471b1ded4e8Sguohongyu // TODO: tlb is none blocked ,when tlb miss, p1 req need cancle. Now there seemes has bug 4727052722fSJay //tlb resp 473de7689fcSJay val tlb_resp_valid = RegInit(false.B) 474de7689fcSJay when(p0_fire) {tlb_resp_valid := true.B} 475de7689fcSJay .elsewhen(tlb_resp_valid && (p1_fire || p1_discard)) {tlb_resp_valid := false.B} 4767052722fSJay 47703efd994Shappy-lx val tlb_resp_paddr = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.paddr(0)) 47803efd994Shappy-lx val tlb_resp_pf = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).pf.instr && tlb_resp_valid) 47903efd994Shappy-lx val tlb_resp_af = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).af.instr && tlb_resp_valid) 4807052722fSJay 4817052722fSJay val p1_exception = VecInit(Seq(tlb_resp_pf, tlb_resp_af)) 4827052722fSJay val p1_has_except = p1_exception.reduce(_ || _) 483b1ded4e8Sguohongyu val p1_paddr = tlb_resp_paddr 4847052722fSJay 485b1ded4e8Sguohongyu val p1_ptag = get_phy_tag(p1_paddr) 4867052722fSJay 4877052722fSJay val p1_meta_ptags = ResultHoldBypass(data = VecInit(fromIMeta.map(way => way.tag)),valid = RegNext(p0_fire)) 488b1ded4e8Sguohongyu val p1_meta_valids = ResultHoldBypass(data = fromIMetaValid,valid = RegNext(p0_fire)) 489b1ded4e8Sguohongyu 4907052722fSJay val p1_tag_eq_vec = VecInit(p1_meta_ptags.map(_ === p1_ptag )) 491b1ded4e8Sguohongyu val p1_tag_match_vec = VecInit(p1_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && p1_meta_valids(w)}) 4927052722fSJay val p1_tag_match = ParallelOR(p1_tag_match_vec) 493b1ded4e8Sguohongyu 494b1ded4e8Sguohongyu val p1_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p1_paddr, blockBytes, PAddrBits))).reduce(_||_) 495b1ded4e8Sguohongyu 496b1ded4e8Sguohongyu 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) 497b1ded4e8Sguohongyu 4987052722fSJay 4997052722fSJay //overriding the invalid req 500b1ded4e8Sguohongyu val p1_req_cancle = (p1_hit || (tlb_resp_valid && p1_exception.reduce(_ || _)) || io.fencei) && p1_valid 5017052722fSJay val p1_req_accept = p1_valid && tlb_resp_valid && p1_miss 5027052722fSJay 5037052722fSJay p1_ready := p1_fire || p1_req_cancle || !p1_valid 504a108d429SJay p1_fire := p1_valid && p1_req_accept && p2_ready && enableBit 5057052722fSJay p1_discard := p1_valid && p1_req_cancle 5067052722fSJay 5077052722fSJay /** Prefetch Stage 2: filtered req PIQ enqueue */ 5087052722fSJay val p2_valid = generatePipeControl(lastFire = p1_fire, thisFire = p2_fire || p2_discard, thisFlush = false.B, lastFlush = false.B) 509b1ded4e8Sguohongyu val p2_pmp_fire = p2_valid 510b1ded4e8Sguohongyu val pmpExcpAF = fromPMP.instr 5117052722fSJay 512b1ded4e8Sguohongyu val p2_paddr = RegEnable(p1_paddr, p1_fire) 513b1ded4e8Sguohongyu val p2_except_pf = RegEnable(tlb_resp_pf, p1_fire) 514b1ded4e8Sguohongyu val p2_except_af = DataHoldBypass(pmpExcpAF, p2_pmp_fire) || RegEnable(tlb_resp_af, p1_fire) 515b1ded4e8Sguohongyu val p2_mmio = DataHoldBypass(io.pmp.resp.mmio && !p2_except_af && !p2_except_pf, p2_pmp_fire) 516b1ded4e8Sguohongyu val p2_vaddr = RegEnable(p1_vaddr, p1_fire) 517b1ded4e8Sguohongyu 5187052722fSJay 51900240ba6SJay /*when a prefetch req meet with a miss req in MSHR cancle the prefetch req */ 52000240ba6SJay val p2_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p2_paddr, blockBytes, PAddrBits))).reduce(_||_) 52100240ba6SJay 5227052722fSJay //TODO wait PMP logic 523b1ded4e8Sguohongyu val p2_exception = VecInit(Seq(pmpExcpAF, p2_mmio)).reduce(_||_) 524b1ded4e8Sguohongyu 525b1ded4e8Sguohongyu io.pmp.req.valid := p2_pmp_fire 526b1ded4e8Sguohongyu io.pmp.req.bits.addr := p2_paddr 527b1ded4e8Sguohongyu io.pmp.req.bits.size := 3.U 528b1ded4e8Sguohongyu io.pmp.req.bits.cmd := TlbCmd.exec 5297052722fSJay 5307052722fSJay p2_ready := p2_fire || p2_discard || !p2_valid 531b1ded4e8Sguohongyu p2_fire := p2_valid && !p2_exception && p3_ready && p2_pmp_fire 532b1ded4e8Sguohongyu p2_discard := p2_valid && (p2_exception && p2_pmp_fire || io.fencei) 5337052722fSJay 5347052722fSJay /** Prefetch Stage 2: filtered req PIQ enqueue */ 535a108d429SJay val p3_valid = generatePipeControl(lastFire = p2_fire, thisFire = p3_fire || p3_discard, thisFlush = false.B, lastFlush = false.B) 5367052722fSJay 537b1ded4e8Sguohongyu val p3_paddr = RegEnable(p2_paddr, p2_fire) 538b1ded4e8Sguohongyu val p3_check_in_mshr = RegEnable(p2_check_in_mshr, p2_fire) 539b1ded4e8Sguohongyu val p3_vaddr = RegEnable(p2_vaddr, p2_fire) 540b1ded4e8Sguohongyu val p3_vidx = get_idx(p3_vaddr) 541b1ded4e8Sguohongyu // check in prefetch buffer 542b1ded4e8Sguohongyu toIPFBuffer.vSetIdx := p3_vidx 543b1ded4e8Sguohongyu toIPFBuffer.paddr := p3_paddr 544b1ded4e8Sguohongyu val p3_buffer_hit = fromIPFBuffer.ipf_hit 5457052722fSJay 546a108d429SJay val p3_hit_dir = VecInit((0 until nPrefetchEntries).map(i => prefetch_dir(i).valid && prefetch_dir(i).paddr === p3_paddr )).reduce(_||_) 547b1ded4e8Sguohongyu //Cache miss handling by main pipe 548b1ded4e8Sguohongyu val p3_hit_mp_miss = VecInit((0 until PortNumber).map(i => fromMainPipe(i).valid && (fromMainPipe(i).bits.ptage === get_phy_tag(p3_paddr) && 549b1ded4e8Sguohongyu (fromMainPipe(i).bits.vSetIdx === p3_vidx)))).reduce(_||_) 550b1ded4e8Sguohongyu val p3_req_cancel = p3_hit_dir || p3_check_in_mshr || !enableBit || p3_hit_mp_miss || p3_buffer_hit || io.fencei 551b1ded4e8Sguohongyu p3_discard := p3_valid && p3_req_cancel 552a108d429SJay 553b1ded4e8Sguohongyu toMissUnit.enqReq.valid := p3_valid && !p3_req_cancel 5547052722fSJay toMissUnit.enqReq.bits.paddr := p3_paddr 555b1ded4e8Sguohongyu toMissUnit.enqReq.bits.vSetIdx := p3_vidx 5567052722fSJay 557b1ded4e8Sguohongyu when(io.fencei){ 558b1ded4e8Sguohongyu maxPrefetchCounter := 0.U 559a108d429SJay 560a108d429SJay prefetch_dir.foreach(_.valid := false.B) 561a108d429SJay }.elsewhen(toMissUnit.enqReq.fire()){ 562b1ded4e8Sguohongyu when(reachMaxSize){ 563b1ded4e8Sguohongyu prefetch_dir(io.freePIQEntry).paddr := p3_paddr 564b1ded4e8Sguohongyu }.otherwise { 565b1ded4e8Sguohongyu maxPrefetchCounter := maxPrefetchCounter + 1.U 566a108d429SJay 567b1ded4e8Sguohongyu prefetch_dir(maxPrefetchCounter).valid := true.B 568b1ded4e8Sguohongyu prefetch_dir(maxPrefetchCounter).paddr := p3_paddr 569b1ded4e8Sguohongyu } 570a108d429SJay } 571a108d429SJay 572a108d429SJay p3_ready := toMissUnit.enqReq.ready || !enableBit 5737052722fSJay p3_fire := toMissUnit.enqReq.fire() 5747052722fSJay 5757052722fSJay} 5767052722fSJay 577b1ded4e8Sguohongyuclass PIQEntry(edge: TLEdgeOut, id: Int)(implicit p: Parameters) extends IPrefetchModule 5787052722fSJay{ 5797052722fSJay val io = IO(new Bundle{ 580b1ded4e8Sguohongyu val id = Input(UInt((log2Ceil(nPrefetchEntries + PortNumber)).W)) 5817052722fSJay 5827052722fSJay val req = Flipped(DecoupledIO(new PIQReq)) 5837052722fSJay 584b1ded4e8Sguohongyu val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 585b1ded4e8Sguohongyu val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 5867052722fSJay 587b1ded4e8Sguohongyu //write back to Prefetch Buffer 588b1ded4e8Sguohongyu val piq_write_ipbuffer = DecoupledIO(new IPFBufferWrite) 589b1ded4e8Sguohongyu 590b1ded4e8Sguohongyu //TODO: fencei flush instructions 591b1ded4e8Sguohongyu val fencei = Input(Bool()) 592b1ded4e8Sguohongyu 593b1ded4e8Sguohongyu val prefetch_entry_data = DecoupledIO(new PIQData) 5947052722fSJay }) 5957052722fSJay 596b1ded4e8Sguohongyu val s_idle :: s_memReadReq :: s_memReadResp :: s_write_back :: s_finish:: Nil = Enum(5) 5977052722fSJay val state = RegInit(s_idle) 5987052722fSJay 599b1ded4e8Sguohongyu //req register 600b1ded4e8Sguohongyu val req = Reg(new PIQReq) 601b1ded4e8Sguohongyu val req_idx = req.vSetIdx //virtual index 602b1ded4e8Sguohongyu val req_tag = get_phy_tag(req.paddr) //physical tag 603b1ded4e8Sguohongyu 604b1ded4e8Sguohongyu val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant) 605b1ded4e8Sguohongyu 606b1ded4e8Sguohongyu //8 for 64 bits bus and 2 for 256 bits 607b1ded4e8Sguohongyu val readBeatCnt = Reg(UInt(log2Up(refillCycles).W)) 608b1ded4e8Sguohongyu val respDataReg = Reg(Vec(refillCycles,UInt(beatBits.W))) 609b1ded4e8Sguohongyu 610b1ded4e8Sguohongyu //to main pipe s1 611b1ded4e8Sguohongyu io.prefetch_entry_data.valid := state =/= s_idle 612b1ded4e8Sguohongyu io.prefetch_entry_data.bits.vSetIdx := req_idx 613b1ded4e8Sguohongyu io.prefetch_entry_data.bits.ptage := req_tag 614b1ded4e8Sguohongyu io.prefetch_entry_data.bits.cacheline := respDataReg.asUInt 615b1ded4e8Sguohongyu io.prefetch_entry_data.bits.writeBack := state === s_write_back 616b1ded4e8Sguohongyu 617b1ded4e8Sguohongyu //initial 618b1ded4e8Sguohongyu io.mem_acquire.bits := DontCare 619b1ded4e8Sguohongyu io.mem_grant.ready := true.B 620b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits:= DontCare 621b1ded4e8Sguohongyu 622b1ded4e8Sguohongyu io.req.ready := state === s_idle 623b1ded4e8Sguohongyu io.mem_acquire.valid := state === s_memReadReq 624b1ded4e8Sguohongyu 625b1ded4e8Sguohongyu val needFlushReg = RegInit(false.B) 626b1ded4e8Sguohongyu when(state === s_idle || state === s_finish){ 627b1ded4e8Sguohongyu needFlushReg := false.B 628b1ded4e8Sguohongyu } 629b1ded4e8Sguohongyu when((state === s_memReadReq || state === s_memReadResp || state === s_write_back) && io.fencei){ 630b1ded4e8Sguohongyu needFlushReg := true.B 631b1ded4e8Sguohongyu } 632b1ded4e8Sguohongyu val needFlush = needFlushReg || io.fencei 6337052722fSJay 6347052722fSJay //state change 6357052722fSJay switch(state){ 6367052722fSJay is(s_idle){ 6377052722fSJay when(io.req.fire()){ 638b1ded4e8Sguohongyu readBeatCnt := 0.U 639b1ded4e8Sguohongyu state := s_memReadReq 6407052722fSJay req := io.req.bits 6417052722fSJay } 6427052722fSJay } 6437052722fSJay 6447052722fSJay // memory request 645b1ded4e8Sguohongyu is(s_memReadReq){ 646b1ded4e8Sguohongyu when(io.mem_acquire.fire()){ 647b1ded4e8Sguohongyu state := s_memReadResp 648b1ded4e8Sguohongyu } 649b1ded4e8Sguohongyu } 650b1ded4e8Sguohongyu 651b1ded4e8Sguohongyu is(s_memReadResp){ 652b1ded4e8Sguohongyu when (edge.hasData(io.mem_grant.bits)) { 653b1ded4e8Sguohongyu when (io.mem_grant.fire()) { 654b1ded4e8Sguohongyu readBeatCnt := readBeatCnt + 1.U 655b1ded4e8Sguohongyu respDataReg(readBeatCnt) := io.mem_grant.bits.data 656b1ded4e8Sguohongyu when (readBeatCnt === (refillCycles - 1).U) { 657b1ded4e8Sguohongyu assert(refill_done, "refill not done!") 658b1ded4e8Sguohongyu state := s_write_back 659b1ded4e8Sguohongyu } 660b1ded4e8Sguohongyu } 661b1ded4e8Sguohongyu } 662b1ded4e8Sguohongyu } 663b1ded4e8Sguohongyu 664b1ded4e8Sguohongyu is(s_write_back){ 665b1ded4e8Sguohongyu state := Mux(io.piq_write_ipbuffer.fire() || needFlush, s_finish, s_write_back) 666b1ded4e8Sguohongyu } 667b1ded4e8Sguohongyu 668b1ded4e8Sguohongyu is(s_finish){ 6697052722fSJay state := s_idle 6707052722fSJay } 6717052722fSJay } 6727052722fSJay 673b1ded4e8Sguohongyu //refill write and meta write 674b1ded4e8Sguohongyu //WARNING: Maybe could not finish refill in 1 cycle 675b1ded4e8Sguohongyu io.piq_write_ipbuffer.valid := (state === s_write_back) && !needFlush 676b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.tag := req_tag 677b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.index := req_idx 678b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.paddr := req.paddr 679b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.data := respDataReg.asUInt 680b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.buffIdx := io.id - PortNumber.U 6817052722fSJay 6827052722fSJay XSPerfAccumulate("PrefetchEntryReq" + Integer.toString(id, 10), io.req.fire()) 6837052722fSJay 684b1ded4e8Sguohongyu //mem request 685b1ded4e8Sguohongyu io.mem_acquire.bits := edge.Get( 686b1ded4e8Sguohongyu fromSource = io.id, 687b1ded4e8Sguohongyu toAddress = Cat(req.paddr(PAddrBits - 1, log2Ceil(blockBytes)), 0.U(log2Ceil(blockBytes).W)), 688b1ded4e8Sguohongyu lgSize = (log2Up(cacheParams.blockBytes)).U)._2 689b1ded4e8Sguohongyu 6907052722fSJay} 691