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