xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala (revision b1ded4e8375ab58ac87a32698bfab53120d706f6)
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._
227052722fSJayimport freechips.rocketchip.tilelink._
237052722fSJayimport utils._
247052722fSJayimport xiangshan.cache.mmu._
257052722fSJayimport xiangshan.frontend._
26*b1ded4e8Sguohongyuimport utility._
277052722fSJay
287052722fSJay
297052722fSJayabstract class IPrefetchBundle(implicit p: Parameters) extends ICacheBundle
307052722fSJayabstract class IPrefetchModule(implicit p: Parameters) extends ICacheModule
317052722fSJay
32*b1ded4e8Sguohongyu//TODO: remove this
33*b1ded4e8Sguohongyuobject DebugFlags {
34*b1ded4e8Sguohongyu  val fdip = false
357052722fSJay}
367052722fSJay
37*b1ded4e8Sguohongyuclass PIQReq(implicit p: Parameters) extends IPrefetchBundle {
38*b1ded4e8Sguohongyu  val paddr      = UInt(PAddrBits.W)
39*b1ded4e8Sguohongyu  val vSetIdx   = UInt(idxBits.W)
40*b1ded4e8Sguohongyu}
41*b1ded4e8Sguohongyu
42*b1ded4e8Sguohongyuclass PIQData(implicit p: Parameters) extends IPrefetchBundle {
43*b1ded4e8Sguohongyu  val ptage = UInt(tagBits.W)
44*b1ded4e8Sguohongyu  val vSetIdx = UInt(idxBits.W)
45*b1ded4e8Sguohongyu  val cacheline = UInt(blockBits.W)
46*b1ded4e8Sguohongyu  val writeBack = Bool()
47*b1ded4e8Sguohongyu}
48*b1ded4e8Sguohongyu
49*b1ded4e8Sguohongyuclass PIQToMainPipe(implicit  p: Parameters) extends IPrefetchBundle{
50*b1ded4e8Sguohongyu  val info = DecoupledIO(new PIQData)
51*b1ded4e8Sguohongyu}
52*b1ded4e8Sguohongyu/* need change name */
53*b1ded4e8Sguohongyuclass MainPipeToPrefetchPipe(implicit p: Parameters) extends IPrefetchBundle {
54*b1ded4e8Sguohongyu  val ptage = UInt(tagBits.W)
55*b1ded4e8Sguohongyu  val vSetIdx = UInt(idxBits.W)
56*b1ded4e8Sguohongyu}
57*b1ded4e8Sguohongyu
58*b1ded4e8Sguohongyuclass MainPipeMissInfo(implicit p: Parameters) extends IPrefetchBundle {
59*b1ded4e8Sguohongyu  val s1_already_check_ipf = Output(Bool())
60*b1ded4e8Sguohongyu  val s2_miss_info = Vec(PortNumber, ValidIO(new MainPipeToPrefetchPipe))
61*b1ded4e8Sguohongyu}
627052722fSJay
637052722fSJayclass IPrefetchToMissUnit(implicit  p: Parameters) extends IPrefetchBundle{
647052722fSJay  val enqReq  = DecoupledIO(new PIQReq)
657052722fSJay}
667052722fSJay
677052722fSJayclass IPredfetchIO(implicit p: Parameters) extends IPrefetchBundle {
687052722fSJay  val fromFtq         = Flipped(new FtqPrefechBundle)
69f1fe8698SLemover  val iTLBInter       = new TlbRequestIO
7061e1db30SJay  val pmp             =   new ICachePMPBundle
71*b1ded4e8Sguohongyu  val toIMeta         = Decoupled(new ICacheReadBundle)
727052722fSJay  val fromIMeta       = Input(new ICacheMetaRespBundle)
737052722fSJay  val toMissUnit      = new IPrefetchToMissUnit
74*b1ded4e8Sguohongyu  val freePIQEntry    = Input(UInt(log2Ceil(nPrefetchEntries).W))
7500240ba6SJay  val fromMSHR        = Flipped(Vec(PortNumber,ValidIO(UInt(PAddrBits.W))))
76*b1ded4e8Sguohongyu  val IPFBufferRead   = Flipped(new IPFBufferFilterRead)
77*b1ded4e8Sguohongyu  /** icache main pipe to prefetch pipe*/
78*b1ded4e8Sguohongyu  val fromMainPipe    = Flipped(Vec(PortNumber,ValidIO(new MainPipeToPrefetchPipe)))
79a108d429SJay
80a108d429SJay  val prefetchEnable = Input(Bool())
81a108d429SJay  val prefetchDisable = Input(Bool())
82*b1ded4e8Sguohongyu  val fencei         = Input(Bool())
83*b1ded4e8Sguohongyu}
84*b1ded4e8Sguohongyu
85*b1ded4e8Sguohongyu/** Prefetch Buffer **/
86*b1ded4e8Sguohongyu
87*b1ded4e8Sguohongyu
88*b1ded4e8Sguohongyuclass PrefetchBuffer(implicit p: Parameters) extends IPrefetchModule
89*b1ded4e8Sguohongyu{
90*b1ded4e8Sguohongyu  val io = IO(new Bundle{
91*b1ded4e8Sguohongyu    val read  = new IPFBufferRead
92*b1ded4e8Sguohongyu    val filter_read = new IPFBufferFilterRead
93*b1ded4e8Sguohongyu    val write = Flipped(ValidIO(new IPFBufferWrite))
94*b1ded4e8Sguohongyu    /** to ICache replacer */
95*b1ded4e8Sguohongyu    val replace = new IPFBufferMove
96*b1ded4e8Sguohongyu    /** move & move filter port */
97*b1ded4e8Sguohongyu    val mainpipe_missinfo = Flipped(new MainPipeMissInfo)
98*b1ded4e8Sguohongyu    val meta_filter_read = new ICacheMetaReqBundle
99*b1ded4e8Sguohongyu    val move  = new Bundle() {
100*b1ded4e8Sguohongyu      val meta_write = DecoupledIO(new ICacheMetaWriteBundle)
101*b1ded4e8Sguohongyu      val data_write = DecoupledIO(new ICacheDataWriteBundle)
102*b1ded4e8Sguohongyu    }
103*b1ded4e8Sguohongyu    val fencei = Input(Bool())
104*b1ded4e8Sguohongyu  })
105*b1ded4e8Sguohongyu
106*b1ded4e8Sguohongyu  class IPFBufferEntryMeta(implicit p: Parameters) extends IPrefetchBundle
107*b1ded4e8Sguohongyu  {
108*b1ded4e8Sguohongyu    val tag = UInt(tagBits.W)
109*b1ded4e8Sguohongyu    val index = UInt(idxBits.W)
110*b1ded4e8Sguohongyu    val paddr = UInt(PAddrBits.W)
111*b1ded4e8Sguohongyu    val valid = Bool()
112*b1ded4e8Sguohongyu    val confidence = UInt(log2Ceil(maxIPFMoveConf + 1).W)
113*b1ded4e8Sguohongyu    val move = Bool()
114*b1ded4e8Sguohongyu  }
115*b1ded4e8Sguohongyu
116*b1ded4e8Sguohongyu  class IPFBufferEntryData(implicit p: Parameters) extends IPrefetchBundle
117*b1ded4e8Sguohongyu  {
118*b1ded4e8Sguohongyu    val cachline = UInt(blockBits.W)
119*b1ded4e8Sguohongyu  }
120*b1ded4e8Sguohongyu
121*b1ded4e8Sguohongyu  def InitQueue[T <: Data](entry: T, size: Int): Vec[T] ={
122*b1ded4e8Sguohongyu    return RegInit(VecInit(Seq.fill(size)(0.U.asTypeOf(entry.cloneType))))
123*b1ded4e8Sguohongyu  }
124*b1ded4e8Sguohongyu
125*b1ded4e8Sguohongyu  val meta_buffer = InitQueue(new IPFBufferEntryMeta, size = nIPFBufferSize)
126*b1ded4e8Sguohongyu  val data_buffer = InitQueue(new IPFBufferEntryData, size = nIPFBufferSize)
127*b1ded4e8Sguohongyu
128*b1ded4e8Sguohongyu  /** filter read logic */
129*b1ded4e8Sguohongyu  val fr_vidx = io.filter_read.req.vSetIdx
130*b1ded4e8Sguohongyu  val fr_ptag = get_phy_tag(io.filter_read.req.paddr)
131*b1ded4e8Sguohongyu
132*b1ded4e8Sguohongyu  val fr_hit_in_buffer = meta_buffer.map(e => e.valid && (e.tag === fr_ptag) && (e.index === fr_vidx)).reduce(_||_)
133*b1ded4e8Sguohongyu  val fr_hit_in_s1, fr_hit_in_s2, fr_hit_in_s3 = Wire(Bool())
134*b1ded4e8Sguohongyu
135*b1ded4e8Sguohongyu  io.filter_read.resp.ipf_hit := fr_hit_in_buffer || fr_hit_in_s1 || fr_hit_in_s2 || fr_hit_in_s3
136*b1ded4e8Sguohongyu
137*b1ded4e8Sguohongyu  /** read logic */
138*b1ded4e8Sguohongyu  (0 until PortNumber).foreach(i => io.read.req(i).ready := true.B)
139*b1ded4e8Sguohongyu  val r_valid = VecInit((0 until PortNumber).map( i => io.read.req(i).valid)).reduce(_||_)
140*b1ded4e8Sguohongyu  val r_vidx = VecInit((0 until PortNumber).map(i => get_idx(io.read.req(i).bits.vaddr)))
141*b1ded4e8Sguohongyu  val r_ptag = VecInit((0 until PortNumber).map(i => get_phy_tag(io.read.req(i).bits.paddr)))
142*b1ded4e8Sguohongyu  val r_hit_oh = VecInit((0 until PortNumber).map(i =>
143*b1ded4e8Sguohongyu    VecInit(meta_buffer.map(entry =>
144*b1ded4e8Sguohongyu      io.read.req(i).valid && // need this condition
145*b1ded4e8Sguohongyu        entry.valid &&
146*b1ded4e8Sguohongyu        entry.tag === r_ptag(i) &&
147*b1ded4e8Sguohongyu        entry.index === r_vidx(i)
148*b1ded4e8Sguohongyu    ))))
149*b1ded4e8Sguohongyu  val r_buffer_hit = VecInit(r_hit_oh.map(_.reduce(_||_)))
150*b1ded4e8Sguohongyu  val r_buffer_hit_idx = VecInit(r_hit_oh.map(PriorityEncoder(_)))
151*b1ded4e8Sguohongyu  val r_buffer_hit_data = VecInit((0 until PortNumber).map(i => Mux1H(r_hit_oh(i), data_buffer.map(_.cachline))))
152*b1ded4e8Sguohongyu
153*b1ded4e8Sguohongyu  /** "read" also check data in move pipeline */
154*b1ded4e8Sguohongyu  val r_moves1pipe_hit_s1, r_moves1pipe_hit_s2, r_moves1pipe_hit_s3 = WireInit(VecInit(Seq.fill(PortNumber)(false.B)))
155*b1ded4e8Sguohongyu  val s1_move_data_cacheline, s2_move_data_cacheline, s3_move_data_cacheline = Wire(UInt(blockBits.W))
156*b1ded4e8Sguohongyu
157*b1ded4e8Sguohongyu  (0 until PortNumber).foreach{ i =>
158*b1ded4e8Sguohongyu    io.read.resp(i).valid := io.read.req(i).valid
159*b1ded4e8Sguohongyu    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)
160*b1ded4e8Sguohongyu    io.read.resp(i).bits.cacheline := Mux(r_buffer_hit(i), r_buffer_hit_data(i),
161*b1ded4e8Sguohongyu      Mux(r_moves1pipe_hit_s1(i), s1_move_data_cacheline,
162*b1ded4e8Sguohongyu        Mux(r_moves1pipe_hit_s2(i), s2_move_data_cacheline, s3_move_data_cacheline)))
163*b1ded4e8Sguohongyu  }
164*b1ded4e8Sguohongyu
165*b1ded4e8Sguohongyu  /** move logic */
166*b1ded4e8Sguohongyu  val r_buffer_hit_s2     = RegNext(r_buffer_hit, init=0.U.asTypeOf(r_buffer_hit.cloneType))
167*b1ded4e8Sguohongyu  val r_buffer_hit_idx_s2 = RegNext(r_buffer_hit_idx)
168*b1ded4e8Sguohongyu  val r_rvalid_s2         = RegNext(r_valid, init=false.B)
169*b1ded4e8Sguohongyu
170*b1ded4e8Sguohongyu  val s2_move_valid_0 = r_rvalid_s2 && r_buffer_hit_s2(0)
171*b1ded4e8Sguohongyu  val s2_move_valid_1 = r_rvalid_s2 && r_buffer_hit_s2(1)
172*b1ded4e8Sguohongyu
173*b1ded4e8Sguohongyu  XSPerfAccumulate("prefetch_hit_bank_0", r_rvalid_s2 && r_buffer_hit_s2(0))
174*b1ded4e8Sguohongyu  XSPerfAccumulate("prefetch_hit_bank_1", r_rvalid_s2 && r_buffer_hit_s2(1))
175*b1ded4e8Sguohongyu
176*b1ded4e8Sguohongyu  val move_queue    = RegInit(VecInit(Seq.fill(nIPFBufferSize)(0.U.asTypeOf(r_buffer_hit_idx_s2(0)))))
177*b1ded4e8Sguohongyu
178*b1ded4e8Sguohongyu  val curr_move_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W))
179*b1ded4e8Sguohongyu  val curr_hit_ptr  = RegInit(0.U(log2Ceil(nIPFBufferSize).W))
180*b1ded4e8Sguohongyu
181*b1ded4e8Sguohongyu  val s2_move_conf_full_0 = meta_buffer(r_buffer_hit_idx_s2(0)).confidence === (maxIPFMoveConf).U
182*b1ded4e8Sguohongyu  val s2_move_conf_full_1 = meta_buffer(r_buffer_hit_idx_s2(1)).confidence === (maxIPFMoveConf).U
183*b1ded4e8Sguohongyu
184*b1ded4e8Sguohongyu  val move_repeat_0 = meta_buffer(r_buffer_hit_idx_s2(0)).move
185*b1ded4e8Sguohongyu  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))
186*b1ded4e8Sguohongyu
187*b1ded4e8Sguohongyu  val s2_move_0 = s2_move_valid_0 && !move_repeat_0
188*b1ded4e8Sguohongyu  val s2_move_1 = s2_move_valid_1 && !move_repeat_1
189*b1ded4e8Sguohongyu
190*b1ded4e8Sguohongyu  val s2_move_enqueue_0 = s2_move_0 && s2_move_conf_full_0
191*b1ded4e8Sguohongyu  val s2_move_enqueue_1 = s2_move_1 && s2_move_conf_full_1
192*b1ded4e8Sguohongyu
193*b1ded4e8Sguohongyu  when(s2_move_0) {
194*b1ded4e8Sguohongyu    when(s2_move_conf_full_0) {
195*b1ded4e8Sguohongyu      meta_buffer(r_buffer_hit_idx_s2(0)).move := true.B
196*b1ded4e8Sguohongyu    }.otherwise {
197*b1ded4e8Sguohongyu      meta_buffer(r_buffer_hit_idx_s2(0)).confidence := meta_buffer(r_buffer_hit_idx_s2(0)).confidence + 1.U
198*b1ded4e8Sguohongyu    }
199*b1ded4e8Sguohongyu  }
200*b1ded4e8Sguohongyu  when(s2_move_1) {
201*b1ded4e8Sguohongyu    when(s2_move_conf_full_1) {
202*b1ded4e8Sguohongyu      meta_buffer(r_buffer_hit_idx_s2(1)).move := true.B
203*b1ded4e8Sguohongyu    }.otherwise {
204*b1ded4e8Sguohongyu      meta_buffer(r_buffer_hit_idx_s2(1)).confidence := meta_buffer(r_buffer_hit_idx_s2(1)).confidence + 1.U
205*b1ded4e8Sguohongyu    }
206*b1ded4e8Sguohongyu  }
207*b1ded4e8Sguohongyu
208*b1ded4e8Sguohongyu  when(s2_move_enqueue_0 && !s2_move_enqueue_1) {
209*b1ded4e8Sguohongyu    move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0)
210*b1ded4e8Sguohongyu
211*b1ded4e8Sguohongyu    when((curr_hit_ptr + 1.U) =/= curr_move_ptr){
212*b1ded4e8Sguohongyu      curr_hit_ptr := curr_hit_ptr + 1.U
213*b1ded4e8Sguohongyu    }
214*b1ded4e8Sguohongyu  }.elsewhen(!s2_move_enqueue_0 && s2_move_enqueue_1) {
215*b1ded4e8Sguohongyu    move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(1)
216*b1ded4e8Sguohongyu
217*b1ded4e8Sguohongyu    when((curr_hit_ptr + 1.U) =/= curr_move_ptr){
218*b1ded4e8Sguohongyu      curr_hit_ptr := curr_hit_ptr + 1.U
219*b1ded4e8Sguohongyu    }
220*b1ded4e8Sguohongyu  }.elsewhen(s2_move_enqueue_0 && s2_move_enqueue_1) {
221*b1ded4e8Sguohongyu    move_queue(curr_hit_ptr) := r_buffer_hit_idx_s2(0)
222*b1ded4e8Sguohongyu    move_queue(curr_hit_ptr + 1.U) := r_buffer_hit_idx_s2(1)
223*b1ded4e8Sguohongyu    when((curr_hit_ptr + 2.U) =/= curr_move_ptr){
224*b1ded4e8Sguohongyu      curr_hit_ptr := curr_hit_ptr + 2.U
225*b1ded4e8Sguohongyu    }.otherwise{
226*b1ded4e8Sguohongyu      curr_hit_ptr := curr_hit_ptr + 1.U
227*b1ded4e8Sguohongyu    }
228*b1ded4e8Sguohongyu  }
229*b1ded4e8Sguohongyu
230*b1ded4e8Sguohongyu  val move_queue_empty = curr_move_ptr === curr_hit_ptr
231*b1ded4e8Sguohongyu  /** pipeline control signal */
232*b1ded4e8Sguohongyu  val s1_ready, s2_ready, s3_ready = Wire(Bool())
233*b1ded4e8Sguohongyu  val s0_fire, s1_fire, s2_fire, s3_fire = Wire(Bool())
234*b1ded4e8Sguohongyu
235*b1ded4e8Sguohongyu  /** stage 0 */
236*b1ded4e8Sguohongyu  val s0_valid        = !move_queue_empty && meta_buffer(move_queue(curr_move_ptr)).move
237*b1ded4e8Sguohongyu
238*b1ded4e8Sguohongyu  val s0_move_idx     = move_queue(curr_move_ptr)
239*b1ded4e8Sguohongyu  val s0_move_meta    = meta_buffer(s0_move_idx)
240*b1ded4e8Sguohongyu  val s0_move_data    = data_buffer(s0_move_idx)
241*b1ded4e8Sguohongyu  io.replace.vsetIdx  := meta_buffer(s0_move_idx).index
242*b1ded4e8Sguohongyu  val s0_waymask      = io.replace.waymask
243*b1ded4e8Sguohongyu
244*b1ded4e8Sguohongyu  s0_fire             := s0_valid && s1_ready
245*b1ded4e8Sguohongyu
246*b1ded4e8Sguohongyu  /** curr_move_ptr control logic */
247*b1ded4e8Sguohongyu  val s0_move_jump = !move_queue_empty && !meta_buffer(move_queue(curr_move_ptr)).move
248*b1ded4e8Sguohongyu  when (s0_fire) {
249*b1ded4e8Sguohongyu    curr_move_ptr := curr_move_ptr + 1.U
250*b1ded4e8Sguohongyu    meta_buffer(s0_move_idx).valid := false.B
251*b1ded4e8Sguohongyu    meta_buffer(s0_move_idx).move  := false.B
252*b1ded4e8Sguohongyu    meta_buffer(s0_move_idx).confidence := 0.U
253*b1ded4e8Sguohongyu  }.elsewhen(s0_move_jump) {
254*b1ded4e8Sguohongyu    curr_move_ptr := curr_move_ptr + 1.U
255*b1ded4e8Sguohongyu  }
256*b1ded4e8Sguohongyu
257*b1ded4e8Sguohongyu  /** stage 1 : send req to metaArray */
258*b1ded4e8Sguohongyu  val s1_valid        = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = io.fencei, lastFlush = false.B)
259*b1ded4e8Sguohongyu
260*b1ded4e8Sguohongyu  val s1_move_idx     = RegEnable(s0_move_idx, s0_fire)
261*b1ded4e8Sguohongyu  val s1_move_meta    = RegEnable(s0_move_meta, s0_fire)
262*b1ded4e8Sguohongyu  val s1_move_data    = RegEnable(s0_move_data, s0_fire)
263*b1ded4e8Sguohongyu  val s1_waymask      = RegEnable(s0_waymask, s0_fire)
264*b1ded4e8Sguohongyu
265*b1ded4e8Sguohongyu  io.meta_filter_read.toIMeta.valid             := s1_valid
266*b1ded4e8Sguohongyu  io.meta_filter_read.toIMeta.bits.isDoubleLine := false.B
267*b1ded4e8Sguohongyu  io.meta_filter_read.toIMeta.bits.vSetIdx(0)   := s1_move_meta.index // just use port 0
268*b1ded4e8Sguohongyu  io.meta_filter_read.toIMeta.bits.vSetIdx(1)   := DontCare
269*b1ded4e8Sguohongyu
270*b1ded4e8Sguohongyu  s1_ready            := !s1_valid || s1_fire
271*b1ded4e8Sguohongyu  s1_fire             := s1_valid && io.meta_filter_read.toIMeta.ready && s2_ready
272*b1ded4e8Sguohongyu
273*b1ded4e8Sguohongyu  fr_hit_in_s1 := s1_valid && s1_move_meta.index === fr_vidx && s1_move_meta.tag === fr_ptag
274*b1ded4e8Sguohongyu  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))
275*b1ded4e8Sguohongyu  s1_move_data_cacheline := s1_move_data.cachline
276*b1ded4e8Sguohongyu
277*b1ded4e8Sguohongyu  /** stage 2 : collect message from metaArray and mainPipe to filter */
278*b1ded4e8Sguohongyu  val s2_valid        = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = io.fencei, lastFlush = false.B)
279*b1ded4e8Sguohongyu
280*b1ded4e8Sguohongyu  val s2_move_idx     = RegEnable(s1_move_idx, s1_fire)
281*b1ded4e8Sguohongyu  val s2_move_meta    = RegEnable(s1_move_meta, s1_fire)
282*b1ded4e8Sguohongyu  val s2_move_data    = RegEnable(s1_move_data, s1_fire)
283*b1ded4e8Sguohongyu  val s2_waymask      = RegEnable(s1_waymask, s1_fire)
284*b1ded4e8Sguohongyu
285*b1ded4e8Sguohongyu  val s2_meta_ptags   = ResultHoldBypass(data = io.meta_filter_read.fromIMeta.tags, valid = RegNext(s1_fire))
286*b1ded4e8Sguohongyu  val s2_meta_valids  = ResultHoldBypass(data = io.meta_filter_read.fromIMeta.entryValid, valid = RegNext(s1_fire))
287*b1ded4e8Sguohongyu
288*b1ded4e8Sguohongyu  val s2_tag_eq_vec = VecInit((0 until nWays).map(w => s2_meta_ptags(0)(w) === s2_move_meta.tag)) // just use port 0
289*b1ded4e8Sguohongyu  val s2_tag_match_vec = VecInit(s2_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s2_meta_valids(0)(w)})
290*b1ded4e8Sguohongyu  val s2_hit_in_meta_array = ParallelOR(s2_tag_match_vec)
291*b1ded4e8Sguohongyu
292*b1ded4e8Sguohongyu  val main_s2_missinfo = io.mainpipe_missinfo.s2_miss_info
293*b1ded4e8Sguohongyu  val s2_hit_main_s2_missreq = VecInit((0 until PortNumber).map(i =>
294*b1ded4e8Sguohongyu    main_s2_missinfo(i).valid && s2_move_meta.index === main_s2_missinfo(i).bits.vSetIdx
295*b1ded4e8Sguohongyu      && s2_move_meta.tag === main_s2_missinfo(i).bits.ptage)).reduce(_||_)
296*b1ded4e8Sguohongyu
297*b1ded4e8Sguohongyu  val s2_discard        = s2_hit_in_meta_array || s2_hit_main_s2_missreq // || s2_hit_main_s1_missreq
298*b1ded4e8Sguohongyu  val s2_discard_latch  = holdReleaseLatch(valid = s2_discard, release = s2_fire, flush = io.fencei)
299*b1ded4e8Sguohongyu  if(DebugFlags.fdip){
300*b1ded4e8Sguohongyu    when (s2_fire && s2_discard_latch) {
301*b1ded4e8Sguohongyu      printf("<%d> IPrefetchBuffer: s2_discard : hit_in_meta_array=%d,hit_in_main_s2=%d, ptag=0x%x\n",
302*b1ded4e8Sguohongyu        GTimer(), s2_hit_in_meta_array, s2_hit_main_s2_missreq, s2_move_meta.tag)
303*b1ded4e8Sguohongyu    }
304*b1ded4e8Sguohongyu  }
305*b1ded4e8Sguohongyu
306*b1ded4e8Sguohongyu  s2_ready := !s2_valid || s2_fire
307*b1ded4e8Sguohongyu  s2_fire := s2_valid && s3_ready && io.mainpipe_missinfo.s1_already_check_ipf
308*b1ded4e8Sguohongyu
309*b1ded4e8Sguohongyu  fr_hit_in_s2 := s2_valid && s2_move_meta.index === fr_vidx && s2_move_meta.tag === fr_ptag
310*b1ded4e8Sguohongyu  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))
311*b1ded4e8Sguohongyu  s2_move_data_cacheline := s2_move_data.cachline
312*b1ded4e8Sguohongyu
313*b1ded4e8Sguohongyu  /** stage 3 : move data to metaArray and dataArray */
314*b1ded4e8Sguohongyu  val s3_valid = generatePipeControl(lastFire = s2_fire, thisFire = s3_fire, thisFlush = io.fencei, lastFlush = false.B)
315*b1ded4e8Sguohongyu
316*b1ded4e8Sguohongyu  val s3_move_idx = RegEnable(s2_move_idx, s2_fire)
317*b1ded4e8Sguohongyu  val s3_move_meta = RegEnable(s2_move_meta, s2_fire)
318*b1ded4e8Sguohongyu  val s3_move_data = RegEnable(s2_move_data, s2_fire)
319*b1ded4e8Sguohongyu  val s3_waymask = RegEnable(s2_waymask, s2_fire)
320*b1ded4e8Sguohongyu  val s3_discard = RegEnable(s2_discard_latch, s2_fire)
321*b1ded4e8Sguohongyu
322*b1ded4e8Sguohongyu  io.move.meta_write.valid := s3_valid && !s3_discard && !io.fencei
323*b1ded4e8Sguohongyu  io.move.data_write.valid := s3_valid && !s3_discard && !io.fencei
324*b1ded4e8Sguohongyu  io.move.meta_write.bits.generate(
325*b1ded4e8Sguohongyu    tag = s3_move_meta.tag,
326*b1ded4e8Sguohongyu    idx = s3_move_meta.index,
327*b1ded4e8Sguohongyu    waymask = s3_waymask,
328*b1ded4e8Sguohongyu    bankIdx = s3_move_meta.index(0))
329*b1ded4e8Sguohongyu  io.move.data_write.bits.generate(
330*b1ded4e8Sguohongyu    data = s3_move_data.cachline,
331*b1ded4e8Sguohongyu    idx = s3_move_meta.index,
332*b1ded4e8Sguohongyu    waymask = s3_waymask,
333*b1ded4e8Sguohongyu    bankIdx = s3_move_meta.index(0),
334*b1ded4e8Sguohongyu    paddr = s3_move_meta.paddr)
335*b1ded4e8Sguohongyu
336*b1ded4e8Sguohongyu  s3_ready := !s3_valid || s3_fire
337*b1ded4e8Sguohongyu  s3_fire := io.move.meta_write.fire && io.move.data_write.fire || s3_discard || io.fencei
338*b1ded4e8Sguohongyu  assert((io.move.meta_write.fire && io.move.data_write.fire) || (!io.move.meta_write.fire && !io.move.data_write.fire),
339*b1ded4e8Sguohongyu    "meta and data array need fire at same time")
340*b1ded4e8Sguohongyu
341*b1ded4e8Sguohongyu  fr_hit_in_s3 := s3_valid && s3_move_meta.index === fr_vidx && s3_move_meta.tag === fr_ptag
342*b1ded4e8Sguohongyu  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))
343*b1ded4e8Sguohongyu  s3_move_data_cacheline := s3_move_data.cachline
344*b1ded4e8Sguohongyu
345*b1ded4e8Sguohongyu  if (DebugFlags.fdip) {
346*b1ded4e8Sguohongyu    when(io.move.meta_write.fire) {
347*b1ded4e8Sguohongyu      printf("<%d> IPrefetchBuffer: move data to meta sram:ptag=0x%x,vidx=0x%x,waymask=0x%x\n",
348*b1ded4e8Sguohongyu        GTimer(), s3_move_meta.tag,s3_move_meta.index,s3_waymask )
349*b1ded4e8Sguohongyu    }
350*b1ded4e8Sguohongyu  }
351*b1ded4e8Sguohongyu
352*b1ded4e8Sguohongyu  /** write logic */
353*b1ded4e8Sguohongyu  val replacer = ReplacementPolicy.fromString(Some("random"), nIPFBufferSize)
354*b1ded4e8Sguohongyu  val curr_write_ptr = RegInit(0.U(log2Ceil(nIPFBufferSize).W))
355*b1ded4e8Sguohongyu  val victim_way = curr_write_ptr + 1.U//replacer.way
356*b1ded4e8Sguohongyu
357*b1ded4e8Sguohongyu  when(io.write.valid) {
358*b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).tag := io.write.bits.meta.tag
359*b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).index := io.write.bits.meta.index
360*b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).paddr := io.write.bits.meta.paddr
361*b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).valid := true.B
362*b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).move  := false.B
363*b1ded4e8Sguohongyu    meta_buffer(curr_write_ptr).confidence := 0.U
364*b1ded4e8Sguohongyu
365*b1ded4e8Sguohongyu    data_buffer(curr_write_ptr).cachline := io.write.bits.data
366*b1ded4e8Sguohongyu
367*b1ded4e8Sguohongyu    //update replacer
368*b1ded4e8Sguohongyu    replacer.access(curr_write_ptr)
369*b1ded4e8Sguohongyu    curr_write_ptr := victim_way
370*b1ded4e8Sguohongyu
371*b1ded4e8Sguohongyu  }
372*b1ded4e8Sguohongyu
373*b1ded4e8Sguohongyu  /** fencei: invalid all entries */
374*b1ded4e8Sguohongyu  when(io.fencei) {
375*b1ded4e8Sguohongyu    meta_buffer.foreach{
376*b1ded4e8Sguohongyu      case b =>
377*b1ded4e8Sguohongyu        b.valid := false.B
378*b1ded4e8Sguohongyu        b.move := false.B
379*b1ded4e8Sguohongyu        b.confidence := 0.U
380*b1ded4e8Sguohongyu    }
381*b1ded4e8Sguohongyu  }
382*b1ded4e8Sguohongyu
3837052722fSJay}
3847052722fSJay
3857052722fSJayclass IPrefetchPipe(implicit p: Parameters) extends  IPrefetchModule
3867052722fSJay{
3877052722fSJay  val io = IO(new IPredfetchIO)
3887052722fSJay
389a108d429SJay  val enableBit = RegInit(false.B)
390*b1ded4e8Sguohongyu  val maxPrefetchCounter = RegInit(0.U(log2Ceil(nPrefetchEntries + 1).W))
391a108d429SJay
392*b1ded4e8Sguohongyu  val reachMaxSize = maxPrefetchCounter === nPrefetchEntries.U
393a108d429SJay
394*b1ded4e8Sguohongyu  // when(io.prefetchEnable){
395*b1ded4e8Sguohongyu  //   enableBit := true.B
396*b1ded4e8Sguohongyu  // }.elsewhen((enableBit && io.prefetchDisable) || (enableBit && reachMaxSize)){
397*b1ded4e8Sguohongyu  //   enableBit := false.B
398*b1ded4e8Sguohongyu  // }
399*b1ded4e8Sguohongyu  // ignore prefetchEnable from ICacheMainPipe
400a108d429SJay  enableBit := true.B
401a108d429SJay
402a108d429SJay  class PrefetchDir(implicit  p: Parameters) extends IPrefetchBundle
403a108d429SJay  {
404a108d429SJay    val valid = Bool()
405a108d429SJay    val paddr = UInt(PAddrBits.W)
406a108d429SJay  }
407a108d429SJay
408a108d429SJay  val prefetch_dir = RegInit(VecInit(Seq.fill(nPrefetchEntries)(0.U.asTypeOf(new PrefetchDir))))
409a108d429SJay
4107052722fSJay  val fromFtq = io.fromFtq
411*b1ded4e8Sguohongyu  val fromMainPipe = io.fromMainPipe
4127052722fSJay  val (toITLB,  fromITLB) = (io.iTLBInter.req, io.iTLBInter.resp)
413c3b763d0SYinan Xu  io.iTLBInter.req_kill := false.B
414*b1ded4e8Sguohongyu  val (toIMeta, fromIMeta, fromIMetaValid) = (io.toIMeta, io.fromIMeta.metaData(0), io.fromIMeta.entryValid(0))
415*b1ded4e8Sguohongyu  val (toIPFBuffer, fromIPFBuffer) = (io.IPFBufferRead.req, io.IPFBufferRead.resp)
4167052722fSJay  val (toPMP,  fromPMP)   = (io.pmp.req, io.pmp.resp)
4177052722fSJay  val toMissUnit = io.toMissUnit
4187052722fSJay
4197052722fSJay  val p0_fire, p1_fire, p2_fire, p3_fire =  WireInit(false.B)
420*b1ded4e8Sguohongyu  val p0_discard, p1_discard, p2_discard, p3_discard = WireInit(false.B)
4217052722fSJay  val p0_ready, p1_ready, p2_ready, p3_ready = WireInit(false.B)
4227052722fSJay
4237052722fSJay  /** Prefetch Stage 0: req from Ftq */
4247052722fSJay  val p0_valid  =   fromFtq.req.valid
425d6b06a99SJay  val p0_vaddr  =   addrAlign(fromFtq.req.bits.target, blockBytes, VAddrBits)
426*b1ded4e8Sguohongyu  val p0_vaddr_reg = RegEnable(p0_vaddr, fromFtq.req.fire())
4277052722fSJay
428*b1ded4e8Sguohongyu  /* Cancel request when prefetch not enable
429*b1ded4e8Sguohongyu   * or the request from FTQ is same as last time */
430*b1ded4e8Sguohongyu  val p0_req_cancel = !enableBit || (p0_vaddr === p0_vaddr_reg) || io.fencei
431*b1ded4e8Sguohongyu  p0_fire   :=   p0_valid && p1_ready && toITLB.fire() && !fromITLB.bits.miss && toIMeta.ready && enableBit && !p0_req_cancel
432*b1ded4e8Sguohongyu  p0_discard := p0_valid && p0_req_cancel
433*b1ded4e8Sguohongyu
434*b1ded4e8Sguohongyu  toIMeta.valid     := p0_valid && !p0_discard
435afed18b5SJenius  toIMeta.bits.vSetIdx(0) := get_idx(p0_vaddr)
436*b1ded4e8Sguohongyu
437afed18b5SJenius  toIMeta.bits.vSetIdx(1) := DontCare
438afed18b5SJenius  toIMeta.bits.isDoubleLine := false.B
4397052722fSJay
440*b1ded4e8Sguohongyu  toITLB.valid         := p0_valid && !p0_discard
4417052722fSJay  toITLB.bits.size     := 3.U // TODO: fix the size
4427052722fSJay  toITLB.bits.vaddr    := p0_vaddr
4437052722fSJay  toITLB.bits.debug.pc := p0_vaddr
4447052722fSJay
445f1fe8698SLemover  toITLB.bits.kill                := DontCare
4467052722fSJay  toITLB.bits.cmd                 := TlbCmd.exec
447f1fe8698SLemover  toITLB.bits.debug.robIdx        := DontCare
4487052722fSJay  toITLB.bits.debug.isFirstIssue  := DontCare
449*b1ded4e8Sguohongyu  toITLB.bits.memidx              := DontCare
450*b1ded4e8Sguohongyu  toITLB.bits.no_translate        := false.B
4517052722fSJay
4527052722fSJay  fromITLB.ready := true.B
4537052722fSJay
454*b1ded4e8Sguohongyu  fromFtq.req.ready :=  !p0_valid || p0_fire || p0_discard
4557052722fSJay
4567052722fSJay  /** Prefetch Stage 1: cache probe filter */
4577052722fSJay  val p1_valid =  generatePipeControl(lastFire = p0_fire, thisFire = p1_fire || p1_discard, thisFlush = false.B, lastFlush = false.B)
4587052722fSJay
459005e809bSJiuyang Liu  val p1_vaddr   =  RegEnable(p0_vaddr,    p0_fire)
460*b1ded4e8Sguohongyu  // TODO: tlb is none blocked ,when tlb miss, p1 req need cancle. Now there seemes has bug
4617052722fSJay  //tlb resp
462de7689fcSJay  val tlb_resp_valid = RegInit(false.B)
463de7689fcSJay  when(p0_fire) {tlb_resp_valid := true.B}
464de7689fcSJay    .elsewhen(tlb_resp_valid && (p1_fire || p1_discard)) {tlb_resp_valid := false.B}
4657052722fSJay
46603efd994Shappy-lx  val tlb_resp_paddr = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.paddr(0))
46703efd994Shappy-lx  val tlb_resp_pf    = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).pf.instr && tlb_resp_valid)
46803efd994Shappy-lx  val tlb_resp_af    = ResultHoldBypass(valid = RegNext(p0_fire), data = fromITLB.bits.excp(0).af.instr && tlb_resp_valid)
4697052722fSJay
4707052722fSJay  val p1_exception  = VecInit(Seq(tlb_resp_pf, tlb_resp_af))
4717052722fSJay  val p1_has_except =  p1_exception.reduce(_ || _)
472*b1ded4e8Sguohongyu  val p1_paddr = tlb_resp_paddr
4737052722fSJay
474*b1ded4e8Sguohongyu  val p1_ptag = get_phy_tag(p1_paddr)
4757052722fSJay
4767052722fSJay  val p1_meta_ptags       = ResultHoldBypass(data = VecInit(fromIMeta.map(way => way.tag)),valid = RegNext(p0_fire))
477*b1ded4e8Sguohongyu  val p1_meta_valids      = ResultHoldBypass(data = fromIMetaValid,valid = RegNext(p0_fire))
478*b1ded4e8Sguohongyu
4797052722fSJay  val p1_tag_eq_vec       =  VecInit(p1_meta_ptags.map(_  ===  p1_ptag ))
480*b1ded4e8Sguohongyu  val p1_tag_match_vec    =  VecInit(p1_tag_eq_vec.zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && p1_meta_valids(w)})
4817052722fSJay  val p1_tag_match        =  ParallelOR(p1_tag_match_vec)
482*b1ded4e8Sguohongyu
483*b1ded4e8Sguohongyu  val p1_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p1_paddr, blockBytes, PAddrBits))).reduce(_||_)
484*b1ded4e8Sguohongyu
485*b1ded4e8Sguohongyu  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)
486*b1ded4e8Sguohongyu
4877052722fSJay
4887052722fSJay  //overriding the invalid req
489*b1ded4e8Sguohongyu  val p1_req_cancle = (p1_hit || (tlb_resp_valid && p1_exception.reduce(_ || _)) || io.fencei) && p1_valid
4907052722fSJay  val p1_req_accept   = p1_valid && tlb_resp_valid && p1_miss
4917052722fSJay
4927052722fSJay  p1_ready    :=   p1_fire || p1_req_cancle || !p1_valid
493a108d429SJay  p1_fire     :=   p1_valid && p1_req_accept && p2_ready && enableBit
4947052722fSJay  p1_discard  :=   p1_valid && p1_req_cancle
4957052722fSJay
4967052722fSJay  /** Prefetch Stage 2: filtered req PIQ enqueue */
4977052722fSJay  val p2_valid =  generatePipeControl(lastFire = p1_fire, thisFire = p2_fire || p2_discard, thisFlush = false.B, lastFlush = false.B)
498*b1ded4e8Sguohongyu  val p2_pmp_fire = p2_valid
499*b1ded4e8Sguohongyu  val pmpExcpAF = fromPMP.instr
5007052722fSJay
501*b1ded4e8Sguohongyu  val p2_paddr     = RegEnable(p1_paddr,  p1_fire)
502*b1ded4e8Sguohongyu  val p2_except_pf = RegEnable(tlb_resp_pf, p1_fire)
503*b1ded4e8Sguohongyu  val p2_except_af = DataHoldBypass(pmpExcpAF, p2_pmp_fire) || RegEnable(tlb_resp_af, p1_fire)
504*b1ded4e8Sguohongyu  val p2_mmio      = DataHoldBypass(io.pmp.resp.mmio && !p2_except_af && !p2_except_pf, p2_pmp_fire)
505*b1ded4e8Sguohongyu  val p2_vaddr   =  RegEnable(p1_vaddr,    p1_fire)
506*b1ded4e8Sguohongyu
5077052722fSJay
50800240ba6SJay  /*when a prefetch req meet with a miss req in MSHR cancle the prefetch req */
50900240ba6SJay  val p2_check_in_mshr = VecInit(io.fromMSHR.map(mshr => mshr.valid && mshr.bits === addrAlign(p2_paddr, blockBytes, PAddrBits))).reduce(_||_)
51000240ba6SJay
5117052722fSJay  //TODO wait PMP logic
512*b1ded4e8Sguohongyu  val p2_exception  = VecInit(Seq(pmpExcpAF, p2_mmio)).reduce(_||_)
513*b1ded4e8Sguohongyu
514*b1ded4e8Sguohongyu  io.pmp.req.valid      := p2_pmp_fire
515*b1ded4e8Sguohongyu  io.pmp.req.bits.addr  := p2_paddr
516*b1ded4e8Sguohongyu  io.pmp.req.bits.size  := 3.U
517*b1ded4e8Sguohongyu  io.pmp.req.bits.cmd   := TlbCmd.exec
5187052722fSJay
5197052722fSJay  p2_ready :=   p2_fire || p2_discard || !p2_valid
520*b1ded4e8Sguohongyu  p2_fire  :=   p2_valid && !p2_exception && p3_ready && p2_pmp_fire
521*b1ded4e8Sguohongyu  p2_discard := p2_valid && (p2_exception && p2_pmp_fire || io.fencei)
5227052722fSJay
5237052722fSJay  /** Prefetch Stage 2: filtered req PIQ enqueue */
524a108d429SJay  val p3_valid =  generatePipeControl(lastFire = p2_fire, thisFire = p3_fire || p3_discard, thisFlush = false.B, lastFlush = false.B)
5257052722fSJay
526*b1ded4e8Sguohongyu  val p3_paddr = RegEnable(p2_paddr,  p2_fire)
527*b1ded4e8Sguohongyu  val p3_check_in_mshr = RegEnable(p2_check_in_mshr,  p2_fire)
528*b1ded4e8Sguohongyu  val p3_vaddr   =  RegEnable(p2_vaddr,    p2_fire)
529*b1ded4e8Sguohongyu  val p3_vidx = get_idx(p3_vaddr)
530*b1ded4e8Sguohongyu  // check in prefetch buffer
531*b1ded4e8Sguohongyu  toIPFBuffer.vSetIdx := p3_vidx
532*b1ded4e8Sguohongyu  toIPFBuffer.paddr := p3_paddr
533*b1ded4e8Sguohongyu  val p3_buffer_hit = fromIPFBuffer.ipf_hit
5347052722fSJay
535a108d429SJay  val p3_hit_dir = VecInit((0 until nPrefetchEntries).map(i => prefetch_dir(i).valid && prefetch_dir(i).paddr === p3_paddr )).reduce(_||_)
536*b1ded4e8Sguohongyu  //Cache miss handling by main pipe
537*b1ded4e8Sguohongyu  val p3_hit_mp_miss = VecInit((0 until PortNumber).map(i => fromMainPipe(i).valid && (fromMainPipe(i).bits.ptage === get_phy_tag(p3_paddr) &&
538*b1ded4e8Sguohongyu    (fromMainPipe(i).bits.vSetIdx === p3_vidx)))).reduce(_||_)
539*b1ded4e8Sguohongyu  val p3_req_cancel = p3_hit_dir || p3_check_in_mshr || !enableBit || p3_hit_mp_miss || p3_buffer_hit || io.fencei
540*b1ded4e8Sguohongyu  p3_discard := p3_valid && p3_req_cancel
541a108d429SJay
542*b1ded4e8Sguohongyu  toMissUnit.enqReq.valid := p3_valid && !p3_req_cancel
5437052722fSJay  toMissUnit.enqReq.bits.paddr := p3_paddr
544*b1ded4e8Sguohongyu  toMissUnit.enqReq.bits.vSetIdx := p3_vidx
5457052722fSJay
546*b1ded4e8Sguohongyu  when(io.fencei){
547*b1ded4e8Sguohongyu    maxPrefetchCounter := 0.U
548a108d429SJay
549a108d429SJay    prefetch_dir.foreach(_.valid := false.B)
550a108d429SJay  }.elsewhen(toMissUnit.enqReq.fire()){
551*b1ded4e8Sguohongyu    when(reachMaxSize){
552*b1ded4e8Sguohongyu      prefetch_dir(io.freePIQEntry).paddr := p3_paddr
553*b1ded4e8Sguohongyu    }.otherwise {
554*b1ded4e8Sguohongyu      maxPrefetchCounter := maxPrefetchCounter + 1.U
555a108d429SJay
556*b1ded4e8Sguohongyu      prefetch_dir(maxPrefetchCounter).valid := true.B
557*b1ded4e8Sguohongyu      prefetch_dir(maxPrefetchCounter).paddr := p3_paddr
558*b1ded4e8Sguohongyu    }
559a108d429SJay  }
560a108d429SJay
561a108d429SJay  p3_ready := toMissUnit.enqReq.ready || !enableBit
5627052722fSJay  p3_fire  := toMissUnit.enqReq.fire()
5637052722fSJay
5647052722fSJay}
5657052722fSJay
566*b1ded4e8Sguohongyuclass PIQEntry(edge: TLEdgeOut, id: Int)(implicit p: Parameters) extends IPrefetchModule
5677052722fSJay{
5687052722fSJay  val io = IO(new Bundle{
569*b1ded4e8Sguohongyu    val id          = Input(UInt((log2Ceil(nPrefetchEntries + PortNumber)).W))
5707052722fSJay
5717052722fSJay    val req         = Flipped(DecoupledIO(new PIQReq))
5727052722fSJay
573*b1ded4e8Sguohongyu    val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle))
574*b1ded4e8Sguohongyu    val mem_grant   = Flipped(DecoupledIO(new TLBundleD(edge.bundle)))
5757052722fSJay
576*b1ded4e8Sguohongyu    //write back to Prefetch Buffer
577*b1ded4e8Sguohongyu    val piq_write_ipbuffer = DecoupledIO(new IPFBufferWrite)
578*b1ded4e8Sguohongyu
579*b1ded4e8Sguohongyu    //TODO: fencei flush instructions
580*b1ded4e8Sguohongyu    val fencei      = Input(Bool())
581*b1ded4e8Sguohongyu
582*b1ded4e8Sguohongyu    val prefetch_entry_data = DecoupledIO(new PIQData)
5837052722fSJay  })
5847052722fSJay
585*b1ded4e8Sguohongyu  val s_idle :: s_memReadReq :: s_memReadResp :: s_write_back :: s_finish:: Nil = Enum(5)
5867052722fSJay  val state = RegInit(s_idle)
5877052722fSJay
588*b1ded4e8Sguohongyu  //req register
589*b1ded4e8Sguohongyu  val req = Reg(new PIQReq)
590*b1ded4e8Sguohongyu  val req_idx = req.vSetIdx                     //virtual index
591*b1ded4e8Sguohongyu  val req_tag = get_phy_tag(req.paddr)           //physical tag
592*b1ded4e8Sguohongyu
593*b1ded4e8Sguohongyu  val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant)
594*b1ded4e8Sguohongyu
595*b1ded4e8Sguohongyu  //8 for 64 bits bus and 2 for 256 bits
596*b1ded4e8Sguohongyu  val readBeatCnt = Reg(UInt(log2Up(refillCycles).W))
597*b1ded4e8Sguohongyu  val respDataReg = Reg(Vec(refillCycles,UInt(beatBits.W)))
598*b1ded4e8Sguohongyu
599*b1ded4e8Sguohongyu  //to main pipe s1
600*b1ded4e8Sguohongyu  io.prefetch_entry_data.valid := state =/= s_idle
601*b1ded4e8Sguohongyu  io.prefetch_entry_data.bits.vSetIdx := req_idx
602*b1ded4e8Sguohongyu  io.prefetch_entry_data.bits.ptage := req_tag
603*b1ded4e8Sguohongyu  io.prefetch_entry_data.bits.cacheline := respDataReg.asUInt
604*b1ded4e8Sguohongyu  io.prefetch_entry_data.bits.writeBack := state === s_write_back
605*b1ded4e8Sguohongyu
606*b1ded4e8Sguohongyu  //initial
607*b1ded4e8Sguohongyu  io.mem_acquire.bits := DontCare
608*b1ded4e8Sguohongyu  io.mem_grant.ready := true.B
609*b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits:= DontCare
610*b1ded4e8Sguohongyu
611*b1ded4e8Sguohongyu  io.req.ready := state === s_idle
612*b1ded4e8Sguohongyu  io.mem_acquire.valid := state === s_memReadReq
613*b1ded4e8Sguohongyu
614*b1ded4e8Sguohongyu  val needFlushReg = RegInit(false.B)
615*b1ded4e8Sguohongyu  when(state === s_idle || state === s_finish){
616*b1ded4e8Sguohongyu    needFlushReg := false.B
617*b1ded4e8Sguohongyu  }
618*b1ded4e8Sguohongyu  when((state === s_memReadReq || state === s_memReadResp || state === s_write_back) && io.fencei){
619*b1ded4e8Sguohongyu    needFlushReg := true.B
620*b1ded4e8Sguohongyu  }
621*b1ded4e8Sguohongyu  val needFlush = needFlushReg || io.fencei
6227052722fSJay
6237052722fSJay  //state change
6247052722fSJay  switch(state){
6257052722fSJay    is(s_idle){
6267052722fSJay      when(io.req.fire()){
627*b1ded4e8Sguohongyu        readBeatCnt := 0.U
628*b1ded4e8Sguohongyu        state := s_memReadReq
6297052722fSJay        req := io.req.bits
6307052722fSJay      }
6317052722fSJay    }
6327052722fSJay
6337052722fSJay    // memory request
634*b1ded4e8Sguohongyu    is(s_memReadReq){
635*b1ded4e8Sguohongyu      when(io.mem_acquire.fire()){
636*b1ded4e8Sguohongyu        state := s_memReadResp
637*b1ded4e8Sguohongyu      }
638*b1ded4e8Sguohongyu    }
639*b1ded4e8Sguohongyu
640*b1ded4e8Sguohongyu    is(s_memReadResp){
641*b1ded4e8Sguohongyu      when (edge.hasData(io.mem_grant.bits)) {
642*b1ded4e8Sguohongyu        when (io.mem_grant.fire()) {
643*b1ded4e8Sguohongyu          readBeatCnt := readBeatCnt + 1.U
644*b1ded4e8Sguohongyu          respDataReg(readBeatCnt) := io.mem_grant.bits.data
645*b1ded4e8Sguohongyu          when (readBeatCnt === (refillCycles - 1).U) {
646*b1ded4e8Sguohongyu            assert(refill_done, "refill not done!")
647*b1ded4e8Sguohongyu            state := s_write_back
648*b1ded4e8Sguohongyu          }
649*b1ded4e8Sguohongyu        }
650*b1ded4e8Sguohongyu      }
651*b1ded4e8Sguohongyu    }
652*b1ded4e8Sguohongyu
653*b1ded4e8Sguohongyu    is(s_write_back){
654*b1ded4e8Sguohongyu      state := Mux(io.piq_write_ipbuffer.fire() || needFlush, s_finish, s_write_back)
655*b1ded4e8Sguohongyu    }
656*b1ded4e8Sguohongyu
657*b1ded4e8Sguohongyu    is(s_finish){
6587052722fSJay      state := s_idle
6597052722fSJay    }
6607052722fSJay  }
6617052722fSJay
662*b1ded4e8Sguohongyu  //refill write and meta write
663*b1ded4e8Sguohongyu  //WARNING: Maybe could not finish refill in 1 cycle
664*b1ded4e8Sguohongyu  io.piq_write_ipbuffer.valid := (state === s_write_back) && !needFlush
665*b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.meta.tag := req_tag
666*b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.meta.index := req_idx
667*b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.meta.paddr := req.paddr
668*b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.data := respDataReg.asUInt
669*b1ded4e8Sguohongyu  io.piq_write_ipbuffer.bits.buffIdx := io.id - PortNumber.U
6707052722fSJay
6717052722fSJay  XSPerfAccumulate("PrefetchEntryReq" + Integer.toString(id, 10), io.req.fire())
6727052722fSJay
673*b1ded4e8Sguohongyu  //mem request
674*b1ded4e8Sguohongyu  io.mem_acquire.bits  := edge.Get(
675*b1ded4e8Sguohongyu    fromSource      = io.id,
676*b1ded4e8Sguohongyu    toAddress       = Cat(req.paddr(PAddrBits - 1, log2Ceil(blockBytes)), 0.U(log2Ceil(blockBytes).W)),
677*b1ded4e8Sguohongyu    lgSize          = (log2Up(cacheParams.blockBytes)).U)._2
678*b1ded4e8Sguohongyu
6797052722fSJay}
680