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 = !reset.asBool 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 } 66 67 when(if1_pcUpdate) 68 { 69 if1_pc := if1_npc 70 } 71 72 bpu.io.in.valid := if1_valid 73 bpu.io.in.pc := if1_npc 74 75 //------------------------- 76 // IF2 btb resonse 77 // icache visit 78 //------------------------- 79 //local 80 val if2_flush = WireInit(false.B) 81 val if2_update = if1_fire && !if2_flush 82 val if2_valid = RegNext(if2_update) 83 val if2_pc = if1_pc 84 val if2_btb_taken = bpu.io.btbOut.valid 85 val if2_btb_insMask = bpu.io.btbOut.bits.instrValid 86 val if2_btb_target = bpu.io.btbOut.bits.target 87 val if2_snpc = Cat(if2_pc(VAddrBits-1, groupAlign) + 1.U, 0.U(groupAlign.W)) 88 val if2_flush = WireInit(false.B) 89 90 //next 91 val if3_ready = WireInit(false.B) 92 93 //pipe fire 94 val if2_fire = if2_valid && if3_ready 95 val if2_ready = (if2_fire && io.icacheReq.fire()) || !if2_valid 96 97 io.icacheReq.valid := if2_fire 98 io.icacheReq.bits := groupPC(if2_pc) 99 100 when(if2_valid && if2_btb_taken) 101 { 102 if1_npc := if2_btb_target 103 } .otherwise 104 { 105 if1_npc := if2_snpc 106 } 107 108 //------------------------- 109 // IF3 icache hit check 110 //------------------------- 111 //local 112 val if3_flush = WireInit(false.B) 113 val if3_update = if2_fire && !if3_flush 114 val if3_valid = RegNext(if3_update) 115 val if3_pc = RegEnable(if2_pc,if3_update) 116 val if3_btb_target = RegEnable(if2_btb_target,if3_update) 117 val if3_btb_taken = RegEnable(if2_btb_taken,if3_update) 118 119 //next 120 val if4_ready = WireInit(false.B) 121 122 //pipe fire 123 val if3_fire = if3_valid && if4_ready 124 val if3_ready = if3_fire || !if3_valid 125 126 //------------------------- 127 // IF4 icache resonse 128 // RAS result 129 // taget generate 130 //------------------------- 131 val if4_flush = WireInit(false.B) 132 val if4_update = if3_fire && !if4_flush 133 val if4_valid = RegNext(if4_update) 134 val if4_pc = RegEnable(if3_pc,if4_update) 135 val if4_btb_target = RegEnable(if3_btb_target,if4_update) 136 val if4_btb_taken = RegEnable(if3_btb_taken,if4_update) 137 138 139 140 when(if4_valid && io.icacheResp.fire()) 141 { 142 if1_npc := if4_btb_target 143 } 144 145 146 //redirect 147 when(io.redirect.valid){ 148 if1_npc := io.redirect.bits.target 149 if2_flush := true.B 150 if3_flush := true.B 151 if4_flush := true.B 152 } 153 154 155 //Output -> iBuffer 156 if4_ready := io.fetchPacket.ready && io.icacheResp.valid 157 io.fetchPacket.valid := if4_valid && !if4_flush 158 io.fetchPacket.instrs := io.icacheResp.bits.icacheOut 159 io.fetchPacket.mask := Fill(FetchWidth*2, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 1) 160 io.fetchPacket.pc := if4_pc 161 162 //to BPU 163 bpu.io.predecode.valid := if4_valid 164 bpu.io.predecode.bits <> io.icacheResp.bits.predecode 165 bpu.io.predecode.bits.mask := Fill(FetchWidth, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 2) //TODO: consider RVC 166 167 io.icacheResp.ready := io.fetchPacket.ready 168 169} 170 171