IFU.scala 23.5 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 27
import utils._

28 29 30 31 32 33 34 35 36 37
trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{
  def mmioBusWidth = 64
  def mmioBusBytes = mmioBusWidth /8
  def mmioBeats = FetchWidth * 4 * 8 / mmioBusWidth
  def mmioMask  = VecInit(List.fill(PredictWidth)(true.B)).asUInt
  def mmioBusAligned(pc :UInt): UInt = align(pc, mmioBusBytes)
}

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

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

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

51 52 53 54 55 56
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)
57
  val fromMissQueue = Vec(2,Flipped(Decoupled(new ICacheMissResp)))
J
JinYue 已提交
58 59
}

60
class NewIFUIO(implicit p: Parameters) extends XSBundle {
61 62
  val ftqInter        = new FtqInterface  
  val icacheInter     = new ICacheInterface 
63
  val toIbuffer       = Decoupled(new FetchToIBuffer)
64
  val iTLBInter       = Vec(2, new BlockTlbRequestIO) 
J
JinYue 已提交
65 66
}

67 68 69 70 71 72 73 74
// 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
}

75
class IfuToPreDecode(implicit p: Parameters) extends XSBundle {
76
  val data          = if(HasCExtension) Vec(PredictWidth + 1, UInt(16.W)) else Vec(PredictWidth, UInt(32.W))  
77
  val startAddr     = UInt(VAddrBits.W)
78
  val fallThruAddr  = UInt(VAddrBits.W)
J
JinYue 已提交
79
  val fallThruError = Bool()
J
JinYue 已提交
80
  val isDoubleLine  = Bool()
81
  val ftqOffset     = Valid(UInt(log2Ceil(PredictWidth).W))
J
jinyue110 已提交
82
  val target        = UInt(VAddrBits.W)
J
JinYue 已提交
83 84
  val pageFault     = Vec(2, Bool())
  val accessFault   = Vec(2, Bool())
J
JinYue 已提交
85
  val instValid     = Bool() 
86
  val lastHalfMatch = Bool()
87
  val oversize      = Bool()
88 89
}

90
class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
J
JinYue 已提交
91
{
92
  println(s"icache ways: ${nWays} sets:${nSets}")
J
JinYue 已提交
93
  val io = IO(new NewIFUIO)
94 95 96
  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)
J
JinYue 已提交
97
  val (toITLB, fromITLB) = (VecInit(io.iTLBInter.map(_.req)), VecInit(io.iTLBInter.map(_.resp)))
98
  
99
  def isCrossLineReq(start: UInt, end: UInt): Bool = start(blockOffBits) ^ end(blockOffBits)
100

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

J
JinYue 已提交
103

J
jinyue110 已提交
104 105 106 107 108
  //---------------------------------------------
  //  Fetch Stage 1 :
  //  * Send req to ICache Meta/Data
  //  * Check whether need 2 line fetch
  //---------------------------------------------
L
Lingrui98 已提交
109
  
J
JinYue 已提交
110
  val f0_valid                             = fromFtq.req.valid
Z
zoujr 已提交
111
  val f0_ftq_req                           = fromFtq.req.bits
J
jinyue110 已提交
112 113
  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 已提交
114
  val f0_vSetIdx                           = VecInit(get_idx((f0_ftq_req.startAddr)), get_idx(f0_ftq_req.fallThruAddr))
Z
zoujr 已提交
115
  val f0_fire                              = fromFtq.req.fire()
L
Lingrui98 已提交
116
  
J
JinYue 已提交
117
  val f0_flush, f1_flush, f2_flush, f3_flush = WireInit(false.B)
118 119 120 121 122
  val from_bpu_f0_flush, from_bpu_f1_flush, from_bpu_f2_flush, from_bpu_f3_flush = WireInit(false.B)
  
  from_bpu_f0_flush := fromFtq.flushFromBpu.shouldFlushByStage2(f0_ftq_req.ftqIdx) ||
                       fromFtq.flushFromBpu.shouldFlushByStage3(f0_ftq_req.ftqIdx)

J
JinYue 已提交
123 124 125
  val f3_redirect = WireInit(false.B)
  f3_flush := fromFtq.redirect.valid
  f2_flush := f3_flush || f3_redirect
126 127
  f1_flush := f2_flush || from_bpu_f1_flush
  f0_flush := f1_flush || from_bpu_f0_flush
J
JinYue 已提交
128

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

131
  //fetch: send addr to Meta/TLB and Data simultaneously
J
jinyue110 已提交
132
  val fetch_req = List(toMeta, toData)
