xref: /XiangShan/src/main/scala/xiangshan/frontend/RAS.scala (revision 1b864daa5bd11b38c9ec9b375e70e548d8087294)
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 = RegInit(0.U)asTypeOf(Vec(RasSize,rasEntry))
40    val sp = RegInit(0.U(log2Up(RasSize).W))
41    val ras_top_entry = ras(sp)
42    val ras_top_addr = ras_top_entry.retAddr
43
44    val is_empty = sp === 0.U
45    val is_full = sp === (RasSize - 1).U
46    // save ras checkpoint info
47    io.branchInfo.rasSp := sp
48    io.branchInfo.rasTopCtr := ras_top_entry.ctr
49
50    io.out.valid := !is_empty && io.is_ret
51
52    // update RAS
53    // speculative update RAS
54    io.out.bits.target := 0.U
55    when (!is_full && io.callIdx.valid) {
56        //push
57        //XDebug("d")
58        val new_addr:= io.pc.bits + (io.callIdx.bits << 2.U) + 4.U
59        val rasWrite = WireInit(0.U.asTypeOf(rasEntry()))
60        val allocNewEntry = new_addr =/= ras_top_addr
61        rasWrite.ctr := Mux(allocNewEntry, 1.U, ras_top_entry.ctr + 1.U)
62        rasWrite.retAddr := Mux(allocNewEntry, new_addr, ras_top_addr)
63        ras(sp) := rasWrite
64        when(allocNewEntry){sp := sp + 1.U }
65    }.elsewhen (!is_empty && io.is_ret) {
66        //pop
67        io.out.bits.target := ras_top_addr
68        when (ras_top_entry.ctr === 1.U) {
69            sp := Mux(sp === 0.U, 0.U, sp - 1.U)
70        }.otherwise {
71            ras_top_entry.ctr := ras_top_entry.ctr - 1.U
72        }
73    }
74    // TODO: back-up stack for ras
75    // use checkpoint to recover RAS
76    val recoverSp = io.recover.bits.brInfo.rasSp
77    val recoverCtr = io.recover.bits.brInfo.rasTopCtr
78    when (io.redirect.valid && io.redirect.bits.isMisPred) {
79        sp := recoverSp
80        ras(recoverSp).ctr := recoverCtr
81    }
82
83}