xref: /XiangShan/src/main/scala/xiangshan/frontend/RAS.scala (revision 238ed4e2ade7dfd3a929deb0d7906328e5c64def)
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 =ValiIO(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 is_ret = Input(Bool())
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    when (!is_full && io.callIdx.valid) {
51        //push
52        io.out.bits.target := ras_top_addr
53        val rasWrite = WireInit(0.U.asTypeOf(rasEntry()))
54        val allocNewEntry = rasWrite.retAddr =/= rasTopAddr
55        rasWrite.ctr := Mux(allocNewEntry, 1.U, rasTop.ctr + 1.U)
56        rasWrite.retAddr := io.pc.bits + (io.callIdx.bits << 2.U) + 4.U
57        ras(sp) := in.target
58        when(allocNewEntry){sp := sp + 1.U }
59    }.elsewhen ((!is_empty && io.retIdx.valid) {
60        //pop
61        when (ras_top_entry.ctr === 1.U) {
62            sp := Mux(sp.value === 0.U, 0.U, sp - 1.U)
63        }.otherwise {
64            ras_top_entry.ctr := ras_top_entry.ctr - 1.U
65        }
66    }
67    // TODO: back-up stack for ras
68    // use checkpoint to recover RAS
69    val recoverSp = io.redirect.rasSp
70    val recoverCtr = io.redirect.rasTopCtr
71    when (io.redirect.valid && io.redirect.isMisPred) {
72        sp := recoverSp
73        ras(recoverSp) := Cat(recoverCtr, ras(recoverSp).retAddr).asTypeOf(rasEntry())
74    }
75
76}