133
  for(i <- 0 until 2) {
134
    fetch_req(i).valid := f0_fire
135 136 137
    fetch_req(i).bits.isDoubleLine := f0_doubleLine
    fetch_req(i).bits.vSetIdx := f0_vSetIdx
  }
138

J
JinYue 已提交
139
  fromFtq.req.ready := fetch_req(0).ready && fetch_req(1).ready && f1_ready && GTimer() > 500.U
J
jinyue110 已提交
140 141 142

  //---------------------------------------------
  //  Fetch Stage 2 :
J
JinYue 已提交
143
  //  * Send req to ITLB and TLB Response (Get Paddr)
J
jinyue110 已提交
144 145 146 147
  //  * ICache Response (Get Meta and Data)
  //  * Hit Check (Generate hit signal and hit vector)
  //  * Get victim way
  //---------------------------------------------
J
JinYue 已提交
148

J
jinyue110 已提交
149 150
  //TODO: handle fetch exceptions

J
JinYue 已提交
151
  val tlbRespAllValid = WireInit(false.B)
J
jinyue110 已提交
152

J
JinYue 已提交
153
  val f1_valid      = RegInit(false.B)
J
jinyue110 已提交
154 155 156 157
  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 已提交
158 159 160
  val f1_fire       = f1_valid && tlbRespAllValid && f2_ready

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

162 163
  from_bpu_f1_flush := fromFtq.flushFromBpu.shouldFlushByStage3(f1_ftq_req.ftqIdx)

Z
zoujr 已提交
164 165 166 167
  val preDecoder      = Module(new PreDecode)
  val (preDecoderIn, preDecoderOut)   = (preDecoder.io.in, preDecoder.io.out)

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

L
Lingrui98 已提交
170 171 172
  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 已提交
173

J
JinYue 已提交
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
  toITLB(0).valid         := f1_valid
  toITLB(0).bits.vaddr    := align(f1_ftq_req.startAddr, blockBytes)
  toITLB(0).bits.debug.pc := align(f1_ftq_req.startAddr, blockBytes)
  
  toITLB(1).valid         := f1_valid && f1_doubleLine
  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
    port.bits.roqIdx              := DontCare
    port.bits.debug.isFirstIssue  := DontCare
  }

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

  val (tlbRespValid, tlbRespPAddr) = (fromITLB.map(_.valid), VecInit(fromITLB.map(_.bits.paddr)))
  val (tlbRespMiss,  tlbRespMMIO)  = (fromITLB.map(port => port.bits.miss && port.valid), fromITLB.map(port => port.bits.mmio && port.valid))
  val (tlbExcpPF,    tlbExcpAF)    = (fromITLB.map(port => port.bits.excp.pf.instr && port.valid), fromITLB.map(port => port.bits.excp.af.instr && port.valid))

  tlbRespAllValid := tlbRespValid(0)  && (tlbRespValid(1) || !f1_doubleLine)

  val f1_pAddrs             = tlbRespPAddr   //TODO: Temporary assignment
J
JinYue 已提交
197
  val f1_pTags              = VecInit(f1_pAddrs.map(get_phy_tag(_)))
J
JinYue 已提交
198
  val (f1_tags, f1_cacheline_valid, f1_datas)   = (meta_resp.tags, meta_resp.valid, data_resp.datas)
199 200
  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) })
J
JinYue 已提交
201
  val (bank0_hit,bank1_hit) = (ParallelOR(bank0_hit_vec) && !tlbExcpPF(0) && !tlbExcpAF(0), ParallelOR(bank1_hit_vec) && !tlbExcpPF(1) && !tlbExcpAF(1)) 
J
JinYue 已提交
202
  val f1_hit                = (bank0_hit && bank1_hit && f1_valid && f1_doubleLine) || (f1_valid && !f1_doubleLine && bank0_hit)  
J
JinYue 已提交
203 204
  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 已提交
205

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

209 210
  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)))) )
211
   
J
jinyue110 已提交
212
  ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)}
213
  
J
jinyue110 已提交
214
  val f1_hit_data      =  VecInit(f1_datas.zipWithIndex.map { case(bank, i) =>
215 216
    val bank_hit_data = Mux1H(f1_bank_hit_vec(i).asUInt, bank)
    bank_hit_data
J
jinyue110 已提交
217 218
  })

219

J
jinyue110 已提交
220 221 222
  //---------------------------------------------
  //  Fetch Stage 3 :
  //  * get data from last stage (hit from f1_hit_data/miss from missQueue response)
J
JinYue 已提交
223
  //  * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!!
