xref: /XiangShan/src/main/scala/xiangshan/frontend/RAS.scala (revision 255f2bca32db8615878ec212b4f2a9114a079869)
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}