IFU.scala 38.4 KB
Newer Older
L
Lingrui98 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
* Copyright (c) 2020-2021 Peng Cheng Laboratory
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

J
JinYue 已提交
17 18 19 20 21
package xiangshan.frontend

import chipsalliance.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
J
Jay 已提交
22
import freechips.rocketchip.rocket.RVCDecoder
J
JinYue 已提交
23
import xiangshan._
J
JinYue 已提交
24
import xiangshan.cache.mmu._
25
import xiangshan.frontend.icache._
J
JinYue 已提交
26
import utils._
L
Lemover 已提交
27
import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle}
G
Guokai Chen 已提交
28
import huancun.utils.ChiselDB
J
JinYue 已提交
29

30 31
trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{
  def mmioBusWidth = 64
32
  def mmioBusBytes = mmioBusWidth / 8
33
  def maxInstrLen = 32
34 35
}

J
Jay 已提交
36
trait HasIFUConst extends HasXSParameter{
37 38 39
  def addrAlign(addr: UInt, bytes: Int, highest: Int): UInt = Cat(addr(highest-1, log2Ceil(bytes)), 0.U(log2Ceil(bytes).W))
  def fetchQueueSize = 2

J
Jay 已提交
40 41 42
  def getBasicBlockIdx( pc: UInt, start:  UInt ): UInt = {
    val byteOffset = pc - start
    (byteOffset - instBytes.U)(log2Ceil(PredictWidth),instOffsetBits)
43
  }
44
}
45

46 47 48 49
class IfuToFtqIO(implicit p:Parameters) extends XSBundle {
  val pdWb = Valid(new PredecodeWritebackBundle)
}

J
JinYue 已提交
50
class FtqInterface(implicit p: Parameters) extends XSBundle {
Z
zoujr 已提交
51
  val fromFtq = Flipped(new FtqToIfuIO)
Y
Yinan Xu 已提交
52
  val toFtq   = new IfuToFtqIO
53 54
}

55 56 57 58
class UncacheInterface(implicit p: Parameters) extends XSBundle {
  val fromUncache = Flipped(DecoupledIO(new InsUncacheResp))
  val toUncache   = DecoupledIO( new InsUncacheReq )
}
59

60
class NewIFUIO(implicit p: Parameters) extends XSBundle {
Y
Yinan Xu 已提交
61
  val ftqInter        = new FtqInterface
J
Jenius 已提交
62
  val icacheInter     = Flipped(new IFUICacheIO)
63 64
  val icacheStop      = Output(Bool())
  val icachePerfInfo  = Input(new ICachePerfInfo)
65
  val toIbuffer       = Decoupled(new FetchToIBuffer)
66
  val uncacheInter   =  new UncacheInterface
67 68
  val frontendTrigger = Flipped(new FrontendTdataDistributeIO)
  val csrTriggerEnable = Input(Vec(4, Bool()))
69
  val rob_commits = Flipped(Vec(CommitWidth, Valid(new RobCommitInfo)))
70
  val iTLBInter       = new TlbRequestIO
71
  val pmp             =   new ICachePMPBundle
72
  val mmioCommitRead  = new mmioCommitRead
J
JinYue 已提交
73 74
}

75 76 77 78 79 80 81 82
// record the situation in which fallThruAddr falls into
// the middle of an RVI inst
class LastHalfInfo(implicit p: Parameters) extends XSBundle {
  val valid = Bool()
  val middlePC = UInt(VAddrBits.W)
  def matchThisBlock(startAddr: UInt) = valid && middlePC === startAddr
}

83
class IfuToPreDecode(implicit p: Parameters) extends XSBundle {
J
Jay 已提交
84 85 86 87 88 89 90 91
  val data                =  if(HasCExtension) Vec(PredictWidth + 1, UInt(16.W)) else Vec(PredictWidth, UInt(32.W))
  val frontendTrigger     = new FrontendTdataDistributeIO
  val csrTriggerEnable    = Vec(4, Bool())
  val pc                  = Vec(PredictWidth, UInt(VAddrBits.W))
}


class IfuToPredChecker(implicit p: Parameters) extends XSBundle {
92
  val ftqOffset     = Valid(UInt(log2Ceil(PredictWidth).W))
J
Jay 已提交
93
  val jumpOffset    = Vec(PredictWidth, UInt(XLEN.W))
J
jinyue110 已提交
94
  val target        = UInt(VAddrBits.W)
J
Jay 已提交
95 96 97 98
  val instrRange    = Vec(PredictWidth, Bool())
  val instrValid    = Vec(PredictWidth, Bool())
  val pds           = Vec(PredictWidth, new PreDecodeInfo)
  val pc            = Vec(PredictWidth, UInt(VAddrBits.W))
99 100
}

G
Guokai Chen 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
class FetchToIBufferDB extends Bundle {
  val start_addr = UInt(39.W)
  val instr_count = UInt(32.W)
  val exception = Bool()
  val is_cache_hit = Bool()
}

class IfuWbToFtqDB extends Bundle {
  val start_addr = UInt(39.W)
  val is_miss_pred = Bool()
  val miss_pred_offset = UInt(32.W)
  val checkJalFault = Bool()
  val checkRetFault = Bool()
  val checkTargetFault = Bool()
  val checkNotCFIFault = Bool()
  val checkInvalidTaken = Bool()
}

J
Jay 已提交
119 120 121 122 123 124
class NewIFU(implicit p: Parameters) extends XSModule
  with HasICacheParameters
  with HasIFUConst
  with HasPdConst
  with HasCircularQueuePtrHelper
  with HasPerfEvents