J
jinyue110 已提交
224 225 226
  //  * cut cacheline(s) and send to PreDecode
  //  * check if prediction is right (branch target and type, jump direction and type , jal target )
  //---------------------------------------------
J
JinYue 已提交
227 228
  val f2_fetchFinish = Wire(Bool())

J
JinYue 已提交
229
  val f2_valid        = RegInit(false.B)
J
JinYue 已提交
230 231
  val f2_ftq_req      = RegEnable(next = f1_ftq_req,    enable = f1_fire)
  val f2_situation    = RegEnable(next = f1_situation,  enable=f1_fire)
J
JinYue 已提交
232
  val f2_doubleLine   = RegEnable(next = f1_doubleLine, enable=f1_fire)
J
JinYue 已提交
233 234 235
  val f2_fire         = f2_valid && f2_fetchFinish && f3_ready

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

L
Lingrui98 已提交
237 238
  when(f2_flush)                  {f2_valid := false.B}
  .elsewhen(f1_fire && !f1_flush) {f2_valid := true.B }
J
JinYue 已提交
239 240
  .elsewhen(f2_fire)              {f2_valid := false.B}

241 242 243

  val f2_pAddrs   = RegEnable(next = f1_pAddrs, enable = f1_fire)
  val f2_hit      = RegEnable(next = f1_hit   , enable = f1_fire)
J
JinYue 已提交
244
  val f2_bank_hit = RegEnable(next = f1_bank_hit, enable = f1_fire)
245 246 247
  val f2_miss     = f2_valid && !f2_hit 
  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 已提交
248 249 250 251 252
  //exception information
  val f2_except_pf = RegEnable(next = VecInit(tlbExcpPF), enable = f1_fire)
  val f2_except_af = RegEnable(next = VecInit(tlbExcpAF), enable = f1_fire)
  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(_||_))
253

J
JinYue 已提交
254
  //instruction 
J
JinYue 已提交
255
  val wait_idle :: wait_queue_ready :: wait_send_req  :: wait_two_resp :: wait_0_resp :: wait_1_resp :: wait_one_resp ::wait_finish :: Nil = Enum(8)
J
JinYue 已提交
256
  val wait_state = RegInit(wait_idle)
J
jinyue110 已提交
257 258 259 260 261 262

  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))

J
JinYue 已提交
263 264 265 266
  val  only_0_miss = f2_valid && !f2_hit && !f2_doubleLine && !f2_has_except
  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_valid && !f2_bank_hit(0) && f2_bank_hit(1) && f2_doubleLine  && !f2_has_except),
                                                          (f2_valid && !f2_bank_hit(0) && !f2_bank_hit(1) && f2_doubleLine && !f2_has_except),
J
JinYue 已提交
267 268
                                                       )

J
JinYue 已提交
269 270
  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 已提交
271
  //val  fetch0_except_1 = hit_0_except_1 || miss_0_except_1
J
JinYue 已提交
272 273
  val  except_0        = f2_valid && f2_except(0)                                                   

274 275 276 277 278
  val f2_mq_datas     = Reg(Vec(2, UInt(blockBits.W)))   

  when(fromMissQueue(0).fire) {f2_mq_datas(0) :=  fromMissQueue(0).bits.data}
  when(fromMissQueue(1).fire) {f2_mq_datas(1) :=  fromMissQueue(1).bits.data}

J
JinYue 已提交
279 280
  switch(wait_state){
    is(wait_idle){
J
JinYue 已提交
281 282 283
      when(miss_0_except_1){
        wait_state :=  Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
      }.elsewhen( only_0_miss  || miss_0_hit_1){
J
JinYue 已提交
284
        wait_state :=  Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
J
JinYue 已提交
285
      }.elsewhen(hit_0_miss_1){
J
JinYue 已提交
286
        wait_state :=  Mux(toMissQueue(1).ready, wait_queue_ready ,wait_idle )
J
JinYue 已提交
287
      }.elsewhen( miss_0_miss_1 ){
J
JinYue 已提交
288
        wait_state := Mux(toMissQueue(0).ready && toMissQueue(1).ready, wait_queue_ready ,wait_idle)
J
jinyue110 已提交
289
      }
J
JinYue 已提交
290
    }
J
jinyue110 已提交
291

J
JinYue 已提交
292
    //TODO: naive logic for wait icache response
J
JinYue 已提交
293 294 295
    is(wait_queue_ready){
      wait_state := wait_send_req
    }
J
JinYue 已提交
296

J
JinYue 已提交
297
    is(wait_send_req) {
J
JinYue 已提交
298
      when(miss_0_except_1 || only_0_miss || hit_0_miss_1 || miss_0_hit_1){
J
JinYue 已提交
299 300 301 302 303 304 305
        wait_state :=  wait_one_resp
      }.elsewhen( miss_0_miss_1 ){
        wait_state := wait_two_resp
      }
    }

    is(wait_one_resp) {
J
JinYue 已提交
306
      when( (miss_0_except_1 ||only_0_miss || miss_0_hit_1) && fromMissQueue(0).fire()){
J
JinYue 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
        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 已提交
326 327 328
      }
    }

J
JinYue 已提交
329 330 331 332 333
    is(wait_1_resp) {
      when(fromMissQueue(1).fire()){
        wait_state := wait_finish
      }
    }
J
jinyue110 已提交
334

J
JinYue 已提交
335
    is(wait_finish) {
J
JinYue 已提交
336
      when(f2_fire) {wait_state := wait_idle }
J
JinYue 已提交
337 338
    }
  }
