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}