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