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