1package xiangshan.frontend 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.backend.ALUOpType 7import utils._ 8import chisel3.experimental.chiselName 9 10class RASEntry() extends XSBundle { 11 val retAddr = UInt(VAddrBits.W) 12 val ctr = UInt(8.W) // layer of nested call functions 13} 14 15@chiselName 16class RAS extends BasePredictor 17{ 18 class RASResp extends Resp 19 { 20 val target =UInt(VAddrBits.W) 21 } 22 23 class RASBranchInfo extends Meta 24 { 25 val rasSp = UInt(log2Up(RasSize).W) 26 val rasTop = new RASEntry 27 } 28 29 class RASIO extends DefaultBasePredictorIO 30 { 31 val is_ret = Input(Bool()) 32 val callIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W))) 33 val isRVC = Input(Bool()) 34 val isLastHalfRVI = Input(Bool()) 35 val redirect = Flipped(ValidIO(new Redirect)) 36 val out = ValidIO(new RASResp) 37 val meta = Output(new RASBranchInfo) 38 } 39 40 41 def rasEntry() = new RASEntry 42 43 object RASEntry { 44 def apply(retAddr: UInt, ctr: UInt): RASEntry = { 45 val e = Wire(rasEntry()) 46 e.retAddr := retAddr 47 e.ctr := ctr 48 e 49 } 50 } 51 52 override val io = IO(new RASIO) 53 override val debug = true 54 55 @chiselName 56 class RASStack(val rasSize: Int) extends XSModule { 57 val io = IO(new Bundle { 58 val push_valid = Input(Bool()) 59 val pop_valid = Input(Bool()) 60 val new_addr = Input(UInt(VAddrBits.W)) 61 val top_addr = Output(UInt(VAddrBits.W)) 62 val is_empty = Output(Bool()) 63 val is_full = Output(Bool()) 64 val copy_valid = Input(Bool()) 65 val copy_in_mem = Input(Vec(rasSize, rasEntry())) 66 val copy_in_sp = Input(UInt(log2Up(rasSize).W)) 67 val copy_in_top = Input(rasEntry()) 68 val copy_out_mem = Output(Vec(rasSize, rasEntry())) 69 val copy_out_sp = Output(UInt(log2Up(rasSize).W)) 70 val copy_out_top = Output(rasEntry()) 71 72 }) 73 val debugIO = IO(new Bundle{ 74 val write_entry = Output(rasEntry()) 75 val alloc_new = Output(Bool()) 76 val sp = Output(UInt(log2Up(rasSize).W)) 77 val topRegister = Output(rasEntry()) 78 }) 79 @chiselName 80 class Stack(val size: Int) extends XSModule { 81 val io = IO(new Bundle { 82 val rIdx = Input(UInt(log2Up(size).W)) 83 val rdata = Output(rasEntry()) 84 val wen = Input(Bool()) 85 val wIdx = Input(UInt(log2Up(size).W)) 86 val wdata = Input(rasEntry()) 87 val copyen = Input(Bool()) 88 val copy_in = Input(Vec(size, rasEntry())) 89 val copy_out = Output(Vec(size, rasEntry())) 90 }) 91 val mem = Reg(Vec(size, rasEntry())) 92 when (io.wen) { 93 mem(io.wIdx) := io.wdata 94 } 95 io.rdata := mem(io.rIdx) 96 (0 until size).foreach { i => io.copy_out(i) := mem(i) } 97 when (io.copyen) { 98 (0 until size).foreach {i => mem(i) := io.copy_in(i) } 99 } 100 } 101 val sp = RegInit(RasSize.U((log2Up(rasSize) + 1).W)) 102 val topRegister = RegInit(0.U.asTypeOf(new RASEntry)) 103 val stack = Module(new Stack(rasSize)).io 104 105 stack.rIdx := sp - 1.U 106 val top_addr = topRegister.retAddr 107 val top_ctr = topRegister.ctr 108 val alloc_new = io.new_addr =/= top_addr 109 // stack.wen := io.push_valid || io.pop_valid && top_ctr =/= 1.U 110 // stack.wIdx := Mux(io.pop_valid && top_ctr =/= 1.U, sp - 1.U, Mux(alloc_new, sp, sp - 1.U)) 111 // val write_addr = Mux(io.pop_valid && top_ctr =/= 1.U, top_addr, io.new_addr) 112 // val write_ctr = Mux(io.pop_valid && top_ctr =/= 1.U, top_ctr - 1.U, Mux(alloc_new, 1.U, top_ctr + 1.U)) 113 114 stack.wen := io.push_valid && !io.is_empty 115 stack.wIdx := sp 116 val write_addr = topRegister.retAddr 117 val write_ctr = topRegister.ctr 118 119 val write_entry = RASEntry(write_addr, write_ctr) 120 stack.wdata := write_entry 121 debugIO.write_entry := write_entry 122 debugIO.alloc_new := alloc_new 123 debugIO.sp := sp 124 debugIO.topRegister := topRegister 125 126 val is_empty = sp === RasSize.U 127 val is_full = sp === (RasSize - 1).U 128 129 when (io.push_valid && alloc_new) { 130 sp := Mux(is_full, sp, Mux(is_empty, 0.U,sp + 1.U)) 131 top_addr := io.new_addr 132 top_ctr := 1.U 133 } .elsewhen(io.push_valid) { 134 top_ctr := top_ctr + 1.U 135 } 136 137 when (io.pop_valid && top_ctr === 1.U) { 138 sp := Mux(is_empty, sp ,Mux(sp === 0.U, RasSize.U,sp - 1.U)) 139 top_addr := stack.rdata.retAddr 140 top_ctr := stack.rdata.ctr 141 } .elsewhen(io.pop_valid) { 142 top_ctr := top_ctr - 1.U 143 } 144 145 io.copy_out_mem := stack.copy_out 146 io.copy_out_sp := sp 147 io.copy_out_top := topRegister 148 if(EnableCommit){ 149 stack.copyen := io.copy_valid 150 stack.copy_in := io.copy_in_mem 151 } else { 152 stack.copyen := false.B 153 stack.copy_in := DontCare 154 } 155 when (io.copy_valid) { 156 sp := io.copy_in_sp 157 topRegister := io.copy_in_top 158 } 159 160 io.top_addr := top_addr 161 io.is_empty := is_empty 162 io.is_full := is_full 163 } 164 165 // val ras_0 = Reg(Vec(RasSize, rasEntry())) //RegInit(0.U)asTypeOf(Vec(RasSize,rasEntry)) cause comb loop 166 // val ras_1 = Reg(Vec(RasSize, rasEntry())) 167 // val sp_0 = RegInit(0.U(log2Up(RasSize).W)) 168 // val sp_1 = RegInit(0.U(log2Up(RasSize).W)) 169 // val choose_bit = RegInit(false.B) //start with 0 170 // val spec_ras = Mux(choose_bit, ras_1, ras_0) 171 // val spec_sp = Mux(choose_bit,sp_1,sp_0) 172 // val commit_ras = Mux(choose_bit, ras_0, ras_1) 173 // val commit_sp = Mux(choose_bit,sp_0,sp_1) 174 175 // val spec_ras = Reg(Vec(RasSize, rasEntry())) 176 // val spec_sp = RegInit(0.U(log2Up(RasSize).W)) 177 // val commit_ras = Reg(Vec(RasSize, rasEntry())) 178 // val commit_sp = RegInit(0.U(log2Up(RasSize).W)) 179 180 val spec = Module(new RASStack(RasSize)) 181 val spec_ras = spec.io 182 183 184 val spec_push = WireInit(false.B) 185 val spec_pop = WireInit(false.B) 186 val jump_is_first = io.callIdx.bits === 0.U 187 val call_is_last_half = io.isLastHalfRVI && jump_is_first 188 val spec_new_addr = packetAligned(io.pc.bits) + (io.callIdx.bits << instOffsetBits.U) + Mux( (io.isRVC | call_is_last_half) && HasCExtension.B, 2.U, 4.U) 189 spec_ras.push_valid := spec_push 190 spec_ras.pop_valid := spec_pop 191 spec_ras.new_addr := spec_new_addr 192 val spec_is_empty = spec_ras.is_empty 193 val spec_is_full = spec_ras.is_full 194 val spec_top_addr = spec_ras.top_addr 195 196 spec_push := !spec_is_full && io.callIdx.valid && io.pc.valid 197 spec_pop := !spec_is_empty && io.is_ret && io.pc.valid 198 199 val copy_valid = io.redirect.valid 200 val copy_next = RegNext(copy_valid) 201 // val copy_bits = RegNext(io.recover.bpuMeta) 202 203 if(EnableCommit){ 204 val commit_cfi = io.redirect.bits.cfiUpdate 205 val commit = Module(new RASStack(RasSize)) 206 val commit_ras = commit.io 207 208 val commit_push = WireInit(false.B) 209 val commit_pop = WireInit(false.B) 210 val commit_new_addr = Mux(commit_cfi.pd.isRVC && HasCExtension.B, commit_cfi.pc + 2.U, commit_cfi.pc + 4.U) 211 commit_ras.push_valid := commit_push 212 commit_ras.pop_valid := commit_pop 213 commit_ras.new_addr := commit_new_addr 214 val commit_is_empty = commit_ras.is_empty 215 val commit_is_full = commit_ras.is_full 216 val commit_top_addr = commit_ras.top_addr 217 218 val update_valid = io.update.valid 219 val update = io.update.bits 220 val update_call_valid = update_valid && update.cfiIsCall && update.cfiIndex.valid && update.valids(update.cfiIndex.bits) 221 val update_ret_valid = update_valid && update.cfiIsRet && update.cfiIndex.valid && update.valids(update.cfiIndex.bits) 222 commit_push := !commit_is_full && update_call_valid 223 commit_pop := !commit_is_empty && update_ret_valid 224 225 commit_ras.copy_valid := false.B 226 commit_ras.copy_in_mem := DontCare 227 commit_ras.copy_in_sp := DontCare 228 commit_ras.copy_in_top := DontCare 229 230 spec_ras.copy_valid := copy_next 231 spec_ras.copy_in_mem := commit_ras.copy_out_mem 232 233 spec_ras.copy_in_sp := commit_ras.copy_out_sp 234 spec_ras.copy_in_top := commit_ras.copy_out_top 235 236 //no need to pass the ras branchInfo 237 io.meta.rasSp := DontCare 238 io.meta.rasTop := DontCare 239 240 if (BPUDebug && debug) { 241 val commit_debug = commit.debugIO 242 XSDebug("----------------RAS(commit)----------------\n") 243 XSDebug(" TopRegister: 0x%x %d \n",commit_debug.topRegister.retAddr,commit_debug.topRegister.ctr) 244 XSDebug(" index addr ctr \n") 245 for(i <- 0 until RasSize){ 246 XSDebug(" (%d) 0x%x %d",i.U,commit_ras.copy_out_mem(i).retAddr,commit_ras.copy_out_mem(i).ctr) 247 when(i.U === commit_ras.copy_out_sp){XSDebug(false,true.B," <----sp")} 248 XSDebug(false,true.B,"\n") 249 } 250 XSDebug(commit_push, "(commit_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d | TopReg.addr %x ctr:%d\n",commit_new_addr,commit_debug.write_entry.ctr,commit_debug.alloc_new,commit_debug.sp.asUInt,commit_debug.topRegister.retAddr,commit_debug.topRegister.ctr) 251 XSDebug(commit_pop, "(commit_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 252 } 253 254 } else { 255 val retMissPred = copy_valid && io.redirect.bits.level === 0.U && io.redirect.bits.cfiUpdate.pd.isRet 256 val recoverSp = io.redirect.bits.cfiUpdate.rasSp 257 val recoverTopAddr = io.redirect.bits.cfiUpdate.rasEntry.retAddr 258 val recoverTopCtr = io.redirect.bits.cfiUpdate.rasEntry.ctr 259 spec_ras.copy_valid := copy_valid 260 spec_ras.copy_in_mem := DontCare 261 262 spec_ras.copy_in_sp := Mux(retMissPred && recoverTopCtr === 1.U ,recoverSp - 1.U,recoverSp) 263 spec_ras.copy_in_top.retAddr := recoverTopAddr 264 spec_ras.copy_in_top.ctr := Mux(!retMissPred , recoverTopCtr, Mux(recoverTopCtr === 1.U,recoverTopCtr, recoverTopCtr - 1.U)) 265 266 io.meta.rasSp := spec_ras.copy_out_sp 267 io.meta.rasTop := spec.debugIO.topRegister 268 269 } 270 271 io.out.valid := !spec_is_empty 272 io.out.bits.target := spec_top_addr 273 // TODO: back-up stack for ras 274 // use checkpoint to recover RAS 275 276 if (BPUDebug && debug) { 277 val spec_debug = spec.debugIO 278 XSDebug("----------------RAS(spec)----------------\n") 279 XSDebug(" TopRegister: 0x%x %d \n",spec_debug.topRegister.retAddr,spec_debug.topRegister.ctr) 280 XSDebug(" index addr ctr \n") 281 for(i <- 0 until RasSize){ 282 XSDebug(" (%d) 0x%x %d",i.U,spec_ras.copy_out_mem(i).retAddr,spec_ras.copy_out_mem(i).ctr) 283 when(i.U === spec_ras.copy_out_sp){XSDebug(false,true.B," <----sp")} 284 XSDebug(false,true.B,"\n") 285 } 286 XSDebug(spec_push, "(spec_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n",spec_new_addr,spec_debug.write_entry.ctr,spec_debug.alloc_new,spec_debug.sp.asUInt) 287 XSDebug(spec_pop, "(spec_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 288 289 XSDebug("copyValid:%d copyNext:%d recover(SP:%d retAddr:%x ctr:%d) \n",copy_valid,copy_next,io.redirect.bits.cfiUpdate.rasSp,io.redirect.bits.cfiUpdate.rasEntry.retAddr,io.redirect.bits.cfiUpdate.rasEntry.ctr) 290 } 291 292} 293