1package xiangshan.frontend 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.backend.ALUOpType 7import utils._ 8 9class RAS extends BasePredictor 10 with RASParameter 11{ 12 class RASResp extends Resp 13 { 14 val target =UInt(VAddrBits.W) 15 } 16 17 class RASBranchInfo extends Meta 18 { 19 val rasSp = UInt(log2Up(RasSize).W) 20 val rasTopCtr = UInt(8.W) 21 } 22 23 class RASIO extends DefaultBasePredictorIO 24 { 25 val retIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W))) 26 val callIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W))) 27 val isRVC = Input(Bool()) 28 val redirect = Flipped(ValidIO(new Redirect))) 29 val out = ValidIO(new RASResp) 30 val branchInfo = ValidIO(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 val ras = RegInit(VecInit(RasSize, 0.U.asTypeOf(rasEntry()))) 38 val sp = RegInit(0.U(log2Up(RasSize).W)) 39 val ras_top_entry = ras(sp) 40 val ras_top_addr = ras_top_entry.retAddr 41 42 val is_empty = sp === 0.U 43 val is_full = sp === (RasSize - 1).U 44 // save ras checkpoint info 45 io.out.bits.rasSp := sp 46 io.out.bits.rasTopCtr := rasTop.ctr 47 48 // update RAS 49 // speculative update RAS 50 51 when (!is_full && io.callIdx.valid) { 52 //push 53 when (ras_top_entry.ctr === 1.U) { 54 sp := Mux(sp.value === 0.U, 0.U, sp - 1.U) 55 }.otherwise { 56 ras_top_entry.ctr := ras_top_entry.ctr - 1.U 57 } 58 }.elsewhen ((!is_empty && io.retIdx.valid) { 59 //pop 60 io.out.bits.target := ras_top_addr 61 val rasWrite = WireInit(0.U.asTypeOf(rasEntry())) 62 val allocNewEntry = rasWrite.retAddr =/= rasTopAddr 63 rasWrite.ctr := Mux(allocNewEntry, 1.U, rasTop.ctr + 1.U) 64 rasWrite.retAddr := io.pc.bits + (io.callIdx.bits << 2.U) + 4.U 65 ras(sp) := in.target 66 when(allocNewEntry){sp := sp + 1.U } 67 } 68 // TODO: back-up stack for ras 69 // use checkpoint to recover RAS 70 val recoverSp = io.redirect.rasSp 71 val recoverCtr = io.redirect.rasTopCtr 72 when (io.redirect.valid && io.redirect.isMisPred) { 73 sp := recoverSp 74 ras(recoverSp) := Cat(recoverCtr, ras(recoverSp).retAddr).asTypeOf(rasEntry()) 75 } 76 77}