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 val specEmpty = Bool() 15 } 16 17 class RASBranchInfo extends Meta 18 { 19 val rasSp = UInt(log2Up(RasSize).W) 20 val rasTopCtr = UInt(8.W) 21 val rasToqAddr = UInt(VAddrBits.W) 22 } 23 24 class RASIO extends DefaultBasePredictorIO 25 { 26 val is_ret = Input(Bool()) 27 val callIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W))) 28 val isRVC = 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 io.out.bits.specEmpty := spec_is_empty 69 70 // update spec RAS 71 // speculative update RAS 72 val spec_push = !spec_is_full && io.callIdx.valid && io.pc.valid 73 val spec_pop = !spec_is_empty && io.is_ret && io.pc.valid 74 val spec_new_addr = io.pc.bits + (io.callIdx.bits << 1.U) + Mux(io.isRVC,2.U,4.U) 75 val spec_ras_write = WireInit(0.U.asTypeOf(rasEntry())) 76 val sepc_alloc_new = spec_new_addr =/= spec_ras_top_addr 77 when (spec_push) { 78 //push 79 spec_ras_write.ctr := 1.U 80 spec_ras_write.retAddr := spec_new_addr 81 when(sepc_alloc_new){ 82 spec_sp := spec_sp + 1.U 83 spec_ras(spec_sp) := spec_ras_write 84 }.otherwise{ 85 spec_ras_top_ctr := spec_ras_top_ctr + 1.U 86 } 87 } 88 89 when (spec_pop) { 90 //pop 91 when (spec_ras_top_ctr === 1.U) { 92 spec_sp := Mux(spec_sp === 0.U, 0.U, spec_sp - 1.U) 93 }.otherwise { 94 spec_ras_top_ctr := spec_ras_top_ctr - 1.U 95 } 96 } 97 io.out.bits.target := spec_ras_top_addr 98 // TODO: back-up stack for ras 99 // use checkpoint to recover RAS 100 101 val commit_is_empty = commit_sp === 0.U 102 val commit_is_full = commit_sp === (RasSize - 1).U 103 val commit_ras_top_entry = commit_ras(commit_sp-1.U) 104 val commit_ras_top_addr = commit_ras_top_entry.retAddr 105 val commit_ras_top_ctr = commit_ras_top_entry.ctr 106 //update commit ras 107 val commit_push = !commit_is_full && io.recover.valid && io.recover.bits.pd.isCall 108 val commit_pop = !commit_is_empty && io.recover.valid && io.recover.bits.pd.isRet 109 val commit_new_addr = Mux(io.recover.bits.pd.isRVC,io.recover.bits.pc + 2.U,io.recover.bits.pc + 4.U) 110 val commit_ras_write = WireInit(0.U.asTypeOf(rasEntry())) 111 val commit_alloc_new = commit_new_addr =/= commit_ras_top_addr 112 when (commit_push) { 113 //push 114 commit_ras_write.ctr := 1.U 115 commit_ras_write.retAddr := commit_new_addr 116 when(commit_alloc_new){ 117 commit_sp := commit_sp + 1.U 118 commit_ras(commit_sp) := commit_ras_write 119 }.otherwise{ 120 commit_ras_top_ctr := commit_ras_top_ctr + 1.U 121 } 122 } 123 124 when (commit_pop) { 125 //pop 126 when (commit_ras_top_ctr === 1.U) { 127 commit_sp := Mux(commit_sp === 0.U, 0.U, commit_sp - 1.U) 128 }.otherwise { 129 commit_ras_top_ctr := commit_ras_top_ctr - 1.U 130 } 131 } 132 133 val copy_valid = io.recover.valid && io.recover.bits.isMisPred 134 val copy_next = RegNext(copy_valid) 135 when(copy_next) 136 { 137 for(i <- 0 until RasSize) 138 { 139 spec_ras(i) := commit_ras(i) 140 spec_sp := commit_sp 141 } 142 } 143 144 if (BPUDebug && debug) { 145 XSDebug("----------------RAS(spec)----------------\n") 146 XSDebug(" index addr ctr \n") 147 for(i <- 0 until RasSize){ 148 XSDebug(" (%d) 0x%x %d",i.U,spec_ras(i).retAddr,spec_ras(i).ctr) 149 when(i.U === spec_sp){XSDebug(false,true.B," <----sp")} 150 XSDebug(false,true.B,"\n") 151 } 152 XSDebug("----------------RAS(commit)----------------\n") 153 XSDebug(" index addr ctr \n") 154 for(i <- 0 until RasSize){ 155 XSDebug(" (%d) 0x%x %d",i.U,commit_ras(i).retAddr,commit_ras(i).ctr) 156 when(i.U === commit_sp){XSDebug(false,true.B," <----sp")} 157 XSDebug(false,true.B,"\n") 158 } 159 160 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) 161 XSDebug(spec_pop, "(spec_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 162 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) 163 XSDebug(commit_pop, "(commit_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 164 XSDebug("copyValid:%d copyNext:%d \n",copy_valid,copy_next) 165 } 166 167 168 // val recoverSp = io.recover.bits.brInfo.rasSp 169 // val recoverCtr = io.recover.bits.brInfo.rasTopCtr 170 // val recoverAddr = io.recover.bits.brInfo.rasToqAddr 171 // val recover_top = ras(recoverSp - 1.U) 172 // when (recover_valid) { 173 // sp := recoverSp 174 // recover_top.ctr := recoverCtr 175 // recover_top.retAddr := recoverAddr 176 // XSDebug("RAS update: SP:%d , Ctr:%d \n",recoverSp,recoverCtr) 177 // } 178 // val recover_and_push = recover_valid && push 179 // val recover_and_pop = recover_valid && pop 180 // val recover_alloc_new = new_addr =/= recoverAddr 181 // when(recover_and_push) 182 // { 183 // when(recover_alloc_new){ 184 // sp := recoverSp + 1.U 185 // ras(recoverSp).retAddr := new_addr 186 // ras(recoverSp).ctr := 1.U 187 // recover_top.retAddr := recoverAddr 188 // recover_top.ctr := recoverCtr 189 // } .otherwise{ 190 // sp := recoverSp 191 // recover_top.ctr := recoverCtr + 1.U 192 // recover_top.retAddr := recoverAddr 193 // } 194 // } .elsewhen(recover_and_pop) 195 // { 196 // io.out.bits.target := recoverAddr 197 // when ( recover_top.ctr === 1.U) { 198 // sp := recoverSp - 1.U 199 // }.otherwise { 200 // sp := recoverSp 201 // recover_top.ctr := recoverCtr - 1.U 202 // } 203 // } 204 205} 206