IFU.scala 30.0 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 22
package xiangshan.frontend

import chipsalliance.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
import xiangshan._
J
jinyue110 已提交
23
import xiangshan.cache._
J
JinYue 已提交
24
import xiangshan.cache.mmu._
J
JinYue 已提交
25
import chisel3.experimental.verification
J
JinYue 已提交
26
import utils._
L
Lemover 已提交
27
import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle}
J
JinYue 已提交
28

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

trait HasIFUConst extends HasXSParameter {
  def align(pc: UInt, bytes: Int): UInt = Cat(pc(VAddrBits-1, log2Ceil(bytes)), 0.U(log2Ceil(bytes).W))
37 38
  // def groupAligned(pc: UInt)  = align(pc, groupBytes)
  // def packetAligned(pc: UInt) = align(pc, packetBytes)
39
}
40

41 42 43 44
class IfuToFtqIO(implicit p:Parameters) extends XSBundle {
  val pdWb = Valid(new PredecodeWritebackBundle)
}

J
JinYue 已提交
45
class FtqInterface(implicit p: Parameters) extends XSBundle {
Z
zoujr 已提交
46
  val fromFtq = Flipped(new FtqToIfuIO)
Y
Yinan Xu 已提交
47
  val toFtq   = new IfuToFtqIO
48 49
}

50 51 52 53 54
class UncacheInterface(implicit p: Parameters) extends XSBundle {
  val fromUncache = Flipped(DecoupledIO(new InsUncacheResp))
  val toUncache   = DecoupledIO( new InsUncacheReq )
}

55 56 57 58 59 60
class ICacheInterface(implicit p: Parameters) extends XSBundle {
  val toIMeta       = Decoupled(new ICacheReadBundle)
  val toIData       = Decoupled(new ICacheReadBundle)
  val toMissQueue   = Vec(2,Decoupled(new ICacheMissReq))
  val fromIMeta     = Input(new ICacheMetaRespBundle)
  val fromIData     = Input(new ICacheDataRespBundle)
61
  val fromMissQueue = Vec(2,Flipped(Decoupled(new ICacheMissResp)))
J
JinYue 已提交
62 63
}

64
class NewIFUIO(implicit p: Parameters) extends XSBundle {
Y
Yinan Xu 已提交
65 66
  val ftqInter        = new FtqInterface
  val icacheInter     = new ICacheInterface
67
  val toIbuffer       = Decoupled(new FetchToIBuffer)
Y
Yinan Xu 已提交
68
  val iTLBInter       = Vec(2, new BlockTlbRequestIO)
69
  val uncacheInter   =  new UncacheInterface
L
Lemover 已提交
70 71
  val pmp             = Vec(2, new Bundle {
    val req = Valid(new PMPReqBundle())
72
    val resp = Flipped(new PMPRespBundle())
L
Lemover 已提交
73
  })
J
JinYue 已提交
74 75
}

76 77 78 79 80 81 82 83
// 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
}

84
class IfuToPreDecode(implicit p: Parameters) extends XSBundle {
Y
Yinan Xu 已提交
85
  val data          = if(HasCExtension) Vec(PredictWidth + 1, UInt(16.W)) else Vec(PredictWidth, UInt(32.W))
86
  val startAddr     = UInt(VAddrBits.W)
87
  val fallThruAddr  = UInt(VAddrBits.W)
J
JinYue 已提交
88
  val fallThruError = Bool()
J
JinYue 已提交
89
  val isDoubleLine  = Bool()
90
  val ftqOffset     = Valid(UInt(log2Ceil(PredictWidth).W))
J
jinyue110 已提交
91
  val target        = UInt(VAddrBits.W)
J
JinYue 已提交
92 93
  val pageFault     = Vec(2, Bool())
  val accessFault   = Vec(2, Bool())
Y
Yinan Xu 已提交
94
  val instValid     = Bool()
95
  val lastHalfMatch = Bool()
96
  val oversize      = Bool()
97
  val mmio = Bool()
98 99
}

