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