xref: /XiangShan/src/main/scala/xiangshan/frontend/IFU.scala (revision ee286e3b31ae1b5b9b93a480461aadca454c6e73)
1package xiangshan.frontend
2
3import chisel3._
4import chisel3.util._
5import device.RAMHelper
6import xiangshan._
7import utils._
8
9trait HasIFUConst { this: XSModule =>
10  val resetVector = 0x80000000L//TODO: set reset vec
11  val groupAlign = log2Up(FetchWidth * 4)
12  def groupPC(pc: UInt): UInt = Cat(pc(VAddrBits-1, groupAlign), 0.U(groupAlign.W))
13  // def snpc(pc: UInt): UInt = pc + (1 << groupAlign).U
14  def mask(pc: UInt): UInt = (Fill(PredictWidth * 2, 1.U(1.W)) >> pc(groupAlign - 1, 1))(PredictWidth - 1, 0)
15  def snpc(pc: UInt): UInt = pc + (PopCount(mask(pc)) << 1)
16}
17
18class IFUIO extends XSBundle
19{
20  val fetchPacket = DecoupledIO(new FetchPacket)
21  val redirect = Flipped(ValidIO(new Redirect))
22  val outOfOrderBrInfo = Flipped(ValidIO(new BranchUpdateInfo))
23  val inOrderBrInfo = Flipped(ValidIO(new BranchUpdateInfo))
24  val icacheReq = DecoupledIO(new FakeIcacheReq)
25  val icacheResp = Flipped(DecoupledIO(new FakeIcacheResp))
26}
27
28
29class IFU extends XSModule with HasIFUConst
30{
31  val io = IO(new IFUIO)
32  val bpu = if (EnableBPD) Module(new BPU) else Module(new FakeBPU)
33
34  val if2_redirect, if3_redirect, if4_redirect = WireInit(false.B)
35  val if1_flush, if2_flush, if3_flush, if4_flush = WireInit(false.B)
36
37  //********************** IF1 ****************************//
38  val if1_valid = !reset.asBool
39  val if1_npc = WireInit(0.U(VAddrBits.W))
40  val if2_ready = WireInit(false.B)
41  val if1_fire = if1_valid && (if2_ready || if1_flush) && io.icacheReq.ready
42
43  val extHist = RegInit(Vec(ExtHistoryLength, 0.U(1.W)))
44  val headPtr = RegInit(0.U(log2Up(ExtHistoryLength).W))
45  val updateHist = io.outOfOrderBrInfo.valid
46  val newPtr = Wire(UInt(log2Up(ExtHistoryLength).W))
47  val ptr = Mux(updateHist, newPtr, headPtr)
48  when (updateHist) { headPtr := newPtr }
49  val hist = Wire(Vec(HistoryLength, UInt(1.W)))
50  for (i <- 0 until HistoryLength) {
51    hist(i) := extHist(ptr + i.U)
52  }
53
54  //********************** IF2 ****************************//
55  val if2_valid = RegEnable(next = if1_valid, init = false.B, enable = if1_fire)
56  val if3_ready = WireInit(false.B)
57  val if2_fire = if2_valid && if3_ready
58  val if2_pc = RegEnable(next = if1_npc, init = resetVector.U, enable = if1_fire)
59  val if2_snpc = snpc(if2_pc)
60  if2_ready := if2_fire || !if2_valid
61
62  when (RegNext(reset.asBool) && !reset.asBool) {
63    if1_npc := resetVector.U(VAddrBits.W)
64  }.elsewhen (if2_fire) {
65    if1_npc := if2_snpc
66  }.otherwise {
67    if1_npc := RegNext(if1_npc)
68  }
69
70  val if2_bp = bpu.io.out(0).bits
71  val if2_prev_half_valid = RegInit(false.B)
72  val if2_prev_half_redirect = RegInit(false.B)
73  val if2_prev_half_fetchpc = Reg(UInt(VAddrBits.W))
74  val if2_prev_half_idx = Reg(UInt(log2Up(PredictWidth).W))
75  val if2_prev_half_tgt = Reg(UInt(VAddrBits.W))
76  val if2_prev_half_taken = RegInit(false.B)
77  when (if2_flush) {
78    if2_prev_half_valid := false.B
79    if2_prev_half_redirect := false.B
80  }.elsewhen (if2_fire && if2_bp.saveHalfRVI) {
81    if2_prev_half_valid := true.B
82    if2_prev_half_redirect := if2_bp.redirect && bpu.io.out(0).valid
83    if2_prev_half_fetchpc := if2_pc
84    if2_prev_half_idx := Mux(if2_bp.redirect && bpu.io.out(0).valid, if2_bp.jmpIdx, PopCount(mask(if2_pc)) - 1.U)
85    if2_prev_half_tgt := if2_bp.target
86    if2_prev_half_taken := if2_bp.taken
87  }.elsewhen (if2_fire) {
88    if2_prev_half_valid := false.B
89    if2_prev_half_redirect := false.B
90  }
91
92  if2_redirect := if2_fire && (if2_prev_half_valid && if2_prev_half_redirect || bpu.io.out(0).valid && if2_bp.redirect && !if2_bp.saveHalfRVI)
93  when (if2_redirect) {
94    if1_npc := Mux(if2_prev_half_valid && if2_prev_half_redirect, if2_prev_half_tgt, if2_bp.target)
95  }
96
97  //********************** IF3 ****************************//
98  val if3_valid = RegEnable(next = if2_valid, init = false.B, enable = if2_fire)
99  val if4_ready = WireInit(false.B)
100  val if3_fire = if3_valid && if4_ready && io.icacheResp.valid
101
102
103  //********************** IF4 ****************************//
104
105
106
107  io.icacheReq.valid := if1_valid
108  io.icacheReq.bits.addr := if1_npc
109  // io.icacheReq.bits.flush :=
110  io.icacheResp.ready := if3_valid
111
112  bpu.io.inOrderBrInfo <> io.inOrderBrInfo
113  bpu.io.flush := Cat(if4_flush, if3_flush, if2_flush)
114  bpu.io.in.valid := if1_fire
115  bpu.io.in.bits.pc := if1_npc
116  bpu.io.in.bits.hist := hist.asUInt
117  bpu.io.in.bits.inMask := mask(if1_npc)
118  bpu.io.out(0).ready := if2_fire
119  // bpu.io.out(1).ready
120  // bpu.io.out(2).ready
121}