1package xiangshan.frontend 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.backend.ALUOpType 7import utils._ 8 9class RAS extends BasePredictor 10{ 11 class RASResp extends Resp 12 { 13 val target =UInt(VAddrBits.W) 14 } 15 16 class RASBranchInfo extends Meta 17 { 18 val rasSp = UInt(log2Up(RasSize).W) 19 val rasTopCtr = UInt(8.W) 20 val rasToqAddr = UInt(VAddrBits.W) 21 } 22 23 class RASIO extends DefaultBasePredictorIO 24 { 25 val is_ret = Input(Bool()) 26 val callIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W))) 27 val isRVC = Input(Bool()) 28 val isLastHalfRVI = Input(Bool()) 29 val recover = Flipped(ValidIO(new BranchUpdateInfo)) 30 val out = ValidIO(new RASResp) 31 val branchInfo = Output(new RASBranchInfo) 32 } 33 34 def rasEntry() = new Bundle { 35 val retAddr = UInt(VAddrBits.W) 36 val ctr = UInt(8.W) // layer of nested call functions 37 } 38 override val io = IO(new RASIO) 39 40 // val ras_0 = Reg(Vec(RasSize, rasEntry())) //RegInit(0.U)asTypeOf(Vec(RasSize,rasEntry)) cause comb loop 41 // val ras_1 = Reg(Vec(RasSize, rasEntry())) 42 // val sp_0 = RegInit(0.U(log2Up(RasSize).W)) 43 // val sp_1 = RegInit(0.U(log2Up(RasSize).W)) 44 // val choose_bit = RegInit(false.B) //start with 0 45 // val spec_ras = Mux(choose_bit, ras_1, ras_0) 46 // val spec_sp = Mux(choose_bit,sp_1,sp_0) 47 // val commit_ras = Mux(choose_bit, ras_0, ras_1) 48 // val commit_sp = Mux(choose_bit,sp_0,sp_1) 49 50 val spec_ras = Reg(Vec(RasSize, rasEntry())) 51 val spec_sp = RegInit(0.U(log2Up(RasSize).W)) 52 val commit_ras = Reg(Vec(RasSize, rasEntry())) 53 val commit_sp = RegInit(0.U(log2Up(RasSize).W)) 54 55 56 val spec_is_empty = spec_sp === 0.U 57 val spec_is_full = spec_sp === (RasSize - 1).U 58 59 val spec_ras_top_entry = spec_ras(spec_sp-1.U) 60 val spec_ras_top_addr = spec_ras_top_entry.retAddr 61 val spec_ras_top_ctr = spec_ras_top_entry.ctr 62 //no need to pass the ras branchInfo 63 io.branchInfo.rasSp := DontCare 64 io.branchInfo.rasTopCtr := DontCare 65 io.branchInfo.rasToqAddr := DontCare 66 67 io.out.valid := !spec_is_empty && io.is_ret 68 69 // update spec RAS 70 // speculative update RAS 71 val spec_push = !spec_is_full && io.callIdx.valid && io.pc.valid 72 val spec_pop = !spec_is_empty && io.is_ret && io.pc.valid 73 val spec_new_addr = io.pc.bits + (io.callIdx.bits << 1.U) + Mux(io.isRVC,2.U,Mux(io.isLastHalfRVI, 2.U, 4.U)) 74 val spec_ras_write = WireInit(0.U.asTypeOf(rasEntry())) 75 val sepc_alloc_new = spec_new_addr =/= spec_ras_top_addr 76 when (spec_push) { 77 //push 78 spec_ras_write.ctr := 1.U 79 spec_ras_write.retAddr := spec_new_addr 80 when(sepc_alloc_new){ 81 spec_sp := spec_sp + 1.U 82 spec_ras(spec_sp) := spec_ras_write 83 }.otherwise{ 84 spec_ras_top_ctr := spec_ras_top_ctr + 1.U 85 } 86 } 87 88 when (spec_pop) { 89 //pop 90 when (spec_ras_top_ctr === 1.U) { 91 spec_sp := Mux(spec_sp === 0.U, 0.U, spec_sp - 1.U) 92 }.otherwise { 93 spec_ras_top_ctr := spec_ras_top_ctr - 1.U 94 } 95 } 96 io.out.bits.target := spec_ras_top_addr 97 // TODO: back-up stack for ras 98 // use checkpoint to recover RAS 99 100 val commit_is_empty = commit_sp === 0.U 101 val commit_is_full = commit_sp === (RasSize - 1).U 102 val commit_ras_top_entry = commit_ras(commit_sp-1.U) 103 val commit_ras_top_addr = commit_ras_top_entry.retAddr 104 val commit_ras_top_ctr = commit_ras_top_entry.ctr 105 //update commit ras 106 val commit_push = !commit_is_full && io.recover.valid && io.recover.bits.pd.isCall 107 val commit_pop = !commit_is_empty && io.recover.valid && io.recover.bits.pd.isRet 108 val commit_new_addr = Mux(io.recover.bits.pd.isRVC,io.recover.bits.pc + 2.U,io.recover.bits.pc + 4.U) 109 val commit_ras_write = WireInit(0.U.asTypeOf(rasEntry())) 110 val commit_alloc_new = commit_new_addr =/= commit_ras_top_addr 111 when (commit_push) { 112 //push 113 commit_ras_write.ctr := 1.U 114 commit_ras_write.retAddr := commit_new_addr 115 when(commit_alloc_new){ 116 commit_sp := commit_sp + 1.U 117 commit_ras(commit_sp) := commit_ras_write 118 }.otherwise{ 119 commit_ras_top_ctr := commit_ras_top_ctr + 1.U 120 } 121 } 122 123 when (commit_pop) { 124 //pop 125 when (commit_ras_top_ctr === 1.U) { 126 commit_sp := Mux(commit_sp === 0.U, 0.U, commit_sp - 1.U) 127 }.otherwise { 128 commit_ras_top_ctr := commit_ras_top_ctr - 1.U 129 } 130 } 131 132 val copy_valid = io.recover.valid && io.recover.bits.isMisPred 133 val copy_next = RegNext(copy_valid) 134 when(copy_next) 135 { 136 for(i <- 0 until RasSize) 137 { 138 spec_ras(i) := commit_ras(i) 139 spec_sp := commit_sp 140 } 141 } 142 143 if (BPUDebug && debug) { 144 XSDebug("----------------RAS(spec)----------------\n") 145 XSDebug(" index addr ctr \n") 146 for(i <- 0 until RasSize){ 147 XSDebug(" (%d) 0x%x %d",i.U,spec_ras(i).retAddr,spec_ras(i).ctr) 148 when(i.U === spec_sp){XSDebug(false,true.B," <----sp")} 149 XSDebug(false,true.B,"\n") 150 } 151 XSDebug("----------------RAS(commit)----------------\n") 152 XSDebug(" index addr ctr \n") 153 for(i <- 0 until RasSize){ 154 XSDebug(" (%d) 0x%x %d",i.U,commit_ras(i).retAddr,commit_ras(i).ctr) 155 when(i.U === commit_sp){XSDebug(false,true.B," <----sp")} 156 XSDebug(false,true.B,"\n") 157 } 158 159 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) 160 XSDebug(spec_pop, "(spec_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 161 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) 162 XSDebug(commit_pop, "(commit_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 163 XSDebug("copyValid:%d copyNext:%d \n",copy_valid,copy_next) 164 } 165 166 167 // val recoverSp = io.recover.bits.brInfo.rasSp 168 // val recoverCtr = io.recover.bits.brInfo.rasTopCtr 169 // val recoverAddr = io.recover.bits.brInfo.rasToqAddr 170 // val recover_top = ras(recoverSp - 1.U) 171 // when (recover_valid) { 172 // sp := recoverSp 173 // recover_top.ctr := recoverCtr 174 // recover_top.retAddr := recoverAddr 175 // XSDebug("RAS update: SP:%d , Ctr:%d \n",recoverSp,recoverCtr) 176 // } 177 // val recover_and_push = recover_valid && push 178 // val recover_and_pop = recover_valid && pop 179 // val recover_alloc_new = new_addr =/= recoverAddr 180 // when(recover_and_push) 181 // { 182 // when(recover_alloc_new){ 183 // sp := recoverSp + 1.U 184 // ras(recoverSp).retAddr := new_addr 185 // ras(recoverSp).ctr := 1.U 186 // recover_top.retAddr := recoverAddr 187 // recover_top.ctr := recoverCtr 188 // } .otherwise{ 189 // sp := recoverSp 190 // recover_top.ctr := recoverCtr + 1.U 191 // recover_top.retAddr := recoverAddr 192 // } 193 // } .elsewhen(recover_and_pop) 194 // { 195 // io.out.bits.target := recoverAddr 196 // when ( recover_top.ctr === 1.U) { 197 // sp := recoverSp - 1.U 198 // }.otherwise { 199 // sp := recoverSp 200 // recover_top.ctr := recoverCtr - 1.U 201 // } 202 // } 203 204} 205