1/*************************************************************************************** 2 * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3 * Copyright (c) 2020-2021 Peng Cheng Laboratory 4 * 5 * XiangShan is licensed under Mulan PSL v2. 6 * You can use this software according to the terms and conditions of the Mulan PSL v2. 7 * You may obtain a copy of Mulan PSL v2 at: 8 * http://license.coscl.org.cn/MulanPSL2 9 * 10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13 * 14 * See the Mulan PSL v2 for more details. 15 ***************************************************************************************/ 16 17package xiangshan.frontend.icache 18 19import chipsalliance.rocketchip.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import difftest.DifftestRefillEvent 23import freechips.rocketchip.tilelink._ 24import utils._ 25import xiangshan.cache.mmu._ 26import xiangshan.frontend._ 27import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 28import huancun.PreferCacheKey 29import utility.ReqSourceKey 30import xiangshan.{MemReqSource, XSCoreParamsKey} 31import utility._ 32 33 34abstract class IPrefetchBundle(implicit p: Parameters) extends ICacheBundle 35abstract class IPrefetchModule(implicit p: Parameters) extends ICacheModule 36 37//TODO: remove this 38object DebugFlags { 39 val fdip = false 40} 41 42class PIQReq(implicit p: Parameters) extends IPrefetchBundle { 43 val paddr = UInt(PAddrBits.W) 44 val vSetIdx = UInt(idxBits.W) 45} 46 47class PIQData(implicit p: Parameters) extends IPrefetchBundle { 48 val ptage = UInt(tagBits.W) 49 val vSetIdx = UInt(idxBits.W) 50 val cacheline = UInt(blockBits.W) 51 val writeBack = Bool() 52} 53 54class PIQToMainPipe(implicit p: Parameters) extends IPrefetchBundle{ 55 val info = DecoupledIO(new PIQData) 56} 57/* need change name */ 58class MainPipeToPrefetchPipe(implicit p: Parameters) extends IPrefetchBundle { 59 val ptage = UInt(tagBits.W) 60 val vSetIdx = UInt(idxBits.W) 61} 62 63class MainPipeMissInfo(implicit p: Parameters) extends IPrefetchBundle { 64 val s1_already_check_ipf = Output(Bool()) 65 val s2_miss_info = Vec(PortNumber, ValidIO(new MainPipeToPrefetchPipe)) 66} 67 68class IPrefetchToMissUnit(implicit p: Parameters) extends IPrefetchBundle{ 69 val enqReq = DecoupledIO(new PIQReq) 70} 71 72class IPredfetchIO(implicit p: Parameters) extends IPrefetchBundle { 73 val fromFtq = Flipped(new FtqPrefechBundle) 74 val iTLBInter = new TlbRequestIO 75 val pmp = new ICachePMPBundle 76 val toIMeta = Decoupled(new ICacheMetaReadReqBundle) 77 val fromIMeta = Input(new ICacheMetaReadRespBundle) 78 val toMissUnit = new IPrefetchToMissUnit 79 val freePIQEntry = Input(UInt(log2Ceil(nPrefetchEntries).W)) 80 val fromMSHR = Flipped(Vec(totalMSHRNum,ValidIO(UInt(PAddrBits.W)))) 81 val IPFBufferRead = Flipped(new IPFBufferFilterRead) 82 /** icache main pipe to prefetch pipe*/ 83 val mainPipeMissSlotInfo = Flipped(Vec(PortNumber,ValidIO(new MainPipeToPrefetchPipe))) 84 85 val prefetchEnable = Input(Bool()) 86 val prefetchDisable = Input(Bool()) 87 val fencei = Input(Bool()) 88} 89 90/** Prefetch Buffer **/ 91 92class IPFWritePtrQueue(implicit p: Parameters) extends IPrefetchModule with HasCircularQueuePtrHelper 93{ 94 val io = IO(new Bundle{ 95 val free_ptr = DecoupledIO(UInt(log2Ceil(nIPFBufferSize).W)) 96 val release_ptr = Flipped(ValidIO(UInt(log2Ceil(nIPFBufferSize).W))) 97 val flush = Input(Bool()) 98 }) 99 /* define ptr */ 100 class IPFPtr(implicit p: Parameters) extends CircularQueuePtr[IPFPtr]( 101 p => p(XSCoreParamsKey).icacheParameters.nPrefBufferEntries 102 ){ 103 } 104 105 object IPFPtr { 106 def apply(f: Bool, v: UInt)(implicit p: Parameters): IPFPtr = { 107 val ptr = Wire(new IPFPtr) 108 ptr.flag := f 109 ptr.value := v 110 ptr 111 } 112 } 113 114 val queue = RegInit(VecInit((0 until nIPFBufferSize).map(i => i.U(log2Ceil(nIPFBufferSize).W)))) 115 val enq_ptr = RegInit(IPFPtr(true.B, 0.U)) 116 val deq_ptr = RegInit(IPFPtr(false.B, 0.U)) 117 118 io.free_ptr.valid := !isEmpty(enq_ptr, deq_ptr) 119 io.free_ptr.bits := queue(deq_ptr.value) 120 deq_ptr := deq_ptr + io.free_ptr.fire 121 122 when (io.release_ptr.valid) { 123 queue(enq_ptr.value) := io.release_ptr.bits 124 enq_ptr := enq_ptr + 1.U 125 } 126 127 when (io.flush) { 128 queue := RegInit(VecInit((0 until nIPFBufferSize).map(i => i.U(log2Ceil(nIPFBufferSize).W)))) 129 enq_ptr := RegInit(IPFPtr(true.B, 0.U)) 130 deq_ptr := RegInit(IPFPtr(false.B, 0.U)) 131 } 132 133 XSError(isBefore(enq_ptr, deq_ptr) && !isFull(enq_ptr, deq_ptr), "enq_ptr should not before deq_ptr\n") 134} 135 136 137class PrefetchBuffer(implicit p: Parameters) extends IPrefetchModule 138{ 139 val io = IO(new Bundle{ 140 val hartId = Input(UInt(8.W)) 141 val read = new IPFBufferRead 142 val filter_read = Vec(prefetchPipeNum, new IPFBufferFilterRead) 143 val write = Flipped(ValidIO(new IPFBufferWrite)) 144 /** to ICache replacer */ 145 val replace = new IPFBufferMove 146 /** move & move filter port */ 147 val mainpipe_missinfo = Flipped(new MainPipeMissInfo) 148 val meta_filter_read_req = Decoupled(new ICacheMetaReadReqBundle) 149 val meta_filter_read_resp = Input(new ICacheMetaReadRespBundle) 150 val move = new Bundle() { 151 val meta_write = DecoupledIO(new ICacheMetaWriteBundle) 152 val data_write = DecoupledIO(new ICacheDataWriteBundle) 153 } 154 val fencei = Input(Bool()) 155 }) 156 157 class IPFBufferEntryMeta(implicit p: Parameters) extends IPrefetchBundle 158 { 159 val tag = UInt(tagBits.W) 160 val index = UInt(idxBits.W) 161 val paddr = UInt(PAddrBits.W) 162 val valid = Bool() 163 val confidence = UInt(log2Ceil(maxIPFMoveConf + 1).W) 164 val move = Bool() 165 val has_been_hit = Bool() 166 } 167 168 class IPFBufferEntryData(implicit p: Parameters) extends IPrefetchBundle 169 { 170 val cachline = UInt(blockBits.W) 171 } 172 173 def InitQueue[T <: Data](entry: T, size: Int): Vec[T] ={ 174 return RegInit(VecInit(Seq.fill(size)(0.U.asTypeOf(entry.cloneType)))) 175 } 176 177 val meta_buffer = InitQueue(new IPFBufferEntryMeta, size = nIPFBufferSize) 178 val data_buffer = InitQueue(new IPFBufferEntryData, size = nIPFBufferSize) 179 180 val ipf_write_ptr_queue = Module(new IPFWritePtrQueue()) 181 ipf_write_ptr_queue.io.flush := io.fencei 182 183 val meta_buffer_empty_oh = WireInit(VecInit(Seq.fill(nIPFBufferSize)(false.B))) 184 (0 until nIPFBufferSize).foreach { i => 185 meta_buffer_empty_oh(i) := !meta_buffer(i).valid 186 } 187 XSPerfAccumulate("ipfbuffer_empty_entry_multi_cycle", PopCount(meta_buffer_empty_oh)) 188 189 /** filter read logic */ 190 val fr_vidx = (0 until prefetchPipeNum).map (i => io.filter_read(i).req.vSetIdx) 191 val fr_ptag = (0 until prefetchPipeNum).map (i => get_phy_tag(io.filter_read(i).req.paddr)) 192 193 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(_||_)) 194 val fr_hit_in_s1, fr_hit_in_s2, fr_hit_in_s3 = Wire(Vec(prefetchPipeNum, Bool())) 195 196 (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)) 197 198 /** read logic */ 199 (0 until PortNumber).foreach(i => io.read.req(i).ready := true.B) 200 val r_valid = VecInit((0 until PortNumber).map( i => io.read.req(i).valid)).reduce(_||_) 201 val r_vidx = VecInit((0 until PortNumber).map(i => get_idx(io.read.req(i).bits.vaddr))) 202 val r_ptag = VecInit((0 until PortNumber).map(i => get_phy_tag(io.read.req(i).bits.paddr))) 203 val r_hit_oh = VecInit((0 until PortNumber).map(i => 204 VecInit(meta_buffer.map(entry => 205 io.read.req(i).valid && // need this condition 206 entry.valid && 207 entry.tag === r_ptag(i) && 208 entry.index === r_vidx(i) 209 )))) 210 val r_buffer_hit = VecInit(r_hit_oh.map(_.reduce(_||_))) 211 val r_buffer_hit_idx = VecInit(r_hit_oh.map(PriorityEncoder(_))) 212 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 213 214 /** "read" also check data in move pipeline */ 215 val r_moves1pipe_hit_s1, r_moves1pipe_hit_s2, r_moves1pipe_hit_s3 = WireInit(VecInit(Seq.fill(PortNumber)(false.B))) 216 val s1_move_data_cacheline, s2_move_data_cacheline, s3_move_data_cacheline = Wire(UInt(blockBits.W)) 217 218 (0 until PortNumber).foreach{ i => 219 io.read.resp(i).valid := io.read.req(i).valid 220 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) 221 io.read.resp(i).bits.cacheline := Mux(r_buffer_hit(i), r_buffer_hit_data(i), 222 Mux(r_moves1pipe_hit_s1(i), s1_move_data_cacheline, 223 Mux(r_moves1pipe_hit_s2(i), s2_move_data_cacheline, s3_move_data_cacheline))) 224 } 225 226 (0 until PortNumber).foreach { i => 227 when(io.read.req(i).valid && r_hit_oh(i).reduce(_ || _)) { 228 meta_buffer(r_buffer_hit_idx(i)).has_been_hit := true.B 229 } 230 XSPerfAccumulate("ipf_entry_first_hit_by_port_" + i, io.read.req(i).valid && r_hit_oh(i).reduce(_ || _) && 231 meta_buffer(r_buffer_hit_idx(i)).has_been_hit === false.B) 232 } 233 234 235 /** move logic */ 236 val r_buffer_hit_s2 = RegNext(r_buffer_hit, init=0.U.asTypeOf(r_buffer_hit.cloneType)) 237 val r_buffer_hit_idx_s2 = RegNext(r_buffer_hit_idx) 238 val r_rvalid_s2 = RegNext(r_valid, init=false.B) 239 240 val s2_move_valid_0 = r_rvalid_s2 && r_buffer_hit_s2(0) 241 val s2_move_valid_1 = r_rvalid_s2 && r_buffer_hit_s2(1) 242 243 XSPerfAccumulate("prefetch_hit_bank_0", r_rvalid_s2 && r_buffer_hit_s2(0)) 244 XSPerfAccumulate("prefetch_hit_bank_1", r_rvalid_s2 && r_buffer_hit_s2(1)) 245 246 val move_queue = RegInit(VecInit(Seq.fill(nIPFBufferSize)(0.U.asTypeOf(r_buffer_hit_idx_s2(0))))) 247 248 val curr_move_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 249 val curr_hit_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W)) 250 251 val s2_move_conf_full_0 = meta_buffer(r_buffer_hit_idx_s2(0)).confidence === (maxIPFMoveConf).U 252 val s2_move_conf_full_1 = meta_buffer(r_buffer_hit_idx_s2(1)).confidence === (maxIPFMoveConf).U 253 254 val move_repeat_0 = meta_buffer(r_buffer_hit_idx_s2(0)).move 255 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)) 256 257 val s2_move_0 = s2_move_valid_0 && !move_repeat_0 258 val s2_move_1 = s2_move_valid_1 && !move_repeat_1 259 260 val s2_move_enqueue_0 = s2_move_0 && s2_move_conf_full_0 261 val s2_move_enqueue_1 = s2_move_1 && s2_move_conf_full_1 262 263 when(s2_move_0) { 264 when(s2_move_conf_full_0) { 265 meta_buffer(r_buffer_hit_idx_s2(0)).move := true.B 266 }.otherwise { 267 meta_buffer(r_buffer_hit_idx_s2(0)).confidence := meta_buffer(r_buffer_hit_idx_s2(0)).confidence + 1.U 268 } 269 } 270 when(s2_move_1) { 271 when(s2_move_conf_full_1) { 272 meta_buffer(r_buffer_hit_idx_s2(1)).move := true.B 273 }.otherwise { 274 meta_buffer(r_buffer_hit_idx_s2(1)).confidence := meta_buffer(r_buffer_hit_idx_s2(1)).confidence + 1.U 275 } 276 } 277 278 when(s2_move_enqueue_0 && !s2_move_enqueue_1) { 279 move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0) 280 281 when((curr_hit_ptr + 1.U) =/= curr_move_ptr){ 282 curr_hit_ptr := curr_hit_ptr + 1.U 283 } 284 }.elsewhen(!s2_move_enqueue_0 && s2_move_enqueue_1) { 285 move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(1) 286 287 when((curr_hit_ptr + 1.U) =/= curr_move_ptr){ 288 curr_hit_ptr := curr_hit_ptr + 1.U 289 } 290 }.elsewhen(s2_move_enqueue_0 && s2_move_enqueue_1) { 291 move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0) 292 move_queue(curr_hit_ptr + 1.U) := r_buffer_hit_idx_s2(1) 293 when((curr_hit_ptr + 2.U) =/= curr_move_ptr){ 294 curr_hit_ptr := curr_hit_ptr + 2.U 295 }.otherwise{ 296 curr_hit_ptr := curr_hit_ptr + 1.U 297 } 298 } 299 300 val move_queue_empty = curr_move_ptr === curr_hit_ptr 301 /** pipeline control signal */ 302 val s1_ready, s2_ready, s3_ready = Wire(Bool()) 303 val s0_fire, s1_fire, s2_fire, s3_fire = Wire(Bool()) 304 305 /** stage 0 */ 306 val s0_valid = !move_queue_empty && meta_buffer(move_queue(curr_move_ptr)).move 307 308 val s0_move_idx = move_queue(curr_move_ptr) 309 val s0_move_meta = meta_buffer(s0_move_idx) 310 val s0_move_data = data_buffer(s0_move_idx) 311 io.replace.vsetIdx := meta_buffer(s0_move_idx).index 312 val s0_waymask = io.replace.waymask 313 314 s0_fire := s0_valid && s1_ready 315 316 /** curr_move_ptr control logic */ 317 val s0_move_jump = !move_queue_empty && !meta_buffer(move_queue(curr_move_ptr)).move 318 when (s0_fire) { 319 curr_move_ptr := curr_move_ptr + 1.U 320 meta_buffer(s0_move_idx).valid := false.B // TODO : maybe should not invalid 321 meta_buffer(s0_move_idx).move := false.B 322 meta_buffer(s0_move_idx).confidence := 0.U 323 }.elsewhen(s0_move_jump) { 324 curr_move_ptr := curr_move_ptr + 1.U 325 } 326 327 /** stage 1 : send req to metaArray */ 328 val s1_valid = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = io.fencei, lastFlush = false.B) 329 330 val s1_move_idx = RegEnable(s0_move_idx, s0_fire) 331 val s1_move_meta = RegEnable(s0_move_meta, s0_fire) 332 val s1_move_data = RegEnable(s0_move_data, s0_fire) 333 val s1_waymask = RegEnable(s0_waymask, s0_fire) 334 335 io.meta_filter_read_req.valid := s1_valid 336 io.meta_filter_read_req.bits.idx := s1_move_meta.index 337 338 s1_ready := !s1_valid || s1_fire 339 s1_fire := s1_valid && io.meta_filter_read_req.ready && s2_ready 340 341 (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)) 342 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)) 343 s1_move_data_cacheline := s1_move_data.cachline 344 345 /** stage 2 : collect message from metaArray and mainPipe to filter */ 346 val s2_valid = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = io.fencei, lastFlush = false.B) 347 348 val s2_move_idx = RegEnable(s1_move_idx, s1_fire) 349 val s2_move_meta = RegEnable(s1_move_meta, s1_fire) 350 val s2_move_data = RegEnable(s1_move_data, s1_fire) 351 val s2_waymask = RegEnable(s1_waymask, s1_fire) 352 353 val s2_meta_ptags = ResultHoldBypass(data = io.meta_filter_read_resp.tags, valid = RegNext(s1_fire)) 354 val s2_meta_valids = ResultHoldBypass(data = io.meta_filter_read_resp.entryValid, valid = RegNext(s1_fire)) 355 356 val s2_tag_eq_vec = VecInit((0 until nWays).map(w => s2_meta_ptags(w) === s2_move_meta.tag)) // just use port 0 357 val s2_tag_match_vec = VecInit(s2_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s2_meta_valids(w)}) 358 val s2_hit_in_meta_array = ParallelOR(s2_tag_match_vec) 359 360 val main_s2_missinfo = io.mainpipe_missinfo.s2_miss_info 361 val s2_hit_main_s2_missreq = VecInit((0 until PortNumber).map(i => 362 main_s2_missinfo(i).valid && s2_move_meta.index === main_s2_missinfo(i).bits.vSetIdx 363 && s2_move_meta.tag === main_s2_missinfo(i).bits.ptage)).reduce(_||_) 364 365 val s2_discard = s2_hit_in_meta_array || s2_hit_main_s2_missreq // || s2_hit_main_s1_missreq 366 val s2_discard_latch = holdReleaseLatch(valid = s2_discard, release = s2_fire, flush = io.fencei) 367 if(DebugFlags.fdip){ 368 when (s2_fire && s2_discard_latch) { 369 printf("<%d> IPrefetchBuffer: s2_discard : hit_in_meta_array=%d,hit_in_main_s2=%d, ptag=0x%x\n", 370 GTimer(), s2_hit_in_meta_array, s2_hit_main_s2_missreq, s2_move_meta.tag) 371 } 372 } 373 374 s2_ready := !s2_valid || s2_fire 375 s2_fire := s2_valid && s3_ready && io.mainpipe_missinfo.s1_already_check_ipf 376 377 (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)) 378 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)) 379 s2_move_data_cacheline := s2_move_data.cachline 380 381 /** stage 3 : move data to metaArray and dataArray */ 382 val s3_valid = generatePipeControl(lastFire = s2_fire, thisFire = s3_fire, thisFlush = io.fencei, lastFlush = false.B) 383 384 val s3_move_idx = RegEnable(s2_move_idx, s2_fire) 385 val s3_move_meta = RegEnable(s2_move_meta, s2_fire) 386 val s3_move_data = RegEnable(s2_move_data, s2_fire) 387 val s3_waymask = RegEnable(s2_waymask, s2_fire) 388 val s3_discard = RegEnable(s2_discard_latch, s2_fire) 389 390 io.move.meta_write.valid := s3_valid && !s3_discard && !io.fencei 391 io.move.data_write.valid := s3_valid && !s3_discard && !io.fencei 392 io.move.meta_write.bits.generate( 393 tag = s3_move_meta.tag, 394 idx = s3_move_meta.index, 395 waymask = s3_waymask, 396 bankIdx = s3_move_meta.index(0)) 397 io.move.data_write.bits.generate( 398 data = s3_move_data.cachline, 399 idx = s3_move_meta.index, 400 waymask = s3_waymask, 401 bankIdx = s3_move_meta.index(0), 402 paddr = s3_move_meta.paddr) 403 404 s3_ready := !s3_valid || s3_fire 405 s3_fire := io.move.meta_write.fire && io.move.data_write.fire || s3_discard || io.fencei 406 assert((io.move.meta_write.fire && io.move.data_write.fire) || (!io.move.meta_write.fire && !io.move.data_write.fire), 407 "meta and data array need fire at same time") 408 409 (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)) 410 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)) 411 s3_move_data_cacheline := s3_move_data.cachline 412 413 if (DebugFlags.fdip) { 414 when(io.move.meta_write.fire) { 415 printf("<%d> IPrefetchBuffer: move data to meta sram:ptag=0x%x,vidx=0x%x,waymask=0x%x\n", 416 GTimer(), s3_move_meta.tag,s3_move_meta.index,s3_waymask ) 417 } 418 } 419 420 if (env.EnableDifftest) { 421 val difftest = Module(new DifftestRefillEvent) 422 difftest.io.clock := clock 423 difftest.io.coreid := io.hartId 424 difftest.io.cacheid := 6.U 425 difftest.io.valid := io.move.meta_write.fire 426 difftest.io.addr := s3_move_meta.paddr 427 difftest.io.data := s3_move_data.cachline.asTypeOf(difftest.io.data) 428 } 429 430 /** write logic */ 431 val replacer = ReplacementPolicy.fromString(Some("random"), nIPFBufferSize) 432 val curr_write_ptr = Wire(UInt(log2Ceil(nIPFBufferSize).W)) 433 when (ipf_write_ptr_queue.io.free_ptr.valid) { 434 curr_write_ptr := ipf_write_ptr_queue.io.free_ptr.bits 435 }.otherwise { 436 curr_write_ptr := replacer.way 437 when (io.write.valid) { 438 replacer.miss 439 } 440 } 441 442 ipf_write_ptr_queue.io.release_ptr.valid := s0_fire 443 ipf_write_ptr_queue.io.release_ptr.bits := s0_move_idx 444 445 ipf_write_ptr_queue.io.free_ptr.ready := io.write.valid 446 when(io.write.valid) { 447 meta_buffer(curr_write_ptr).tag := io.write.bits.meta.tag 448 meta_buffer(curr_write_ptr).index := io.write.bits.meta.index 449 meta_buffer(curr_write_ptr).paddr := io.write.bits.meta.paddr 450 meta_buffer(curr_write_ptr).valid := true.B 451 meta_buffer(curr_write_ptr).move := false.B 452 meta_buffer(curr_write_ptr).confidence := 0.U 453 meta_buffer(curr_write_ptr).has_been_hit := false.B 454 455 data_buffer(curr_write_ptr).cachline := io.write.bits.data 456 457 } 458 459 /** fencei: invalid all entries */ 460 when(io.fencei) { 461 meta_buffer.foreach { b => 462 b.valid := false.B 463 b.move := false.B 464 b.confidence := 0.U 465 b.has_been_hit := false.B 466 } 467 (0 until PortNumber).foreach(i => r_buffer_hit_s2(i) := 0.U ) 468 r_rvalid_s2 := 0.U 469 curr_move_ptr := 0.U 470 curr_hit_ptr := 0.U 471 } 472 473} 474 475class IPrefetchPipe(implicit p: Parameters) extends IPrefetchModule 476{ 477 val io = IO(new IPredfetchIO) 478 479 val enableBit = RegInit(false.B) 480 val maxPrefetchCounter = RegInit(0.U(log2Ceil(nPrefetchEntries + 1).W)) 481 482 val reachMaxSize = maxPrefetchCounter === nPrefetchEntries.U 483 484 // when(io.prefetchEnable){ 485 // enableBit := true.B 486 // }.elsewhen((enableBit && io.prefetchDisable) || (enableBit && reachMaxSize)){ 487 // enableBit := false.B 488 // } 489 // ignore prefetchEnable from ICacheMainPipe 490 enableBit := true.B 491 492 class PrefetchDir(implicit p: Parameters) extends IPrefetchBundle 493 { 494 val valid = Bool() 495 val paddr = UInt(PAddrBits.W) 496 } 497 498 val prefetch_dir = RegInit(VecInit(Seq.fill(nPrefetchEntries)(0.U.asTypeOf(new PrefetchDir)))) 499 500 val fromFtq = io.fromFtq 501 val mainPipeMissSlotInfo = io.mainPipeMissSlotInfo 502 val (toITLB, fromITLB) = (io.iTLBInter.req, io.iTLBInter.resp) 503 io.iTLBInter.req_kill := false.B 504 val (toIMeta, fromIMeta, fromIMetaValid) = (io.toIMeta, io.fromIMeta.metaData, io.fromIMeta.entryValid) 505 val (toIPFBuffer, fromIPFBuffer) = (io.IPFBufferRead.req, io.IPFBufferRead.resp) 506 val (toPMP, fromPMP) = (io.pmp.req, io.pmp.resp) 507 val toMissUnit = io.toMissUnit 508 509 val p0_fire, p1_fire, p2_fire, p3_fire = WireInit(false.B) 510 val p0_discard, p1_discard, p2_discard, p3_discard = WireInit(false.B) 511 val p1_ready, p2_ready, p3_ready = WireInit(false.B) 512 513 /** Prefetch Stage 0: req from Ftq */ 514 val p0_valid = fromFtq.req.valid 515 val p0_vaddr = addrAlign(fromFtq.req.bits.target, blockBytes, VAddrBits) 516 val p0_vaddr_reg = RegEnable(p0_vaddr, fromFtq.req.fire()) 517 518 /* Cancel request when prefetch not enable 519 * or the request from FTQ is same as last time */ 520 val p0_req_cancel = !enableBit || (p0_vaddr === p0_vaddr_reg) || io.fencei 521 p0_fire := p0_valid && p1_ready && toITLB.fire() && !fromITLB.bits.miss && toIMeta.ready && enableBit && !p0_req_cancel 522 // p0_discard := p0_valid && p0_req_cancel 523 524 toIMeta.valid := p0_valid && !p0_req_cancel 525 toIMeta.bits.idx := get_idx(p0_vaddr) 526 527 toITLB.valid := p0_valid && !p0_req_cancel 528 toITLB.bits.size := 3.U // TODO: fix the size 529 toITLB.bits.vaddr := p0_vaddr 530 toITLB.bits.debug.pc := p0_vaddr 531 532 toITLB.bits.kill := DontCare 533 toITLB.bits.cmd := TlbCmd.exec 534 toITLB.bits.debug.robIdx := DontCare 535 toITLB.bits.debug.isFirstIssue := DontCare 536 toITLB.bits.memidx := DontCare 537 toITLB.bits.no_translate := false.B 538 539 fromITLB.ready := true.B 540 541 fromFtq.req.ready := p0_req_cancel || fromITLB.bits.miss || p1_ready && toITLB.ready && toIMeta.ready 542 543 /** Prefetch Stage 1: check in cache & ICacheMainPipeMSHR */ 544 val p1_valid = generatePipeControl(lastFire = p0_fire, thisFire = p1_fire || p1_discard, thisFlush = false.B, lastFlush = false.B) 545 val p1_vaddr = RegEnable(p0_vaddr, p0_fire) 546 547 // 1. tlb resp process 548 val tlb_resp_paddr = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.paddr(0)) 549 val tlb_resp_pf = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).pf.instr) 550 val tlb_resp_af = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).af.instr) 551 val p1_exception = VecInit(Seq(tlb_resp_pf, tlb_resp_af)) 552 val p1_has_except = p1_exception.reduce(_ || _) 553 val p1_paddr = tlb_resp_paddr 554 555 // 2. register IMeta 556 val p1_meta_ptags_reg = RegEnable(VecInit(fromIMeta.map(way => way.tag)), RegNext(p0_fire)) 557 val p1_meta_valids_reg = RegEnable(fromIMetaValid, RegNext(p0_fire)) 558 559 // 3. check ICacheMissEntry 560 val p1_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p1_paddr, blockBytes, PAddrBits))).reduce(_||_) 561 562 // shake 563 val p1_req_cancel = p1_check_in_mshr || p1_has_except || io.fencei 564 p1_ready := p1_valid && p2_ready || !p1_valid 565 p1_fire := p1_valid && !p1_req_cancel && p2_ready && enableBit 566 p1_discard := p1_valid && p1_req_cancel 567 568 /** Prefetch Stage 2: check PMP & send check req to ICacheMainPipeMSHR */ 569 val p2_valid = generatePipeControl(lastFire = p1_fire, thisFire = p2_fire || p2_discard, thisFlush = false.B, lastFlush = false.B) 570 val p2_paddr = RegEnable(p1_paddr, p1_fire) 571 val p2_vaddr = RegEnable(p1_vaddr, p1_fire) 572 573 // 1. check imeta 574 val p2_ptag = get_phy_tag(p2_paddr) 575 val p2_tag_eq_vec = VecInit(p1_meta_ptags_reg.map(_ === p2_ptag )) 576 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)}) 577 val p2_tag_match = DataHoldBypass(ParallelOR(p2_tag_match_vec), RegNext(p1_fire)) 578 579 // 2. check PMP 580 val p2_pmp_fire = p2_valid 581 val pmpExcpAF = fromPMP.instr 582 val p2_except_pf = RegEnable(tlb_resp_pf, p1_fire) 583 val p2_except_af = DataHoldBypass(pmpExcpAF, p2_pmp_fire) || RegEnable(tlb_resp_af, p1_fire) 584 val p2_mmio = DataHoldBypass(io.pmp.resp.mmio && !p2_except_af && !p2_except_pf, p2_pmp_fire) 585 val p2_exception = VecInit(Seq(pmpExcpAF, p2_mmio)).reduce(_||_) 586 toPMP.valid := p2_pmp_fire 587 toPMP.bits.addr := p2_paddr 588 toPMP.bits.size := 3.U 589 toPMP.bits.cmd := TlbCmd.exec 590 591 // 3. check ICacheMissEntry 592 val p2_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p2_paddr, blockBytes, PAddrBits))).reduce(_||_) 593 594 // shake 595 val p2_req_cancel = p2_exception || p2_check_in_mshr || p2_tag_match || io.fencei 596 // p2_ready := p2_fire || p2_discard || !p2_valid 597 p2_ready := p3_ready && p2_valid || !p2_valid 598 p2_fire := p2_valid && !p2_req_cancel && p3_ready && enableBit 599 p2_discard := p2_valid && p2_req_cancel 600 601 /** Prefetch Stage 3: filtered req PIQ enqueue */ 602 val p3_valid = generatePipeControl(lastFire = p2_fire, thisFire = p3_fire || p3_discard, thisFlush = false.B, lastFlush = false.B) 603 val p3_paddr = RegEnable(p2_paddr, p2_fire) 604 val p3_vaddr = RegEnable(p2_vaddr, p2_fire) 605 606 // 1. check ICacheMissEntry 607 val p3_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p3_paddr, blockBytes, PAddrBits))).reduce(_||_) 608 609 // 2. check prefetch buffer 610 val p3_vidx = get_idx(p3_vaddr) 611 toIPFBuffer.vSetIdx := p3_vidx 612 toIPFBuffer.paddr := p3_paddr 613 val p3_hit_buffer = fromIPFBuffer.ipf_hit 614 615 // 3. check dir 616 val p3_hit_dir = VecInit((0 until nPrefetchEntries).map(i => prefetch_dir(i).valid && prefetch_dir(i).paddr === p3_paddr )).reduce(_||_) 617 618 // 4. check miss handling by main pipe 619 val p3_hit_mp_miss = VecInit((0 until PortNumber).map(i => 620 mainPipeMissSlotInfo(i).valid && (mainPipeMissSlotInfo(i).bits.ptage === get_phy_tag(p3_paddr) && 621 (mainPipeMissSlotInfo(i).bits.vSetIdx === p3_vidx)))).reduce(_||_) 622 623 // 5. send prefetch req to missUnit 624 val p3_req_cancel = p3_check_in_mshr || p3_hit_buffer || p3_hit_dir || p3_hit_mp_miss || io.fencei 625 toMissUnit.enqReq.valid := p3_valid && !p3_req_cancel 626 toMissUnit.enqReq.bits.paddr := p3_paddr 627 toMissUnit.enqReq.bits.vSetIdx := p3_vidx 628 629 // 6. shake 630 // p3_ready := p3_fire || p3_discard || !p3_valid 631 p3_ready := toMissUnit.enqReq.ready && p3_valid || !p3_valid 632 p3_fire := toMissUnit.enqReq.fire() 633 p3_discard := p3_valid && p3_req_cancel 634 635 when(io.fencei){ 636 maxPrefetchCounter := 0.U 637 prefetch_dir.foreach(_.valid := false.B) 638 }.elsewhen(toMissUnit.enqReq.fire()){ 639// when(reachMaxSize){ 640// prefetch_dir(io.freePIQEntry).paddr := p3_paddr 641// }.otherwise { 642// maxPrefetchCounter := maxPrefetchCounter + 1.U 643// 644// prefetch_dir(maxPrefetchCounter).valid := true.B 645// prefetch_dir(maxPrefetchCounter).paddr := p3_paddr 646// } 647 // now prefetch_dir hold status for all PIQ 648 prefetch_dir(io.freePIQEntry).paddr := p3_paddr 649 prefetch_dir(io.freePIQEntry).valid := true.B 650 } 651} 652 653class PIQEntry(edge: TLEdgeOut, id: Int)(implicit p: Parameters) extends IPrefetchModule 654{ 655 val io = IO(new Bundle{ 656 val id = Input(UInt((log2Ceil(nPrefetchEntries + PortNumber)).W)) 657 658 val req = Flipped(DecoupledIO(new PIQReq)) 659 660 val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 661 val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 662 663 //write back to Prefetch Buffer 664 val piq_write_ipbuffer = DecoupledIO(new IPFBufferWrite) 665 666 val fencei = Input(Bool()) 667 668 val prefetch_entry_data = DecoupledIO(new PIQData) 669 670 val ongoing_req = ValidIO(UInt(PAddrBits.W)) 671 }) 672 673 val s_idle :: s_memReadReq :: s_memReadResp :: s_write_back :: s_finish:: Nil = Enum(5) 674 val state = RegInit(s_idle) 675 676 //req register 677 val req = Reg(new PIQReq) 678 val req_idx = req.vSetIdx //virtual index 679 val req_tag = get_phy_tag(req.paddr) //physical tag 680 681 val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant) 682 683 //8 for 64 bits bus and 2 for 256 bits 684 val readBeatCnt = Reg(UInt(log2Up(refillCycles).W)) 685 val respDataReg = Reg(Vec(refillCycles,UInt(beatBits.W))) 686 687 //to main pipe s1 688 io.prefetch_entry_data.valid := state =/= s_idle 689 io.prefetch_entry_data.bits.vSetIdx := req_idx 690 io.prefetch_entry_data.bits.ptage := req_tag 691 io.prefetch_entry_data.bits.cacheline := respDataReg.asUInt 692 io.prefetch_entry_data.bits.writeBack := state === s_write_back 693 694 //initial 695 io.mem_acquire.bits := DontCare 696 io.mem_grant.ready := true.B 697 io.piq_write_ipbuffer.bits:= DontCare 698 699 io.req.ready := state === s_idle 700 io.mem_acquire.valid := state === s_memReadReq 701 702 val needflush_r = RegInit(false.B) 703 when (state === s_idle) { needflush_r := false.B } 704 when (state =/= s_idle && io.fencei) { needflush_r := true.B } 705 val needflush = needflush_r | io.fencei 706 707 //state change 708 switch(state){ 709 is(s_idle){ 710 when(io.req.fire()){ 711 readBeatCnt := 0.U 712 state := s_memReadReq 713 req := io.req.bits 714 } 715 } 716 717 // memory request 718 is(s_memReadReq){ 719 when(io.mem_acquire.fire()){ 720 state := s_memReadResp 721 } 722 } 723 724 is(s_memReadResp){ 725 when (edge.hasData(io.mem_grant.bits)) { 726 when (io.mem_grant.fire()) { 727 readBeatCnt := readBeatCnt + 1.U 728 respDataReg(readBeatCnt) := io.mem_grant.bits.data 729 when (readBeatCnt === (refillCycles - 1).U) { 730 assert(refill_done, "refill not done!") 731 state := s_write_back 732 } 733 } 734 } 735 } 736 737 is(s_write_back){ 738 state := Mux(io.piq_write_ipbuffer.fire() || needflush, s_finish, s_write_back) 739 } 740 741 is(s_finish){ 742 state := s_idle 743 } 744 } 745 746 //refill write and meta write 747 //WARNING: Maybe could not finish refill in 1 cycle 748 io.piq_write_ipbuffer.valid := (state === s_write_back) && !needflush 749 io.piq_write_ipbuffer.bits.meta.tag := req_tag 750 io.piq_write_ipbuffer.bits.meta.index := req_idx 751 io.piq_write_ipbuffer.bits.meta.paddr := req.paddr 752 io.piq_write_ipbuffer.bits.data := respDataReg.asUInt 753 io.piq_write_ipbuffer.bits.buffIdx := io.id - PortNumber.U 754 755 io.ongoing_req.valid := state =/= s_idle 756 io.ongoing_req.bits := addrAlign(req.paddr, blockBytes, PAddrBits) 757 758 XSPerfAccumulate("PrefetchEntryReq" + Integer.toString(id, 10), io.req.fire()) 759 760 //mem request 761 io.mem_acquire.bits := edge.Get( 762 fromSource = io.id, 763 toAddress = Cat(req.paddr(PAddrBits - 1, log2Ceil(blockBytes)), 0.U(log2Ceil(blockBytes).W)), 764 lgSize = (log2Up(cacheParams.blockBytes)).U)._2 765 io.mem_acquire.bits.user.lift(PreferCacheKey).foreach(_ := true.B) 766 io.mem_acquire.bits.user.lift(ReqSourceKey).foreach(_ := MemReqSource.L1InstPrefetch.id.U) 767 768} 769