J
JinYue 已提交
125
{
J
JinYue 已提交
126
  val io = IO(new NewIFUIO)
127
  val (toFtq, fromFtq)    = (io.ftqInter.toFtq, io.ftqInter.fromFtq)
J
Jenius 已提交
128
  val fromICache = io.icacheInter.resp
129
  val (toUncache, fromUncache) = (io.uncacheInter.toUncache , io.uncacheInter.fromUncache)
Y
Yinan Xu 已提交
130

131
  def isCrossLineReq(start: UInt, end: UInt): Bool = start(blockOffBits) ^ end(blockOffBits)
132

J
JinYue 已提交
133
  def isLastInCacheline(addr: UInt): Bool = addr(blockOffBits - 1, 1) === 0.U
134

135 136 137 138
  class TlbExept(implicit p: Parameters) extends XSBundle{
    val pageFault = Bool()
    val accessFault = Bool()
    val mmio = Bool()
139
  }
J
JinYue 已提交
140

J
Jenius 已提交
141 142
  val preDecoders       = Seq.fill(4){ Module(new PreDecode) }

J
Jay 已提交
143 144
  val predChecker     = Module(new PredChecker)
  val frontendTrigger = Module(new FrontendTrigger)
J
Jenius 已提交
145
  val (checkerIn, checkerOutStage1, checkerOutStage2)         = (predChecker.io.in, predChecker.io.out.stage1Out,predChecker.io.out.stage2Out)
146

147
  io.iTLBInter.req_kill := false.B
148
  io.iTLBInter.resp.ready := true.B
149

150 151 152 153 154 155
  /**
    ******************************************************************************
    * IFU Stage 0
    * - send cacheline fetch request to ICacheMainPipe
    ******************************************************************************
    */
Y
Yinan Xu 已提交
156

J
JinYue 已提交
157
  val f0_valid                             = fromFtq.req.valid
Z
zoujr 已提交
158
  val f0_ftq_req                           = fromFtq.req.bits
J
JinYue 已提交
159
  val f0_doubleLine                        = fromFtq.req.bits.crossCacheline
J
JinYue 已提交
160
  val f0_vSetIdx                           = VecInit(get_idx((f0_ftq_req.startAddr)), get_idx(f0_ftq_req.nextlineStart))
Z
zoujr 已提交
161
  val f0_fire                              = fromFtq.req.fire()
J
JinYue 已提交
162

J
JinYue 已提交
163
  val f0_flush, f1_flush, f2_flush, f3_flush = WireInit(false.B)
164
  val from_bpu_f0_flush, from_bpu_f1_flush, from_bpu_f2_flush, from_bpu_f3_flush = WireInit(false.B)
Y
Yinan Xu 已提交
165

L
Lingrui98 已提交
166 167
  from_bpu_f0_flush := fromFtq.flushFromBpu.shouldFlushByStage2(f0_ftq_req.ftqIdx) ||
                       fromFtq.flushFromBpu.shouldFlushByStage3(f0_ftq_req.ftqIdx)
168

J
Jay 已提交
169 170 171 172 173 174
  val wb_redirect , mmio_redirect,  backend_redirect= WireInit(false.B)
  val f3_wb_not_flush = WireInit(false.B)

  backend_redirect := fromFtq.redirect.valid
  f3_flush := backend_redirect || (wb_redirect && !f3_wb_not_flush)
  f2_flush := backend_redirect || mmio_redirect || wb_redirect
175 176
  f1_flush := f2_flush || from_bpu_f1_flush
  f0_flush := f1_flush || from_bpu_f0_flush
J
JinYue 已提交
177

J
JinYue 已提交
178 179
  val f1_ready, f2_ready, f3_ready         = WireInit(false.B)

J
Jenius 已提交
180
  fromFtq.req.ready := f1_ready && io.icacheInter.icacheReady
J
jinyue110 已提交
181

182
  /** <PERF> f0 fetch bubble */
J
jinyue110 已提交
183

184
  XSPerfAccumulate("fetch_bubble_ftq_not_valid",   !fromFtq.req.valid && fromFtq.req.ready  )
J
Jenius 已提交
185 186 187
  // XSPerfAccumulate("fetch_bubble_pipe_stall",    f0_valid && toICache(0).ready && toICache(1).ready && !f1_ready )
  // XSPerfAccumulate("fetch_bubble_icache_0_busy",   f0_valid && !toICache(0).ready  )
  // XSPerfAccumulate("fetch_bubble_icache_1_busy",   f0_valid && !toICache(1).ready  )
188 189 190 191
  XSPerfAccumulate("fetch_flush_backend_redirect",   backend_redirect  )
  XSPerfAccumulate("fetch_flush_wb_redirect",    wb_redirect  )
  XSPerfAccumulate("fetch_flush_bpu_f1_flush",   from_bpu_f1_flush  )
  XSPerfAccumulate("fetch_flush_bpu_f0_flush",   from_bpu_f0_flush  )
192 193 194 195 196 197 198 199


  /**
    ******************************************************************************
    * IFU Stage 1
    * - calculate pc/half_pc/cut_ptr for every instruction
    ******************************************************************************
    */
J
jinyue110 已提交
200

J
JinYue 已提交
201
  val f1_valid      = RegInit(false.B)
202 203 204 205
  val f1_ftq_req    = RegEnable(f0_ftq_req,    f0_fire)
  // val f1_situation  = RegEnable(f0_situation,  f0_fire)
  val f1_doubleLine = RegEnable(f0_doubleLine, f0_fire)
  val f1_vSetIdx    = RegEnable(f0_vSetIdx,    f0_fire)
206
  val f1_fire       = f1_valid && f2_ready
J
JinYue 已提交
207

208
  f1_ready := f1_fire || !f1_valid
Z
zoujr 已提交
209

210
  from_bpu_f1_flush := fromFtq.flushFromBpu.shouldFlushByStage3(f1_ftq_req.ftqIdx) && f1_valid
L
Lingrui98 已提交
211
  // from_bpu_f1_flush := false.B
212

L
Lingrui98 已提交
213 214 215
  when(f1_flush)                  {f1_valid  := false.B}
  .elsewhen(f0_fire && !f0_flush) {f1_valid  := true.B}
  .elsewhen(f1_fire)              {f1_valid  := false.B}
J
JinYue 已提交
216

J
Jay 已提交
217 218 219 220
  val f1_pc                 = VecInit((0 until PredictWidth).map(i => f1_ftq_req.startAddr + (i * 2).U))
  val f1_half_snpc          = VecInit((0 until PredictWidth).map(i => f1_ftq_req.startAddr + ((i+2) * 2).U))
  val f1_cut_ptr            = if(HasCExtension)  VecInit((0 until PredictWidth + 1).map(i =>  Cat(0.U(1.W), f1_ftq_req.startAddr(blockOffBits-1, 1)) + i.U ))
                                  else           VecInit((0 until PredictWidth).map(i =>     Cat(0.U(1.W), f1_ftq_req.startAddr(blockOffBits-1, 2)) + i.U ))
J
JinYue 已提交
221

222 223 224 225 226 227 228 229 230 231 232
  /**
    ******************************************************************************
    * IFU Stage 2
    * - icache response data (latched for pipeline stop)
    * - generate exceprion bits for every instruciton (page fault/access fault/mmio)
    * - generate predicted instruction range (1 means this instruciton is in this fetch packet)
    * - cut data from cachlines to packet instruction code
    * - instruction predecode and RVC expand
    ******************************************************************************
    */

233
  val icacheRespAllValid = WireInit(false.B)
234

235
  val f2_valid      = RegInit(false.B)
236 237 238 239
  val f2_ftq_req    = RegEnable(f1_ftq_req,    f1_fire)
  // val f2_situation  = RegEnable(f1_situation,  f1_fire)
  val f2_doubleLine = RegEnable(f1_doubleLine, f1_fire)
  val f2_vSetIdx    = RegEnable(f1_vSetIdx,    f1_fire)
240
  val f2_fire       = f2_valid && f3_ready && icacheRespAllValid
241

242
  f2_ready := f2_fire || !f2_valid
243
  //TODO: addr compare may be timing critical
J
JinYue 已提交
244
  val f2_icache_all_resp_wire       =  fromICache(0).valid && (fromICache(0).bits.vaddr ===  f2_ftq_req.startAddr) && ((fromICache(1).valid && (fromICache(1).bits.vaddr ===  f2_ftq_req.nextlineStart)) || !f2_doubleLine)
245
  val f2_icache_all_resp_reg        = RegInit(false.B)
J
JinYue 已提交
246

247
  icacheRespAllValid := f2_icache_all_resp_reg || f2_icache_all_resp_wire
248

249
  io.icacheStop := !f3_ready
J
JinYue 已提交
250

251 252 253
  when(f2_flush)                                              {f2_icache_all_resp_reg := false.B}
  .elsewhen(f2_valid && f2_icache_all_resp_wire && !f3_ready) {f2_icache_all_resp_reg := true.B}
  .elsewhen(f2_fire && f2_icache_all_resp_reg)                {f2_icache_all_resp_reg := false.B}
J
JinYue 已提交
254

L
Lingrui98 已提交
255 256
  when(f2_flush)                  {f2_valid := false.B}
  .elsewhen(f1_fire && !f1_flush) {f2_valid := true.B }
J
JinYue 已提交
257 258
  .elsewhen(f2_fire)              {f2_valid := false.B}

259
  // val f2_cache_response_data = ResultHoldBypass(valid = f2_icache_all_resp_wire, data = VecInit(fromICache.map(_.bits.readData)))
J
Jenius 已提交
260 261 262
  val f2_cache_response_reg_data  = VecInit(fromICache.map(_.bits.registerData))
  val f2_cache_response_sram_data = VecInit(fromICache.map(_.bits.sramData))
  val f2_cache_response_select    = VecInit(fromICache.map(_.bits.select))
263

J
jinyue110 已提交
264

265 266
  val f2_except_pf    = VecInit((0 until PortNumber).map(i => fromICache(i).bits.tlbExcp.pageFault))
  val f2_except_af    = VecInit((0 until PortNumber).map(i => fromICache(i).bits.tlbExcp.accessFault))
267
  val f2_mmio         = fromICache(0).bits.tlbExcp.mmio && !fromICache(0).bits.tlbExcp.accessFault &&
R
rvcoresjw 已提交
268
                                                           !fromICache(0).bits.tlbExcp.pageFault
J
jinyue110 已提交
269

270 271 272
  val f2_pc               = RegEnable(f1_pc,  f1_fire)
  val f2_half_snpc        = RegEnable(f1_half_snpc,  f1_fire)
  val f2_cut_ptr          = RegEnable(f1_cut_ptr,  f1_fire)
273

274
  val f2_resend_vaddr     = RegEnable(f1_ftq_req.startAddr + 2.U,  f1_fire)
J
Jay 已提交
275 276 277

  def isNextLine(pc: UInt, startAddr: UInt) = {
    startAddr(blockOffBits) ^ pc(blockOffBits)
J
JinYue 已提交
278 279
  }

J
Jay 已提交
280 281
  def isLastInLine(pc: UInt) = {
    pc(blockOffBits - 1, 0) === "b111110".U
282
  }
Y
Yinan Xu 已提交
283

J
Jay 已提交
284 285
  val f2_foldpc = VecInit(f2_pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth)))
  val f2_jump_range = Fill(PredictWidth, !f2_ftq_req.ftqOffset.valid) | Fill(PredictWidth, 1.U(1.W)) >> ~f2_ftq_req.ftqOffset.bits
