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