100
class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
J
JinYue 已提交
101
{
102
  println(s"icache ways: ${nWays} sets:${nSets}")
J
JinYue 已提交
103
  val io = IO(new NewIFUIO)
104 105 106
  val (toFtq, fromFtq)    = (io.ftqInter.toFtq, io.ftqInter.fromFtq)
  val (toMeta, toData, meta_resp, data_resp) =  (io.icacheInter.toIMeta, io.icacheInter.toIData, io.icacheInter.fromIMeta, io.icacheInter.fromIData)
  val (toMissQueue, fromMissQueue) = (io.icacheInter.toMissQueue, io.icacheInter.fromMissQueue)
107
  val (toUncache, fromUncache) = (io.uncacheInter.toUncache , io.uncacheInter.fromUncache)
J
JinYue 已提交
108
  val (toITLB, fromITLB) = (VecInit(io.iTLBInter.map(_.req)), VecInit(io.iTLBInter.map(_.resp)))
L
Lemover 已提交
109
  val fromPMP = io.pmp.map(_.resp)
Y
Yinan Xu 已提交
110

111
  def isCrossLineReq(start: UInt, end: UInt): Bool = start(blockOffBits) ^ end(blockOffBits)
112

113
  def isLastInCacheline(fallThruAddr: UInt): Bool = fallThruAddr(blockOffBits - 1, 1) === 0.U
114

J
JinYue 已提交
115

J
jinyue110 已提交
116 117 118 119 120
  //---------------------------------------------
  //  Fetch Stage 1 :
  //  * Send req to ICache Meta/Data
  //  * Check whether need 2 line fetch
  //---------------------------------------------
Y
Yinan Xu 已提交
121

J
JinYue 已提交
122
  val f0_valid                             = fromFtq.req.valid
Z
zoujr 已提交
123
  val f0_ftq_req                           = fromFtq.req.bits
J
jinyue110 已提交
124 125
  val f0_situation                         = VecInit(Seq(isCrossLineReq(f0_ftq_req.startAddr, f0_ftq_req.fallThruAddr), isLastInCacheline(f0_ftq_req.fallThruAddr)))
  val f0_doubleLine                        = f0_situation(0) || f0_situation(1)
J
JinYue 已提交
126
  val f0_vSetIdx                           = VecInit(get_idx((f0_ftq_req.startAddr)), get_idx(f0_ftq_req.fallThruAddr))
Z
zoujr 已提交
127
  val f0_fire                              = fromFtq.req.fire()
J
JinYue 已提交
128

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

132 133 134
  from_bpu_f0_flush := fromFtq.flushFromBpu.shouldFlushByStage2(f0_ftq_req.ftqIdx) ||
                       fromFtq.flushFromBpu.shouldFlushByStage3(f0_ftq_req.ftqIdx)

J
JinYue 已提交
135 136 137
  val f3_redirect = WireInit(false.B)
  f3_flush := fromFtq.redirect.valid
  f2_flush := f3_flush || f3_redirect
138 139
  f1_flush := f2_flush || from_bpu_f1_flush
  f0_flush := f1_flush || from_bpu_f0_flush
J
JinYue 已提交
140

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

143
  //fetch: send addr to Meta/TLB and Data simultaneously
J
jinyue110 已提交
144
  val fetch_req = List(toMeta, toData)
145
  for(i <- 0 until 2) {
146
    fetch_req(i).valid := f0_fire
147 148 149
    fetch_req(i).bits.isDoubleLine := f0_doubleLine
    fetch_req(i).bits.vSetIdx := f0_vSetIdx
  }
150

J
JinYue 已提交
151
  fromFtq.req.ready := fetch_req(0).ready && fetch_req(1).ready && f1_ready && GTimer() > 500.U
J
jinyue110 已提交
152

J
JinYue 已提交
153 154 155 156 157
  XSPerfAccumulate("ifu_bubble_ftq_not_valid",   !f0_valid )
  XSPerfAccumulate("ifu_bubble_pipe_stall",    f0_valid && fetch_req(0).ready && fetch_req(1).ready && !f1_ready )
  XSPerfAccumulate("ifu_bubble_sram_0_busy",   f0_valid && !fetch_req(0).ready  )
  XSPerfAccumulate("ifu_bubble_sram_1_busy",   f0_valid && !fetch_req(1).ready  )

J
jinyue110 已提交
158 159
  //---------------------------------------------
  //  Fetch Stage 2 :
J
JinYue 已提交
160
  //  * Send req to ITLB and TLB Response (Get Paddr)
J
jinyue110 已提交
161 162 163 164
  //  * ICache Response (Get Meta and Data)
  //  * Hit Check (Generate hit signal and hit vector)
  //  * Get victim way
  //---------------------------------------------
J
JinYue 已提交
165

J
jinyue110 已提交
166 167
  //TODO: handle fetch exceptions

J
JinYue 已提交
168
  val tlbRespAllValid = WireInit(false.B)
J
jinyue110 已提交
169

J
JinYue 已提交
170
  val f1_valid      = RegInit(false.B)
J
jinyue110 已提交
171 172 173 174
  val f1_ftq_req    = RegEnable(next = f0_ftq_req,    enable=f0_fire)
  val f1_situation  = RegEnable(next = f0_situation,  enable=f0_fire)
  val f1_doubleLine = RegEnable(next = f0_doubleLine, enable=f0_fire)
  val f1_vSetIdx    = RegEnable(next = f0_vSetIdx,    enable=f0_fire)
J
JinYue 已提交
175 176 177
  val f1_fire       = f1_valid && tlbRespAllValid && f2_ready

  f1_ready := f2_ready && tlbRespAllValid || !f1_valid
Z
zoujr 已提交
178

179 180
  from_bpu_f1_flush := fromFtq.flushFromBpu.shouldFlushByStage3(f1_ftq_req.ftqIdx)

Z
zoujr 已提交
181 182 183 184
  val preDecoder      = Module(new PreDecode)
  val (preDecoderIn, preDecoderOut)   = (preDecoder.io.in, preDecoder.io.out)

  //flush generate and to Ftq
J
JinYue 已提交
185
  val predecodeOutValid = WireInit(false.B)
J
jinyue110 已提交
186

L
Lingrui98 已提交
187 188 189
  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 已提交
190

J
JinYue 已提交
191
  toITLB(0).valid         := f1_valid
L
Lemover 已提交
192
  toITLB(0).bits.size     := 3.U // TODO: fix the size
J
JinYue 已提交
193 194
  toITLB(0).bits.vaddr    := align(f1_ftq_req.startAddr, blockBytes)
  toITLB(0).bits.debug.pc := align(f1_ftq_req.startAddr, blockBytes)
Y
Yinan Xu 已提交
195

J
JinYue 已提交
196
  toITLB(1).valid         := f1_valid && f1_doubleLine
L
Lemover 已提交
197
  toITLB(1).bits.size     := 3.U // TODO: fix the size
J
JinYue 已提交
198 199 200 201 202
  toITLB(1).bits.vaddr    := align(f1_ftq_req.fallThruAddr, blockBytes)
  toITLB(1).bits.debug.pc := align(f1_ftq_req.fallThruAddr, blockBytes)

  toITLB.map{port =>
    port.bits.cmd                 := TlbCmd.exec
Y
Yinan Xu 已提交
203
    port.bits.robIdx              := DontCare
J
JinYue 已提交
204 205 206 207 208 209
    port.bits.debug.isFirstIssue  := DontCare
  }

  fromITLB.map(_.ready := true.B)

  val (tlbRespValid, tlbRespPAddr) = (fromITLB.map(_.valid), VecInit(fromITLB.map(_.bits.paddr)))
210
  val (tlbRespMiss) = (fromITLB.map(port => port.bits.miss && port.valid))
L
Lemover 已提交
211 212 213
  val (tlbExcpPF,    tlbExcpAF)    = (fromITLB.map(port => port.bits.excp.pf.instr && port.valid),
    fromITLB.map(port => (port.bits.excp.af.instr) && port.valid)) //TODO: Temp treat mmio req as access fault

J
JinYue 已提交
214 215 216
  tlbRespAllValid := tlbRespValid(0)  && (tlbRespValid(1) || !f1_doubleLine)

  val f1_pAddrs             = tlbRespPAddr   //TODO: Temporary assignment
J
JinYue 已提交
217
  val f1_pTags              = VecInit(f1_pAddrs.map(get_phy_tag(_)))
J
JinYue 已提交
218
  val (f1_tags, f1_cacheline_valid, f1_datas)   = (meta_resp.tags, meta_resp.valid, data_resp.datas)
219 220
  val bank0_hit_vec         = VecInit(f1_tags(0).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(0)(i) && way_tag ===  f1_pTags(0) })
  val bank1_hit_vec         = VecInit(f1_tags(1).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(1)(i) && way_tag ===  f1_pTags(1) })
