1*09c6f1ddSLingrui98/*************************************************************************************** 2*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*09c6f1ddSLingrui98* 5*09c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2. 6*09c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*09c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at: 8*09c6f1ddSLingrui98* http://license.coscl.org.cn/MulanPSL2 9*09c6f1ddSLingrui98* 10*09c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*09c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*09c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*09c6f1ddSLingrui98* 14*09c6f1ddSLingrui98* See the Mulan PSL v2 for more details. 15*09c6f1ddSLingrui98***************************************************************************************/ 16*09c6f1ddSLingrui98 17*09c6f1ddSLingrui98package xiangshan.frontend 18*09c6f1ddSLingrui98 19*09c6f1ddSLingrui98import chipsalliance.rocketchip.config.Parameters 20*09c6f1ddSLingrui98import chisel3._ 21*09c6f1ddSLingrui98import chisel3.experimental.chiselName 22*09c6f1ddSLingrui98import chisel3.util._ 23*09c6f1ddSLingrui98import utils._ 24*09c6f1ddSLingrui98import xiangshan._ 25*09c6f1ddSLingrui98 26*09c6f1ddSLingrui98class RASEntry()(implicit p: Parameters) extends XSBundle { 27*09c6f1ddSLingrui98 val retAddr = UInt(VAddrBits.W) 28*09c6f1ddSLingrui98 val ctr = UInt(8.W) // layer of nested call functions 29*09c6f1ddSLingrui98} 30*09c6f1ddSLingrui98 31*09c6f1ddSLingrui98@chiselName 32*09c6f1ddSLingrui98class RAS(implicit p: Parameters) extends BasePredictor { 33*09c6f1ddSLingrui98 object RASEntry { 34*09c6f1ddSLingrui98 def apply(retAddr: UInt, ctr: UInt): RASEntry = { 35*09c6f1ddSLingrui98 val e = Wire(new RASEntry) 36*09c6f1ddSLingrui98 e.retAddr := retAddr 37*09c6f1ddSLingrui98 e.ctr := ctr 38*09c6f1ddSLingrui98 e 39*09c6f1ddSLingrui98 } 40*09c6f1ddSLingrui98 } 41*09c6f1ddSLingrui98 42*09c6f1ddSLingrui98 @chiselName 43*09c6f1ddSLingrui98 class RASStack(val rasSize: Int) extends XSModule { 44*09c6f1ddSLingrui98 val io = IO(new Bundle { 45*09c6f1ddSLingrui98 val push_valid = Input(Bool()) 46*09c6f1ddSLingrui98 val pop_valid = Input(Bool()) 47*09c6f1ddSLingrui98 val spec_new_addr = Input(UInt(VAddrBits.W)) 48*09c6f1ddSLingrui98 49*09c6f1ddSLingrui98 val recover_sp = Input(UInt(log2Up(rasSize).W)) 50*09c6f1ddSLingrui98 val recover_top = Input(new RASEntry) 51*09c6f1ddSLingrui98 val recover_valid = Input(Bool()) 52*09c6f1ddSLingrui98 val recover_push = Input(Bool()) 53*09c6f1ddSLingrui98 val recover_pop = Input(Bool()) 54*09c6f1ddSLingrui98 val recover_new_addr = Input(UInt(VAddrBits.W)) 55*09c6f1ddSLingrui98 56*09c6f1ddSLingrui98 val sp = Output(UInt(log2Up(rasSize).W)) 57*09c6f1ddSLingrui98 val top = Output(new RASEntry) 58*09c6f1ddSLingrui98 }) 59*09c6f1ddSLingrui98 60*09c6f1ddSLingrui98 val debugIO = IO(new Bundle{ 61*09c6f1ddSLingrui98 val push_entry = Output(new RASEntry) 62*09c6f1ddSLingrui98 val alloc_new = Output(Bool()) 63*09c6f1ddSLingrui98 val sp = Output(UInt(log2Up(rasSize).W)) 64*09c6f1ddSLingrui98 val topRegister = Output(new RASEntry) 65*09c6f1ddSLingrui98 val out_mem = Output(Vec(RasSize, new RASEntry)) 66*09c6f1ddSLingrui98 }) 67*09c6f1ddSLingrui98 68*09c6f1ddSLingrui98 val stack = Mem(RasSize, new RASEntry) 69*09c6f1ddSLingrui98 val sp = RegInit(0.U(log2Up(rasSize).W)) 70*09c6f1ddSLingrui98 val top = RegInit(0.U.asTypeOf(new RASEntry)) 71*09c6f1ddSLingrui98 val topPtr = RegInit(0.U(log2Up(rasSize).W)) 72*09c6f1ddSLingrui98 73*09c6f1ddSLingrui98 def ptrInc(ptr: UInt) = Mux(ptr === (rasSize-1).U, 0.U, ptr + 1.U) 74*09c6f1ddSLingrui98 def ptrDec(ptr: UInt) = Mux(ptr === 0.U, (rasSize-1).U, ptr - 1.U) 75*09c6f1ddSLingrui98 76*09c6f1ddSLingrui98 val alloc_new = io.spec_new_addr =/= top.retAddr || top.ctr.andR 77*09c6f1ddSLingrui98 val recover_alloc_new = io.recover_new_addr =/= io.recover_top.retAddr || io.recover_top.ctr.andR 78*09c6f1ddSLingrui98 79*09c6f1ddSLingrui98 // TODO: fix overflow and underflow bugs 80*09c6f1ddSLingrui98 def update(recover: Bool)(do_push: Bool, do_pop: Bool, do_alloc_new: Bool, 81*09c6f1ddSLingrui98 do_sp: UInt, do_top_ptr: UInt, do_new_addr: UInt, 82*09c6f1ddSLingrui98 do_top: RASEntry) = { 83*09c6f1ddSLingrui98 when (do_push) { 84*09c6f1ddSLingrui98 when (do_alloc_new) { 85*09c6f1ddSLingrui98 sp := ptrInc(do_sp) 86*09c6f1ddSLingrui98 topPtr := do_sp 87*09c6f1ddSLingrui98 top.retAddr := do_new_addr 88*09c6f1ddSLingrui98 top.ctr := 1.U 89*09c6f1ddSLingrui98 stack.write(do_sp, RASEntry(do_new_addr, 1.U)) 90*09c6f1ddSLingrui98 }.otherwise { 91*09c6f1ddSLingrui98 when (recover) { 92*09c6f1ddSLingrui98 sp := do_sp 93*09c6f1ddSLingrui98 topPtr := do_top_ptr 94*09c6f1ddSLingrui98 top.retAddr := do_top.retAddr 95*09c6f1ddSLingrui98 } 96*09c6f1ddSLingrui98 top.ctr := do_top.ctr + 1.U 97*09c6f1ddSLingrui98 stack.write(do_top_ptr, RASEntry(do_new_addr, do_top.ctr + 1.U)) 98*09c6f1ddSLingrui98 } 99*09c6f1ddSLingrui98 }.elsewhen (do_pop) { 100*09c6f1ddSLingrui98 when (do_top.ctr === 1.U) { 101*09c6f1ddSLingrui98 sp := ptrDec(do_sp) 102*09c6f1ddSLingrui98 topPtr := ptrDec(do_top_ptr) 103*09c6f1ddSLingrui98 top := stack.read(ptrDec(do_top_ptr)) 104*09c6f1ddSLingrui98 }.otherwise { 105*09c6f1ddSLingrui98 when (recover) { 106*09c6f1ddSLingrui98 sp := do_sp 107*09c6f1ddSLingrui98 topPtr := do_top_ptr 108*09c6f1ddSLingrui98 top.retAddr := do_top.retAddr 109*09c6f1ddSLingrui98 } 110*09c6f1ddSLingrui98 top.ctr := do_top.ctr - 1.U 111*09c6f1ddSLingrui98 stack.write(do_top_ptr, RASEntry(do_top.retAddr, do_top.ctr - 1.U)) 112*09c6f1ddSLingrui98 } 113*09c6f1ddSLingrui98 }.otherwise { 114*09c6f1ddSLingrui98 when (recover) { 115*09c6f1ddSLingrui98 sp := do_sp 116*09c6f1ddSLingrui98 topPtr := do_top_ptr 117*09c6f1ddSLingrui98 top := do_top 118*09c6f1ddSLingrui98 stack.write(do_top_ptr, do_top) 119*09c6f1ddSLingrui98 } 120*09c6f1ddSLingrui98 } 121*09c6f1ddSLingrui98 } 122*09c6f1ddSLingrui98 123*09c6f1ddSLingrui98 update(io.recover_valid)( 124*09c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_push, io.push_valid), 125*09c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_pop, io.pop_valid), 126*09c6f1ddSLingrui98 Mux(io.recover_valid, recover_alloc_new, alloc_new), 127*09c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_sp, sp), 128*09c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_sp - 1.U, topPtr), 129*09c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_new_addr, io.spec_new_addr), 130*09c6f1ddSLingrui98 Mux(io.recover_valid, io.recover_top, top)) 131*09c6f1ddSLingrui98 132*09c6f1ddSLingrui98 io.sp := sp 133*09c6f1ddSLingrui98 io.top := top 134*09c6f1ddSLingrui98 135*09c6f1ddSLingrui98 debugIO.push_entry := RASEntry(io.spec_new_addr, Mux(alloc_new, 1.U, top.ctr + 1.U)) 136*09c6f1ddSLingrui98 debugIO.alloc_new := alloc_new 137*09c6f1ddSLingrui98 debugIO.sp := sp 138*09c6f1ddSLingrui98 debugIO.topRegister := top 139*09c6f1ddSLingrui98 for (i <- 0 until RasSize) { 140*09c6f1ddSLingrui98 debugIO.out_mem(i) := stack.read(i.U) 141*09c6f1ddSLingrui98 } 142*09c6f1ddSLingrui98 } 143*09c6f1ddSLingrui98 144*09c6f1ddSLingrui98 val spec = Module(new RASStack(RasSize)) 145*09c6f1ddSLingrui98 val spec_ras = spec.io 146*09c6f1ddSLingrui98 147*09c6f1ddSLingrui98 148*09c6f1ddSLingrui98 val spec_push = WireInit(false.B) 149*09c6f1ddSLingrui98 val spec_pop = WireInit(false.B) 150*09c6f1ddSLingrui98 // val jump_is_first = io.callIdx.bits === 0.U 151*09c6f1ddSLingrui98 // val call_is_last_half = io.isLastHalfRVI && jump_is_first 152*09c6f1ddSLingrui98 // 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) 153*09c6f1ddSLingrui98 val spec_new_addr = io.in.bits.resp_in(0).s2.fallThroughAddr 154*09c6f1ddSLingrui98 spec_ras.push_valid := spec_push 155*09c6f1ddSLingrui98 spec_ras.pop_valid := spec_pop 156*09c6f1ddSLingrui98 spec_ras.spec_new_addr := spec_new_addr 157*09c6f1ddSLingrui98 val spec_top_addr = spec_ras.top.retAddr 158*09c6f1ddSLingrui98 159*09c6f1ddSLingrui98 // confirm that the call/ret is the taken cfi 160*09c6f1ddSLingrui98 spec_push := io.s2_fire && io.in.bits.resp_in(0).s2.hit_taken_on_call 161*09c6f1ddSLingrui98 spec_pop := io.s2_fire && io.in.bits.resp_in(0).s2.hit_taken_on_ret 162*09c6f1ddSLingrui98 163*09c6f1ddSLingrui98 when (spec_pop) { 164*09c6f1ddSLingrui98 io.out.resp.s2.preds.jmp_target := spec_top_addr 165*09c6f1ddSLingrui98 } 166*09c6f1ddSLingrui98 167*09c6f1ddSLingrui98 io.out.resp.s2.rasSp := spec_ras.sp 168*09c6f1ddSLingrui98 io.out.resp.s2.rasTop := spec_ras.top 169*09c6f1ddSLingrui98 170*09c6f1ddSLingrui98 io.out.resp.s3 := RegEnable(io.out.resp.s2, io.s2_fire) 171*09c6f1ddSLingrui98 172*09c6f1ddSLingrui98 val redirect = RegNext(io.redirect) 173*09c6f1ddSLingrui98 val do_recover = redirect.valid 174*09c6f1ddSLingrui98 val recover_cfi = redirect.bits.cfiUpdate 175*09c6f1ddSLingrui98 176*09c6f1ddSLingrui98 val retMissPred = do_recover && redirect.bits.level === 0.U && recover_cfi.pd.isRet 177*09c6f1ddSLingrui98 val callMissPred = do_recover && redirect.bits.level === 0.U && recover_cfi.pd.isCall 178*09c6f1ddSLingrui98 // when we mispredict a call, we must redo a push operation 179*09c6f1ddSLingrui98 // similarly, when we mispredict a return, we should redo a pop 180*09c6f1ddSLingrui98 spec_ras.recover_valid := do_recover 181*09c6f1ddSLingrui98 spec_ras.recover_push := callMissPred 182*09c6f1ddSLingrui98 spec_ras.recover_pop := retMissPred 183*09c6f1ddSLingrui98 184*09c6f1ddSLingrui98 spec_ras.recover_sp := recover_cfi.rasSp 185*09c6f1ddSLingrui98 spec_ras.recover_top := recover_cfi.rasEntry 186*09c6f1ddSLingrui98 spec_ras.recover_new_addr := recover_cfi.pc + Mux(recover_cfi.pd.isRVC, 2.U, 4.U) 187*09c6f1ddSLingrui98 188*09c6f1ddSLingrui98 // TODO: back-up stack for ras 189*09c6f1ddSLingrui98 // use checkpoint to recover RAS 190*09c6f1ddSLingrui98 191*09c6f1ddSLingrui98 val spec_debug = spec.debugIO 192*09c6f1ddSLingrui98 XSDebug("----------------RAS----------------\n") 193*09c6f1ddSLingrui98 XSDebug(" TopRegister: 0x%x %d \n",spec_debug.topRegister.retAddr,spec_debug.topRegister.ctr) 194*09c6f1ddSLingrui98 XSDebug(" index addr ctr \n") 195*09c6f1ddSLingrui98 for(i <- 0 until RasSize){ 196*09c6f1ddSLingrui98 XSDebug(" (%d) 0x%x %d",i.U,spec_debug.out_mem(i).retAddr,spec_debug.out_mem(i).ctr) 197*09c6f1ddSLingrui98 when(i.U === spec_debug.sp){XSDebug(false,true.B," <----sp")} 198*09c6f1ddSLingrui98 XSDebug(false,true.B,"\n") 199*09c6f1ddSLingrui98 } 200*09c6f1ddSLingrui98 XSDebug(spec_push, "(spec_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n", 201*09c6f1ddSLingrui98 spec_new_addr,spec_debug.push_entry.ctr,spec_debug.alloc_new,spec_debug.sp.asUInt) 202*09c6f1ddSLingrui98 XSDebug(spec_pop, "(spec_ras)pop outAddr: 0x%x \n",io.out.resp.s2.target) 203*09c6f1ddSLingrui98 val redirectUpdate = redirect.bits.cfiUpdate 204*09c6f1ddSLingrui98 XSDebug("recoverValid:%d recover(SP:%d retAddr:%x ctr:%d) \n", 205*09c6f1ddSLingrui98 do_recover,redirectUpdate.rasSp,redirectUpdate.rasEntry.retAddr,redirectUpdate.rasEntry.ctr) 206*09c6f1ddSLingrui98} 207