1package xiangshan.frontend 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.backend.ALUOpType 7import utils._ 8import chisel3.experimental.chiselName 9 10@chiselName 11class RAS extends BasePredictor 12{ 13 class RASResp extends Resp 14 { 15 val target =UInt(VAddrBits.W) 16 } 17 18 class RASBranchInfo extends Meta 19 { 20 val rasSp = UInt(log2Up(RasSize).W) 21 val rasTopCtr = UInt(8.W) 22 val rasToqAddr = UInt(VAddrBits.W) 23 } 24 25 class RASIO extends DefaultBasePredictorIO 26 { 27 val is_ret = Input(Bool()) 28 val callIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W))) 29 val isRVC = Input(Bool()) 30 val isLastHalfRVI = Input(Bool()) 31 val recover = Flipped(ValidIO(new CfiUpdateInfo)) 32 val out = ValidIO(new RASResp) 33 val meta = Output(new RASBranchInfo) 34 } 35 36 class RASEntry() extends XSBundle { 37 val retAddr = UInt(VAddrBits.W) 38 val ctr = UInt(8.W) // layer of nested call functions 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_out_mem = Output(Vec(rasSize, rasEntry())) 68 val copy_out_sp = Output(UInt(log2Up(rasSize).W)) 69 }) 70 val debugIO = IO(new Bundle{ 71 val write_entry = Output(rasEntry()) 72 val alloc_new = Output(Bool()) 73 val sp = Output(UInt(log2Up(rasSize).W)) 74 }) 75 @chiselName 76 class Stack(val size: Int) extends XSModule { 77 val io = IO(new Bundle { 78 val rIdx = Input(UInt(log2Up(size).W)) 79 val rdata = Output(rasEntry()) 80 val wen = Input(Bool()) 81 val wIdx = Input(UInt(log2Up(size).W)) 82 val wdata = Input(rasEntry()) 83 val copyen = Input(Bool()) 84 val copy_in = Input(Vec(size, rasEntry())) 85 val copy_out = Output(Vec(size, rasEntry())) 86 }) 87 val mem = Reg(Vec(size, rasEntry())) 88 when (io.wen) { 89 mem(io.wIdx) := io.wdata 90 } 91 io.rdata := mem(io.rIdx) 92 (0 until size).foreach { i => io.copy_out(i) := mem(i) } 93 when (io.copyen) { 94 (0 until size).foreach {i => mem(i) := io.copy_in(i) } 95 } 96 } 97 val sp = RegInit(0.U(log2Up(rasSize).W)) 98 val stack = Module(new Stack(rasSize)).io 99 100 stack.rIdx := sp - 1.U 101 val top_entry = stack.rdata 102 val top_addr = top_entry.retAddr 103 val top_ctr = top_entry.ctr 104 val alloc_new = io.new_addr =/= top_addr 105 stack.wen := io.push_valid || io.pop_valid && top_ctr =/= 1.U 106 stack.wIdx := Mux(io.pop_valid && top_ctr =/= 1.U, sp - 1.U, Mux(alloc_new, sp, sp - 1.U)) 107 val write_addr = Mux(io.pop_valid && top_ctr =/= 1.U, top_addr, io.new_addr) 108 val write_ctr = Mux(io.pop_valid && top_ctr =/= 1.U, top_ctr - 1.U, Mux(alloc_new, 1.U, top_ctr + 1.U)) 109 val write_entry = RASEntry(write_addr, write_ctr) 110 stack.wdata := write_entry 111 debugIO.write_entry := write_entry 112 debugIO.alloc_new := alloc_new 113 debugIO.sp := sp 114 115 when (io.push_valid && alloc_new) { 116 sp := sp + 1.U 117 } 118 119 when (io.pop_valid && top_ctr === 1.U) { 120 sp := Mux(sp === 0.U, 0.U, sp - 1.U) 121 } 122 123 io.copy_out_mem := stack.copy_out 124 io.copy_out_sp := sp 125 stack.copyen := io.copy_valid 126 stack.copy_in := io.copy_in_mem 127 when (io.copy_valid) { 128 sp := io.copy_in_sp 129 } 130 131 io.top_addr := top_addr 132 io.is_empty := sp === 0.U 133 io.is_full := sp === (RasSize - 1).U 134 } 135 136 // val ras_0 = Reg(Vec(RasSize, rasEntry())) //RegInit(0.U)asTypeOf(Vec(RasSize,rasEntry)) cause comb loop 137 // val ras_1 = Reg(Vec(RasSize, rasEntry())) 138 // val sp_0 = RegInit(0.U(log2Up(RasSize).W)) 139 // val sp_1 = RegInit(0.U(log2Up(RasSize).W)) 140 // val choose_bit = RegInit(false.B) //start with 0 141 // val spec_ras = Mux(choose_bit, ras_1, ras_0) 142 // val spec_sp = Mux(choose_bit,sp_1,sp_0) 143 // val commit_ras = Mux(choose_bit, ras_0, ras_1) 144 // val commit_sp = Mux(choose_bit,sp_0,sp_1) 145 146 // val spec_ras = Reg(Vec(RasSize, rasEntry())) 147 // val spec_sp = RegInit(0.U(log2Up(RasSize).W)) 148 // val commit_ras = Reg(Vec(RasSize, rasEntry())) 149 // val commit_sp = RegInit(0.U(log2Up(RasSize).W)) 150 151 val spec = Module(new RASStack(RasSize)) 152 val spec_ras = spec.io 153 154 155 val spec_push = WireInit(false.B) 156 val spec_pop = WireInit(false.B) 157 val spec_new_addr = WireInit(bankAligned(io.pc.bits) + (io.callIdx.bits << 1.U) + Mux(io.isRVC,2.U,Mux(io.isLastHalfRVI, 2.U, 4.U))) 158 spec_ras.push_valid := spec_push 159 spec_ras.pop_valid := spec_pop 160 spec_ras.new_addr := spec_new_addr 161 val spec_is_empty = spec_ras.is_empty 162 val spec_is_full = spec_ras.is_full 163 val spec_top_addr = spec_ras.top_addr 164 165 spec_push := !spec_is_full && io.callIdx.valid && io.pc.valid 166 spec_pop := !spec_is_empty && io.is_ret && io.pc.valid 167 168 val commit = Module(new RASStack(RasSize)) 169 val commit_ras = commit.io 170 171 val commit_push = WireInit(false.B) 172 val commit_pop = WireInit(false.B) 173 val commit_new_addr = Mux(io.recover.bits.pd.isRVC,io.recover.bits.pc + 2.U,io.recover.bits.pc + 4.U) 174 commit_ras.push_valid := commit_push 175 commit_ras.pop_valid := commit_pop 176 commit_ras.new_addr := commit_new_addr 177 val commit_is_empty = commit_ras.is_empty 178 val commit_is_full = commit_ras.is_full 179 val commit_top_addr = commit_ras.top_addr 180 181 commit_push := !commit_is_full && io.recover.valid && io.recover.bits.pd.isCall 182 commit_pop := !commit_is_empty && io.recover.valid && io.recover.bits.pd.isRet 183 184 185 io.out.valid := !spec_is_empty 186 io.out.bits.target := spec_top_addr 187 // TODO: back-up stack for ras 188 // use checkpoint to recover RAS 189 190 val copy_valid = io.recover.valid && (io.recover.bits.isMisPred || io.recover.bits.isReplay) 191 val copy_next = RegNext(copy_valid) 192 spec_ras.copy_valid := copy_next 193 spec_ras.copy_in_mem := commit_ras.copy_out_mem 194 spec_ras.copy_in_sp := commit_ras.copy_out_sp 195 commit_ras.copy_valid := false.B 196 commit_ras.copy_in_mem := DontCare 197 commit_ras.copy_in_sp := DontCare 198 199 //no need to pass the ras branchInfo 200 io.meta.rasSp := DontCare 201 io.meta.rasTopCtr := DontCare 202 io.meta.rasToqAddr := DontCare 203 204 if (BPUDebug && debug) { 205 val spec_debug = spec.debugIO 206 val commit_debug = commit.debugIO 207 XSDebug("----------------RAS(spec)----------------\n") 208 XSDebug(" index addr ctr \n") 209 for(i <- 0 until RasSize){ 210 XSDebug(" (%d) 0x%x %d",i.U,spec_ras.copy_out_mem(i).retAddr,spec_ras.copy_out_mem(i).ctr) 211 when(i.U === spec_ras.copy_out_sp){XSDebug(false,true.B," <----sp")} 212 XSDebug(false,true.B,"\n") 213 } 214 XSDebug("----------------RAS(commit)----------------\n") 215 XSDebug(" index addr ctr \n") 216 for(i <- 0 until RasSize){ 217 XSDebug(" (%d) 0x%x %d",i.U,commit_ras.copy_out_mem(i).retAddr,commit_ras.copy_out_mem(i).ctr) 218 when(i.U === commit_ras.copy_out_sp){XSDebug(false,true.B," <----sp")} 219 XSDebug(false,true.B,"\n") 220 } 221 222 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) 223 XSDebug(spec_pop, "(spec_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 224 XSDebug(commit_push, "(commit_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n",commit_new_addr,commit_debug.write_entry.ctr,commit_debug.alloc_new,commit_debug.sp.asUInt) 225 XSDebug(commit_pop, "(commit_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 226 XSDebug("copyValid:%d copyNext:%d \n",copy_valid,copy_next) 227 } 228 229 230 // val recoverSp = io.recover.bits.brInfo.rasSp 231 // val recoverCtr = io.recover.bits.brInfo.rasTopCtr 232 // val recoverAddr = io.recover.bits.brInfo.rasToqAddr 233 // val recover_top = ras(recoverSp - 1.U) 234 // when (recover_valid) { 235 // sp := recoverSp 236 // recover_top.ctr := recoverCtr 237 // recover_top.retAddr := recoverAddr 238 // XSDebug("RAS update: SP:%d , Ctr:%d \n",recoverSp,recoverCtr) 239 // } 240 // val recover_and_push = recover_valid && push 241 // val recover_and_pop = recover_valid && pop 242 // val recover_alloc_new = new_addr =/= recoverAddr 243 // when(recover_and_push) 244 // { 245 // when(recover_alloc_new){ 246 // sp := recoverSp + 1.U 247 // ras(recoverSp).retAddr := new_addr 248 // ras(recoverSp).ctr := 1.U 249 // recover_top.retAddr := recoverAddr 250 // recover_top.ctr := recoverCtr 251 // } .otherwise{ 252 // sp := recoverSp 253 // recover_top.ctr := recoverCtr + 1.U 254 // recover_top.retAddr := recoverAddr 255 // } 256 // } .elsewhen(recover_and_pop) 257 // { 258 // io.out.bits.target := recoverAddr 259 // when ( recover_top.ctr === 1.U) { 260 // sp := recoverSp - 1.U 261 // }.otherwise { 262 // sp := recoverSp 263 // recover_top.ctr := recoverCtr - 1.U 264 // } 265 // } 266 267} 268