J
jinyue110 已提交
339

J
JinYue 已提交
340
  when(f2_flush) { wait_state := wait_idle }
341

J
JinYue 已提交
342
  (0 until 2).map { i =>
J
JinYue 已提交
343
    if(i == 1) toMissQueue(i).valid := (hit_0_miss_1 || miss_0_miss_1) && wait_state === wait_queue_ready
J
JinYue 已提交
344
      else     toMissQueue(i).valid := (only_0_miss || miss_0_hit_1 || miss_0_miss_1) && wait_state === wait_queue_ready
J
JinYue 已提交
345 346 347 348 349 350
    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
  }

J
JinYue 已提交
351
  val miss_all_fix       = (wait_state === wait_finish)
J
JinYue 已提交
352 353
  
  f2_fetchFinish         := ((f2_valid && f2_hit) || miss_all_fix || hit_0_except_1 || except_0)
J
JinYue 已提交
354

J
JinYue 已提交
355 356

  (touch_ways zip touch_sets).zipWithIndex.map{ case((t_w,t_s), i) =>
J
jinyue110 已提交
357 358 359 360
    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 已提交
361 362 363
    t_s(1)         := f2_vSetIdx(i)
    t_w(1).valid   := f2_valid && !f2_bank_hit(i)
    t_w(1).bits    := OHToUInt(f2_waymask(i))
364
  }
J
JinYue 已提交
365
  
J
JinYue 已提交
366 367
  val sec_miss_reg   = RegInit(0.U.asTypeOf(Vec(4, Bool())))
  val reservedRefillData = Reg(Vec(2, UInt(blockBits.W)))
J
JinYue 已提交
368
  val f2_hit_datas    = RegEnable(next = f1_hit_data, enable = f1_fire) 
J
JinYue 已提交
369
  val f2_datas        = Wire(Vec(2, UInt(blockBits.W)))
J
JinYue 已提交
370

J
JinYue 已提交
371
  f2_datas.zipWithIndex.map{case(bank,i) =>  
372 373
    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 已提交
374
  }
J
JinYue 已提交
375

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

J
JinYue 已提交
379
  def cut(cacheline: UInt, start: UInt) : Vec[UInt] ={
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
    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)
      )
      result 
    } 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)
      )
      result 
    }
397 398
  }

J
JinYue 已提交
399
  val f2_cut_data = cut( Cat(f2_datas.map(cacheline => cacheline.asUInt ).reverse).asUInt, f2_ftq_req.startAddr )
400
  
J
JinYue 已提交
401
  // deal with secondary miss in f1 
J
JinYue 已提交
402 403 404 405 406 407 408 409 410 411 412 413
  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) ))

  val isSameLine = f2_0_f1_0 || f2_0_f1_1 || f2_1_f1_0 || f2_1_f1_1 
  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 已提交
414
  }.elsewhen(isSameLine && !f1_flush && f2_fire){
J
JinYue 已提交
415 416
    sec_miss_reg.zipWithIndex.map{case(sig, i) => sig := sec_miss_sit(i)}
    hasSecMiss := true.B
J
JinYue 已提交
417
  }.elsewhen((!isSameLine || f1_flush) && hasSecMiss && f2_fire){
J
JinYue 已提交
418 419 420 421
    sec_miss_reg.map(sig => sig := false.B)
    hasSecMiss := false.B
  }

J
JinYue 已提交
422
  when((f2_0_f1_0 || f2_0_f1_1) && f2_fire){
J
JinYue 已提交
423 424
    reservedRefillData(0) := f2_mq_datas(0)
  }
J
JinYue 已提交
425

J
JinYue 已提交
426
  when((f2_1_f1_0 || f2_1_f1_1) && f2_fire){
J
JinYue 已提交
427 428
    reservedRefillData(1) := f2_mq_datas(1)
  }
