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