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._ 22afa866b1Sguohongyuimport difftest.DifftestRefillEvent 237052722fSJayimport freechips.rocketchip.tilelink._ 247052722fSJayimport utils._ 257052722fSJayimport xiangshan.cache.mmu._ 267052722fSJayimport xiangshan.frontend._ 27d2b20d1aSTang Haojinimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 28d2b20d1aSTang Haojinimport huancun.PreferCacheKey 29*b92c5693STang Haojinimport xiangshan.XSCoreParamsKey 30b1ded4e8Sguohongyuimport utility._ 317052722fSJay 327052722fSJay 337052722fSJayabstract class IPrefetchBundle(implicit p: Parameters) extends ICacheBundle 347052722fSJayabstract class IPrefetchModule(implicit p: Parameters) extends ICacheModule 357052722fSJay 36b1ded4e8Sguohongyu//TODO: remove this 37b1ded4e8Sguohongyuobject DebugFlags { 38b1ded4e8Sguohongyu val fdip = false 397052722fSJay} 407052722fSJay 41b1ded4e8Sguohongyuclass PIQReq(implicit p: Parameters) extends IPrefetchBundle { 42b1ded4e8Sguohongyu val paddr = UInt(PAddrBits.W) 43b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 44b1ded4e8Sguohongyu} 45b1ded4e8Sguohongyu 46b1ded4e8Sguohongyuclass PIQData(implicit p: Parameters) extends IPrefetchBundle { 47b1ded4e8Sguohongyu val ptage = UInt(tagBits.W) 48b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 49b1ded4e8Sguohongyu val cacheline = UInt(blockBits.W) 50b1ded4e8Sguohongyu val writeBack = Bool() 51b1ded4e8Sguohongyu} 52b1ded4e8Sguohongyu 53b1ded4e8Sguohongyuclass PIQToMainPipe(implicit p: Parameters) extends IPrefetchBundle{ 54b1ded4e8Sguohongyu val info = DecoupledIO(new PIQData) 55b1ded4e8Sguohongyu} 56b1ded4e8Sguohongyu/* need change name */ 57b1ded4e8Sguohongyuclass MainPipeToPrefetchPipe(implicit p: Parameters) extends IPrefetchBundle { 58b1ded4e8Sguohongyu val ptage = UInt(tagBits.W) 59b1ded4e8Sguohongyu val vSetIdx = UInt(idxBits.W) 60b1ded4e8Sguohongyu} 61b1ded4e8Sguohongyu 62b1ded4e8Sguohongyuclass MainPipeMissInfo(implicit p: Parameters) extends IPrefetchBundle { 63b1ded4e8Sguohongyu val s1_already_check_ipf = Output(Bool()) 64b1ded4e8Sguohongyu val s2_miss_info = Vec(PortNumber, ValidIO(new MainPipeToPrefetchPipe)) 65b1ded4e8Sguohongyu} 667052722fSJay 677052722fSJayclass IPrefetchToMissUnit(implicit p: Parameters) extends IPrefetchBundle{ 687052722fSJay val enqReq = DecoupledIO(new PIQReq) 697052722fSJay} 707052722fSJay 717052722fSJayclass IPredfetchIO(implicit p: Parameters) extends IPrefetchBundle { 727052722fSJay val fromFtq = Flipped(new FtqPrefechBundle) 73f1fe8698SLemover val iTLBInter = new TlbRequestIO 7461e1db30SJay val pmp = new ICachePMPBundle 750c26d810Sguohongyu val toIMeta = Decoupled(new ICacheMetaReadReqBundle) 760c26d810Sguohongyu val fromIMeta = Input(new ICacheMetaReadRespBundle) 777052722fSJay val toMissUnit = new IPrefetchToMissUnit 78b1ded4e8Sguohongyu val freePIQEntry = Input(UInt(log2Ceil(nPrefetchEntries).W)) 79974a902cSguohongyu val fromMSHR = Flipped(Vec(totalMSHRNum,ValidIO(UInt(PAddrBits.W)))) 80b1ded4e8Sguohongyu val IPFBufferRead = Flipped(new IPFBufferFilterRead) 81b1ded4e8Sguohongyu /** icache main pipe to prefetch pipe*/ 82974a902cSguohongyu val mainPipeMissSlotInfo = Flipped(Vec(PortNumber,ValidIO(new MainPipeToPrefetchPipe))) 83a108d429SJay 84a108d429SJay val prefetchEnable = Input(Bool()) 85a108d429SJay val prefetchDisable = Input(Bool()) 86b1ded4e8Sguohongyu val fencei = Input(Bool()) 87b1ded4e8Sguohongyu} 88b1ded4e8Sguohongyu 89b1ded4e8Sguohongyu/** Prefetch Buffer **/ 90b1ded4e8Sguohongyu 9164d7d412Sguohongyuclass IPFWritePtrQueue(implicit p: Parameters) extends IPrefetchModule with HasCircularQueuePtrHelper 9264d7d412Sguohongyu{ 9364d7d412Sguohongyu val io = IO(new Bundle{ 9464d7d412Sguohongyu val free_ptr = DecoupledIO(UInt(log2Ceil(nIPFBufferSize).W)) 9564d7d412Sguohongyu val release_ptr = Flipped(ValidIO(UInt(log2Ceil(nIPFBufferSize).W))) 962a6078bfSguohongyu val flush = Input(Bool()) 9764d7d412Sguohongyu }) 9864d7d412Sguohongyu /* define ptr */ 9964d7d412Sguohongyu class IPFPtr(implicit p: Parameters) extends CircularQueuePtr[IPFPtr]( 10064d7d412Sguohongyu p => p(XSCoreParamsKey).icacheParameters.nPrefBufferEntries 10164d7d412Sguohongyu ){ 10264d7d412Sguohongyu } 10364d7d412Sguohongyu 10464d7d412Sguohongyu object IPFPtr { 10564d7d412Sguohongyu def apply(f: Bool, v: UInt)(implicit p: Parameters): IPFPtr = { 10664d7d412Sguohongyu val ptr = Wire(new IPFPtr) 10764d7d412Sguohongyu ptr.flag := f 10864d7d412Sguohongyu ptr.value := v 10964d7d412Sguohongyu ptr 11064d7d412Sguohongyu } 11164d7d412Sguohongyu } 11264d7d412Sguohongyu 11364d7d412Sguohongyu val queue = RegInit(VecInit((0 until nIPFBufferSize).map(i => i.U(log2Ceil(nIPFBufferSize).W)))) 11464d7d412Sguohongyu val enq_ptr = RegInit(IPFPtr(true.B, 0.U)) 11564d7d412Sguohongyu val deq_ptr = RegInit(IPFPtr(false.B, 0.U)) 11664d7d412Sguohongyu 11764d7d412Sguohongyu io.free_ptr.valid := !isEmpty(enq_ptr, deq_ptr) 11864d7d412Sguohongyu io.free_ptr.bits := queue(deq_ptr.value) 11964d7d412Sguohongyu deq_ptr := deq_ptr + io.free_ptr.fire 12064d7d412Sguohongyu 12164d7d412Sguohongyu when (io.release_ptr.valid) { 12264d7d412Sguohongyu queue(enq_ptr.value) := io.release_ptr.bits 12364d7d412Sguohongyu enq_ptr := enq_ptr + 1.U 12464d7d412Sguohongyu } 12564d7d412Sguohongyu 1262a6078bfSguohongyu when (io.flush) { 1272a6078bfSguohongyu queue := RegInit(VecInit((0 until nIPFBufferSize).map(i => i.U(log2Ceil(nIPFBufferSize).W)))) 1282a6078bfSguohongyu enq_ptr := RegInit(IPFPtr(true.B, 0.U)) 1292a6078bfSguohongyu deq_ptr := RegInit(IPFPtr(false.B, 0.U)) 1302a6078bfSguohongyu } 1312a6078bfSguohongyu 13264d7d412Sguohongyu XSError(isBefore(enq_ptr, deq_ptr) && !isFull(enq_ptr, deq_ptr), "enq_ptr should not before deq_ptr\n") 13364d7d412Sguohongyu} 13464d7d412Sguohongyu 135b1ded4e8Sguohongyu 136b1ded4e8Sguohongyuclass PrefetchBuffer(implicit p: Parameters) extends IPrefetchModule 137b1ded4e8Sguohongyu{ 138b1ded4e8Sguohongyu val io = IO(new Bundle{ 139c2ba7c80Sguohongyu val hartId = Input(UInt(8.W)) 140b1ded4e8Sguohongyu val read = new IPFBufferRead 1410c26d810Sguohongyu val filter_read = Vec(prefetchPipeNum, new IPFBufferFilterRead) 142b1ded4e8Sguohongyu val write = Flipped(ValidIO(new IPFBufferWrite)) 143b1ded4e8Sguohongyu /** to ICache replacer */ 144b1ded4e8Sguohongyu val replace = new IPFBufferMove 145b1ded4e8Sguohongyu /** move & move filter port */ 146b1ded4e8Sguohongyu val mainpipe_missinfo = Flipped(new MainPipeMissInfo) 1470c26d810Sguohongyu val meta_filter_read_req = Decoupled(new ICacheMetaReadReqBundle) 1480c26d810Sguohongyu val meta_filter_read_resp = Input(new ICacheMetaReadRespBundle) 149b1ded4e8Sguohongyu val move = new Bundle() { 150b1ded4e8Sguohongyu val meta_write = DecoupledIO(new ICacheMetaWriteBundle) 151b1ded4e8Sguohongyu val data_write = DecoupledIO(new ICacheDataWriteBundle) 152b1ded4e8Sguohongyu } 153b1ded4e8Sguohongyu val fencei = Input(Bool()) 154b1ded4e8Sguohongyu }) 155b1ded4e8Sguohongyu 156b1ded4e8Sguohongyu class IPFBufferEntryMeta(implicit p: Parameters) extends IPrefetchBundle 157b1ded4e8Sguohongyu { 158b1ded4e8Sguohongyu val tag = UInt(tagBits.W) 159b1ded4e8Sguohongyu val index = UInt(idxBits.W) 160b1ded4e8Sguohongyu val paddr = UInt(PAddrBits.W) 161b1ded4e8Sguohongyu val valid = Bool() 162b1ded4e8Sguohongyu val confidence = UInt(log2Ceil(maxIPFMoveConf + 1).W) 163b1ded4e8Sguohongyu val move = Bool() 164d4112e88Sguohongyu val has_been_hit = Bool() 165b1ded4e8Sguohongyu } 166b1ded4e8Sguohongyu 167b1ded4e8Sguohongyu class IPFBufferEntryData(implicit p: Parameters) extends IPrefetchBundle 168b1ded4e8Sguohongyu { 169b1ded4e8Sguohongyu val cachline = UInt(blockBits.W) 170b1ded4e8Sguohongyu } 171b1ded4e8Sguohongyu 172b1ded4e8Sguohongyu def InitQueue[T <: Data](entry: T, size: Int): Vec[T] ={ 173b1ded4e8Sguohongyu return RegInit(VecInit(Seq.fill(size)(0.U.asTypeOf(entry.cloneType)))) 174b1ded4e8Sguohongyu } 175b1ded4e8Sguohongyu 176b1ded4e8Sguohongyu val meta_buffer = InitQueue(new IPFBufferEntryMeta, size = nIPFBufferSize) 177b1ded4e8Sguohongyu val data_buffer = InitQueue(new IPFBufferEntryData, size = nIPFBufferSize) 178b1ded4e8Sguohongyu 17964d7d412Sguohongyu val ipf_write_ptr_queue = Module(new IPFWritePtrQueue()) 1802a6078bfSguohongyu ipf_write_ptr_queue.io.flush := io.fencei 18164d7d412Sguohongyu 1826f9ed85eSguohongyu val meta_buffer_empty_oh = WireInit(VecInit(Seq.fill(nIPFBufferSize)(false.B))) 1836f9ed85eSguohongyu (0 until nIPFBufferSize).foreach { i => 1846f9ed85eSguohongyu meta_buffer_empty_oh(i) := !meta_buffer(i).valid 1856f9ed85eSguohongyu } 1866f9ed85eSguohongyu XSPerfAccumulate("ipfbuffer_empty_entry_multi_cycle", PopCount(meta_buffer_empty_oh)) 1876f9ed85eSguohongyu 188b1ded4e8Sguohongyu /** filter read logic */ 1890c26d810Sguohongyu val fr_vidx = (0 until prefetchPipeNum).map (i => io.filter_read(i).req.vSetIdx) 1900c26d810Sguohongyu val fr_ptag = (0 until prefetchPipeNum).map (i => get_phy_tag(io.filter_read(i).req.paddr)) 191b1ded4e8Sguohongyu 1920c26d810Sguohongyu val fr_hit_in_buffer = (0 until prefetchPipeNum).map (i => meta_buffer.map(e => e.valid && (e.tag === fr_ptag(i)) && (e.index === fr_vidx(i))).reduce(_||_)) 19334f9624dSguohongyu val fr_hit_in_s1, fr_hit_in_s2, fr_hit_in_s3 = Wire(Vec(prefetchPipeNum, Bool())) 194b1ded4e8Sguohongyu 1950c26d810Sguohongyu (0 until prefetchPipeNum).foreach(i => io.filter_read(i).resp.ipf_hit := fr_hit_in_buffer(i) || fr_hit_in_s1(i) || fr_hit_in_s2(i) || fr_hit_in_s3(i)) 196b1ded4e8Sguohongyu 197b1ded4e8Sguohongyu /** read logic */ 198b1ded4e8Sguohongyu (0 until PortNumber).foreach(i => io.read.req(i).ready := true.B) 199b1ded4e8Sguohongyu val r_valid = VecInit((0 until PortNumber).map( i => io.read.req(i).valid)).reduce(_||_) 200b1ded4e8Sguohongyu val r_vidx = VecInit((0 until PortNumber).map(i => get_idx(io.read.req(i).bits.vaddr))) 201b1ded4e8Sguohongyu val r_ptag = VecInit((0 until PortNumber).map(i => get_phy_tag(io.read.req(i).bits.paddr))) 202b1ded4e8Sguohongyu val r_hit_oh = VecInit((0 until PortNumber).map(i => 203b1ded4e8Sguohongyu VecInit(meta_buffer.map(entry => 204b1ded4e8Sguohongyu io.read.req(i).valid && // need this condition 205b1ded4e8Sguohongyu entry.valid && 206b1ded4e8Sguohongyu entry.tag === r_ptag(i) && 207b1ded4e8Sguohongyu entry.index === r_vidx(i) 208b1ded4e8Sguohongyu )))) 209b1ded4e8Sguohongyu val r_buffer_hit = VecInit(r_hit_oh.map(_.reduce(_||_))) 210b1ded4e8Sguohongyu val r_buffer_hit_idx = VecInit(r_hit_oh.map(PriorityEncoder(_))) 21164d7d412Sguohongyu val r_buffer_hit_data = VecInit((0 until PortNumber).map(i => Mux1H(r_hit_oh(i), data_buffer.map(_.cachline)))) // TODO : be careful of Mux1H 212b1ded4e8Sguohongyu 213b1ded4e8Sguohongyu /** "read" also check data in move pipeline */ 214b1ded4e8Sguohongyu val r_moves1pipe_hit_s1, r_moves1pipe_hit_s2, r_moves1pipe_hit_s3 = WireInit(VecInit(Seq.fill(PortNumber)(false.B))) 215b1ded4e8Sguohongyu val s1_move_data_cacheline, s2_move_data_cacheline, s3_move_data_cacheline = Wire(UInt(blockBits.W)) 216b1ded4e8Sguohongyu 217b1ded4e8Sguohongyu (0 until PortNumber).foreach{ i => 218b1ded4e8Sguohongyu io.read.resp(i).valid := io.read.req(i).valid 219b1ded4e8Sguohongyu 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) 220b1ded4e8Sguohongyu io.read.resp(i).bits.cacheline := Mux(r_buffer_hit(i), r_buffer_hit_data(i), 221b1ded4e8Sguohongyu Mux(r_moves1pipe_hit_s1(i), s1_move_data_cacheline, 222b1ded4e8Sguohongyu Mux(r_moves1pipe_hit_s2(i), s2_move_data_cacheline, s3_move_data_cacheline))) 223b1ded4e8Sguohongyu } 224b1ded4e8Sguohongyu 225d4112e88Sguohongyu (0 until PortNumber).foreach { i => 22669c27f53Sguohongyu when(io.read.req(i).valid && r_hit_oh(i).reduce(_ || _)) { 227d4112e88Sguohongyu meta_buffer(r_buffer_hit_idx(i)).has_been_hit := true.B 228d4112e88Sguohongyu } 22969c27f53Sguohongyu XSPerfAccumulate("ipf_entry_first_hit_by_port_" + i, io.read.req(i).valid && r_hit_oh(i).reduce(_ || _) && 230d4112e88Sguohongyu meta_buffer(r_buffer_hit_idx(i)).has_been_hit === false.B) 231d4112e88Sguohongyu } 232d4112e88Sguohongyu 233d4112e88Sguohongyu 234b1ded4e8Sguohongyu /** move logic */ 235b1ded4e8Sguohongyu val r_buffer_hit_s2 = RegNext(r_buffer_hit, init=0.U.asTypeOf(r_buffer_hit.cloneType)) 236b1ded4e8Sguohongyu val r_buffer_hit_idx_s2 = RegNext(r_buffer_hit_idx) 237b1ded4e8Sguohongyu val r_rvalid_s2 = RegNext(r_valid, init=false.B) 238b1ded4e8Sguohongyu 239b1ded4e8Sguohongyu val s2_move_valid_0 = r_rvalid_s2 && r_buffer_hit_s2(0) 240b1ded4e8Sguohongyu val s2_move_valid_1 = r_rvalid_s2 && r_buffer_hit_s2(1) 241b1ded4e8Sguohongyu 242b1ded4e8Sguohongyu XSPerfAccumulate("prefetch_hit_bank_0", r_rvalid_s2 && r_buffer_hit_s2(0)) 243b1ded4e8Sguohongyu XSPerfAccumulate("prefetch_hit_bank_1", r_rvalid_s2 && r_buffer_hit_s2(1)) 244b1ded4e8Sguohongyu 245b1ded4e8Sguohongyu val move_queue = RegInit(VecInit(Seq.fill(nIPFBufferSize)(0.U.asTypeOf(r_buffer_hit_idx_s2(0))))) 246b1ded4e8Sguohongyu 247b1ded4e8Sguohongyu val curr_move_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 248b1ded4e8Sguohongyu val curr_hit_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 249b1ded4e8Sguohongyu 250b1ded4e8Sguohongyu val s2_move_conf_full_0 = meta_buffer(r_buffer_hit_idx_s2(0)).confidence === (maxIPFMoveConf).U 251b1ded4e8Sguohongyu val s2_move_conf_full_1 = meta_buffer(r_buffer_hit_idx_s2(1)).confidence === (maxIPFMoveConf).U 252b1ded4e8Sguohongyu 253b1ded4e8Sguohongyu val move_repeat_0 = meta_buffer(r_buffer_hit_idx_s2(0)).move 254b1ded4e8Sguohongyu 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)) 255b1ded4e8Sguohongyu 256b1ded4e8Sguohongyu val s2_move_0 = s2_move_valid_0 && !move_repeat_0 257b1ded4e8Sguohongyu val s2_move_1 = s2_move_valid_1 && !move_repeat_1 258b1ded4e8Sguohongyu 259b1ded4e8Sguohongyu val s2_move_enqueue_0 = s2_move_0 && s2_move_conf_full_0 260b1ded4e8Sguohongyu val s2_move_enqueue_1 = s2_move_1 && s2_move_conf_full_1 261b1ded4e8Sguohongyu 262b1ded4e8Sguohongyu when(s2_move_0) { 263b1ded4e8Sguohongyu when(s2_move_conf_full_0) { 264b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(0)).move := true.B 265b1ded4e8Sguohongyu }.otherwise { 266b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(0)).confidence := meta_buffer(r_buffer_hit_idx_s2(0)).confidence + 1.U 267b1ded4e8Sguohongyu } 268b1ded4e8Sguohongyu } 269b1ded4e8Sguohongyu when(s2_move_1) { 270b1ded4e8Sguohongyu when(s2_move_conf_full_1) { 271b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(1)).move := true.B 272b1ded4e8Sguohongyu }.otherwise { 273b1ded4e8Sguohongyu meta_buffer(r_buffer_hit_idx_s2(1)).confidence := meta_buffer(r_buffer_hit_idx_s2(1)).confidence + 1.U 274b1ded4e8Sguohongyu } 275b1ded4e8Sguohongyu } 276b1ded4e8Sguohongyu 277b1ded4e8Sguohongyu when(s2_move_enqueue_0 && !s2_move_enqueue_1) { 278b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0) 279b1ded4e8Sguohongyu 280b1ded4e8Sguohongyu when((curr_hit_ptr + 1.U) =/= curr_move_ptr){ 281b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 282b1ded4e8Sguohongyu } 283b1ded4e8Sguohongyu }.elsewhen(!s2_move_enqueue_0 && s2_move_enqueue_1) { 284b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(1) 285b1ded4e8Sguohongyu 286b1ded4e8Sguohongyu when((curr_hit_ptr + 1.U) =/= curr_move_ptr){ 287b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 288b1ded4e8Sguohongyu } 289b1ded4e8Sguohongyu }.elsewhen(s2_move_enqueue_0 && s2_move_enqueue_1) { 290b1ded4e8Sguohongyu move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0) 291b1ded4e8Sguohongyu move_queue(curr_hit_ptr + 1.U) := r_buffer_hit_idx_s2(1) 292b1ded4e8Sguohongyu when((curr_hit_ptr + 2.U) =/= curr_move_ptr){ 293b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 2.U 294b1ded4e8Sguohongyu }.otherwise{ 295b1ded4e8Sguohongyu curr_hit_ptr := curr_hit_ptr + 1.U 296b1ded4e8Sguohongyu } 297b1ded4e8Sguohongyu } 298b1ded4e8Sguohongyu 299b1ded4e8Sguohongyu val move_queue_empty = curr_move_ptr === curr_hit_ptr 300b1ded4e8Sguohongyu /** pipeline control signal */ 301b1ded4e8Sguohongyu val s1_ready, s2_ready, s3_ready = Wire(Bool()) 302b1ded4e8Sguohongyu val s0_fire, s1_fire, s2_fire, s3_fire = Wire(Bool()) 303b1ded4e8Sguohongyu 304b1ded4e8Sguohongyu /** stage 0 */ 305b1ded4e8Sguohongyu val s0_valid = !move_queue_empty && meta_buffer(move_queue(curr_move_ptr)).move 306b1ded4e8Sguohongyu 307b1ded4e8Sguohongyu val s0_move_idx = move_queue(curr_move_ptr) 308b1ded4e8Sguohongyu val s0_move_meta = meta_buffer(s0_move_idx) 309b1ded4e8Sguohongyu val s0_move_data = data_buffer(s0_move_idx) 310b1ded4e8Sguohongyu io.replace.vsetIdx := meta_buffer(s0_move_idx).index 311b1ded4e8Sguohongyu val s0_waymask = io.replace.waymask 312b1ded4e8Sguohongyu 313b1ded4e8Sguohongyu s0_fire := s0_valid && s1_ready 314b1ded4e8Sguohongyu 315b1ded4e8Sguohongyu /** curr_move_ptr control logic */ 316b1ded4e8Sguohongyu val s0_move_jump = !move_queue_empty && !meta_buffer(move_queue(curr_move_ptr)).move 317b1ded4e8Sguohongyu when (s0_fire) { 318b1ded4e8Sguohongyu curr_move_ptr := curr_move_ptr + 1.U 31964d7d412Sguohongyu meta_buffer(s0_move_idx).valid := false.B // TODO : maybe should not invalid 320b1ded4e8Sguohongyu meta_buffer(s0_move_idx).move := false.B 321b1ded4e8Sguohongyu meta_buffer(s0_move_idx).confidence := 0.U 322b1ded4e8Sguohongyu }.elsewhen(s0_move_jump) { 323b1ded4e8Sguohongyu curr_move_ptr := curr_move_ptr + 1.U 324b1ded4e8Sguohongyu } 325b1ded4e8Sguohongyu 326b1ded4e8Sguohongyu /** stage 1 : send req to metaArray */ 327b1ded4e8Sguohongyu val s1_valid = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = io.fencei, lastFlush = false.B) 328b1ded4e8Sguohongyu 329b1ded4e8Sguohongyu val s1_move_idx = RegEnable(s0_move_idx, s0_fire) 330b1ded4e8Sguohongyu val s1_move_meta = RegEnable(s0_move_meta, s0_fire) 331b1ded4e8Sguohongyu val s1_move_data = RegEnable(s0_move_data, s0_fire) 332b1ded4e8Sguohongyu val s1_waymask = RegEnable(s0_waymask, s0_fire) 333b1ded4e8Sguohongyu 3340c26d810Sguohongyu io.meta_filter_read_req.valid := s1_valid 3350c26d810Sguohongyu io.meta_filter_read_req.bits.idx := s1_move_meta.index 336b1ded4e8Sguohongyu 337b1ded4e8Sguohongyu s1_ready := !s1_valid || s1_fire 3380c26d810Sguohongyu s1_fire := s1_valid && io.meta_filter_read_req.ready && s2_ready 339b1ded4e8Sguohongyu 3400c26d810Sguohongyu (0 until prefetchPipeNum).foreach(i => fr_hit_in_s1(i) := s1_valid && s1_move_meta.index === fr_vidx(i) && s1_move_meta.tag === fr_ptag(i)) 341b1ded4e8Sguohongyu 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)) 342b1ded4e8Sguohongyu s1_move_data_cacheline := s1_move_data.cachline 343b1ded4e8Sguohongyu 344b1ded4e8Sguohongyu /** stage 2 : collect message from metaArray and mainPipe to filter */ 345b1ded4e8Sguohongyu val s2_valid = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = io.fencei, lastFlush = false.B) 346b1ded4e8Sguohongyu 347b1ded4e8Sguohongyu val s2_move_idx = RegEnable(s1_move_idx, s1_fire) 348b1ded4e8Sguohongyu val s2_move_meta = RegEnable(s1_move_meta, s1_fire) 349b1ded4e8Sguohongyu val s2_move_data = RegEnable(s1_move_data, s1_fire) 350b1ded4e8Sguohongyu val s2_waymask = RegEnable(s1_waymask, s1_fire) 351b1ded4e8Sguohongyu 3520c26d810Sguohongyu val s2_meta_ptags = ResultHoldBypass(data = io.meta_filter_read_resp.tags, valid = RegNext(s1_fire)) 3530c26d810Sguohongyu val s2_meta_valids = ResultHoldBypass(data = io.meta_filter_read_resp.entryValid, valid = RegNext(s1_fire)) 354b1ded4e8Sguohongyu 3550c26d810Sguohongyu val s2_tag_eq_vec = VecInit((0 until nWays).map(w => s2_meta_ptags(w) === s2_move_meta.tag)) // just use port 0 3560c26d810Sguohongyu val s2_tag_match_vec = VecInit(s2_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s2_meta_valids(w)}) 357b1ded4e8Sguohongyu val s2_hit_in_meta_array = ParallelOR(s2_tag_match_vec) 358b1ded4e8Sguohongyu 359b1ded4e8Sguohongyu val main_s2_missinfo = io.mainpipe_missinfo.s2_miss_info 360b1ded4e8Sguohongyu val s2_hit_main_s2_missreq = VecInit((0 until PortNumber).map(i => 361b1ded4e8Sguohongyu main_s2_missinfo(i).valid && s2_move_meta.index === main_s2_missinfo(i).bits.vSetIdx 362b1ded4e8Sguohongyu && s2_move_meta.tag === main_s2_missinfo(i).bits.ptage)).reduce(_||_) 363b1ded4e8Sguohongyu 364b1ded4e8Sguohongyu val s2_discard = s2_hit_in_meta_array || s2_hit_main_s2_missreq // || s2_hit_main_s1_missreq 365b1ded4e8Sguohongyu val s2_discard_latch = holdReleaseLatch(valid = s2_discard, release = s2_fire, flush = io.fencei) 366b1ded4e8Sguohongyu if(DebugFlags.fdip){ 367b1ded4e8Sguohongyu when (s2_fire && s2_discard_latch) { 368b1ded4e8Sguohongyu printf("<%d> IPrefetchBuffer: s2_discard : hit_in_meta_array=%d,hit_in_main_s2=%d, ptag=0x%x\n", 369b1ded4e8Sguohongyu GTimer(), s2_hit_in_meta_array, s2_hit_main_s2_missreq, s2_move_meta.tag) 370b1ded4e8Sguohongyu } 371b1ded4e8Sguohongyu } 372b1ded4e8Sguohongyu 373b1ded4e8Sguohongyu s2_ready := !s2_valid || s2_fire 374b1ded4e8Sguohongyu s2_fire := s2_valid && s3_ready && io.mainpipe_missinfo.s1_already_check_ipf 375b1ded4e8Sguohongyu 3760c26d810Sguohongyu (0 until prefetchPipeNum).foreach(i => fr_hit_in_s2(i) := s2_valid && s2_move_meta.index === fr_vidx(i) && s2_move_meta.tag === fr_ptag(i)) 377b1ded4e8Sguohongyu 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)) 378b1ded4e8Sguohongyu s2_move_data_cacheline := s2_move_data.cachline 379b1ded4e8Sguohongyu 380b1ded4e8Sguohongyu /** stage 3 : move data to metaArray and dataArray */ 381b1ded4e8Sguohongyu val s3_valid = generatePipeControl(lastFire = s2_fire, thisFire = s3_fire, thisFlush = io.fencei, lastFlush = false.B) 382b1ded4e8Sguohongyu 383b1ded4e8Sguohongyu val s3_move_idx = RegEnable(s2_move_idx, s2_fire) 384b1ded4e8Sguohongyu val s3_move_meta = RegEnable(s2_move_meta, s2_fire) 385b1ded4e8Sguohongyu val s3_move_data = RegEnable(s2_move_data, s2_fire) 386b1ded4e8Sguohongyu val s3_waymask = RegEnable(s2_waymask, s2_fire) 387b1ded4e8Sguohongyu val s3_discard = RegEnable(s2_discard_latch, s2_fire) 388b1ded4e8Sguohongyu 389b1ded4e8Sguohongyu io.move.meta_write.valid := s3_valid && !s3_discard && !io.fencei 390b1ded4e8Sguohongyu io.move.data_write.valid := s3_valid && !s3_discard && !io.fencei 391b1ded4e8Sguohongyu io.move.meta_write.bits.generate( 392b1ded4e8Sguohongyu tag = s3_move_meta.tag, 393b1ded4e8Sguohongyu idx = s3_move_meta.index, 394b1ded4e8Sguohongyu waymask = s3_waymask, 395b1ded4e8Sguohongyu bankIdx = s3_move_meta.index(0)) 396b1ded4e8Sguohongyu io.move.data_write.bits.generate( 397b1ded4e8Sguohongyu data = s3_move_data.cachline, 398b1ded4e8Sguohongyu idx = s3_move_meta.index, 399b1ded4e8Sguohongyu waymask = s3_waymask, 400b1ded4e8Sguohongyu bankIdx = s3_move_meta.index(0), 401b1ded4e8Sguohongyu paddr = s3_move_meta.paddr) 402b1ded4e8Sguohongyu 403b1ded4e8Sguohongyu s3_ready := !s3_valid || s3_fire 404b1ded4e8Sguohongyu s3_fire := io.move.meta_write.fire && io.move.data_write.fire || s3_discard || io.fencei 405b1ded4e8Sguohongyu assert((io.move.meta_write.fire && io.move.data_write.fire) || (!io.move.meta_write.fire && !io.move.data_write.fire), 406b1ded4e8Sguohongyu "meta and data array need fire at same time") 407b1ded4e8Sguohongyu 4080c26d810Sguohongyu (0 until prefetchPipeNum).foreach(i => fr_hit_in_s3(i) := s3_valid && s3_move_meta.index === fr_vidx(i) && s3_move_meta.tag === fr_ptag(i)) 409b1ded4e8Sguohongyu 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)) 410b1ded4e8Sguohongyu s3_move_data_cacheline := s3_move_data.cachline 411b1ded4e8Sguohongyu 412b1ded4e8Sguohongyu if (DebugFlags.fdip) { 413b1ded4e8Sguohongyu when(io.move.meta_write.fire) { 414b1ded4e8Sguohongyu printf("<%d> IPrefetchBuffer: move data to meta sram:ptag=0x%x,vidx=0x%x,waymask=0x%x\n", 415b1ded4e8Sguohongyu GTimer(), s3_move_meta.tag,s3_move_meta.index,s3_waymask ) 416b1ded4e8Sguohongyu } 417b1ded4e8Sguohongyu } 418b1ded4e8Sguohongyu 419afa866b1Sguohongyu if (env.EnableDifftest) { 420afa866b1Sguohongyu val difftest = Module(new DifftestRefillEvent) 421afa866b1Sguohongyu difftest.io.clock := clock 422c2ba7c80Sguohongyu difftest.io.coreid := io.hartId 423afa866b1Sguohongyu difftest.io.cacheid := 6.U 424afa866b1Sguohongyu difftest.io.valid := io.move.meta_write.fire 425afa866b1Sguohongyu difftest.io.addr := s3_move_meta.paddr 426afa866b1Sguohongyu difftest.io.data := s3_move_data.cachline.asTypeOf(difftest.io.data) 427afa866b1Sguohongyu } 428afa866b1Sguohongyu 429b1ded4e8Sguohongyu /** write logic */ 430b1ded4e8Sguohongyu val replacer = ReplacementPolicy.fromString(Some("random"), nIPFBufferSize) 43164d7d412Sguohongyu val curr_write_ptr = Wire(UInt(log2Ceil(nIPFBufferSize).W)) 43264d7d412Sguohongyu when (ipf_write_ptr_queue.io.free_ptr.valid) { 43364d7d412Sguohongyu curr_write_ptr := ipf_write_ptr_queue.io.free_ptr.bits 43464d7d412Sguohongyu }.otherwise { 43564d7d412Sguohongyu curr_write_ptr := replacer.way 43664d7d412Sguohongyu when (io.write.valid) { 43764d7d412Sguohongyu replacer.miss 43864d7d412Sguohongyu } 43964d7d412Sguohongyu } 440b1ded4e8Sguohongyu 44164d7d412Sguohongyu ipf_write_ptr_queue.io.release_ptr.valid := s0_fire 44264d7d412Sguohongyu ipf_write_ptr_queue.io.release_ptr.bits := s0_move_idx 44364d7d412Sguohongyu 44464d7d412Sguohongyu ipf_write_ptr_queue.io.free_ptr.ready := io.write.valid 445b1ded4e8Sguohongyu when(io.write.valid) { 446b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).tag := io.write.bits.meta.tag 447b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).index := io.write.bits.meta.index 448b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).paddr := io.write.bits.meta.paddr 449b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).valid := true.B 450b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).move := false.B 451b1ded4e8Sguohongyu meta_buffer(curr_write_ptr).confidence := 0.U 452d4112e88Sguohongyu meta_buffer(curr_write_ptr).has_been_hit := false.B 453b1ded4e8Sguohongyu 454b1ded4e8Sguohongyu data_buffer(curr_write_ptr).cachline := io.write.bits.data 455b1ded4e8Sguohongyu 456b1ded4e8Sguohongyu } 457b1ded4e8Sguohongyu 458b1ded4e8Sguohongyu /** fencei: invalid all entries */ 459b1ded4e8Sguohongyu when(io.fencei) { 4602a6078bfSguohongyu meta_buffer.foreach { b => 461b1ded4e8Sguohongyu b.valid := false.B 462b1ded4e8Sguohongyu b.move := false.B 463b1ded4e8Sguohongyu b.confidence := 0.U 4642a6078bfSguohongyu b.has_been_hit := false.B 465b1ded4e8Sguohongyu } 4661d4724e4Sguohongyu (0 until PortNumber).foreach(i => r_buffer_hit_s2(i) := 0.U ) 4672a6078bfSguohongyu r_rvalid_s2 := 0.U 4682a6078bfSguohongyu curr_move_ptr := 0.U 4692a6078bfSguohongyu curr_hit_ptr := 0.U 470b1ded4e8Sguohongyu } 471b1ded4e8Sguohongyu 4727052722fSJay} 4737052722fSJay 4747052722fSJayclass IPrefetchPipe(implicit p: Parameters) extends IPrefetchModule 4757052722fSJay{ 4767052722fSJay val io = IO(new IPredfetchIO) 4777052722fSJay 478a108d429SJay val enableBit = RegInit(false.B) 479b1ded4e8Sguohongyu val maxPrefetchCounter = RegInit(0.U(log2Ceil(nPrefetchEntries + 1).W)) 480a108d429SJay 481b1ded4e8Sguohongyu val reachMaxSize = maxPrefetchCounter === nPrefetchEntries.U 482a108d429SJay 483b1ded4e8Sguohongyu // when(io.prefetchEnable){ 484b1ded4e8Sguohongyu // enableBit := true.B 485b1ded4e8Sguohongyu // }.elsewhen((enableBit && io.prefetchDisable) || (enableBit && reachMaxSize)){ 486b1ded4e8Sguohongyu // enableBit := false.B 487b1ded4e8Sguohongyu // } 488b1ded4e8Sguohongyu // ignore prefetchEnable from ICacheMainPipe 489a108d429SJay enableBit := true.B 490a108d429SJay 491a108d429SJay class PrefetchDir(implicit p: Parameters) extends IPrefetchBundle 492a108d429SJay { 493a108d429SJay val valid = Bool() 494a108d429SJay val paddr = UInt(PAddrBits.W) 495a108d429SJay } 496a108d429SJay 497a108d429SJay val prefetch_dir = RegInit(VecInit(Seq.fill(nPrefetchEntries)(0.U.asTypeOf(new PrefetchDir)))) 498a108d429SJay 4997052722fSJay val fromFtq = io.fromFtq 500974a902cSguohongyu val mainPipeMissSlotInfo = io.mainPipeMissSlotInfo 5017052722fSJay val (toITLB, fromITLB) = (io.iTLBInter.req, io.iTLBInter.resp) 502c3b763d0SYinan Xu io.iTLBInter.req_kill := false.B 5030c26d810Sguohongyu val (toIMeta, fromIMeta, fromIMetaValid) = (io.toIMeta, io.fromIMeta.metaData, io.fromIMeta.entryValid) 504b1ded4e8Sguohongyu val (toIPFBuffer, fromIPFBuffer) = (io.IPFBufferRead.req, io.IPFBufferRead.resp) 5057052722fSJay val (toPMP, fromPMP) = (io.pmp.req, io.pmp.resp) 5067052722fSJay val toMissUnit = io.toMissUnit 5077052722fSJay 5087052722fSJay val p0_fire, p1_fire, p2_fire, p3_fire = WireInit(false.B) 509b1ded4e8Sguohongyu val p0_discard, p1_discard, p2_discard, p3_discard = WireInit(false.B) 5109bba777eSssszwic val p1_ready, p2_ready, p3_ready = WireInit(false.B) 5117052722fSJay 5127052722fSJay /** Prefetch Stage 0: req from Ftq */ 5137052722fSJay val p0_valid = fromFtq.req.valid 514d6b06a99SJay val p0_vaddr = addrAlign(fromFtq.req.bits.target, blockBytes, VAddrBits) 515b1ded4e8Sguohongyu val p0_vaddr_reg = RegEnable(p0_vaddr, fromFtq.req.fire()) 5167052722fSJay 517b1ded4e8Sguohongyu /* Cancel request when prefetch not enable 518b1ded4e8Sguohongyu * or the request from FTQ is same as last time */ 519b1ded4e8Sguohongyu val p0_req_cancel = !enableBit || (p0_vaddr === p0_vaddr_reg) || io.fencei 520b1ded4e8Sguohongyu p0_fire := p0_valid && p1_ready && toITLB.fire() && !fromITLB.bits.miss && toIMeta.ready && enableBit && !p0_req_cancel 5219bba777eSssszwic // p0_discard := p0_valid && p0_req_cancel 522b1ded4e8Sguohongyu 5239bba777eSssszwic toIMeta.valid := p0_valid && !p0_req_cancel 5240c26d810Sguohongyu toIMeta.bits.idx := get_idx(p0_vaddr) 5257052722fSJay 5269bba777eSssszwic toITLB.valid := p0_valid && !p0_req_cancel 5277052722fSJay toITLB.bits.size := 3.U // TODO: fix the size 5287052722fSJay toITLB.bits.vaddr := p0_vaddr 5297052722fSJay toITLB.bits.debug.pc := p0_vaddr 5307052722fSJay 531f1fe8698SLemover toITLB.bits.kill := DontCare 5327052722fSJay toITLB.bits.cmd := TlbCmd.exec 533f1fe8698SLemover toITLB.bits.debug.robIdx := DontCare 5347052722fSJay toITLB.bits.debug.isFirstIssue := DontCare 535b1ded4e8Sguohongyu toITLB.bits.memidx := DontCare 536b1ded4e8Sguohongyu toITLB.bits.no_translate := false.B 5377052722fSJay 5387052722fSJay fromITLB.ready := true.B 5397052722fSJay 5409bba777eSssszwic fromFtq.req.ready := p0_req_cancel || fromITLB.bits.miss || p1_ready && toITLB.ready && toIMeta.ready 5417052722fSJay 542974a902cSguohongyu /** Prefetch Stage 1: check in cache & ICacheMainPipeMSHR */ 5437052722fSJay val p1_valid = generatePipeControl(lastFire = p0_fire, thisFire = p1_fire || p1_discard, thisFlush = false.B, lastFlush = false.B) 544005e809bSJiuyang Liu val p1_vaddr = RegEnable(p0_vaddr, p0_fire) 5457052722fSJay 5469bba777eSssszwic // 1. tlb resp process 54703efd994Shappy-lx val tlb_resp_paddr = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.paddr(0)) 5489bba777eSssszwic val tlb_resp_pf = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).pf.instr) 5499bba777eSssszwic val tlb_resp_af = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).af.instr) 5507052722fSJay val p1_exception = VecInit(Seq(tlb_resp_pf, tlb_resp_af)) 5517052722fSJay val p1_has_except = p1_exception.reduce(_ || _) 552b1ded4e8Sguohongyu val p1_paddr = tlb_resp_paddr 5537052722fSJay 5549bba777eSssszwic // 2. register IMeta 5559bba777eSssszwic val p1_meta_ptags_reg = RegEnable(VecInit(fromIMeta.map(way => way.tag)), RegNext(p0_fire)) 5569bba777eSssszwic val p1_meta_valids_reg = RegEnable(fromIMetaValid, RegNext(p0_fire)) 5577052722fSJay 5589bba777eSssszwic // 3. check ICacheMissEntry 559b1ded4e8Sguohongyu val p1_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p1_paddr, blockBytes, PAddrBits))).reduce(_||_) 560b1ded4e8Sguohongyu 5619bba777eSssszwic // shake 5629bba777eSssszwic val p1_req_cancel = p1_check_in_mshr || p1_has_except || io.fencei 5639bba777eSssszwic p1_ready := p1_valid && p2_ready || !p1_valid 5649bba777eSssszwic p1_fire := p1_valid && !p1_req_cancel && p2_ready && enableBit 5659bba777eSssszwic p1_discard := p1_valid && p1_req_cancel 5667052722fSJay 567974a902cSguohongyu /** Prefetch Stage 2: check PMP & send check req to ICacheMainPipeMSHR */ 5687052722fSJay val p2_valid = generatePipeControl(lastFire = p1_fire, thisFire = p2_fire || p2_discard, thisFlush = false.B, lastFlush = false.B) 5699bba777eSssszwic val p2_paddr = RegEnable(p1_paddr, p1_fire) 5709bba777eSssszwic val p2_vaddr = RegEnable(p1_vaddr, p1_fire) 5719bba777eSssszwic 5729bba777eSssszwic // 1. check imeta 5739bba777eSssszwic val p2_ptag = get_phy_tag(p2_paddr) 5749bba777eSssszwic val p2_tag_eq_vec = VecInit(p1_meta_ptags_reg.map(_ === p2_ptag )) 5759bba777eSssszwic val p2_tag_match_vec = VecInit(p2_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && p1_meta_valids_reg(w)}) 5769bba777eSssszwic val p2_tag_match = DataHoldBypass(ParallelOR(p2_tag_match_vec), RegNext(p1_fire)) 5779bba777eSssszwic 5789bba777eSssszwic // 2. check PMP 579b1ded4e8Sguohongyu val p2_pmp_fire = p2_valid 580b1ded4e8Sguohongyu val pmpExcpAF = fromPMP.instr 581b1ded4e8Sguohongyu val p2_except_pf = RegEnable(tlb_resp_pf, p1_fire) 582b1ded4e8Sguohongyu val p2_except_af = DataHoldBypass(pmpExcpAF, p2_pmp_fire) || RegEnable(tlb_resp_af, p1_fire) 583b1ded4e8Sguohongyu val p2_mmio = DataHoldBypass(io.pmp.resp.mmio && !p2_except_af && !p2_except_pf, p2_pmp_fire) 5849bba777eSssszwic val p2_exception = VecInit(Seq(pmpExcpAF, p2_mmio)).reduce(_||_) 5859bba777eSssszwic toPMP.valid := p2_pmp_fire 5869bba777eSssszwic toPMP.bits.addr := p2_paddr 5879bba777eSssszwic toPMP.bits.size := 3.U 5889bba777eSssszwic toPMP.bits.cmd := TlbCmd.exec 589b1ded4e8Sguohongyu 5909bba777eSssszwic // 3. check ICacheMissEntry 59100240ba6SJay val p2_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p2_paddr, blockBytes, PAddrBits))).reduce(_||_) 59200240ba6SJay 5939bba777eSssszwic // shake 5949bba777eSssszwic val p2_req_cancel = p2_exception || p2_check_in_mshr || p2_tag_match || io.fencei 5959bba777eSssszwic // p2_ready := p2_fire || p2_discard || !p2_valid 5969bba777eSssszwic p2_ready := p3_ready && p2_valid || !p2_valid 5979bba777eSssszwic p2_fire := p2_valid && !p2_req_cancel && p3_ready && enableBit 5989bba777eSssszwic p2_discard := p2_valid && p2_req_cancel 599b1ded4e8Sguohongyu 6009bba777eSssszwic /** Prefetch Stage 3: filtered req PIQ enqueue */ 601a108d429SJay val p3_valid = generatePipeControl(lastFire = p2_fire, thisFire = p3_fire || p3_discard, thisFlush = false.B, lastFlush = false.B) 602b1ded4e8Sguohongyu val p3_paddr = RegEnable(p2_paddr, p2_fire) 603b1ded4e8Sguohongyu val p3_vaddr = RegEnable(p2_vaddr, p2_fire) 6049bba777eSssszwic 6059bba777eSssszwic // 1. check ICacheMissEntry 6069bba777eSssszwic val p3_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p3_paddr, blockBytes, PAddrBits))).reduce(_||_) 6079bba777eSssszwic 6089bba777eSssszwic // 2. check prefetch buffer 609b1ded4e8Sguohongyu val p3_vidx = get_idx(p3_vaddr) 610b1ded4e8Sguohongyu toIPFBuffer.vSetIdx := p3_vidx 611b1ded4e8Sguohongyu toIPFBuffer.paddr := p3_paddr 6129bba777eSssszwic val p3_hit_buffer = fromIPFBuffer.ipf_hit 6137052722fSJay 6149bba777eSssszwic // 3. check dir 615a108d429SJay val p3_hit_dir = VecInit((0 until nPrefetchEntries).map(i => prefetch_dir(i).valid && prefetch_dir(i).paddr === p3_paddr )).reduce(_||_) 6169bba777eSssszwic 6179bba777eSssszwic // 4. check miss handling by main pipe 618974a902cSguohongyu val p3_hit_mp_miss = VecInit((0 until PortNumber).map(i => 619974a902cSguohongyu mainPipeMissSlotInfo(i).valid && (mainPipeMissSlotInfo(i).bits.ptage === get_phy_tag(p3_paddr) && 620974a902cSguohongyu (mainPipeMissSlotInfo(i).bits.vSetIdx === p3_vidx)))).reduce(_||_) 621a108d429SJay 6229bba777eSssszwic // 5. send prefetch req to missUnit 6239bba777eSssszwic val p3_req_cancel = p3_check_in_mshr || p3_hit_buffer || p3_hit_dir || p3_hit_mp_miss || io.fencei 624b1ded4e8Sguohongyu toMissUnit.enqReq.valid := p3_valid && !p3_req_cancel 6257052722fSJay toMissUnit.enqReq.bits.paddr := p3_paddr 626b1ded4e8Sguohongyu toMissUnit.enqReq.bits.vSetIdx := p3_vidx 6277052722fSJay 6289bba777eSssszwic // 6. shake 6299bba777eSssszwic // p3_ready := p3_fire || p3_discard || !p3_valid 6309bba777eSssszwic p3_ready := toMissUnit.enqReq.ready && p3_valid || !p3_valid 6319bba777eSssszwic p3_fire := toMissUnit.enqReq.fire() 6329bba777eSssszwic p3_discard := p3_valid && p3_req_cancel 6339bba777eSssszwic 634b1ded4e8Sguohongyu when(io.fencei){ 635b1ded4e8Sguohongyu maxPrefetchCounter := 0.U 636a108d429SJay prefetch_dir.foreach(_.valid := false.B) 637a108d429SJay }.elsewhen(toMissUnit.enqReq.fire()){ 638974a902cSguohongyu// when(reachMaxSize){ 639974a902cSguohongyu// prefetch_dir(io.freePIQEntry).paddr := p3_paddr 640974a902cSguohongyu// }.otherwise { 641974a902cSguohongyu// maxPrefetchCounter := maxPrefetchCounter + 1.U 642974a902cSguohongyu// 643974a902cSguohongyu// prefetch_dir(maxPrefetchCounter).valid := true.B 644974a902cSguohongyu// prefetch_dir(maxPrefetchCounter).paddr := p3_paddr 645974a902cSguohongyu// } 646974a902cSguohongyu // now prefetch_dir hold status for all PIQ 647b1ded4e8Sguohongyu prefetch_dir(io.freePIQEntry).paddr := p3_paddr 648974a902cSguohongyu prefetch_dir(io.freePIQEntry).valid := true.B 649a108d429SJay } 6507052722fSJay} 6517052722fSJay 652b1ded4e8Sguohongyuclass PIQEntry(edge: TLEdgeOut, id: Int)(implicit p: Parameters) extends IPrefetchModule 6537052722fSJay{ 6547052722fSJay val io = IO(new Bundle{ 655b1ded4e8Sguohongyu val id = Input(UInt((log2Ceil(nPrefetchEntries + PortNumber)).W)) 6567052722fSJay 6577052722fSJay val req = Flipped(DecoupledIO(new PIQReq)) 6587052722fSJay 659b1ded4e8Sguohongyu val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 660b1ded4e8Sguohongyu val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 6617052722fSJay 662b1ded4e8Sguohongyu //write back to Prefetch Buffer 663b1ded4e8Sguohongyu val piq_write_ipbuffer = DecoupledIO(new IPFBufferWrite) 664b1ded4e8Sguohongyu 665b1ded4e8Sguohongyu val fencei = Input(Bool()) 666b1ded4e8Sguohongyu 667b1ded4e8Sguohongyu val prefetch_entry_data = DecoupledIO(new PIQData) 668974a902cSguohongyu 669974a902cSguohongyu val ongoing_req = ValidIO(UInt(PAddrBits.W)) 6707052722fSJay }) 6717052722fSJay 672b1ded4e8Sguohongyu val s_idle :: s_memReadReq :: s_memReadResp :: s_write_back :: s_finish:: Nil = Enum(5) 6737052722fSJay val state = RegInit(s_idle) 6747052722fSJay 675b1ded4e8Sguohongyu //req register 676b1ded4e8Sguohongyu val req = Reg(new PIQReq) 677b1ded4e8Sguohongyu val req_idx = req.vSetIdx //virtual index 678b1ded4e8Sguohongyu val req_tag = get_phy_tag(req.paddr) //physical tag 679b1ded4e8Sguohongyu 680b1ded4e8Sguohongyu val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant) 681b1ded4e8Sguohongyu 682b1ded4e8Sguohongyu //8 for 64 bits bus and 2 for 256 bits 683b1ded4e8Sguohongyu val readBeatCnt = Reg(UInt(log2Up(refillCycles).W)) 684b1ded4e8Sguohongyu val respDataReg = Reg(Vec(refillCycles,UInt(beatBits.W))) 685b1ded4e8Sguohongyu 686b1ded4e8Sguohongyu //to main pipe s1 687b1ded4e8Sguohongyu io.prefetch_entry_data.valid := state =/= s_idle 688b1ded4e8Sguohongyu io.prefetch_entry_data.bits.vSetIdx := req_idx 689b1ded4e8Sguohongyu io.prefetch_entry_data.bits.ptage := req_tag 690b1ded4e8Sguohongyu io.prefetch_entry_data.bits.cacheline := respDataReg.asUInt 691b1ded4e8Sguohongyu io.prefetch_entry_data.bits.writeBack := state === s_write_back 692b1ded4e8Sguohongyu 693b1ded4e8Sguohongyu //initial 694b1ded4e8Sguohongyu io.mem_acquire.bits := DontCare 695b1ded4e8Sguohongyu io.mem_grant.ready := true.B 696b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits:= DontCare 697b1ded4e8Sguohongyu 698b1ded4e8Sguohongyu io.req.ready := state === s_idle 699b1ded4e8Sguohongyu io.mem_acquire.valid := state === s_memReadReq 700b1ded4e8Sguohongyu 7012a6078bfSguohongyu val needflush_r = RegInit(false.B) 7022a6078bfSguohongyu when (state === s_idle) { needflush_r := false.B } 7032a6078bfSguohongyu when (state =/= s_idle && io.fencei) { needflush_r := true.B } 7042a6078bfSguohongyu val needflush = needflush_r | io.fencei 7057052722fSJay 7067052722fSJay //state change 7077052722fSJay switch(state){ 7087052722fSJay is(s_idle){ 7097052722fSJay when(io.req.fire()){ 710b1ded4e8Sguohongyu readBeatCnt := 0.U 711b1ded4e8Sguohongyu state := s_memReadReq 7127052722fSJay req := io.req.bits 7137052722fSJay } 7147052722fSJay } 7157052722fSJay 7167052722fSJay // memory request 717b1ded4e8Sguohongyu is(s_memReadReq){ 718b1ded4e8Sguohongyu when(io.mem_acquire.fire()){ 719b1ded4e8Sguohongyu state := s_memReadResp 720b1ded4e8Sguohongyu } 721b1ded4e8Sguohongyu } 722b1ded4e8Sguohongyu 723b1ded4e8Sguohongyu is(s_memReadResp){ 724b1ded4e8Sguohongyu when (edge.hasData(io.mem_grant.bits)) { 725b1ded4e8Sguohongyu when (io.mem_grant.fire()) { 726b1ded4e8Sguohongyu readBeatCnt := readBeatCnt + 1.U 727b1ded4e8Sguohongyu respDataReg(readBeatCnt) := io.mem_grant.bits.data 728b1ded4e8Sguohongyu when (readBeatCnt === (refillCycles - 1).U) { 729b1ded4e8Sguohongyu assert(refill_done, "refill not done!") 730b1ded4e8Sguohongyu state := s_write_back 731b1ded4e8Sguohongyu } 732b1ded4e8Sguohongyu } 733b1ded4e8Sguohongyu } 734b1ded4e8Sguohongyu } 735b1ded4e8Sguohongyu 736b1ded4e8Sguohongyu is(s_write_back){ 7372a6078bfSguohongyu state := Mux(io.piq_write_ipbuffer.fire() || needflush, s_finish, s_write_back) 738b1ded4e8Sguohongyu } 739b1ded4e8Sguohongyu 740b1ded4e8Sguohongyu is(s_finish){ 7417052722fSJay state := s_idle 7427052722fSJay } 7437052722fSJay } 7447052722fSJay 745b1ded4e8Sguohongyu //refill write and meta write 746b1ded4e8Sguohongyu //WARNING: Maybe could not finish refill in 1 cycle 7472a6078bfSguohongyu io.piq_write_ipbuffer.valid := (state === s_write_back) && !needflush 748b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.tag := req_tag 749b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.index := req_idx 750b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.meta.paddr := req.paddr 751b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.data := respDataReg.asUInt 752b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits.buffIdx := io.id - PortNumber.U 7537052722fSJay 754974a902cSguohongyu io.ongoing_req.valid := state =/= s_idle 755974a902cSguohongyu io.ongoing_req.bits := addrAlign(req.paddr, blockBytes, PAddrBits) 756974a902cSguohongyu 7577052722fSJay XSPerfAccumulate("PrefetchEntryReq" + Integer.toString(id, 10), io.req.fire()) 7587052722fSJay 759b1ded4e8Sguohongyu //mem request 760b1ded4e8Sguohongyu io.mem_acquire.bits := edge.Get( 761b1ded4e8Sguohongyu fromSource = io.id, 762b1ded4e8Sguohongyu toAddress = Cat(req.paddr(PAddrBits - 1, log2Ceil(blockBytes)), 0.U(log2Ceil(blockBytes).W)), 763b1ded4e8Sguohongyu lgSize = (log2Up(cacheParams.blockBytes)).U)._2 764d2b20d1aSTang Haojin io.mem_acquire.bits.user.lift(PreferCacheKey).foreach(_ := true.B) 765d2b20d1aSTang Haojin io.mem_acquire.bits.user.lift(ReqSourceKey).foreach(_ := MemReqSource.L1InstPrefetch.id.U) 766b1ded4e8Sguohongyu 7677052722fSJay} 768