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 } 21 22 class RASIO extends DefaultBasePredictorIO 23 { 24 val is_ret = Input(Bool()) 25 val callIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W))) 26 val isRVC = Input(Bool()) 27 val redirect = Flipped(ValidIO(new Redirect)) 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 = Reg(Vec(RasSize, rasEntry())) //RegInit(0.U)asTypeOf(Vec(RasSize,rasEntry)) cause comb loop 40 val sp = RegInit(0.U(log2Up(RasSize).W)) 41 42 val is_empty = sp === 0.U 43 val is_full = sp === (RasSize - 1).U 44 45 val ras_top_entry = ras(sp-1.U) 46 val ras_top_addr = ras_top_entry.retAddr 47 val ras_top_ctr = ras_top_entry.ctr 48 // save ras checkpoint info 49 io.branchInfo.rasSp := sp 50 io.branchInfo.rasTopCtr := ras(sp).ctr 51 52 io.out.valid := !is_empty && io.is_ret 53 XSDebug(" index addr ctr \n") 54 for(i <- 0 until RasSize){ 55 XSDebug(" (%d) 0x%x %d",i.U,ras(i).retAddr,ras(i).ctr) 56 when(i.U === sp){XSDebug(false,true.B," <----sp")} 57 XSDebug(false,true.B,"\n") 58 } 59 // update RAS 60 // speculative update RAS 61 val push_only = !is_full && io.callIdx.valid && !io.is_ret && io.pc.valid 62 val pop_only = !is_empty && io.is_ret && !io.callIdx.valid && io.pc.valid 63 io.out.bits.target := 0.U 64 when (push_only) { 65 //push 66 //XSDebug("d") 67 val new_addr = io.pc.bits + (io.callIdx.bits << 1.U) + Mux(io.isRVC,2.U,4.U) 68 val rasWrite = WireInit(0.U.asTypeOf(rasEntry())) 69 val allocNewEntry = new_addr =/= ras_top_addr 70 rasWrite.ctr := 1.U 71 rasWrite.retAddr := new_addr 72 when(allocNewEntry){ 73 sp := sp + 1.U 74 ras(sp) := rasWrite 75 }.otherwise{ 76 ras_top_ctr := ras_top_ctr + 1.U 77 } 78 XSDebug("push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n",rasWrite.retAddr,rasWrite.ctr,allocNewEntry,sp.asUInt) 79 } 80 81 when (pop_only) { 82 //pop 83 io.out.bits.target := ras_top_addr 84 when (ras_top_ctr === 1.U) { 85 sp := Mux(sp === 0.U, 0.U, sp - 1.U) 86 }.otherwise { 87 ras_top_ctr := ras_top_ctr - 1.U 88 } 89 XSDebug("pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 90 }.elsewhen 91 // TODO: back-up stack for ras 92 // use checkpoint to recover RAS 93 val recoverSp = io.recover.bits.brInfo.rasSp 94 val recoverCtr = io.recover.bits.brInfo.rasTopCtr 95 when (io.redirect.valid && io.redirect.bits.isMisPred) { 96 sp := recoverSp 97 ras(recoverSp).ctr := recoverCtr 98 XSDebug("RAS update: SP:%d , Ctr:%d \n",recoverSp,recoverCtr) 99 } 100 101}