Y
Yinan Xu 已提交
221 222
  val (bank0_hit,bank1_hit) = (ParallelOR(bank0_hit_vec) && !tlbExcpPF(0) && !tlbExcpAF(0), ParallelOR(bank1_hit_vec) && !tlbExcpPF(1) && !tlbExcpAF(1))
  val f1_hit                = (bank0_hit && bank1_hit && f1_valid && f1_doubleLine) || (f1_valid && !f1_doubleLine && bank0_hit)
J
JinYue 已提交
223 224
  val f1_bank_hit_vec       = VecInit(Seq(bank0_hit_vec, bank1_hit_vec))
  val f1_bank_hit           = VecInit(Seq(bank0_hit, bank1_hit))
J
JinYue 已提交
225

226 227
  //MMIO
  //MMIO only need 1 instruction
228
  // val f1_mmio = tlbRespMMIO(0) && f1_valid
229 230


231
  val replacers       = Seq.fill(2)(ReplacementPolicy.fromString(Some("random"),nWays,nSets/2))
232
  val f1_victim_masks = VecInit(replacers.zipWithIndex.map{case (replacer, i) => UIntToOH(replacer.way(f1_vSetIdx(i)))})
J
JinYue 已提交
233

234 235
  val touch_sets = Seq.fill(2)(Wire(Vec(2, UInt(log2Ceil(nSets/2).W))))
  val touch_ways = Seq.fill(2)(Wire(Vec(2, Valid(UInt(log2Ceil(nWays).W)))) )
Y
Yinan Xu 已提交
236

J
jinyue110 已提交
237
  ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)}
Y
Yinan Xu 已提交
238

J
jinyue110 已提交
239
  val f1_hit_data      =  VecInit(f1_datas.zipWithIndex.map { case(bank, i) =>
240 241
    val bank_hit_data = Mux1H(f1_bank_hit_vec(i).asUInt, bank)
    bank_hit_data
J
jinyue110 已提交
242 243
  })

J
JinYue 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
  (0 until nWays).map{ w =>
    XSPerfAccumulate("line_0_hit_way_" + Integer.toString(w, 10),  f1_fire && f1_bank_hit(0) && OHToUInt(f1_bank_hit_vec(0))  === w.U)
  }

  (0 until nWays).map{ w =>
    XSPerfAccumulate("line_0_victim_way_" + Integer.toString(w, 10),  f1_fire && !f1_bank_hit(0) && OHToUInt(f1_victim_masks(0))  === w.U)
  }

  (0 until nWays).map{ w =>
    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)
  }

  (0 until nWays).map{ w =>
    XSPerfAccumulate("line_1_victim_way_" + Integer.toString(w, 10),  f1_fire && f1_doubleLine && !f1_bank_hit(1) && OHToUInt(f1_victim_masks(1))  === w.U)
  }

  XSPerfAccumulate("ifu_bubble_f1_tlb_miss",    f1_valid && !tlbRespAllValid )
261

J
jinyue110 已提交
262 263 264
  //---------------------------------------------
  //  Fetch Stage 3 :
  //  * get data from last stage (hit from f1_hit_data/miss from missQueue response)
