xref: /XiangShan/src/main/scala/xiangshan/frontend/RAS.scala (revision d57bda64dd69dbc246bd52257ef7392f220149aa)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17// package xiangshan.frontend
18//
19// import chipsalliance.rocketchip.config.Parameters
20// import chisel3._
21// import chisel3.util._
22// import xiangshan._
23// import utils._
24// import chisel3.experimental.chiselName
25//
26// class RASEntry()(implicit p: Parameters) extends XSBundle {
27//     val retAddr = UInt(VAddrBits.W)
28//     val ctr = UInt(8.W) // layer of nested call functions
29// }
30//
31// @chiselName
32// class RAS(implicit p: Parameters) extends BasePredictor
33// {
34//     class RASResp extends Resp
35//     {
36//         val target =UInt(VAddrBits.W)
37//     }
38//
39//     class RASBranchInfo extends Meta
40//     {
41//         val rasSp = UInt(log2Up(RasSize).W)
42//         val rasTop = new RASEntry
43//     }
44//
45//     class RASIO extends DefaultBasePredictorIO
46//     {
47//         val is_ret = Input(Bool())
48//         val callIdx = Flipped(ValidIO(UInt(log2Ceil(PredictWidth).W)))
49//         val isRVC = Input(Bool())
50//         val isLastHalfRVI = Input(Bool())
51//         val redirect =  Flipped(ValidIO(new Redirect))
52//         val out = Output(new RASResp)
53//         val meta = Output(new RASBranchInfo)
54//     }
55//
56//
57//     def rasEntry() = new RASEntry
58//
59//     object RASEntry {
60//         def apply(retAddr: UInt, ctr: UInt): RASEntry = {
61//             val e = Wire(rasEntry())
62//             e.retAddr := retAddr
63//             e.ctr := ctr
64//             e
65//         }
66//     }
67//
68//     override val io = IO(new RASIO)
69//     override val debug = true
70//
71//     @chiselName
72//     class RASStack(val rasSize: Int) extends XSModule {
73//         val io = IO(new Bundle {
74//             val push_valid = Input(Bool())
75//             val pop_valid = Input(Bool())
76//             val spec_new_addr = Input(UInt(VAddrBits.W))
77//
78//             val recover_sp = Input(UInt(log2Up(rasSize).W))
79//             val recover_top = Input(rasEntry())
80//             val recover_valid = Input(Bool())
81//             val recover_push = Input(Bool())
82//             val recover_pop = Input(Bool())
83//             val recover_new_addr = Input(UInt(VAddrBits.W))
84//
85//             val sp = Output(UInt(log2Up(rasSize).W))
86//             val top = Output(rasEntry())
87//         })
88//         val debugIO = IO(new Bundle{
89//             val push_entry = Output(rasEntry())
90//             val alloc_new = Output(Bool())
91//             val sp = Output(UInt(log2Up(rasSize).W))
92//             val topRegister = Output(rasEntry())
93//             val out_mem = Output(Vec(RasSize, rasEntry()))
94//         })
95//
96//         val stack = Mem(RasSize, new RASEntry)
97//         val sp = RegInit(0.U(log2Up(rasSize).W))
98//         val top = RegInit(0.U.asTypeOf(new RASEntry))
99//         val topPtr = RegInit(0.U(log2Up(rasSize).W))
100//
101//         def ptrInc(ptr: UInt) = Mux(ptr === (rasSize-1).U, 0.U, ptr + 1.U)
102//         def ptrDec(ptr: UInt) = Mux(ptr === 0.U, (rasSize-1).U, ptr - 1.U)
103//
104//         val alloc_new = io.spec_new_addr =/= top.retAddr || top.ctr.andR
105//         val recover_alloc_new = io.recover_new_addr =/= io.recover_top.retAddr || io.recover_top.ctr.andR
106//
107//         // TODO: fix overflow and underflow bugs
108//         def update(recover: Bool)(do_push: Bool, do_pop: Bool, do_alloc_new: Bool,
109//             do_sp: UInt, do_top_ptr: UInt, do_new_addr: UInt,
110//             do_top: RASEntry) = {
111//                 when (do_push) {
112//                     when (do_alloc_new) {
113//                         sp     := ptrInc(do_sp)
114//                         topPtr := do_sp
115//                         top.retAddr := do_new_addr
116//                         top.ctr := 1.U
117//                         stack.write(do_sp, RASEntry(do_new_addr, 1.U))
118//                     }.otherwise {
119//                         when (recover) {
120//                             sp := do_sp
121//                             topPtr := do_top_ptr
122//                             top.retAddr := do_top.retAddr
123//                         }
124//                         top.ctr := do_top.ctr + 1.U
125//                         stack.write(do_top_ptr, RASEntry(do_new_addr, do_top.ctr + 1.U))
126//                     }
127//                 }.elsewhen (do_pop) {
128//                     when (do_top.ctr === 1.U) {
129//                         sp     := ptrDec(do_sp)
130//                         topPtr := ptrDec(do_top_ptr)
131//                         top := stack.read(ptrDec(do_top_ptr))
132//                     }.otherwise {
133//                         when (recover) {
134//                             sp := do_sp
135//                             topPtr := do_top_ptr
136//                             top.retAddr := do_top.retAddr
137//                         }
138//                         top.ctr := do_top.ctr - 1.U
139//                         stack.write(do_top_ptr, RASEntry(do_top.retAddr, do_top.ctr - 1.U))
140//                     }
141//                 }.otherwise {
142//                     when (recover) {
143//                         sp := do_sp
144//                         topPtr := do_top_ptr
145//                         top := do_top
146//                         stack.write(do_top_ptr, do_top)
147//                     }
148//                 }
149//                 XSPerfAccumulate("ras_overflow", do_push && do_alloc_new && ptrInc(do_sp) === 0.U)
150//                 XSPerfAccumulate("ras_underflow", do_pop && do_top.ctr === 1.U && ptrDec(do_sp) === (rasSize-1).U)
151//             }
152//
153//         update(io.recover_valid)(
154//             Mux(io.recover_valid, io.recover_push,     io.push_valid),
155//             Mux(io.recover_valid, io.recover_pop,      io.pop_valid),
156//             Mux(io.recover_valid, recover_alloc_new,   alloc_new),
157//             Mux(io.recover_valid, io.recover_sp,       sp),
158//             Mux(io.recover_valid, io.recover_sp - 1.U, topPtr),
159//             Mux(io.recover_valid, io.recover_new_addr, io.spec_new_addr),
160//             Mux(io.recover_valid, io.recover_top,      top))
161//
162//         io.sp := sp
163//         io.top := top
164//
165//         debugIO.push_entry := RASEntry(io.spec_new_addr, Mux(alloc_new, 1.U, top.ctr + 1.U))
166//         debugIO.alloc_new := alloc_new
167//         debugIO.sp := sp
168//         debugIO.topRegister := top
169//         for (i <- 0 until RasSize) {
170//             debugIO.out_mem(i) := stack.read(i.U)
171//         }
172//
173//     }
174//
175//     val spec = Module(new RASStack(RasSize))
176//     val spec_ras = spec.io
177//
178//
179//     val spec_push = WireInit(false.B)
180//     val spec_pop = WireInit(false.B)
181//     val jump_is_first = io.callIdx.bits === 0.U
182//     val call_is_last_half = io.isLastHalfRVI && jump_is_first
183//     val spec_new_addr = packetAligned(io.pc.bits) + (io.callIdx.bits << instOffsetBits.U) + Mux( (io.isRVC | call_is_last_half) && HasCExtension.B, 2.U, 4.U)
184//     spec_ras.push_valid := spec_push
185//     spec_ras.pop_valid  := spec_pop
186//     spec_ras.spec_new_addr   := spec_new_addr
187//     val spec_top_addr = spec_ras.top.retAddr
188//
189//     spec_push := io.callIdx.valid && io.pc.valid
190//     spec_pop  := io.is_ret && io.pc.valid
191//
192//     val redirect = RegNext(io.redirect)
193//     val copy_valid = redirect.valid
194//     val recover_cfi = redirect.bits.cfiUpdate
195//
196//     val retMissPred  = copy_valid && redirect.bits.level === 0.U && recover_cfi.pd.isRet
197//     val callMissPred = copy_valid && redirect.bits.level === 0.U && recover_cfi.pd.isCall
198//     // when we mispredict a call, we must redo a push operation
199//     // similarly, when we mispredict a return, we should redo a pop
200//     spec_ras.recover_valid := copy_valid
201//     spec_ras.recover_push := callMissPred
202//     spec_ras.recover_pop  := retMissPred
203//
204//     spec_ras.recover_sp  := recover_cfi.rasSp
205//     spec_ras.recover_top := recover_cfi.rasEntry
206//     spec_ras.recover_new_addr := recover_cfi.pc + Mux(recover_cfi.pd.isRVC, 2.U, 4.U)
207//
208//     io.meta.rasSp := spec_ras.sp
209//     io.meta.rasTop := spec_ras.top
210//
211//     io.out.target := spec_top_addr
212//     // TODO: back-up stack for ras
213//     // use checkpoint to recover RAS
214//
215//     if (BPUDebug && debug) {
216//         val spec_debug = spec.debugIO
217//         XSDebug("----------------RAS----------------\n")
218//         XSDebug(" TopRegister: 0x%x   %d \n",spec_debug.topRegister.retAddr,spec_debug.topRegister.ctr)
219//         XSDebug("  index       addr           ctr \n")
220//         for(i <- 0 until RasSize){
221//             XSDebug("  (%d)   0x%x      %d",i.U,spec_debug.out_mem(i).retAddr,spec_debug.out_mem(i).ctr)
222//             when(i.U === spec_debug.sp){XSDebug(false,true.B,"   <----sp")}
223//             XSDebug(false,true.B,"\n")
224//         }
225//         XSDebug(spec_push, "(spec_ras)push  inAddr: 0x%x  inCtr: %d |  allocNewEntry:%d |   sp:%d \n",
226//             spec_new_addr,spec_debug.push_entry.ctr,spec_debug.alloc_new,spec_debug.sp.asUInt)
227//         XSDebug(spec_pop, "(spec_ras)pop  outAddr: 0x%x \n",io.out.target)
228//         val redirectUpdate = redirect.bits.cfiUpdate
229//         XSDebug("copyValid:%d recover(SP:%d retAddr:%x ctr:%d) \n",
230//             copy_valid,redirectUpdate.rasSp,redirectUpdate.rasEntry.retAddr,redirectUpdate.rasEntry.ctr)
231//     }
232//
233// }
234