109c6f1ddSLingrui98/*************************************************************************************** 209c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 309c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory 409c6f1ddSLingrui98* 509c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2. 609c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2. 709c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at: 809c6f1ddSLingrui98* http://license.coscl.org.cn/MulanPSL2 909c6f1ddSLingrui98* 1009c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 1109c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 1209c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 1309c6f1ddSLingrui98* 1409c6f1ddSLingrui98* See the Mulan PSL v2 for more details. 1509c6f1ddSLingrui98***************************************************************************************/ 1609c6f1ddSLingrui98 1709c6f1ddSLingrui98package xiangshan.frontend 1809c6f1ddSLingrui98 1909c6f1ddSLingrui98import chipsalliance.rocketchip.config.Parameters 2009c6f1ddSLingrui98import chisel3._ 2109c6f1ddSLingrui98import chisel3.experimental.chiselName 2209c6f1ddSLingrui98import chisel3.util._ 2309c6f1ddSLingrui98import utils._ 2409c6f1ddSLingrui98import xiangshan._ 2509c6f1ddSLingrui98 2609c6f1ddSLingrui98class RASEntry()(implicit p: Parameters) extends XSBundle { 2709c6f1ddSLingrui98 val retAddr = UInt(VAddrBits.W) 2809c6f1ddSLingrui98 val ctr = UInt(8.W) // layer of nested call functions 2909c6f1ddSLingrui98} 3009c6f1ddSLingrui98 3109c6f1ddSLingrui98@chiselName 3209c6f1ddSLingrui98class RAS(implicit p: Parameters) extends BasePredictor { 3309c6f1ddSLingrui98 object RASEntry { 3409c6f1ddSLingrui98 def apply(retAddr: UInt, ctr: UInt): RASEntry = { 3509c6f1ddSLingrui98 val e = Wire(new RASEntry) 3609c6f1ddSLingrui98 e.retAddr := retAddr 3709c6f1ddSLingrui98 e.ctr := ctr 3809c6f1ddSLingrui98 e 3909c6f1ddSLingrui98 } 4009c6f1ddSLingrui98 } 4109c6f1ddSLingrui98 4209c6f1ddSLingrui98 @chiselName 4309c6f1ddSLingrui98 class RASStack(val rasSize: Int) extends XSModule { 4409c6f1ddSLingrui98 val io = IO(new Bundle { 4509c6f1ddSLingrui98 val push_valid = Input(Bool()) 4609c6f1ddSLingrui98 val pop_valid = Input(Bool()) 4709c6f1ddSLingrui98 val spec_new_addr = Input(UInt(VAddrBits.W)) 4809c6f1ddSLingrui98 4909c6f1ddSLingrui98 val recover_sp = Input(UInt(log2Up(rasSize).W)) 5009c6f1ddSLingrui98 val recover_top = Input(new RASEntry) 5109c6f1ddSLingrui98 val recover_valid = Input(Bool()) 5209c6f1ddSLingrui98 val recover_push = Input(Bool()) 5309c6f1ddSLingrui98 val recover_pop = Input(Bool()) 5409c6f1ddSLingrui98 val recover_new_addr = Input(UInt(VAddrBits.W)) 5509c6f1ddSLingrui98 5609c6f1ddSLingrui98 val sp = Output(UInt(log2Up(rasSize).W)) 5709c6f1ddSLingrui98 val top = Output(new RASEntry) 5809c6f1ddSLingrui98 }) 5909c6f1ddSLingrui98 6009c6f1ddSLingrui98 val debugIO = IO(new Bundle{ 6109c6f1ddSLingrui98 val push_entry = Output(new RASEntry) 6209c6f1ddSLingrui98 val alloc_new = Output(Bool()) 6309c6f1ddSLingrui98 val sp = Output(UInt(log2Up(rasSize).W)) 6409c6f1ddSLingrui98 val topRegister = Output(new RASEntry) 6509c6f1ddSLingrui98 val out_mem = Output(Vec(RasSize, new RASEntry)) 6609c6f1ddSLingrui98 }) 6709c6f1ddSLingrui98 6809c6f1ddSLingrui98 val stack = Mem(RasSize, new RASEntry) 6909c6f1ddSLingrui98 val sp = RegInit(0.U(log2Up(rasSize).W)) 7009c6f1ddSLingrui98 val top = RegInit(0.U.asTypeOf(new RASEntry)) 7109c6f1ddSLingrui98 val topPtr = RegInit(0.U(log2Up(rasSize).W)) 7209c6f1ddSLingrui98 7309c6f1ddSLingrui98 def ptrInc(ptr: UInt) = Mux(ptr === (rasSize-1).U, 0.U, ptr + 1.U) 7409c6f1ddSLingrui98 def ptrDec(ptr: UInt) = Mux(ptr === 0.U, (rasSize-1).U, ptr - 1.U) 7509c6f1ddSLingrui98 7609c6f1ddSLingrui98 val alloc_new = io.spec_new_addr =/= top.retAddr || top.ctr.andR 7709c6f1ddSLingrui98 val recover_alloc_new = io.recover_new_addr =/= io.recover_top.retAddr || io.recover_top.ctr.andR 7809c6f1ddSLingrui98 7909c6f1ddSLingrui98 // TODO: fix overflow and underflow bugs 8009c6f1ddSLingrui98 def update(recover: Bool)(do_push: Bool, do_pop: Bool, do_alloc_new: Bool, 8109c6f1ddSLingrui98 do_sp: UInt, do_top_ptr: UInt, do_new_addr: UInt, 8209c6f1ddSLingrui98 do_top: RASEntry) = { 8309c6f1ddSLingrui98 when (do_push) { 8409c6f1ddSLingrui98 when (do_alloc_new) { 8509c6f1ddSLingrui98 sp := ptrInc(do_sp) 8609c6f1ddSLingrui98 topPtr := do_sp 8709c6f1ddSLingrui98 top.retAddr := do_new_addr 8809c6f1ddSLingrui98 top.ctr := 1.U 8909c6f1ddSLingrui98 stack.write(do_sp, RASEntry(do_new_addr, 1.U)) 9009c6f1ddSLingrui98 }.otherwise { 9109c6f1ddSLingrui98 when (recover) { 9209c6f1ddSLingrui98 sp := do_sp 9309c6f1ddSLingrui98 topPtr := do_top_ptr 9409c6f1ddSLingrui98 top.retAddr := do_top.retAddr 9509c6f1ddSLingrui98 } 9609c6f1ddSLingrui98 top.ctr := do_top.ctr + 1.U 9709c6f1ddSLingrui98 stack.write(do_top_ptr, RASEntry(do_new_addr, do_top.ctr + 1.U)) 9809c6f1ddSLingrui98 } 9909c6f1ddSLingrui98 }.elsewhen (do_pop) { 10009c6f1ddSLingrui98 when (do_top.ctr === 1.U) { 10109c6f1ddSLingrui98 sp := ptrDec(do_sp) 10209c6f1ddSLingrui98 topPtr := ptrDec(do_top_ptr) 10309c6f1ddSLingrui98 top := stack.read(ptrDec(do_top_ptr)) 10409c6f1ddSLingrui98 }.otherwise { 10509c6f1ddSLingrui98 when (recover) { 10609c6f1ddSLingrui98 sp := do_sp 10709c6f1ddSLingrui98 topPtr := do_top_ptr 10809c6f1ddSLingrui98 top.retAddr := do_top.retAddr 10909c6f1ddSLingrui98 } 11009c6f1ddSLingrui98 top.ctr := do_top.ctr - 1.U 11109c6f1ddSLingrui98 stack.write(do_top_ptr, RASEntry(do_top.retAddr, do_top.ctr - 1.U)) 11209c6f1ddSLingrui98 } 11309c6f1ddSLingrui98 }.otherwise { 11409c6f1ddSLingrui98 when (recover) { 11509c6f1ddSLingrui98 sp := do_sp 11609c6f1ddSLingrui98 topPtr := do_top_ptr 11709c6f1ddSLingrui98 top := do_top 11809c6f1ddSLingrui98 stack.write(do_top_ptr, do_top) 11909c6f1ddSLingrui98 } 12009c6f1ddSLingrui98 } 12109c6f1ddSLingrui98 } 12209c6f1ddSLingrui98 123d717fd1eSLingrui98 12409c6f1ddSLingrui98 update(io.recover_valid)( 12509c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_push, io.push_valid), 12609c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_pop, io.pop_valid), 12709c6f1ddSLingrui98 Mux(io.recover_valid, recover_alloc_new, alloc_new), 12809c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_sp, sp), 12909c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_sp - 1.U, topPtr), 13009c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_new_addr, io.spec_new_addr), 13109c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_top, top)) 13209c6f1ddSLingrui98 13309c6f1ddSLingrui98 io.sp := sp 13409c6f1ddSLingrui98 io.top := top 13509c6f1ddSLingrui98 136d717fd1eSLingrui98 val resetIdx = RegInit(0.U(log2Ceil(RasSize).W)) 137d717fd1eSLingrui98 val do_reset = RegInit(true.B) 138d717fd1eSLingrui98 when (do_reset) { 139d717fd1eSLingrui98 stack.write(resetIdx, RASEntry(0x80000000L.U, 0.U)) 140d717fd1eSLingrui98 } 141d717fd1eSLingrui98 resetIdx := resetIdx + do_reset 142d717fd1eSLingrui98 when (resetIdx === (RasSize-1).U) { 143d717fd1eSLingrui98 do_reset := false.B 144d717fd1eSLingrui98 } 145d717fd1eSLingrui98 14609c6f1ddSLingrui98 debugIO.push_entry := RASEntry(io.spec_new_addr, Mux(alloc_new, 1.U, top.ctr + 1.U)) 14709c6f1ddSLingrui98 debugIO.alloc_new := alloc_new 14809c6f1ddSLingrui98 debugIO.sp := sp 14909c6f1ddSLingrui98 debugIO.topRegister := top 15009c6f1ddSLingrui98 for (i <- 0 until RasSize) { 15109c6f1ddSLingrui98 debugIO.out_mem(i) := stack.read(i.U) 15209c6f1ddSLingrui98 } 15309c6f1ddSLingrui98 } 15409c6f1ddSLingrui98 15509c6f1ddSLingrui98 val spec = Module(new RASStack(RasSize)) 15609c6f1ddSLingrui98 val spec_ras = spec.io 157*cb4f77ceSLingrui98 val spec_top_addr = spec_ras.top.retAddr 15809c6f1ddSLingrui98 15909c6f1ddSLingrui98 160*cb4f77ceSLingrui98 val s2_spec_push = WireInit(false.B) 161*cb4f77ceSLingrui98 val s2_spec_pop = WireInit(false.B) 16209c6f1ddSLingrui98 // val jump_is_first = io.callIdx.bits === 0.U 16309c6f1ddSLingrui98 // val call_is_last_half = io.isLastHalfRVI && jump_is_first 16409c6f1ddSLingrui98 // val spec_new_addr = packetAligned(io.pc.bits) + (io.callIdx.bits << instOffsetBits.U) + Mux( (io.isRVC | call_is_last_half) && HasCExtension.B, 2.U, 4.U) 165*cb4f77ceSLingrui98 val s2_spec_new_addr = io.in.bits.resp_in(0).s2.full_pred.fallThroughAddr 166*cb4f77ceSLingrui98 spec_ras.push_valid := s2_spec_push 167*cb4f77ceSLingrui98 spec_ras.pop_valid := s2_spec_pop 168*cb4f77ceSLingrui98 spec_ras.spec_new_addr := s2_spec_new_addr 16909c6f1ddSLingrui98 17009c6f1ddSLingrui98 // confirm that the call/ret is the taken cfi 171*cb4f77ceSLingrui98 s2_spec_push := io.s2_fire && io.in.bits.resp_in(0).s2.full_pred.hit_taken_on_call 172*cb4f77ceSLingrui98 s2_spec_pop := io.s2_fire && io.in.bits.resp_in(0).s2.full_pred.hit_taken_on_ret 17309c6f1ddSLingrui98 174*cb4f77ceSLingrui98 val s2_jalr_target = io.out.resp.s2.full_pred.jalr_target 175*cb4f77ceSLingrui98 val s2_last_target_in = io.in.bits.resp_in(0).s2.full_pred.targets.last 176*cb4f77ceSLingrui98 val s2_last_target_out = io.out.resp.s2.full_pred.targets.last 177*cb4f77ceSLingrui98 val s2_is_jalr = io.in.bits.resp_in(0).s2.full_pred.is_jalr 178*cb4f77ceSLingrui98 val s2_is_ret = io.in.bits.resp_in(0).s2.full_pred.is_ret 179b30c10d6SLingrui98 // assert(is_jalr && is_ret || !is_ret) 180*cb4f77ceSLingrui98 when(s2_is_ret) { 181*cb4f77ceSLingrui98 s2_jalr_target := spec_top_addr 182b30c10d6SLingrui98 // FIXME: should use s1 globally 18309c6f1ddSLingrui98 } 184*cb4f77ceSLingrui98 s2_last_target_out := Mux(s2_is_jalr, s2_jalr_target, s2_last_target_in) 18509c6f1ddSLingrui98 186*cb4f77ceSLingrui98 val s3_top = RegEnable(spec_ras.top, io.s2_fire) 187*cb4f77ceSLingrui98 val s3_sp = RegEnable(spec_ras.sp, io.s2_fire) 188*cb4f77ceSLingrui98 val s3_spec_new_addr = RegEnable(s2_spec_new_addr, io.s2_fire) 189*cb4f77ceSLingrui98 190*cb4f77ceSLingrui98 val s3_jalr_target = io.out.resp.s3.full_pred.jalr_target 191*cb4f77ceSLingrui98 val s3_last_target_in = io.in.bits.resp_in(0).s3.full_pred.targets.last 192*cb4f77ceSLingrui98 val s3_last_target_out = io.out.resp.s3.full_pred.targets.last 193*cb4f77ceSLingrui98 val s3_is_jalr = io.in.bits.resp_in(0).s3.full_pred.is_jalr 194*cb4f77ceSLingrui98 val s3_is_ret = io.in.bits.resp_in(0).s3.full_pred.is_ret 195*cb4f77ceSLingrui98 // assert(is_jalr && is_ret || !is_ret) 196*cb4f77ceSLingrui98 when(s3_is_ret) { 197*cb4f77ceSLingrui98 s3_jalr_target := s3_top.retAddr 198*cb4f77ceSLingrui98 // FIXME: should use s1 globally 199*cb4f77ceSLingrui98 } 200*cb4f77ceSLingrui98 s3_last_target_out := Mux(s3_is_jalr, s3_jalr_target, s3_last_target_in) 201*cb4f77ceSLingrui98 202*cb4f77ceSLingrui98 val s3_pushed_in_s2 = RegEnable(s2_spec_push, io.s2_fire) 203*cb4f77ceSLingrui98 val s3_popped_in_s2 = RegEnable(s2_spec_pop, io.s2_fire) 204*cb4f77ceSLingrui98 val s3_spec_push = io.s3_fire && io.in.bits.resp_in(0).s3.full_pred.hit_taken_on_call 205*cb4f77ceSLingrui98 val s3_spec_pop = io.s3_fire && io.in.bits.resp_in(0).s3.full_pred.hit_taken_on_ret 206*cb4f77ceSLingrui98 207*cb4f77ceSLingrui98 val s3_recover = s3_pushed_in_s2 =/= s3_spec_push || s3_popped_in_s2 =/= s3_spec_pop 208*cb4f77ceSLingrui98 io.out.resp.s3.rasSp := spec_ras.sp 209*cb4f77ceSLingrui98 io.out.resp.s3.rasTop := spec_ras.top 21009c6f1ddSLingrui98 21109c6f1ddSLingrui98 21209c6f1ddSLingrui98 val redirect = RegNext(io.redirect) 213*cb4f77ceSLingrui98 val do_recover = redirect.valid || s3_recover 21409c6f1ddSLingrui98 val recover_cfi = redirect.bits.cfiUpdate 21509c6f1ddSLingrui98 21609c6f1ddSLingrui98 val retMissPred = do_recover && redirect.bits.level === 0.U && recover_cfi.pd.isRet 21709c6f1ddSLingrui98 val callMissPred = do_recover && redirect.bits.level === 0.U && recover_cfi.pd.isCall 21809c6f1ddSLingrui98 // when we mispredict a call, we must redo a push operation 21909c6f1ddSLingrui98 // similarly, when we mispredict a return, we should redo a pop 22009c6f1ddSLingrui98 spec_ras.recover_valid := do_recover 221*cb4f77ceSLingrui98 spec_ras.recover_push := Mux(redirect.valid, callMissPred, s3_spec_push) 222*cb4f77ceSLingrui98 spec_ras.recover_pop := Mux(redirect.valid, retMissPred, s3_spec_pop) 22309c6f1ddSLingrui98 224*cb4f77ceSLingrui98 spec_ras.recover_sp := Mux(redirect.valid, recover_cfi.rasSp, s3_sp) 225*cb4f77ceSLingrui98 spec_ras.recover_top := Mux(redirect.valid, recover_cfi.rasEntry, s3_top) 226*cb4f77ceSLingrui98 spec_ras.recover_new_addr := Mux(redirect.valid, recover_cfi.pc + Mux(recover_cfi.pd.isRVC, 2.U, 4.U), s3_spec_new_addr) 22709c6f1ddSLingrui98 228*cb4f77ceSLingrui98 229*cb4f77ceSLingrui98 XSPerfAccumulate("ras_s3_recover", s3_recover) 230*cb4f77ceSLingrui98 XSPerfAccumulate("ras_redirect_recover", redirect.valid) 231*cb4f77ceSLingrui98 XSPerfAccumulate("ras_s3_and_redirect_recover_at_the_same_time", s3_recover && redirect.valid) 23209c6f1ddSLingrui98 // TODO: back-up stack for ras 23309c6f1ddSLingrui98 // use checkpoint to recover RAS 23409c6f1ddSLingrui98 23509c6f1ddSLingrui98 val spec_debug = spec.debugIO 23609c6f1ddSLingrui98 XSDebug("----------------RAS----------------\n") 23709c6f1ddSLingrui98 XSDebug(" TopRegister: 0x%x %d \n",spec_debug.topRegister.retAddr,spec_debug.topRegister.ctr) 23809c6f1ddSLingrui98 XSDebug(" index addr ctr \n") 23909c6f1ddSLingrui98 for(i <- 0 until RasSize){ 24009c6f1ddSLingrui98 XSDebug(" (%d) 0x%x %d",i.U,spec_debug.out_mem(i).retAddr,spec_debug.out_mem(i).ctr) 24109c6f1ddSLingrui98 when(i.U === spec_debug.sp){XSDebug(false,true.B," <----sp")} 24209c6f1ddSLingrui98 XSDebug(false,true.B,"\n") 24309c6f1ddSLingrui98 } 244*cb4f77ceSLingrui98 XSDebug(s2_spec_push, "(spec_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n", 245*cb4f77ceSLingrui98 s2_spec_new_addr,spec_debug.push_entry.ctr,spec_debug.alloc_new,spec_debug.sp.asUInt) 246*cb4f77ceSLingrui98 XSDebug(s2_spec_pop, "(spec_ras)pop outAddr: 0x%x \n",io.out.resp.s2.getTarget) 24709c6f1ddSLingrui98 val redirectUpdate = redirect.bits.cfiUpdate 24809c6f1ddSLingrui98 XSDebug("recoverValid:%d recover(SP:%d retAddr:%x ctr:%d) \n", 24909c6f1ddSLingrui98 do_recover,redirectUpdate.rasSp,redirectUpdate.rasEntry.retAddr,redirectUpdate.rasEntry.ctr) 25009c6f1ddSLingrui98} 251