xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala (revision d2b20d1a96e238e36a849bd253f65ec7b6a5db38)
17052722fSJay/***************************************************************************************
27052722fSJay  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
37052722fSJay  * Copyright (c) 2020-2021 Peng Cheng Laboratory
47052722fSJay  *
57052722fSJay  * XiangShan is licensed under Mulan PSL v2.
67052722fSJay  * You can use this software according to the terms and conditions of the Mulan PSL v2.
77052722fSJay  * You may obtain a copy of Mulan PSL v2 at:
87052722fSJay  *          http://license.coscl.org.cn/MulanPSL2
97052722fSJay  *
107052722fSJay  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
117052722fSJay  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
127052722fSJay  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
137052722fSJay  *
147052722fSJay  * See the Mulan PSL v2 for more details.
157052722fSJay  ***************************************************************************************/
167052722fSJay
177052722fSJaypackage xiangshan.frontend.icache
187052722fSJay
197052722fSJayimport chipsalliance.rocketchip.config.Parameters
207052722fSJayimport chisel3._
217052722fSJayimport chisel3.util._
22afa866b1Sguohongyuimport difftest.DifftestRefillEvent
237052722fSJayimport freechips.rocketchip.tilelink._
247052722fSJayimport utils._
257052722fSJayimport xiangshan.cache.mmu._
267052722fSJayimport xiangshan.frontend._
27*d2b20d1aSTang Haojinimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle}
28*d2b20d1aSTang Haojinimport huancun.PreferCacheKey
29*d2b20d1aSTang Haojinimport utility.ReqSourceKey
30*d2b20d1aSTang Haojinimport xiangshan.{MemReqSource, XSCoreParamsKey}
31b1ded4e8Sguohongyuimport utility._
327052722fSJay
337052722fSJay
347052722fSJayabstract class IPrefetchBundle(implicit p: Parameters) extends ICacheBundle
357052722fSJayabstract class IPrefetchModule(implicit p: Parameters) extends ICacheModule
367052722fSJay
37b1ded4e8Sguohongyu//TODO: remove this
38b1ded4e8Sguohongyuobject DebugFlags {
39b1ded4e8Sguohongyu  val fdip = false
407052722fSJay}
417052722fSJay
42b1ded4e8Sguohongyuclass PIQReq(implicit p: Parameters) extends IPrefetchBundle {
43b1ded4e8Sguohongyu  val paddr      = UInt(PAddrBits.W)
44b1ded4e8Sguohongyu  val vSetIdx   = UInt(idxBits.W)
45b1ded4e8Sguohongyu}
46b1ded4e8Sguohongyu
47b1ded4e8Sguohongyuclass PIQData(implicit p: Parameters) extends IPrefetchBundle {
48b1ded4e8Sguohongyu  val ptage = UInt(tagBits.W)
49b1ded4e8Sguohongyu  val vSetIdx = UInt(idxBits.W)
50b1ded4e8Sguohongyu  val cacheline = UInt(blockBits.W)
51b1ded4e8Sguohongyu  val writeBack = Bool()
52b1ded4e8Sguohongyu}
53b1ded4e8Sguohongyu
54b1ded4e8Sguohongyuclass PIQToMainPipe(implicit  p: Parameters) extends IPrefetchBundle{
55b1ded4e8Sguohongyu  val info = DecoupledIO(new PIQData)
56b1ded4e8Sguohongyu}
57b1ded4e8Sguohongyu/* need change name */
58b1ded4e8Sguohongyuclass MainPipeToPrefetchPipe(implicit p: Parameters) extends IPrefetchBundle {
59b1ded4e8Sguohongyu  val ptage = UInt(tagBits.W)
60b1ded4e8Sguohongyu  val vSetIdx = UInt(idxBits.W)
61b1ded4e8Sguohongyu}
62b1ded4e8Sguohongyu
63b1ded4e8Sguohongyuclass MainPipeMissInfo(implicit p: Parameters) extends IPrefetchBundle {
64b1ded4e8Sguohongyu  val s1_already_check_ipf = Output(Bool())
65b1ded4e8Sguohongyu  val s2_miss_info = Vec(PortNumber, ValidIO(new MainPipeToPrefetchPipe))
66b1ded4e8Sguohongyu}
677052722fSJay
687052722fSJayclass IPrefetchToMissUnit(implicit  p: Parameters) extends IPrefetchBundle{
697052722fSJay  val enqReq  = DecoupledIO(new PIQReq)
707052722fSJay}
717052722fSJay
727052722fSJayclass IPredfetchIO(implicit p: Parameters) extends IPrefetchBundle {
737052722fSJay  val fromFtq         = Flipped(new FtqPrefechBundle)
74f1fe8698SLemover  val iTLBInter       = new TlbRequestIO
7561e1db30SJay  val pmp             =   new ICachePMPBundle
760c26d810Sguohongyu  val toIMeta         = Decoupled(new ICacheMetaReadReqBundle)
770c26d810Sguohongyu  val fromIMeta       = Input(new ICacheMetaReadRespBundle)
787052722fSJay  val toMissUnit      = new IPrefetchToMissUnit
79b1ded4e8Sguohongyu  val freePIQEntry    = Input(UInt(log2Ceil(nPrefetchEntries).W))
80974a902cSguohongyu  val fromMSHR        = Flipped(Vec(totalMSHRNum,ValidIO(UInt(PAddrBits.W))))
81b1ded4e8Sguohongyu  val IPFBufferRead   = Flipped(new IPFBufferFilterRead)
82b1ded4e8Sguohongyu  /** icache main pipe to prefetch pipe*/
83974a902cSguohongyu  val mainPipeMissSlotInfo = Flipped(Vec(PortNumber,ValidIO(new MainPipeToPrefetchPipe)))
84a108d429SJay
85a108d429SJay  val prefetchEnable = Input(Bool())
86a108d429SJay  val prefetchDisable = Input(Bool())
87b1ded4e8Sguohongyu  val fencei         = Input(Bool())
88b1ded4e8Sguohongyu}
89b1ded4e8Sguohongyu
90b1ded4e8Sguohongyu/** Prefetch Buffer **/
91b1ded4e8Sguohongyu
9264d7d412Sguohongyuclass IPFWritePtrQueue(implicit p: Parameters) extends IPrefetchModule with HasCircularQueuePtrHelper
9364d7d412Sguohongyu{
9464d7d412Sguohongyu  val io = IO(new Bundle{
9564d7d412Sguohongyu    val free_ptr = DecoupledIO(UInt(log2Ceil(nIPFBufferSize).W))
9664d7d412Sguohongyu    val release_ptr = Flipped(ValidIO(UInt(log2Ceil(nIPFBufferSize).W)))
972a6078bfSguohongyu    val flush = Input(Bool())
9864d7d412Sguohongyu  })
9964d7d412Sguohongyu  /* define ptr */
10064d7d412Sguohongyu  class IPFPtr(implicit p: Parameters) extends CircularQueuePtr[IPFPtr](
10164d7d412Sguohongyu    p => p(XSCoreParamsKey).icacheParameters.nPrefBufferEntries
10264d7d412Sguohongyu  ){
10364d7d412Sguohongyu  }
10464d7d412Sguohongyu
10564d7d412Sguohongyu  object IPFPtr {
10664d7d412Sguohongyu    def apply(f: Bool, v: UInt)(implicit p: Parameters): IPFPtr = {
10764d7d412Sguohongyu      val ptr = Wire(new IPFPtr)
10864d7d412Sguohongyu      ptr.flag := f
10964d7d412Sguohongyu      ptr.value := v
11064d7d412Sguohongyu      ptr
11164d7d412Sguohongyu    }
11264d7d412Sguohongyu  }
11364d7d412Sguohongyu
11464d7d412Sguohongyu  val queue = RegInit(VecInit((0 until nIPFBufferSize).map(i => i.U(log2Ceil(nIPFBufferSize).W))))
11564d7d412Sguohongyu  val enq_ptr = RegInit(IPFPtr(true.B, 0.U))
11664d7d412Sguohongyu  val deq_ptr = RegInit(IPFPtr(false.B, 0.U))
11764d7d412Sguohongyu
11864d7d412Sguohongyu  io.free_ptr.valid := !isEmpty(enq_ptr, deq_ptr)
11964d7d412Sguohongyu  io.free_ptr.bits := queue(deq_ptr.value)
12064d7d412Sguohongyu  deq_ptr := deq_ptr + io.free_ptr.fire
12164d7d412Sguohongyu
12264d7d412Sguohongyu  when (io.release_ptr.valid) {
12364d7d412Sguohongyu    queue(enq_ptr.value) := io.release_ptr.bits
12464d7d412Sguohongyu    enq_ptr := enq_ptr + 1.U
12564d7d412Sguohongyu  }
12664d7d412Sguohongyu
1272a6078bfSguohongyu  when (io.flush) {
1282a6078bfSguohongyu    queue := RegInit(VecInit((0 until nIPFBufferSize).map(i => i.U(log2Ceil(nIPFBufferSize).W))))
1292a6078bfSguohongyu    enq_ptr := RegInit(IPFPtr(true.B, 0.U))
1302a6078bfSguohongyu    deq_ptr := RegInit(IPFPtr(false.B, 0.U))
1312a6078bfSguohongyu  }
1322a6078bfSguohongyu
13364d7d412Sguohongyu  XSError(isBefore(enq_ptr, deq_ptr) && !isFull(enq_ptr, deq_ptr), "enq_ptr should not before deq_ptr\n")
13464d7d412Sguohongyu}
13564d7d412Sguohongyu
136b1ded4e8Sguohongyu
137b1ded4e8Sguohongyuclass PrefetchBuffer(implicit p: Parameters) extends IPrefetchModule
138b1ded4e8Sguohongyu{
139b1ded4e8Sguohongyu  val io = IO(new Bundle{
140c2ba7c80Sguohongyu    val hartId = Input(UInt(8.W))
141b1ded4e8Sguohongyu    val read  = new IPFBufferRead
1420c26d810Sguohongyu    val filter_read = Vec(prefetchPipeNum, new IPFBufferFilterRead)
143b1ded4e8Sguohongyu    val write = Flipped(ValidIO(new IPFBufferWrite))
144b1ded4e8Sguohongyu    /** to ICache replacer */
145b1ded4e8Sguohongyu    val replace = new IPFBufferMove
146b1ded4e8Sguohongyu    /** move & move filter port */
147b1ded4e8Sguohongyu    val mainpipe_missinfo = Flipped(new MainPipeMissInfo)
1480c26d810Sguohongyu    val meta_filter_read_req = Decoupled(new ICacheMetaReadReqBundle)
1490c26d810Sguohongyu    val meta_filter_read_resp = Input(new ICacheMetaReadRespBundle)
150b1ded4e8Sguohongyu    val move  = new Bundle() {
151b1ded4e8Sguohongyu      val meta_write = DecoupledIO(new ICacheMetaWriteBundle)
152b1ded4e8Sguohongyu      val data_write = DecoupledIO(new ICacheDataWriteBundle)
153b1ded4e8Sguohongyu    }
154b1ded4e8Sguohongyu    val fencei = Input(Bool())
155b1ded4e8Sguohongyu  })
156b1ded4e8Sguohongyu
157b1ded4e8Sguohongyu  class IPFBufferEntryMeta(implicit p: Parameters) extends IPrefetchBundle
158b1ded4e8Sguohongyu  {
159b1ded4e8Sguohongyu    val tag = UInt(tagBits.W)
160b1ded4e8Sguohongyu    val index = UInt(idxBits.W)
161b1ded4e8Sguohongyu    val paddr = UInt(PAddrBits.W)
162b1ded4e8Sguohongyu    val valid = Bool()
163b1ded4e8Sguohongyu    val confidence = UInt(log2Ceil(maxIPFMoveConf + 1).W)
164b1ded4e8Sguohongyu    val move = Bool()
165d4112e88Sguohongyu    val has_been_hit = Bool()
166b1ded4e8Sguohongyu  }
167b1ded4e8Sguohongyu
168b1ded4e8Sguohongyu  class IPFBufferEntryData(implicit p: Parameters) extends IPrefetchBundle
169b1ded4e8Sguohongyu  {
170b1ded4e8Sguohongyu    val cachline = UInt(blockBits.W)
171b1ded4e8Sguohongyu  }
172b1ded4e8Sguohongyu
173b1ded4e8Sguohongyu  def InitQueue[T <: Data](entry: T, size: Int): Vec[T] ={
174b1ded4e8Sguohongyu    return RegInit(VecInit(Seq.fill(size)(0.U.asTypeOf(entry.cloneType))))
175b1ded4e8Sguohongyu  }
176b1ded4e8Sguohongyu
177b1ded4e8Sguohongyu  val meta_buffer = InitQueue(new IPFBufferEntryMeta, size = nIPFBufferSize)
178b1ded4e8Sguohongyu  val data_buffer = InitQueue(new IPFBufferEntryData, size = nIPFBufferSize)
179b1ded4e8Sguohongyu
18064d7d412Sguohongyu  val ipf_write_ptr_queue = Module(new IPFWritePtrQueue())
1812a6078bfSguohongyu  ipf_write_ptr_queue.io.flush := io.fencei
18264d7d412Sguohongyu
1836f9ed85eSguohongyu  val meta_buffer_empty_oh = WireInit(VecInit(Seq.fill(nIPFBufferSize)(false.B)))
1846f9ed85eSguohongyu  (0 until nIPFBufferSize).foreach { i =>
1856f9ed85eSguohongyu    meta_buffer_empty_oh(i) := !meta_buffer(i).valid
1866f9ed85eSguohongyu  }
1876f9ed85eSguohongyu  XSPerfAccumulate("ipfbuffer_empty_entry_multi_cycle", PopCount(meta_buffer_empty_oh))
1886f9ed85eSguohongyu
189b1ded4e8Sguohongyu  /** filter read logic */
1900c26d810Sguohongyu  val fr_vidx = (0 until prefetchPipeNum).map (i => io.filter_read(i).req.vSetIdx)
1910c26d810Sguohongyu  val fr_ptag = (0 until prefetchPipeNum).map (i => get_phy_tag(io.filter_read(i).req.paddr))
192b1ded4e8Sguohongyu
1930c26d810Sguohongyu  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(_||_))
19434f9624dSguohongyu  val fr_hit_in_s1, fr_hit_in_s2, fr_hit_in_s3 = Wire(Vec(prefetchPipeNum, Bool()))
195b1ded4e8Sguohongyu
1960c26d810Sguohongyu  (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))
197b1ded4e8Sguohongyu
198b1ded4e8Sguohongyu  /** read logic */
199b1ded4e8Sguohongyu  (0 until PortNumber).foreach(i => io.read.req(i).ready := true.B)
200b1ded4e8Sguohongyu  val r_valid = VecInit((0 until PortNumber).map( i => io.read.req(i).valid)).reduce(_||_)
201b1ded4e8Sguohongyu  val r_vidx = VecInit((0 until PortNumber).map(i => get_idx(io.read.req(i).bits.vaddr)))
202b1ded4e8Sguohongyu  val r_ptag = VecInit((0 until PortNumber).map(i => get_phy_tag(io.read.req(i).bits.paddr)))
203b1ded4e8Sguohongyu  val r_hit_oh = VecInit((0 until PortNumber).map(i =>
204b1ded4e8Sguohongyu    VecInit(meta_buffer.map(entry =>
205b1ded4e8Sguohongyu      io.read.req(i).valid && // need this condition
206b1ded4e8Sguohongyu        entry.valid &&
207b1ded4e8Sguohongyu        entry.tag === r_ptag(i) &&
208b1ded4e8Sguohongyu        entry.index === r_vidx(i)
209b1ded4e8Sguohongyu    ))))
210b1ded4e8Sguohongyu  val r_buffer_hit = VecInit(r_hit_oh.map(_.reduce(_||_)))
211b1ded4e8Sguohongyu  val r_buffer_hit_idx = VecInit(r_hit_oh.map(PriorityEncoder(_)))
21264d7d412Sguohongyu  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
213b1ded4e8Sguohongyu
214b1ded4e8Sguohongyu  /** "read" also check data in move pipeline */
215b1ded4e8Sguohongyu  val r_moves1pipe_hit_s1, r_moves1pipe_hit_s2, r_moves1pipe_hit_s3 = WireInit(VecInit(Seq.fill(PortNumber)(false.B)))
216b1ded4e8Sguohongyu  val s1_move_data_cacheline, s2_move_data_cacheline, s3_move_data_cacheline = Wire(UInt(blockBits.W))
217b1ded4e8Sguohongyu
218b1ded4e8Sguohongyu  (0 until PortNumber).foreach{ i =>
219b1ded4e8Sguohongyu    io.read.resp(i).valid := io.read.req(i).valid
220b1ded4e8Sguohongyu    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)
221b1ded4e8Sguohongyu    io.read.resp(i).bits.cacheline := Mux(r_buffer_hit(i), r_buffer_hit_data(i),
222b1ded4e8Sguohongyu      Mux(r_moves1pipe_hit_s1(i), s1_move_data_cacheline,
223b1ded4e8Sguohongyu        Mux(r_moves1pipe_hit_s2(i), s2_move_data_cacheline, s3_move_data_cacheline)))
224b1ded4e8Sguohongyu  }
225b1ded4e8Sguohongyu
226d4112e88Sguohongyu  (0 until PortNumber).foreach { i =>
22769c27f53Sguohongyu    when(io.read.req(i).valid && r_hit_oh(i).reduce(_ || _)) {
228d4112e88Sguohongyu      meta_buffer(r_buffer_hit_idx(i)).has_been_hit := true.B
229d4112e88Sguohongyu    }
23069c27f53Sguohongyu    XSPerfAccumulate("ipf_entry_first_hit_by_port_" + i, io.read.req(i).valid && r_hit_oh(i).reduce(_ || _) &&
231d4112e88Sguohongyu      meta_buffer(r_buffer_hit_idx(i)).has_been_hit === false.B)
232d4112e88Sguohongyu  }
233d4112e88Sguohongyu
234d4112e88Sguohongyu
235b1ded4e8Sguohongyu  /** move logic */
236b1ded4e8Sguohongyu  val r_buffer_hit_s2     = RegNext(r_buffer_hit, init=0.U.asTypeOf(r_buffer_hit.cloneType))
237b1ded4e8Sguohongyu  val r_buffer_hit_idx_s2 = RegNext(r_buffer_hit_idx)
238b1ded4e8Sguohongyu  val r_rvalid_s2         = RegNext(r_valid, init=false.B)
239b1ded4e8Sguohongyu
240b1ded4e8Sguohongyu  val s2_move_valid_0 = r_rvalid_s2 && r_buffer_hit_s2(0)
241b1ded4e8Sguohongyu  val s2_move_valid_1 = r_rvalid_s2 && r_buffer_hit_s2(1)
242b1ded4e8Sguohongyu
243b1ded4e8Sguohongyu  XSPerfAccumulate("prefetch_hit_bank_0", r_rvalid_s2 && r_buffer_hit_s2(0))
244b1ded4e8Sguohongyu  XSPerfAccumulate("prefetch_hit_bank_1", r_rvalid_s2 && r_buffer_hit_s2(1))
245b1ded4e8Sguohongyu
246b1ded4e8Sguohongyu  val move_queue    = RegInit(VecInit(Seq.fill(nIPFBufferSize)(0.U.asTypeOf(r_buffer_hit_idx_s2(0)))))
247b1ded4e8Sguohongyu
248b1ded4e8Sguohongyu  val curr_move_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W))
249b1ded4e8Sguohongyu  val curr_hit_ptr  = RegInit(0.U(log2Ceil(nIPFBufferSize).W))
250b1ded4e8Sguohongyu
251b1ded4e8Sguohongyu  val s2_move_conf_full_0 = meta_buffer(r_buffer_hit_idx_s2(0)).confidence === (maxIPFMoveConf).U
252b1ded4e8Sguohongyu  val s2_move_conf_full_1 = meta_buffer(r_buffer_hit_idx_s2(1)).confidence === (maxIPFMoveConf).U
253b1ded4e8Sguohongyu
254b1ded4e8Sguohongyu  val move_repeat_0 = meta_buffer(r_buffer_hit_idx_s2(0)).move
255b1ded4e8Sguohongyu  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))
256b1ded4e8Sguohongyu
257b1ded4e8Sguohongyu  val s2_move_0 = s2_move_valid_0 && !move_repeat_0
258b1ded4e8Sguohongyu  val s2_move_1 = s2_move_valid_1 && !move_repeat_1
259b1ded4e8Sguohongyu
260b1ded4e8Sguohongyu  val s2_move_enqueue_0 = s2_move_0 && s2_move_conf_full_0
261b1ded4e8Sguohongyu  val s2_move_enqueue_1 = s2_move_1 && s2_move_conf_full_1
262b1ded4e8Sguohongyu
263b1ded4e8Sguohongyu  when(s2_move_0) {
264b1ded4e8Sguohongyu    when(s2_move_conf_full_0) {
265b1ded4e8Sguohongyu      meta_buffer(r_buffer_hit_idx_s2(0)).move := true.B
266b1ded4e8Sguohongyu    }.otherwise {
267b1ded4e8Sguohongyu      meta_buffer(r_buffer_hit_idx_s2(0)).confidence := meta_buffer(r_buffer_hit_idx_s2(0)).confidence + 1.U
268b1ded4e8Sguohongyu    }
269b1ded4e8Sguohongyu  }
270b1ded4e8Sguohongyu  when(s2_move_1) {
271b1ded4e8Sguohongyu    when(s2_move_conf_full_1) {
272b1ded4e8Sguohongyu      meta_buffer(r_buffer_hit_idx_s2(1)).move := true.B
273b1ded4e8Sguohongyu    }.otherwise {
274b1ded4e8Sguohongyu      meta_buffer(r_buffer_hit_idx_s2(1)).confidence := meta_buffer(r_buffer_hit_idx_s2(1)).confidence + 1.U
275b1ded4e8Sguohongyu    }
276b1ded4e8Sguohongyu  }
277b1ded4e8Sguohongyu
278b1ded4e8Sguohongyu  when(s2_move_enqueue_0 && !s2_move_enqueue_1) {
279b1ded4e8Sguohongyu    move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0)
280b1ded4e8Sguohongyu
281b1ded4e8Sguohongyu    when((curr_hit_ptr + 1.U) =/= curr_move_ptr){
282b1ded4e8Sguohongyu      curr_hit_ptr := curr_hit_ptr + 1.U
283b1ded4e8Sguohongyu    }
284b1ded4e8Sguohongyu  }.elsewhen(!s2_move_enqueue_0 && s2_move_enqueue_1) {
285b1ded4e8Sguohongyu    move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(1)
286b1ded4e8Sguohongyu
287b1ded4e8Sguohongyu    when((curr_hit_ptr + 1.U) =/= curr_move_ptr){
288b1ded4e8Sguohongyu      curr_hit_ptr := curr_hit_ptr + 1.U
289b1ded4e8Sguohongyu    }
290b1ded4e8Sguohongyu  }.elsewhen(s2_move_enqueue_0 && s2_move_enqueue_1) {
291b1ded4e8Sguohongyu    move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0)
292b1ded4e8Sguohongyu    move_queue(curr_hit_ptr + 1.U) := r_buffer_hit_idx_s2(1)
293b1ded4e8Sguohongyu    when((curr_hit_ptr + 2.U) =/= curr_move_ptr){
294b1ded4e8Sguohongyu      curr_hit_ptr := curr_hit_ptr + 2.U
295b1ded4e8Sguohongyu    }.otherwise{
296b1ded4e8Sguohongyu      curr_hit_ptr := curr_hit_ptr + 1.U
297b1ded4e8Sguohongyu    }
298b1ded4e8Sguohongyu  }
299b1ded4e8Sguohongyu
300b1ded4e8Sguohongyu  val move_queue_empty = curr_move_ptr === curr_hit_ptr
301b1ded4e8Sguohongyu  /** pipeline control signal */
302b1ded4e8Sguohongyu  val s1_ready, s2_ready, s3_ready = Wire(Bool())
303b1ded4e8Sguohongyu  val s0_fire, s1_fire, s2_fire, s3_fire = Wire(Bool())
304b1ded4e8Sguohongyu
305b1ded4e8Sguohongyu  /** stage 0 */
306b1ded4e8Sguohongyu  val s0_valid        = !move_queue_empty && meta_buffer(move_queue(curr_move_ptr)).move
307b1ded4e8Sguohongyu
308b1ded4e8Sguohongyu  val s0_move_idx     = move_queue(curr_move_ptr)
309b1ded4e8Sguohongyu  val s0_move_meta    = meta_buffer(s0_move_idx)
310b1ded4e8Sguohongyu  val s0_move_data    = data_buffer(s0_move_idx)
311b1ded4e8Sguohongyu  io.replace.vsetIdx  := meta_buffer(s0_move_idx).index
312b1ded4e8Sguohongyu  val s0_waymask      = io.replace.waymask
313b1ded4e8Sguohongyu
314b1ded4e8Sguohongyu  s0_fire             := s0_valid && s1_ready
315b1ded4e8Sguohongyu
316b1ded4e8Sguohongyu  /** curr_move_ptr control logic */
317b1ded4e8Sguohongyu  val s0_move_jump = !move_queue_empty && !meta_buffer(move_queue(curr_move_ptr)).move
318b1ded4e8Sguohongyu  when (s0_fire) {
319b1ded4e8Sguohongyu    curr_move_ptr := curr_move_ptr + 1.U
32064d7d412Sguohongyu    meta_buffer(s0_move_idx).valid := false.B // TODO : maybe should not invalid
321b1ded4e8Sguohongyu    meta_buffer(s0_move_idx).move  := false.B
322b1ded4e8Sguohongyu    meta_buffer(s0_move_idx).confidence := 0.U
323b1ded4e8Sguohongyu  }.elsewhen(s0_move_jump) {
324b1ded4e8Sguohongyu    curr_move_ptr := curr_move_ptr + 1.U
325b1ded4e8Sguohongyu  }
326b1ded4e8Sguohongyu
327b1ded4e8Sguohongyu  /** stage 1 : send req to metaArray */
328b1ded4e8Sguohongyu  val s1_valid        = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = io.fencei, lastFlush = false.B)
329b1ded4e8Sguohongyu
330b1ded4e8Sguohongyu  val s1_move_idx     = RegEnable(s0_move_idx, s0_fire)
331b1ded4e8Sguohongyu  val s1_move_meta    = RegEnable(s0_move_meta, s0_fire)
332b1ded4e8Sguohongyu  val s1_move_data    = RegEnable(s0_move_data, s0_fire)
333b1ded4e8Sguohongyu  val s1_waymask      = RegEnable(s0_waymask, s0_fire)
334b1ded4e8Sguohongyu
3350c26d810Sguohongyu  io.meta_filter_read_req.valid := s1_valid
3360c26d810Sguohongyu  io.meta_filter_read_req.bits.idx := s1_move_meta.index
337b1ded4e8Sguohongyu
338b1ded4e8Sguohongyu  s1_ready            := !s1_valid || s1_fire
3390c26d810Sguohongyu  s1_fire             := s1_valid && io.meta_filter_read_req.ready && s2_ready
340b1ded4e8Sguohongyu
3410c26d810Sguohongyu  (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))
342b1ded4e8Sguohongyu  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))
343b1ded4e8Sguohongyu  s1_move_data_cacheline := s1_move_data.cachline
344b1ded4e8Sguohongyu
345b1ded4e8Sguohongyu  /** stage 2 : collect message from metaArray and mainPipe to filter */
346b1ded4e8Sguohongyu  val s2_valid        = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = io.fencei, lastFlush = false.B)
347b1ded4e8Sguohongyu
348b1ded4e8Sguohongyu  val s2_move_idx     = RegEnable(s1_move_idx, s1_fire)
349b1ded4e8Sguohongyu  val s2_move_meta    = RegEnable(s1_move_meta, s1_fire)
350b1ded4e8Sguohongyu  val s2_move_data    = RegEnable(s1_move_data, s1_fire)
351b1ded4e8Sguohongyu  val s2_waymask      = RegEnable(s1_waymask, s1_fire)
352b1ded4e8Sguohongyu
3530c26d810Sguohongyu  val s2_meta_ptags   = ResultHoldBypass(data = io.meta_filter_read_resp.tags, valid = RegNext(s1_fire))
3540c26d810Sguohongyu  val s2_meta_valids  = ResultHoldBypass(data = io.meta_filter_read_resp.entryValid, valid = RegNext(s1_fire))
355b1ded4e8Sguohongyu
3560c26d810Sguohongyu  val s2_tag_eq_vec = VecInit((0 until nWays).map(w => s2_meta_ptags(w) === s2_move_meta.tag)) // just use port 0
3570c26d810Sguohongyu  val s2_tag_match_vec = VecInit(s2_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s2_meta_valids(w)})
358b1ded4e8Sguohongyu  val s2_hit_in_meta_array = ParallelOR(s2_tag_match_vec)
359b1ded4e8Sguohongyu
360b1ded4e8Sguohongyu  val main_s2_missinfo = io.mainpipe_missinfo.s2_miss_info
361b1ded4e8Sguohongyu  val s2_hit_main_s2_missreq = VecInit((0 until PortNumber).map(i =>
362b1ded4e8Sguohongyu    main_s2_missinfo(i).valid && s2_move_meta.index === main_s2_missinfo(i).bits.vSetIdx
363b1ded4e8Sguohongyu      && s2_move_meta.tag === main_s2_missinfo(i).bits.ptage)).reduce(_||_)
364b1ded4e8Sguohongyu
365b1ded4e8Sguohongyu  val s2_discard        = s2_hit_in_meta_array || s2_hit_main_s2_missreq // || s2_hit_main_s1_missreq
366b1ded4e8Sguohongyu  val s2_discard_latch  = holdReleaseLatch(valid = s2_discard, release = s2_fire, flush = io.fencei)
367b1ded4e8Sguohongyu  if(DebugFlags.fdip){
368b1ded4e8Sguohongyu    when (s2_fire && s2_discard_latch) {
369b1ded4e8Sguohongyu      printf("<%d> IPrefetchBuffer: s2_discard : hit_in_meta_array=%d,hit_in_main_s2=%d, ptag=0x%x\n",
370b1ded4e8Sguohongyu        GTimer(), s2_hit_in_meta_array, s2_hit_main_s2_missreq, s2_move_meta.tag)
371b1ded4e8Sguohongyu    }
372b1ded4e8Sguohongyu  }
373b1ded4e8Sguohongyu
374b1ded4e8Sguohongyu  s2_ready := !s2_valid || s2_fire
375b1ded4e8Sguohongyu  s2_fire := s2_valid && s3_ready && io.mainpipe_missinfo.s1_already_check_ipf
376b1ded4e8Sguohongyu
3770c26d810Sguohongyu  (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))
378b1ded4e8Sguohongyu  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))
379b1ded4e8Sguohongyu  s2_move_data_cacheline := s2_move_data.cachline
380b1ded4e8Sguohongyu
381b1ded4e8Sguohongyu  /** stage 3 : move data to metaArray and dataArray */
382b1ded4e8Sguohongyu  val s3_valid = generatePipeControl(lastFire = s2_fire, thisFire = s3_fire, thisFlush = io.fencei, lastFlush = false.B)
383b1ded4e8Sguohongyu
384b1ded4e8Sguohongyu  val s3_move_idx = RegEnable(s2_move_idx, s2_fire)
385b1ded4e8Sguohongyu  val s3_move_meta = RegEnable(s2_move_meta, s2_fire)
386b1ded4e8Sguohongyu  val s3_move_data = RegEnable(s2_move_data, s2_fire)
387b1ded4e8Sguohongyu  val s3_waymask = RegEnable(s2_waymask, s2_fire)
388b1ded4e8Sguohongyu  val s3_discard = RegEnable(s2_discard_latch, s2_fire)
389b1ded4e8Sguohongyu
390b1ded4e8Sguohongyu  io.move.meta_write.valid := s3_valid && !s3_discard && !io.fencei
391b1ded4e8Sguohongyu  io.move.data_write.valid := s3_valid && !s3_discard && !io.fencei
392b1ded4e8Sguohongyu  io.move.meta_write.bits.generate(
393b1ded4e8Sguohongyu    tag = s3_move_meta.tag,
394b1ded4e8Sguohongyu    idx = s3_move_meta.index,
395b1ded4e8Sguohongyu    waymask = s3_waymask,
396b1ded4e8Sguohongyu    bankIdx = s3_move_meta.index(0))
397b1ded4e8Sguohongyu  io.move.data_write.bits.generate(
398b1ded4e8Sguohongyu    data = s3_move_data.cachline,
399b1ded4e8Sguohongyu    idx = s3_move_meta.index,
400b1ded4e8Sguohongyu    waymask = s3_waymask,
401b1ded4e8Sguohongyu    bankIdx = s3_move_meta.index(0),
402b1ded4e8Sguohongyu    paddr = s3_move_meta.paddr)
403b1ded4e8Sguohongyu
404b1ded4e8Sguohongyu  s3_ready := !s3_valid || s3_fire
405b1ded4e8Sguohongyu  s3_fire := io.move.meta_write.fire && io.move.data_write.fire || s3_discard || io.fencei
406b1ded4e8Sguohongyu  assert((io.move.meta_write.fire && io.move.data_write.fire) || (!io.move.meta_write.fire && !io.move.data_write.fire),
407b1ded4e8Sguohongyu    "meta and data array need fire at same time")
408b1ded4e8Sguohongyu
4090c26d810Sguohongyu  (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))
410b1ded4e8Sguohongyu  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))
411b1ded4e8Sguohongyu  s3_move_data_cacheline := s3_move_data.cachline
412b1ded4e8Sguohongyu
413b1ded4e8Sguohongyu  if (DebugFlags.fdip) {
414b1ded4e8Sguohongyu    when(io.move.meta_write.fire) {
415b1ded4e8Sguohongyu      printf("<%d> IPrefetchBuffer: move data to meta sram:ptag=0x%x,vidx=0x%x,waymask=0x%x\n",
416b1ded4e8Sguohongyu        GTimer(), s3_move_meta.tag,s3_move_meta.index,s3_waymask )
417b1ded4e8Sguohongyu    }
418b1ded4e8Sguohongyu  }
419b1ded4e8Sguohongyu
420afa866b1Sguohongyu  if (env.EnableDifftest) {
421afa866b1Sguohongyu    val difftest = Module(new DifftestRefillEvent)
422afa866b1Sguohongyu    difftest.io.clock := clock
423c2ba7c80Sguohongyu    difftest.io.coreid := io.hartId
424afa866b1Sguohongyu    difftest.io.cacheid := 6.U
425afa866b1Sguohongyu    difftest.io.valid := io.move.meta_write.fire
426afa866b1Sguohongyu    difftest.io.addr := s3_move_meta.paddr
427afa866b1Sguohongyu    difftest.io.data := s3_move_data.cachline.asTypeOf(difftest.io.data)
428afa866b1Sguohongyu  }
429afa866b1Sguohongyu
430b1ded4e8Sguohongyu  /** write logic */
431b1ded4e8Sguohongyu  val replacer = ReplacementPolicy.fromString(Some("random"), nIPFBufferSize)
43264d7d412Sguohongyu  val curr_write_ptr = Wire(UInt(log2Ceil(nIPFBufferSize).W))
43364d7d412Sguohongyu  when (ipf_write_ptr_queue.io.free_ptr.valid) {
43464d7d412Sguohongyu    curr_write_ptr := ipf_write_ptr_queue.io.free_ptr.bits
43564d7d412Sguohongyu  }.otherwise {
43664d7d412Sguohongyu    curr_write_ptr := replacer.way
43764d7d412Sguohongyu    when (io.write.valid) {
43864d7d412Sguohongyu      replacer.miss
43964d7d412Sguohongyu    }
44064d7d412Sguohongyu  }
441b1ded4e8Sguohongyu
44264d7d412Sguohongyu  ipf_write_ptr_queue.io.release_ptr.valid := s0_fire
44364d7d412Sguohongyu  ipf_write_ptr_queue.io.release_ptr.bits := s0_move_idx
44464d7d412Sguohongyu
44564d7d412Sguohongyu  ipf_write_ptr_queue.io.free_ptr.ready := io.write.valid
446b1ded4e8Sguohongyu  when(io.write.valid) {
447b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).tag := io.write.bits.meta.tag
448b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).index := io.write.bits.meta.index
449b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).paddr := io.write.bits.meta.paddr
450b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).valid := true.B
451b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).move  := false.B
452b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).confidence := 0.U
453d4112e88Sguohongyu    meta_buffer(curr_write_ptr).has_been_hit := false.B
454b1ded4e8Sguohongyu
455b1ded4e8Sguohongyu    data_buffer(curr_write_ptr).cachline := io.write.bits.data
456b1ded4e8Sguohongyu
457b1ded4e8Sguohongyu  }
458b1ded4e8Sguohongyu
459b1ded4e8Sguohongyu  /** fencei: invalid all entries */
460b1ded4e8Sguohongyu  when(io.fencei) {
4612a6078bfSguohongyu    meta_buffer.foreach { b =>
462b1ded4e8Sguohongyu      b.valid := false.B
463b1ded4e8Sguohongyu      b.move := false.B
464b1ded4e8Sguohongyu      b.confidence := 0.U
4652a6078bfSguohongyu      b.has_been_hit := false.B
466b1ded4e8Sguohongyu    }
4671d4724e4Sguohongyu    (0 until PortNumber).foreach(i => r_buffer_hit_s2(i) := 0.U )
4682a6078bfSguohongyu    r_rvalid_s2 := 0.U
4692a6078bfSguohongyu    curr_move_ptr := 0.U
4702a6078bfSguohongyu    curr_hit_ptr := 0.U
471b1ded4e8Sguohongyu  }
472b1ded4e8Sguohongyu
4737052722fSJay}
4747052722fSJay
4757052722fSJayclass IPrefetchPipe(implicit p: Parameters) extends  IPrefetchModule
4767052722fSJay{
4777052722fSJay  val io = IO(new IPredfetchIO)
4787052722fSJay
479a108d429SJay  val enableBit = RegInit(false.B)
480b1ded4e8Sguohongyu  val maxPrefetchCounter = RegInit(0.U(log2Ceil(nPrefetchEntries + 1).W))
481a108d429SJay
482b1ded4e8Sguohongyu  val reachMaxSize = maxPrefetchCounter === nPrefetchEntries.U
483a108d429SJay
484b1ded4e8Sguohongyu  // when(io.prefetchEnable){
485b1ded4e8Sguohongyu  //   enableBit := true.B
486b1ded4e8Sguohongyu  // }.elsewhen((enableBit && io.prefetchDisable) || (enableBit && reachMaxSize)){
487b1ded4e8Sguohongyu  //   enableBit := false.B
488b1ded4e8Sguohongyu  // }
489b1ded4e8Sguohongyu  // ignore prefetchEnable from ICacheMainPipe
490a108d429SJay  enableBit := true.B
491a108d429SJay
492a108d429SJay  class PrefetchDir(implicit  p: Parameters) extends IPrefetchBundle
493a108d429SJay  {
494a108d429SJay    val valid = Bool()
495a108d429SJay    val paddr = UInt(PAddrBits.W)
496a108d429SJay  }
497a108d429SJay
498a108d429SJay  val prefetch_dir = RegInit(VecInit(Seq.fill(nPrefetchEntries)(0.U.asTypeOf(new PrefetchDir))))
499a108d429SJay
5007052722fSJay  val fromFtq = io.fromFtq
501974a902cSguohongyu  val mainPipeMissSlotInfo = io.mainPipeMissSlotInfo
5027052722fSJay  val (toITLB,  fromITLB) = (io.iTLBInter.req, io.iTLBInter.resp)
503c3b763d0SYinan Xu  io.iTLBInter.req_kill := false.B
5040c26d810Sguohongyu  val (toIMeta, fromIMeta, fromIMetaValid) = (io.toIMeta, io.fromIMeta.metaData, io.fromIMeta.entryValid)
505b1ded4e8Sguohongyu  val (toIPFBuffer, fromIPFBuffer) = (io.IPFBufferRead.req, io.IPFBufferRead.resp)
5067052722fSJay  val (toPMP,  fromPMP)   = (io.pmp.req, io.pmp.resp)
5077052722fSJay  val toMissUnit = io.toMissUnit
5087052722fSJay
5097052722fSJay  val p0_fire, p1_fire, p2_fire, p3_fire =  WireInit(false.B)
510b1ded4e8Sguohongyu  val p0_discard, p1_discard, p2_discard, p3_discard = WireInit(false.B)
5117052722fSJay  val p0_ready, p1_ready, p2_ready, p3_ready = WireInit(false.B)
5127052722fSJay
5137052722fSJay  /** Prefetch Stage 0: req from Ftq */
5147052722fSJay  val p0_valid  =   fromFtq.req.valid
515d6b06a99SJay  val p0_vaddr  =   addrAlign(fromFtq.req.bits.target, blockBytes, VAddrBits)
516b1ded4e8Sguohongyu  val p0_vaddr_reg = RegEnable(p0_vaddr, fromFtq.req.fire())
5177052722fSJay
518b1ded4e8Sguohongyu  /* Cancel request when prefetch not enable
519b1ded4e8Sguohongyu   * or the request from FTQ is same as last time */
520b1ded4e8Sguohongyu  val p0_req_cancel = !enableBit || (p0_vaddr === p0_vaddr_reg) || io.fencei
521b1ded4e8Sguohongyu  p0_fire   :=   p0_valid && p1_ready && toITLB.fire() && !fromITLB.bits.miss && toIMeta.ready && enableBit && !p0_req_cancel
522b1ded4e8Sguohongyu  p0_discard := p0_valid && p0_req_cancel
523b1ded4e8Sguohongyu
524b1ded4e8Sguohongyu  toIMeta.valid     := p0_valid && !p0_discard
5250c26d810Sguohongyu  toIMeta.bits.idx  := get_idx(p0_vaddr)
5267052722fSJay
527b1ded4e8Sguohongyu  toITLB.valid         := p0_valid && !p0_discard
5287052722fSJay  toITLB.bits.size     := 3.U // TODO: fix the size
5297052722fSJay  toITLB.bits.vaddr    := p0_vaddr
5307052722fSJay  toITLB.bits.debug.pc := p0_vaddr
5317052722fSJay
532f1fe8698SLemover  toITLB.bits.kill                := DontCare
5337052722fSJay  toITLB.bits.cmd                 := TlbCmd.exec
534f1fe8698SLemover  toITLB.bits.debug.robIdx        := DontCare
5357052722fSJay  toITLB.bits.debug.isFirstIssue  := DontCare
536b1ded4e8Sguohongyu  toITLB.bits.memidx              := DontCare
537b1ded4e8Sguohongyu  toITLB.bits.no_translate        := false.B
5387052722fSJay
5397052722fSJay  fromITLB.ready := true.B
5407052722fSJay
54134f9624dSguohongyu  fromFtq.req.ready := p0_req_cancel || p1_ready && toITLB.ready && !fromITLB.bits.miss && toIMeta.ready
5427052722fSJay
543974a902cSguohongyu  /** Prefetch Stage 1: check in cache & ICacheMainPipeMSHR */
5447052722fSJay  val p1_valid =  generatePipeControl(lastFire = p0_fire, thisFire = p1_fire || p1_discard, thisFlush = false.B, lastFlush = false.B)
5457052722fSJay
546005e809bSJiuyang Liu  val p1_vaddr   =  RegEnable(p0_vaddr,    p0_fire)
547b1ded4e8Sguohongyu  // TODO: tlb is none blocked ,when tlb miss, p1 req need cancle. Now there seemes has bug
5487052722fSJay  //tlb resp
549de7689fcSJay  val tlb_resp_valid = RegInit(false.B)
550de7689fcSJay  when(p0_fire) {tlb_resp_valid := true.B}
551de7689fcSJay    .elsewhen(tlb_resp_valid && (p1_fire || p1_discard)) {tlb_resp_valid := false.B}
5527052722fSJay
55303efd994Shappy-lx  val tlb_resp_paddr = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.paddr(0))
55403efd994Shappy-lx  val tlb_resp_pf    = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).pf.instr && tlb_resp_valid)
55503efd994Shappy-lx  val tlb_resp_af    = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).af.instr && tlb_resp_valid)
5567052722fSJay
5577052722fSJay  val p1_exception  = VecInit(Seq(tlb_resp_pf, tlb_resp_af))
5587052722fSJay  val p1_has_except =  p1_exception.reduce(_ || _)
559b1ded4e8Sguohongyu  val p1_paddr = tlb_resp_paddr
5607052722fSJay
561b1ded4e8Sguohongyu  val p1_ptag = get_phy_tag(p1_paddr)
5627052722fSJay
5637052722fSJay  val p1_meta_ptags       = ResultHoldBypass(data = VecInit(fromIMeta.map(way => way.tag)),valid = RegNext(p0_fire))
564b1ded4e8Sguohongyu  val p1_meta_valids      = ResultHoldBypass(data = fromIMetaValid,valid = RegNext(p0_fire))
565b1ded4e8Sguohongyu
5667052722fSJay  val p1_tag_eq_vec       =  VecInit(p1_meta_ptags.map(_  ===  p1_ptag ))
567b1ded4e8Sguohongyu  val p1_tag_match_vec    =  VecInit(p1_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && p1_meta_valids(w)})
5687052722fSJay  val p1_tag_match        =  ParallelOR(p1_tag_match_vec)
569974a902cSguohongyu  // check ICacheMissEntry
570b1ded4e8Sguohongyu  val p1_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p1_paddr, blockBytes, PAddrBits))).reduce(_||_)
571b1ded4e8Sguohongyu
572b1ded4e8Sguohongyu  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)
573b1ded4e8Sguohongyu
5747052722fSJay
5757052722fSJay  //overriding the invalid req
576b1ded4e8Sguohongyu  val p1_req_cancle = (p1_hit || (tlb_resp_valid && p1_exception.reduce(_ || _)) || io.fencei) && p1_valid
5777052722fSJay  val p1_req_accept   = p1_valid && tlb_resp_valid && p1_miss
5787052722fSJay
5797052722fSJay  p1_ready    :=   p1_fire || p1_req_cancle || !p1_valid
580a108d429SJay  p1_fire     :=   p1_valid && p1_req_accept && p2_ready && enableBit
5817052722fSJay  p1_discard  :=   p1_valid && p1_req_cancle
5827052722fSJay
583974a902cSguohongyu  /** Prefetch Stage 2: check PMP & send check req to ICacheMainPipeMSHR */
5847052722fSJay  val p2_valid =  generatePipeControl(lastFire = p1_fire, thisFire = p2_fire || p2_discard, thisFlush = false.B, lastFlush = false.B)
585b1ded4e8Sguohongyu  val p2_pmp_fire = p2_valid
586b1ded4e8Sguohongyu  val pmpExcpAF = fromPMP.instr
5877052722fSJay
588b1ded4e8Sguohongyu  val p2_paddr     = RegEnable(p1_paddr,  p1_fire)
589b1ded4e8Sguohongyu  val p2_except_pf = RegEnable(tlb_resp_pf, p1_fire)
590b1ded4e8Sguohongyu  val p2_except_af = DataHoldBypass(pmpExcpAF, p2_pmp_fire) || RegEnable(tlb_resp_af, p1_fire)
591b1ded4e8Sguohongyu  val p2_mmio      = DataHoldBypass(io.pmp.resp.mmio && !p2_except_af && !p2_except_pf, p2_pmp_fire)
592b1ded4e8Sguohongyu  val p2_vaddr   =  RegEnable(p1_vaddr,    p1_fire)
593b1ded4e8Sguohongyu
5947052722fSJay
59500240ba6SJay  /*when a prefetch req meet with a miss req in MSHR cancle the prefetch req */
59600240ba6SJay  val p2_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p2_paddr, blockBytes, PAddrBits))).reduce(_||_)
59700240ba6SJay
5987052722fSJay  //TODO wait PMP logic
599b1ded4e8Sguohongyu  val p2_exception  = VecInit(Seq(pmpExcpAF, p2_mmio)).reduce(_||_)
600b1ded4e8Sguohongyu
601b1ded4e8Sguohongyu  io.pmp.req.valid      := p2_pmp_fire
602b1ded4e8Sguohongyu  io.pmp.req.bits.addr  := p2_paddr
603b1ded4e8Sguohongyu  io.pmp.req.bits.size  := 3.U
604b1ded4e8Sguohongyu  io.pmp.req.bits.cmd   := TlbCmd.exec
6057052722fSJay
6067052722fSJay  p2_ready :=   p2_fire || p2_discard || !p2_valid
607b1ded4e8Sguohongyu  p2_fire  :=   p2_valid && !p2_exception && p3_ready && p2_pmp_fire
608cb9c9c0fSguohongyu  p2_discard := p2_valid && (p2_exception && p2_pmp_fire || io.fencei || p2_check_in_mshr)
6097052722fSJay
6107052722fSJay  /** Prefetch Stage 2: filtered req PIQ enqueue */
611a108d429SJay  val p3_valid =  generatePipeControl(lastFire = p2_fire, thisFire = p3_fire || p3_discard, thisFlush = false.B, lastFlush = false.B)
6127052722fSJay
613b1ded4e8Sguohongyu  val p3_paddr = RegEnable(p2_paddr,  p2_fire)
614cb9c9c0fSguohongyu  val p3_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p3_paddr, blockBytes, PAddrBits))).reduce(_||_)
615b1ded4e8Sguohongyu  val p3_vaddr   =  RegEnable(p2_vaddr,    p2_fire)
616b1ded4e8Sguohongyu  val p3_vidx = get_idx(p3_vaddr)
617b1ded4e8Sguohongyu  // check in prefetch buffer
618b1ded4e8Sguohongyu  toIPFBuffer.vSetIdx := p3_vidx
619b1ded4e8Sguohongyu  toIPFBuffer.paddr := p3_paddr
620b1ded4e8Sguohongyu  val p3_buffer_hit = fromIPFBuffer.ipf_hit
6217052722fSJay
622a108d429SJay  val p3_hit_dir = VecInit((0 until nPrefetchEntries).map(i => prefetch_dir(i).valid && prefetch_dir(i).paddr === p3_paddr )).reduce(_||_)
623974a902cSguohongyu  //Cache miss handling by main pipe, info from mainpipe missslot
624974a902cSguohongyu  val p3_hit_mp_miss = VecInit((0 until PortNumber).map(i =>
625974a902cSguohongyu    mainPipeMissSlotInfo(i).valid && (mainPipeMissSlotInfo(i).bits.ptage === get_phy_tag(p3_paddr) &&
626974a902cSguohongyu    (mainPipeMissSlotInfo(i).bits.vSetIdx === p3_vidx)))).reduce(_||_)
627974a902cSguohongyu  val p3_req_cancel = /*p3_hit_dir ||*/ p3_check_in_mshr || !enableBit || p3_hit_mp_miss || p3_buffer_hit || io.fencei
628b1ded4e8Sguohongyu  p3_discard := p3_valid && p3_req_cancel
629a108d429SJay
630b1ded4e8Sguohongyu  toMissUnit.enqReq.valid := p3_valid && !p3_req_cancel
6317052722fSJay  toMissUnit.enqReq.bits.paddr := p3_paddr
632b1ded4e8Sguohongyu  toMissUnit.enqReq.bits.vSetIdx := p3_vidx
6337052722fSJay
634b1ded4e8Sguohongyu  when(io.fencei){
635b1ded4e8Sguohongyu    maxPrefetchCounter := 0.U
636a108d429SJay
637a108d429SJay    prefetch_dir.foreach(_.valid := false.B)
638a108d429SJay  }.elsewhen(toMissUnit.enqReq.fire()){
639974a902cSguohongyu//    when(reachMaxSize){
640974a902cSguohongyu//      prefetch_dir(io.freePIQEntry).paddr := p3_paddr
641974a902cSguohongyu//    }.otherwise {
642974a902cSguohongyu//      maxPrefetchCounter := maxPrefetchCounter + 1.U
643974a902cSguohongyu//
644974a902cSguohongyu//      prefetch_dir(maxPrefetchCounter).valid := true.B
645974a902cSguohongyu//      prefetch_dir(maxPrefetchCounter).paddr := p3_paddr
646974a902cSguohongyu//    }
647974a902cSguohongyu    // now prefetch_dir hold status for all PIQ
648b1ded4e8Sguohongyu    prefetch_dir(io.freePIQEntry).paddr := p3_paddr
649974a902cSguohongyu    prefetch_dir(io.freePIQEntry).valid := true.B
650a108d429SJay  }
651a108d429SJay
652a108d429SJay  p3_ready := toMissUnit.enqReq.ready || !enableBit
6537052722fSJay  p3_fire  := toMissUnit.enqReq.fire()
6547052722fSJay
6557052722fSJay}
6567052722fSJay
657b1ded4e8Sguohongyuclass PIQEntry(edge: TLEdgeOut, id: Int)(implicit p: Parameters) extends IPrefetchModule
6587052722fSJay{
6597052722fSJay  val io = IO(new Bundle{
660b1ded4e8Sguohongyu    val id          = Input(UInt((log2Ceil(nPrefetchEntries + PortNumber)).W))
6617052722fSJay
6627052722fSJay    val req         = Flipped(DecoupledIO(new PIQReq))
6637052722fSJay
664b1ded4e8Sguohongyu    val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle))
665b1ded4e8Sguohongyu    val mem_grant   = Flipped(DecoupledIO(new TLBundleD(edge.bundle)))
6667052722fSJay
667b1ded4e8Sguohongyu    //write back to Prefetch Buffer
668b1ded4e8Sguohongyu    val piq_write_ipbuffer = DecoupledIO(new IPFBufferWrite)
669b1ded4e8Sguohongyu
670b1ded4e8Sguohongyu    val fencei      = Input(Bool())
671b1ded4e8Sguohongyu
672b1ded4e8Sguohongyu    val prefetch_entry_data = DecoupledIO(new PIQData)
673974a902cSguohongyu
674974a902cSguohongyu    val ongoing_req    = ValidIO(UInt(PAddrBits.W))
6757052722fSJay  })
6767052722fSJay
677b1ded4e8Sguohongyu  val s_idle :: s_memReadReq :: s_memReadResp :: s_write_back :: s_finish:: Nil = Enum(5)
6787052722fSJay  val state = RegInit(s_idle)
6797052722fSJay
680b1ded4e8Sguohongyu  //req register
681b1ded4e8Sguohongyu  val req = Reg(new PIQReq)
682b1ded4e8Sguohongyu  val req_idx = req.vSetIdx                     //virtual index
683b1ded4e8Sguohongyu  val req_tag = get_phy_tag(req.paddr)           //physical tag
684b1ded4e8Sguohongyu
685b1ded4e8Sguohongyu  val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant)
686b1ded4e8Sguohongyu
687b1ded4e8Sguohongyu  //8 for 64 bits bus and 2 for 256 bits
688b1ded4e8Sguohongyu  val readBeatCnt = Reg(UInt(log2Up(refillCycles).W))
689b1ded4e8Sguohongyu  val respDataReg = Reg(Vec(refillCycles,UInt(beatBits.W)))
690b1ded4e8Sguohongyu
691b1ded4e8Sguohongyu  //to main pipe s1
692b1ded4e8Sguohongyu  io.prefetch_entry_data.valid := state =/= s_idle
693b1ded4e8Sguohongyu  io.prefetch_entry_data.bits.vSetIdx := req_idx
694b1ded4e8Sguohongyu  io.prefetch_entry_data.bits.ptage := req_tag
695b1ded4e8Sguohongyu  io.prefetch_entry_data.bits.cacheline := respDataReg.asUInt
696b1ded4e8Sguohongyu  io.prefetch_entry_data.bits.writeBack := state === s_write_back
697b1ded4e8Sguohongyu
698b1ded4e8Sguohongyu  //initial
699b1ded4e8Sguohongyu  io.mem_acquire.bits := DontCare
700b1ded4e8Sguohongyu  io.mem_grant.ready := true.B
701b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits:= DontCare
702b1ded4e8Sguohongyu
703b1ded4e8Sguohongyu  io.req.ready := state === s_idle
704b1ded4e8Sguohongyu  io.mem_acquire.valid := state === s_memReadReq
705b1ded4e8Sguohongyu
7062a6078bfSguohongyu  val needflush_r = RegInit(false.B)
7072a6078bfSguohongyu  when (state === s_idle) { needflush_r := false.B }
7082a6078bfSguohongyu  when (state =/= s_idle && io.fencei) { needflush_r := true.B }
7092a6078bfSguohongyu  val needflush = needflush_r | io.fencei
7107052722fSJay
7117052722fSJay  //state change
7127052722fSJay  switch(state){
7137052722fSJay    is(s_idle){
7147052722fSJay      when(io.req.fire()){
715b1ded4e8Sguohongyu        readBeatCnt := 0.U
716b1ded4e8Sguohongyu        state := s_memReadReq
7177052722fSJay        req := io.req.bits
7187052722fSJay      }
7197052722fSJay    }
7207052722fSJay
7217052722fSJay    // memory request
722b1ded4e8Sguohongyu    is(s_memReadReq){
723b1ded4e8Sguohongyu      when(io.mem_acquire.fire()){
724b1ded4e8Sguohongyu        state := s_memReadResp
725b1ded4e8Sguohongyu      }
726b1ded4e8Sguohongyu    }
727b1ded4e8Sguohongyu
728b1ded4e8Sguohongyu    is(s_memReadResp){
729b1ded4e8Sguohongyu      when (edge.hasData(io.mem_grant.bits)) {
730b1ded4e8Sguohongyu        when (io.mem_grant.fire()) {
731b1ded4e8Sguohongyu          readBeatCnt := readBeatCnt + 1.U
732b1ded4e8Sguohongyu          respDataReg(readBeatCnt) := io.mem_grant.bits.data
733b1ded4e8Sguohongyu          when (readBeatCnt === (refillCycles - 1).U) {
734b1ded4e8Sguohongyu            assert(refill_done, "refill not done!")
735b1ded4e8Sguohongyu            state := s_write_back
736b1ded4e8Sguohongyu          }
737b1ded4e8Sguohongyu        }
738b1ded4e8Sguohongyu      }
739b1ded4e8Sguohongyu    }
740b1ded4e8Sguohongyu
741b1ded4e8Sguohongyu    is(s_write_back){
7422a6078bfSguohongyu      state := Mux(io.piq_write_ipbuffer.fire() || needflush, s_finish, s_write_back)
743b1ded4e8Sguohongyu    }
744b1ded4e8Sguohongyu
745b1ded4e8Sguohongyu    is(s_finish){
7467052722fSJay      state := s_idle
7477052722fSJay    }
7487052722fSJay  }
7497052722fSJay
750b1ded4e8Sguohongyu  //refill write and meta write
751b1ded4e8Sguohongyu  //WARNING: Maybe could not finish refill in 1 cycle
7522a6078bfSguohongyu  io.piq_write_ipbuffer.valid := (state === s_write_back) && !needflush
753b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.meta.tag := req_tag
754b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.meta.index := req_idx
755b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.meta.paddr := req.paddr
756b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.data := respDataReg.asUInt
757b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.buffIdx := io.id - PortNumber.U
7587052722fSJay
759974a902cSguohongyu  io.ongoing_req.valid := state =/= s_idle
760974a902cSguohongyu  io.ongoing_req.bits := addrAlign(req.paddr, blockBytes, PAddrBits)
761974a902cSguohongyu
7627052722fSJay  XSPerfAccumulate("PrefetchEntryReq" + Integer.toString(id, 10), io.req.fire())
7637052722fSJay
764b1ded4e8Sguohongyu  //mem request
765b1ded4e8Sguohongyu  io.mem_acquire.bits  := edge.Get(
766b1ded4e8Sguohongyu    fromSource      = io.id,
767b1ded4e8Sguohongyu    toAddress       = Cat(req.paddr(PAddrBits - 1, log2Ceil(blockBytes)), 0.U(log2Ceil(blockBytes).W)),
768b1ded4e8Sguohongyu    lgSize          = (log2Up(cacheParams.blockBytes)).U)._2
769*d2b20d1aSTang Haojin  io.mem_acquire.bits.user.lift(PreferCacheKey).foreach(_ := true.B)
770*d2b20d1aSTang Haojin  io.mem_acquire.bits.user.lift(ReqSourceKey).foreach(_ := MemReqSource.L1InstPrefetch.id.U)
771b1ded4e8Sguohongyu
7727052722fSJay}
773