J
JinYue 已提交
286
  val f2_ftr_range  = Fill(PredictWidth,  f2_ftq_req.ftqOffset.valid) | Fill(PredictWidth, 1.U(1.W)) >> ~getBasicBlockIdx(f2_ftq_req.nextStartAddr, f2_ftq_req.startAddr)
J
Jay 已提交
287 288 289
  val f2_instr_range = f2_jump_range & f2_ftr_range
  val f2_pf_vec = VecInit((0 until PredictWidth).map(i => (!isNextLine(f2_pc(i), f2_ftq_req.startAddr) && f2_except_pf(0)   ||  isNextLine(f2_pc(i), f2_ftq_req.startAddr) && f2_doubleLine &&  f2_except_pf(1))))
  val f2_af_vec = VecInit((0 until PredictWidth).map(i => (!isNextLine(f2_pc(i), f2_ftq_req.startAddr) && f2_except_af(0)   ||  isNextLine(f2_pc(i), f2_ftq_req.startAddr) && f2_doubleLine && f2_except_af(1))))
J
JinYue 已提交
290

291 292
  val f2_paddrs       = VecInit((0 until PortNumber).map(i => fromICache(i).bits.paddr))
  val f2_perf_info    = io.icachePerfInfo
J
JinYue 已提交
293

J
Jay 已提交
294
  def cut(cacheline: UInt, cutPtr: Vec[UInt]) : Vec[UInt] ={
J
Jenius 已提交
295 296 297
    require(HasCExtension)
    // if(HasCExtension){
      val partCacheline = cacheline((blockBytes * 8 * 2 * 3) / 4 - 1, 0)
298
      val result   = Wire(Vec(PredictWidth + 1, UInt(16.W)))
J
Jenius 已提交
299
      val dataVec  = cacheline.asTypeOf(Vec(blockBytes * 3 /4, UInt(16.W))) //47 16-bit data vector
300
      (0 until PredictWidth + 1).foreach( i =>
J
Jenius 已提交
301
        result(i) := dataVec(cutPtr(i)) //the max ptr is 3*blockBytes/4-1
302
      )
Y
Yinan Xu 已提交
303
      result
J
Jenius 已提交
304 305 306 307 308 309 310 311
    // } else {
    //   val result   = Wire(Vec(PredictWidth, UInt(32.W)) )
    //   val dataVec  = cacheline.asTypeOf(Vec(blockBytes * 2/ 4, UInt(32.W)))
    //   (0 until PredictWidth).foreach( i =>
    //     result(i) := dataVec(cutPtr(i))
    //   )
    //   result
    // }
312 313
  }

J
Jenius 已提交
314 315 316 317 318 319 320 321 322 323
  val f2_data_2_cacheline =  Wire(Vec(4, UInt((2 * blockBits).W)))
  f2_data_2_cacheline(0) := Cat(f2_cache_response_reg_data(1) , f2_cache_response_reg_data(0))
  f2_data_2_cacheline(1) := Cat(f2_cache_response_reg_data(1) , f2_cache_response_sram_data(0))
  f2_data_2_cacheline(2) := Cat(f2_cache_response_sram_data(1) , f2_cache_response_reg_data(0))
  f2_data_2_cacheline(3) := Cat(f2_cache_response_sram_data(1) , f2_cache_response_sram_data(0))

  val f2_cut_data   = VecInit(f2_data_2_cacheline.map(data => cut(  data, f2_cut_ptr )))

  val f2_predecod_ptr = Wire(UInt(2.W))
  f2_predecod_ptr := Cat(f2_cache_response_select(1),f2_cache_response_select(0))
J
JinYue 已提交
324

325
  /** predecode (include RVC expander) */
J
Jenius 已提交
326 327 328 329 330 331 332 333 334 335 336 337 338
  // preDecoderRegIn.data := f2_reg_cut_data
  // preDecoderRegInIn.frontendTrigger := io.frontendTrigger
  // preDecoderRegInIn.csrTriggerEnable := io.csrTriggerEnable
  // preDecoderRegIn.pc  := f2_pc

  val preDecoderOut = Mux1H(UIntToOH(f2_predecod_ptr), preDecoders.map(_.io.out))
  for(i <- 0 until 4){
    val preDecoderIn  = preDecoders(i).io.in
    preDecoderIn.data := f2_cut_data(i)
    preDecoderIn.frontendTrigger := io.frontendTrigger  
    preDecoderIn.csrTriggerEnable := io.csrTriggerEnable
    preDecoderIn.pc  := f2_pc
  }
