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