xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala (revision 92b88f30156d46e844042eea94f7121557fd09a1)
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