J
JinYue 已提交
339

340 341
  //val f2_expd_instr     = preDecoderOut.expInstr
  val f2_instr          = preDecoderOut.instr
J
Jenius 已提交
342 343 344 345
  val f2_pd             = preDecoderOut.pd
  val f2_jump_offset    = preDecoderOut.jumpOffset
  val f2_hasHalfValid   =  preDecoderOut.hasHalfValid
  val f2_crossPageFault = VecInit((0 until PredictWidth).map(i => isLastInLine(f2_pc(i)) && !f2_except_pf(0) && f2_doubleLine &&  f2_except_pf(1) && !f2_pd(i).isRVC ))
J
JinYue 已提交
346

347 348
  XSPerfAccumulate("fetch_bubble_icache_not_resp",   f2_valid && !icacheRespAllValid )

J
JinYue 已提交
349

350 351 352 353 354 355 356 357 358 359
  /**
    ******************************************************************************
    * IFU Stage 3
    * - handle MMIO instruciton
    *  -send request to Uncache fetch Unit
    *  -every packet include 1 MMIO instruction
    *  -MMIO instructions will stop fetch pipeline until commiting from RoB
    *  -flush to snpc (send ifu_redirect to Ftq)
    * - Ibuffer enqueue
    * - check predict result in Frontend (jalFault/retFault/notCFIFault/invalidTakenFault/targetFault)
360
    * - handle last half RVI instruction
361 362 363
    ******************************************************************************
    */

J
JinYue 已提交
364
  val f3_valid          = RegInit(false.B)
365 366 367
  val f3_ftq_req        = RegEnable(f2_ftq_req,    f2_fire)
  // val f3_situation      = RegEnable(f2_situation,  f2_fire)
  val f3_doubleLine     = RegEnable(f2_doubleLine, f2_fire)
368 369
  val f3_fire           = io.toIbuffer.fire()

370
  f3_ready := f3_fire || !f3_valid
J
JinYue 已提交
371

J
Jenius 已提交
372
  val f3_cut_data       = RegEnable(next = f2_cut_data(f2_predecod_ptr), enable=f2_fire)
373 374 375 376 377

  val f3_except_pf      = RegEnable(f2_except_pf,  f2_fire)
  val f3_except_af      = RegEnable(f2_except_af,  f2_fire)
  val f3_mmio           = RegEnable(f2_mmio   ,  f2_fire)

378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
  //val f3_expd_instr     = RegEnable(next = f2_expd_instr,  enable = f2_fire)
  val f3_instr          = RegEnable(next = f2_instr, enable = f2_fire)
  val f3_expd_instr     = VecInit((0 until PredictWidth).map{ i => 
    val expander       = Module(new RVCExpander)
    expander.io.in := f3_instr(i)
    expander.io.out.bits
  })

  val f3_pd             = RegEnable(next = f2_pd,          enable = f2_fire)
  val f3_jump_offset    = RegEnable(next = f2_jump_offset, enable = f2_fire)
  val f3_af_vec         = RegEnable(next = f2_af_vec,      enable = f2_fire)
  val f3_pf_vec         = RegEnable(next = f2_pf_vec ,     enable = f2_fire)
  val f3_pc             = RegEnable(next = f2_pc,          enable = f2_fire)
  val f3_half_snpc        = RegEnable(next = f2_half_snpc, enable = f2_fire)
  val f3_instr_range    = RegEnable(next = f2_instr_range, enable = f2_fire)
  val f3_foldpc         = RegEnable(next = f2_foldpc,      enable = f2_fire)
  val f3_crossPageFault = RegEnable(next = f2_crossPageFault,      enable = f2_fire)
  val f3_hasHalfValid   = RegEnable(next = f2_hasHalfValid,      enable = f2_fire)
J
JinYue 已提交
396 397
  val f3_except         = VecInit((0 until 2).map{i => f3_except_pf(i) || f3_except_af(i)})
  val f3_has_except     = f3_valid && (f3_except_af.reduce(_||_) || f3_except_pf.reduce(_||_))
398 399
  val f3_pAddrs   = RegEnable(f2_paddrs,  f2_fire)
  val f3_resend_vaddr   = RegEnable(f2_resend_vaddr,       f2_fire)
400

J
JinYue 已提交
401 402 403
  when(f3_valid && !f3_ftq_req.ftqOffset.valid){
    assert(f3_ftq_req.startAddr + 32.U >= f3_ftq_req.nextStartAddr , "More tha 32 Bytes fetch is not allowed!")
  }
404

J
Jay 已提交
405
  /*** MMIO State Machine***/
406 407 408 409
  val f3_mmio_data    = Reg(Vec(2, UInt(16.W)))
  val mmio_is_RVC     = RegInit(false.B)
  val mmio_resend_addr =RegInit(0.U(PAddrBits.W))
  val mmio_resend_af  = RegInit(false.B)
410 411
  val mmio_resend_pf  = RegInit(false.B)

412 413 414
  //last instuction finish
  val is_first_instr = RegInit(true.B)
  io.mmioCommitRead.mmioFtqPtr := RegNext(f3_ftq_req.ftqIdx + 1.U)
415

416
  val m_idle :: m_waitLastCmt:: m_sendReq :: m_waitResp :: m_sendTLB :: m_tlbResp :: m_sendPMP :: m_resendReq :: m_waitResendResp :: m_waitCommit :: m_commited :: Nil = Enum(11)
417
  val mmio_state = RegInit(m_idle)
418

419
  val f3_req_is_mmio     = f3_mmio && f3_valid
J
Jay 已提交
420
  val mmio_commit = VecInit(io.rob_commits.map{commit => commit.valid && commit.bits.ftqIdx === f3_ftq_req.ftqIdx &&  commit.bits.ftqOffset === 0.U}).asUInt.orR
421
  val f3_mmio_req_commit = f3_req_is_mmio && mmio_state === m_commited
422

423
  val f3_mmio_to_commit =  f3_req_is_mmio && mmio_state === m_waitCommit
424 425 426
  val f3_mmio_to_commit_next = RegNext(f3_mmio_to_commit)
  val f3_mmio_can_go      = f3_mmio_to_commit && !f3_mmio_to_commit_next

427 428
  val fromFtqRedirectReg    = RegNext(fromFtq.redirect,init = 0.U.asTypeOf(fromFtq.redirect))
  val mmioF3Flush           = RegNext(f3_flush,init = false.B)
429 430
  val f3_ftq_flush_self     = fromFtqRedirectReg.valid && RedirectLevel.flushItself(fromFtqRedirectReg.bits.level)
  val f3_ftq_flush_by_older = fromFtqRedirectReg.valid && isBefore(fromFtqRedirectReg.bits.ftqIdx, f3_ftq_req.ftqIdx)
431

432
  val f3_need_not_flush = f3_req_is_mmio && fromFtqRedirectReg.valid && !f3_ftq_flush_self && !f3_ftq_flush_by_older
433