J
JinYue 已提交
265
  //  * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!!
J
jinyue110 已提交
266 267 268
  //  * cut cacheline(s) and send to PreDecode
  //  * check if prediction is right (branch target and type, jump direction and type , jal target )
  //---------------------------------------------
J
JinYue 已提交
269 270
  val f2_fetchFinish = Wire(Bool())

J
JinYue 已提交
271
  val f2_valid        = RegInit(false.B)
J
JinYue 已提交
272 273
  val f2_ftq_req      = RegEnable(next = f1_ftq_req,    enable = f1_fire)
  val f2_situation    = RegEnable(next = f1_situation,  enable=f1_fire)
J
JinYue 已提交
274
  val f2_doubleLine   = RegEnable(next = f1_doubleLine, enable=f1_fire)
J
JinYue 已提交
275 276 277
  val f2_fire         = f2_valid && f2_fetchFinish && f3_ready

  f2_ready := (f3_ready && f2_fetchFinish) || !f2_valid
J
jinyue110 已提交
278

L
Lingrui98 已提交
279 280
  when(f2_flush)                  {f2_valid := false.B}
  .elsewhen(f1_fire && !f1_flush) {f2_valid := true.B }
J
JinYue 已提交
281 282
  .elsewhen(f2_fire)              {f2_valid := false.B}

L
Lemover 已提交
283
  val pmpExcpAF = fromPMP.map(port => port.instr)
284
  val mmio = fromPMP.map(port => port.mmio) // TODO: handle it
285

286

287 288
  val f2_pAddrs   = RegEnable(next = f1_pAddrs, enable = f1_fire)
  val f2_hit      = RegEnable(next = f1_hit   , enable = f1_fire)
J
JinYue 已提交
289
  val f2_bank_hit = RegEnable(next = f1_bank_hit, enable = f1_fire)
Y
Yinan Xu 已提交
290
  val f2_miss     = f2_valid && !f2_hit
291 292
  val (f2_vSetIdx, f2_pTags) = (RegEnable(next = f1_vSetIdx, enable = f1_fire), RegEnable(next = f1_pTags, enable = f1_fire))
  val f2_waymask  = RegEnable(next = f1_victim_masks, enable = f1_fire)
J
JinYue 已提交
293 294
  //exception information
  val f2_except_pf = RegEnable(next = VecInit(tlbExcpPF), enable = f1_fire)
L
Lemover 已提交
295
  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))
J
JinYue 已提交
296 297
  val f2_except    = VecInit((0 until 2).map{i => f2_except_pf(i) || f2_except_af(i)})
  val f2_has_except = f2_valid && (f2_except_af.reduce(_||_) || f2_except_pf.reduce(_||_))
298
  //MMIO
299
  val f2_mmio      = DataHoldBypass(io.pmp(0).resp.mmio && !f2_except_af(0) && !f2_except_pf(0), RegNext(f1_fire)).asBool()
300

L
Lemover 已提交
301 302 303 304 305 306
  io.pmp.zipWithIndex.map { case (p, i) =>
    p.req.valid := f2_fire
    p.req.bits.addr := f2_pAddrs(i)
    p.req.bits.size := 3.U // TODO
    p.req.bits.cmd := TlbCmd.exec
  }
307

Y
Yinan Xu 已提交
308
  //instruction
309
  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)
J
JinYue 已提交
310
  val wait_state = RegInit(wait_idle)
J
jinyue110 已提交
311 312 313 314 315 316

  fromMissQueue.map{port => port.ready := true.B}

  val (miss0_resp, miss1_resp) = (fromMissQueue(0).fire(), fromMissQueue(1).fire())
  val (bank0_fix, bank1_fix)   = (miss0_resp  && !f2_bank_hit(0), miss1_resp && f2_doubleLine && !f2_bank_hit(1))

317 318 319 320 321 322
  val  only_0_miss = f2_valid && !f2_hit && !f2_doubleLine && !f2_has_except && !f2_mmio
  val  only_0_hit  = f2_valid && f2_hit && !f2_doubleLine  && !f2_mmio
  val  hit_0_hit_1  = f2_valid && f2_hit && f2_doubleLine  && !f2_mmio
  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),
                                                          (f2_valid && !f2_bank_hit(0) && f2_bank_hit(1) && f2_doubleLine  && !f2_has_except  && !f2_mmio),
                                                          (f2_valid && !f2_bank_hit(0) && !f2_bank_hit(1) && f2_doubleLine && !f2_has_except  && !f2_mmio),
J
JinYue 已提交
323 324
                                                       )

Y
Yinan Xu 已提交
325 326
  val  hit_0_except_1  = f2_valid && f2_doubleLine &&  !f2_except(0) && f2_except(1)  &&  f2_bank_hit(0)
  val  miss_0_except_1 = f2_valid && f2_doubleLine &&  !f2_except(0) && f2_except(1)  && !f2_bank_hit(0)
J
JinYue 已提交
327
  //val  fetch0_except_1 = hit_0_except_1 || miss_0_except_1
Y
Yinan Xu 已提交
328
  val  except_0        = f2_valid && f2_except(0)
J
JinYue 已提交
329

Y
Yinan Xu 已提交
330
  val f2_mq_datas     = Reg(Vec(2, UInt(blockBits.W)))
