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