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