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 XDebug(" 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," <----sp")} 57 XSDebug(false,"\n") 58 } 59 // update RAS 60 // speculative update RAS 61 io.out.bits.target := 0.U 62 when (!is_full && io.callIdx.valid && io.pc.valid) { 63 //push 64 //XDebug("d") 65 val new_addr = io.pc.bits + (io.callIdx.bits << 1.U) + 4.U //TODO: consider RVC 66 val rasWrite = WireInit(0.U.asTypeOf(rasEntry())) 67 val allocNewEntry = new_addr =/= ras_top_addr 68 rasWrite.ctr := 1.U 69 rasWrite.retAddr := new_addr 70 when(allocNewEntry){ 71 sp := sp + 1.U 72 ras(sp) := rasWrite 73 }.otherwise{ 74 ras_top_ctr := ras_top_ctr + 1.U 75 } 76 XSDebug("push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n",rasWrite.retAddr,rasWrite.ctr,allocNewEntry,sp.asUInt) 77 }.elsewhen (!is_empty && io.is_ret) { 78 //pop 79 io.out.bits.target := ras_top_addr 80 when (ras_top_ctr === 1.U) { 81 sp := Mux(sp === 0.U, 0.U, sp - 1.U) 82 }.otherwise { 83 ras_top_ctr := ras_top_ctr - 1.U 84 } 85 XSDebug("pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target) 86 } 87 // TODO: back-up stack for ras 88 // use checkpoint to recover RAS 89 val recoverSp = io.recover.bits.brInfo.rasSp 90 val recoverCtr = io.recover.bits.brInfo.rasTopCtr 91 when (io.redirect.valid && io.redirect.bits.isMisPred) { 92 sp := recoverSp 93 ras(recoverSp).ctr := recoverCtr 94 } 95 96}