331
  val f2_mmio_data    = Reg(UInt(maxInstrLen.W))
332 333 334

  when(fromMissQueue(0).fire) {f2_mq_datas(0) :=  fromMissQueue(0).bits.data}
  when(fromMissQueue(1).fire) {f2_mq_datas(1) :=  fromMissQueue(1).bits.data}
335
  when(fromUncache.fire())    {f2_mmio_data   :=  fromUncache.bits.data}
336

J
JinYue 已提交
337 338
  switch(wait_state){
    is(wait_idle){
339
      when(f2_mmio && f2_valid && !f2_except_af(0) && !f2_except_pf(0)){
340 341
        wait_state :=  wait_send_mmio
      }.elsewhen(miss_0_except_1){
J
JinYue 已提交
342 343
        wait_state :=  Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
      }.elsewhen( only_0_miss  || miss_0_hit_1){
J
JinYue 已提交
344
        wait_state :=  Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
J
JinYue 已提交
345
      }.elsewhen(hit_0_miss_1){
J
JinYue 已提交
346
        wait_state :=  Mux(toMissQueue(1).ready, wait_queue_ready ,wait_idle )
J
JinYue 已提交
347
      }.elsewhen( miss_0_miss_1 ){
J
JinYue 已提交
348
        wait_state := Mux(toMissQueue(0).ready && toMissQueue(1).ready, wait_queue_ready ,wait_idle)
J
jinyue110 已提交
349
      }
J
JinYue 已提交
350
    }
J
jinyue110 已提交
351

352 353 354 355 356 357 358 359
    is(wait_send_mmio){
      wait_state := Mux(toUncache.fire(), wait_mmio_resp,wait_send_mmio )
    }

    is(wait_mmio_resp){
      wait_state :=  Mux(fromUncache.fire(), wait_finish, wait_mmio_resp)
    }

J
JinYue 已提交
360
    //TODO: naive logic for wait icache response
J
JinYue 已提交
361 362 363
    is(wait_queue_ready){
      wait_state := wait_send_req
    }
J
JinYue 已提交
364

J
JinYue 已提交
365
    is(wait_send_req) {
J
JinYue 已提交
366
      when(miss_0_except_1 || only_0_miss || hit_0_miss_1 || miss_0_hit_1){
J
JinYue 已提交
367 368 369 370 371 372 373
        wait_state :=  wait_one_resp
      }.elsewhen( miss_0_miss_1 ){
        wait_state := wait_two_resp
      }
    }

    is(wait_one_resp) {
J
JinYue 已提交
374
      when( (miss_0_except_1 ||only_0_miss || miss_0_hit_1) && fromMissQueue(0).fire()){
J
JinYue 已提交
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
        wait_state := wait_finish
      }.elsewhen( hit_0_miss_1 && fromMissQueue(1).fire()){
        wait_state := wait_finish
      }
    }

    is(wait_two_resp) {
      when(fromMissQueue(0).fire() && fromMissQueue(1).fire()){
        wait_state := wait_finish
      }.elsewhen( !fromMissQueue(0).fire() && fromMissQueue(1).fire() ){
        wait_state := wait_0_resp
      }.elsewhen(fromMissQueue(0).fire() && !fromMissQueue(1).fire()){
        wait_state := wait_1_resp
      }
    }

    is(wait_0_resp) {
      when(fromMissQueue(0).fire()){
        wait_state := wait_finish
J
jinyue110 已提交
394 395 396
      }
    }

J
JinYue 已提交
397 398 399 400 401
    is(wait_1_resp) {
      when(fromMissQueue(1).fire()){
        wait_state := wait_finish
      }
    }
J
jinyue110 已提交
402

J
JinYue 已提交
403
    is(wait_finish) {
J
JinYue 已提交
404
      when(f2_fire) {wait_state := wait_idle }
J
JinYue 已提交
405 406
    }
  }
J
jinyue110 已提交
407

J
JinYue 已提交
408
  when(f2_flush) { wait_state := wait_idle }
409

J
JinYue 已提交
410
  (0 until 2).map { i =>
J
JinYue 已提交
411
    if(i == 1) toMissQueue(i).valid := (hit_0_miss_1 || miss_0_miss_1) && wait_state === wait_queue_ready
412
      else     toMissQueue(i).valid := (only_0_miss || miss_0_hit_1 || miss_0_miss_1 || miss_0_except_1) && wait_state === wait_queue_ready
J
JinYue 已提交
413 414 415 416 417 418
    toMissQueue(i).bits.addr    := f2_pAddrs(i)
    toMissQueue(i).bits.vSetIdx := f2_vSetIdx(i)
    toMissQueue(i).bits.waymask := f2_waymask(i)
    toMissQueue(i).bits.clientID :=0.U
  }

419 420 421 422 423 424
  toUncache.valid :=  (wait_state === wait_send_mmio) && !f2_except_af(0)
  //assert( (GTimer() < 5000.U && toUncache.fire()) || !toUncache.fire() ) 
  toUncache.bits.addr := f2_ftq_req.startAddr

  fromUncache.ready := true.B

J
JinYue 已提交
425
  val miss_all_fix       = (wait_state === wait_finish)
Y
Yinan Xu 已提交
426

J
JinYue 已提交
427
  f2_fetchFinish         := ((f2_valid && f2_hit) || miss_all_fix || hit_0_except_1 || except_0)