J
JinYue 已提交
429 430


J
JinYue 已提交
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
  //---------------------------------------------
  //  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)

  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(_||_))

  
  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
  preDecoderIn.pageFault     :=  f3_except_pf  
  preDecoderIn.accessFault   :=  f3_except_af


475
  // TODO: What if next packet does not match?
J
JinYue 已提交
476 477
  when (f3_flush) {
    f3_lastHalf.valid := false.B
478
  }.elsewhen (io.toIbuffer.fire()) {
J
JinYue 已提交
479 480
    f3_lastHalf.valid := preDecoderOut.hasLastHalf
    f3_lastHalf.middlePC := preDecoderOut.realEndPC
481 482
  }

J
JinYue 已提交
483
  val f3_predecode_range = VecInit(preDecoderOut.pd.map(inst => inst.valid)).asUInt
484

J
JinYue 已提交
485
  io.toIbuffer.valid          := f3_valid 
J
jinyue110 已提交
486
  io.toIbuffer.bits.instrs    := preDecoderOut.instrs
J
JinYue 已提交
487
  io.toIbuffer.bits.valid     := f3_predecode_range & preDecoderOut.instrRange.asUInt
J
jinyue110 已提交
488
  io.toIbuffer.bits.pd        := preDecoderOut.pd
J
JinYue 已提交
489
  io.toIbuffer.bits.ftqPtr    := f3_ftq_req.ftqIdx
490 491
  io.toIbuffer.bits.pc        := preDecoderOut.pc
  io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := preDecoderOut.takens(i)}
492
  io.toIbuffer.bits.foldpc    := preDecoderOut.pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth))
J
JinYue 已提交
493 494 495
  io.toIbuffer.bits.ipf       := preDecoderOut.pageFault
  io.toIbuffer.bits.acf       := preDecoderOut.accessFault
  io.toIbuffer.bits.crossPageIPFFix := preDecoderOut.crossPageIPF
J
JinYue 已提交
496

J
JinYue 已提交
497
  //Write back to Ftq
J
JinYue 已提交
498
  val finishFetchMaskReg = RegNext(f3_valid && !(f2_fire && !f2_flush))
J
JinYue 已提交
499

J
JinYue 已提交
500
  toFtq.pdWb.valid           := !finishFetchMaskReg && f3_valid
J
jinyue110 已提交
501
  toFtq.pdWb.bits.pc         := preDecoderOut.pc
502
  toFtq.pdWb.bits.pd         := preDecoderOut.pd 
J
JinYue 已提交
503 504 505
  toFtq.pdWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid :=  f3_predecode_range(i)}
  toFtq.pdWb.bits.ftqIdx     := f3_ftq_req.ftqIdx
  toFtq.pdWb.bits.ftqOffset  := f3_ftq_req.ftqOffset.bits 
506 507 508
  toFtq.pdWb.bits.misOffset  := preDecoderOut.misOffset
  toFtq.pdWb.bits.cfiOffset  := preDecoderOut.cfiOffset
  toFtq.pdWb.bits.target     := preDecoderOut.target
509
  toFtq.pdWb.bits.jalTarget  := preDecoderOut.jalTarget
510
  toFtq.pdWb.bits.instrRange := preDecoderOut.instrRange
511

J
JinYue 已提交
512 513
  val predecodeFlush     = preDecoderOut.misOffset.valid && f3_valid
  val predecodeFlushReg  = RegNext(predecodeFlush && !(f2_fire && !f2_flush))
514

J
JinYue 已提交
515
  f3_redirect := !predecodeFlushReg && predecodeFlush
J
JinYue 已提交
516

L
Lingrui98 已提交
517 518 519 520 521 522 523 524 525 526
  // Performance Counter
  XSPerfAccumulate("req",   io.toIbuffer.fire() )
  XSPerfAccumulate("miss",  io.toIbuffer.fire() && !f3_hit )
  XSPerfAccumulate("frontendFlush",  f3_redirect )
  XSPerfAccumulate("only_0_miss",   only_0_miss )
  XSPerfAccumulate("hit_0_miss_1",  hit_0_miss_1 )
  XSPerfAccumulate("miss_0_hit_1",  miss_0_hit_1 )
  XSPerfAccumulate("miss_0_miss_1", miss_0_miss_1 )
  XSPerfAccumulate("crossLine", io.toIbuffer.fire() && f3_situation(0) )
  XSPerfAccumulate("lastInLin", io.toIbuffer.fire() && f3_situation(1) )
527
}