434 435 436 437
  when(is_first_instr && mmio_commit){
    is_first_instr := false.B
  }

438 439 440 441 442
  when(f3_flush && !f3_req_is_mmio)                                                 {f3_valid := false.B}
  .elsewhen(mmioF3Flush && f3_req_is_mmio && !f3_need_not_flush)                    {f3_valid := false.B}
  .elsewhen(f2_fire && !f2_flush )                                                  {f3_valid := true.B }
  .elsewhen(io.toIbuffer.fire() && !f3_req_is_mmio)                                 {f3_valid := false.B}
  .elsewhen{f3_req_is_mmio && f3_mmio_req_commit}                                   {f3_valid := false.B}
443 444 445

  val f3_mmio_use_seq_pc = RegInit(false.B)

446 447
  val (redirect_ftqIdx, redirect_ftqOffset)  = (fromFtqRedirectReg.bits.ftqIdx,fromFtqRedirectReg.bits.ftqOffset)
  val redirect_mmio_req = fromFtqRedirectReg.valid && redirect_ftqIdx === f3_ftq_req.ftqIdx && redirect_ftqOffset === 0.U
448 449 450 451 452 453

  when(RegNext(f2_fire && !f2_flush) && f3_req_is_mmio)        { f3_mmio_use_seq_pc := true.B  }
  .elsewhen(redirect_mmio_req)                                 { f3_mmio_use_seq_pc := false.B }

  f3_ready := Mux(f3_req_is_mmio, io.toIbuffer.ready && f3_mmio_req_commit || !f3_valid , io.toIbuffer.ready || !f3_valid)

454
  // mmio state machine
455
  switch(mmio_state){
456
    is(m_idle){
457
      when(f3_req_is_mmio){
458 459 460 461 462 463 464 465 466
        mmio_state :=  m_waitLastCmt
      }
    }

    is(m_waitLastCmt){
      when(is_first_instr){
        mmio_state := m_sendReq
      }.otherwise{
        mmio_state := Mux(io.mmioCommitRead.mmioLastCommit, m_sendReq, m_waitLastCmt)
467 468
      }
    }
469

470 471
    is(m_sendReq){
      mmio_state :=  Mux(toUncache.fire(), m_waitResp, m_sendReq )
472 473
    }

474
    is(m_waitResp){
475 476
      when(fromUncache.fire()){
          val isRVC =  fromUncache.bits.data(1,0) =/= 3.U
477 478 479 480 481 482
          val needResend = !isRVC && f3_pAddrs(0)(2,1) === 3.U
          mmio_state :=  Mux(needResend, m_sendTLB , m_waitCommit)

          mmio_is_RVC := isRVC
          f3_mmio_data(0)   :=  fromUncache.bits.data(15,0)
          f3_mmio_data(1)   :=  fromUncache.bits.data(31,16)
483
      }
484
    }
485

486
    is(m_sendTLB){
487 488 489
      when( io.iTLBInter.req.valid && !io.iTLBInter.resp.bits.miss ){
        mmio_state :=  m_tlbResp
      }
490 491 492
    }

    is(m_tlbResp){
493 494
      val tlbExept = io.iTLBInter.resp.bits.excp(0).pf.instr ||
                     io.iTLBInter.resp.bits.excp(0).af.instr
495
      mmio_state :=  Mux(tlbExept,m_waitCommit,m_sendPMP)
496
      mmio_resend_addr := io.iTLBInter.resp.bits.paddr(0)
497 498
      mmio_resend_af := mmio_resend_af || io.iTLBInter.resp.bits.excp(0).af.instr
      mmio_resend_pf := mmio_resend_pf || io.iTLBInter.resp.bits.excp(0).pf.instr
499 500 501
    }

    is(m_sendPMP){
502 503 504
      val pmpExcpAF = io.pmp.resp.instr || !io.pmp.resp.mmio
      mmio_state :=  Mux(pmpExcpAF, m_waitCommit , m_resendReq)
      mmio_resend_af := pmpExcpAF
505 506 507 508
    }

    is(m_resendReq){
      mmio_state :=  Mux(toUncache.fire(), m_waitResendResp, m_resendReq )
509
    }
510

511
    is(m_waitResendResp){
512
      when(fromUncache.fire()){
513 514
          mmio_state :=  m_waitCommit
          f3_mmio_data(1)   :=  fromUncache.bits.data(15,0)
515
      }
516
    }
517

518
    is(m_waitCommit){
J
Jay 已提交
519
      when(mmio_commit){
520
          mmio_state  :=  m_commited
521
      }
522
    }
J
Jay 已提交
523

524
    //normal mmio instruction
525
    is(m_commited){
526 527 528
      mmio_state := m_idle
      mmio_is_RVC := false.B
      mmio_resend_addr := 0.U
J
Jay 已提交
529
    }
530 531
  }

532
  //exception or flush by older branch prediction
J
Jay 已提交
533
  when(f3_ftq_flush_self || f3_ftq_flush_by_older)  {
534 535 536
    mmio_state := m_idle
    mmio_is_RVC := false.B
    mmio_resend_addr := 0.U
537
    mmio_resend_af := false.B
538
    f3_mmio_data.map(_ := 0.U)
539 540
  }

541 542
  toUncache.valid     :=  ((mmio_state === m_sendReq) || (mmio_state === m_resendReq)) && f3_req_is_mmio
  toUncache.bits.addr := Mux((mmio_state === m_resendReq), mmio_resend_addr, f3_pAddrs(0))
543 544
  fromUncache.ready   := true.B

545
  io.iTLBInter.req.valid         := (mmio_state === m_sendTLB) && f3_req_is_mmio
546
  io.iTLBInter.req.bits.size     := 3.U
547 548 549
  io.iTLBInter.req.bits.vaddr    := f3_resend_vaddr
  io.iTLBInter.req.bits.debug.pc := f3_resend_vaddr

550
  io.iTLBInter.req.bits.kill                := false.B // IFU use itlb for mmio, doesn't need sync, set it to false
551
  io.iTLBInter.req.bits.cmd                 := TlbCmd.exec
552
  io.iTLBInter.req.bits.debug.robIdx        := DontCare
553 554 555 556 557 558
  io.iTLBInter.req.bits.debug.isFirstIssue  := DontCare

  io.pmp.req.valid := (mmio_state === m_sendPMP) && f3_req_is_mmio
  io.pmp.req.bits.addr  := mmio_resend_addr
  io.pmp.req.bits.size  := 3.U
  io.pmp.req.bits.cmd   := TlbCmd.exec
J
JinYue 已提交
559

J
Jay 已提交
560 561 562 563 564 565 566 567 568
  val f3_lastHalf       = RegInit(0.U.asTypeOf(new LastHalfInfo))

  val f3_predecode_range = VecInit(preDecoderOut.pd.map(inst => inst.valid)).asUInt
  val f3_mmio_range      = VecInit((0 until PredictWidth).map(i => if(i ==0) true.B else false.B))
  val f3_instr_valid     = Wire(Vec(PredictWidth, Bool()))

  /*** prediction result check   ***/
  checkerIn.ftqOffset   := f3_ftq_req.ftqOffset
  checkerIn.jumpOffset  := f3_jump_offset
