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