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