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