J
JinYue 已提交
428

J
JinYue 已提交
429
  XSPerfAccumulate("ifu_bubble_f2_miss",    f2_valid && !f2_fetchFinish )
J
JinYue 已提交
430 431

  (touch_ways zip touch_sets).zipWithIndex.map{ case((t_w,t_s), i) =>
J
jinyue110 已提交
432 433 434 435
    t_s(0)         := f1_vSetIdx(i)
    t_w(0).valid   := f1_bank_hit(i)
    t_w(0).bits    := OHToUInt(f1_bank_hit_vec(i))

J
JinYue 已提交
436 437 438
    t_s(1)         := f2_vSetIdx(i)
    t_w(1).valid   := f2_valid && !f2_bank_hit(i)
    t_w(1).bits    := OHToUInt(f2_waymask(i))
439
  }
Y
Yinan Xu 已提交
440

J
JinYue 已提交
441 442
  val sec_miss_reg   = RegInit(0.U.asTypeOf(Vec(4, Bool())))
  val reservedRefillData = Reg(Vec(2, UInt(blockBits.W)))
Y
Yinan Xu 已提交
443
  val f2_hit_datas    = RegEnable(next = f1_hit_data, enable = f1_fire)
J
JinYue 已提交
444
  val f2_datas        = Wire(Vec(2, UInt(blockBits.W)))
J
JinYue 已提交
445

Y
Yinan Xu 已提交
446
  f2_datas.zipWithIndex.map{case(bank,i) =>
447 448
    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))))
    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))))
J
JinYue 已提交
449
  }
J
JinYue 已提交
450

451
  val f2_jump_valids          = Fill(PredictWidth, !preDecoderOut.cfiOffset.valid)   | Fill(PredictWidth, 1.U(1.W)) >> (~preDecoderOut.cfiOffset.bits)
452
  val f2_predecode_valids     = VecInit(preDecoderOut.pd.map(instr => instr.valid)).asUInt & f2_jump_valids
J
JinYue 已提交
453

J
JinYue 已提交
454
  def cut(cacheline: UInt, start: UInt) : Vec[UInt] ={
455 456 457 458 459 460 461
    if(HasCExtension){
      val result   = Wire(Vec(PredictWidth + 1, UInt(16.W)))
      val dataVec  = cacheline.asTypeOf(Vec(blockBytes * 2/ 2, UInt(16.W)))
      val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 1))
      (0 until PredictWidth + 1).foreach( i =>
        result(i) := dataVec(startPtr + i.U)
      )
Y
Yinan Xu 已提交
462
      result
463 464 465 466 467 468 469
    } else {
      val result   = Wire(Vec(PredictWidth, UInt(32.W)) )
      val dataVec  = cacheline.asTypeOf(Vec(blockBytes * 2/ 4, UInt(32.W)))
      val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 2))
      (0 until PredictWidth).foreach( i =>
        result(i) := dataVec(startPtr + i.U)
      )
Y
Yinan Xu 已提交
470
      result
471
    }
472 473
  }

J
JinYue 已提交
474
  val f2_cut_data = cut( Cat(f2_datas.map(cacheline => cacheline.asUInt ).reverse).asUInt, f2_ftq_req.startAddr )
475 476 477 478
  when(f2_mmio){
    f2_cut_data(0) := f2_mmio_data(15, 0)
    f2_cut_data(1) := f2_mmio_data(31, 16)
  }
Y
Yinan Xu 已提交
479 480

  // deal with secondary miss in f1
J
JinYue 已提交
481 482 483 484 485
  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)))
  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)))
  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) ))
  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) ))

Y
Yinan Xu 已提交
486
  val isSameLine = f2_0_f1_0 || f2_0_f1_1 || f2_1_f1_0 || f2_1_f1_1
J
JinYue 已提交
487 488 489 490 491 492
  val sec_miss_sit   = VecInit(Seq(f2_0_f1_0, f2_0_f1_1, f2_1_f1_0, f2_1_f1_1))
  val hasSecMiss     = RegInit(false.B)

  when(f2_flush){
    sec_miss_reg.map(sig => sig := false.B)
    hasSecMiss := false.B
J
JinYue 已提交
493
  }.elsewhen(isSameLine && !f1_flush && f2_fire){
J
JinYue 已提交
494 495
    sec_miss_reg.zipWithIndex.map{case(sig, i) => sig := sec_miss_sit(i)}
    hasSecMiss := true.B
J
JinYue 已提交
496
  }.elsewhen((!isSameLine || f1_flush) && hasSecMiss && f2_fire){
J
JinYue 已提交
497 498 499 500
    sec_miss_reg.map(sig => sig := false.B)
    hasSecMiss := false.B
  }

J
JinYue 已提交
501
  when((f2_0_f1_0 || f2_0_f1_1) && f2_fire){
J
JinYue 已提交
502 503
    reservedRefillData(0) := f2_mq_datas(0)
  }
J
JinYue 已提交
504

J
JinYue 已提交
505
  when((f2_1_f1_0 || f2_1_f1_1) && f2_fire){
J
JinYue 已提交
506 507
    reservedRefillData(1) := f2_mq_datas(1)
  }
J
JinYue 已提交
508 509


