1package xiangshan.frontend 2 3import chisel3._ 4import chisel3.util._ 5import chisel3.core.{withReset} 6import device.RAMHelper 7import xiangshan._ 8 9trait HasIFUConst { this: XSModule => 10 val resetVector = 0x80000000L//TODO: set reset vec 11 12 val groupAlign = log2Up(FetchWidth * 4) 13 def groupPC(pc: UInt): UInt = Cat(pc(VAddrBits-1, groupAlign), 0.U(groupAlign.W)) 14 15} 16 17class IFUIO extends IFUBundle 18{ 19 val fetchPacket = DecoupledIO(new FetchPacket) 20 val redirect = Flipped(ValidIO(new Redirect)) 21 val icacheReq = DecoupledIO(UInt(VAddrBits.W) 22 val icacheResp = Flipped(DecoupledIO(new FakeIcacheResp)) 23} 24 25class FakeBPU extends XSModule { 26 val io = IO(new Bundle() { 27 val redirect = Flipped(ValidIO(new Redirect)) 28 val in = new Bundle { val pc = Flipped(Valid(UInt(VAddrBits.W))) } 29 val btbOut = ValidIO(new BranchPrediction) 30 val tageOut = ValidIO(new BranchPrediction) 31 val predecode = Flipped(ValidIO(new Predecode)) 32 }) 33 34 io.btbOut.valid := false.B 35 io.btbOut.bits <> DontCare 36 io.tageOut.valid := false.B 37 io.tageOut.bits <> DontCare 38} 39 40 41 42class IFU(implicit val p: XSConfig) extends IFUModule with HasIFUConst 43{ 44 val io = IO(new IFUIO) 45 val bpu = Module(new FakeBPU) 46 47 //------------------------- 48 // IF1 PC update 49 //------------------------- 50 //local 51 val if1_npc = WireInit(0.U(VAddrBits.W)) 52 val if1_valid = WireInit(false.B) 53 val if1_pc = RegInit(resetVector.U(VAddrBits.W)) 54 //next 55 val if2_ready = WireInit(false.B) 56 val if1_ready = if2_ready 57 58 //pipe fire 59 val if1_fire = if1_valid && if1_ready 60 val if1_pcUpdate = io.redirect.valid || if1_fire 61 62 when(RegNext(reset.asBool) && !reset.asBool) 63 { 64 if1_npc := resetVector.U(VAddrBits.W) 65 if1_valid := true.B 66 } 67 68 when(if1_pcUpdate) 69 { 70 if1_pc := if1_npc 71 } 72 73 bpu.io.in.valid := if1_valid 74 bpu.io.in.pc := if1_npc 75 76 //------------------------- 77 // IF2 btb resonse 78 // icache visit 79 //------------------------- 80 //local 81 val if2_flush = WireInit(false.B) 82 val if2_update = if1_fire && !if2_flush 83 val if2_valid = RegNext(if2_update) 84 val if2_pc = if1_pc 85 val if2_btb_taken = bpu.io.btbOut.valid 86 val if2_btb_insMask = bpu.io.btbOut.bits.instrValid 87 val if2_btb_target = bpu.io.btbOut.bits.target 88 val if2_snpc = Cat(if2_pc(VAddrBits-1, groupAlign) + 1.U, 0.U(groupAlign.W)) 89 val if2_flush = WireInit(false.B) 90 91 //next 92 val if3_ready = WireInit(false.B) 93 94 //pipe fire 95 val if2_fire = if2_valid && if3_ready 96 val if2_ready = (if2_fire && io.icacheReq.fire()) || !if2_valid 97 98 io.icacheReq.valid := if2_fire 99 io.icacheReq.bits := groupPC(if2_pc) 100 101 when(if2_valid && if2_btb_taken) 102 { 103 if1_npc := if2_btb_target 104 } .otherwise 105 { 106 if1_npc := if2_snpc 107 } 108 109 //------------------------- 110 // IF3 icache hit check 111 //------------------------- 112 //local 113 val if3_flush = WireInit(false.B) 114 val if3_update = if2_fire && !if3_flush 115 val if3_valid = RegNext(if3_update) 116 val if3_pc = RegEnable(if2_pc,if3_update) 117 val if3_btb_target = RegEnable(if2_btb_target,if3_update) 118 val if3_btb_taken = RegEnable(if2_btb_taken,if3_update) 119 120 //next 121 val if4_ready = WireInit(false.B) 122 123 //pipe fire 124 val if3_fire = if3_valid && if4_ready 125 val if3_ready = if3_fire || !if3_valid 126 127 //------------------------- 128 // IF4 icache resonse 129 // RAS result 130 // taget generate 131 //------------------------- 132 val if4_flush = WireInit(false.B) 133 val if4_update = if3_fire && !if4_flush 134 val if4_valid = RegNext(if4_update) 135 val if4_pc = RegEnable(if3_pc,if4_update) 136 val if4_btb_target = RegEnable(if3_btb_target,if4_update) 137 val if4_btb_taken = RegEnable(if3_btb_taken,if4_update) 138 139 140 141 when(if4_valid && io.icacheResp.fire()) 142 { 143 if1_npc := if4_btb_target 144 } 145 146 147 //redirect 148 when(io.redirect.valid){ 149 if1_npc := io.redirect.bits.target 150 if2_flush := true.B 151 if3_flush := true.B 152 if4_flush := true.B 153 } 154 155 156 //Output -> iBuffer 157 if4_ready := io.fetchPacket.ready && io.icacheResp.valid 158 io.fetchPacket.valid := if4_valid && !if4_flush 159 io.fetchPacket.instrs := io.icacheResp.bits.icacheOut 160 io.fetchPacket.mask := Fill(FetchWidth*2, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 1) 161 io.fetchPacket.pc := if4_pc 162 163 //to BPU 164 bpu.io.predecode.valid := if4_valid 165 bpu.io.predecode.bits <> io.icacheResp.bits.predecode 166 bpu.io.predecode.bits.mask := Fill(FetchWidth, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 2) //TODO: consider RVC 167 168 io.icacheResp.ready := io.fetchPacket.ready 169 170} 171 172