1package xiangshan.frontend 2 3import chisel3._ 4import chisel3.util._ 5import device.RAMHelper 6import xiangshan._ 7import xiangshan.utils._ 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 FakeIcacheResp extends XSBundle { 18 val icacheOut = Vec(FetchWidth, UInt(32.W)) 19 val predecode = new Predecode 20} 21 22 23class IFUIO extends XSBundle 24{ 25 val fetchPacket = DecoupledIO(new FetchPacket) 26 val redirectInfo = Input(new RedirectInfo) 27 val icacheReq = DecoupledIO(UInt(VAddrBits.W)) 28 val icacheResp = Flipped(DecoupledIO(new FakeIcacheResp)) 29} 30 31class FakeBPU extends XSModule{ 32 val io = IO(new Bundle() { 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 extends XSModule with HasIFUConst 48{ 49 val io = IO(new IFUIO) 50 //val bpu = Module(new BPU) 51 val bpu = Module(new FakeBPU) 52 53 //------------------------- 54 // IF1 PC update 55 //------------------------- 56 //local 57 val if1_npc = WireInit(0.U(VAddrBits.W)) 58 val if1_valid = !reset.asBool //TODO:this is ugly 59 val if1_pc = RegInit(resetVector.U(VAddrBits.W)) 60 //next 61 val if2_ready = WireInit(false.B) 62 val if2_snpc = Cat(if1_pc(VAddrBits-1, groupAlign) + 1.U, 0.U(groupAlign.W)) 63 val if1_ready = if2_ready 64 65 //pipe fire 66 val if1_fire = if1_valid && if1_ready 67 val if1_pcUpdate = io.redirectInfo.flush() || if1_fire 68 69 when(RegNext(reset.asBool) && !reset.asBool){ 70 XSDebug("RESET....\n") 71 if1_npc := resetVector.U(VAddrBits.W) 72 } .otherwise{ 73 if1_npc := if2_snpc 74 } 75 76 when(if1_pcUpdate) 77 { 78 if1_pc := if1_npc 79 } 80 81 bpu.io.in.pc.valid := if1_valid 82 bpu.io.in.pc.bits := if1_npc 83 84 XSDebug("[IF1]if1_valid:%d || if1_npc:0x%x || if1_pcUpdate:%d if1_pc:0x%x || if2_ready:%d",if1_valid,if1_npc,if1_pcUpdate,if1_pc,if2_ready) 85 XSDebug(false,if1_fire,"------IF1->fire!!!") 86 XSDebug(false,true.B,"\n") 87 88 //------------------------- 89 // IF2 btb resonse 90 // icache visit 91 //------------------------- 92 //local 93 //val if2_flush = WireInit(false.B) 94 val if2_valid = RegEnable(next=if1_valid,init=false.B,enable=if1_fire) 95 val if2_pc = if1_pc 96 val if2_btb_taken = bpu.io.btbOut.valid 97 val if2_btb_insMask = bpu.io.btbOut.bits.instrValid 98 val if2_btb_target = bpu.io.btbOut.bits.target 99 100 //next 101 val if3_ready = WireInit(false.B) 102 103 //pipe fire 104 val if2_fire = if2_valid && if3_ready && io.icacheReq.fire() 105 if2_ready := (if2_fire) || !if2_valid 106 107 io.icacheReq.valid := if2_valid 108 io.icacheReq.bits := groupPC(if2_pc) 109 110 when(if2_valid && if2_btb_taken) 111 { 112 if1_npc := if2_btb_target 113 } 114 115 XSDebug("[IF2]if2_valid:%d || if2_pc:0x%x || if3_ready:%d ",if2_valid,if2_pc,if3_ready) 116 //XSDebug("[IF2-BPU-out]if2_btbTaken:%d || if2_btb_insMask:%b || if2_btb_target:0x%x \n",if2_btb_taken,if2_btb_insMask.asUInt,if2_btb_target) 117 XSDebug(false,if2_fire,"------IF2->fire!!!") 118 XSDebug(false,true.B,"\n") 119 XSDebug("[IF2-Icache-Req] icache_in_valid:%d icache_in_ready:%d\n",io.icacheReq.valid,io.icacheReq.ready) 120 121 //------------------------- 122 // IF3 icache hit check 123 //------------------------- 124 //local 125 val if3_valid = RegEnable(next=if2_valid,init=false.B,enable=if2_fire) 126 val if3_pc = RegEnable(if2_pc,if2_fire) 127 val if3_btb_target = RegEnable(if2_btb_target,if2_fire) 128 val if3_btb_taken = RegEnable(if2_btb_taken,if2_fire) 129 130 //next 131 val if4_ready = WireInit(false.B) 132 133 //pipe fire 134 val if3_fire = if3_valid && if4_ready 135 if3_ready := if3_fire || !if3_valid 136 137 138 XSDebug("[IF3]if3_valid:%d || if3_pc:0x%x || if4_ready:%d ",if3_valid,if3_pc,if4_ready) 139 XSDebug(false,if3_fire,"------IF3->fire!!!") 140 XSDebug(false,true.B,"\n") 141 142 //------------------------- 143 // IF4 icache resonse 144 // RAS result 145 // taget generate 146 //------------------------- 147 val if4_valid = RegEnable(next=if3_valid,init=false.B,enable=if3_fire) 148 val if4_pc = RegEnable(if3_pc,if3_fire) 149 val if4_btb_target = RegEnable(if3_btb_target,if3_fire) 150 val if4_btb_taken = RegEnable(if3_btb_taken,if3_fire) 151 val if4_tage_target = bpu.io.tageOut.bits.target 152 val if4_tage_taken = bpu.io.tageOut.valid 153 val if4_tage_insMask = bpu.io.tageOut.bits.instrValid 154 XSDebug("[IF4]if4_valid:%d || if4_pc:0x%x \n",if4_valid,if4_pc) 155 //XSDebug("[IF4-TAGE-out]if4_tage_taken:%d || if4_btb_insMask:%b || if4_tage_target:0x%x \n",if4_tage_taken,if4_tage_insMask.asUInt,if4_tage_target) 156 XSDebug("[IF4-ICACHE-RESP]icacheResp.valid:%d icacheResp.ready:%d\n",io.icacheResp.valid,io.icacheResp.ready) 157 158 when(if4_valid && io.icacheResp.fire() && if4_tage_taken) 159 { 160 if1_npc := if4_tage_target 161 } 162 163 164 //redirect: miss predict 165 when(io.redirectInfo.flush()){ 166 if1_npc := io.redirectInfo.redirect.target 167 if3_valid := false.B 168 if4_valid := false.B 169 } 170 XSDebug(io.redirectInfo.flush(),"[IFU-REDIRECT] target:0x%x \n",io.redirectInfo.redirect.target.asUInt) 171 172 //Output -> iBuffer 173 io.fetchPacket <> DontCare 174 if4_ready := io.fetchPacket.ready && (io.icacheResp.valid || !if4_valid) 175 io.fetchPacket.valid := if4_valid && !io.redirectInfo.flush() 176 io.fetchPacket.bits.instrs := io.icacheResp.bits.icacheOut 177 io.fetchPacket.bits.mask := Fill(FetchWidth*2, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 1) 178 io.fetchPacket.bits.pc := if4_pc 179 180 //to BPU 181 bpu.io.predecode.valid := io.icacheResp.fire() && if4_valid 182 bpu.io.predecode.bits <> io.icacheResp.bits.predecode 183 bpu.io.predecode.bits.mask := Fill(FetchWidth, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 2) //TODO: consider RVC 184 185 io.icacheResp.ready := io.fetchPacket.ready 186 187} 188 189