xref: /XiangShan/src/main/scala/xiangshan/frontend/newRAS.scala (revision 7af6acb01d3e68a3ff29bcf1bdcfc7fe565dc89c)
1c89b4642SGuokai Chen/***************************************************************************************
2c89b4642SGuokai Chen* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3c89b4642SGuokai Chen* Copyright (c) 2020-2021 Peng Cheng Laboratory
4c89b4642SGuokai Chen*
5c89b4642SGuokai Chen* XiangShan is licensed under Mulan PSL v2.
6c89b4642SGuokai Chen* You can use this software according to the terms and conditions of the Mulan PSL v2.
7c89b4642SGuokai Chen* You may obtain a copy of Mulan PSL v2 at:
8c89b4642SGuokai Chen*          http://license.coscl.org.cn/MulanPSL2
9c89b4642SGuokai Chen*
10c89b4642SGuokai Chen* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11c89b4642SGuokai Chen* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12c89b4642SGuokai Chen* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13c89b4642SGuokai Chen*
14c89b4642SGuokai Chen* See the Mulan PSL v2 for more details.
15c89b4642SGuokai Chen***************************************************************************************/
16c89b4642SGuokai Chenpackage xiangshan.frontend
17c89b4642SGuokai Chen
188891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
19c89b4642SGuokai Chenimport chisel3._
20c89b4642SGuokai Chenimport chisel3.util._
21c89b4642SGuokai Chenimport utils._
22c89b4642SGuokai Chenimport utility._
23c89b4642SGuokai Chenimport xiangshan._
24c89b4642SGuokai Chenimport xiangshan.frontend._
25c89b4642SGuokai Chen
26c89b4642SGuokai Chenclass RASEntry()(implicit p: Parameters) extends XSBundle {
27c89b4642SGuokai Chen    val retAddr = UInt(VAddrBits.W)
28c89b4642SGuokai Chen    val ctr = UInt(8.W) // layer of nested call functions
29c89b4642SGuokai Chen    def =/=(that: RASEntry) = this.retAddr =/= that.retAddr || this.ctr =/= that.ctr
30c89b4642SGuokai Chen}
31c89b4642SGuokai Chen
32c89b4642SGuokai Chenclass RASPtr(implicit p: Parameters) extends CircularQueuePtr[RASPtr](
33c89b4642SGuokai Chen  p => p(XSCoreParamsKey).RasSpecSize
34c89b4642SGuokai Chen){
35c89b4642SGuokai Chen}
36c89b4642SGuokai Chen
37c89b4642SGuokai Chenobject RASPtr {
38c89b4642SGuokai Chen  def apply(f: Bool, v: UInt)(implicit p: Parameters): RASPtr = {
39c89b4642SGuokai Chen    val ptr = Wire(new RASPtr)
40c89b4642SGuokai Chen    ptr.flag := f
41c89b4642SGuokai Chen    ptr.value := v
42c89b4642SGuokai Chen    ptr
43c89b4642SGuokai Chen  }
44c89b4642SGuokai Chen  def inverse(ptr: RASPtr)(implicit p: Parameters): RASPtr = {
45c89b4642SGuokai Chen    apply(!ptr.flag, ptr.value)
46c89b4642SGuokai Chen  }
47c89b4642SGuokai Chen}
48c89b4642SGuokai Chen
49c89b4642SGuokai Chenclass RASMeta(implicit p: Parameters) extends XSBundle {
50c89b4642SGuokai Chen  val ssp = UInt(log2Up(RasSize).W)
5177bef50aSGuokai Chen  val sctr = UInt(RasCtrSize.W)
52c89b4642SGuokai Chen  val TOSW = new RASPtr
53c89b4642SGuokai Chen  val TOSR = new RASPtr
54c89b4642SGuokai Chen  val NOS = new RASPtr
55c89b4642SGuokai Chen}
56c89b4642SGuokai Chen
57c89b4642SGuokai Chenobject RASMeta {
58c89b4642SGuokai Chen  def apply(ssp: UInt, sctr: UInt, TOSW: RASPtr, TOSR: RASPtr, NOS: RASPtr)(implicit p: Parameters):RASMeta = {
59c89b4642SGuokai Chen    val e = Wire(new RASMeta)
60c89b4642SGuokai Chen    e.ssp := ssp
61c89b4642SGuokai Chen    e.sctr := sctr
62c89b4642SGuokai Chen    e.TOSW := TOSW
63c89b4642SGuokai Chen    e.TOSR := TOSR
64c89b4642SGuokai Chen    e.NOS := NOS
65c89b4642SGuokai Chen    e
66c89b4642SGuokai Chen  }
67c89b4642SGuokai Chen}
68c89b4642SGuokai Chen
69c89b4642SGuokai Chenclass RASDebug(implicit p: Parameters) extends XSBundle {
70c89b4642SGuokai Chen  val spec_queue = Output(Vec(RasSpecSize, new RASEntry))
71c89b4642SGuokai Chen  val spec_nos = Output(Vec(RasSpecSize, new RASPtr))
72c89b4642SGuokai Chen  val commit_stack = Output(Vec(RasSize, new RASEntry))
73c89b4642SGuokai Chen}
74c89b4642SGuokai Chen
75c89b4642SGuokai Chenclass RAS(implicit p: Parameters) extends BasePredictor {
76c89b4642SGuokai Chen  override val meta_size = WireInit(0.U.asTypeOf(new RASMeta)).getWidth
77c89b4642SGuokai Chen
78c89b4642SGuokai Chen  object RASEntry {
79c89b4642SGuokai Chen    def apply(retAddr: UInt, ctr: UInt): RASEntry = {
80c89b4642SGuokai Chen      val e = Wire(new RASEntry)
81c89b4642SGuokai Chen      e.retAddr := retAddr
82c89b4642SGuokai Chen      e.ctr := ctr
83c89b4642SGuokai Chen      e
84c89b4642SGuokai Chen    }
85c89b4642SGuokai Chen  }
86c89b4642SGuokai Chen
87c89b4642SGuokai Chen
88c89b4642SGuokai Chen  class RASStack(rasSize: Int, rasSpecSize: Int) extends XSModule with HasCircularQueuePtrHelper {
89c89b4642SGuokai Chen    val io = IO(new Bundle {
90c89b4642SGuokai Chen      val spec_push_valid = Input(Bool())
91c89b4642SGuokai Chen      val spec_pop_valid = Input(Bool())
92c89b4642SGuokai Chen      val spec_push_addr = Input(UInt(VAddrBits.W))
93c89b4642SGuokai Chen      // for write bypass between s2 and s3
94c89b4642SGuokai Chen
95c89b4642SGuokai Chen      val s2_fire = Input(Bool())
96c89b4642SGuokai Chen      val s3_fire = Input(Bool())
97c89b4642SGuokai Chen      val s3_cancel = Input(Bool())
98c89b4642SGuokai Chen      val s3_meta = Input(new RASMeta)
99c89b4642SGuokai Chen      val s3_missed_pop = Input(Bool())
100c89b4642SGuokai Chen      val s3_missed_push = Input(Bool())
101c89b4642SGuokai Chen      val s3_pushAddr = Input(UInt(VAddrBits.W))
102c89b4642SGuokai Chen      val spec_pop_addr = Output(UInt(VAddrBits.W))
103c89b4642SGuokai Chen
104c89b4642SGuokai Chen      val commit_push_valid = Input(Bool())
105c89b4642SGuokai Chen      val commit_pop_valid = Input(Bool())
106c89b4642SGuokai Chen      val commit_push_addr = Input(UInt(VAddrBits.W))
107c89b4642SGuokai Chen      val commit_meta_TOSW = Input(new RASPtr)
108c89b4642SGuokai Chen      val commit_meta_TOSR = Input(new RASPtr)
109c89b4642SGuokai Chen      // for debug purpose only
110c89b4642SGuokai Chen      val commit_meta_ssp = Input(UInt(log2Up(RasSize).W))
11177bef50aSGuokai Chen      val commit_meta_sctr = Input(UInt(RasCtrSize.W))
112c89b4642SGuokai Chen
113c89b4642SGuokai Chen      val redirect_valid = Input(Bool())
114c89b4642SGuokai Chen      val redirect_isCall = Input(Bool())
115c89b4642SGuokai Chen      val redirect_isRet = Input(Bool())
116c89b4642SGuokai Chen      val redirect_meta_ssp = Input(UInt(log2Up(RasSize).W))
11777bef50aSGuokai Chen      val redirect_meta_sctr = Input(UInt(RasCtrSize.W))
118c89b4642SGuokai Chen      val redirect_meta_TOSW = Input(new RASPtr)
119c89b4642SGuokai Chen      val redirect_meta_TOSR = Input(new RASPtr)
120c89b4642SGuokai Chen      val redirect_meta_NOS = Input(new RASPtr)
121c89b4642SGuokai Chen      val redirect_callAddr = Input(UInt(VAddrBits.W))
122c89b4642SGuokai Chen
123c89b4642SGuokai Chen      val ssp = Output(UInt(log2Up(RasSize).W))
12477bef50aSGuokai Chen      val sctr = Output(UInt(RasCtrSize.W))
125c89b4642SGuokai Chen      val nsp = Output(UInt(log2Up(RasSize).W))
126c89b4642SGuokai Chen      val TOSR = Output(new RASPtr)
127c89b4642SGuokai Chen      val TOSW = Output(new RASPtr)
128c89b4642SGuokai Chen      val NOS = Output(new RASPtr)
129c89b4642SGuokai Chen      val BOS = Output(new RASPtr)
130c89b4642SGuokai Chen
131c89b4642SGuokai Chen      val debug = new RASDebug
132c89b4642SGuokai Chen    })
133c89b4642SGuokai Chen
134c89b4642SGuokai Chen    val commit_stack = RegInit(VecInit(Seq.fill(RasSize)(RASEntry(0.U, 0.U))))
135c89b4642SGuokai Chen    val spec_queue = RegInit(VecInit(Seq.fill(rasSpecSize)(RASEntry(0.U, 0.U))))
136c89b4642SGuokai Chen    val spec_nos = RegInit(VecInit(Seq.fill(rasSpecSize)(RASPtr(false.B, 0.U))))
137c89b4642SGuokai Chen
138c89b4642SGuokai Chen    val nsp = RegInit(0.U(log2Up(rasSize).W))
139c89b4642SGuokai Chen    val ssp = RegInit(0.U(log2Up(rasSize).W))
140c89b4642SGuokai Chen
141c89b4642SGuokai Chen    val sctr = RegInit(0.U(RasCtrSize.W))
142c89b4642SGuokai Chen    val TOSR = RegInit(RASPtr(true.B, (RasSpecSize - 1).U))
143c89b4642SGuokai Chen    val TOSW = RegInit(RASPtr(false.B, 0.U))
144c89b4642SGuokai Chen    val BOS = RegInit(RASPtr(false.B, 0.U))
145c89b4642SGuokai Chen
146c89b4642SGuokai Chen    val spec_overflowed = RegInit(false.B)
147c89b4642SGuokai Chen
148c89b4642SGuokai Chen    val writeBypassEntry = Reg(new RASEntry)
149c89b4642SGuokai Chen    val writeBypassNos = Reg(new RASPtr)
150c89b4642SGuokai Chen
151c89b4642SGuokai Chen    val writeBypassValid = RegInit(0.B)
152c89b4642SGuokai Chen    val writeBypassValidWire = Wire(Bool())
153c89b4642SGuokai Chen
154c89b4642SGuokai Chen    def TOSRinRange(currentTOSR: RASPtr, currentTOSW: RASPtr) = {
155c89b4642SGuokai Chen      val inflightValid = WireInit(false.B)
156c89b4642SGuokai Chen      // if in range, TOSR should be no younger than BOS and strictly younger than TOSW
157c89b4642SGuokai Chen      when (!isBefore(currentTOSR, BOS) && isBefore(currentTOSR, currentTOSW)) {
158c89b4642SGuokai Chen        inflightValid := true.B
159c89b4642SGuokai Chen      }
160c89b4642SGuokai Chen      inflightValid
161c89b4642SGuokai Chen    }
162c89b4642SGuokai Chen
163c89b4642SGuokai Chen    def getCommitTop(currentSsp: UInt) = {
164c89b4642SGuokai Chen      commit_stack(currentSsp)
165c89b4642SGuokai Chen    }
166c89b4642SGuokai Chen
167c89b4642SGuokai Chen    def getTopNos(currentTOSR: RASPtr, allowBypass: Boolean):RASPtr = {
168c89b4642SGuokai Chen      val ret = Wire(new RASPtr)
169c89b4642SGuokai Chen      if (allowBypass){
170c89b4642SGuokai Chen        when (writeBypassValid) {
171c89b4642SGuokai Chen          ret := writeBypassNos
172c89b4642SGuokai Chen        } .otherwise {
173c89b4642SGuokai Chen          ret := spec_nos(TOSR.value)
174c89b4642SGuokai Chen        }
175c89b4642SGuokai Chen      } else {
176c89b4642SGuokai Chen        ret := spec_nos(TOSR.value) // invalid when TOSR is not in range
177c89b4642SGuokai Chen      }
178c89b4642SGuokai Chen      ret
179c89b4642SGuokai Chen    }
180c89b4642SGuokai Chen
181c89b4642SGuokai Chen    def getTop(currentSsp: UInt, currentSctr: UInt, currentTOSR: RASPtr, currentTOSW: RASPtr, allowBypass: Boolean):RASEntry = {
182c89b4642SGuokai Chen      val ret = Wire(new RASEntry)
183c89b4642SGuokai Chen      if (allowBypass) {
184c89b4642SGuokai Chen        when (writeBypassValid) {
185c89b4642SGuokai Chen          ret := writeBypassEntry
186c89b4642SGuokai Chen        } .elsewhen (TOSRinRange(currentTOSR, currentTOSW)) {
187c89b4642SGuokai Chen          ret := spec_queue(currentTOSR.value)
188c89b4642SGuokai Chen        } .otherwise {
189c89b4642SGuokai Chen          ret := getCommitTop(currentSsp)
190c89b4642SGuokai Chen        }
191c89b4642SGuokai Chen      } else {
192c89b4642SGuokai Chen        when (TOSRinRange(currentTOSR, currentTOSW)) {
193c89b4642SGuokai Chen          ret := spec_queue(currentTOSR.value)
194c89b4642SGuokai Chen        } .otherwise {
195c89b4642SGuokai Chen          ret := getCommitTop(currentSsp)
196c89b4642SGuokai Chen        }
197c89b4642SGuokai Chen      }
198c89b4642SGuokai Chen
199c89b4642SGuokai Chen      ret
200c89b4642SGuokai Chen    }
201c89b4642SGuokai Chen
202c89b4642SGuokai Chen    // it would be unsafe for specPtr manipulation if specSize is not power of 2
203c89b4642SGuokai Chen    assert(log2Up(RasSpecSize) == log2Floor(RasSpecSize))
204c89b4642SGuokai Chen    def ctrMax = ((1l << RasCtrSize) - 1).U
205c89b4642SGuokai Chen    def ptrInc(ptr: UInt) = ptr + 1.U
206c89b4642SGuokai Chen    def ptrDec(ptr: UInt) = ptr - 1.U
207c89b4642SGuokai Chen
208c89b4642SGuokai Chen    def specPtrInc(ptr: RASPtr) = ptr + 1.U
209c89b4642SGuokai Chen    def specPtrDec(ptr: RASPtr) = ptr - 1.U
210c89b4642SGuokai Chen
211c89b4642SGuokai Chen
212c89b4642SGuokai Chen
213c89b4642SGuokai Chen
214c89b4642SGuokai Chen
215c89b4642SGuokai Chen
216c89b4642SGuokai Chen    when (io.redirect_valid && io.redirect_isCall) {
217c89b4642SGuokai Chen      writeBypassValidWire := true.B
218c89b4642SGuokai Chen      writeBypassValid := true.B
219c89b4642SGuokai Chen    } .elsewhen (io.redirect_valid) {
220c89b4642SGuokai Chen      // clear current top writeBypass if doing redirect
221c89b4642SGuokai Chen      writeBypassValidWire := false.B
222c89b4642SGuokai Chen      writeBypassValid := false.B
223c89b4642SGuokai Chen    } .elsewhen (io.s2_fire) {
224c89b4642SGuokai Chen      writeBypassValidWire := io.spec_push_valid
225c89b4642SGuokai Chen      writeBypassValid := io.spec_push_valid
226c89b4642SGuokai Chen    } .elsewhen (io.s3_fire) {
227c89b4642SGuokai Chen      writeBypassValidWire := false.B
228c89b4642SGuokai Chen      writeBypassValid := false.B
229c89b4642SGuokai Chen    } .otherwise {
230c89b4642SGuokai Chen      writeBypassValidWire := writeBypassValid
231c89b4642SGuokai Chen    }
232c89b4642SGuokai Chen
233c89b4642SGuokai Chen
234c89b4642SGuokai Chen
235c89b4642SGuokai Chen    val topEntry = getTop(ssp, sctr, TOSR, TOSW, true)
236c89b4642SGuokai Chen    val topNos = getTopNos(TOSR, true)
237c89b4642SGuokai Chen    val redirectTopEntry = getTop(io.redirect_meta_ssp, io.redirect_meta_sctr, io.redirect_meta_TOSR, io.redirect_meta_TOSW, false)
238c89b4642SGuokai Chen    val redirectTopNos = io.redirect_meta_NOS
239c89b4642SGuokai Chen    val s3TopEntry = getTop(io.s3_meta.ssp, io.s3_meta.sctr, io.s3_meta.TOSR, io.s3_meta.TOSW, false)
240c89b4642SGuokai Chen    val s3TopNos = io.s3_meta.NOS
241c89b4642SGuokai Chen
242c89b4642SGuokai Chen    val writeEntry = Wire(new RASEntry)
243c89b4642SGuokai Chen    val writeNos = Wire(new RASPtr)
244c89b4642SGuokai Chen    writeEntry.retAddr := Mux(io.redirect_valid && io.redirect_isCall,  io.redirect_callAddr, io.spec_push_addr)
245c89b4642SGuokai Chen    writeEntry.ctr := Mux(io.redirect_valid && io.redirect_isCall,
246c89b4642SGuokai Chen      Mux(redirectTopEntry.retAddr === io.redirect_callAddr && redirectTopEntry.ctr < ctrMax, io.redirect_meta_sctr + 1.U, 0.U),
247c89b4642SGuokai Chen      Mux(topEntry.retAddr === io.spec_push_addr && topEntry.ctr < ctrMax, sctr + 1.U, 0.U))
248c89b4642SGuokai Chen
249c89b4642SGuokai Chen    writeNos := Mux(io.redirect_valid && io.redirect_isCall,
250c89b4642SGuokai Chen      io.redirect_meta_NOS, TOSR)
251c89b4642SGuokai Chen
252c89b4642SGuokai Chen    when (io.spec_push_valid || (io.redirect_valid && io.redirect_isCall)) {
253c89b4642SGuokai Chen      writeBypassEntry := writeEntry
254c89b4642SGuokai Chen      writeBypassNos := writeNos
255c89b4642SGuokai Chen    }
256c89b4642SGuokai Chen
257c89b4642SGuokai Chen    val realPush = Wire(Bool())
258c89b4642SGuokai Chen    val realWriteEntry = Wire(new RASEntry)
259c89b4642SGuokai Chen    val timingTop = RegInit(0.U.asTypeOf(new RASEntry))
260c89b4642SGuokai Chen    val timingNos = RegInit(0.U.asTypeOf(new RASPtr))
261c89b4642SGuokai Chen
262c89b4642SGuokai Chen    when (writeBypassValidWire) {
263c89b4642SGuokai Chen      when ((io.redirect_valid && io.redirect_isCall) || io.spec_push_valid) {
264c89b4642SGuokai Chen        timingTop := writeEntry
265c89b4642SGuokai Chen        timingNos := writeNos
266c89b4642SGuokai Chen      } .otherwise {
267c89b4642SGuokai Chen        timingTop := writeBypassEntry
268c89b4642SGuokai Chen        timingNos := writeBypassNos
269c89b4642SGuokai Chen      }
270c89b4642SGuokai Chen
271c89b4642SGuokai Chen    } .elsewhen (io.redirect_valid && io.redirect_isRet) {
272c89b4642SGuokai Chen      // getTop using redirect Nos as TOSR
273c89b4642SGuokai Chen      val popRedSsp = Wire(UInt(log2Up(rasSize).W))
27477bef50aSGuokai Chen      val popRedSctr = Wire(UInt(RasCtrSize.W))
275c89b4642SGuokai Chen      val popRedTOSR = io.redirect_meta_NOS
276c89b4642SGuokai Chen      val popRedTOSW = io.redirect_meta_TOSW
277c89b4642SGuokai Chen
278c89b4642SGuokai Chen      when (io.redirect_meta_sctr > 0.U) {
279c89b4642SGuokai Chen        popRedSctr := io.redirect_meta_sctr - 1.U
280c89b4642SGuokai Chen        popRedSsp := io.redirect_meta_ssp
281c89b4642SGuokai Chen      } .elsewhen (TOSRinRange(popRedTOSR, TOSW)) {
282c89b4642SGuokai Chen        popRedSsp := ptrDec(io.redirect_meta_ssp)
283c89b4642SGuokai Chen        popRedSctr := spec_queue(popRedTOSR.value).ctr
284c89b4642SGuokai Chen      } .otherwise {
285c89b4642SGuokai Chen        popRedSsp := ptrDec(io.redirect_meta_ssp)
286c89b4642SGuokai Chen        popRedSctr := getCommitTop(ptrDec(io.redirect_meta_ssp)).ctr
287c89b4642SGuokai Chen      }
288c89b4642SGuokai Chen      // We are deciding top for the next cycle, no need to use bypass here
289c89b4642SGuokai Chen      timingTop := getTop(popRedSsp, popRedSctr, popRedTOSR, popRedTOSW, false)
290c89b4642SGuokai Chen    } .elsewhen (io.redirect_valid) {
291c89b4642SGuokai Chen      // Neither call nor ret
292c89b4642SGuokai Chen      val popSsp = io.redirect_meta_ssp
293c89b4642SGuokai Chen      val popSctr = io.redirect_meta_sctr
294c89b4642SGuokai Chen      val popTOSR = io.redirect_meta_TOSR
295c89b4642SGuokai Chen      val popTOSW = io.redirect_meta_TOSW
296c89b4642SGuokai Chen
297c89b4642SGuokai Chen      timingTop := getTop(popSsp, popSctr, popTOSR, popTOSW, false)
298c89b4642SGuokai Chen
299c89b4642SGuokai Chen    } .elsewhen (io.spec_pop_valid) {
300c89b4642SGuokai Chen      // getTop using current Nos as TOSR
301c89b4642SGuokai Chen      val popSsp = Wire(UInt(log2Up(rasSize).W))
30277bef50aSGuokai Chen      val popSctr = Wire(UInt(RasCtrSize.W))
303c89b4642SGuokai Chen      val popTOSR = topNos
304c89b4642SGuokai Chen      val popTOSW = TOSW
305c89b4642SGuokai Chen
306c89b4642SGuokai Chen      when (sctr > 0.U) {
307c89b4642SGuokai Chen        popSctr := sctr - 1.U
308c89b4642SGuokai Chen        popSsp := ssp
309c89b4642SGuokai Chen      } .elsewhen (TOSRinRange(popTOSR, TOSW)) {
310c89b4642SGuokai Chen        popSsp := ptrDec(ssp)
311c89b4642SGuokai Chen        popSctr := spec_queue(popTOSR.value).ctr
312c89b4642SGuokai Chen      } .otherwise {
313c89b4642SGuokai Chen        popSsp := ptrDec(ssp)
314c89b4642SGuokai Chen        popSctr := getCommitTop(ptrDec(ssp)).ctr
315c89b4642SGuokai Chen      }
316c89b4642SGuokai Chen      // We are deciding top for the next cycle, no need to use bypass here
317c89b4642SGuokai Chen      timingTop := getTop(popSsp, popSctr, popTOSR, popTOSW, false)
318c89b4642SGuokai Chen    } .elsewhen (realPush) {
319c89b4642SGuokai Chen      // just updating spec queue, cannot read from there
320c89b4642SGuokai Chen      timingTop := realWriteEntry
321c89b4642SGuokai Chen    } .elsewhen (io.s3_cancel) {
322c89b4642SGuokai Chen      // s3 is different with s2
323c89b4642SGuokai Chen      timingTop := getTop(io.s3_meta.ssp, io.s3_meta.sctr, io.s3_meta.TOSR, io.s3_meta.TOSW, false)
324c89b4642SGuokai Chen      when (io.s3_missed_push) {
325c89b4642SGuokai Chen        val writeEntry_s3 = Wire(new RASEntry)
326c89b4642SGuokai Chen        timingTop := writeEntry_s3
327c89b4642SGuokai Chen        writeEntry_s3.retAddr := io.s3_pushAddr
328c89b4642SGuokai Chen        writeEntry_s3.ctr := Mux(timingTop.retAddr === io.s3_pushAddr && io.s3_meta.sctr < ctrMax, io.s3_meta.sctr + 1.U, 0.U)
329c89b4642SGuokai Chen      } .elsewhen (io.s3_missed_pop) {
330c89b4642SGuokai Chen        val popRedSsp_s3 = Wire(UInt(log2Up(rasSize).W))
33177bef50aSGuokai Chen        val popRedSctr_s3 = Wire(UInt(RasCtrSize.W))
332c89b4642SGuokai Chen        val popRedTOSR_s3 = io.s3_meta.NOS
333c89b4642SGuokai Chen        val popRedTOSW_s3 = io.s3_meta.TOSW
334c89b4642SGuokai Chen
335c89b4642SGuokai Chen        when (io.s3_meta.sctr > 0.U) {
336c89b4642SGuokai Chen          popRedSctr_s3 := io.s3_meta.sctr - 1.U
337c89b4642SGuokai Chen          popRedSsp_s3 := io.s3_meta.ssp
338c89b4642SGuokai Chen        } .elsewhen (TOSRinRange(popRedTOSR_s3, popRedTOSW_s3)) {
339c89b4642SGuokai Chen          popRedSsp_s3 := ptrDec(io.s3_meta.ssp)
340c89b4642SGuokai Chen          popRedSctr_s3 := spec_queue(popRedTOSR_s3.value).ctr
341c89b4642SGuokai Chen        } .otherwise {
342c89b4642SGuokai Chen          popRedSsp_s3 := ptrDec(io.s3_meta.ssp)
343c89b4642SGuokai Chen          popRedSctr_s3 := getCommitTop(ptrDec(io.s3_meta.ssp)).ctr
344c89b4642SGuokai Chen        }
345c89b4642SGuokai Chen        // We are deciding top for the next cycle, no need to use bypass here
346c89b4642SGuokai Chen        timingTop := getTop(popRedSsp_s3, popRedSctr_s3, popRedTOSR_s3, popRedTOSW_s3, false)
347c89b4642SGuokai Chen      }
348c89b4642SGuokai Chen    } .otherwise {
349c89b4642SGuokai Chen      // easy case
350c89b4642SGuokai Chen      val popSsp = ssp
351c89b4642SGuokai Chen      val popSctr = sctr
352c89b4642SGuokai Chen      val popTOSR = TOSR
353c89b4642SGuokai Chen      val popTOSW = TOSW
354c89b4642SGuokai Chen      timingTop := getTop(popSsp, popSctr, popTOSR, popTOSW, false)
355c89b4642SGuokai Chen    }
356c89b4642SGuokai Chen    val diffTop = Mux(writeBypassValid, writeBypassEntry.retAddr, topEntry.retAddr)
357c89b4642SGuokai Chen
358c89b4642SGuokai Chen    XSPerfAccumulate("ras_top_mismatch", diffTop =/= timingTop.retAddr);
359c89b4642SGuokai Chen    // could diff when more pop than push and a commit stack is updated with inflight info
360c89b4642SGuokai Chen
361c89b4642SGuokai Chen    val realWriteEntry_next = RegEnable(writeEntry, io.s2_fire || io.redirect_isCall)
362c89b4642SGuokai Chen    val s3_missPushEntry = Wire(new RASEntry)
363c89b4642SGuokai Chen    val s3_missPushAddr = Wire(new RASPtr)
364c89b4642SGuokai Chen    val s3_missPushNos = Wire(new RASPtr)
365c89b4642SGuokai Chen
366c89b4642SGuokai Chen    s3_missPushEntry.retAddr := io.s3_pushAddr
367c89b4642SGuokai Chen    s3_missPushEntry.ctr := Mux(s3TopEntry.retAddr === io.s3_pushAddr && s3TopEntry.ctr < ctrMax, io.s3_meta.sctr + 1.U, 0.U)
368c89b4642SGuokai Chen    s3_missPushAddr := io.s3_meta.TOSW
369c89b4642SGuokai Chen    s3_missPushNos := io.s3_meta.TOSR
370c89b4642SGuokai Chen
371c89b4642SGuokai Chen
372c89b4642SGuokai Chen
373c89b4642SGuokai Chen    realWriteEntry := Mux(io.redirect_isCall, realWriteEntry_next,
374c89b4642SGuokai Chen      Mux(io.s3_missed_push, s3_missPushEntry,
375c89b4642SGuokai Chen      realWriteEntry_next))
376c89b4642SGuokai Chen
377c89b4642SGuokai Chen    val realWriteAddr_next = RegEnable(Mux(io.redirect_valid && io.redirect_isCall, io.redirect_meta_TOSW, TOSW), io.s2_fire || (io.redirect_valid && io.redirect_isCall))
378c89b4642SGuokai Chen    val realWriteAddr = Mux(io.redirect_isCall, realWriteAddr_next,
379c89b4642SGuokai Chen      Mux(io.s3_missed_push, s3_missPushAddr,
380c89b4642SGuokai Chen      realWriteAddr_next))
381c89b4642SGuokai Chen    val realNos_next = RegEnable(Mux(io.redirect_valid && io.redirect_isCall, io.redirect_meta_TOSR, TOSR), io.s2_fire || (io.redirect_valid && io.redirect_isCall))
382c89b4642SGuokai Chen    val realNos = Mux(io.redirect_isCall, realNos_next,
383c89b4642SGuokai Chen      Mux(io.s3_missed_push, s3_missPushNos,
384c89b4642SGuokai Chen      realNos_next))
385c89b4642SGuokai Chen
386c89b4642SGuokai Chen    realPush := (io.s3_fire && (!io.s3_cancel && RegEnable(io.spec_push_valid, io.s2_fire) || io.s3_missed_push)) || RegNext(io.redirect_valid && io.redirect_isCall)
387c89b4642SGuokai Chen
388c89b4642SGuokai Chen    when (realPush) {
389c89b4642SGuokai Chen      spec_queue(realWriteAddr.value) := realWriteEntry
390c89b4642SGuokai Chen      spec_nos(realWriteAddr.value) := realNos
391c89b4642SGuokai Chen    }
392c89b4642SGuokai Chen
393c89b4642SGuokai Chen    def specPush(retAddr: UInt, currentSsp: UInt, currentSctr: UInt, currentTOSR: RASPtr, currentTOSW: RASPtr, topEntry: RASEntry) = {
394c89b4642SGuokai Chen      TOSR := currentTOSW
395c89b4642SGuokai Chen      TOSW := specPtrInc(currentTOSW)
396c89b4642SGuokai Chen      // spec sp and ctr should always be maintained
397c89b4642SGuokai Chen      when (topEntry.retAddr === retAddr && currentSctr < ctrMax) {
398c89b4642SGuokai Chen        sctr := currentSctr + 1.U
399c89b4642SGuokai Chen      } .otherwise {
400c89b4642SGuokai Chen        ssp := ptrInc(currentSsp)
401c89b4642SGuokai Chen        sctr := 0.U
402c89b4642SGuokai Chen      }
403c89b4642SGuokai Chen      // if we are draining the capacity of spec queue, force move BOS forward
404c89b4642SGuokai Chen      when (specPtrInc(currentTOSW) === BOS) {
405c89b4642SGuokai Chen        BOS := specPtrInc(BOS)
406c89b4642SGuokai Chen        spec_overflowed := true.B;
407c89b4642SGuokai Chen      }
408c89b4642SGuokai Chen    }
409c89b4642SGuokai Chen
410c89b4642SGuokai Chen    when (io.spec_push_valid) {
411c89b4642SGuokai Chen      specPush(io.spec_push_addr, ssp, sctr, TOSR, TOSW, topEntry)
412c89b4642SGuokai Chen    }
413c89b4642SGuokai Chen    def specPop(currentSsp: UInt, currentSctr: UInt, currentTOSR: RASPtr, currentTOSW: RASPtr, currentTopNos: RASPtr) = {
414c89b4642SGuokai Chen      // TOSR is only maintained when spec queue is not empty
415c89b4642SGuokai Chen      when (TOSRinRange(currentTOSR, currentTOSW)) {
416c89b4642SGuokai Chen        TOSR := currentTopNos
417c89b4642SGuokai Chen      }
418c89b4642SGuokai Chen      // spec sp and ctr should always be maintained
419c89b4642SGuokai Chen      when (currentSctr > 0.U) {
420c89b4642SGuokai Chen        sctr := currentSctr - 1.U
421c89b4642SGuokai Chen      } .elsewhen (TOSRinRange(currentTopNos, currentTOSW)) {
422c89b4642SGuokai Chen        // in range, use inflight data
423c89b4642SGuokai Chen        ssp := ptrDec(currentSsp)
424c89b4642SGuokai Chen        sctr := spec_queue(currentTopNos.value).ctr
425c89b4642SGuokai Chen      } .otherwise {
426c89b4642SGuokai Chen        // NOS not in range, use commit data
427c89b4642SGuokai Chen        ssp := ptrDec(currentSsp)
428c89b4642SGuokai Chen        sctr := getCommitTop(ptrDec(currentSsp)).ctr
429c89b4642SGuokai Chen        // in overflow state, we cannot determine the next sctr, sctr here is not accurate
430c89b4642SGuokai Chen      }
431c89b4642SGuokai Chen    }
432c89b4642SGuokai Chen    when (io.spec_pop_valid) {
433c89b4642SGuokai Chen      specPop(ssp, sctr, TOSR, TOSW, topNos)
434c89b4642SGuokai Chen    }
435c89b4642SGuokai Chen
436c89b4642SGuokai Chen    // io.spec_pop_addr := Mux(writeBypassValid, writeBypassEntry.retAddr, topEntry.retAddr)
437c89b4642SGuokai Chen
438c89b4642SGuokai Chen    io.spec_pop_addr := timingTop.retAddr
439c89b4642SGuokai Chen    io.BOS := BOS
440c89b4642SGuokai Chen    io.TOSW := TOSW
441c89b4642SGuokai Chen    io.TOSR := TOSR
442c89b4642SGuokai Chen    io.NOS := topNos
443c89b4642SGuokai Chen    io.ssp := ssp
444c89b4642SGuokai Chen    io.sctr := sctr
445c89b4642SGuokai Chen    io.nsp := nsp
446c89b4642SGuokai Chen
447c89b4642SGuokai Chen    when (io.s3_cancel) {
448c89b4642SGuokai Chen      // recovery of all related pointers
449c89b4642SGuokai Chen      TOSR := io.s3_meta.TOSR
450c89b4642SGuokai Chen      TOSW := io.s3_meta.TOSW
451c89b4642SGuokai Chen      ssp := io.s3_meta.ssp
452c89b4642SGuokai Chen      sctr := io.s3_meta.sctr
453c89b4642SGuokai Chen
454c89b4642SGuokai Chen      // for missing pop, we also need to do a pop here
455c89b4642SGuokai Chen      when (io.s3_missed_pop) {
456c89b4642SGuokai Chen        specPop(io.s3_meta.ssp, io.s3_meta.sctr, io.s3_meta.TOSR, io.s3_meta.TOSW, io.s3_meta.NOS)
457c89b4642SGuokai Chen      }
458c89b4642SGuokai Chen      when (io.s3_missed_push) {
459c89b4642SGuokai Chen        // do not use any bypass from f2
460c89b4642SGuokai Chen        specPush(io.s3_pushAddr, io.s3_meta.ssp, io.s3_meta.sctr, io.s3_meta.TOSR, io.s3_meta.TOSW, s3TopEntry)
461c89b4642SGuokai Chen      }
462c89b4642SGuokai Chen    }
463c89b4642SGuokai Chen
464c89b4642SGuokai Chen    val commitTop = commit_stack(nsp)
465c89b4642SGuokai Chen
466c89b4642SGuokai Chen    when (io.commit_pop_valid) {
467c89b4642SGuokai Chen
468c89b4642SGuokai Chen      val nsp_update = Wire(UInt(log2Up(rasSize).W))
469c89b4642SGuokai Chen      when (io.commit_meta_ssp =/= nsp) {
470c89b4642SGuokai Chen        // force set nsp to commit ssp to avoid permanent errors
471c89b4642SGuokai Chen        nsp_update := io.commit_meta_ssp
472c89b4642SGuokai Chen      } .otherwise {
473c89b4642SGuokai Chen        nsp_update := nsp
474c89b4642SGuokai Chen      }
475c89b4642SGuokai Chen
476c89b4642SGuokai Chen      // if ctr > 0, --ctr in stack, otherwise --nsp
477c89b4642SGuokai Chen      when (commitTop.ctr > 0.U) {
478c89b4642SGuokai Chen        commit_stack(nsp_update).ctr := commitTop.ctr - 1.U
479c89b4642SGuokai Chen        nsp := nsp_update
480c89b4642SGuokai Chen      } .otherwise {
481c89b4642SGuokai Chen        nsp := ptrDec(nsp_update);
482c89b4642SGuokai Chen      }
483c89b4642SGuokai Chen      // XSError(io.commit_meta_ssp =/= nsp, "nsp mismatch with expected ssp")
484c89b4642SGuokai Chen    }
485c89b4642SGuokai Chen
486c89b4642SGuokai Chen    val commit_push_addr = spec_queue(io.commit_meta_TOSW.value).retAddr
487c89b4642SGuokai Chen
488c89b4642SGuokai Chen
489c89b4642SGuokai Chen
490c89b4642SGuokai Chen    when (io.commit_push_valid) {
491c89b4642SGuokai Chen      val nsp_update = Wire(UInt(log2Up(rasSize).W))
492c89b4642SGuokai Chen      when (io.commit_meta_ssp =/= nsp) {
493c89b4642SGuokai Chen        // force set nsp to commit ssp to avoid permanent errors
494c89b4642SGuokai Chen        nsp_update := io.commit_meta_ssp
495c89b4642SGuokai Chen      } .otherwise {
496c89b4642SGuokai Chen        nsp_update := nsp
497c89b4642SGuokai Chen      }
498c89b4642SGuokai Chen      // if ctr < max && topAddr == push addr, ++ctr, otherwise ++nsp
499c89b4642SGuokai Chen      when (commitTop.ctr < ctrMax && commitTop.retAddr === commit_push_addr) {
500c89b4642SGuokai Chen        commit_stack(nsp_update).ctr := commitTop.ctr + 1.U
501c89b4642SGuokai Chen        nsp := nsp_update
502c89b4642SGuokai Chen      } .otherwise {
503c89b4642SGuokai Chen        nsp := ptrInc(nsp_update)
504c89b4642SGuokai Chen        commit_stack(ptrInc(nsp_update)).retAddr := commit_push_addr
505c89b4642SGuokai Chen        commit_stack(ptrInc(nsp_update)).ctr := 0.U
506c89b4642SGuokai Chen      }
507c89b4642SGuokai Chen      // when overflow, BOS may be forced move forward, do not revert those changes
508c89b4642SGuokai Chen      when (!spec_overflowed || isAfter(specPtrInc(io.commit_meta_TOSW), BOS)) {
509c89b4642SGuokai Chen        BOS := specPtrInc(io.commit_meta_TOSW)
510c89b4642SGuokai Chen        spec_overflowed := false.B
511c89b4642SGuokai Chen      }
512c89b4642SGuokai Chen
513c89b4642SGuokai Chen      // XSError(io.commit_meta_ssp =/= nsp, "nsp mismatch with expected ssp")
514c89b4642SGuokai Chen      // XSError(io.commit_push_addr =/= commit_push_addr, "addr from commit mismatch with addr from spec")
515c89b4642SGuokai Chen    }
516c89b4642SGuokai Chen
517c89b4642SGuokai Chen    when (io.redirect_valid) {
518c89b4642SGuokai Chen      TOSR := io.redirect_meta_TOSR
519c89b4642SGuokai Chen      TOSW := io.redirect_meta_TOSW
520c89b4642SGuokai Chen      ssp := io.redirect_meta_ssp
521c89b4642SGuokai Chen      sctr := io.redirect_meta_sctr
522c89b4642SGuokai Chen
523c89b4642SGuokai Chen      when (io.redirect_isCall) {
524c89b4642SGuokai Chen        specPush(io.redirect_callAddr, io.redirect_meta_ssp, io.redirect_meta_sctr, io.redirect_meta_TOSR, io.redirect_meta_TOSW, redirectTopEntry)
525c89b4642SGuokai Chen      }
526c89b4642SGuokai Chen      when (io.redirect_isRet) {
527c89b4642SGuokai Chen        specPop(io.redirect_meta_ssp, io.redirect_meta_sctr, io.redirect_meta_TOSR, io.redirect_meta_TOSW, redirectTopNos)
528c89b4642SGuokai Chen      }
529c89b4642SGuokai Chen    }
530c89b4642SGuokai Chen
531c89b4642SGuokai Chen    io.debug.commit_stack.zipWithIndex.foreach{case (a, i) => a := commit_stack(i)}
532c89b4642SGuokai Chen    io.debug.spec_nos.zipWithIndex.foreach{case (a, i) => a := spec_nos(i)}
533c89b4642SGuokai Chen    io.debug.spec_queue.zipWithIndex.foreach{ case (a, i) => a := spec_queue(i)}
534c89b4642SGuokai Chen  }
535c89b4642SGuokai Chen
536c89b4642SGuokai Chen  val stack = Module(new RASStack(RasSize, RasSpecSize)).io
537c89b4642SGuokai Chen
538c89b4642SGuokai Chen  val s2_spec_push = WireInit(false.B)
539c89b4642SGuokai Chen  val s2_spec_pop = WireInit(false.B)
540c89b4642SGuokai Chen  val s2_full_pred = io.in.bits.resp_in(0).s2.full_pred(2)
541c89b4642SGuokai Chen  // when last inst is an rvi call, fall through address would be set to the middle of it, so an addition is needed
542c89b4642SGuokai Chen  val s2_spec_new_addr = s2_full_pred.fallThroughAddr + Mux(s2_full_pred.last_may_be_rvi_call, 2.U, 0.U)
543c89b4642SGuokai Chen  stack.spec_push_valid := s2_spec_push
544c89b4642SGuokai Chen  stack.spec_pop_valid  := s2_spec_pop
545c89b4642SGuokai Chen  stack.spec_push_addr := s2_spec_new_addr
546c89b4642SGuokai Chen
547c89b4642SGuokai Chen  // confirm that the call/ret is the taken cfi
548c89b4642SGuokai Chen  s2_spec_push := io.s2_fire(2) && s2_full_pred.hit_taken_on_call && !io.s3_redirect(2)
549c89b4642SGuokai Chen  s2_spec_pop  := io.s2_fire(2) && s2_full_pred.hit_taken_on_ret  && !io.s3_redirect(2)
550c89b4642SGuokai Chen
551c89b4642SGuokai Chen  //val s2_jalr_target = io.out.s2.full_pred.jalr_target
552c89b4642SGuokai Chen  //val s2_last_target_in = s2_full_pred.targets.last
553c89b4642SGuokai Chen  // val s2_last_target_out = io.out.s2.full_pred(2).targets.last
554c89b4642SGuokai Chen  val s2_is_jalr = s2_full_pred.is_jalr
555c89b4642SGuokai Chen  val s2_is_ret = s2_full_pred.is_ret
556c89b4642SGuokai Chen  val s2_top = stack.spec_pop_addr
557c89b4642SGuokai Chen  // assert(is_jalr && is_ret || !is_ret)
558c89b4642SGuokai Chen  when(s2_is_ret && io.ctrl.ras_enable) {
559c89b4642SGuokai Chen    io.out.s2.full_pred.map(_.jalr_target).foreach(_ := s2_top)
560c89b4642SGuokai Chen    // FIXME: should use s1 globally
561c89b4642SGuokai Chen  }
562c89b4642SGuokai Chen  //s2_last_target_out := Mux(s2_is_jalr, s2_jalr_target, s2_last_target_in)
563c89b4642SGuokai Chen  io.out.s2.full_pred.zipWithIndex.foreach{ case (a, i) =>
564c89b4642SGuokai Chen    a.targets.last := Mux(s2_is_jalr, io.out.s2.full_pred(i).jalr_target, io.in.bits.resp_in(0).s2.full_pred(i).targets.last)
565c89b4642SGuokai Chen  }
566c89b4642SGuokai Chen
567c89b4642SGuokai Chen  val s2_meta = Wire(new RASMeta)
568c89b4642SGuokai Chen  s2_meta.ssp := stack.ssp
569c89b4642SGuokai Chen  s2_meta.sctr := stack.sctr
570c89b4642SGuokai Chen  s2_meta.TOSR := stack.TOSR
571c89b4642SGuokai Chen  s2_meta.TOSW := stack.TOSW
572c89b4642SGuokai Chen  s2_meta.NOS := stack.NOS
573c89b4642SGuokai Chen
574c89b4642SGuokai Chen  val s3_top = RegEnable(stack.spec_pop_addr, io.s2_fire(2))
575c89b4642SGuokai Chen  val s3_spec_new_addr = RegEnable(s2_spec_new_addr, io.s2_fire(2))
576c89b4642SGuokai Chen
577c89b4642SGuokai Chen  // val s3_jalr_target = io.out.s3.full_pred.jalr_target
578c89b4642SGuokai Chen  // val s3_last_target_in = io.in.bits.resp_in(0).s3.full_pred(2).targets.last
579c89b4642SGuokai Chen  // val s3_last_target_out = io.out.s3.full_pred(2).targets.last
580c89b4642SGuokai Chen  val s3_is_jalr = io.in.bits.resp_in(0).s3.full_pred(2).is_jalr
581c89b4642SGuokai Chen  val s3_is_ret = io.in.bits.resp_in(0).s3.full_pred(2).is_ret
582c89b4642SGuokai Chen  // assert(is_jalr && is_ret || !is_ret)
583c89b4642SGuokai Chen  when(s3_is_ret && io.ctrl.ras_enable) {
584c89b4642SGuokai Chen    io.out.s3.full_pred.map(_.jalr_target).foreach(_ := s3_top)
585c89b4642SGuokai Chen    // FIXME: should use s1 globally
586c89b4642SGuokai Chen  }
587c89b4642SGuokai Chen  // s3_last_target_out := Mux(s3_is_jalr, s3_jalr_target, s3_last_target_in)
588c89b4642SGuokai Chen  io.out.s3.full_pred.zipWithIndex.foreach{ case (a, i) =>
589c89b4642SGuokai Chen    a.targets.last := Mux(s3_is_jalr, io.out.s3.full_pred(i).jalr_target, io.in.bits.resp_in(0).s3.full_pred(i).targets.last)
590c89b4642SGuokai Chen  }
591c89b4642SGuokai Chen
592c89b4642SGuokai Chen  val s3_pushed_in_s2 = RegEnable(s2_spec_push, io.s2_fire(2))
593c89b4642SGuokai Chen  val s3_popped_in_s2 = RegEnable(s2_spec_pop,  io.s2_fire(2))
594c89b4642SGuokai Chen  val s3_push = io.in.bits.resp_in(0).s3.full_pred(2).hit_taken_on_call
595c89b4642SGuokai Chen  val s3_pop  = io.in.bits.resp_in(0).s3.full_pred(2).hit_taken_on_ret
596c89b4642SGuokai Chen
597c89b4642SGuokai Chen  val s3_cancel = io.s3_fire(2) && (s3_pushed_in_s2 =/= s3_push || s3_popped_in_s2 =/= s3_pop)
598c89b4642SGuokai Chen  stack.s2_fire := io.s2_fire(2)
599c89b4642SGuokai Chen  stack.s3_fire := io.s3_fire(2)
600c89b4642SGuokai Chen
601c89b4642SGuokai Chen  stack.s3_cancel := s3_cancel
602c89b4642SGuokai Chen
603c89b4642SGuokai Chen  val s3_meta = RegEnable(s2_meta, io.s2_fire(2))
604c89b4642SGuokai Chen
605c89b4642SGuokai Chen  stack.s3_meta := s3_meta
606c89b4642SGuokai Chen  stack.s3_missed_pop := s3_pop && !s3_popped_in_s2
607c89b4642SGuokai Chen  stack.s3_missed_push := s3_push && !s3_pushed_in_s2
608c89b4642SGuokai Chen  stack.s3_pushAddr := s3_spec_new_addr
609c89b4642SGuokai Chen
610c89b4642SGuokai Chen  // no longer need the top Entry, but TOSR, TOSW, ssp sctr
611c89b4642SGuokai Chen  // TODO: remove related signals
612c89b4642SGuokai Chen  io.out.last_stage_spec_info.sctr  := s3_meta.sctr
613c89b4642SGuokai Chen  io.out.last_stage_spec_info.ssp := s3_meta.ssp
614c89b4642SGuokai Chen  io.out.last_stage_spec_info.TOSW := s3_meta.TOSW
615c89b4642SGuokai Chen  io.out.last_stage_spec_info.TOSR := s3_meta.TOSR
616c89b4642SGuokai Chen  io.out.last_stage_spec_info.NOS := s3_meta.NOS
617c89b4642SGuokai Chen  io.out.last_stage_spec_info.topAddr := s3_top
618c89b4642SGuokai Chen  io.out.last_stage_meta := s3_meta.asUInt
619c89b4642SGuokai Chen
620c89b4642SGuokai Chen
621*7af6acb0SEaston Man  val redirect = RegNextWithEnable(io.redirect)
622c89b4642SGuokai Chen  val do_recover = redirect.valid
623c89b4642SGuokai Chen  val recover_cfi = redirect.bits.cfiUpdate
624c89b4642SGuokai Chen
625c89b4642SGuokai Chen  val retMissPred  = do_recover && redirect.bits.level === 0.U && recover_cfi.pd.isRet
626c89b4642SGuokai Chen  val callMissPred = do_recover && redirect.bits.level === 0.U && recover_cfi.pd.isCall
627c89b4642SGuokai Chen  // when we mispredict a call, we must redo a push operation
628c89b4642SGuokai Chen  // similarly, when we mispredict a return, we should redo a pop
629c89b4642SGuokai Chen  stack.redirect_valid := do_recover
630c89b4642SGuokai Chen  stack.redirect_isCall := callMissPred
631c89b4642SGuokai Chen  stack.redirect_isRet := retMissPred
632c89b4642SGuokai Chen  stack.redirect_meta_ssp := recover_cfi.ssp
633c89b4642SGuokai Chen  stack.redirect_meta_sctr := recover_cfi.sctr
634c89b4642SGuokai Chen  stack.redirect_meta_TOSW := recover_cfi.TOSW
635c89b4642SGuokai Chen  stack.redirect_meta_TOSR := recover_cfi.TOSR
636c89b4642SGuokai Chen  stack.redirect_meta_NOS := recover_cfi.NOS
637c89b4642SGuokai Chen  stack.redirect_callAddr := recover_cfi.pc + Mux(recover_cfi.pd.isRVC, 2.U, 4.U)
638c89b4642SGuokai Chen
639c89b4642SGuokai Chen  val update = io.update.bits
640c89b4642SGuokai Chen  val updateMeta = io.update.bits.meta.asTypeOf(new RASMeta)
641c89b4642SGuokai Chen  val updateValid = io.update.valid
642c89b4642SGuokai Chen
643c89b4642SGuokai Chen  stack.commit_push_valid := updateValid && update.is_call_taken
644c89b4642SGuokai Chen  stack.commit_pop_valid := updateValid && update.is_ret_taken
645c89b4642SGuokai Chen  stack.commit_push_addr := update.ftb_entry.getFallThrough(update.pc) + Mux(update.ftb_entry.last_may_be_rvi_call, 2.U, 0.U)
646c89b4642SGuokai Chen  stack.commit_meta_TOSW := updateMeta.TOSW
647c89b4642SGuokai Chen  stack.commit_meta_TOSR := updateMeta.TOSR
648c89b4642SGuokai Chen  stack.commit_meta_ssp := updateMeta.ssp
649c89b4642SGuokai Chen  stack.commit_meta_sctr := updateMeta.sctr
650c89b4642SGuokai Chen
651c89b4642SGuokai Chen
652c89b4642SGuokai Chen  XSPerfAccumulate("ras_s3_cancel", s3_cancel)
653c89b4642SGuokai Chen  XSPerfAccumulate("ras_redirect_recover", redirect.valid)
654c89b4642SGuokai Chen  XSPerfAccumulate("ras_s3_and_redirect_recover_at_the_same_time", s3_cancel && redirect.valid)
655c89b4642SGuokai Chen
656c89b4642SGuokai Chen
657c89b4642SGuokai Chen  val spec_debug = stack.debug
658c89b4642SGuokai Chen  XSDebug(io.s2_fire(2), "----------------RAS----------------\n")
659c89b4642SGuokai Chen  XSDebug(io.s2_fire(2), " TopRegister: 0x%x\n",stack.spec_pop_addr)
660c89b4642SGuokai Chen  XSDebug(io.s2_fire(2), "  index       addr           ctr           nos (spec part)\n")
661c89b4642SGuokai Chen  for(i <- 0 until RasSpecSize){
662c89b4642SGuokai Chen      XSDebug(io.s2_fire(2), "  (%d)   0x%x      %d       %d",i.U,spec_debug.spec_queue(i).retAddr,spec_debug.spec_queue(i).ctr, spec_debug.spec_nos(i).value)
663c89b4642SGuokai Chen      when(i.U === stack.TOSW.value){XSDebug(io.s2_fire(2), "   <----TOSW")}
664c89b4642SGuokai Chen      when(i.U === stack.TOSR.value){XSDebug(io.s2_fire(2), "   <----TOSR")}
665c89b4642SGuokai Chen      when(i.U === stack.BOS.value){XSDebug(io.s2_fire(2), "   <----BOS")}
666c89b4642SGuokai Chen      XSDebug(io.s2_fire(2), "\n")
667c89b4642SGuokai Chen  }
668c89b4642SGuokai Chen  XSDebug(io.s2_fire(2), "  index       addr           ctr   (committed part)\n")
669c89b4642SGuokai Chen  for(i <- 0 until RasSize){
670c89b4642SGuokai Chen      XSDebug(io.s2_fire(2), "  (%d)   0x%x      %d",i.U,spec_debug.commit_stack(i).retAddr,spec_debug.commit_stack(i).ctr)
671c89b4642SGuokai Chen      when(i.U === stack.ssp){XSDebug(io.s2_fire(2), "   <----ssp")}
672c89b4642SGuokai Chen      when(i.U === stack.nsp){XSDebug(io.s2_fire(2), "   <----nsp")}
673c89b4642SGuokai Chen      XSDebug(io.s2_fire(2), "\n")
674c89b4642SGuokai Chen  }
675c89b4642SGuokai Chen  /*
676c89b4642SGuokai Chen  XSDebug(s2_spec_push, "s2_spec_push  inAddr: 0x%x  inCtr: %d |  allocNewEntry:%d |   sp:%d \n",
677c89b4642SGuokai Chen  s2_spec_new_addr,spec_debug.spec_push_entry.ctr,spec_debug.spec_alloc_new,spec_debug.sp.asUInt)
678c89b4642SGuokai Chen  XSDebug(s2_spec_pop, "s2_spec_pop  outAddr: 0x%x \n",io.out.s2.getTarget)
679c89b4642SGuokai Chen  val s3_recover_entry = spec_debug.recover_push_entry
680c89b4642SGuokai Chen  XSDebug(s3_recover && s3_push, "s3_recover_push  inAddr: 0x%x  inCtr: %d |  allocNewEntry:%d |   sp:%d \n",
681c89b4642SGuokai Chen    s3_recover_entry.retAddr, s3_recover_entry.ctr, spec_debug.recover_alloc_new, s3_sp.asUInt)
682c89b4642SGuokai Chen  XSDebug(s3_recover && s3_pop, "s3_recover_pop  outAddr: 0x%x \n",io.out.s3.getTarget)
683c89b4642SGuokai Chen  val redirectUpdate = redirect.bits.cfiUpdate
684c89b4642SGuokai Chen  XSDebug(do_recover && callMissPred, "redirect_recover_push\n")
685c89b4642SGuokai Chen  XSDebug(do_recover && retMissPred, "redirect_recover_pop\n")
686c89b4642SGuokai Chen  XSDebug(do_recover, "redirect_recover(SP:%d retAddr:%x ctr:%d) \n",
687c89b4642SGuokai Chen      redirectUpdate.rasSp,redirectUpdate.rasEntry.retAddr,redirectUpdate.rasEntry.ctr)
688c89b4642SGuokai Chen  */
689c89b4642SGuokai Chen
690c89b4642SGuokai Chen  generatePerfEvent()
691c89b4642SGuokai Chen}
692