J
JinYue 已提交
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
  //---------------------------------------------
  //  Fetch Stage 4 :
  //  * get data from last stage (hit from f1_hit_data/miss from missQueue response)
  //  * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!!
  //  * cut cacheline(s) and send to PreDecode
  //  * check if prediction is right (branch target and type, jump direction and type , jal target )
  //---------------------------------------------
  val f3_valid          = RegInit(false.B)
  val f3_ftq_req        = RegEnable(next = f2_ftq_req,    enable=f2_fire)
  val f3_situation      = RegEnable(next = f2_situation,  enable=f2_fire)
  val f3_doubleLine     = RegEnable(next = f2_doubleLine, enable=f2_fire)
  val f3_fire           = io.toIbuffer.fire()

  when(f3_flush)                  {f3_valid := false.B}
  .elsewhen(f2_fire && !f2_flush) {f3_valid := true.B }
  .elsewhen(io.toIbuffer.fire())  {f3_valid := false.B}

  f3_ready := io.toIbuffer.ready || !f2_valid

  val f3_cut_data       = RegEnable(next = f2_cut_data, enable=f2_fire)
  val f3_except_pf      = RegEnable(next = f2_except_pf, enable = f2_fire)
  val f3_except_af      = RegEnable(next = f2_except_af, enable = f2_fire)
  val f3_hit            = RegEnable(next = f2_hit   , enable = f2_fire)
533
  val f3_mmio           = RegEnable(next = f2_mmio   , enable = f2_fire)
J
JinYue 已提交
534 535 536 537 538 539

  val f3_lastHalf       = RegInit(0.U.asTypeOf(new LastHalfInfo))
  val f3_lastHalfMatch  = f3_lastHalf.matchThisBlock(f3_ftq_req.startAddr)
  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(_||_))

J
JinYue 已提交
540 541 542 543 544 545 546 547 548 549 550 551 552 553
  //performance counter
  val f3_only_0_hit     = RegEnable(next = only_0_hit, enable = f2_fire)
  val f3_only_0_miss    = RegEnable(next = only_0_miss, enable = f2_fire)
  val f3_hit_0_hit_1    = RegEnable(next = hit_0_hit_1, enable = f2_fire)
  val f3_hit_0_miss_1   = RegEnable(next = hit_0_miss_1, enable = f2_fire)
  val f3_miss_0_hit_1   = RegEnable(next = miss_0_hit_1, enable = f2_fire)
  val f3_miss_0_miss_1  = RegEnable(next = miss_0_miss_1, enable = f2_fire)

  val f3_bank_hit = RegEnable(next = f2_bank_hit, enable = f2_fire)
  val f3_req_0 = io.toIbuffer.fire()
  val f3_req_1 = io.toIbuffer.fire() && f3_doubleLine
  val f3_hit_0 = io.toIbuffer.fire() & f3_bank_hit(0)
  val f3_hit_1 = io.toIbuffer.fire() && f3_doubleLine & f3_bank_hit(1)

J
JinYue 已提交
554 555 556 557 558 559 560 561 562 563
  preDecoderIn.instValid     :=  f3_valid && !f3_has_except
  preDecoderIn.data          :=  f3_cut_data
  preDecoderIn.startAddr     :=  f3_ftq_req.startAddr
  preDecoderIn.fallThruAddr  :=  f3_ftq_req.fallThruAddr
  preDecoderIn.fallThruError :=  f3_ftq_req.fallThruError
  preDecoderIn.isDoubleLine  :=  f3_doubleLine
  preDecoderIn.ftqOffset     :=  f3_ftq_req.ftqOffset
  preDecoderIn.target        :=  f3_ftq_req.target
  preDecoderIn.oversize      :=  f3_ftq_req.oversize
  preDecoderIn.lastHalfMatch :=  f3_lastHalfMatch
Y
Yinan Xu 已提交
564
  preDecoderIn.pageFault     :=  f3_except_pf
J
JinYue 已提交
565
  preDecoderIn.accessFault   :=  f3_except_af
566
  preDecoderIn.mmio          :=  f3_mmio
J
JinYue 已提交
567 568


569
  // TODO: What if next packet does not match?
J
JinYue 已提交
570 571
  when (f3_flush) {
    f3_lastHalf.valid := false.B
572
  }.elsewhen (io.toIbuffer.fire()) {
J
JinYue 已提交
573 574
    f3_lastHalf.valid := preDecoderOut.hasLastHalf
    f3_lastHalf.middlePC := preDecoderOut.realEndPC
575 576
  }

J
JinYue 已提交
577
  val f3_predecode_range = VecInit(preDecoderOut.pd.map(inst => inst.valid)).asUInt
578
  val f3_mmio_range      = VecInit((0 until PredictWidth).map(i => if(i ==0) true.B else false.B))
579

Y
Yinan Xu 已提交
580
  io.toIbuffer.valid          := f3_valid
J
jinyue110 已提交
581
  io.toIbuffer.bits.instrs    := preDecoderOut.instrs
582
  io.toIbuffer.bits.valid     := Mux(f3_mmio, f3_mmio_range.asUInt, f3_predecode_range & preDecoderOut.instrRange.asUInt)
J
jinyue110 已提交
583
  io.toIbuffer.bits.pd        := preDecoderOut.pd
J
JinYue 已提交
584
  io.toIbuffer.bits.ftqPtr    := f3_ftq_req.ftqIdx
