xref: /XiangShan/src/main/scala/xiangshan/frontend/RAS.scala (revision ed809609d6857124d6c0b25bddaf9a4b8367ec39)
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        val rasToqAddr = UInt(VAddrBits.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 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_0 = Reg(Vec(RasSize, rasEntry()))  //RegInit(0.U)asTypeOf(Vec(RasSize,rasEntry)) cause comb loop
40    // val ras_1 = Reg(Vec(RasSize, rasEntry()))
41    // val sp_0 = RegInit(0.U(log2Up(RasSize).W))
42    // val sp_1 = RegInit(0.U(log2Up(RasSize).W))
43    // val choose_bit = RegInit(false.B)   //start with 0
44    // val spec_ras = Mux(choose_bit, ras_1, ras_0)
45    // val spec_sp = Mux(choose_bit,sp_1,sp_0)
46    // val commit_ras = Mux(choose_bit, ras_0, ras_1)
47    // val commit_sp = Mux(choose_bit,sp_0,sp_1)
48
49    val spec_ras = Reg(Vec(RasSize, rasEntry()))
50    val spec_sp = RegInit(0.U(log2Up(RasSize).W))
51    val commit_ras = Reg(Vec(RasSize, rasEntry()))
52    val commit_sp = RegInit(0.U(log2Up(RasSize).W))
53
54
55    val spec_is_empty = spec_sp === 0.U
56    val spec_is_full = spec_sp === (RasSize - 1).U
57
58    val spec_ras_top_entry = spec_ras(spec_sp-1.U)
59    val spec_ras_top_addr = spec_ras_top_entry.retAddr
60    val spec_ras_top_ctr = spec_ras_top_entry.ctr
61    //no need to pass the ras branchInfo
62    io.branchInfo.rasSp := DontCare
63    io.branchInfo.rasTopCtr := DontCare
64    io.branchInfo.rasToqAddr := DontCare
65
66    io.out.valid := !spec_is_empty && io.is_ret
67    XSDebug("----------------RAS(spec)----------------\n")
68    XSDebug("  index       addr           ctr \n")
69    for(i <- 0 until RasSize){
70        XSDebug("  (%d)   0x%x      %d",i.U,spec_ras(i).retAddr,spec_ras(i).ctr)
71        when(i.U === spec_sp){XSDebug(false,true.B,"   <----sp")}
72        XSDebug(false,true.B,"\n")
73    }
74    XSDebug("----------------RAS(commit)----------------\n")
75    XSDebug("  index       addr           ctr \n")
76    for(i <- 0 until RasSize){
77        XSDebug("  (%d)   0x%x      %d",i.U,commit_ras(i).retAddr,commit_ras(i).ctr)
78        when(i.U === commit_sp){XSDebug(false,true.B,"   <----sp")}
79        XSDebug(false,true.B,"\n")
80    }
81    // update spec RAS
82    // speculative update RAS
83    val spec_push = !spec_is_full && io.callIdx.valid && io.pc.valid
84    val spec_pop = !spec_is_empty && io.is_ret && io.pc.valid
85    val spec_new_addr = io.pc.bits + (io.callIdx.bits << 1.U) + Mux(io.isRVC,2.U,4.U)
86    val spec_ras_write = WireInit(0.U.asTypeOf(rasEntry()))
87    val sepc_alloc_new = spec_new_addr =/= spec_ras_top_addr
88    when (spec_push) {
89        //push
90        spec_ras_write.ctr := 1.U
91        spec_ras_write.retAddr := spec_new_addr
92        when(sepc_alloc_new){
93            spec_sp := spec_sp + 1.U
94            spec_ras(spec_sp) := spec_ras_write
95        }.otherwise{
96            spec_ras_top_ctr := spec_ras_top_ctr + 1.U
97        }
98        XSDebug("(spec_ras)push  inAddr: 0x%x  inCtr: %d |  allocNewEntry:%d |   sp:%d \n",spec_ras_write.retAddr,spec_ras_write.ctr,sepc_alloc_new,spec_sp.asUInt)
99    }
100
101    when (spec_pop) {
102        //pop
103        when (spec_ras_top_ctr === 1.U) {
104            spec_sp := Mux(spec_sp === 0.U, 0.U, spec_sp - 1.U)
105        }.otherwise {
106           spec_ras_top_ctr := spec_ras_top_ctr - 1.U
107        }
108        XSDebug("(spec_ras)pop outValid:%d  outAddr: 0x%x \n",io.out.valid,io.out.bits.target)
109    }
110    io.out.bits.target := spec_ras_top_addr
111    // TODO: back-up stack for ras
112    // use checkpoint to recover RAS
113
114    val commit_is_empty = commit_sp === 0.U
115    val commit_is_full = commit_sp === (RasSize - 1).U
116    val commit_ras_top_entry = commit_ras(commit_sp-1.U)
117    val commit_ras_top_addr = commit_ras_top_entry.retAddr
118    val commit_ras_top_ctr = commit_ras_top_entry.ctr
119    //update commit ras
120    val commit_push = !commit_is_full && io.recover.valid && io.recover.bits.pd.isCall
121    val commit_pop = !commit_is_empty && io.recover.valid && io.recover.bits.pd.isRet
122    val commit_new_addr = io.recover.bits.pc + 4.U  //TODO: consider RVC
123    val commit_ras_write = WireInit(0.U.asTypeOf(rasEntry()))
124    val commit_alloc_new = commit_new_addr =/= commit_ras_top_addr
125    when (commit_push) {
126        //push
127        commit_ras_write.ctr := 1.U
128        commit_ras_write.retAddr := commit_new_addr
129        when(commit_alloc_new){
130            commit_sp := commit_sp + 1.U
131            commit_ras(commit_sp) := commit_ras_write
132        }.otherwise{
133            commit_ras_top_ctr := commit_ras_top_ctr + 1.U
134        }
135        XSDebug("(commit_ras)push  inAddr: 0x%x  inCtr: %d |  allocNewEntry:%d |   sp:%d \n",commit_ras_write.retAddr,commit_ras_write.ctr,sepc_alloc_new,commit_sp.asUInt)
136    }
137
138    when (commit_pop) {
139        //pop
140        when (commit_ras_top_ctr === 1.U) {
141            commit_sp := Mux(commit_sp === 0.U, 0.U, commit_sp - 1.U)
142        }.otherwise {
143           commit_ras_top_ctr := commit_ras_top_ctr - 1.U
144        }
145        XSDebug("(commit_ras)pop outValid:%d  outAddr: 0x%x \n",io.out.valid,io.out.bits.target)
146    }
147
148    val copy_valid = io.recover.valid && io.recover.bits.isMisPred
149    val copy_next = RegNext(copy_valid)
150    XSDebug("copyValid:%d copyNext:%d \n",copy_valid,copy_next)
151    when(copy_next)
152    {
153        for(i <- 0 until RasSize)
154        {
155            spec_ras(i) := commit_ras(i)
156            spec_sp := commit_sp
157        }
158    }
159
160    // val recoverSp = io.recover.bits.brInfo.rasSp
161    // val recoverCtr = io.recover.bits.brInfo.rasTopCtr
162    // val recoverAddr = io.recover.bits.brInfo.rasToqAddr
163    // val recover_top = ras(recoverSp - 1.U)
164    // when (recover_valid) {
165    //     sp := recoverSp
166    //     recover_top.ctr := recoverCtr
167    //     recover_top.retAddr := recoverAddr
168    //     XSDebug("RAS update: SP:%d , Ctr:%d \n",recoverSp,recoverCtr)
169    // }
170    // val recover_and_push = recover_valid && push
171    // val recover_and_pop = recover_valid && pop
172    // val recover_alloc_new = new_addr =/= recoverAddr
173    // when(recover_and_push)
174    // {
175    //     when(recover_alloc_new){
176    //         sp := recoverSp + 1.U
177    //         ras(recoverSp).retAddr := new_addr
178    //         ras(recoverSp).ctr := 1.U
179    //         recover_top.retAddr := recoverAddr
180    //         recover_top.ctr := recoverCtr
181    //     } .otherwise{
182    //         sp := recoverSp
183    //         recover_top.ctr := recoverCtr + 1.U
184    //         recover_top.retAddr := recoverAddr
185    //     }
186    // } .elsewhen(recover_and_pop)
187    // {
188    //     io.out.bits.target := recoverAddr
189    //     when ( recover_top.ctr === 1.U) {
190    //         sp := recoverSp - 1.U
191    //     }.otherwise {
192    //         sp := recoverSp
193    //        recover_top.ctr := recoverCtr - 1.U
194    //     }
195    // }
196
197}