J
JinYue 已提交
569
  checkerIn.target      := f3_ftq_req.nextStartAddr
J
Jay 已提交
570 571 572 573 574
  checkerIn.instrRange  := f3_instr_range.asTypeOf(Vec(PredictWidth, Bool()))
  checkerIn.instrValid  := f3_instr_valid.asTypeOf(Vec(PredictWidth, Bool()))
  checkerIn.pds         := f3_pd
  checkerIn.pc          := f3_pc

575
  /*** handle half RVI in the last 2 Bytes  ***/
J
Jay 已提交
576 577

  def hasLastHalf(idx: UInt) = {
J
Jenius 已提交
578 579
    //!f3_pd(idx).isRVC && checkerOutStage1.fixedRange(idx) && f3_instr_valid(idx) && !checkerOutStage1.fixedTaken(idx) && !checkerOutStage2.fixedMissPred(idx) && ! f3_req_is_mmio
    !f3_pd(idx).isRVC && checkerOutStage1.fixedRange(idx) && f3_instr_valid(idx) && !checkerOutStage1.fixedTaken(idx) && ! f3_req_is_mmio
J
Jay 已提交
580 581
  }

J
Jenius 已提交
582
  val f3_last_validIdx             = ~ParallelPriorityEncoder(checkerOutStage1.fixedRange.reverse)
J
Jay 已提交
583 584 585 586 587 588

  val f3_hasLastHalf         = hasLastHalf((PredictWidth - 1).U)
  val f3_false_lastHalf      = hasLastHalf(f3_last_validIdx)
  val f3_false_snpc          = f3_half_snpc(f3_last_validIdx)

  val f3_lastHalf_mask    = VecInit((0 until PredictWidth).map( i => if(i ==0) false.B else true.B )).asUInt()
J
Jenius 已提交
589
  val f3_lastHalf_disable = RegInit(false.B)
J
JinYue 已提交
590

591 592 593 594
  when(f3_flush || (f3_fire && f3_lastHalf_disable)){
    f3_lastHalf_disable := false.B
  }

J
JinYue 已提交
595 596
  when (f3_flush) {
    f3_lastHalf.valid := false.B
J
Jay 已提交
597
  }.elsewhen (f3_fire) {
J
Jenius 已提交
598
    f3_lastHalf.valid := f3_hasLastHalf && !f3_lastHalf_disable
J
JinYue 已提交
599
    f3_lastHalf.middlePC := f3_ftq_req.nextStartAddr
600 601
  }

J
Jay 已提交
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
  f3_instr_valid := Mux(f3_lastHalf.valid,f3_hasHalfValid ,VecInit(f3_pd.map(inst => inst.valid)))

  /*** frontend Trigger  ***/
  frontendTrigger.io.pds  := f3_pd
  frontendTrigger.io.pc   := f3_pc
  frontendTrigger.io.data   := f3_cut_data

  frontendTrigger.io.frontendTrigger  := io.frontendTrigger
  frontendTrigger.io.csrTriggerEnable := io.csrTriggerEnable

  val f3_triggered = frontendTrigger.io.triggered

  /*** send to Ibuffer  ***/

  io.toIbuffer.valid            := f3_valid && (!f3_req_is_mmio || f3_mmio_can_go) && !f3_flush
  io.toIbuffer.bits.instrs      := f3_expd_instr
  io.toIbuffer.bits.valid       := f3_instr_valid.asUInt
J
Jenius 已提交
619
  io.toIbuffer.bits.enqEnable   := checkerOutStage1.fixedRange.asUInt & f3_instr_valid.asUInt
J
Jay 已提交
620 621 622
  io.toIbuffer.bits.pd          := f3_pd
  io.toIbuffer.bits.ftqPtr      := f3_ftq_req.ftqIdx
  io.toIbuffer.bits.pc          := f3_pc
J
Jenius 已提交
623
  io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := checkerOutStage1.fixedTaken(i) && !f3_req_is_mmio}
J
Jay 已提交
624
  io.toIbuffer.bits.foldpc      := f3_foldpc
625
  io.toIbuffer.bits.ipf         := VecInit(f3_pf_vec.zip(f3_crossPageFault).map{case (pf, crossPF) => pf || crossPF})
J
Jay 已提交
626 627 628 629 630
  io.toIbuffer.bits.acf         := f3_af_vec
  io.toIbuffer.bits.crossPageIPFFix := f3_crossPageFault
  io.toIbuffer.bits.triggered   := f3_triggered

  when(f3_lastHalf.valid){
J
Jenius 已提交
631
    io.toIbuffer.bits.enqEnable := checkerOutStage1.fixedRange.asUInt & f3_instr_valid.asUInt & f3_lastHalf_mask
J
Jay 已提交
632 633 634
    io.toIbuffer.bits.valid     := f3_lastHalf_mask & f3_instr_valid.asUInt
  }

635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657


  //Write back to Ftq
  val f3_cache_fetch = f3_valid && !(f2_fire && !f2_flush)
  val finishFetchMaskReg = RegNext(f3_cache_fetch)

  val mmioFlushWb = Wire(Valid(new PredecodeWritebackBundle))
  val f3_mmio_missOffset = Wire(ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))
  f3_mmio_missOffset.valid := f3_req_is_mmio
  f3_mmio_missOffset.bits  := 0.U

  mmioFlushWb.valid           := (f3_req_is_mmio && mmio_state === m_waitCommit && RegNext(fromUncache.fire())  && f3_mmio_use_seq_pc)
  mmioFlushWb.bits.pc         := f3_pc
  mmioFlushWb.bits.pd         := f3_pd
  mmioFlushWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid :=  f3_mmio_range(i)}
  mmioFlushWb.bits.ftqIdx     := f3_ftq_req.ftqIdx
  mmioFlushWb.bits.ftqOffset  := f3_ftq_req.ftqOffset.bits
  mmioFlushWb.bits.misOffset  := f3_mmio_missOffset
  mmioFlushWb.bits.cfiOffset  := DontCare
  mmioFlushWb.bits.target     := Mux(mmio_is_RVC, f3_ftq_req.startAddr + 2.U , f3_ftq_req.startAddr + 4.U)
  mmioFlushWb.bits.jalTarget  := DontCare
  mmioFlushWb.bits.instrRange := f3_mmio_range