585
  io.toIbuffer.bits.pc        := preDecoderOut.pc
586
  io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := preDecoderOut.takens(i) && !f3_mmio}
587
  io.toIbuffer.bits.foldpc    := preDecoderOut.pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth))
J
JinYue 已提交
588 589 590
  io.toIbuffer.bits.ipf       := preDecoderOut.pageFault
  io.toIbuffer.bits.acf       := preDecoderOut.accessFault
  io.toIbuffer.bits.crossPageIPFFix := preDecoderOut.crossPageIPF
J
JinYue 已提交
591

J
JinYue 已提交
592
  //Write back to Ftq
J
JinYue 已提交
593
  val finishFetchMaskReg = RegNext(f3_valid && !(f2_fire && !f2_flush))
J
JinYue 已提交
594

595 596 597 598
  val f3_mmio_missOffset = Wire(ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))
  f3_mmio_missOffset.valid := f3_mmio
  f3_mmio_missOffset.bits  := 0.U

J
JinYue 已提交
599
  toFtq.pdWb.valid           := !finishFetchMaskReg && f3_valid
J
jinyue110 已提交
600
  toFtq.pdWb.bits.pc         := preDecoderOut.pc
Y
Yinan Xu 已提交
601
  toFtq.pdWb.bits.pd         := preDecoderOut.pd
602
  toFtq.pdWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid :=  Mux(f3_mmio, f3_mmio_range(i), f3_predecode_range(i))}
J
JinYue 已提交
603
  toFtq.pdWb.bits.ftqIdx     := f3_ftq_req.ftqIdx
Y
Yinan Xu 已提交
604
  toFtq.pdWb.bits.ftqOffset  := f3_ftq_req.ftqOffset.bits
605
  toFtq.pdWb.bits.misOffset  := Mux(f3_mmio, f3_mmio_missOffset, preDecoderOut.misOffset)
606
  toFtq.pdWb.bits.cfiOffset  := preDecoderOut.cfiOffset
607
  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)
608
  toFtq.pdWb.bits.jalTarget  := preDecoderOut.jalTarget
609
  toFtq.pdWb.bits.instrRange := Mux(f3_mmio, f3_mmio_range, preDecoderOut.instrRange)
610

611
  val predecodeFlush     = ((preDecoderOut.misOffset.valid || f3_mmio) && f3_valid) 
J
JinYue 已提交
612
  val predecodeFlushReg  = RegNext(predecodeFlush && !(f2_fire && !f2_flush))
613

614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
  val perfinfo = IO(new Bundle(){
    val perfEvents = Output(new PerfEventsBundle(15))
  })

  val perfEvents = Seq(
    ("frontendFlush                ", f3_redirect                                ),
    ("ifu_req                      ", io.toIbuffer.fire()                        ),
    ("ifu_miss                     ", io.toIbuffer.fire() && !f3_hit             ),
    ("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                                   ),
    ("only_0_hit                   ", f3_only_0_hit       && io.toIbuffer.fire() ),
    ("only_0_miss                  ", f3_only_0_miss      && io.toIbuffer.fire() ),
    ("hit_0_hit_1                  ", f3_hit_0_hit_1      && io.toIbuffer.fire() ),
    ("hit_0_miss_1                 ", f3_hit_0_miss_1     && io.toIbuffer.fire() ),
    ("miss_0_hit_1                 ", f3_miss_0_hit_1     && io.toIbuffer.fire() ),
    ("miss_0_miss_1                ", f3_miss_0_miss_1    && io.toIbuffer.fire() ),
    ("cross_line_block             ", io.toIbuffer.fire() && f3_situation(0)     ),
    ("fall_through_is_cacheline_end", io.toIbuffer.fire() && f3_situation(1)     ),
  )

  for (((perf_out,(perf_name,perf)),i) <- perfinfo.perfEvents.perf_events.zip(perfEvents).zipWithIndex) {
    perf_out.incr_step := RegNext(perf)
  }
J
JinYue 已提交
639

J
JinYue 已提交
640
  f3_redirect := !predecodeFlushReg && predecodeFlush
J
JinYue 已提交
641

J
JinYue 已提交
642 643 644 645 646 647
  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 )
L
Lingrui98 已提交
648
  XSPerfAccumulate("frontendFlush",  f3_redirect )
J
JinYue 已提交
649 650 651 652 653 654 655 656
  XSPerfAccumulate("only_0_hit",      f3_only_0_hit   && io.toIbuffer.fire()  )
  XSPerfAccumulate("only_0_miss",     f3_only_0_miss  && io.toIbuffer.fire()  )
  XSPerfAccumulate("hit_0_hit_1",     f3_hit_0_hit_1  && io.toIbuffer.fire()  )
  XSPerfAccumulate("hit_0_miss_1",    f3_hit_0_miss_1 && io.toIbuffer.fire()  )
  XSPerfAccumulate("miss_0_hit_1",    f3_miss_0_hit_1  && io.toIbuffer.fire() )
  XSPerfAccumulate("miss_0_miss_1",   f3_miss_0_miss_1 && io.toIbuffer.fire() )
  XSPerfAccumulate("cross_line_block", io.toIbuffer.fire() && f3_situation(0) )
  XSPerfAccumulate("fall_through_is_cacheline_end", io.toIbuffer.fire() && f3_situation(1) )
657
}