xref: /XiangShan/src/main/scala/xiangshan/frontend/IFU.scala (revision b005f7c67708267adf97c948d6d041442e12f52a)
109c6f1ddSLingrui98/***************************************************************************************
209c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
309c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory
409c6f1ddSLingrui98*
509c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2.
609c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2.
709c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at:
809c6f1ddSLingrui98*          http://license.coscl.org.cn/MulanPSL2
909c6f1ddSLingrui98*
1009c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
1109c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
1209c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
1309c6f1ddSLingrui98*
1409c6f1ddSLingrui98* See the Mulan PSL v2 for more details.
1509c6f1ddSLingrui98***************************************************************************************/
1609c6f1ddSLingrui98
1709c6f1ddSLingrui98package xiangshan.frontend
1809c6f1ddSLingrui98
1909c6f1ddSLingrui98import chipsalliance.rocketchip.config.Parameters
2009c6f1ddSLingrui98import chisel3._
2109c6f1ddSLingrui98import chisel3.util._
2209c6f1ddSLingrui98import xiangshan._
2309c6f1ddSLingrui98import xiangshan.cache._
2409c6f1ddSLingrui98import xiangshan.cache.mmu._
2509c6f1ddSLingrui98import chisel3.experimental.verification
2609c6f1ddSLingrui98import utils._
27b6982e83SLemoverimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle}
2809c6f1ddSLingrui98
2909c6f1ddSLingrui98trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{
3009c6f1ddSLingrui98  def mmioBusWidth = 64
3109c6f1ddSLingrui98  def mmioBusBytes = mmioBusWidth / 8
320be662e4SJay  def maxInstrLen = 32
3309c6f1ddSLingrui98}
3409c6f1ddSLingrui98
3509c6f1ddSLingrui98trait HasIFUConst extends HasXSParameter {
3609c6f1ddSLingrui98  def align(pc: UInt, bytes: Int): UInt = Cat(pc(VAddrBits-1, log2Ceil(bytes)), 0.U(log2Ceil(bytes).W))
3709c6f1ddSLingrui98  // def groupAligned(pc: UInt)  = align(pc, groupBytes)
3809c6f1ddSLingrui98  // def packetAligned(pc: UInt) = align(pc, packetBytes)
3909c6f1ddSLingrui98}
4009c6f1ddSLingrui98
4109c6f1ddSLingrui98class IfuToFtqIO(implicit p:Parameters) extends XSBundle {
4209c6f1ddSLingrui98  val pdWb = Valid(new PredecodeWritebackBundle)
4309c6f1ddSLingrui98}
4409c6f1ddSLingrui98
4509c6f1ddSLingrui98class FtqInterface(implicit p: Parameters) extends XSBundle {
4609c6f1ddSLingrui98  val fromFtq = Flipped(new FtqToIfuIO)
4709c6f1ddSLingrui98  val toFtq   = new IfuToFtqIO
4809c6f1ddSLingrui98}
4909c6f1ddSLingrui98
500be662e4SJayclass UncacheInterface(implicit p: Parameters) extends XSBundle {
510be662e4SJay  val fromUncache = Flipped(DecoupledIO(new InsUncacheResp))
520be662e4SJay  val toUncache   = DecoupledIO( new InsUncacheReq )
530be662e4SJay}
540be662e4SJay
5509c6f1ddSLingrui98class ICacheInterface(implicit p: Parameters) extends XSBundle {
5609c6f1ddSLingrui98  val toIMeta       = Decoupled(new ICacheReadBundle)
5709c6f1ddSLingrui98  val toIData       = Decoupled(new ICacheReadBundle)
5809c6f1ddSLingrui98  val toMissQueue   = Vec(2,Decoupled(new ICacheMissReq))
5909c6f1ddSLingrui98  val fromIMeta     = Input(new ICacheMetaRespBundle)
6009c6f1ddSLingrui98  val fromIData     = Input(new ICacheDataRespBundle)
6109c6f1ddSLingrui98  val fromMissQueue = Vec(2,Flipped(Decoupled(new ICacheMissResp)))
6209c6f1ddSLingrui98}
6309c6f1ddSLingrui98
6409c6f1ddSLingrui98class NewIFUIO(implicit p: Parameters) extends XSBundle {
6509c6f1ddSLingrui98  val ftqInter        = new FtqInterface
6609c6f1ddSLingrui98  val icacheInter     = new ICacheInterface
6709c6f1ddSLingrui98  val toIbuffer       = Decoupled(new FetchToIBuffer)
6809c6f1ddSLingrui98  val iTLBInter       = Vec(2, new BlockTlbRequestIO)
690be662e4SJay  val uncacheInter   =  new UncacheInterface
70b6982e83SLemover  val pmp             = Vec(2, new Bundle {
71b6982e83SLemover    val req = Valid(new PMPReqBundle())
72ca2f90a6SLemover    val resp = Flipped(new PMPRespBundle())
73b6982e83SLemover  })
7409c6f1ddSLingrui98}
7509c6f1ddSLingrui98
7609c6f1ddSLingrui98// record the situation in which fallThruAddr falls into
7709c6f1ddSLingrui98// the middle of an RVI inst
7809c6f1ddSLingrui98class LastHalfInfo(implicit p: Parameters) extends XSBundle {
7909c6f1ddSLingrui98  val valid = Bool()
8009c6f1ddSLingrui98  val middlePC = UInt(VAddrBits.W)
8109c6f1ddSLingrui98  def matchThisBlock(startAddr: UInt) = valid && middlePC === startAddr
8209c6f1ddSLingrui98}
8309c6f1ddSLingrui98
8409c6f1ddSLingrui98class IfuToPreDecode(implicit p: Parameters) extends XSBundle {
8509c6f1ddSLingrui98  val data          = if(HasCExtension) Vec(PredictWidth + 1, UInt(16.W)) else Vec(PredictWidth, UInt(32.W))
8609c6f1ddSLingrui98  val startAddr     = UInt(VAddrBits.W)
8709c6f1ddSLingrui98  val fallThruAddr  = UInt(VAddrBits.W)
8809c6f1ddSLingrui98  val fallThruError = Bool()
8909c6f1ddSLingrui98  val isDoubleLine  = Bool()
9009c6f1ddSLingrui98  val ftqOffset     = Valid(UInt(log2Ceil(PredictWidth).W))
9109c6f1ddSLingrui98  val target        = UInt(VAddrBits.W)
9209c6f1ddSLingrui98  val pageFault     = Vec(2, Bool())
9309c6f1ddSLingrui98  val accessFault   = Vec(2, Bool())
9409c6f1ddSLingrui98  val instValid     = Bool()
9509c6f1ddSLingrui98  val lastHalfMatch = Bool()
9609c6f1ddSLingrui98  val oversize      = Bool()
970be662e4SJay  val mmio = Bool()
9809c6f1ddSLingrui98}
9909c6f1ddSLingrui98
10009c6f1ddSLingrui98class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
10109c6f1ddSLingrui98{
10209c6f1ddSLingrui98  println(s"icache ways: ${nWays} sets:${nSets}")
10309c6f1ddSLingrui98  val io = IO(new NewIFUIO)
10409c6f1ddSLingrui98  val (toFtq, fromFtq)    = (io.ftqInter.toFtq, io.ftqInter.fromFtq)
10509c6f1ddSLingrui98  val (toMeta, toData, meta_resp, data_resp) =  (io.icacheInter.toIMeta, io.icacheInter.toIData, io.icacheInter.fromIMeta, io.icacheInter.fromIData)
10609c6f1ddSLingrui98  val (toMissQueue, fromMissQueue) = (io.icacheInter.toMissQueue, io.icacheInter.fromMissQueue)
1070be662e4SJay  val (toUncache, fromUncache) = (io.uncacheInter.toUncache , io.uncacheInter.fromUncache)
10809c6f1ddSLingrui98  val (toITLB, fromITLB) = (VecInit(io.iTLBInter.map(_.req)), VecInit(io.iTLBInter.map(_.resp)))
109b6982e83SLemover  val fromPMP = io.pmp.map(_.resp)
11009c6f1ddSLingrui98
11109c6f1ddSLingrui98  def isCrossLineReq(start: UInt, end: UInt): Bool = start(blockOffBits) ^ end(blockOffBits)
11209c6f1ddSLingrui98
11309c6f1ddSLingrui98  def isLastInCacheline(fallThruAddr: UInt): Bool = fallThruAddr(blockOffBits - 1, 1) === 0.U
11409c6f1ddSLingrui98
115*b005f7c6SJay    def ResultHoldBypass[T<:Data](data: T, valid: Bool): T = {
116*b005f7c6SJay    Mux(valid, data, RegEnable(data, valid))
117*b005f7c6SJay  }
11809c6f1ddSLingrui98
11909c6f1ddSLingrui98  //---------------------------------------------
12009c6f1ddSLingrui98  //  Fetch Stage 1 :
12109c6f1ddSLingrui98  //  * Send req to ICache Meta/Data
12209c6f1ddSLingrui98  //  * Check whether need 2 line fetch
12309c6f1ddSLingrui98  //---------------------------------------------
12409c6f1ddSLingrui98
12509c6f1ddSLingrui98  val f0_valid                             = fromFtq.req.valid
12609c6f1ddSLingrui98  val f0_ftq_req                           = fromFtq.req.bits
12709c6f1ddSLingrui98  val f0_situation                         = VecInit(Seq(isCrossLineReq(f0_ftq_req.startAddr, f0_ftq_req.fallThruAddr), isLastInCacheline(f0_ftq_req.fallThruAddr)))
12809c6f1ddSLingrui98  val f0_doubleLine                        = f0_situation(0) || f0_situation(1)
12909c6f1ddSLingrui98  val f0_vSetIdx                           = VecInit(get_idx((f0_ftq_req.startAddr)), get_idx(f0_ftq_req.fallThruAddr))
13009c6f1ddSLingrui98  val f0_fire                              = fromFtq.req.fire()
13109c6f1ddSLingrui98
13209c6f1ddSLingrui98  val f0_flush, f1_flush, f2_flush, f3_flush = WireInit(false.B)
13309c6f1ddSLingrui98  val from_bpu_f0_flush, from_bpu_f1_flush, from_bpu_f2_flush, from_bpu_f3_flush = WireInit(false.B)
13409c6f1ddSLingrui98
13509c6f1ddSLingrui98  from_bpu_f0_flush := fromFtq.flushFromBpu.shouldFlushByStage2(f0_ftq_req.ftqIdx) ||
13609c6f1ddSLingrui98                       fromFtq.flushFromBpu.shouldFlushByStage3(f0_ftq_req.ftqIdx)
13709c6f1ddSLingrui98
13809c6f1ddSLingrui98  val f3_redirect = WireInit(false.B)
13909c6f1ddSLingrui98  f3_flush := fromFtq.redirect.valid
14009c6f1ddSLingrui98  f2_flush := f3_flush || f3_redirect
14109c6f1ddSLingrui98  f1_flush := f2_flush || from_bpu_f1_flush
14209c6f1ddSLingrui98  f0_flush := f1_flush || from_bpu_f0_flush
14309c6f1ddSLingrui98
14409c6f1ddSLingrui98  val f1_ready, f2_ready, f3_ready         = WireInit(false.B)
14509c6f1ddSLingrui98
14609c6f1ddSLingrui98  //fetch: send addr to Meta/TLB and Data simultaneously
14709c6f1ddSLingrui98  val fetch_req = List(toMeta, toData)
14809c6f1ddSLingrui98  for(i <- 0 until 2) {
14909c6f1ddSLingrui98    fetch_req(i).valid := f0_fire
15009c6f1ddSLingrui98    fetch_req(i).bits.isDoubleLine := f0_doubleLine
15109c6f1ddSLingrui98    fetch_req(i).bits.vSetIdx := f0_vSetIdx
15209c6f1ddSLingrui98  }
15309c6f1ddSLingrui98
15409c6f1ddSLingrui98  fromFtq.req.ready := fetch_req(0).ready && fetch_req(1).ready && f1_ready && GTimer() > 500.U
15509c6f1ddSLingrui98
156f7c29b0aSJinYue  XSPerfAccumulate("ifu_bubble_ftq_not_valid",   !f0_valid )
157f7c29b0aSJinYue  XSPerfAccumulate("ifu_bubble_pipe_stall",    f0_valid && fetch_req(0).ready && fetch_req(1).ready && !f1_ready )
158f7c29b0aSJinYue  XSPerfAccumulate("ifu_bubble_sram_0_busy",   f0_valid && !fetch_req(0).ready  )
159f7c29b0aSJinYue  XSPerfAccumulate("ifu_bubble_sram_1_busy",   f0_valid && !fetch_req(1).ready  )
160f7c29b0aSJinYue
16109c6f1ddSLingrui98  //---------------------------------------------
16209c6f1ddSLingrui98  //  Fetch Stage 2 :
16309c6f1ddSLingrui98  //  * Send req to ITLB and TLB Response (Get Paddr)
16409c6f1ddSLingrui98  //  * ICache Response (Get Meta and Data)
16509c6f1ddSLingrui98  //  * Hit Check (Generate hit signal and hit vector)
16609c6f1ddSLingrui98  //  * Get victim way
16709c6f1ddSLingrui98  //---------------------------------------------
16809c6f1ddSLingrui98
16909c6f1ddSLingrui98  //TODO: handle fetch exceptions
17009c6f1ddSLingrui98
17109c6f1ddSLingrui98  val tlbRespAllValid = WireInit(false.B)
17209c6f1ddSLingrui98
17309c6f1ddSLingrui98  val f1_valid      = RegInit(false.B)
17409c6f1ddSLingrui98  val f1_ftq_req    = RegEnable(next = f0_ftq_req,    enable=f0_fire)
17509c6f1ddSLingrui98  val f1_situation  = RegEnable(next = f0_situation,  enable=f0_fire)
17609c6f1ddSLingrui98  val f1_doubleLine = RegEnable(next = f0_doubleLine, enable=f0_fire)
17709c6f1ddSLingrui98  val f1_vSetIdx    = RegEnable(next = f0_vSetIdx,    enable=f0_fire)
17809c6f1ddSLingrui98  val f1_fire       = f1_valid && tlbRespAllValid && f2_ready
17909c6f1ddSLingrui98
18009c6f1ddSLingrui98  f1_ready := f2_ready && tlbRespAllValid || !f1_valid
18109c6f1ddSLingrui98
18209c6f1ddSLingrui98  from_bpu_f1_flush := fromFtq.flushFromBpu.shouldFlushByStage3(f1_ftq_req.ftqIdx)
18309c6f1ddSLingrui98
18409c6f1ddSLingrui98  val preDecoder      = Module(new PreDecode)
18509c6f1ddSLingrui98  val (preDecoderIn, preDecoderOut)   = (preDecoder.io.in, preDecoder.io.out)
18609c6f1ddSLingrui98
18709c6f1ddSLingrui98  //flush generate and to Ftq
18809c6f1ddSLingrui98  val predecodeOutValid = WireInit(false.B)
18909c6f1ddSLingrui98
19009c6f1ddSLingrui98  when(f1_flush)                  {f1_valid  := false.B}
19109c6f1ddSLingrui98  .elsewhen(f0_fire && !f0_flush) {f1_valid  := true.B}
19209c6f1ddSLingrui98  .elsewhen(f1_fire)              {f1_valid  := false.B}
19309c6f1ddSLingrui98
19409c6f1ddSLingrui98  toITLB(0).valid         := f1_valid
195b6982e83SLemover  toITLB(0).bits.size     := 3.U // TODO: fix the size
19609c6f1ddSLingrui98  toITLB(0).bits.vaddr    := align(f1_ftq_req.startAddr, blockBytes)
19709c6f1ddSLingrui98  toITLB(0).bits.debug.pc := align(f1_ftq_req.startAddr, blockBytes)
19809c6f1ddSLingrui98
19909c6f1ddSLingrui98  toITLB(1).valid         := f1_valid && f1_doubleLine
200b6982e83SLemover  toITLB(1).bits.size     := 3.U // TODO: fix the size
20109c6f1ddSLingrui98  toITLB(1).bits.vaddr    := align(f1_ftq_req.fallThruAddr, blockBytes)
20209c6f1ddSLingrui98  toITLB(1).bits.debug.pc := align(f1_ftq_req.fallThruAddr, blockBytes)
20309c6f1ddSLingrui98
20409c6f1ddSLingrui98  toITLB.map{port =>
20509c6f1ddSLingrui98    port.bits.cmd                 := TlbCmd.exec
2069aca92b9SYinan Xu    port.bits.robIdx              := DontCare
20709c6f1ddSLingrui98    port.bits.debug.isFirstIssue  := DontCare
20809c6f1ddSLingrui98  }
20909c6f1ddSLingrui98
21009c6f1ddSLingrui98  fromITLB.map(_.ready := true.B)
21109c6f1ddSLingrui98
21209c6f1ddSLingrui98  val (tlbRespValid, tlbRespPAddr) = (fromITLB.map(_.valid), VecInit(fromITLB.map(_.bits.paddr)))
213ca2f90a6SLemover  val (tlbRespMiss) = (fromITLB.map(port => port.bits.miss && port.valid))
214b6982e83SLemover  val (tlbExcpPF,    tlbExcpAF)    = (fromITLB.map(port => port.bits.excp.pf.instr && port.valid),
215b6982e83SLemover    fromITLB.map(port => (port.bits.excp.af.instr) && port.valid)) //TODO: Temp treat mmio req as access fault
216b6982e83SLemover
21709c6f1ddSLingrui98  tlbRespAllValid := tlbRespValid(0)  && (tlbRespValid(1) || !f1_doubleLine)
21809c6f1ddSLingrui98
219*b005f7c6SJay  val f1_pAddrs             = tlbRespPAddr
22003c39bdeSJinYue  val f1_pTags              = VecInit(f1_pAddrs.map(get_phy_tag(_)))
221*b005f7c6SJay
222*b005f7c6SJay  val f1_tags               = ResultHoldBypass(data = meta_resp.tags, valid = RegNext(toMeta.fire()))
223*b005f7c6SJay  val f1_cacheline_valid    = ResultHoldBypass(data = meta_resp.valid, valid = RegNext(toMeta.fire()))
224*b005f7c6SJay  val f1_datas              = ResultHoldBypass(data = data_resp.datas, valid = RegNext(toData.fire()))
225*b005f7c6SJay
22609c6f1ddSLingrui98  val bank0_hit_vec         = VecInit(f1_tags(0).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(0)(i) && way_tag ===  f1_pTags(0) })
22709c6f1ddSLingrui98  val bank1_hit_vec         = VecInit(f1_tags(1).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(1)(i) && way_tag ===  f1_pTags(1) })
22809c6f1ddSLingrui98  val (bank0_hit,bank1_hit) = (ParallelOR(bank0_hit_vec) && !tlbExcpPF(0) && !tlbExcpAF(0), ParallelOR(bank1_hit_vec) && !tlbExcpPF(1) && !tlbExcpAF(1))
22909c6f1ddSLingrui98  val f1_hit                = (bank0_hit && bank1_hit && f1_valid && f1_doubleLine) || (f1_valid && !f1_doubleLine && bank0_hit)
23009c6f1ddSLingrui98  val f1_bank_hit_vec       = VecInit(Seq(bank0_hit_vec, bank1_hit_vec))
23109c6f1ddSLingrui98  val f1_bank_hit           = VecInit(Seq(bank0_hit, bank1_hit))
23209c6f1ddSLingrui98
2330be662e4SJay  //MMIO
2340be662e4SJay  //MMIO only need 1 instruction
235ca2f90a6SLemover  // val f1_mmio = tlbRespMMIO(0) && f1_valid
2360be662e4SJay
2370be662e4SJay
23809c6f1ddSLingrui98  val replacers       = Seq.fill(2)(ReplacementPolicy.fromString(Some("random"),nWays,nSets/2))
23909c6f1ddSLingrui98  val f1_victim_masks = VecInit(replacers.zipWithIndex.map{case (replacer, i) => UIntToOH(replacer.way(f1_vSetIdx(i)))})
24009c6f1ddSLingrui98
24109c6f1ddSLingrui98  val touch_sets = Seq.fill(2)(Wire(Vec(2, UInt(log2Ceil(nSets/2).W))))
24209c6f1ddSLingrui98  val touch_ways = Seq.fill(2)(Wire(Vec(2, Valid(UInt(log2Ceil(nWays).W)))) )
24309c6f1ddSLingrui98
24409c6f1ddSLingrui98  ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)}
24509c6f1ddSLingrui98
24609c6f1ddSLingrui98  val f1_hit_data      =  VecInit(f1_datas.zipWithIndex.map { case(bank, i) =>
24709c6f1ddSLingrui98    val bank_hit_data = Mux1H(f1_bank_hit_vec(i).asUInt, bank)
24809c6f1ddSLingrui98    bank_hit_data
24909c6f1ddSLingrui98  })
25009c6f1ddSLingrui98
251f7c29b0aSJinYue  (0 until nWays).map{ w =>
252f7c29b0aSJinYue    XSPerfAccumulate("line_0_hit_way_" + Integer.toString(w, 10),  f1_fire && f1_bank_hit(0) && OHToUInt(f1_bank_hit_vec(0))  === w.U)
253f7c29b0aSJinYue  }
254f7c29b0aSJinYue
255f7c29b0aSJinYue  (0 until nWays).map{ w =>
256f7c29b0aSJinYue    XSPerfAccumulate("line_0_victim_way_" + Integer.toString(w, 10),  f1_fire && !f1_bank_hit(0) && OHToUInt(f1_victim_masks(0))  === w.U)
257f7c29b0aSJinYue  }
258f7c29b0aSJinYue
259f7c29b0aSJinYue  (0 until nWays).map{ w =>
260f7c29b0aSJinYue    XSPerfAccumulate("line_1_hit_way_" + Integer.toString(w, 10),  f1_fire && f1_doubleLine && f1_bank_hit(1) && OHToUInt(f1_bank_hit_vec(1))  === w.U)
261f7c29b0aSJinYue  }
262f7c29b0aSJinYue
263f7c29b0aSJinYue  (0 until nWays).map{ w =>
264f7c29b0aSJinYue    XSPerfAccumulate("line_1_victim_way_" + Integer.toString(w, 10),  f1_fire && f1_doubleLine && !f1_bank_hit(1) && OHToUInt(f1_victim_masks(1))  === w.U)
265f7c29b0aSJinYue  }
266f7c29b0aSJinYue
267f7c29b0aSJinYue  XSPerfAccumulate("ifu_bubble_f1_tlb_miss",    f1_valid && !tlbRespAllValid )
26809c6f1ddSLingrui98
26909c6f1ddSLingrui98  //---------------------------------------------
27009c6f1ddSLingrui98  //  Fetch Stage 3 :
27109c6f1ddSLingrui98  //  * get data from last stage (hit from f1_hit_data/miss from missQueue response)
27209c6f1ddSLingrui98  //  * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!!
27309c6f1ddSLingrui98  //  * cut cacheline(s) and send to PreDecode
27409c6f1ddSLingrui98  //  * check if prediction is right (branch target and type, jump direction and type , jal target )
27509c6f1ddSLingrui98  //---------------------------------------------
27609c6f1ddSLingrui98  val f2_fetchFinish = Wire(Bool())
27709c6f1ddSLingrui98
27809c6f1ddSLingrui98  val f2_valid        = RegInit(false.B)
27909c6f1ddSLingrui98  val f2_ftq_req      = RegEnable(next = f1_ftq_req,    enable = f1_fire)
28009c6f1ddSLingrui98  val f2_situation    = RegEnable(next = f1_situation,  enable=f1_fire)
28109c6f1ddSLingrui98  val f2_doubleLine   = RegEnable(next = f1_doubleLine, enable=f1_fire)
28209c6f1ddSLingrui98  val f2_fire         = f2_valid && f2_fetchFinish && f3_ready
28309c6f1ddSLingrui98
28409c6f1ddSLingrui98  f2_ready := (f3_ready && f2_fetchFinish) || !f2_valid
28509c6f1ddSLingrui98
28609c6f1ddSLingrui98  when(f2_flush)                  {f2_valid := false.B}
28709c6f1ddSLingrui98  .elsewhen(f1_fire && !f1_flush) {f2_valid := true.B }
28809c6f1ddSLingrui98  .elsewhen(f2_fire)              {f2_valid := false.B}
28909c6f1ddSLingrui98
290b6982e83SLemover  val pmpExcpAF = fromPMP.map(port => port.instr)
291ca2f90a6SLemover  val mmio = fromPMP.map(port => port.mmio) // TODO: handle it
29209c6f1ddSLingrui98
2930be662e4SJay
29409c6f1ddSLingrui98  val f2_pAddrs   = RegEnable(next = f1_pAddrs, enable = f1_fire)
29509c6f1ddSLingrui98  val f2_hit      = RegEnable(next = f1_hit   , enable = f1_fire)
29609c6f1ddSLingrui98  val f2_bank_hit = RegEnable(next = f1_bank_hit, enable = f1_fire)
29709c6f1ddSLingrui98  val f2_miss     = f2_valid && !f2_hit
29809c6f1ddSLingrui98  val (f2_vSetIdx, f2_pTags) = (RegEnable(next = f1_vSetIdx, enable = f1_fire), RegEnable(next = f1_pTags, enable = f1_fire))
29909c6f1ddSLingrui98  val f2_waymask  = RegEnable(next = f1_victim_masks, enable = f1_fire)
30009c6f1ddSLingrui98  //exception information
30109c6f1ddSLingrui98  val f2_except_pf = RegEnable(next = VecInit(tlbExcpPF), enable = f1_fire)
302b6982e83SLemover  val f2_except_af = VecInit(RegEnable(next = VecInit(tlbExcpAF), enable = f1_fire).zip(pmpExcpAF).map(a => a._1 || DataHoldBypass(a._2, RegNext(f1_fire)).asBool))
30309c6f1ddSLingrui98  val f2_except    = VecInit((0 until 2).map{i => f2_except_pf(i) || f2_except_af(i)})
30409c6f1ddSLingrui98  val f2_has_except = f2_valid && (f2_except_af.reduce(_||_) || f2_except_pf.reduce(_||_))
3050be662e4SJay  //MMIO
30616c9060fSJay  val f2_mmio      = DataHoldBypass(io.pmp(0).resp.mmio && !f2_except_af(0) && !f2_except_pf(0), RegNext(f1_fire)).asBool()
3070be662e4SJay
308b6982e83SLemover  io.pmp.zipWithIndex.map { case (p, i) =>
309b6982e83SLemover    p.req.valid := f2_fire
310b6982e83SLemover    p.req.bits.addr := f2_pAddrs(i)
311b6982e83SLemover    p.req.bits.size := 3.U // TODO
312b6982e83SLemover    p.req.bits.cmd := TlbCmd.exec
313b6982e83SLemover  }
31409c6f1ddSLingrui98
31509c6f1ddSLingrui98  //instruction
3160be662e4SJay  val wait_idle :: wait_queue_ready :: wait_send_req  :: wait_two_resp :: wait_0_resp :: wait_1_resp :: wait_one_resp ::wait_finish :: wait_send_mmio :: wait_mmio_resp ::Nil = Enum(10)
31709c6f1ddSLingrui98  val wait_state = RegInit(wait_idle)
31809c6f1ddSLingrui98
31909c6f1ddSLingrui98  fromMissQueue.map{port => port.ready := true.B}
32009c6f1ddSLingrui98
32109c6f1ddSLingrui98  val (miss0_resp, miss1_resp) = (fromMissQueue(0).fire(), fromMissQueue(1).fire())
32209c6f1ddSLingrui98  val (bank0_fix, bank1_fix)   = (miss0_resp  && !f2_bank_hit(0), miss1_resp && f2_doubleLine && !f2_bank_hit(1))
32309c6f1ddSLingrui98
3240be662e4SJay  val  only_0_miss = f2_valid && !f2_hit && !f2_doubleLine && !f2_has_except && !f2_mmio
3250be662e4SJay  val  only_0_hit  = f2_valid && f2_hit && !f2_doubleLine  && !f2_mmio
3260be662e4SJay  val  hit_0_hit_1  = f2_valid && f2_hit && f2_doubleLine  && !f2_mmio
3270be662e4SJay  val (hit_0_miss_1 ,  miss_0_hit_1,  miss_0_miss_1) = (  (f2_valid && !f2_bank_hit(1) && f2_bank_hit(0) && f2_doubleLine  && !f2_has_except  && !f2_mmio),
3280be662e4SJay                                                          (f2_valid && !f2_bank_hit(0) && f2_bank_hit(1) && f2_doubleLine  && !f2_has_except  && !f2_mmio),
3290be662e4SJay                                                          (f2_valid && !f2_bank_hit(0) && !f2_bank_hit(1) && f2_doubleLine && !f2_has_except  && !f2_mmio),
33009c6f1ddSLingrui98                                                       )
33109c6f1ddSLingrui98
33209c6f1ddSLingrui98  val  hit_0_except_1  = f2_valid && f2_doubleLine &&  !f2_except(0) && f2_except(1)  &&  f2_bank_hit(0)
33309c6f1ddSLingrui98  val  miss_0_except_1 = f2_valid && f2_doubleLine &&  !f2_except(0) && f2_except(1)  && !f2_bank_hit(0)
33409c6f1ddSLingrui98  //val  fetch0_except_1 = hit_0_except_1 || miss_0_except_1
33509c6f1ddSLingrui98  val  except_0        = f2_valid && f2_except(0)
33609c6f1ddSLingrui98
33709c6f1ddSLingrui98  val f2_mq_datas     = Reg(Vec(2, UInt(blockBits.W)))
3380be662e4SJay  val f2_mmio_data    = Reg(UInt(maxInstrLen.W))
33909c6f1ddSLingrui98
34009c6f1ddSLingrui98  when(fromMissQueue(0).fire) {f2_mq_datas(0) :=  fromMissQueue(0).bits.data}
34109c6f1ddSLingrui98  when(fromMissQueue(1).fire) {f2_mq_datas(1) :=  fromMissQueue(1).bits.data}
3420be662e4SJay  when(fromUncache.fire())    {f2_mmio_data   :=  fromUncache.bits.data}
34309c6f1ddSLingrui98
34409c6f1ddSLingrui98  switch(wait_state){
34509c6f1ddSLingrui98    is(wait_idle){
346ca2f90a6SLemover      when(f2_mmio && f2_valid && !f2_except_af(0) && !f2_except_pf(0)){
3470be662e4SJay        wait_state :=  wait_send_mmio
3480be662e4SJay      }.elsewhen(miss_0_except_1){
34909c6f1ddSLingrui98        wait_state :=  Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
35009c6f1ddSLingrui98      }.elsewhen( only_0_miss  || miss_0_hit_1){
35109c6f1ddSLingrui98        wait_state :=  Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
35209c6f1ddSLingrui98      }.elsewhen(hit_0_miss_1){
35309c6f1ddSLingrui98        wait_state :=  Mux(toMissQueue(1).ready, wait_queue_ready ,wait_idle )
35409c6f1ddSLingrui98      }.elsewhen( miss_0_miss_1 ){
35509c6f1ddSLingrui98        wait_state := Mux(toMissQueue(0).ready && toMissQueue(1).ready, wait_queue_ready ,wait_idle)
35609c6f1ddSLingrui98      }
35709c6f1ddSLingrui98    }
35809c6f1ddSLingrui98
3590be662e4SJay    is(wait_send_mmio){
3600be662e4SJay      wait_state := Mux(toUncache.fire(), wait_mmio_resp,wait_send_mmio )
3610be662e4SJay    }
3620be662e4SJay
3630be662e4SJay    is(wait_mmio_resp){
3640be662e4SJay      wait_state :=  Mux(fromUncache.fire(), wait_finish, wait_mmio_resp)
3650be662e4SJay    }
3660be662e4SJay
36709c6f1ddSLingrui98    //TODO: naive logic for wait icache response
36809c6f1ddSLingrui98    is(wait_queue_ready){
36909c6f1ddSLingrui98      wait_state := wait_send_req
37009c6f1ddSLingrui98    }
37109c6f1ddSLingrui98
37209c6f1ddSLingrui98    is(wait_send_req) {
37309c6f1ddSLingrui98      when(miss_0_except_1 || only_0_miss || hit_0_miss_1 || miss_0_hit_1){
37409c6f1ddSLingrui98        wait_state :=  wait_one_resp
37509c6f1ddSLingrui98      }.elsewhen( miss_0_miss_1 ){
37609c6f1ddSLingrui98        wait_state := wait_two_resp
37709c6f1ddSLingrui98      }
37809c6f1ddSLingrui98    }
37909c6f1ddSLingrui98
38009c6f1ddSLingrui98    is(wait_one_resp) {
38109c6f1ddSLingrui98      when( (miss_0_except_1 ||only_0_miss || miss_0_hit_1) && fromMissQueue(0).fire()){
38209c6f1ddSLingrui98        wait_state := wait_finish
38309c6f1ddSLingrui98      }.elsewhen( hit_0_miss_1 && fromMissQueue(1).fire()){
38409c6f1ddSLingrui98        wait_state := wait_finish
38509c6f1ddSLingrui98      }
38609c6f1ddSLingrui98    }
38709c6f1ddSLingrui98
38809c6f1ddSLingrui98    is(wait_two_resp) {
38909c6f1ddSLingrui98      when(fromMissQueue(0).fire() && fromMissQueue(1).fire()){
39009c6f1ddSLingrui98        wait_state := wait_finish
39109c6f1ddSLingrui98      }.elsewhen( !fromMissQueue(0).fire() && fromMissQueue(1).fire() ){
39209c6f1ddSLingrui98        wait_state := wait_0_resp
39309c6f1ddSLingrui98      }.elsewhen(fromMissQueue(0).fire() && !fromMissQueue(1).fire()){
39409c6f1ddSLingrui98        wait_state := wait_1_resp
39509c6f1ddSLingrui98      }
39609c6f1ddSLingrui98    }
39709c6f1ddSLingrui98
39809c6f1ddSLingrui98    is(wait_0_resp) {
39909c6f1ddSLingrui98      when(fromMissQueue(0).fire()){
40009c6f1ddSLingrui98        wait_state := wait_finish
40109c6f1ddSLingrui98      }
40209c6f1ddSLingrui98    }
40309c6f1ddSLingrui98
40409c6f1ddSLingrui98    is(wait_1_resp) {
40509c6f1ddSLingrui98      when(fromMissQueue(1).fire()){
40609c6f1ddSLingrui98        wait_state := wait_finish
40709c6f1ddSLingrui98      }
40809c6f1ddSLingrui98    }
40909c6f1ddSLingrui98
41009c6f1ddSLingrui98    is(wait_finish) {
41109c6f1ddSLingrui98      when(f2_fire) {wait_state := wait_idle }
41209c6f1ddSLingrui98    }
41309c6f1ddSLingrui98  }
41409c6f1ddSLingrui98
41509c6f1ddSLingrui98  when(f2_flush) { wait_state := wait_idle }
41609c6f1ddSLingrui98
41709c6f1ddSLingrui98  (0 until 2).map { i =>
41809c6f1ddSLingrui98    if(i == 1) toMissQueue(i).valid := (hit_0_miss_1 || miss_0_miss_1) && wait_state === wait_queue_ready
419eee4cb5cSJay      else     toMissQueue(i).valid := (only_0_miss || miss_0_hit_1 || miss_0_miss_1 || miss_0_except_1) && wait_state === wait_queue_ready
42009c6f1ddSLingrui98    toMissQueue(i).bits.addr    := f2_pAddrs(i)
42109c6f1ddSLingrui98    toMissQueue(i).bits.vSetIdx := f2_vSetIdx(i)
42209c6f1ddSLingrui98    toMissQueue(i).bits.waymask := f2_waymask(i)
42309c6f1ddSLingrui98    toMissQueue(i).bits.clientID :=0.U
42409c6f1ddSLingrui98  }
42509c6f1ddSLingrui98
4260be662e4SJay  toUncache.valid :=  (wait_state === wait_send_mmio) && !f2_except_af(0)
4270be662e4SJay  //assert( (GTimer() < 5000.U && toUncache.fire()) || !toUncache.fire() )
4280be662e4SJay  toUncache.bits.addr := f2_ftq_req.startAddr
4290be662e4SJay
4300be662e4SJay  fromUncache.ready := true.B
4310be662e4SJay
43209c6f1ddSLingrui98  val miss_all_fix       = (wait_state === wait_finish)
43309c6f1ddSLingrui98
43409c6f1ddSLingrui98  f2_fetchFinish         := ((f2_valid && f2_hit) || miss_all_fix || hit_0_except_1 || except_0)
43509c6f1ddSLingrui98
436f7c29b0aSJinYue  XSPerfAccumulate("ifu_bubble_f2_miss",    f2_valid && !f2_fetchFinish )
43709c6f1ddSLingrui98
43809c6f1ddSLingrui98  (touch_ways zip touch_sets).zipWithIndex.map{ case((t_w,t_s), i) =>
43909c6f1ddSLingrui98    t_s(0)         := f1_vSetIdx(i)
44009c6f1ddSLingrui98    t_w(0).valid   := f1_bank_hit(i)
44109c6f1ddSLingrui98    t_w(0).bits    := OHToUInt(f1_bank_hit_vec(i))
44209c6f1ddSLingrui98
44309c6f1ddSLingrui98    t_s(1)         := f2_vSetIdx(i)
44409c6f1ddSLingrui98    t_w(1).valid   := f2_valid && !f2_bank_hit(i)
44509c6f1ddSLingrui98    t_w(1).bits    := OHToUInt(f2_waymask(i))
44609c6f1ddSLingrui98  }
44709c6f1ddSLingrui98
44809c6f1ddSLingrui98  val sec_miss_reg   = RegInit(0.U.asTypeOf(Vec(4, Bool())))
44909c6f1ddSLingrui98  val reservedRefillData = Reg(Vec(2, UInt(blockBits.W)))
45009c6f1ddSLingrui98  val f2_hit_datas    = RegEnable(next = f1_hit_data, enable = f1_fire)
45109c6f1ddSLingrui98  val f2_datas        = Wire(Vec(2, UInt(blockBits.W)))
45209c6f1ddSLingrui98
45309c6f1ddSLingrui98  f2_datas.zipWithIndex.map{case(bank,i) =>
45409c6f1ddSLingrui98    if(i == 0) bank := Mux(f2_bank_hit(i), f2_hit_datas(i),Mux(sec_miss_reg(2),reservedRefillData(1),Mux(sec_miss_reg(0),reservedRefillData(0), f2_mq_datas(i))))
45509c6f1ddSLingrui98    else bank := Mux(f2_bank_hit(i), f2_hit_datas(i),Mux(sec_miss_reg(3),reservedRefillData(1),Mux(sec_miss_reg(1),reservedRefillData(0), f2_mq_datas(i))))
45609c6f1ddSLingrui98  }
45709c6f1ddSLingrui98
45809c6f1ddSLingrui98  val f2_jump_valids          = Fill(PredictWidth, !preDecoderOut.cfiOffset.valid)   | Fill(PredictWidth, 1.U(1.W)) >> (~preDecoderOut.cfiOffset.bits)
45909c6f1ddSLingrui98  val f2_predecode_valids     = VecInit(preDecoderOut.pd.map(instr => instr.valid)).asUInt & f2_jump_valids
46009c6f1ddSLingrui98
46109c6f1ddSLingrui98  def cut(cacheline: UInt, start: UInt) : Vec[UInt] ={
46209c6f1ddSLingrui98    if(HasCExtension){
46309c6f1ddSLingrui98      val result   = Wire(Vec(PredictWidth + 1, UInt(16.W)))
46409c6f1ddSLingrui98      val dataVec  = cacheline.asTypeOf(Vec(blockBytes * 2/ 2, UInt(16.W)))
46509c6f1ddSLingrui98      val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 1))
46609c6f1ddSLingrui98      (0 until PredictWidth + 1).foreach( i =>
46709c6f1ddSLingrui98        result(i) := dataVec(startPtr + i.U)
46809c6f1ddSLingrui98      )
46909c6f1ddSLingrui98      result
47009c6f1ddSLingrui98    } else {
47109c6f1ddSLingrui98      val result   = Wire(Vec(PredictWidth, UInt(32.W)) )
47209c6f1ddSLingrui98      val dataVec  = cacheline.asTypeOf(Vec(blockBytes * 2/ 4, UInt(32.W)))
47309c6f1ddSLingrui98      val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 2))
47409c6f1ddSLingrui98      (0 until PredictWidth).foreach( i =>
47509c6f1ddSLingrui98        result(i) := dataVec(startPtr + i.U)
47609c6f1ddSLingrui98      )
47709c6f1ddSLingrui98      result
47809c6f1ddSLingrui98    }
47909c6f1ddSLingrui98  }
48009c6f1ddSLingrui98
48109c6f1ddSLingrui98  val f2_cut_data = cut( Cat(f2_datas.map(cacheline => cacheline.asUInt ).reverse).asUInt, f2_ftq_req.startAddr )
4820be662e4SJay  when(f2_mmio){
4830be662e4SJay    f2_cut_data(0) := f2_mmio_data(15, 0)
4840be662e4SJay    f2_cut_data(1) := f2_mmio_data(31, 16)
4850be662e4SJay  }
48609c6f1ddSLingrui98
48709c6f1ddSLingrui98  // deal with secondary miss in f1
48809c6f1ddSLingrui98  val f2_0_f1_0 =   ((f2_valid && !f2_bank_hit(0)) && f1_valid && (get_block_addr(f2_ftq_req.startAddr) === get_block_addr(f1_ftq_req.startAddr)))
48909c6f1ddSLingrui98  val f2_0_f1_1 =   ((f2_valid && !f2_bank_hit(0)) && f1_valid && f1_doubleLine && (get_block_addr(f2_ftq_req.startAddr) === get_block_addr(f1_ftq_req.startAddr + blockBytes.U)))
49009c6f1ddSLingrui98  val f2_1_f1_0 =   ((f2_valid && !f2_bank_hit(1) && f2_doubleLine) && f1_valid && (get_block_addr(f2_ftq_req.startAddr+ blockBytes.U) === get_block_addr(f1_ftq_req.startAddr) ))
49109c6f1ddSLingrui98  val f2_1_f1_1 =   ((f2_valid && !f2_bank_hit(1) && f2_doubleLine) && f1_valid && f1_doubleLine && (get_block_addr(f2_ftq_req.startAddr+ blockBytes.U) === get_block_addr(f1_ftq_req.startAddr + blockBytes.U) ))
49209c6f1ddSLingrui98
49309c6f1ddSLingrui98  val isSameLine = f2_0_f1_0 || f2_0_f1_1 || f2_1_f1_0 || f2_1_f1_1
49409c6f1ddSLingrui98  val sec_miss_sit   = VecInit(Seq(f2_0_f1_0, f2_0_f1_1, f2_1_f1_0, f2_1_f1_1))
49509c6f1ddSLingrui98  val hasSecMiss     = RegInit(false.B)
49609c6f1ddSLingrui98
49709c6f1ddSLingrui98  when(f2_flush){
49809c6f1ddSLingrui98    sec_miss_reg.map(sig => sig := false.B)
49909c6f1ddSLingrui98    hasSecMiss := false.B
50009c6f1ddSLingrui98  }.elsewhen(isSameLine && !f1_flush && f2_fire){
50109c6f1ddSLingrui98    sec_miss_reg.zipWithIndex.map{case(sig, i) => sig := sec_miss_sit(i)}
50209c6f1ddSLingrui98    hasSecMiss := true.B
50309c6f1ddSLingrui98  }.elsewhen((!isSameLine || f1_flush) && hasSecMiss && f2_fire){
50409c6f1ddSLingrui98    sec_miss_reg.map(sig => sig := false.B)
50509c6f1ddSLingrui98    hasSecMiss := false.B
50609c6f1ddSLingrui98  }
50709c6f1ddSLingrui98
50809c6f1ddSLingrui98  when((f2_0_f1_0 || f2_0_f1_1) && f2_fire){
50909c6f1ddSLingrui98    reservedRefillData(0) := f2_mq_datas(0)
51009c6f1ddSLingrui98  }
51109c6f1ddSLingrui98
51209c6f1ddSLingrui98  when((f2_1_f1_0 || f2_1_f1_1) && f2_fire){
51309c6f1ddSLingrui98    reservedRefillData(1) := f2_mq_datas(1)
51409c6f1ddSLingrui98  }
51509c6f1ddSLingrui98
51609c6f1ddSLingrui98
51709c6f1ddSLingrui98  //---------------------------------------------
51809c6f1ddSLingrui98  //  Fetch Stage 4 :
51909c6f1ddSLingrui98  //  * get data from last stage (hit from f1_hit_data/miss from missQueue response)
52009c6f1ddSLingrui98  //  * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!!
52109c6f1ddSLingrui98  //  * cut cacheline(s) and send to PreDecode
52209c6f1ddSLingrui98  //  * check if prediction is right (branch target and type, jump direction and type , jal target )
52309c6f1ddSLingrui98  //---------------------------------------------
52409c6f1ddSLingrui98  val f3_valid          = RegInit(false.B)
52509c6f1ddSLingrui98  val f3_ftq_req        = RegEnable(next = f2_ftq_req,    enable=f2_fire)
52609c6f1ddSLingrui98  val f3_situation      = RegEnable(next = f2_situation,  enable=f2_fire)
52709c6f1ddSLingrui98  val f3_doubleLine     = RegEnable(next = f2_doubleLine, enable=f2_fire)
52809c6f1ddSLingrui98  val f3_fire           = io.toIbuffer.fire()
52909c6f1ddSLingrui98
53009c6f1ddSLingrui98  when(f3_flush)                  {f3_valid := false.B}
53109c6f1ddSLingrui98  .elsewhen(f2_fire && !f2_flush) {f3_valid := true.B }
53209c6f1ddSLingrui98  .elsewhen(io.toIbuffer.fire())  {f3_valid := false.B}
53309c6f1ddSLingrui98
53409c6f1ddSLingrui98  f3_ready := io.toIbuffer.ready || !f2_valid
53509c6f1ddSLingrui98
53609c6f1ddSLingrui98  val f3_cut_data       = RegEnable(next = f2_cut_data, enable=f2_fire)
53709c6f1ddSLingrui98  val f3_except_pf      = RegEnable(next = f2_except_pf, enable = f2_fire)
53809c6f1ddSLingrui98  val f3_except_af      = RegEnable(next = f2_except_af, enable = f2_fire)
53909c6f1ddSLingrui98  val f3_hit            = RegEnable(next = f2_hit   , enable = f2_fire)
5400be662e4SJay  val f3_mmio           = RegEnable(next = f2_mmio   , enable = f2_fire)
54109c6f1ddSLingrui98
54209c6f1ddSLingrui98  val f3_lastHalf       = RegInit(0.U.asTypeOf(new LastHalfInfo))
54309c6f1ddSLingrui98  val f3_lastHalfMatch  = f3_lastHalf.matchThisBlock(f3_ftq_req.startAddr)
54409c6f1ddSLingrui98  val f3_except         = VecInit((0 until 2).map{i => f3_except_pf(i) || f3_except_af(i)})
54509c6f1ddSLingrui98  val f3_has_except     = f3_valid && (f3_except_af.reduce(_||_) || f3_except_pf.reduce(_||_))
54609c6f1ddSLingrui98
547f7c29b0aSJinYue  //performance counter
548f7c29b0aSJinYue  val f3_only_0_hit     = RegEnable(next = only_0_hit, enable = f2_fire)
549f7c29b0aSJinYue  val f3_only_0_miss    = RegEnable(next = only_0_miss, enable = f2_fire)
550f7c29b0aSJinYue  val f3_hit_0_hit_1    = RegEnable(next = hit_0_hit_1, enable = f2_fire)
551f7c29b0aSJinYue  val f3_hit_0_miss_1   = RegEnable(next = hit_0_miss_1, enable = f2_fire)
552f7c29b0aSJinYue  val f3_miss_0_hit_1   = RegEnable(next = miss_0_hit_1, enable = f2_fire)
553f7c29b0aSJinYue  val f3_miss_0_miss_1  = RegEnable(next = miss_0_miss_1, enable = f2_fire)
554f7c29b0aSJinYue
555f7c29b0aSJinYue  val f3_bank_hit = RegEnable(next = f2_bank_hit, enable = f2_fire)
556f7c29b0aSJinYue  val f3_req_0 = io.toIbuffer.fire()
557f7c29b0aSJinYue  val f3_req_1 = io.toIbuffer.fire() && f3_doubleLine
558f7c29b0aSJinYue  val f3_hit_0 = io.toIbuffer.fire() & f3_bank_hit(0)
559f7c29b0aSJinYue  val f3_hit_1 = io.toIbuffer.fire() && f3_doubleLine & f3_bank_hit(1)
560f7c29b0aSJinYue
56109c6f1ddSLingrui98  preDecoderIn.instValid     :=  f3_valid && !f3_has_except
56209c6f1ddSLingrui98  preDecoderIn.data          :=  f3_cut_data
56309c6f1ddSLingrui98  preDecoderIn.startAddr     :=  f3_ftq_req.startAddr
56409c6f1ddSLingrui98  preDecoderIn.fallThruAddr  :=  f3_ftq_req.fallThruAddr
56509c6f1ddSLingrui98  preDecoderIn.fallThruError :=  f3_ftq_req.fallThruError
56609c6f1ddSLingrui98  preDecoderIn.isDoubleLine  :=  f3_doubleLine
56709c6f1ddSLingrui98  preDecoderIn.ftqOffset     :=  f3_ftq_req.ftqOffset
56809c6f1ddSLingrui98  preDecoderIn.target        :=  f3_ftq_req.target
56909c6f1ddSLingrui98  preDecoderIn.oversize      :=  f3_ftq_req.oversize
57009c6f1ddSLingrui98  preDecoderIn.lastHalfMatch :=  f3_lastHalfMatch
57109c6f1ddSLingrui98  preDecoderIn.pageFault     :=  f3_except_pf
57209c6f1ddSLingrui98  preDecoderIn.accessFault   :=  f3_except_af
5730be662e4SJay  preDecoderIn.mmio          :=  f3_mmio
57409c6f1ddSLingrui98
57509c6f1ddSLingrui98
57609c6f1ddSLingrui98  // TODO: What if next packet does not match?
57709c6f1ddSLingrui98  when (f3_flush) {
57809c6f1ddSLingrui98    f3_lastHalf.valid := false.B
57909c6f1ddSLingrui98  }.elsewhen (io.toIbuffer.fire()) {
58009c6f1ddSLingrui98    f3_lastHalf.valid := preDecoderOut.hasLastHalf
58109c6f1ddSLingrui98    f3_lastHalf.middlePC := preDecoderOut.realEndPC
58209c6f1ddSLingrui98  }
58309c6f1ddSLingrui98
58409c6f1ddSLingrui98  val f3_predecode_range = VecInit(preDecoderOut.pd.map(inst => inst.valid)).asUInt
5850be662e4SJay  val f3_mmio_range      = VecInit((0 until PredictWidth).map(i => if(i ==0) true.B else false.B))
58609c6f1ddSLingrui98
58709c6f1ddSLingrui98  io.toIbuffer.valid          := f3_valid
58809c6f1ddSLingrui98  io.toIbuffer.bits.instrs    := preDecoderOut.instrs
5890be662e4SJay  io.toIbuffer.bits.valid     := Mux(f3_mmio, f3_mmio_range.asUInt, f3_predecode_range & preDecoderOut.instrRange.asUInt)
59009c6f1ddSLingrui98  io.toIbuffer.bits.pd        := preDecoderOut.pd
59109c6f1ddSLingrui98  io.toIbuffer.bits.ftqPtr    := f3_ftq_req.ftqIdx
59209c6f1ddSLingrui98  io.toIbuffer.bits.pc        := preDecoderOut.pc
5930be662e4SJay  io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := preDecoderOut.takens(i) && !f3_mmio}
59409c6f1ddSLingrui98  io.toIbuffer.bits.foldpc    := preDecoderOut.pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth))
59509c6f1ddSLingrui98  io.toIbuffer.bits.ipf       := preDecoderOut.pageFault
59609c6f1ddSLingrui98  io.toIbuffer.bits.acf       := preDecoderOut.accessFault
59709c6f1ddSLingrui98  io.toIbuffer.bits.crossPageIPFFix := preDecoderOut.crossPageIPF
59809c6f1ddSLingrui98
59909c6f1ddSLingrui98  //Write back to Ftq
60009c6f1ddSLingrui98  val finishFetchMaskReg = RegNext(f3_valid && !(f2_fire && !f2_flush))
60109c6f1ddSLingrui98
6020be662e4SJay  val f3_mmio_missOffset = Wire(ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))
6030be662e4SJay  f3_mmio_missOffset.valid := f3_mmio
6040be662e4SJay  f3_mmio_missOffset.bits  := 0.U
6050be662e4SJay
60609c6f1ddSLingrui98  toFtq.pdWb.valid           := !finishFetchMaskReg && f3_valid
60709c6f1ddSLingrui98  toFtq.pdWb.bits.pc         := preDecoderOut.pc
60809c6f1ddSLingrui98  toFtq.pdWb.bits.pd         := preDecoderOut.pd
6090be662e4SJay  toFtq.pdWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid :=  Mux(f3_mmio, f3_mmio_range(i), f3_predecode_range(i))}
61009c6f1ddSLingrui98  toFtq.pdWb.bits.ftqIdx     := f3_ftq_req.ftqIdx
61109c6f1ddSLingrui98  toFtq.pdWb.bits.ftqOffset  := f3_ftq_req.ftqOffset.bits
6120be662e4SJay  toFtq.pdWb.bits.misOffset  := Mux(f3_mmio, f3_mmio_missOffset, preDecoderOut.misOffset)
61309c6f1ddSLingrui98  toFtq.pdWb.bits.cfiOffset  := preDecoderOut.cfiOffset
6140be662e4SJay  toFtq.pdWb.bits.target     :=  Mux(f3_mmio,Mux(toFtq.pdWb.bits.pd(0).isRVC, toFtq.pdWb.bits.pc(0) + 2.U , toFtq.pdWb.bits.pc(0)+4.U) ,preDecoderOut.target)
61509c6f1ddSLingrui98  toFtq.pdWb.bits.jalTarget  := preDecoderOut.jalTarget
6160be662e4SJay  toFtq.pdWb.bits.instrRange := Mux(f3_mmio, f3_mmio_range, preDecoderOut.instrRange)
61709c6f1ddSLingrui98
6180be662e4SJay  val predecodeFlush     = ((preDecoderOut.misOffset.valid || f3_mmio) && f3_valid)
61909c6f1ddSLingrui98  val predecodeFlushReg  = RegNext(predecodeFlush && !(f2_fire && !f2_flush))
62009c6f1ddSLingrui98
621cd365d4cSrvcoresjw  val perfinfo = IO(new Bundle(){
622cd365d4cSrvcoresjw    val perfEvents = Output(new PerfEventsBundle(15))
623cd365d4cSrvcoresjw  })
624cd365d4cSrvcoresjw
625cd365d4cSrvcoresjw  val perfEvents = Seq(
626cd365d4cSrvcoresjw    ("frontendFlush                ", f3_redirect                                ),
627cd365d4cSrvcoresjw    ("ifu_req                      ", io.toIbuffer.fire()                        ),
628cd365d4cSrvcoresjw    ("ifu_miss                     ", io.toIbuffer.fire() && !f3_hit             ),
629cd365d4cSrvcoresjw    ("ifu_req_cacheline_0          ", f3_req_0                                   ),
630cd365d4cSrvcoresjw    ("ifu_req_cacheline_1          ", f3_req_1                                   ),
631cd365d4cSrvcoresjw    ("ifu_req_cacheline_0_hit      ", f3_hit_1                                   ),
632cd365d4cSrvcoresjw    ("ifu_req_cacheline_1_hit      ", f3_hit_1                                   ),
633cd365d4cSrvcoresjw    ("only_0_hit                   ", f3_only_0_hit       && io.toIbuffer.fire() ),
634cd365d4cSrvcoresjw    ("only_0_miss                  ", f3_only_0_miss      && io.toIbuffer.fire() ),
635cd365d4cSrvcoresjw    ("hit_0_hit_1                  ", f3_hit_0_hit_1      && io.toIbuffer.fire() ),
636cd365d4cSrvcoresjw    ("hit_0_miss_1                 ", f3_hit_0_miss_1     && io.toIbuffer.fire() ),
637cd365d4cSrvcoresjw    ("miss_0_hit_1                 ", f3_miss_0_hit_1     && io.toIbuffer.fire() ),
638cd365d4cSrvcoresjw    ("miss_0_miss_1                ", f3_miss_0_miss_1    && io.toIbuffer.fire() ),
639cd365d4cSrvcoresjw    ("cross_line_block             ", io.toIbuffer.fire() && f3_situation(0)     ),
640cd365d4cSrvcoresjw    ("fall_through_is_cacheline_end", io.toIbuffer.fire() && f3_situation(1)     ),
641cd365d4cSrvcoresjw  )
642cd365d4cSrvcoresjw
643cd365d4cSrvcoresjw  for (((perf_out,(perf_name,perf)),i) <- perfinfo.perfEvents.perf_events.zip(perfEvents).zipWithIndex) {
644cd365d4cSrvcoresjw    perf_out.incr_step := RegNext(perf)
645cd365d4cSrvcoresjw  }
646f7c29b0aSJinYue
64709c6f1ddSLingrui98  f3_redirect := !predecodeFlushReg && predecodeFlush
64809c6f1ddSLingrui98
649f7c29b0aSJinYue  XSPerfAccumulate("ifu_req",   io.toIbuffer.fire() )
650f7c29b0aSJinYue  XSPerfAccumulate("ifu_miss",  io.toIbuffer.fire() && !f3_hit )
651f7c29b0aSJinYue  XSPerfAccumulate("ifu_req_cacheline_0", f3_req_0  )
652f7c29b0aSJinYue  XSPerfAccumulate("ifu_req_cacheline_1", f3_req_1  )
653f7c29b0aSJinYue  XSPerfAccumulate("ifu_req_cacheline_0_hit",   f3_hit_0 )
654f7c29b0aSJinYue  XSPerfAccumulate("ifu_req_cacheline_1_hit",   f3_hit_1 )
65509c6f1ddSLingrui98  XSPerfAccumulate("frontendFlush",  f3_redirect )
656f7c29b0aSJinYue  XSPerfAccumulate("only_0_hit",      f3_only_0_hit   && io.toIbuffer.fire()  )
657f7c29b0aSJinYue  XSPerfAccumulate("only_0_miss",     f3_only_0_miss  && io.toIbuffer.fire()  )
658f7c29b0aSJinYue  XSPerfAccumulate("hit_0_hit_1",     f3_hit_0_hit_1  && io.toIbuffer.fire()  )
659f7c29b0aSJinYue  XSPerfAccumulate("hit_0_miss_1",    f3_hit_0_miss_1 && io.toIbuffer.fire()  )
660f7c29b0aSJinYue  XSPerfAccumulate("miss_0_hit_1",    f3_miss_0_hit_1  && io.toIbuffer.fire() )
661f7c29b0aSJinYue  XSPerfAccumulate("miss_0_miss_1",   f3_miss_0_miss_1 && io.toIbuffer.fire() )
662f7c29b0aSJinYue  XSPerfAccumulate("cross_line_block", io.toIbuffer.fire() && f3_situation(0) )
663f7c29b0aSJinYue  XSPerfAccumulate("fall_through_is_cacheline_end", io.toIbuffer.fire() && f3_situation(1) )
66409c6f1ddSLingrui98}
665