J
Jay 已提交
658 659
  /** external predecode for MMIO instruction */
  when(f3_req_is_mmio){
660
    val inst  = Cat(f3_mmio_data(1), f3_mmio_data(0))
J
Jay 已提交
661 662 663 664 665 666 667 668
    val currentIsRVC   = isRVC(inst)

    val brType::isCall::isRet::Nil = brInfo(inst)
    val jalOffset = jal_offset(inst, currentIsRVC)
    val brOffset  = br_offset(inst, currentIsRVC)

    io.toIbuffer.bits.instrs (0) := new RVCDecoder(inst, XLEN).decode.bits

669

J
Jay 已提交
670 671 672 673 674 675
    io.toIbuffer.bits.pd(0).valid   := true.B
    io.toIbuffer.bits.pd(0).isRVC   := currentIsRVC
    io.toIbuffer.bits.pd(0).brType  := brType
    io.toIbuffer.bits.pd(0).isCall  := isCall
    io.toIbuffer.bits.pd(0).isRet   := isRet

676
    io.toIbuffer.bits.acf(0) := mmio_resend_af
677 678
    io.toIbuffer.bits.ipf(0) := mmio_resend_pf
    io.toIbuffer.bits.crossPageIPFFix(0) := mmio_resend_pf
679

J
Jay 已提交
680
    io.toIbuffer.bits.enqEnable   := f3_mmio_range.asUInt
681

682 683 684 685 686 687
    mmioFlushWb.bits.pd(0).valid   := true.B
    mmioFlushWb.bits.pd(0).isRVC   := currentIsRVC
    mmioFlushWb.bits.pd(0).brType  := brType
    mmioFlushWb.bits.pd(0).isCall  := isCall
    mmioFlushWb.bits.pd(0).isRet   := isRet
  }
J
Jay 已提交
688

689
  mmio_redirect := (f3_req_is_mmio && mmio_state === m_waitCommit && RegNext(fromUncache.fire())  && f3_mmio_use_seq_pc)
J
Jay 已提交
690

691 692 693
  XSPerfAccumulate("fetch_bubble_ibuffer_not_ready",   io.toIbuffer.valid && !io.toIbuffer.ready )


694 695 696 697
  /**
    ******************************************************************************
    * IFU Write Back Stage
    * - write back predecode information to Ftq to update
698
    * - redirect if found fault prediction
699 700 701 702
    * - redirect if has false hit last half (last PC is not start + 32 Bytes, but in the midle of an notCFI RVI instruction)
    ******************************************************************************
    */

J
Jay 已提交
703 704 705
  val wb_valid          = RegNext(RegNext(f2_fire && !f2_flush) && !f3_req_is_mmio && !f3_flush)
  val wb_ftq_req        = RegNext(f3_ftq_req)

J
Jenius 已提交
706 707
  val wb_check_result_stage1   = RegNext(checkerOutStage1)
  val wb_check_result_stage2   = checkerOutStage2
J
Jay 已提交
708 709 710 711 712 713 714
  val wb_instr_range    = RegNext(io.toIbuffer.bits.enqEnable)
  val wb_pc             = RegNext(f3_pc)
  val wb_pd             = RegNext(f3_pd)
  val wb_instr_valid    = RegNext(f3_instr_valid)

  /* false hit lastHalf */
  val wb_lastIdx        = RegNext(f3_last_validIdx)
715
  val wb_false_lastHalf = RegNext(f3_false_lastHalf) && wb_lastIdx =/= (PredictWidth - 1).U
J
Jay 已提交
716
  val wb_false_target   = RegNext(f3_false_snpc)
717

J
Jay 已提交
718 719 720
  val wb_half_flush = wb_false_lastHalf
  val wb_half_target = wb_false_target

721 722
  /* false oversize */
  val lastIsRVC = wb_instr_range.asTypeOf(Vec(PredictWidth,Bool())).last  && wb_pd.last.isRVC
723
  val lastIsRVI = wb_instr_range.asTypeOf(Vec(PredictWidth,Bool()))(PredictWidth - 2) && !wb_pd(PredictWidth - 2).isRVC
J
Jenius 已提交
724
  val lastTaken = wb_check_result_stage1.fixedTaken.last
725

J
Jay 已提交
726 727
  f3_wb_not_flush := wb_ftq_req.ftqIdx === f3_ftq_req.ftqIdx && f3_valid && wb_valid

J
Jenius 已提交
728 729 730
  /** if a req with a last half but miss predicted enters in wb stage, and this cycle f3 stalls,  
    * we set a flag to notify f3 that the last half flag need not to be set.
    */
731
  //f3_fire is after wb_valid
732
  when(wb_valid && RegNext(f3_hasLastHalf,init = false.B) 
733
        && wb_check_result_stage2.fixedMissPred(PredictWidth - 1) && !f3_fire  && !RegNext(f3_fire,init = false.B) && !f3_flush
J
Jenius 已提交
734 735
      ){
    f3_lastHalf_disable := true.B
J
Jenius 已提交
736 737
  }

738
  //wb_valid and f3_fire are in same cycle
739 740
  when(wb_valid && RegNext(f3_hasLastHalf,init = false.B) 
        && wb_check_result_stage2.fixedMissPred(PredictWidth - 1) && f3_fire
741 742 743 744
      ){
    f3_lastHalf.valid := false.B
  }

J
Jay 已提交
745 746 747 748 749 750 751
  val checkFlushWb = Wire(Valid(new PredecodeWritebackBundle))
  checkFlushWb.valid                  := wb_valid
  checkFlushWb.bits.pc                := wb_pc
  checkFlushWb.bits.pd                := wb_pd
  checkFlushWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid := wb_instr_valid(i)}
  checkFlushWb.bits.ftqIdx            := wb_ftq_req.ftqIdx
  checkFlushWb.bits.ftqOffset         := wb_ftq_req.ftqOffset.bits
J
Jenius 已提交
752 753 754 755 756 757
  checkFlushWb.bits.misOffset.valid   := ParallelOR(wb_check_result_stage2.fixedMissPred) || wb_half_flush
  checkFlushWb.bits.misOffset.bits    := Mux(wb_half_flush, wb_lastIdx, ParallelPriorityEncoder(wb_check_result_stage2.fixedMissPred))
  checkFlushWb.bits.cfiOffset.valid   := ParallelOR(wb_check_result_stage1.fixedTaken)
  checkFlushWb.bits.cfiOffset.bits    := ParallelPriorityEncoder(wb_check_result_stage1.fixedTaken)
  checkFlushWb.bits.target            := Mux(wb_half_flush, wb_half_target, wb_check_result_stage2.fixedTarget(ParallelPriorityEncoder(wb_check_result_stage2.fixedMissPred)))
  checkFlushWb.bits.jalTarget         := wb_check_result_stage2.fixedTarget(ParallelPriorityEncoder(VecInit(wb_pd.zip(wb_instr_valid).map{case (pd, v) => v && pd.isJal })))
J
Jay 已提交
758 759
  checkFlushWb.bits.instrRange        := wb_instr_range.asTypeOf(Vec(PredictWidth, Bool()))

760
  toFtq.pdWb := Mux(wb_valid, checkFlushWb,  mmioFlushWb)
761

J
Jay 已提交
762
  wb_redirect := checkFlushWb.bits.misOffset.valid && wb_valid
763

764
  /*write back flush type*/
J
Jenius 已提交
765
  val checkFaultType = wb_check_result_stage2.faultType
766 767 768 769 770 771 772 773 774 775 776 777 778 779
  val checkJalFault =  wb_valid && checkFaultType.map(_.isjalFault).reduce(_||_)
  val checkRetFault =  wb_valid && checkFaultType.map(_.isRetFault).reduce(_||_)
  val checkTargetFault =  wb_valid && checkFaultType.map(_.istargetFault).reduce(_||_)
  val checkNotCFIFault =  wb_valid && checkFaultType.map(_.notCFIFault).reduce(_||_)
  val checkInvalidTaken =  wb_valid && checkFaultType.map(_.invalidTakenFault).reduce(_||_)


  XSPerfAccumulate("predecode_flush_jalFault",   checkJalFault )
  XSPerfAccumulate("predecode_flush_retFault",   checkRetFault )
  XSPerfAccumulate("predecode_flush_targetFault",   checkTargetFault )
  XSPerfAccumulate("predecode_flush_notCFIFault",   checkNotCFIFault )
  XSPerfAccumulate("predecode_flush_incalidTakenFault",   checkInvalidTaken )

  when(checkRetFault){
780
    XSDebug("startAddr:%x  nextstartAddr:%x  taken:%d    takenIdx:%d\n",
781 782 783
        wb_ftq_req.startAddr, wb_ftq_req.nextStartAddr, wb_ftq_req.ftqOffset.valid, wb_ftq_req.ftqOffset.bits)
  }

G
Guokai Chen 已提交
784

785
  /** performance counter */
786
  val f3_perf_info     = RegEnable(f2_perf_info,  f2_fire)
787 788 789 790 791
  val f3_req_0    = io.toIbuffer.fire()
  val f3_req_1    = io.toIbuffer.fire() && f3_doubleLine
  val f3_hit_0    = io.toIbuffer.fire() && f3_perf_info.bank_hit(0)
  val f3_hit_1    = io.toIbuffer.fire() && f3_doubleLine & f3_perf_info.bank_hit(1)
  val f3_hit      = f3_perf_info.hit
792
  val perfEvents = Seq(
J
Jay 已提交
793
    ("frontendFlush                ", wb_redirect                                ),
794
    ("ifu_req                      ", io.toIbuffer.fire()                        ),
795
    ("ifu_miss                     ", io.toIbuffer.fire() && !f3_perf_info.hit   ),
796 797 798 799
    ("ifu_req_cacheline_0          ", f3_req_0                                   ),
    ("ifu_req_cacheline_1          ", f3_req_1                                   ),
    ("ifu_req_cacheline_0_hit      ", f3_hit_1                                   ),
    ("ifu_req_cacheline_1_hit      ", f3_hit_1                                   ),
800 801 802 803 804 805
    ("only_0_hit                   ", f3_perf_info.only_0_hit       && io.toIbuffer.fire() ),
    ("only_0_miss                  ", f3_perf_info.only_0_miss      && io.toIbuffer.fire() ),
    ("hit_0_hit_1                  ", f3_perf_info.hit_0_hit_1      && io.toIbuffer.fire() ),
    ("hit_0_miss_1                 ", f3_perf_info.hit_0_miss_1     && io.toIbuffer.fire() ),
    ("miss_0_hit_1                 ", f3_perf_info.miss_0_hit_1     && io.toIbuffer.fire() ),
    ("miss_0_miss_1                ", f3_perf_info.miss_0_miss_1    && io.toIbuffer.fire() ),
806
  )
807
  generatePerfEvent()
J
JinYue 已提交
808

J
JinYue 已提交
809 810 811 812 813 814
  XSPerfAccumulate("ifu_req",   io.toIbuffer.fire() )
  XSPerfAccumulate("ifu_miss",  io.toIbuffer.fire() && !f3_hit )
  XSPerfAccumulate("ifu_req_cacheline_0", f3_req_0  )
  XSPerfAccumulate("ifu_req_cacheline_1", f3_req_1  )
  XSPerfAccumulate("ifu_req_cacheline_0_hit",   f3_hit_0 )
  XSPerfAccumulate("ifu_req_cacheline_1_hit",   f3_hit_1 )
J
Jay 已提交
815
  XSPerfAccumulate("frontendFlush",  wb_redirect )
816 817 818 819 820 821
  XSPerfAccumulate("only_0_hit",      f3_perf_info.only_0_hit   && io.toIbuffer.fire()  )
  XSPerfAccumulate("only_0_miss",     f3_perf_info.only_0_miss  && io.toIbuffer.fire()  )
  XSPerfAccumulate("hit_0_hit_1",     f3_perf_info.hit_0_hit_1  && io.toIbuffer.fire()  )
  XSPerfAccumulate("hit_0_miss_1",    f3_perf_info.hit_0_miss_1  && io.toIbuffer.fire()  )
  XSPerfAccumulate("miss_0_hit_1",    f3_perf_info.miss_0_hit_1   && io.toIbuffer.fire() )
  XSPerfAccumulate("miss_0_miss_1",   f3_perf_info.miss_0_miss_1 && io.toIbuffer.fire() )
822 823 824
  XSPerfAccumulate("hit_0_except_1",   f3_perf_info.hit_0_except_1 && io.toIbuffer.fire() )
  XSPerfAccumulate("miss_0_except_1",   f3_perf_info.miss_0_except_1 && io.toIbuffer.fire() )
  XSPerfAccumulate("except_0",   f3_perf_info.except_0 && io.toIbuffer.fire() )
G
Guokai Chen 已提交
825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860

  val fetchToIBufferTable = ChiselDB.createTable("FetchToIBuffer" + p(XSCoreParamsKey).HartId.toString, new FetchToIBufferDB)
  val ifuWbToFtqTable = ChiselDB.createTable("IfuWbToFtq" + p(XSCoreParamsKey).HartId.toString, new IfuWbToFtqDB)

  val fetchIBufferDumpData = Wire(new FetchToIBufferDB)
  fetchIBufferDumpData.start_addr := f3_ftq_req.startAddr
  fetchIBufferDumpData.instr_count := PopCount(io.toIbuffer.bits.enqEnable)
  fetchIBufferDumpData.exception := (f3_perf_info.except_0 && io.toIbuffer.fire()) || (f3_perf_info.hit_0_except_1 && io.toIbuffer.fire()) || (f3_perf_info.miss_0_except_1 && io.toIbuffer.fire())
  fetchIBufferDumpData.is_cache_hit := f3_hit

  val ifuWbToFtqDumpData = Wire(new IfuWbToFtqDB)
  ifuWbToFtqDumpData.start_addr := wb_ftq_req.startAddr
  ifuWbToFtqDumpData.is_miss_pred := checkFlushWb.bits.misOffset.valid
  ifuWbToFtqDumpData.miss_pred_offset := checkFlushWb.bits.misOffset.bits
  ifuWbToFtqDumpData.checkJalFault := checkJalFault
  ifuWbToFtqDumpData.checkRetFault := checkRetFault
  ifuWbToFtqDumpData.checkTargetFault := checkTargetFault
  ifuWbToFtqDumpData.checkNotCFIFault := checkNotCFIFault
  ifuWbToFtqDumpData.checkInvalidTaken := checkInvalidTaken

  fetchToIBufferTable.log(
    data = fetchIBufferDumpData,
    en = io.toIbuffer.fire(),
    site = "IFU" + p(XSCoreParamsKey).HartId.toString,
    clock = clock,
    reset = reset
  )
  ifuWbToFtqTable.log(
    data = ifuWbToFtqDumpData,
    en = checkFlushWb.valid,
    site = "IFU" + p(XSCoreParamsKey).HartId.toString,
    clock = clock,
    reset = reset
  )


861
}
J
Jenius 已提交
862