109c6f1ddSLingrui98/*************************************************************************************** 209c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 309c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory 409c6f1ddSLingrui98* 509c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2. 609c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2. 709c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at: 809c6f1ddSLingrui98* http://license.coscl.org.cn/MulanPSL2 909c6f1ddSLingrui98* 1009c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 1109c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 1209c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 1309c6f1ddSLingrui98* 1409c6f1ddSLingrui98* See the Mulan PSL v2 for more details. 15c49ebec8SHaoyuan Feng* 16c49ebec8SHaoyuan Feng* 17c49ebec8SHaoyuan Feng* Acknowledgement 18c49ebec8SHaoyuan Feng* 19c49ebec8SHaoyuan Feng* This implementation is inspired by several key papers: 20c49ebec8SHaoyuan Feng* [1] Glenn Reinman, Todd Austin, and Brad Calder. "[A scalable front-end architecture for fast instruction delivery.] 21c49ebec8SHaoyuan Feng* (https://doi.org/10.1109/ISCA.1999.765954)" 26th International Symposium on Computer Architecture (ISCA). 1999. 22c49ebec8SHaoyuan Feng* 2309c6f1ddSLingrui98***************************************************************************************/ 2409c6f1ddSLingrui98 2509c6f1ddSLingrui98package xiangshan.frontend 2609c6f1ddSLingrui98 2709c6f1ddSLingrui98import chisel3._ 2809c6f1ddSLingrui98import chisel3.util._ 29cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters 303c02ee8fSwakafaimport utility._ 31cf7d6b7aSMuziimport utility.ChiselDB 32cf7d6b7aSMuziimport utils._ 3309c6f1ddSLingrui98import xiangshan._ 341ca0e4f3SYinan Xuimport xiangshan.backend.CtrlToFtqIO 352e1be6e1SSteve Gouimport xiangshan.backend.decode.ImmUnion 36cf7d6b7aSMuziimport xiangshan.frontend.icache._ 3751532d8bSGuokai Chen 3851532d8bSGuokai Chenclass FtqDebugBundle extends Bundle { 3951532d8bSGuokai Chen val pc = UInt(39.W) 4051532d8bSGuokai Chen val target = UInt(39.W) 4151532d8bSGuokai Chen val isBr = Bool() 4251532d8bSGuokai Chen val isJmp = Bool() 4351532d8bSGuokai Chen val isCall = Bool() 4451532d8bSGuokai Chen val isRet = Bool() 4551532d8bSGuokai Chen val misPred = Bool() 4651532d8bSGuokai Chen val isTaken = Bool() 4751532d8bSGuokai Chen val predStage = UInt(2.W) 4851532d8bSGuokai Chen} 4909c6f1ddSLingrui98 503b739f49SXuan Huclass FtqPtr(entries: Int) extends CircularQueuePtr[FtqPtr]( 513b739f49SXuan Hu entries 5209c6f1ddSLingrui98 ) { 533b739f49SXuan Hu def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).FtqSize) 5409c6f1ddSLingrui98} 5509c6f1ddSLingrui98 5609c6f1ddSLingrui98object FtqPtr { 5709c6f1ddSLingrui98 def apply(f: Bool, v: UInt)(implicit p: Parameters): FtqPtr = { 5809c6f1ddSLingrui98 val ptr = Wire(new FtqPtr) 5909c6f1ddSLingrui98 ptr.flag := f 6009c6f1ddSLingrui98 ptr.value := v 6109c6f1ddSLingrui98 ptr 6209c6f1ddSLingrui98 } 63cf7d6b7aSMuzi def inverse(ptr: FtqPtr)(implicit p: Parameters): FtqPtr = 6409c6f1ddSLingrui98 apply(!ptr.flag, ptr.value) 6509c6f1ddSLingrui98} 6609c6f1ddSLingrui98 6709c6f1ddSLingrui98class FtqNRSRAM[T <: Data](gen: T, numRead: Int)(implicit p: Parameters) extends XSModule { 6809c6f1ddSLingrui98 6909c6f1ddSLingrui98 val io = IO(new Bundle() { 7009c6f1ddSLingrui98 val raddr = Input(Vec(numRead, UInt(log2Up(FtqSize).W))) 7109c6f1ddSLingrui98 val ren = Input(Vec(numRead, Bool())) 7209c6f1ddSLingrui98 val rdata = Output(Vec(numRead, gen)) 7309c6f1ddSLingrui98 val waddr = Input(UInt(log2Up(FtqSize).W)) 7409c6f1ddSLingrui98 val wen = Input(Bool()) 7509c6f1ddSLingrui98 val wdata = Input(gen) 7609c6f1ddSLingrui98 }) 7709c6f1ddSLingrui98 7809c6f1ddSLingrui98 for (i <- 0 until numRead) { 79*39d55402Spengxiao val sram = Module(new SRAMTemplate(gen, FtqSize, withClockGate = true)) 8009c6f1ddSLingrui98 sram.io.r.req.valid := io.ren(i) 8109c6f1ddSLingrui98 sram.io.r.req.bits.setIdx := io.raddr(i) 8209c6f1ddSLingrui98 io.rdata(i) := sram.io.r.resp.data(0) 8309c6f1ddSLingrui98 sram.io.w.req.valid := io.wen 8409c6f1ddSLingrui98 sram.io.w.req.bits.setIdx := io.waddr 8509c6f1ddSLingrui98 sram.io.w.req.bits.data := VecInit(io.wdata) 8609c6f1ddSLingrui98 } 8709c6f1ddSLingrui98 8809c6f1ddSLingrui98} 8909c6f1ddSLingrui98 9009c6f1ddSLingrui98class Ftq_RF_Components(implicit p: Parameters) extends XSBundle with BPUUtils { 9109c6f1ddSLingrui98 val startAddr = UInt(VAddrBits.W) 92b37e4b45SLingrui98 val nextLineAddr = UInt(VAddrBits.W) 9309c6f1ddSLingrui98 val isNextMask = Vec(PredictWidth, Bool()) 94b37e4b45SLingrui98 val fallThruError = Bool() 95b37e4b45SLingrui98 // val carry = Bool() 9609c6f1ddSLingrui98 def getPc(offset: UInt) = { 9785215037SLingrui98 def getHigher(pc: UInt) = pc(VAddrBits - 1, log2Ceil(PredictWidth) + instOffsetBits + 1) 9885215037SLingrui98 def getOffset(pc: UInt) = pc(log2Ceil(PredictWidth) + instOffsetBits, instOffsetBits) 99cf7d6b7aSMuzi Cat( 100cf7d6b7aSMuzi getHigher(Mux(isNextMask(offset) && startAddr(log2Ceil(PredictWidth) + instOffsetBits), nextLineAddr, startAddr)), 101cf7d6b7aSMuzi getOffset(startAddr) + offset, 102cf7d6b7aSMuzi 0.U(instOffsetBits.W) 103cf7d6b7aSMuzi ) 10409c6f1ddSLingrui98 } 10509c6f1ddSLingrui98 def fromBranchPrediction(resp: BranchPredictionBundle) = { 106a229ab6cSLingrui98 def carryPos(addr: UInt) = addr(instOffsetBits + log2Ceil(PredictWidth) + 1) 107adc0b8dfSGuokai Chen this.startAddr := resp.pc(3) 108adc0b8dfSGuokai Chen this.nextLineAddr := resp.pc(3) + (FetchWidth * 4 * 2).U // may be broken on other configs 10909c6f1ddSLingrui98 this.isNextMask := VecInit((0 until PredictWidth).map(i => 110935edac4STang Haojin (resp.pc(3)(log2Ceil(PredictWidth), 1) +& i.U)(log2Ceil(PredictWidth)).asBool 11109c6f1ddSLingrui98 )) 112adc0b8dfSGuokai Chen this.fallThruError := resp.fallThruError(3) 11309c6f1ddSLingrui98 this 11409c6f1ddSLingrui98 } 115cf7d6b7aSMuzi override def toPrintable: Printable = 116b37e4b45SLingrui98 p"startAddr:${Hexadecimal(startAddr)}" 11709c6f1ddSLingrui98} 11809c6f1ddSLingrui98 11909c6f1ddSLingrui98class Ftq_pd_Entry(implicit p: Parameters) extends XSBundle { 12009c6f1ddSLingrui98 val brMask = Vec(PredictWidth, Bool()) 12109c6f1ddSLingrui98 val jmpInfo = ValidUndirectioned(Vec(3, Bool())) 12209c6f1ddSLingrui98 val jmpOffset = UInt(log2Ceil(PredictWidth).W) 12309c6f1ddSLingrui98 val jalTarget = UInt(VAddrBits.W) 12409c6f1ddSLingrui98 val rvcMask = Vec(PredictWidth, Bool()) 12509c6f1ddSLingrui98 def hasJal = jmpInfo.valid && !jmpInfo.bits(0) 12609c6f1ddSLingrui98 def hasJalr = jmpInfo.valid && jmpInfo.bits(0) 12709c6f1ddSLingrui98 def hasCall = jmpInfo.valid && jmpInfo.bits(1) 12809c6f1ddSLingrui98 def hasRet = jmpInfo.valid && jmpInfo.bits(2) 12909c6f1ddSLingrui98 13009c6f1ddSLingrui98 def fromPdWb(pdWb: PredecodeWritebackBundle) = { 13109c6f1ddSLingrui98 val pds = pdWb.pd 13209c6f1ddSLingrui98 this.brMask := VecInit(pds.map(pd => pd.isBr && pd.valid)) 13309c6f1ddSLingrui98 this.jmpInfo.valid := VecInit(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid)).asUInt.orR 134cf7d6b7aSMuzi this.jmpInfo.bits := ParallelPriorityMux( 135cf7d6b7aSMuzi pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid), 136cf7d6b7aSMuzi pds.map(pd => VecInit(pd.isJalr, pd.isCall, pd.isRet)) 137cf7d6b7aSMuzi ) 13809c6f1ddSLingrui98 this.jmpOffset := ParallelPriorityEncoder(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid)) 13909c6f1ddSLingrui98 this.rvcMask := VecInit(pds.map(pd => pd.isRVC)) 14009c6f1ddSLingrui98 this.jalTarget := pdWb.jalTarget 14109c6f1ddSLingrui98 } 14209c6f1ddSLingrui98 14309c6f1ddSLingrui98 def toPd(offset: UInt) = { 14409c6f1ddSLingrui98 require(offset.getWidth == log2Ceil(PredictWidth)) 14509c6f1ddSLingrui98 val pd = Wire(new PreDecodeInfo) 14609c6f1ddSLingrui98 pd.valid := true.B 14709c6f1ddSLingrui98 pd.isRVC := rvcMask(offset) 14809c6f1ddSLingrui98 val isBr = brMask(offset) 14909c6f1ddSLingrui98 val isJalr = offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(0) 15009c6f1ddSLingrui98 pd.brType := Cat(offset === jmpOffset && jmpInfo.valid, isJalr || isBr) 15109c6f1ddSLingrui98 pd.isCall := offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(1) 15209c6f1ddSLingrui98 pd.isRet := offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(2) 15309c6f1ddSLingrui98 pd 15409c6f1ddSLingrui98 } 15509c6f1ddSLingrui98} 15609c6f1ddSLingrui98 157f9c51548Sssszwicclass PrefetchPtrDB(implicit p: Parameters) extends Bundle { 158f9c51548Sssszwic val fromFtqPtr = UInt(log2Up(p(XSCoreParamsKey).FtqSize).W) 159f9c51548Sssszwic val fromIfuPtr = UInt(log2Up(p(XSCoreParamsKey).FtqSize).W) 160f9c51548Sssszwic} 16109c6f1ddSLingrui98 1623711cf36S小造xu_zhclass Ftq_Redirect_SRAMEntry(implicit p: Parameters) extends SpeculativeInfo { 163abdc3a32Sxu_zh val sc_disagree = if (!env.FPGAPlatform) Some(Vec(numBr, Bool())) else None 1643711cf36S小造xu_zh} 16509c6f1ddSLingrui98 16609c6f1ddSLingrui98class Ftq_1R_SRAMEntry(implicit p: Parameters) extends XSBundle with HasBPUConst { 16709c6f1ddSLingrui98 val meta = UInt(MaxMetaLength.W) 168deb3a97eSGao-Zeyu val ftb_entry = new FTBEntry 16909c6f1ddSLingrui98} 17009c6f1ddSLingrui98 17109c6f1ddSLingrui98class Ftq_Pred_Info(implicit p: Parameters) extends XSBundle { 17209c6f1ddSLingrui98 val target = UInt(VAddrBits.W) 17309c6f1ddSLingrui98 val cfiIndex = ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)) 17409c6f1ddSLingrui98} 17509c6f1ddSLingrui98 17609c6f1ddSLingrui98class FtqRead[T <: Data](private val gen: T)(implicit p: Parameters) extends XSBundle { 17754c6d89dSxiaofeibao-xjtu val valid = Output(Bool()) 17809c6f1ddSLingrui98 val ptr = Output(new FtqPtr) 17909c6f1ddSLingrui98 val offset = Output(UInt(log2Ceil(PredictWidth).W)) 18009c6f1ddSLingrui98 val data = Input(gen) 18154c6d89dSxiaofeibao-xjtu def apply(valid: Bool, ptr: FtqPtr, offset: UInt) = { 18254c6d89dSxiaofeibao-xjtu this.valid := valid 18309c6f1ddSLingrui98 this.ptr := ptr 18409c6f1ddSLingrui98 this.offset := offset 18509c6f1ddSLingrui98 this.data 18609c6f1ddSLingrui98 } 18709c6f1ddSLingrui98} 18809c6f1ddSLingrui98 18909c6f1ddSLingrui98class FtqToBpuIO(implicit p: Parameters) extends XSBundle { 19009c6f1ddSLingrui98 val redirect = Valid(new BranchPredictionRedirect) 19109c6f1ddSLingrui98 val update = Valid(new BranchPredictionUpdate) 19209c6f1ddSLingrui98 val enq_ptr = Output(new FtqPtr) 193fd3aa057SYuandongliang val redirctFromIFU = Output(Bool()) 19409c6f1ddSLingrui98} 19509c6f1ddSLingrui98 1962c9f4a9fSxu_zhclass BpuFlushInfo(implicit p: Parameters) extends XSBundle with HasCircularQueuePtrHelper { 19709c6f1ddSLingrui98 // when ifu pipeline is not stalled, 19809c6f1ddSLingrui98 // a packet from bpu s3 can reach f1 at most 19909c6f1ddSLingrui98 val s2 = Valid(new FtqPtr) 200cb4f77ceSLingrui98 val s3 = Valid(new FtqPtr) 201cf7d6b7aSMuzi def shouldFlushBy(src: Valid[FtqPtr], idx_to_flush: FtqPtr) = 20209c6f1ddSLingrui98 src.valid && !isAfter(src.bits, idx_to_flush) 20309c6f1ddSLingrui98 def shouldFlushByStage2(idx: FtqPtr) = shouldFlushBy(s2, idx) 204cb4f77ceSLingrui98 def shouldFlushByStage3(idx: FtqPtr) = shouldFlushBy(s3, idx) 20509c6f1ddSLingrui98} 2062c9f4a9fSxu_zh 2072c9f4a9fSxu_zhclass FtqToIfuIO(implicit p: Parameters) extends XSBundle { 2082c9f4a9fSxu_zh val req = Decoupled(new FetchRequestBundle) 2092c9f4a9fSxu_zh val redirect = Valid(new BranchPredictionRedirect) 2102c9f4a9fSxu_zh val topdown_redirect = Valid(new BranchPredictionRedirect) 2112c9f4a9fSxu_zh val flushFromBpu = new BpuFlushInfo 21209c6f1ddSLingrui98} 21309c6f1ddSLingrui98 2142c9f4a9fSxu_zhclass FtqToICacheIO(implicit p: Parameters) extends XSBundle { 215c5c5edaeSJenius // NOTE: req.bits must be prepare in T cycle 216c5c5edaeSJenius // while req.valid is set true in T + 1 cycle 217c5c5edaeSJenius val req = Decoupled(new FtqToICacheRequestBundle) 218c5c5edaeSJenius} 219c5c5edaeSJenius 2202c9f4a9fSxu_zhclass FtqToPrefetchIO(implicit p: Parameters) extends XSBundle { 221b92f8445Sssszwic val req = Decoupled(new FtqICacheInfo) 2222c9f4a9fSxu_zh val flushFromBpu = new BpuFlushInfo 223fbdb359dSMuzi val backendException = UInt(ExceptionType.width.W) 224b92f8445Sssszwic} 225b92f8445Sssszwic 22609c6f1ddSLingrui98trait HasBackendRedirectInfo extends HasXSParameter { 22709c6f1ddSLingrui98 def isLoadReplay(r: Valid[Redirect]) = r.bits.flushItself() 22809c6f1ddSLingrui98} 22909c6f1ddSLingrui98 23009c6f1ddSLingrui98class FtqToCtrlIO(implicit p: Parameters) extends XSBundle with HasBackendRedirectInfo { 231b56f947eSYinan Xu // write to backend pc mem 232b56f947eSYinan Xu val pc_mem_wen = Output(Bool()) 233f533cba7SHuSipeng val pc_mem_waddr = Output(UInt(log2Ceil(FtqSize).W)) 234b56f947eSYinan Xu val pc_mem_wdata = Output(new Ftq_RF_Components) 235873dc383SLingrui98 // newest target 2366022c595SsinceforYy val newest_entry_en = Output(Bool()) 237873dc383SLingrui98 val newest_entry_target = Output(UInt(VAddrBits.W)) 238873dc383SLingrui98 val newest_entry_ptr = Output(new FtqPtr) 23909c6f1ddSLingrui98} 24009c6f1ddSLingrui98 24109c6f1ddSLingrui98class FTBEntryGen(implicit p: Parameters) extends XSModule with HasBackendRedirectInfo with HasBPUParameter { 24209c6f1ddSLingrui98 val io = IO(new Bundle { 24309c6f1ddSLingrui98 val start_addr = Input(UInt(VAddrBits.W)) 24409c6f1ddSLingrui98 val old_entry = Input(new FTBEntry) 24509c6f1ddSLingrui98 val pd = Input(new Ftq_pd_Entry) 24609c6f1ddSLingrui98 val cfiIndex = Flipped(Valid(UInt(log2Ceil(PredictWidth).W))) 24709c6f1ddSLingrui98 val target = Input(UInt(VAddrBits.W)) 24809c6f1ddSLingrui98 val hit = Input(Bool()) 24909c6f1ddSLingrui98 val mispredict_vec = Input(Vec(PredictWidth, Bool())) 25009c6f1ddSLingrui98 25109c6f1ddSLingrui98 val new_entry = Output(new FTBEntry) 25209c6f1ddSLingrui98 val new_br_insert_pos = Output(Vec(numBr, Bool())) 25309c6f1ddSLingrui98 val taken_mask = Output(Vec(numBr, Bool())) 254803124a6SLingrui98 val jmp_taken = Output(Bool()) 25509c6f1ddSLingrui98 val mispred_mask = Output(Vec(numBr + 1, Bool())) 25609c6f1ddSLingrui98 25709c6f1ddSLingrui98 // for perf counters 25809c6f1ddSLingrui98 val is_init_entry = Output(Bool()) 25909c6f1ddSLingrui98 val is_old_entry = Output(Bool()) 26009c6f1ddSLingrui98 val is_new_br = Output(Bool()) 26109c6f1ddSLingrui98 val is_jalr_target_modified = Output(Bool()) 262dcf4211fSYuandongliang val is_strong_bias_modified = Output(Bool()) 26309c6f1ddSLingrui98 val is_br_full = Output(Bool()) 26409c6f1ddSLingrui98 }) 26509c6f1ddSLingrui98 26609c6f1ddSLingrui98 // no mispredictions detected at predecode 26709c6f1ddSLingrui98 val hit = io.hit 26809c6f1ddSLingrui98 val pd = io.pd 26909c6f1ddSLingrui98 27009c6f1ddSLingrui98 val init_entry = WireInit(0.U.asTypeOf(new FTBEntry)) 27109c6f1ddSLingrui98 27209c6f1ddSLingrui98 val cfi_is_br = pd.brMask(io.cfiIndex.bits) && io.cfiIndex.valid 27309c6f1ddSLingrui98 val entry_has_jmp = pd.jmpInfo.valid 27409c6f1ddSLingrui98 val new_jmp_is_jal = entry_has_jmp && !pd.jmpInfo.bits(0) && io.cfiIndex.valid 27509c6f1ddSLingrui98 val new_jmp_is_jalr = entry_has_jmp && pd.jmpInfo.bits(0) && io.cfiIndex.valid 27609c6f1ddSLingrui98 val new_jmp_is_call = entry_has_jmp && pd.jmpInfo.bits(1) && io.cfiIndex.valid 27709c6f1ddSLingrui98 val new_jmp_is_ret = entry_has_jmp && pd.jmpInfo.bits(2) && io.cfiIndex.valid 27809c6f1ddSLingrui98 val last_jmp_rvi = entry_has_jmp && pd.jmpOffset === (PredictWidth - 1).U && !pd.rvcMask.last 279a60a2901SLingrui98 // val last_br_rvi = cfi_is_br && io.cfiIndex.bits === (PredictWidth-1).U && !pd.rvcMask.last 28009c6f1ddSLingrui98 28109c6f1ddSLingrui98 val cfi_is_jal = io.cfiIndex.bits === pd.jmpOffset && new_jmp_is_jal 28209c6f1ddSLingrui98 val cfi_is_jalr = io.cfiIndex.bits === pd.jmpOffset && new_jmp_is_jalr 28309c6f1ddSLingrui98 284a60a2901SLingrui98 def carryPos = log2Ceil(PredictWidth) + instOffsetBits 28509c6f1ddSLingrui98 def getLower(pc: UInt) = pc(carryPos - 1, instOffsetBits) 28609c6f1ddSLingrui98 // if not hit, establish a new entry 28709c6f1ddSLingrui98 init_entry.valid := true.B 28809c6f1ddSLingrui98 // tag is left for ftb to assign 289eeb5ff92SLingrui98 290eeb5ff92SLingrui98 // case br 291eeb5ff92SLingrui98 val init_br_slot = init_entry.getSlotForBr(0) 292eeb5ff92SLingrui98 when(cfi_is_br) { 293eeb5ff92SLingrui98 init_br_slot.valid := true.B 294eeb5ff92SLingrui98 init_br_slot.offset := io.cfiIndex.bits 295b37e4b45SLingrui98 init_br_slot.setLowerStatByTarget(io.start_addr, io.target, numBr == 1) 296dcf4211fSYuandongliang init_entry.strong_bias(0) := true.B // set to strong bias on init 297eeb5ff92SLingrui98 } 298eeb5ff92SLingrui98 299eeb5ff92SLingrui98 // case jmp 300eeb5ff92SLingrui98 when(entry_has_jmp) { 301eeb5ff92SLingrui98 init_entry.tailSlot.offset := pd.jmpOffset 302eeb5ff92SLingrui98 init_entry.tailSlot.valid := new_jmp_is_jal || new_jmp_is_jalr 303eeb5ff92SLingrui98 init_entry.tailSlot.setLowerStatByTarget(io.start_addr, Mux(cfi_is_jalr, io.target, pd.jalTarget), isShare = false) 304dcf4211fSYuandongliang init_entry.strong_bias(numBr - 1) := new_jmp_is_jalr // set strong bias for the jalr on init 305eeb5ff92SLingrui98 } 306eeb5ff92SLingrui98 30709c6f1ddSLingrui98 val jmpPft = getLower(io.start_addr) +& pd.jmpOffset +& Mux(pd.rvcMask(pd.jmpOffset), 1.U, 2.U) 308a60a2901SLingrui98 init_entry.pftAddr := Mux(entry_has_jmp && !last_jmp_rvi, jmpPft, getLower(io.start_addr)) 309a60a2901SLingrui98 init_entry.carry := Mux(entry_has_jmp && !last_jmp_rvi, jmpPft(carryPos - instOffsetBits), true.B) 31009c6f1ddSLingrui98 init_entry.isJalr := new_jmp_is_jalr 31109c6f1ddSLingrui98 init_entry.isCall := new_jmp_is_call 31209c6f1ddSLingrui98 init_entry.isRet := new_jmp_is_ret 313f4ebc4b2SLingrui98 // that means fall thru points to the middle of an inst 314ae409b75SSteve Gou init_entry.last_may_be_rvi_call := pd.jmpOffset === (PredictWidth - 1).U && !pd.rvcMask(pd.jmpOffset) 31509c6f1ddSLingrui98 31609c6f1ddSLingrui98 // if hit, check whether a new cfi(only br is possible) is detected 31709c6f1ddSLingrui98 val oe = io.old_entry 318eeb5ff92SLingrui98 val br_recorded_vec = oe.getBrRecordedVec(io.cfiIndex.bits) 31909c6f1ddSLingrui98 val br_recorded = br_recorded_vec.asUInt.orR 32009c6f1ddSLingrui98 val is_new_br = cfi_is_br && !br_recorded 32109c6f1ddSLingrui98 val new_br_offset = io.cfiIndex.bits 32209c6f1ddSLingrui98 // vec(i) means new br will be inserted BEFORE old br(i) 323eeb5ff92SLingrui98 val allBrSlotsVec = oe.allSlotsForBr 32409c6f1ddSLingrui98 val new_br_insert_onehot = VecInit((0 until numBr).map { 325cf7d6b7aSMuzi i => 326cf7d6b7aSMuzi i match { 327eeb5ff92SLingrui98 case 0 => 328eeb5ff92SLingrui98 !allBrSlotsVec(0).valid || new_br_offset < allBrSlotsVec(0).offset 329eeb5ff92SLingrui98 case idx => 330eeb5ff92SLingrui98 allBrSlotsVec(idx - 1).valid && new_br_offset > allBrSlotsVec(idx - 1).offset && 331eeb5ff92SLingrui98 (!allBrSlotsVec(idx).valid || new_br_offset < allBrSlotsVec(idx).offset) 33209c6f1ddSLingrui98 } 33309c6f1ddSLingrui98 }) 33409c6f1ddSLingrui98 33509c6f1ddSLingrui98 val old_entry_modified = WireInit(io.old_entry) 33609c6f1ddSLingrui98 for (i <- 0 until numBr) { 337eeb5ff92SLingrui98 val slot = old_entry_modified.allSlotsForBr(i) 338eeb5ff92SLingrui98 when(new_br_insert_onehot(i)) { 339eeb5ff92SLingrui98 slot.valid := true.B 340eeb5ff92SLingrui98 slot.offset := new_br_offset 341b37e4b45SLingrui98 slot.setLowerStatByTarget(io.start_addr, io.target, i == numBr - 1) 342dcf4211fSYuandongliang old_entry_modified.strong_bias(i) := true.B 343eeb5ff92SLingrui98 }.elsewhen(new_br_offset > oe.allSlotsForBr(i).offset) { 344dcf4211fSYuandongliang old_entry_modified.strong_bias(i) := false.B 345eeb5ff92SLingrui98 // all other fields remain unchanged 346eeb5ff92SLingrui98 }.otherwise { 347eeb5ff92SLingrui98 // case i == 0, remain unchanged 348eeb5ff92SLingrui98 if (i != 0) { 349b37e4b45SLingrui98 val noNeedToMoveFromFormerSlot = (i == numBr - 1).B && !oe.brSlots.last.valid 350eeb5ff92SLingrui98 when(!noNeedToMoveFromFormerSlot) { 351eeb5ff92SLingrui98 slot.fromAnotherSlot(oe.allSlotsForBr(i - 1)) 352dcf4211fSYuandongliang old_entry_modified.strong_bias(i) := oe.strong_bias(i) 35309c6f1ddSLingrui98 } 354eeb5ff92SLingrui98 } 355eeb5ff92SLingrui98 } 356eeb5ff92SLingrui98 } 35709c6f1ddSLingrui98 358eeb5ff92SLingrui98 // two circumstances: 359eeb5ff92SLingrui98 // 1. oe: | br | j |, new br should be in front of j, thus addr of j should be new pft 360eeb5ff92SLingrui98 // 2. oe: | br | br |, new br could be anywhere between, thus new pft is the addr of either 361eeb5ff92SLingrui98 // the previous last br or the new br 362eeb5ff92SLingrui98 val may_have_to_replace = oe.noEmptySlotForNewBr 363eeb5ff92SLingrui98 val pft_need_to_change = is_new_br && may_have_to_replace 36409c6f1ddSLingrui98 // it should either be the given last br or the new br 36509c6f1ddSLingrui98 when(pft_need_to_change) { 366eeb5ff92SLingrui98 val new_pft_offset = 367cf7d6b7aSMuzi Mux(!new_br_insert_onehot.asUInt.orR, new_br_offset, oe.allSlotsForBr.last.offset) 368eeb5ff92SLingrui98 369710a8720SLingrui98 // set jmp to invalid 37009c6f1ddSLingrui98 old_entry_modified.pftAddr := getLower(io.start_addr) + new_pft_offset 37109c6f1ddSLingrui98 old_entry_modified.carry := (getLower(io.start_addr) +& new_pft_offset).head(1).asBool 372f4ebc4b2SLingrui98 old_entry_modified.last_may_be_rvi_call := false.B 37309c6f1ddSLingrui98 old_entry_modified.isCall := false.B 37409c6f1ddSLingrui98 old_entry_modified.isRet := false.B 375eeb5ff92SLingrui98 old_entry_modified.isJalr := false.B 37609c6f1ddSLingrui98 } 37709c6f1ddSLingrui98 37809c6f1ddSLingrui98 val old_entry_jmp_target_modified = WireInit(oe) 379710a8720SLingrui98 val old_target = oe.tailSlot.getTarget(io.start_addr) // may be wrong because we store only 20 lowest bits 380b37e4b45SLingrui98 val old_tail_is_jmp = !oe.tailSlot.sharing 381eeb5ff92SLingrui98 val jalr_target_modified = cfi_is_jalr && (old_target =/= io.target) && old_tail_is_jmp // TODO: pass full jalr target 3823bcae573SLingrui98 when(jalr_target_modified) { 38309c6f1ddSLingrui98 old_entry_jmp_target_modified.setByJmpTarget(io.start_addr, io.target) 384dcf4211fSYuandongliang old_entry_jmp_target_modified.strong_bias := 0.U.asTypeOf(Vec(numBr, Bool())) 38509c6f1ddSLingrui98 } 38609c6f1ddSLingrui98 387dcf4211fSYuandongliang val old_entry_strong_bias = WireInit(oe) 388dcf4211fSYuandongliang val strong_bias_modified_vec = Wire(Vec(numBr, Bool())) // whether modified or not 38909c6f1ddSLingrui98 for (i <- 0 until numBr) { 390dcf4211fSYuandongliang when(br_recorded_vec(0)) { 391dcf4211fSYuandongliang old_entry_strong_bias.strong_bias(0) := 392dcf4211fSYuandongliang oe.strong_bias(0) && io.cfiIndex.valid && oe.brValids(0) && io.cfiIndex.bits === oe.brOffset(0) 393dcf4211fSYuandongliang }.elsewhen(br_recorded_vec(numBr - 1)) { 394dcf4211fSYuandongliang old_entry_strong_bias.strong_bias(0) := false.B 395dcf4211fSYuandongliang old_entry_strong_bias.strong_bias(numBr - 1) := 396dcf4211fSYuandongliang oe.strong_bias(numBr - 1) && io.cfiIndex.valid && oe.brValids(numBr - 1) && io.cfiIndex.bits === oe.brOffset( 397dcf4211fSYuandongliang numBr - 1 398dcf4211fSYuandongliang ) 39909c6f1ddSLingrui98 } 400dcf4211fSYuandongliang strong_bias_modified_vec(i) := oe.strong_bias(i) && oe.brValids(i) && !old_entry_strong_bias.strong_bias(i) 401dcf4211fSYuandongliang } 402dcf4211fSYuandongliang val strong_bias_modified = strong_bias_modified_vec.reduce(_ || _) 40309c6f1ddSLingrui98 40409c6f1ddSLingrui98 val derived_from_old_entry = 405dcf4211fSYuandongliang Mux(is_new_br, old_entry_modified, Mux(jalr_target_modified, old_entry_jmp_target_modified, old_entry_strong_bias)) 40609c6f1ddSLingrui98 40709c6f1ddSLingrui98 io.new_entry := Mux(!hit, init_entry, derived_from_old_entry) 40809c6f1ddSLingrui98 40909c6f1ddSLingrui98 io.new_br_insert_pos := new_br_insert_onehot 41009c6f1ddSLingrui98 io.taken_mask := VecInit((io.new_entry.brOffset zip io.new_entry.brValids).map { 41109c6f1ddSLingrui98 case (off, v) => io.cfiIndex.bits === off && io.cfiIndex.valid && v 41209c6f1ddSLingrui98 }) 413803124a6SLingrui98 io.jmp_taken := io.new_entry.jmpValid && io.new_entry.tailSlot.offset === io.cfiIndex.bits 41409c6f1ddSLingrui98 for (i <- 0 until numBr) { 41509c6f1ddSLingrui98 io.mispred_mask(i) := io.new_entry.brValids(i) && io.mispredict_vec(io.new_entry.brOffset(i)) 41609c6f1ddSLingrui98 } 41709c6f1ddSLingrui98 io.mispred_mask.last := io.new_entry.jmpValid && io.mispredict_vec(pd.jmpOffset) 41809c6f1ddSLingrui98 41909c6f1ddSLingrui98 // for perf counters 42009c6f1ddSLingrui98 io.is_init_entry := !hit 421dcf4211fSYuandongliang io.is_old_entry := hit && !is_new_br && !jalr_target_modified && !strong_bias_modified 42209c6f1ddSLingrui98 io.is_new_br := hit && is_new_br 4233bcae573SLingrui98 io.is_jalr_target_modified := hit && jalr_target_modified 424dcf4211fSYuandongliang io.is_strong_bias_modified := hit && strong_bias_modified 425eeb5ff92SLingrui98 io.is_br_full := hit && is_new_br && may_have_to_replace 42609c6f1ddSLingrui98} 42709c6f1ddSLingrui98 428c5c5edaeSJeniusclass FtqPcMemWrapper(numOtherReads: Int)(implicit p: Parameters) extends XSModule with HasBackendRedirectInfo { 429c5c5edaeSJenius val io = IO(new Bundle { 430c5c5edaeSJenius val ifuPtr_w = Input(new FtqPtr) 431c5c5edaeSJenius val ifuPtrPlus1_w = Input(new FtqPtr) 4326bf9b30dSLingrui98 val ifuPtrPlus2_w = Input(new FtqPtr) 433b92f8445Sssszwic val pfPtr_w = Input(new FtqPtr) 434b92f8445Sssszwic val pfPtrPlus1_w = Input(new FtqPtr) 435c5c5edaeSJenius val commPtr_w = Input(new FtqPtr) 4366bf9b30dSLingrui98 val commPtrPlus1_w = Input(new FtqPtr) 437c5c5edaeSJenius val ifuPtr_rdata = Output(new Ftq_RF_Components) 438c5c5edaeSJenius val ifuPtrPlus1_rdata = Output(new Ftq_RF_Components) 4396bf9b30dSLingrui98 val ifuPtrPlus2_rdata = Output(new Ftq_RF_Components) 440b92f8445Sssszwic val pfPtr_rdata = Output(new Ftq_RF_Components) 441b92f8445Sssszwic val pfPtrPlus1_rdata = Output(new Ftq_RF_Components) 442c5c5edaeSJenius val commPtr_rdata = Output(new Ftq_RF_Components) 4436bf9b30dSLingrui98 val commPtrPlus1_rdata = Output(new Ftq_RF_Components) 444c5c5edaeSJenius 445c5c5edaeSJenius val wen = Input(Bool()) 446c5c5edaeSJenius val waddr = Input(UInt(log2Ceil(FtqSize).W)) 447c5c5edaeSJenius val wdata = Input(new Ftq_RF_Components) 448c5c5edaeSJenius }) 449c5c5edaeSJenius 4506bf9b30dSLingrui98 val num_pc_read = numOtherReads + 5 451cf7d6b7aSMuzi val mem = Module(new SyncDataModuleTemplate(new Ftq_RF_Components, FtqSize, num_pc_read, 1, "FtqPC")) 452c5c5edaeSJenius mem.io.wen(0) := io.wen 453c5c5edaeSJenius mem.io.waddr(0) := io.waddr 454c5c5edaeSJenius mem.io.wdata(0) := io.wdata 455c5c5edaeSJenius 4566bf9b30dSLingrui98 // read one cycle ahead for ftq local reads 457cf7d6b7aSMuzi val raddr_vec = VecInit(Seq( 458cf7d6b7aSMuzi io.ifuPtr_w.value, 459cf7d6b7aSMuzi io.ifuPtrPlus1_w.value, 460cf7d6b7aSMuzi io.ifuPtrPlus2_w.value, 461cf7d6b7aSMuzi io.pfPtr_w.value, 462cf7d6b7aSMuzi io.pfPtrPlus1_w.value, 463cf7d6b7aSMuzi io.commPtrPlus1_w.value, 464cf7d6b7aSMuzi io.commPtr_w.value 465cf7d6b7aSMuzi )) 466c5c5edaeSJenius 467c5c5edaeSJenius mem.io.raddr := raddr_vec 468c5c5edaeSJenius 469b92f8445Sssszwic io.ifuPtr_rdata := mem.io.rdata.dropRight(6).last 470b92f8445Sssszwic io.ifuPtrPlus1_rdata := mem.io.rdata.dropRight(5).last 471b92f8445Sssszwic io.ifuPtrPlus2_rdata := mem.io.rdata.dropRight(4).last 472b92f8445Sssszwic io.pfPtr_rdata := mem.io.rdata.dropRight(3).last 473b92f8445Sssszwic io.pfPtrPlus1_rdata := mem.io.rdata.dropRight(2).last 4746bf9b30dSLingrui98 io.commPtrPlus1_rdata := mem.io.rdata.dropRight(1).last 475c5c5edaeSJenius io.commPtr_rdata := mem.io.rdata.last 476c5c5edaeSJenius} 477c5c5edaeSJenius 47809c6f1ddSLingrui98class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper 479e30430c2SJay with HasBackendRedirectInfo with BPUUtils with HasBPUConst with HasPerfEvents 480e30430c2SJay with HasICacheParameters { 48109c6f1ddSLingrui98 val io = IO(new Bundle { 48209c6f1ddSLingrui98 val fromBpu = Flipped(new BpuToFtqIO) 48309c6f1ddSLingrui98 val fromIfu = Flipped(new IfuToFtqIO) 48409c6f1ddSLingrui98 val fromBackend = Flipped(new CtrlToFtqIO) 48509c6f1ddSLingrui98 48609c6f1ddSLingrui98 val toBpu = new FtqToBpuIO 48709c6f1ddSLingrui98 val toIfu = new FtqToIfuIO 488c5c5edaeSJenius val toICache = new FtqToICacheIO 48909c6f1ddSLingrui98 val toBackend = new FtqToCtrlIO 490b92f8445Sssszwic val toPrefetch = new FtqToPrefetchIO 491b92f8445Sssszwic val icacheFlush = Output(Bool()) 4927052722fSJay 49309c6f1ddSLingrui98 val bpuInfo = new Bundle { 49409c6f1ddSLingrui98 val bpRight = Output(UInt(XLEN.W)) 49509c6f1ddSLingrui98 val bpWrong = Output(UInt(XLEN.W)) 49609c6f1ddSLingrui98 } 4971d1e6d4dSJenius 4981d1e6d4dSJenius val mmioCommitRead = Flipped(new mmioCommitRead) 499d2b20d1aSTang Haojin 500d2b20d1aSTang Haojin // for perf 501d2b20d1aSTang Haojin val ControlBTBMissBubble = Output(Bool()) 502d2b20d1aSTang Haojin val TAGEMissBubble = Output(Bool()) 503d2b20d1aSTang Haojin val SCMissBubble = Output(Bool()) 504d2b20d1aSTang Haojin val ITTAGEMissBubble = Output(Bool()) 505d2b20d1aSTang Haojin val RASMissBubble = Output(Bool()) 50609c6f1ddSLingrui98 }) 50709c6f1ddSLingrui98 io.bpuInfo := DontCare 50809c6f1ddSLingrui98 509d2b20d1aSTang Haojin val topdown_stage = RegInit(0.U.asTypeOf(new FrontendTopDownBundle)) 510d2b20d1aSTang Haojin // only driven by clock, not valid-ready 511d2b20d1aSTang Haojin topdown_stage := io.fromBpu.resp.bits.topdown_info 512d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info := topdown_stage 513d2b20d1aSTang Haojin 514d2b20d1aSTang Haojin val ifuRedirected = RegInit(VecInit(Seq.fill(FtqSize)(false.B))) 515d2b20d1aSTang Haojin 51642dddaceSXuan Hu // io.fromBackend.ftqIdxAhead: bju(BjuCnt) + ldReplay + exception 51742dddaceSXuan Hu val ftqIdxAhead = VecInit(Seq.tabulate(FtqRedirectAheadNum)(i => io.fromBackend.ftqIdxAhead(i))) // only bju 51842dddaceSXuan Hu val ftqIdxSelOH = io.fromBackend.ftqIdxSelOH.bits(FtqRedirectAheadNum - 1, 0) 519bace178aSGao-Zeyu 520bace178aSGao-Zeyu val aheadValid = ftqIdxAhead.map(_.valid).reduce(_ | _) && !io.fromBackend.redirect.valid 521bace178aSGao-Zeyu val realAhdValid = io.fromBackend.redirect.valid && (ftqIdxSelOH > 0.U) && RegNext(aheadValid) 522d2b20d1aSTang Haojin val backendRedirect = Wire(Valid(new BranchPredictionRedirect)) 5231c6fc24aSEaston Man val backendRedirectReg = Wire(Valid(new BranchPredictionRedirect)) 5241c6fc24aSEaston Man backendRedirectReg.valid := RegNext(Mux(realAhdValid, false.B, backendRedirect.valid)) 5251c6fc24aSEaston Man backendRedirectReg.bits := RegEnable(backendRedirect.bits, backendRedirect.valid) 526bace178aSGao-Zeyu val fromBackendRedirect = Wire(Valid(new BranchPredictionRedirect)) 527bace178aSGao-Zeyu fromBackendRedirect := Mux(realAhdValid, backendRedirect, backendRedirectReg) 52809c6f1ddSLingrui98 529df5b4b8eSYinan Xu val stage2Flush = backendRedirect.valid 53009c6f1ddSLingrui98 val backendFlush = stage2Flush || RegNext(stage2Flush) 53109c6f1ddSLingrui98 val ifuFlush = Wire(Bool()) 53209c6f1ddSLingrui98 53309c6f1ddSLingrui98 val flush = stage2Flush || RegNext(stage2Flush) 53409c6f1ddSLingrui98 53509c6f1ddSLingrui98 val allowBpuIn, allowToIfu = WireInit(false.B) 53609c6f1ddSLingrui98 val flushToIfu = !allowToIfu 537bace178aSGao-Zeyu allowBpuIn := !ifuFlush && !backendRedirect.valid && !backendRedirectReg.valid 538bace178aSGao-Zeyu allowToIfu := !ifuFlush && !backendRedirect.valid && !backendRedirectReg.valid 53909c6f1ddSLingrui98 540f56177cbSJenius def copyNum = 5 541b92f8445Sssszwic val bpuPtr, ifuPtr, pfPtr, ifuWbPtr, commPtr, robCommPtr = RegInit(FtqPtr(false.B, 0.U)) 542c9bc5480SLingrui98 val ifuPtrPlus1 = RegInit(FtqPtr(false.B, 1.U)) 5436bf9b30dSLingrui98 val ifuPtrPlus2 = RegInit(FtqPtr(false.B, 2.U)) 544b92f8445Sssszwic val pfPtrPlus1 = RegInit(FtqPtr(false.B, 1.U)) 5456bf9b30dSLingrui98 val commPtrPlus1 = RegInit(FtqPtr(false.B, 1.U)) 546f56177cbSJenius val copied_ifu_ptr = Seq.fill(copyNum)(RegInit(FtqPtr(false.B, 0.U))) 547dc270d3bSJenius val copied_bpu_ptr = Seq.fill(copyNum)(RegInit(FtqPtr(false.B, 0.U))) 5486bf9b30dSLingrui98 require(FtqSize >= 4) 549c5c5edaeSJenius val ifuPtr_write = WireInit(ifuPtr) 550c5c5edaeSJenius val ifuPtrPlus1_write = WireInit(ifuPtrPlus1) 5516bf9b30dSLingrui98 val ifuPtrPlus2_write = WireInit(ifuPtrPlus2) 552b92f8445Sssszwic val pfPtr_write = WireInit(pfPtr) 553b92f8445Sssszwic val pfPtrPlus1_write = WireInit(pfPtrPlus1) 554c5c5edaeSJenius val ifuWbPtr_write = WireInit(ifuWbPtr) 555c5c5edaeSJenius val commPtr_write = WireInit(commPtr) 5566bf9b30dSLingrui98 val commPtrPlus1_write = WireInit(commPtrPlus1) 55789cc69c1STang Haojin val robCommPtr_write = WireInit(robCommPtr) 558c5c5edaeSJenius ifuPtr := ifuPtr_write 559c5c5edaeSJenius ifuPtrPlus1 := ifuPtrPlus1_write 5606bf9b30dSLingrui98 ifuPtrPlus2 := ifuPtrPlus2_write 561b92f8445Sssszwic pfPtr := pfPtr_write 562b92f8445Sssszwic pfPtrPlus1 := pfPtrPlus1_write 563c5c5edaeSJenius ifuWbPtr := ifuWbPtr_write 564c5c5edaeSJenius commPtr := commPtr_write 565f83ef67eSLingrui98 commPtrPlus1 := commPtrPlus1_write 566f56177cbSJenius copied_ifu_ptr.map { ptr => 567f56177cbSJenius ptr := ifuPtr_write 568f56177cbSJenius dontTouch(ptr) 569f56177cbSJenius } 57089cc69c1STang Haojin robCommPtr := robCommPtr_write 57109c6f1ddSLingrui98 val validEntries = distanceBetween(bpuPtr, commPtr) 57243aca6c2SGuokai Chen val canCommit = Wire(Bool()) 57309c6f1ddSLingrui98 574c1b28b66STang Haojin // Instruction page fault and instruction access fault are sent from backend with redirect requests. 575c1b28b66STang Haojin // When IPF and IAF are sent, backendPcFaultIfuPtr points to the FTQ entry whose first instruction 576c1b28b66STang Haojin // raises IPF or IAF, which is ifuWbPtr_write or IfuPtr_write. 577c1b28b66STang Haojin // Only when IFU has written back that FTQ entry can backendIpf and backendIaf be false because this 578c1b28b66STang Haojin // makes sure that IAF and IPF are correctly raised instead of being flushed by redirect requests. 579fbdb359dSMuzi val backendException = RegInit(ExceptionType.none) 580c1b28b66STang Haojin val backendPcFaultPtr = RegInit(FtqPtr(false.B, 0.U)) 581c1b28b66STang Haojin when(fromBackendRedirect.valid) { 582fbdb359dSMuzi backendException := ExceptionType.fromOH( 583fbdb359dSMuzi has_pf = fromBackendRedirect.bits.cfiUpdate.backendIPF, 584fbdb359dSMuzi has_gpf = fromBackendRedirect.bits.cfiUpdate.backendIGPF, 585fbdb359dSMuzi has_af = fromBackendRedirect.bits.cfiUpdate.backendIAF 586fbdb359dSMuzi ) 587cf7d6b7aSMuzi when( 588fbdb359dSMuzi fromBackendRedirect.bits.cfiUpdate.backendIPF || fromBackendRedirect.bits.cfiUpdate.backendIGPF || 589fbdb359dSMuzi fromBackendRedirect.bits.cfiUpdate.backendIAF 590cf7d6b7aSMuzi ) { 591c1b28b66STang Haojin backendPcFaultPtr := ifuWbPtr_write 592c1b28b66STang Haojin } 593c1b28b66STang Haojin }.elsewhen(ifuWbPtr =/= backendPcFaultPtr) { 594fbdb359dSMuzi backendException := ExceptionType.none 595c1b28b66STang Haojin } 596c1b28b66STang Haojin 59709c6f1ddSLingrui98 // ********************************************************************** 59809c6f1ddSLingrui98 // **************************** enq from bpu **************************** 59909c6f1ddSLingrui98 // ********************************************************************** 60043aca6c2SGuokai Chen val new_entry_ready = validEntries < FtqSize.U || canCommit 60109c6f1ddSLingrui98 io.fromBpu.resp.ready := new_entry_ready 60209c6f1ddSLingrui98 60309c6f1ddSLingrui98 val bpu_s2_resp = io.fromBpu.resp.bits.s2 604cb4f77ceSLingrui98 val bpu_s3_resp = io.fromBpu.resp.bits.s3 605adc0b8dfSGuokai Chen val bpu_s2_redirect = bpu_s2_resp.valid(3) && bpu_s2_resp.hasRedirect(3) 606adc0b8dfSGuokai Chen val bpu_s3_redirect = bpu_s3_resp.valid(3) && bpu_s3_resp.hasRedirect(3) 60709c6f1ddSLingrui98 60809c6f1ddSLingrui98 io.toBpu.enq_ptr := bpuPtr 609935edac4STang Haojin val enq_fire = io.fromBpu.resp.fire && allowBpuIn // from bpu s1 610935edac4STang Haojin val bpu_in_fire = (io.fromBpu.resp.fire || bpu_s2_redirect || bpu_s3_redirect) && allowBpuIn 61109c6f1ddSLingrui98 612b37e4b45SLingrui98 val bpu_in_resp = io.fromBpu.resp.bits.selectedResp 613adc0b8dfSGuokai Chen val bpu_in_stage = io.fromBpu.resp.bits.selectedRespIdxForFtq 61409c6f1ddSLingrui98 val bpu_in_resp_ptr = Mux(bpu_in_stage === BP_S1, bpuPtr, bpu_in_resp.ftq_idx) 61509c6f1ddSLingrui98 val bpu_in_resp_idx = bpu_in_resp_ptr.value 61609c6f1ddSLingrui98 617b92f8445Sssszwic // read ports: pfReq1 + pfReq2 ++ ifuReq1 + ifuReq2 + ifuReq3 + commitUpdate2 + commitUpdate 618b92f8445Sssszwic val ftq_pc_mem = Module(new FtqPcMemWrapper(2)) 6196bf9b30dSLingrui98 // resp from uBTB 620c5c5edaeSJenius ftq_pc_mem.io.wen := bpu_in_fire 621c5c5edaeSJenius ftq_pc_mem.io.waddr := bpu_in_resp_idx 622c5c5edaeSJenius ftq_pc_mem.io.wdata.fromBranchPrediction(bpu_in_resp) 62309c6f1ddSLingrui98 62409c6f1ddSLingrui98 // ifuRedirect + backendRedirect + commit 625cf7d6b7aSMuzi val ftq_redirect_mem = Module(new SyncDataModuleTemplate( 626cf7d6b7aSMuzi new Ftq_Redirect_SRAMEntry, 627cf7d6b7aSMuzi FtqSize, 628cf7d6b7aSMuzi IfuRedirectNum + FtqRedirectAheadNum + 1, 629cf7d6b7aSMuzi 1, 630cf7d6b7aSMuzi hasRen = true 631cf7d6b7aSMuzi )) 63209c6f1ddSLingrui98 // these info is intended to enq at the last stage of bpu 633deb3a97eSGao-Zeyu ftq_redirect_mem.io.wen(0) := io.fromBpu.resp.bits.lastStage.valid(3) 634deb3a97eSGao-Zeyu ftq_redirect_mem.io.waddr(0) := io.fromBpu.resp.bits.lastStage.ftq_idx.value 635deb3a97eSGao-Zeyu ftq_redirect_mem.io.wdata(0) := io.fromBpu.resp.bits.last_stage_spec_info 636deb3a97eSGao-Zeyu println(f"ftq redirect MEM: entry ${ftq_redirect_mem.io.wdata(0).getWidth} * ${FtqSize} * 3") 63709c6f1ddSLingrui98 63809c6f1ddSLingrui98 val ftq_meta_1r_sram = Module(new FtqNRSRAM(new Ftq_1R_SRAMEntry, 1)) 63909c6f1ddSLingrui98 // these info is intended to enq at the last stage of bpu 640adc0b8dfSGuokai Chen ftq_meta_1r_sram.io.wen := io.fromBpu.resp.bits.lastStage.valid(3) 64109c6f1ddSLingrui98 ftq_meta_1r_sram.io.waddr := io.fromBpu.resp.bits.lastStage.ftq_idx.value 642c2d1ec7dSLingrui98 ftq_meta_1r_sram.io.wdata.meta := io.fromBpu.resp.bits.last_stage_meta 643deb3a97eSGao-Zeyu ftq_meta_1r_sram.io.wdata.ftb_entry := io.fromBpu.resp.bits.last_stage_ftb_entry 64495a47398SGao-Zeyu // ifuRedirect + backendRedirect (commit moved to ftq_meta_1r_sram) 645cf7d6b7aSMuzi val ftb_entry_mem = Module(new SyncDataModuleTemplate( 646cf7d6b7aSMuzi new FTBEntry_FtqMem, 647cf7d6b7aSMuzi FtqSize, 648cf7d6b7aSMuzi IfuRedirectNum + FtqRedirectAheadNum, 649cf7d6b7aSMuzi 1, 650cf7d6b7aSMuzi hasRen = true 651cf7d6b7aSMuzi )) 652adc0b8dfSGuokai Chen ftb_entry_mem.io.wen(0) := io.fromBpu.resp.bits.lastStage.valid(3) 65309c6f1ddSLingrui98 ftb_entry_mem.io.waddr(0) := io.fromBpu.resp.bits.lastStage.ftq_idx.value 654c2d1ec7dSLingrui98 ftb_entry_mem.io.wdata(0) := io.fromBpu.resp.bits.last_stage_ftb_entry 65509c6f1ddSLingrui98 65609c6f1ddSLingrui98 // multi-write 657b0ed7239SLingrui98 val update_target = Reg(Vec(FtqSize, UInt(VAddrBits.W))) // could be taken target or fallThrough //TODO: remove this 6586bf9b30dSLingrui98 val newest_entry_target = Reg(UInt(VAddrBits.W)) 6591c6fc24aSEaston Man val newest_entry_target_modified = RegInit(false.B) 6606bf9b30dSLingrui98 val newest_entry_ptr = Reg(new FtqPtr) 6611c6fc24aSEaston Man val newest_entry_ptr_modified = RegInit(false.B) 66209c6f1ddSLingrui98 val cfiIndex_vec = Reg(Vec(FtqSize, ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))) 66309c6f1ddSLingrui98 val mispredict_vec = Reg(Vec(FtqSize, Vec(PredictWidth, Bool()))) 66409c6f1ddSLingrui98 val pred_stage = Reg(Vec(FtqSize, UInt(2.W))) 665209a4cafSSteve Gou val pred_s1_cycle = if (!env.FPGAPlatform) Some(Reg(Vec(FtqSize, UInt(64.W)))) else None 66609c6f1ddSLingrui98 66791346769SMuzi val c_empty :: c_toCommit :: c_committed :: c_flushed :: Nil = Enum(4) 6681c6fc24aSEaston Man val commitStateQueueReg = RegInit(VecInit(Seq.fill(FtqSize) { 66991346769SMuzi VecInit(Seq.fill(PredictWidth)(c_empty)) 67009c6f1ddSLingrui98 })) 6711c6fc24aSEaston Man val commitStateQueueEnable = WireInit(VecInit(Seq.fill(FtqSize)(false.B))) 6721c6fc24aSEaston Man val commitStateQueueNext = WireInit(commitStateQueueReg) 6731c6fc24aSEaston Man 6741c6fc24aSEaston Man for (f <- 0 until FtqSize) { 6751c6fc24aSEaston Man when(commitStateQueueEnable(f)) { 6761c6fc24aSEaston Man commitStateQueueReg(f) := commitStateQueueNext(f) 6771c6fc24aSEaston Man } 6781c6fc24aSEaston Man } 67909c6f1ddSLingrui98 68009c6f1ddSLingrui98 val f_to_send :: f_sent :: Nil = Enum(2) 68109c6f1ddSLingrui98 val entry_fetch_status = RegInit(VecInit(Seq.fill(FtqSize)(f_sent))) 68209c6f1ddSLingrui98 68309c6f1ddSLingrui98 val h_not_hit :: h_false_hit :: h_hit :: Nil = Enum(3) 68409c6f1ddSLingrui98 val entry_hit_status = RegInit(VecInit(Seq.fill(FtqSize)(h_not_hit))) 68509c6f1ddSLingrui98 686f63797a4SLingrui98 // modify registers one cycle later to cut critical path 687f63797a4SLingrui98 val last_cycle_bpu_in = RegNext(bpu_in_fire) 6881c6fc24aSEaston Man val last_cycle_bpu_in_ptr = RegEnable(bpu_in_resp_ptr, bpu_in_fire) 6896bf9b30dSLingrui98 val last_cycle_bpu_in_idx = last_cycle_bpu_in_ptr.value 6901c6fc24aSEaston Man val last_cycle_bpu_target = RegEnable(bpu_in_resp.getTarget(3), bpu_in_fire) 6911c6fc24aSEaston Man val last_cycle_cfiIndex = RegEnable(bpu_in_resp.cfiIndex(3), bpu_in_fire) 6921c6fc24aSEaston Man val last_cycle_bpu_in_stage = RegEnable(bpu_in_stage, bpu_in_fire) 693f56177cbSJenius 6947be982afSLingrui98 def extra_copyNum_for_commitStateQueue = 2 6951c6fc24aSEaston Man val copied_last_cycle_bpu_in = 6961c6fc24aSEaston Man VecInit(Seq.fill(copyNum + extra_copyNum_for_commitStateQueue)(RegNext(bpu_in_fire))) 6971c6fc24aSEaston Man val copied_last_cycle_bpu_in_ptr_for_ftq = 6981c6fc24aSEaston Man VecInit(Seq.fill(extra_copyNum_for_commitStateQueue)(RegEnable(bpu_in_resp_ptr, bpu_in_fire))) 699f56177cbSJenius 7001c6fc24aSEaston Man newest_entry_target_modified := false.B 7011c6fc24aSEaston Man newest_entry_ptr_modified := false.B 702f63797a4SLingrui98 when(last_cycle_bpu_in) { 703f63797a4SLingrui98 entry_fetch_status(last_cycle_bpu_in_idx) := f_to_send 704f63797a4SLingrui98 cfiIndex_vec(last_cycle_bpu_in_idx) := last_cycle_cfiIndex 705f63797a4SLingrui98 pred_stage(last_cycle_bpu_in_idx) := last_cycle_bpu_in_stage 7066bf9b30dSLingrui98 707b0ed7239SLingrui98 update_target(last_cycle_bpu_in_idx) := last_cycle_bpu_target // TODO: remove this 7081c6fc24aSEaston Man newest_entry_target_modified := true.B 7096bf9b30dSLingrui98 newest_entry_target := last_cycle_bpu_target 7101c6fc24aSEaston Man newest_entry_ptr_modified := true.B 7116bf9b30dSLingrui98 newest_entry_ptr := last_cycle_bpu_in_ptr 71209c6f1ddSLingrui98 } 71309c6f1ddSLingrui98 7147be982afSLingrui98 // reduce fanout by delay write for a cycle 7157be982afSLingrui98 when(RegNext(last_cycle_bpu_in)) { 7161c6fc24aSEaston Man mispredict_vec(RegEnable(last_cycle_bpu_in_idx, last_cycle_bpu_in)) := 7171c6fc24aSEaston Man WireInit(VecInit(Seq.fill(PredictWidth)(false.B))) 7187be982afSLingrui98 } 7197be982afSLingrui98 720209a4cafSSteve Gou // record s1 pred cycles 721cf7d6b7aSMuzi pred_s1_cycle.map { vec => 722209a4cafSSteve Gou when(bpu_in_fire && (bpu_in_stage === BP_S1)) { 723209a4cafSSteve Gou vec(bpu_in_resp_ptr.value) := bpu_in_resp.full_pred(0).predCycle.getOrElse(0.U) 724209a4cafSSteve Gou } 725cf7d6b7aSMuzi } 726209a4cafSSteve Gou 7277be982afSLingrui98 // reduce fanout using copied last_cycle_bpu_in and copied last_cycle_bpu_in_ptr 7287be982afSLingrui98 val copied_last_cycle_bpu_in_for_ftq = copied_last_cycle_bpu_in.takeRight(extra_copyNum_for_commitStateQueue) 7297be982afSLingrui98 copied_last_cycle_bpu_in_for_ftq.zip(copied_last_cycle_bpu_in_ptr_for_ftq).zipWithIndex.map { 7307be982afSLingrui98 case ((in, ptr), i) => 7317be982afSLingrui98 when(in) { 7327be982afSLingrui98 val perSetEntries = FtqSize / extra_copyNum_for_commitStateQueue // 32 7337be982afSLingrui98 require(FtqSize % extra_copyNum_for_commitStateQueue == 0) 7347be982afSLingrui98 for (j <- 0 until perSetEntries) { 7359361b0c5SLingrui98 when(ptr.value === (i * perSetEntries + j).U) { 73691346769SMuzi commitStateQueueNext(i * perSetEntries + j) := VecInit(Seq.fill(PredictWidth)(c_empty)) 7371c6fc24aSEaston Man // Clock gating optimization, use 1 gate cell to control a row 7381c6fc24aSEaston Man commitStateQueueEnable(i * perSetEntries + j) := true.B 7397be982afSLingrui98 } 7407be982afSLingrui98 } 7417be982afSLingrui98 } 7429361b0c5SLingrui98 } 7437be982afSLingrui98 74409c6f1ddSLingrui98 bpuPtr := bpuPtr + enq_fire 745dc270d3bSJenius copied_bpu_ptr.map(_ := bpuPtr + enq_fire) 746c9bc5480SLingrui98 when(io.toIfu.req.fire && allowToIfu) { 747c5c5edaeSJenius ifuPtr_write := ifuPtrPlus1 7486bf9b30dSLingrui98 ifuPtrPlus1_write := ifuPtrPlus2 7496bf9b30dSLingrui98 ifuPtrPlus2_write := ifuPtrPlus2 + 1.U 750c9bc5480SLingrui98 } 751b92f8445Sssszwic when(io.toPrefetch.req.fire && allowToIfu) { 752b92f8445Sssszwic pfPtr_write := pfPtrPlus1 753b92f8445Sssszwic pfPtrPlus1_write := pfPtrPlus1 + 1.U 754b92f8445Sssszwic } 75509c6f1ddSLingrui98 75609c6f1ddSLingrui98 // only use ftb result to assign hit status 757adc0b8dfSGuokai Chen when(bpu_s2_resp.valid(3)) { 758adc0b8dfSGuokai Chen entry_hit_status(bpu_s2_resp.ftq_idx.value) := Mux(bpu_s2_resp.full_pred(3).hit, h_hit, h_not_hit) 75909c6f1ddSLingrui98 } 76009c6f1ddSLingrui98 7612f4a3aa4SLingrui98 io.toIfu.flushFromBpu.s2.valid := bpu_s2_redirect 76209c6f1ddSLingrui98 io.toIfu.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx 763b92f8445Sssszwic io.toPrefetch.flushFromBpu.s2.valid := bpu_s2_redirect 764b92f8445Sssszwic io.toPrefetch.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx 765adc0b8dfSGuokai Chen when(bpu_s2_redirect) { 76609c6f1ddSLingrui98 bpuPtr := bpu_s2_resp.ftq_idx + 1.U 767dc270d3bSJenius copied_bpu_ptr.map(_ := bpu_s2_resp.ftq_idx + 1.U) 76809c6f1ddSLingrui98 // only when ifuPtr runs ahead of bpu s2 resp should we recover it 76909c6f1ddSLingrui98 when(!isBefore(ifuPtr, bpu_s2_resp.ftq_idx)) { 770c5c5edaeSJenius ifuPtr_write := bpu_s2_resp.ftq_idx 771c5c5edaeSJenius ifuPtrPlus1_write := bpu_s2_resp.ftq_idx + 1.U 7726bf9b30dSLingrui98 ifuPtrPlus2_write := bpu_s2_resp.ftq_idx + 2.U 77309c6f1ddSLingrui98 } 774b92f8445Sssszwic when(!isBefore(pfPtr, bpu_s2_resp.ftq_idx)) { 775b92f8445Sssszwic pfPtr_write := bpu_s2_resp.ftq_idx 776b92f8445Sssszwic pfPtrPlus1_write := bpu_s2_resp.ftq_idx + 1.U 777b92f8445Sssszwic } 77809c6f1ddSLingrui98 } 77909c6f1ddSLingrui98 780cb4f77ceSLingrui98 io.toIfu.flushFromBpu.s3.valid := bpu_s3_redirect 781cb4f77ceSLingrui98 io.toIfu.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx 782b92f8445Sssszwic io.toPrefetch.flushFromBpu.s3.valid := bpu_s3_redirect 783b92f8445Sssszwic io.toPrefetch.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx 784adc0b8dfSGuokai Chen when(bpu_s3_redirect) { 785cb4f77ceSLingrui98 bpuPtr := bpu_s3_resp.ftq_idx + 1.U 786dc270d3bSJenius copied_bpu_ptr.map(_ := bpu_s3_resp.ftq_idx + 1.U) 787cb4f77ceSLingrui98 // only when ifuPtr runs ahead of bpu s2 resp should we recover it 788cb4f77ceSLingrui98 when(!isBefore(ifuPtr, bpu_s3_resp.ftq_idx)) { 789c5c5edaeSJenius ifuPtr_write := bpu_s3_resp.ftq_idx 790c5c5edaeSJenius ifuPtrPlus1_write := bpu_s3_resp.ftq_idx + 1.U 7916bf9b30dSLingrui98 ifuPtrPlus2_write := bpu_s3_resp.ftq_idx + 2.U 792cb4f77ceSLingrui98 } 793b92f8445Sssszwic when(!isBefore(pfPtr, bpu_s3_resp.ftq_idx)) { 794b92f8445Sssszwic pfPtr_write := bpu_s3_resp.ftq_idx 795b92f8445Sssszwic pfPtrPlus1_write := bpu_s3_resp.ftq_idx + 1.U 796b92f8445Sssszwic } 797cb4f77ceSLingrui98 } 798cb4f77ceSLingrui98 79909c6f1ddSLingrui98 XSError(isBefore(bpuPtr, ifuPtr) && !isFull(bpuPtr, ifuPtr), "\nifuPtr is before bpuPtr!\n") 800b92f8445Sssszwic XSError(isBefore(bpuPtr, pfPtr) && !isFull(bpuPtr, pfPtr), "\npfPtr is before bpuPtr!\n") 8012448f137SGuokai Chen XSError(isBefore(ifuWbPtr, commPtr) && !isFull(ifuWbPtr, commPtr), "\ncommPtr is before ifuWbPtr!\n") 80209c6f1ddSLingrui98 803cf7d6b7aSMuzi (0 until copyNum).map(i => XSError(copied_bpu_ptr(i) =/= bpuPtr, "\ncopiedBpuPtr is different from bpuPtr!\n")) 804dc270d3bSJenius 80509c6f1ddSLingrui98 // **************************************************************** 80609c6f1ddSLingrui98 // **************************** to ifu **************************** 80709c6f1ddSLingrui98 // **************************************************************** 808f22cf846SJenius // 0 for ifu, and 1-4 for ICache 809935edac4STang Haojin val bpu_in_bypass_buf = RegEnable(ftq_pc_mem.io.wdata, bpu_in_fire) 810935edac4STang Haojin val copied_bpu_in_bypass_buf = VecInit(Seq.fill(copyNum)(RegEnable(ftq_pc_mem.io.wdata, bpu_in_fire))) 811f56177cbSJenius val bpu_in_bypass_buf_for_ifu = bpu_in_bypass_buf 8121c6fc24aSEaston Man val bpu_in_bypass_ptr = RegEnable(bpu_in_resp_ptr, bpu_in_fire) 81309c6f1ddSLingrui98 val last_cycle_to_ifu_fire = RegNext(io.toIfu.req.fire) 814b92f8445Sssszwic val last_cycle_to_pf_fire = RegNext(io.toPrefetch.req.fire) 81509c6f1ddSLingrui98 8161c6fc24aSEaston Man val copied_bpu_in_bypass_ptr = VecInit(Seq.fill(copyNum)(RegEnable(bpu_in_resp_ptr, bpu_in_fire))) 817f56177cbSJenius val copied_last_cycle_to_ifu_fire = VecInit(Seq.fill(copyNum)(RegNext(io.toIfu.req.fire))) 81888bc4f90SLingrui98 81909c6f1ddSLingrui98 // read pc and target 8206bf9b30dSLingrui98 ftq_pc_mem.io.ifuPtr_w := ifuPtr_write 8216bf9b30dSLingrui98 ftq_pc_mem.io.ifuPtrPlus1_w := ifuPtrPlus1_write 8226bf9b30dSLingrui98 ftq_pc_mem.io.ifuPtrPlus2_w := ifuPtrPlus2_write 823b92f8445Sssszwic ftq_pc_mem.io.pfPtr_w := pfPtr_write 824b92f8445Sssszwic ftq_pc_mem.io.pfPtrPlus1_w := pfPtrPlus1_write 8256bf9b30dSLingrui98 ftq_pc_mem.io.commPtr_w := commPtr_write 8266bf9b30dSLingrui98 ftq_pc_mem.io.commPtrPlus1_w := commPtrPlus1_write 827c5c5edaeSJenius 8285ff19bd8SLingrui98 io.toIfu.req.bits.ftqIdx := ifuPtr 829f63797a4SLingrui98 830f56177cbSJenius val toICachePcBundle = Wire(Vec(copyNum, new Ftq_RF_Components)) 831dc270d3bSJenius val toICacheEntryToSend = Wire(Vec(copyNum, Bool())) 8323e1dbb17SMuzi val nextCycleToPrefetchPcBundle = Wire(new Ftq_RF_Components) 8333e1dbb17SMuzi val nextCycleToPrefetchEntryToSend = Wire(Bool()) 8343e1dbb17SMuzi val toPrefetchPcBundle = RegNext(nextCycleToPrefetchPcBundle) 8353e1dbb17SMuzi val toPrefetchEntryToSend = RegNext(nextCycleToPrefetchEntryToSend) 836b37e4b45SLingrui98 val toIfuPcBundle = Wire(new Ftq_RF_Components) 837f63797a4SLingrui98 val entry_is_to_send = WireInit(entry_fetch_status(ifuPtr.value) === f_to_send) 838f63797a4SLingrui98 val entry_ftq_offset = WireInit(cfiIndex_vec(ifuPtr.value)) 8396bf9b30dSLingrui98 val entry_next_addr = Wire(UInt(VAddrBits.W)) 840b004fa13SJenius 841f56177cbSJenius val pc_mem_ifu_ptr_rdata = VecInit(Seq.fill(copyNum)(RegNext(ftq_pc_mem.io.ifuPtr_rdata))) 842f56177cbSJenius val pc_mem_ifu_plus1_rdata = VecInit(Seq.fill(copyNum)(RegNext(ftq_pc_mem.io.ifuPtrPlus1_rdata))) 843b0ed7239SLingrui98 val diff_entry_next_addr = WireInit(update_target(ifuPtr.value)) // TODO: remove this 844f63797a4SLingrui98 845cf7d6b7aSMuzi val copied_ifu_plus1_to_send = VecInit(Seq.fill(copyNum)(RegNext( 846cf7d6b7aSMuzi entry_fetch_status(ifuPtrPlus1.value) === f_to_send 847cf7d6b7aSMuzi ) || RegNext(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtrPlus1))) 848cf7d6b7aSMuzi val copied_ifu_ptr_to_send = VecInit(Seq.fill(copyNum)(RegNext( 849cf7d6b7aSMuzi entry_fetch_status(ifuPtr.value) === f_to_send 850cf7d6b7aSMuzi ) || RegNext(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr))) 851dc270d3bSJenius 852f56177cbSJenius for (i <- 0 until copyNum) { 853f56177cbSJenius when(copied_last_cycle_bpu_in(i) && copied_bpu_in_bypass_ptr(i) === copied_ifu_ptr(i)) { 854f56177cbSJenius toICachePcBundle(i) := copied_bpu_in_bypass_buf(i) 855dc270d3bSJenius toICacheEntryToSend(i) := true.B 856f56177cbSJenius }.elsewhen(copied_last_cycle_to_ifu_fire(i)) { 857f56177cbSJenius toICachePcBundle(i) := pc_mem_ifu_plus1_rdata(i) 858dc270d3bSJenius toICacheEntryToSend(i) := copied_ifu_plus1_to_send(i) 859f56177cbSJenius }.otherwise { 860f56177cbSJenius toICachePcBundle(i) := pc_mem_ifu_ptr_rdata(i) 861dc270d3bSJenius toICacheEntryToSend(i) := copied_ifu_ptr_to_send(i) 862f56177cbSJenius } 863f56177cbSJenius } 864f56177cbSJenius 8653e1dbb17SMuzi // Calculate requests sent to prefetcher one cycle in advance to cut critical path 8663e1dbb17SMuzi when(bpu_in_fire && bpu_in_resp_ptr === pfPtr_write) { 8673e1dbb17SMuzi nextCycleToPrefetchPcBundle := ftq_pc_mem.io.wdata 8683e1dbb17SMuzi nextCycleToPrefetchEntryToSend := true.B 8693e1dbb17SMuzi }.elsewhen(io.toPrefetch.req.fire) { 8703e1dbb17SMuzi nextCycleToPrefetchPcBundle := ftq_pc_mem.io.pfPtrPlus1_rdata 8713e1dbb17SMuzi nextCycleToPrefetchEntryToSend := entry_fetch_status(pfPtrPlus1.value) === f_to_send || 8723e1dbb17SMuzi last_cycle_bpu_in && bpu_in_bypass_ptr === pfPtrPlus1 873b92f8445Sssszwic }.otherwise { 8743e1dbb17SMuzi nextCycleToPrefetchPcBundle := ftq_pc_mem.io.pfPtr_rdata 8753e1dbb17SMuzi nextCycleToPrefetchEntryToSend := entry_fetch_status(pfPtr.value) === f_to_send || 8763e1dbb17SMuzi last_cycle_bpu_in && bpu_in_bypass_ptr === pfPtr // reduce potential bubbles 877b92f8445Sssszwic } 878b92f8445Sssszwic 879873dc383SLingrui98 // TODO: reconsider target address bypass logic 88009c6f1ddSLingrui98 when(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr) { 88188bc4f90SLingrui98 toIfuPcBundle := bpu_in_bypass_buf_for_ifu 882f678dd91SSteve Gou entry_is_to_send := true.B 8836bf9b30dSLingrui98 entry_next_addr := last_cycle_bpu_target 884f63797a4SLingrui98 entry_ftq_offset := last_cycle_cfiIndex 885b0ed7239SLingrui98 diff_entry_next_addr := last_cycle_bpu_target // TODO: remove this 88609c6f1ddSLingrui98 }.elsewhen(last_cycle_to_ifu_fire) { 887c5c5edaeSJenius toIfuPcBundle := RegNext(ftq_pc_mem.io.ifuPtrPlus1_rdata) 888c5c5edaeSJenius entry_is_to_send := RegNext(entry_fetch_status(ifuPtrPlus1.value) === f_to_send) || 889cf7d6b7aSMuzi RegNext(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtrPlus1) // reduce potential bubbles 890cf7d6b7aSMuzi entry_next_addr := Mux( 891cf7d6b7aSMuzi last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtrPlus1, 89288bc4f90SLingrui98 bpu_in_bypass_buf_for_ifu.startAddr, 893cf7d6b7aSMuzi Mux(ifuPtr === newest_entry_ptr, newest_entry_target, RegNext(ftq_pc_mem.io.ifuPtrPlus2_rdata.startAddr)) 894cf7d6b7aSMuzi ) // ifuPtr+2 895c5c5edaeSJenius }.otherwise { 896c5c5edaeSJenius toIfuPcBundle := RegNext(ftq_pc_mem.io.ifuPtr_rdata) 89728f2cf58SLingrui98 entry_is_to_send := RegNext(entry_fetch_status(ifuPtr.value) === f_to_send) || 89828f2cf58SLingrui98 RegNext(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr) // reduce potential bubbles 899cf7d6b7aSMuzi entry_next_addr := Mux( 900cf7d6b7aSMuzi last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtrPlus1, 90188bc4f90SLingrui98 bpu_in_bypass_buf_for_ifu.startAddr, 902cf7d6b7aSMuzi Mux(ifuPtr === newest_entry_ptr, newest_entry_target, RegNext(ftq_pc_mem.io.ifuPtrPlus1_rdata.startAddr)) 903cf7d6b7aSMuzi ) // ifuPtr+1 90409c6f1ddSLingrui98 } 90509c6f1ddSLingrui98 906f678dd91SSteve Gou io.toIfu.req.valid := entry_is_to_send && ifuPtr =/= bpuPtr 907f63797a4SLingrui98 io.toIfu.req.bits.nextStartAddr := entry_next_addr 908f63797a4SLingrui98 io.toIfu.req.bits.ftqOffset := entry_ftq_offset 909b37e4b45SLingrui98 io.toIfu.req.bits.fromFtqPcBundle(toIfuPcBundle) 910c5c5edaeSJenius 911c5c5edaeSJenius io.toICache.req.valid := entry_is_to_send && ifuPtr =/= bpuPtr 912cf7d6b7aSMuzi io.toICache.req.bits.readValid.zipWithIndex.map { case (copy, i) => 913cf7d6b7aSMuzi copy := toICacheEntryToSend(i) && copied_ifu_ptr(i) =/= copied_bpu_ptr(i) 914cf7d6b7aSMuzi } 915b92f8445Sssszwic io.toICache.req.bits.pcMemRead.zipWithIndex.foreach { case (copy, i) => 916b92f8445Sssszwic copy.fromFtqPcBundle(toICachePcBundle(i)) 917b92f8445Sssszwic copy.ftqIdx := ifuPtr 918b92f8445Sssszwic } 919fbdb359dSMuzi io.toICache.req.bits.backendException := ExceptionType.hasException(backendException) && backendPcFaultPtr === ifuPtr 920b92f8445Sssszwic 921b92f8445Sssszwic io.toPrefetch.req.valid := toPrefetchEntryToSend && pfPtr =/= bpuPtr 922b92f8445Sssszwic io.toPrefetch.req.bits.fromFtqPcBundle(toPrefetchPcBundle) 923b92f8445Sssszwic io.toPrefetch.req.bits.ftqIdx := pfPtr 924fbdb359dSMuzi io.toPrefetch.backendException := Mux(backendPcFaultPtr === pfPtr, backendException, ExceptionType.none) 925b004fa13SJenius // io.toICache.req.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr 926b004fa13SJenius // io.toICache.req.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) => 927b004fa13SJenius // bypassWrtie.startAddr := bpu_in_bypass_buf.tail(i).startAddr 928b004fa13SJenius // bypassWrtie.nextlineStart := bpu_in_bypass_buf.tail(i).nextLineAddr 929b004fa13SJenius // } 930f22cf846SJenius 931b0ed7239SLingrui98 // TODO: remove this 932cf7d6b7aSMuzi XSError( 933cf7d6b7aSMuzi io.toIfu.req.valid && diff_entry_next_addr =/= entry_next_addr, 934cf7d6b7aSMuzi p"\nifu_req_target wrong! ifuPtr: ${ifuPtr}, entry_next_addr: ${Hexadecimal(entry_next_addr)} diff_entry_next_addr: ${Hexadecimal(diff_entry_next_addr)}\n" 935cf7d6b7aSMuzi ) 936b0ed7239SLingrui98 93709c6f1ddSLingrui98 // when fall through is smaller in value than start address, there must be a false hit 938b37e4b45SLingrui98 when(toIfuPcBundle.fallThruError && entry_hit_status(ifuPtr.value) === h_hit) { 93909c6f1ddSLingrui98 when(io.toIfu.req.fire && 940cb4f77ceSLingrui98 !(bpu_s2_redirect && bpu_s2_resp.ftq_idx === ifuPtr) && 941cf7d6b7aSMuzi !(bpu_s3_redirect && bpu_s3_resp.ftq_idx === ifuPtr)) { 94209c6f1ddSLingrui98 entry_hit_status(ifuPtr.value) := h_false_hit 943352db50aSLingrui98 // XSError(true.B, "FTB false hit by fallThroughError, startAddr: %x, fallTHru: %x\n", io.toIfu.req.bits.startAddr, io.toIfu.req.bits.nextStartAddr) 94409c6f1ddSLingrui98 } 945cf7d6b7aSMuzi XSDebug( 946cf7d6b7aSMuzi true.B, 947cf7d6b7aSMuzi "fallThruError! start:%x, fallThru:%x\n", 948cf7d6b7aSMuzi io.toIfu.req.bits.startAddr, 949cf7d6b7aSMuzi io.toIfu.req.bits.nextStartAddr 950cf7d6b7aSMuzi ) 95109c6f1ddSLingrui98 } 95209c6f1ddSLingrui98 953cf7d6b7aSMuzi XSPerfAccumulate( 954cf7d6b7aSMuzi f"fall_through_error_to_ifu", 955cf7d6b7aSMuzi toIfuPcBundle.fallThruError && entry_hit_status(ifuPtr.value) === h_hit && 956cf7d6b7aSMuzi io.toIfu.req.fire && !(bpu_s2_redirect && bpu_s2_resp.ftq_idx === ifuPtr) && !(bpu_s3_redirect && bpu_s3_resp.ftq_idx === ifuPtr) 957cf7d6b7aSMuzi ) 958a60a2901SLingrui98 95909c6f1ddSLingrui98 val ifu_req_should_be_flushed = 960cb4f77ceSLingrui98 io.toIfu.flushFromBpu.shouldFlushByStage2(io.toIfu.req.bits.ftqIdx) || 961cb4f77ceSLingrui98 io.toIfu.flushFromBpu.shouldFlushByStage3(io.toIfu.req.bits.ftqIdx) 96209c6f1ddSLingrui98 96309c6f1ddSLingrui98 when(io.toIfu.req.fire && !ifu_req_should_be_flushed) { 96409c6f1ddSLingrui98 entry_fetch_status(ifuPtr.value) := f_sent 96509c6f1ddSLingrui98 } 96609c6f1ddSLingrui98 96709c6f1ddSLingrui98 // ********************************************************************* 96809c6f1ddSLingrui98 // **************************** wb from ifu **************************** 96909c6f1ddSLingrui98 // ********************************************************************* 97009c6f1ddSLingrui98 val pdWb = io.fromIfu.pdWb 97109c6f1ddSLingrui98 val pds = pdWb.bits.pd 97209c6f1ddSLingrui98 val ifu_wb_valid = pdWb.valid 97309c6f1ddSLingrui98 val ifu_wb_idx = pdWb.bits.ftqIdx.value 97409c6f1ddSLingrui98 // read ports: commit update 975cf7d6b7aSMuzi val ftq_pd_mem = 976cf7d6b7aSMuzi Module(new SyncDataModuleTemplate(new Ftq_pd_Entry, FtqSize, FtqRedirectAheadNum + 1, 1, hasRen = true)) 97709c6f1ddSLingrui98 ftq_pd_mem.io.wen(0) := ifu_wb_valid 97809c6f1ddSLingrui98 ftq_pd_mem.io.waddr(0) := pdWb.bits.ftqIdx.value 97909c6f1ddSLingrui98 ftq_pd_mem.io.wdata(0).fromPdWb(pdWb.bits) 98009c6f1ddSLingrui98 98109c6f1ddSLingrui98 val hit_pd_valid = entry_hit_status(ifu_wb_idx) === h_hit && ifu_wb_valid 98209c6f1ddSLingrui98 val hit_pd_mispred = hit_pd_valid && pdWb.bits.misOffset.valid 98309c6f1ddSLingrui98 val hit_pd_mispred_reg = RegNext(hit_pd_mispred, init = false.B) 984005e809bSJiuyang Liu val pd_reg = RegEnable(pds, pdWb.valid) 985005e809bSJiuyang Liu val start_pc_reg = RegEnable(pdWb.bits.pc(0), pdWb.valid) 986005e809bSJiuyang Liu val wb_idx_reg = RegEnable(ifu_wb_idx, pdWb.valid) 98709c6f1ddSLingrui98 98809c6f1ddSLingrui98 when(ifu_wb_valid) { 98909c6f1ddSLingrui98 val comm_stq_wen = VecInit(pds.map(_.valid).zip(pdWb.bits.instrRange).map { 99009c6f1ddSLingrui98 case (v, inRange) => v && inRange 99109c6f1ddSLingrui98 }) 9921c6fc24aSEaston Man commitStateQueueEnable(ifu_wb_idx) := true.B 9931c6fc24aSEaston Man (commitStateQueueNext(ifu_wb_idx) zip comm_stq_wen).map { 9941c6fc24aSEaston Man case (qe, v) => when(v) { 99591346769SMuzi qe := c_toCommit 9961c6fc24aSEaston Man } 99709c6f1ddSLingrui98 } 99809c6f1ddSLingrui98 } 99909c6f1ddSLingrui98 1000c5c5edaeSJenius when(ifu_wb_valid) { 1001c5c5edaeSJenius ifuWbPtr_write := ifuWbPtr + 1.U 1002c5c5edaeSJenius } 100309c6f1ddSLingrui98 1004f21bbcb2SGuokai Chen XSError(ifu_wb_valid && isAfter(pdWb.bits.ftqIdx, ifuPtr), "IFU returned a predecode before its req, check IFU") 1005f21bbcb2SGuokai Chen 10061c6fc24aSEaston Man ftb_entry_mem.io.ren.get.head := ifu_wb_valid 100709c6f1ddSLingrui98 ftb_entry_mem.io.raddr.head := ifu_wb_idx 100809c6f1ddSLingrui98 val has_false_hit = WireInit(false.B) 100909c6f1ddSLingrui98 when(RegNext(hit_pd_valid)) { 101009c6f1ddSLingrui98 // check for false hit 101109c6f1ddSLingrui98 val pred_ftb_entry = ftb_entry_mem.io.rdata.head 1012eeb5ff92SLingrui98 val brSlots = pred_ftb_entry.brSlots 1013eeb5ff92SLingrui98 val tailSlot = pred_ftb_entry.tailSlot 101409c6f1ddSLingrui98 // we check cfis that bpu predicted 101509c6f1ddSLingrui98 1016eeb5ff92SLingrui98 // bpu predicted branches but denied by predecode 1017eeb5ff92SLingrui98 val br_false_hit = 1018eeb5ff92SLingrui98 brSlots.map { 1019eeb5ff92SLingrui98 s => s.valid && !(pd_reg(s.offset).valid && pd_reg(s.offset).isBr) 1020eeb5ff92SLingrui98 }.reduce(_ || _) || 1021b37e4b45SLingrui98 (tailSlot.valid && pred_ftb_entry.tailSlot.sharing && 1022eeb5ff92SLingrui98 !(pd_reg(tailSlot.offset).valid && pd_reg(tailSlot.offset).isBr)) 1023eeb5ff92SLingrui98 1024eeb5ff92SLingrui98 val jmpOffset = tailSlot.offset 102509c6f1ddSLingrui98 val jmp_pd = pd_reg(jmpOffset) 102609c6f1ddSLingrui98 val jal_false_hit = pred_ftb_entry.jmpValid && 102709c6f1ddSLingrui98 ((pred_ftb_entry.isJal && !(jmp_pd.valid && jmp_pd.isJal)) || 102809c6f1ddSLingrui98 (pred_ftb_entry.isJalr && !(jmp_pd.valid && jmp_pd.isJalr)) || 102909c6f1ddSLingrui98 (pred_ftb_entry.isCall && !(jmp_pd.valid && jmp_pd.isCall)) || 1030cf7d6b7aSMuzi (pred_ftb_entry.isRet && !(jmp_pd.valid && jmp_pd.isRet))) 103109c6f1ddSLingrui98 103209c6f1ddSLingrui98 has_false_hit := br_false_hit || jal_false_hit || hit_pd_mispred_reg 103365fddcf0Szoujr XSDebug(has_false_hit, "FTB false hit by br or jal or hit_pd, startAddr: %x\n", pdWb.bits.pc(0)) 103465fddcf0Szoujr 1035352db50aSLingrui98 // assert(!has_false_hit) 103609c6f1ddSLingrui98 } 103709c6f1ddSLingrui98 103809c6f1ddSLingrui98 when(has_false_hit) { 103909c6f1ddSLingrui98 entry_hit_status(wb_idx_reg) := h_false_hit 104009c6f1ddSLingrui98 } 104109c6f1ddSLingrui98 104209c6f1ddSLingrui98 // ******************************************************************************* 104309c6f1ddSLingrui98 // **************************** redirect from backend **************************** 104409c6f1ddSLingrui98 // ******************************************************************************* 104509c6f1ddSLingrui98 104609c6f1ddSLingrui98 // redirect read cfiInfo, couples to redirectGen s2 104795a47398SGao-Zeyu // ftqIdxAhead(0-3) => ftq_redirect_mem(1-4), reuse ftq_redirect_mem(1) 1048bace178aSGao-Zeyu val ftq_redirect_rdata = Wire(Vec(FtqRedirectAheadNum, new Ftq_Redirect_SRAMEntry)) 1049deb3a97eSGao-Zeyu val ftb_redirect_rdata = Wire(Vec(FtqRedirectAheadNum, new FTBEntry_FtqMem)) 1050c776f0d5Smy-mayfly 1051c776f0d5Smy-mayfly val ftq_pd_rdata = Wire(Vec(FtqRedirectAheadNum, new Ftq_pd_Entry)) 105295a47398SGao-Zeyu for (i <- 1 until FtqRedirectAheadNum) { 105395a47398SGao-Zeyu ftq_redirect_mem.io.ren.get(i + IfuRedirectNum) := ftqIdxAhead(i).valid 105495a47398SGao-Zeyu ftq_redirect_mem.io.raddr(i + IfuRedirectNum) := ftqIdxAhead(i).bits.value 105595a47398SGao-Zeyu ftb_entry_mem.io.ren.get(i + IfuRedirectNum) := ftqIdxAhead(i).valid 105695a47398SGao-Zeyu ftb_entry_mem.io.raddr(i + IfuRedirectNum) := ftqIdxAhead(i).bits.value 1057c776f0d5Smy-mayfly 1058c776f0d5Smy-mayfly ftq_pd_mem.io.ren.get(i) := ftqIdxAhead(i).valid 1059c776f0d5Smy-mayfly ftq_pd_mem.io.raddr(i) := ftqIdxAhead(i).bits.value 10609342624fSGao-Zeyu } 106195a47398SGao-Zeyu ftq_redirect_mem.io.ren.get(IfuRedirectNum) := Mux(aheadValid, ftqIdxAhead(0).valid, backendRedirect.valid) 1062cf7d6b7aSMuzi ftq_redirect_mem.io.raddr(IfuRedirectNum) := Mux( 1063cf7d6b7aSMuzi aheadValid, 1064cf7d6b7aSMuzi ftqIdxAhead(0).bits.value, 1065cf7d6b7aSMuzi backendRedirect.bits.ftqIdx.value 1066cf7d6b7aSMuzi ) 106795a47398SGao-Zeyu ftb_entry_mem.io.ren.get(IfuRedirectNum) := Mux(aheadValid, ftqIdxAhead(0).valid, backendRedirect.valid) 1068cf7d6b7aSMuzi ftb_entry_mem.io.raddr(IfuRedirectNum) := Mux( 1069cf7d6b7aSMuzi aheadValid, 1070cf7d6b7aSMuzi ftqIdxAhead(0).bits.value, 1071cf7d6b7aSMuzi backendRedirect.bits.ftqIdx.value 1072cf7d6b7aSMuzi ) 1073bace178aSGao-Zeyu 1074c776f0d5Smy-mayfly ftq_pd_mem.io.ren.get(0) := Mux(aheadValid, ftqIdxAhead(0).valid, backendRedirect.valid) 1075c776f0d5Smy-mayfly ftq_pd_mem.io.raddr(0) := Mux(aheadValid, ftqIdxAhead(0).bits.value, backendRedirect.bits.ftqIdx.value) 1076c776f0d5Smy-mayfly 1077bace178aSGao-Zeyu for (i <- 0 until FtqRedirectAheadNum) { 107895a47398SGao-Zeyu ftq_redirect_rdata(i) := ftq_redirect_mem.io.rdata(i + IfuRedirectNum) 107995a47398SGao-Zeyu ftb_redirect_rdata(i) := ftb_entry_mem.io.rdata(i + IfuRedirectNum) 1080c776f0d5Smy-mayfly 1081c776f0d5Smy-mayfly ftq_pd_rdata(i) := ftq_pd_mem.io.rdata(i) 1082bace178aSGao-Zeyu } 1083cf7d6b7aSMuzi val stage3CfiInfo = 1084cf7d6b7aSMuzi Mux(realAhdValid, Mux1H(ftqIdxSelOH, ftq_redirect_rdata), ftq_redirect_mem.io.rdata(IfuRedirectNum)) 1085c776f0d5Smy-mayfly val stage3PdInfo = Mux(realAhdValid, Mux1H(ftqIdxSelOH, ftq_pd_rdata), ftq_pd_mem.io.rdata(0)) 108609c6f1ddSLingrui98 val backendRedirectCfi = fromBackendRedirect.bits.cfiUpdate 108709c6f1ddSLingrui98 backendRedirectCfi.fromFtqRedirectSram(stage3CfiInfo) 1088c776f0d5Smy-mayfly backendRedirectCfi.pd := stage3PdInfo.toPd(fromBackendRedirect.bits.ftqOffset) 108909c6f1ddSLingrui98 109095a47398SGao-Zeyu val r_ftb_entry = Mux(realAhdValid, Mux1H(ftqIdxSelOH, ftb_redirect_rdata), ftb_entry_mem.io.rdata(IfuRedirectNum)) 109109c6f1ddSLingrui98 val r_ftqOffset = fromBackendRedirect.bits.ftqOffset 109209c6f1ddSLingrui98 1093d2b20d1aSTang Haojin backendRedirectCfi.br_hit := r_ftb_entry.brIsSaved(r_ftqOffset) 1094d2b20d1aSTang Haojin backendRedirectCfi.jr_hit := r_ftb_entry.isJalr && r_ftb_entry.tailSlot.offset === r_ftqOffset 10953711cf36S小造xu_zh // FIXME: not portable 1096abdc3a32Sxu_zh val sc_disagree = stage3CfiInfo.sc_disagree.getOrElse(VecInit(Seq.fill(numBr)(false.B))) 1097cf7d6b7aSMuzi backendRedirectCfi.sc_hit := backendRedirectCfi.br_hit && Mux( 1098cf7d6b7aSMuzi r_ftb_entry.brSlots(0).offset === r_ftqOffset, 1099cf7d6b7aSMuzi sc_disagree(0), 1100cf7d6b7aSMuzi sc_disagree(1) 1101cf7d6b7aSMuzi ) 1102d2b20d1aSTang Haojin 110309c6f1ddSLingrui98 when(entry_hit_status(fromBackendRedirect.bits.ftqIdx.value) === h_hit) { 110409c6f1ddSLingrui98 backendRedirectCfi.shift := PopCount(r_ftb_entry.getBrMaskByOffset(r_ftqOffset)) +& 110509c6f1ddSLingrui98 (backendRedirectCfi.pd.isBr && !r_ftb_entry.brIsSaved(r_ftqOffset) && 1106eeb5ff92SLingrui98 !r_ftb_entry.newBrCanNotInsert(r_ftqOffset)) 110709c6f1ddSLingrui98 110809c6f1ddSLingrui98 backendRedirectCfi.addIntoHist := backendRedirectCfi.pd.isBr && (r_ftb_entry.brIsSaved(r_ftqOffset) || 1109eeb5ff92SLingrui98 !r_ftb_entry.newBrCanNotInsert(r_ftqOffset)) 111009c6f1ddSLingrui98 }.otherwise { 111109c6f1ddSLingrui98 backendRedirectCfi.shift := (backendRedirectCfi.pd.isBr && backendRedirectCfi.taken).asUInt 111209c6f1ddSLingrui98 backendRedirectCfi.addIntoHist := backendRedirectCfi.pd.isBr.asUInt 111309c6f1ddSLingrui98 } 111409c6f1ddSLingrui98 111509c6f1ddSLingrui98 // *************************************************************************** 111609c6f1ddSLingrui98 // **************************** redirect from ifu **************************** 111709c6f1ddSLingrui98 // *************************************************************************** 1118d2b20d1aSTang Haojin val fromIfuRedirect = WireInit(0.U.asTypeOf(Valid(new BranchPredictionRedirect))) 111909c6f1ddSLingrui98 fromIfuRedirect.valid := pdWb.valid && pdWb.bits.misOffset.valid && !backendFlush 112009c6f1ddSLingrui98 fromIfuRedirect.bits.ftqIdx := pdWb.bits.ftqIdx 112109c6f1ddSLingrui98 fromIfuRedirect.bits.ftqOffset := pdWb.bits.misOffset.bits 112209c6f1ddSLingrui98 fromIfuRedirect.bits.level := RedirectLevel.flushAfter 1123d2b20d1aSTang Haojin fromIfuRedirect.bits.BTBMissBubble := true.B 1124d2b20d1aSTang Haojin fromIfuRedirect.bits.debugIsMemVio := false.B 1125d2b20d1aSTang Haojin fromIfuRedirect.bits.debugIsCtrl := false.B 112609c6f1ddSLingrui98 112709c6f1ddSLingrui98 val ifuRedirectCfiUpdate = fromIfuRedirect.bits.cfiUpdate 112809c6f1ddSLingrui98 ifuRedirectCfiUpdate.pc := pdWb.bits.pc(pdWb.bits.misOffset.bits) 112909c6f1ddSLingrui98 ifuRedirectCfiUpdate.pd := pdWb.bits.pd(pdWb.bits.misOffset.bits) 113009c6f1ddSLingrui98 ifuRedirectCfiUpdate.predTaken := cfiIndex_vec(pdWb.bits.ftqIdx.value).valid 113109c6f1ddSLingrui98 ifuRedirectCfiUpdate.target := pdWb.bits.target 113209c6f1ddSLingrui98 ifuRedirectCfiUpdate.taken := pdWb.bits.cfiOffset.valid 113309c6f1ddSLingrui98 ifuRedirectCfiUpdate.isMisPred := pdWb.bits.misOffset.valid 113409c6f1ddSLingrui98 11351c6fc24aSEaston Man val ifuRedirectReg = RegNextWithEnable(fromIfuRedirect, hasInit = true) 113609c6f1ddSLingrui98 val ifuRedirectToBpu = WireInit(ifuRedirectReg) 113709c6f1ddSLingrui98 ifuFlush := fromIfuRedirect.valid || ifuRedirectToBpu.valid 113809c6f1ddSLingrui98 113916a171eeSEaston Man ftq_redirect_mem.io.ren.get.head := fromIfuRedirect.valid 1140deb3a97eSGao-Zeyu ftq_redirect_mem.io.raddr.head := fromIfuRedirect.bits.ftqIdx.value 114109c6f1ddSLingrui98 114209c6f1ddSLingrui98 val toBpuCfi = ifuRedirectToBpu.bits.cfiUpdate 1143deb3a97eSGao-Zeyu toBpuCfi.fromFtqRedirectSram(ftq_redirect_mem.io.rdata.head) 1144f1267a13SEaston Man when(ifuRedirectReg.bits.cfiUpdate.pd.isRet && ifuRedirectReg.bits.cfiUpdate.pd.valid) { 1145c89b4642SGuokai Chen toBpuCfi.target := toBpuCfi.topAddr 114609c6f1ddSLingrui98 } 114709c6f1ddSLingrui98 1148d2b20d1aSTang Haojin when(ifuRedirectReg.valid) { 1149d2b20d1aSTang Haojin ifuRedirected(ifuRedirectReg.bits.ftqIdx.value) := true.B 1150d2b20d1aSTang Haojin }.elsewhen(RegNext(pdWb.valid)) { 1151d2b20d1aSTang Haojin // if pdWb and no redirect, set to false 1152d2b20d1aSTang Haojin ifuRedirected(last_cycle_bpu_in_ptr.value) := false.B 1153d2b20d1aSTang Haojin } 1154d2b20d1aSTang Haojin 11556022c595SsinceforYy // ********************************************************************** 11566022c595SsinceforYy // ***************************** to backend ***************************** 11576022c595SsinceforYy // ********************************************************************** 11586022c595SsinceforYy // to backend pc mem / target 11596022c595SsinceforYy io.toBackend.pc_mem_wen := RegNext(last_cycle_bpu_in) 1160f533cba7SHuSipeng io.toBackend.pc_mem_waddr := RegEnable(last_cycle_bpu_in_idx, last_cycle_bpu_in) 11616022c595SsinceforYy io.toBackend.pc_mem_wdata := RegEnable(bpu_in_bypass_buf_for_ifu, last_cycle_bpu_in) 11626022c595SsinceforYy 11636022c595SsinceforYy // num cycle is fixed 11646022c595SsinceforYy val newest_entry_en: Bool = RegNext(last_cycle_bpu_in || backendRedirect.valid || ifuRedirectToBpu.valid) 11656022c595SsinceforYy io.toBackend.newest_entry_en := RegNext(newest_entry_en) 11666022c595SsinceforYy io.toBackend.newest_entry_ptr := RegEnable(newest_entry_ptr, newest_entry_en) 11676022c595SsinceforYy io.toBackend.newest_entry_target := RegEnable(newest_entry_target, newest_entry_en) 11686022c595SsinceforYy 116909c6f1ddSLingrui98 // ********************************************************************* 117009c6f1ddSLingrui98 // **************************** wb from exu **************************** 117109c6f1ddSLingrui98 // ********************************************************************* 117209c6f1ddSLingrui98 1173d2b20d1aSTang Haojin backendRedirect.valid := io.fromBackend.redirect.valid 1174d2b20d1aSTang Haojin backendRedirect.bits.connectRedirect(io.fromBackend.redirect.bits) 1175d2b20d1aSTang Haojin backendRedirect.bits.BTBMissBubble := false.B 1176d2b20d1aSTang Haojin 117709c6f1ddSLingrui98 def extractRedirectInfo(wb: Valid[Redirect]) = { 11786bf9b30dSLingrui98 val ftqPtr = wb.bits.ftqIdx 117909c6f1ddSLingrui98 val ftqOffset = wb.bits.ftqOffset 118009c6f1ddSLingrui98 val taken = wb.bits.cfiUpdate.taken 118109c6f1ddSLingrui98 val mispred = wb.bits.cfiUpdate.isMisPred 11826bf9b30dSLingrui98 (wb.valid, ftqPtr, ftqOffset, taken, mispred) 118309c6f1ddSLingrui98 } 118409c6f1ddSLingrui98 118509c6f1ddSLingrui98 // fix mispredict entry 118609c6f1ddSLingrui98 val lastIsMispredict = RegNext( 1187cf7d6b7aSMuzi backendRedirect.valid && backendRedirect.bits.level === RedirectLevel.flushAfter, 1188cf7d6b7aSMuzi init = false.B 118909c6f1ddSLingrui98 ) 119009c6f1ddSLingrui98 119109c6f1ddSLingrui98 def updateCfiInfo(redirect: Valid[Redirect], isBackend: Boolean = true) = { 11926bf9b30dSLingrui98 val (r_valid, r_ptr, r_offset, r_taken, r_mispred) = extractRedirectInfo(redirect) 11936bf9b30dSLingrui98 val r_idx = r_ptr.value 119409c6f1ddSLingrui98 val cfiIndex_bits_wen = r_valid && r_taken && r_offset < cfiIndex_vec(r_idx).bits 119509c6f1ddSLingrui98 val cfiIndex_valid_wen = r_valid && r_offset === cfiIndex_vec(r_idx).bits 119609c6f1ddSLingrui98 when(cfiIndex_bits_wen || cfiIndex_valid_wen) { 119709c6f1ddSLingrui98 cfiIndex_vec(r_idx).valid := cfiIndex_bits_wen || cfiIndex_valid_wen && r_taken 11983f88c020SGuokai Chen }.elsewhen(r_valid && !r_taken && r_offset =/= cfiIndex_vec(r_idx).bits) { 11993f88c020SGuokai Chen cfiIndex_vec(r_idx).valid := false.B 120009c6f1ddSLingrui98 } 120109c6f1ddSLingrui98 when(cfiIndex_bits_wen) { 120209c6f1ddSLingrui98 cfiIndex_vec(r_idx).bits := r_offset 120309c6f1ddSLingrui98 } 12041c6fc24aSEaston Man newest_entry_target_modified := true.B 12056bf9b30dSLingrui98 newest_entry_target := redirect.bits.cfiUpdate.target 12061c6fc24aSEaston Man newest_entry_ptr_modified := true.B 1207873dc383SLingrui98 newest_entry_ptr := r_ptr 12081c6fc24aSEaston Man 1209b0ed7239SLingrui98 update_target(r_idx) := redirect.bits.cfiUpdate.target // TODO: remove this 121009c6f1ddSLingrui98 if (isBackend) { 121109c6f1ddSLingrui98 mispredict_vec(r_idx)(r_offset) := r_mispred 121209c6f1ddSLingrui98 } 121309c6f1ddSLingrui98 } 121409c6f1ddSLingrui98 1215bace178aSGao-Zeyu when(fromBackendRedirect.valid) { 1216bace178aSGao-Zeyu updateCfiInfo(fromBackendRedirect) 121709c6f1ddSLingrui98 }.elsewhen(ifuRedirectToBpu.valid) { 121809c6f1ddSLingrui98 updateCfiInfo(ifuRedirectToBpu, isBackend = false) 121909c6f1ddSLingrui98 } 122009c6f1ddSLingrui98 1221bace178aSGao-Zeyu when(fromBackendRedirect.valid) { 1222bace178aSGao-Zeyu when(fromBackendRedirect.bits.ControlRedirectBubble) { 1223d2b20d1aSTang Haojin when(fromBackendRedirect.bits.ControlBTBMissBubble) { 1224d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.BTBMissBubble.id) := true.B 1225d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.BTBMissBubble.id) := true.B 1226d2b20d1aSTang Haojin }.elsewhen(fromBackendRedirect.bits.TAGEMissBubble) { 1227d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.TAGEMissBubble.id) := true.B 1228d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.TAGEMissBubble.id) := true.B 1229d2b20d1aSTang Haojin }.elsewhen(fromBackendRedirect.bits.SCMissBubble) { 1230d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.SCMissBubble.id) := true.B 1231d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.SCMissBubble.id) := true.B 1232d2b20d1aSTang Haojin }.elsewhen(fromBackendRedirect.bits.ITTAGEMissBubble) { 1233d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.ITTAGEMissBubble.id) := true.B 1234d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.ITTAGEMissBubble.id) := true.B 1235d2b20d1aSTang Haojin }.elsewhen(fromBackendRedirect.bits.RASMissBubble) { 1236d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.RASMissBubble.id) := true.B 1237d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.RASMissBubble.id) := true.B 1238d2b20d1aSTang Haojin } 1239d2b20d1aSTang Haojin 12409342624fSGao-Zeyu }.elsewhen(backendRedirect.bits.MemVioRedirectBubble) { 1241d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.MemVioRedirectBubble.id) := true.B 1242d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.MemVioRedirectBubble.id) := true.B 1243d2b20d1aSTang Haojin }.otherwise { 1244d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.OtherRedirectBubble.id) := true.B 1245d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.OtherRedirectBubble.id) := true.B 1246d2b20d1aSTang Haojin } 1247d2b20d1aSTang Haojin }.elsewhen(ifuRedirectReg.valid) { 1248d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.BTBMissBubble.id) := true.B 1249d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.BTBMissBubble.id) := true.B 1250d2b20d1aSTang Haojin } 1251d2b20d1aSTang Haojin 1252d2b20d1aSTang Haojin io.ControlBTBMissBubble := fromBackendRedirect.bits.ControlBTBMissBubble 1253d2b20d1aSTang Haojin io.TAGEMissBubble := fromBackendRedirect.bits.TAGEMissBubble 1254d2b20d1aSTang Haojin io.SCMissBubble := fromBackendRedirect.bits.SCMissBubble 1255d2b20d1aSTang Haojin io.ITTAGEMissBubble := fromBackendRedirect.bits.ITTAGEMissBubble 1256d2b20d1aSTang Haojin io.RASMissBubble := fromBackendRedirect.bits.RASMissBubble 1257d2b20d1aSTang Haojin 125809c6f1ddSLingrui98 // *********************************************************************************** 125909c6f1ddSLingrui98 // **************************** flush ptr and state queue **************************** 126009c6f1ddSLingrui98 // *********************************************************************************** 126109c6f1ddSLingrui98 1262df5b4b8eSYinan Xu val redirectVec = VecInit(backendRedirect, fromIfuRedirect) 126309c6f1ddSLingrui98 126409c6f1ddSLingrui98 // when redirect, we should reset ptrs and status queues 1265b92f8445Sssszwic io.icacheFlush := redirectVec.map(r => r.valid).reduce(_ || _) 1266b92f8445Sssszwic XSPerfAccumulate("icacheFlushFromBackend", backendRedirect.valid) 1267b92f8445Sssszwic XSPerfAccumulate("icacheFlushFromIFU", fromIfuRedirect.valid) 126809c6f1ddSLingrui98 when(redirectVec.map(r => r.valid).reduce(_ || _)) { 1269cf7d6b7aSMuzi val r = PriorityMux(redirectVec.map(r => r.valid -> r.bits)) 127009c6f1ddSLingrui98 val notIfu = redirectVec.dropRight(1).map(r => r.valid).reduce(_ || _) 12712f4a3aa4SLingrui98 val (idx, offset, flushItSelf) = (r.ftqIdx, r.ftqOffset, RedirectLevel.flushItself(r.level)) 127209c6f1ddSLingrui98 val next = idx + 1.U 127309c6f1ddSLingrui98 bpuPtr := next 1274dc270d3bSJenius copied_bpu_ptr.map(_ := next) 1275c5c5edaeSJenius ifuPtr_write := next 1276c5c5edaeSJenius ifuWbPtr_write := next 1277c5c5edaeSJenius ifuPtrPlus1_write := idx + 2.U 12786bf9b30dSLingrui98 ifuPtrPlus2_write := idx + 3.U 1279b92f8445Sssszwic pfPtr_write := next 1280b92f8445Sssszwic pfPtrPlus1_write := idx + 2.U 12813f88c020SGuokai Chen } 12823f88c020SGuokai Chen when(RegNext(redirectVec.map(r => r.valid).reduce(_ || _))) { 1283cf7d6b7aSMuzi val r = PriorityMux(redirectVec.map(r => r.valid -> r.bits)) 12843f88c020SGuokai Chen val notIfu = redirectVec.dropRight(1).map(r => r.valid).reduce(_ || _) 12853f88c020SGuokai Chen val (idx, offset, flushItSelf) = (r.ftqIdx, r.ftqOffset, RedirectLevel.flushItself(r.level)) 12863f88c020SGuokai Chen when(RegNext(notIfu)) { 12871c6fc24aSEaston Man commitStateQueueEnable(RegNext(idx.value)) := true.B 1288cf7d6b7aSMuzi commitStateQueueNext(RegNext(idx.value)).zipWithIndex.foreach { case (s, i) => 128991346769SMuzi when(i.U > RegNext(offset)) { 129091346769SMuzi s := c_empty 129191346769SMuzi } 129291346769SMuzi when(i.U === RegNext(offset) && RegNext(flushItSelf)) { 129391346769SMuzi s := c_flushed 129409c6f1ddSLingrui98 } 129509c6f1ddSLingrui98 } 129609c6f1ddSLingrui98 } 1297cf7d6b7aSMuzi } 12983f88c020SGuokai Chen 129909c6f1ddSLingrui98 // only the valid bit is actually needed 1300df5b4b8eSYinan Xu io.toIfu.redirect.bits := backendRedirect.bits 130109c6f1ddSLingrui98 io.toIfu.redirect.valid := stage2Flush 1302d2b20d1aSTang Haojin io.toIfu.topdown_redirect := fromBackendRedirect 130309c6f1ddSLingrui98 130409c6f1ddSLingrui98 // commit 13059aca92b9SYinan Xu for (c <- io.fromBackend.rob_commits) { 130609c6f1ddSLingrui98 when(c.valid) { 13071c6fc24aSEaston Man commitStateQueueEnable(c.bits.ftqIdx.value) := true.B 130891346769SMuzi commitStateQueueNext(c.bits.ftqIdx.value)(c.bits.ftqOffset) := c_committed 130988825c5cSYinan Xu // TODO: remove this 131088825c5cSYinan Xu // For instruction fusions, we also update the next instruction 1311c3abb8b6SYinan Xu when(c.bits.commitType === 4.U) { 131291346769SMuzi commitStateQueueNext(c.bits.ftqIdx.value)(c.bits.ftqOffset + 1.U) := c_committed 1313c3abb8b6SYinan Xu }.elsewhen(c.bits.commitType === 5.U) { 131491346769SMuzi commitStateQueueNext(c.bits.ftqIdx.value)(c.bits.ftqOffset + 2.U) := c_committed 1315c3abb8b6SYinan Xu }.elsewhen(c.bits.commitType === 6.U) { 131688825c5cSYinan Xu val index = (c.bits.ftqIdx + 1.U).value 13171c6fc24aSEaston Man commitStateQueueEnable(index) := true.B 131891346769SMuzi commitStateQueueNext(index)(0) := c_committed 1319c3abb8b6SYinan Xu }.elsewhen(c.bits.commitType === 7.U) { 132088825c5cSYinan Xu val index = (c.bits.ftqIdx + 1.U).value 13211c6fc24aSEaston Man commitStateQueueEnable(index) := true.B 132291346769SMuzi commitStateQueueNext(index)(1) := c_committed 132388825c5cSYinan Xu } 132409c6f1ddSLingrui98 } 132509c6f1ddSLingrui98 } 132609c6f1ddSLingrui98 132709c6f1ddSLingrui98 // **************************************************************** 132809c6f1ddSLingrui98 // **************************** to bpu **************************** 132909c6f1ddSLingrui98 // **************************************************************** 133009c6f1ddSLingrui98 1331fd3aa057SYuandongliang io.toBpu.redirctFromIFU := ifuRedirectToBpu.valid 133251981c77SbugGenerator io.toBpu.redirect := Mux(fromBackendRedirect.valid, fromBackendRedirect, ifuRedirectToBpu) 1333209a4cafSSteve Gou val dummy_s1_pred_cycle_vec = VecInit(List.tabulate(FtqSize)(_ => 0.U(64.W))) 1334cf7d6b7aSMuzi val redirect_latency = 1335cf7d6b7aSMuzi GTimer() - pred_s1_cycle.getOrElse(dummy_s1_pred_cycle_vec)(io.toBpu.redirect.bits.ftqIdx.value) + 1.U 1336209a4cafSSteve Gou XSPerfHistogram("backend_redirect_latency", redirect_latency, fromBackendRedirect.valid, 0, 60, 1) 1337cf7d6b7aSMuzi XSPerfHistogram( 1338cf7d6b7aSMuzi "ifu_redirect_latency", 1339cf7d6b7aSMuzi redirect_latency, 1340cf7d6b7aSMuzi !fromBackendRedirect.valid && ifuRedirectToBpu.valid, 1341cf7d6b7aSMuzi 0, 1342cf7d6b7aSMuzi 60, 1343cf7d6b7aSMuzi 1 1344cf7d6b7aSMuzi ) 134509c6f1ddSLingrui98 1346cf7d6b7aSMuzi XSError( 1347cf7d6b7aSMuzi io.toBpu.redirect.valid && isBefore(io.toBpu.redirect.bits.ftqIdx, commPtr), 1348cf7d6b7aSMuzi "Ftq received a redirect after its commit, check backend or replay" 1349cf7d6b7aSMuzi ) 135009c6f1ddSLingrui98 135102f21c16SLingrui98 val may_have_stall_from_bpu = Wire(Bool()) 135202f21c16SLingrui98 val bpu_ftb_update_stall = RegInit(0.U(2.W)) // 2-cycle stall, so we need 3 states 135302f21c16SLingrui98 may_have_stall_from_bpu := bpu_ftb_update_stall =/= 0.U 13549230e379SMuzi 13559230e379SMuzi val validInstructions = commitStateQueueReg(commPtr.value).map(s => s === c_toCommit || s === c_committed) 13569230e379SMuzi val lastInstructionStatus = PriorityMux(validInstructions.reverse.zip(commitStateQueueReg(commPtr.value).reverse)) 13579230e379SMuzi val firstInstructionFlushed = commitStateQueueReg(commPtr.value)(0) === c_flushed 13589230e379SMuzi canCommit := commPtr =/= ifuWbPtr && !may_have_stall_from_bpu && 13599230e379SMuzi (isAfter(robCommPtr, commPtr) || 13609230e379SMuzi validInstructions.reduce(_ || _) && lastInstructionStatus === c_committed) 13619230e379SMuzi val canMoveCommPtr = commPtr =/= ifuWbPtr && !may_have_stall_from_bpu && 13629230e379SMuzi (isAfter(robCommPtr, commPtr) || 13639230e379SMuzi validInstructions.reduce(_ || _) && lastInstructionStatus === c_committed || 13649230e379SMuzi firstInstructionFlushed) 136591346769SMuzi 136691346769SMuzi when(io.fromBackend.rob_commits.map(_.valid).reduce(_ | _)) { 1367cf7d6b7aSMuzi robCommPtr_write := ParallelPriorityMux( 1368cf7d6b7aSMuzi io.fromBackend.rob_commits.map(_.valid).reverse, 1369cf7d6b7aSMuzi io.fromBackend.rob_commits.map(_.bits.ftqIdx).reverse 1370cf7d6b7aSMuzi ) 13719230e379SMuzi }.elsewhen(isAfter(commPtr, robCommPtr)) { 137291346769SMuzi robCommPtr_write := commPtr 137391346769SMuzi }.otherwise { 137491346769SMuzi robCommPtr_write := robCommPtr 137591346769SMuzi } 137609c6f1ddSLingrui98 1377ba5ba1dcSmy-mayfly /** 1378ba5ba1dcSmy-mayfly ************************************************************************************* 1379ba5ba1dcSmy-mayfly * MMIO instruction fetch is allowed only if MMIO is the oldest instruction. 1380ba5ba1dcSmy-mayfly ************************************************************************************* 1381ba5ba1dcSmy-mayfly */ 13821d1e6d4dSJenius val mmioReadPtr = io.mmioCommitRead.mmioFtqPtr 13839230e379SMuzi val mmioLastCommit = isAfter(commPtr, mmioReadPtr) || 13849230e379SMuzi commPtr === mmioReadPtr && validInstructions.reduce(_ || _) && lastInstructionStatus === c_committed 13851d1e6d4dSJenius io.mmioCommitRead.mmioLastCommit := RegNext(mmioLastCommit) 13861d1e6d4dSJenius 138709c6f1ddSLingrui98 // commit reads 1388c5c5edaeSJenius val commit_pc_bundle = RegNext(ftq_pc_mem.io.commPtr_rdata) 138981101dc4SLingrui98 val commit_target = 1390cf7d6b7aSMuzi Mux( 1391cf7d6b7aSMuzi RegNext(commPtr === newest_entry_ptr), 13921c6fc24aSEaston Man RegEnable(newest_entry_target, newest_entry_target_modified), 1393cf7d6b7aSMuzi RegNext(ftq_pc_mem.io.commPtrPlus1_rdata.startAddr) 1394cf7d6b7aSMuzi ) 13951c6fc24aSEaston Man ftq_pd_mem.io.ren.get.last := canCommit 139609c6f1ddSLingrui98 ftq_pd_mem.io.raddr.last := commPtr.value 139709c6f1ddSLingrui98 val commit_pd = ftq_pd_mem.io.rdata.last 139816a171eeSEaston Man ftq_redirect_mem.io.ren.get.last := canCommit 1399deb3a97eSGao-Zeyu ftq_redirect_mem.io.raddr.last := commPtr.value 1400deb3a97eSGao-Zeyu val commit_spec_meta = ftq_redirect_mem.io.rdata.last 140109c6f1ddSLingrui98 ftq_meta_1r_sram.io.ren(0) := canCommit 140209c6f1ddSLingrui98 ftq_meta_1r_sram.io.raddr(0) := commPtr.value 1403deb3a97eSGao-Zeyu val commit_meta = ftq_meta_1r_sram.io.rdata(0).meta 1404deb3a97eSGao-Zeyu val commit_ftb_entry = ftq_meta_1r_sram.io.rdata(0).ftb_entry 140509c6f1ddSLingrui98 140609c6f1ddSLingrui98 // need one cycle to read mem and srams 14071c6fc24aSEaston Man val do_commit_ptr = RegEnable(commPtr, canCommit) 14085371700eSzoujr val do_commit = RegNext(canCommit, init = false.B) 14099230e379SMuzi when(canMoveCommPtr) { 14106bf9b30dSLingrui98 commPtr_write := commPtrPlus1 14116bf9b30dSLingrui98 commPtrPlus1_write := commPtrPlus1 + 1.U 14126bf9b30dSLingrui98 } 14131c6fc24aSEaston Man val commit_state = RegEnable(commitStateQueueReg(commPtr.value), canCommit) 14145371700eSzoujr val can_commit_cfi = WireInit(cfiIndex_vec(commPtr.value)) 1415d4fcfc3eSGuokai Chen val do_commit_cfi = WireInit(cfiIndex_vec(do_commit_ptr.value)) 14163f88c020SGuokai Chen // 14173f88c020SGuokai Chen // when (commitStateQueue(commPtr.value)(can_commit_cfi.bits) =/= c_commited) { 14183f88c020SGuokai Chen // can_commit_cfi.valid := false.B 14193f88c020SGuokai Chen // } 14201c6fc24aSEaston Man val commit_cfi = RegEnable(can_commit_cfi, canCommit) 142191346769SMuzi val debug_cfi = commitStateQueueReg(do_commit_ptr.value)(do_commit_cfi.bits) =/= c_committed && do_commit_cfi.valid 142209c6f1ddSLingrui98 1423cf7d6b7aSMuzi val commit_mispredict: Vec[Bool] = 1424cf7d6b7aSMuzi VecInit((RegEnable(mispredict_vec(commPtr.value), canCommit) zip commit_state).map { 142591346769SMuzi case (mis, state) => mis && state === c_committed 142609c6f1ddSLingrui98 }) 142791346769SMuzi val commit_instCommited: Vec[Bool] = VecInit(commit_state.map(_ === c_committed)) // [PredictWidth] 14285371700eSzoujr val can_commit_hit = entry_hit_status(commPtr.value) 14291c6fc24aSEaston Man val commit_hit = RegEnable(can_commit_hit, canCommit) 14301c6fc24aSEaston Man val diff_commit_target = RegEnable(update_target(commPtr.value), canCommit) // TODO: remove this 14311c6fc24aSEaston Man val commit_stage = RegEnable(pred_stage(commPtr.value), canCommit) 143209c6f1ddSLingrui98 val commit_valid = commit_hit === h_hit || commit_cfi.valid // hit or taken 143309c6f1ddSLingrui98 14345371700eSzoujr val to_bpu_hit = can_commit_hit === h_hit || can_commit_hit === h_false_hit 143502f21c16SLingrui98 switch(bpu_ftb_update_stall) { 143602f21c16SLingrui98 is(0.U) { 143702f21c16SLingrui98 when(can_commit_cfi.valid && !to_bpu_hit && canCommit) { 143802f21c16SLingrui98 bpu_ftb_update_stall := 2.U // 2-cycle stall 143902f21c16SLingrui98 } 144002f21c16SLingrui98 } 144102f21c16SLingrui98 is(2.U) { 144202f21c16SLingrui98 bpu_ftb_update_stall := 1.U 144302f21c16SLingrui98 } 144402f21c16SLingrui98 is(1.U) { 144502f21c16SLingrui98 bpu_ftb_update_stall := 0.U 144602f21c16SLingrui98 } 144702f21c16SLingrui98 is(3.U) { 144802f21c16SLingrui98 XSError(true.B, "bpu_ftb_update_stall should be 0, 1 or 2") 144902f21c16SLingrui98 } 145002f21c16SLingrui98 } 145109c6f1ddSLingrui98 1452b0ed7239SLingrui98 // TODO: remove this 1453b0ed7239SLingrui98 XSError(do_commit && diff_commit_target =/= commit_target, "\ncommit target should be the same as update target\n") 1454b0ed7239SLingrui98 1455b2f6ed0aSSteve Gou // update latency stats 1456b2f6ed0aSSteve Gou val update_latency = GTimer() - pred_s1_cycle.getOrElse(dummy_s1_pred_cycle_vec)(do_commit_ptr.value) + 1.U 1457b2f6ed0aSSteve Gou XSPerfHistogram("bpu_update_latency", update_latency, io.toBpu.update.valid, 0, 64, 2) 1458b2f6ed0aSSteve Gou 145909c6f1ddSLingrui98 io.toBpu.update := DontCare 146009c6f1ddSLingrui98 io.toBpu.update.valid := commit_valid && do_commit 146109c6f1ddSLingrui98 val update = io.toBpu.update.bits 146209c6f1ddSLingrui98 update.false_hit := commit_hit === h_false_hit 146309c6f1ddSLingrui98 update.pc := commit_pc_bundle.startAddr 1464deb3a97eSGao-Zeyu update.meta := commit_meta 1465803124a6SLingrui98 update.cfi_idx := commit_cfi 14668ffcd86aSLingrui98 update.full_target := commit_target 1467edc18578SLingrui98 update.from_stage := commit_stage 1468c2d1ec7dSLingrui98 update.spec_info := commit_spec_meta 14693f88c020SGuokai Chen XSError(commit_valid && do_commit && debug_cfi, "\ncommit cfi can be non c_commited\n") 147009c6f1ddSLingrui98 147109c6f1ddSLingrui98 val commit_real_hit = commit_hit === h_hit 147209c6f1ddSLingrui98 val update_ftb_entry = update.ftb_entry 147309c6f1ddSLingrui98 147409c6f1ddSLingrui98 val ftbEntryGen = Module(new FTBEntryGen).io 147509c6f1ddSLingrui98 ftbEntryGen.start_addr := commit_pc_bundle.startAddr 147609c6f1ddSLingrui98 ftbEntryGen.old_entry := commit_ftb_entry 147709c6f1ddSLingrui98 ftbEntryGen.pd := commit_pd 147809c6f1ddSLingrui98 ftbEntryGen.cfiIndex := commit_cfi 147909c6f1ddSLingrui98 ftbEntryGen.target := commit_target 148009c6f1ddSLingrui98 ftbEntryGen.hit := commit_real_hit 148109c6f1ddSLingrui98 ftbEntryGen.mispredict_vec := commit_mispredict 148209c6f1ddSLingrui98 148309c6f1ddSLingrui98 update_ftb_entry := ftbEntryGen.new_entry 148409c6f1ddSLingrui98 update.new_br_insert_pos := ftbEntryGen.new_br_insert_pos 148509c6f1ddSLingrui98 update.mispred_mask := ftbEntryGen.mispred_mask 148609c6f1ddSLingrui98 update.old_entry := ftbEntryGen.is_old_entry 1487edc18578SLingrui98 update.pred_hit := commit_hit === h_hit || commit_hit === h_false_hit 1488803124a6SLingrui98 update.br_taken_mask := ftbEntryGen.taken_mask 1489cc2d1573SEaston Man update.br_committed := (ftbEntryGen.new_entry.brValids zip ftbEntryGen.new_entry.brOffset) map { 1490cc2d1573SEaston Man case (valid, offset) => valid && commit_instCommited(offset) 1491cc2d1573SEaston Man } 1492803124a6SLingrui98 update.jmp_taken := ftbEntryGen.jmp_taken 1493b37e4b45SLingrui98 1494803124a6SLingrui98 // update.full_pred.fromFtbEntry(ftbEntryGen.new_entry, update.pc) 1495803124a6SLingrui98 // update.full_pred.jalr_target := commit_target 1496803124a6SLingrui98 // update.full_pred.hit := true.B 1497803124a6SLingrui98 // when (update.full_pred.is_jalr) { 1498803124a6SLingrui98 // update.full_pred.targets.last := commit_target 1499803124a6SLingrui98 // } 150009c6f1ddSLingrui98 150109c6f1ddSLingrui98 // ****************************************************************************** 150209c6f1ddSLingrui98 // **************************** commit perf counters **************************** 150309c6f1ddSLingrui98 // ****************************************************************************** 150409c6f1ddSLingrui98 150591346769SMuzi val commit_inst_mask = VecInit(commit_state.map(c => c === c_committed && do_commit)).asUInt 150609c6f1ddSLingrui98 val commit_mispred_mask = commit_mispredict.asUInt 150709c6f1ddSLingrui98 val commit_not_mispred_mask = ~commit_mispred_mask 150809c6f1ddSLingrui98 150909c6f1ddSLingrui98 val commit_br_mask = commit_pd.brMask.asUInt 151009c6f1ddSLingrui98 val commit_jmp_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.jmpInfo.valid.asTypeOf(UInt(1.W))) 1511cf7d6b7aSMuzi val commit_cfi_mask = commit_br_mask | commit_jmp_mask 151209c6f1ddSLingrui98 151309c6f1ddSLingrui98 val mbpInstrs = commit_inst_mask & commit_cfi_mask 151409c6f1ddSLingrui98 151509c6f1ddSLingrui98 val mbpRights = mbpInstrs & commit_not_mispred_mask 151609c6f1ddSLingrui98 val mbpWrongs = mbpInstrs & commit_mispred_mask 151709c6f1ddSLingrui98 151809c6f1ddSLingrui98 io.bpuInfo.bpRight := PopCount(mbpRights) 151909c6f1ddSLingrui98 io.bpuInfo.bpWrong := PopCount(mbpWrongs) 152009c6f1ddSLingrui98 1521b92f8445Sssszwic val hartId = p(XSCoreParamsKey).HartId 1522c686adcdSYinan Xu val isWriteFTQTable = Constantin.createRecord(s"isWriteFTQTable$hartId") 1523c686adcdSYinan Xu val ftqBranchTraceDB = ChiselDB.createTable(s"FTQTable$hartId", new FtqDebugBundle) 152409c6f1ddSLingrui98 // Cfi Info 152509c6f1ddSLingrui98 for (i <- 0 until PredictWidth) { 152609c6f1ddSLingrui98 val pc = commit_pc_bundle.startAddr + (i * instBytes).U 152791346769SMuzi val v = commit_state(i) === c_committed 152809c6f1ddSLingrui98 val isBr = commit_pd.brMask(i) 152909c6f1ddSLingrui98 val isJmp = commit_pd.jmpInfo.valid && commit_pd.jmpOffset === i.U 153009c6f1ddSLingrui98 val isCfi = isBr || isJmp 153109c6f1ddSLingrui98 val isTaken = commit_cfi.valid && commit_cfi.bits === i.U 153209c6f1ddSLingrui98 val misPred = commit_mispredict(i) 1533c2ad24ebSLingrui98 // val ghist = commit_spec_meta.ghist.predHist 1534c2ad24ebSLingrui98 val histPtr = commit_spec_meta.histPtr 1535deb3a97eSGao-Zeyu val predCycle = commit_meta(63, 0) 153609c6f1ddSLingrui98 val target = commit_target 153709c6f1ddSLingrui98 1538cf7d6b7aSMuzi val brIdx = OHToUInt(Reverse(Cat(update_ftb_entry.brValids.zip(update_ftb_entry.brOffset).map { case (v, offset) => 1539cf7d6b7aSMuzi v && offset === i.U 1540cf7d6b7aSMuzi }))) 1541cf7d6b7aSMuzi val inFtbEntry = update_ftb_entry.brValids.zip(update_ftb_entry.brOffset).map { case (v, offset) => 1542cf7d6b7aSMuzi v && offset === i.U 1543cf7d6b7aSMuzi }.reduce(_ || _) 1544cf7d6b7aSMuzi val addIntoHist = 1545cf7d6b7aSMuzi ((commit_hit === h_hit) && inFtbEntry) || (!(commit_hit === h_hit) && i.U === commit_cfi.bits && isBr && commit_cfi.valid) 1546cf7d6b7aSMuzi XSDebug( 1547cf7d6b7aSMuzi v && do_commit && isCfi, 1548cf7d6b7aSMuzi p"cfi_update: isBr(${isBr}) pc(${Hexadecimal(pc)}) " + 1549c2ad24ebSLingrui98 p"taken(${isTaken}) mispred(${misPred}) cycle($predCycle) hist(${histPtr.value}) " + 155009c6f1ddSLingrui98 p"startAddr(${Hexadecimal(commit_pc_bundle.startAddr)}) AddIntoHist(${addIntoHist}) " + 1551cf7d6b7aSMuzi p"brInEntry(${inFtbEntry}) brIdx(${brIdx}) target(${Hexadecimal(target)})\n" 1552cf7d6b7aSMuzi ) 155351532d8bSGuokai Chen 155451532d8bSGuokai Chen val logbundle = Wire(new FtqDebugBundle) 155551532d8bSGuokai Chen logbundle.pc := pc 155651532d8bSGuokai Chen logbundle.target := target 155751532d8bSGuokai Chen logbundle.isBr := isBr 155851532d8bSGuokai Chen logbundle.isJmp := isJmp 155951532d8bSGuokai Chen logbundle.isCall := isJmp && commit_pd.hasCall 156051532d8bSGuokai Chen logbundle.isRet := isJmp && commit_pd.hasRet 156151532d8bSGuokai Chen logbundle.misPred := misPred 156251532d8bSGuokai Chen logbundle.isTaken := isTaken 156351532d8bSGuokai Chen logbundle.predStage := commit_stage 156451532d8bSGuokai Chen 156551532d8bSGuokai Chen ftqBranchTraceDB.log( 156651532d8bSGuokai Chen data = logbundle /* hardware of type T */, 1567da3bf434SMaxpicca-Li en = isWriteFTQTable.orR && v && do_commit && isCfi, 156851532d8bSGuokai Chen site = "FTQ" + p(XSCoreParamsKey).HartId.toString, 156951532d8bSGuokai Chen clock = clock, 157051532d8bSGuokai Chen reset = reset 157151532d8bSGuokai Chen ) 157209c6f1ddSLingrui98 } 157309c6f1ddSLingrui98 157409c6f1ddSLingrui98 val enq = io.fromBpu.resp 15752e1be6e1SSteve Gou val perf_redirect = backendRedirect 157609c6f1ddSLingrui98 157709c6f1ddSLingrui98 XSPerfAccumulate("entry", validEntries) 157809c6f1ddSLingrui98 XSPerfAccumulate("bpu_to_ftq_stall", enq.valid && !enq.ready) 157909c6f1ddSLingrui98 XSPerfAccumulate("mispredictRedirect", perf_redirect.valid && RedirectLevel.flushAfter === perf_redirect.bits.level) 158009c6f1ddSLingrui98 XSPerfAccumulate("replayRedirect", perf_redirect.valid && RedirectLevel.flushItself(perf_redirect.bits.level)) 158109c6f1ddSLingrui98 XSPerfAccumulate("predecodeRedirect", fromIfuRedirect.valid) 158209c6f1ddSLingrui98 158309c6f1ddSLingrui98 XSPerfAccumulate("to_ifu_bubble", io.toIfu.req.ready && !io.toIfu.req.valid) 158409c6f1ddSLingrui98 158509c6f1ddSLingrui98 XSPerfAccumulate("to_ifu_stall", io.toIfu.req.valid && !io.toIfu.req.ready) 158609c6f1ddSLingrui98 XSPerfAccumulate("from_bpu_real_bubble", !enq.valid && enq.ready && allowBpuIn) 158712cedb6fSLingrui98 XSPerfAccumulate("bpu_to_ifu_bubble", bpuPtr === ifuPtr) 1588cf7d6b7aSMuzi XSPerfAccumulate( 1589cf7d6b7aSMuzi "bpu_to_ifu_bubble_when_ftq_full", 1590cf7d6b7aSMuzi (bpuPtr === ifuPtr) && isFull(bpuPtr, commPtr) && io.toIfu.req.ready 1591cf7d6b7aSMuzi ) 159209c6f1ddSLingrui98 1593bace178aSGao-Zeyu XSPerfAccumulate("redirectAhead_ValidNum", ftqIdxAhead.map(_.valid).reduce(_ | _)) 15949342624fSGao-Zeyu XSPerfAccumulate("fromBackendRedirect_ValidNum", io.fromBackend.redirect.valid) 15959342624fSGao-Zeyu XSPerfAccumulate("toBpuRedirect_ValidNum", io.toBpu.redirect.valid) 15969342624fSGao-Zeyu 159709c6f1ddSLingrui98 val from_bpu = io.fromBpu.resp.bits 159809c6f1ddSLingrui98 val to_ifu = io.toIfu.req.bits 159909c6f1ddSLingrui98 1600209a4cafSSteve Gou XSPerfHistogram("commit_num_inst", PopCount(commit_inst_mask), do_commit, 0, PredictWidth + 1, 1) 160109c6f1ddSLingrui98 160209c6f1ddSLingrui98 val commit_jal_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasJal.asTypeOf(UInt(1.W))) 160309c6f1ddSLingrui98 val commit_jalr_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasJalr.asTypeOf(UInt(1.W))) 160409c6f1ddSLingrui98 val commit_call_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasCall.asTypeOf(UInt(1.W))) 160509c6f1ddSLingrui98 val commit_ret_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasRet.asTypeOf(UInt(1.W))) 160609c6f1ddSLingrui98 160709c6f1ddSLingrui98 val mbpBRights = mbpRights & commit_br_mask 160809c6f1ddSLingrui98 val mbpJRights = mbpRights & commit_jal_mask 160909c6f1ddSLingrui98 val mbpIRights = mbpRights & commit_jalr_mask 161009c6f1ddSLingrui98 val mbpCRights = mbpRights & commit_call_mask 161109c6f1ddSLingrui98 val mbpRRights = mbpRights & commit_ret_mask 161209c6f1ddSLingrui98 161309c6f1ddSLingrui98 val mbpBWrongs = mbpWrongs & commit_br_mask 161409c6f1ddSLingrui98 val mbpJWrongs = mbpWrongs & commit_jal_mask 161509c6f1ddSLingrui98 val mbpIWrongs = mbpWrongs & commit_jalr_mask 161609c6f1ddSLingrui98 val mbpCWrongs = mbpWrongs & commit_call_mask 161709c6f1ddSLingrui98 val mbpRWrongs = mbpWrongs & commit_ret_mask 161809c6f1ddSLingrui98 16191d7e5011SLingrui98 val commit_pred_stage = RegNext(pred_stage(commPtr.value)) 16201d7e5011SLingrui98 1621cf7d6b7aSMuzi def pred_stage_map(src: UInt, name: String) = 16221d7e5011SLingrui98 (0 until numBpStages).map(i => 16231d7e5011SLingrui98 f"${name}_stage_${i + 1}" -> PopCount(src.asBools.map(_ && commit_pred_stage === BP_STAGES(i))) 16241d7e5011SLingrui98 ).foldLeft(Map[String, UInt]())(_ + _) 16251d7e5011SLingrui98 16261d7e5011SLingrui98 val mispred_stage_map = pred_stage_map(mbpWrongs, "mispredict") 16271d7e5011SLingrui98 val br_mispred_stage_map = pred_stage_map(mbpBWrongs, "br_mispredict") 16281d7e5011SLingrui98 val jalr_mispred_stage_map = pred_stage_map(mbpIWrongs, "jalr_mispredict") 16291d7e5011SLingrui98 val correct_stage_map = pred_stage_map(mbpRights, "correct") 16301d7e5011SLingrui98 val br_correct_stage_map = pred_stage_map(mbpBRights, "br_correct") 16311d7e5011SLingrui98 val jalr_correct_stage_map = pred_stage_map(mbpIRights, "jalr_correct") 16321d7e5011SLingrui98 163309c6f1ddSLingrui98 val update_valid = io.toBpu.update.valid 163409c6f1ddSLingrui98 def u(cond: Bool) = update_valid && cond 163509c6f1ddSLingrui98 val ftb_false_hit = u(update.false_hit) 163665fddcf0Szoujr // assert(!ftb_false_hit) 163709c6f1ddSLingrui98 val ftb_hit = u(commit_hit === h_hit) 163809c6f1ddSLingrui98 163909c6f1ddSLingrui98 val ftb_new_entry = u(ftbEntryGen.is_init_entry) 1640b37e4b45SLingrui98 val ftb_new_entry_only_br = ftb_new_entry && !update_ftb_entry.jmpValid 1641b37e4b45SLingrui98 val ftb_new_entry_only_jmp = ftb_new_entry && !update_ftb_entry.brValids(0) 1642b37e4b45SLingrui98 val ftb_new_entry_has_br_and_jmp = ftb_new_entry && update_ftb_entry.brValids(0) && update_ftb_entry.jmpValid 164309c6f1ddSLingrui98 164409c6f1ddSLingrui98 val ftb_old_entry = u(ftbEntryGen.is_old_entry) 164509c6f1ddSLingrui98 1646cf7d6b7aSMuzi val ftb_modified_entry = 1647dcf4211fSYuandongliang u(ftbEntryGen.is_new_br || ftbEntryGen.is_jalr_target_modified || ftbEntryGen.is_strong_bias_modified) 164809c6f1ddSLingrui98 val ftb_modified_entry_new_br = u(ftbEntryGen.is_new_br) 1649d2b20d1aSTang Haojin val ftb_modified_entry_ifu_redirected = u(ifuRedirected(do_commit_ptr.value)) 165009c6f1ddSLingrui98 val ftb_modified_entry_jalr_target_modified = u(ftbEntryGen.is_jalr_target_modified) 165109c6f1ddSLingrui98 val ftb_modified_entry_br_full = ftb_modified_entry && ftbEntryGen.is_br_full 1652dcf4211fSYuandongliang val ftb_modified_entry_strong_bias = ftb_modified_entry && ftbEntryGen.is_strong_bias_modified 165309c6f1ddSLingrui98 1654209a4cafSSteve Gou def getFtbEntryLen(pc: UInt, entry: FTBEntry) = (entry.getFallThrough(pc) - pc) >> instOffsetBits 1655209a4cafSSteve Gou val gen_ftb_entry_len = getFtbEntryLen(update.pc, ftbEntryGen.new_entry) 1656209a4cafSSteve Gou XSPerfHistogram("ftb_init_entry_len", gen_ftb_entry_len, ftb_new_entry, 0, PredictWidth + 1, 1) 1657209a4cafSSteve Gou XSPerfHistogram("ftb_modified_entry_len", gen_ftb_entry_len, ftb_modified_entry, 0, PredictWidth + 1, 1) 1658209a4cafSSteve Gou val s3_ftb_entry_len = getFtbEntryLen(from_bpu.s3.pc(0), from_bpu.last_stage_ftb_entry) 1659209a4cafSSteve Gou XSPerfHistogram("s3_ftb_entry_len", s3_ftb_entry_len, from_bpu.s3.valid(0), 0, PredictWidth + 1, 1) 166009c6f1ddSLingrui98 1661209a4cafSSteve Gou XSPerfHistogram("ftq_has_entry", validEntries, true.B, 0, FtqSize + 1, 1) 166209c6f1ddSLingrui98 166309c6f1ddSLingrui98 val perfCountsMap = Map( 166409c6f1ddSLingrui98 "BpInstr" -> PopCount(mbpInstrs), 166509c6f1ddSLingrui98 "BpBInstr" -> PopCount(mbpBRights | mbpBWrongs), 166609c6f1ddSLingrui98 "BpRight" -> PopCount(mbpRights), 166709c6f1ddSLingrui98 "BpWrong" -> PopCount(mbpWrongs), 166809c6f1ddSLingrui98 "BpBRight" -> PopCount(mbpBRights), 166909c6f1ddSLingrui98 "BpBWrong" -> PopCount(mbpBWrongs), 167009c6f1ddSLingrui98 "BpJRight" -> PopCount(mbpJRights), 167109c6f1ddSLingrui98 "BpJWrong" -> PopCount(mbpJWrongs), 167209c6f1ddSLingrui98 "BpIRight" -> PopCount(mbpIRights), 167309c6f1ddSLingrui98 "BpIWrong" -> PopCount(mbpIWrongs), 167409c6f1ddSLingrui98 "BpCRight" -> PopCount(mbpCRights), 167509c6f1ddSLingrui98 "BpCWrong" -> PopCount(mbpCWrongs), 167609c6f1ddSLingrui98 "BpRRight" -> PopCount(mbpRRights), 167709c6f1ddSLingrui98 "BpRWrong" -> PopCount(mbpRWrongs), 167809c6f1ddSLingrui98 "ftb_false_hit" -> PopCount(ftb_false_hit), 167909c6f1ddSLingrui98 "ftb_hit" -> PopCount(ftb_hit), 168009c6f1ddSLingrui98 "ftb_new_entry" -> PopCount(ftb_new_entry), 168109c6f1ddSLingrui98 "ftb_new_entry_only_br" -> PopCount(ftb_new_entry_only_br), 168209c6f1ddSLingrui98 "ftb_new_entry_only_jmp" -> PopCount(ftb_new_entry_only_jmp), 168309c6f1ddSLingrui98 "ftb_new_entry_has_br_and_jmp" -> PopCount(ftb_new_entry_has_br_and_jmp), 168409c6f1ddSLingrui98 "ftb_old_entry" -> PopCount(ftb_old_entry), 168509c6f1ddSLingrui98 "ftb_modified_entry" -> PopCount(ftb_modified_entry), 168609c6f1ddSLingrui98 "ftb_modified_entry_new_br" -> PopCount(ftb_modified_entry_new_br), 168709c6f1ddSLingrui98 "ftb_jalr_target_modified" -> PopCount(ftb_modified_entry_jalr_target_modified), 168809c6f1ddSLingrui98 "ftb_modified_entry_br_full" -> PopCount(ftb_modified_entry_br_full), 1689dcf4211fSYuandongliang "ftb_modified_entry_strong_bias" -> PopCount(ftb_modified_entry_strong_bias) 1690209a4cafSSteve Gou ) ++ mispred_stage_map ++ br_mispred_stage_map ++ jalr_mispred_stage_map ++ 16911d7e5011SLingrui98 correct_stage_map ++ br_correct_stage_map ++ jalr_correct_stage_map 169209c6f1ddSLingrui98 169309c6f1ddSLingrui98 for ((key, value) <- perfCountsMap) { 169409c6f1ddSLingrui98 XSPerfAccumulate(key, value) 169509c6f1ddSLingrui98 } 169609c6f1ddSLingrui98 169709c6f1ddSLingrui98 // --------------------------- Debug -------------------------------- 169809c6f1ddSLingrui98 // XSDebug(enq_fire, p"enq! " + io.fromBpu.resp.bits.toPrintable) 169909c6f1ddSLingrui98 XSDebug(io.toIfu.req.fire, p"fire to ifu " + io.toIfu.req.bits.toPrintable) 170009c6f1ddSLingrui98 XSDebug(do_commit, p"deq! [ptr] $do_commit_ptr\n") 170109c6f1ddSLingrui98 XSDebug(true.B, p"[bpuPtr] $bpuPtr, [ifuPtr] $ifuPtr, [ifuWbPtr] $ifuWbPtr [commPtr] $commPtr\n") 1702cf7d6b7aSMuzi XSDebug( 1703cf7d6b7aSMuzi true.B, 1704cf7d6b7aSMuzi p"[in] v:${io.fromBpu.resp.valid} r:${io.fromBpu.resp.ready} " + 1705cf7d6b7aSMuzi p"[out] v:${io.toIfu.req.valid} r:${io.toIfu.req.ready}\n" 1706cf7d6b7aSMuzi ) 170709c6f1ddSLingrui98 XSDebug(do_commit, p"[deq info] cfiIndex: $commit_cfi, $commit_pc_bundle, target: ${Hexadecimal(commit_target)}\n") 170809c6f1ddSLingrui98 170909c6f1ddSLingrui98 // def ubtbCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 171009c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 171109c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 171209c6f1ddSLingrui98 // Mux(valid && pd.isBr, 171309c6f1ddSLingrui98 // isWrong ^ Mux(ans.hit.asBool, 171409c6f1ddSLingrui98 // Mux(ans.taken.asBool, taken && ans.target === commitEntry.target, 171509c6f1ddSLingrui98 // !taken), 171609c6f1ddSLingrui98 // !taken), 171709c6f1ddSLingrui98 // false.B) 171809c6f1ddSLingrui98 // } 171909c6f1ddSLingrui98 // } 172009c6f1ddSLingrui98 172109c6f1ddSLingrui98 // def btbCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 172209c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 172309c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 172409c6f1ddSLingrui98 // Mux(valid && pd.isBr, 172509c6f1ddSLingrui98 // isWrong ^ Mux(ans.hit.asBool, 172609c6f1ddSLingrui98 // Mux(ans.taken.asBool, taken && ans.target === commitEntry.target, 172709c6f1ddSLingrui98 // !taken), 172809c6f1ddSLingrui98 // !taken), 172909c6f1ddSLingrui98 // false.B) 173009c6f1ddSLingrui98 // } 173109c6f1ddSLingrui98 // } 173209c6f1ddSLingrui98 173309c6f1ddSLingrui98 // def tageCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 173409c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 173509c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 173609c6f1ddSLingrui98 // Mux(valid && pd.isBr, 173709c6f1ddSLingrui98 // isWrong ^ (ans.taken.asBool === taken), 173809c6f1ddSLingrui98 // false.B) 173909c6f1ddSLingrui98 // } 174009c6f1ddSLingrui98 // } 174109c6f1ddSLingrui98 174209c6f1ddSLingrui98 // def loopCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 174309c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 174409c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 174509c6f1ddSLingrui98 // Mux(valid && (pd.isBr) && ans.hit.asBool, 174609c6f1ddSLingrui98 // isWrong ^ (!taken), 174709c6f1ddSLingrui98 // false.B) 174809c6f1ddSLingrui98 // } 174909c6f1ddSLingrui98 // } 175009c6f1ddSLingrui98 175109c6f1ddSLingrui98 // def rasCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 175209c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 175309c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 175409c6f1ddSLingrui98 // Mux(valid && pd.isRet.asBool /*&& taken*/ && ans.hit.asBool, 175509c6f1ddSLingrui98 // isWrong ^ (ans.target === commitEntry.target), 175609c6f1ddSLingrui98 // false.B) 175709c6f1ddSLingrui98 // } 175809c6f1ddSLingrui98 // } 175909c6f1ddSLingrui98 176009c6f1ddSLingrui98 // val ubtbRights = ubtbCheck(commitEntry, commitEntry.metas.map(_.ubtbAns), false.B) 176109c6f1ddSLingrui98 // val ubtbWrongs = ubtbCheck(commitEntry, commitEntry.metas.map(_.ubtbAns), true.B) 176209c6f1ddSLingrui98 // // btb and ubtb pred jal and jalr as well 176309c6f1ddSLingrui98 // val btbRights = btbCheck(commitEntry, commitEntry.metas.map(_.btbAns), false.B) 176409c6f1ddSLingrui98 // val btbWrongs = btbCheck(commitEntry, commitEntry.metas.map(_.btbAns), true.B) 176509c6f1ddSLingrui98 // val tageRights = tageCheck(commitEntry, commitEntry.metas.map(_.tageAns), false.B) 176609c6f1ddSLingrui98 // val tageWrongs = tageCheck(commitEntry, commitEntry.metas.map(_.tageAns), true.B) 176709c6f1ddSLingrui98 176809c6f1ddSLingrui98 // val loopRights = loopCheck(commitEntry, commitEntry.metas.map(_.loopAns), false.B) 176909c6f1ddSLingrui98 // val loopWrongs = loopCheck(commitEntry, commitEntry.metas.map(_.loopAns), true.B) 177009c6f1ddSLingrui98 177109c6f1ddSLingrui98 // val rasRights = rasCheck(commitEntry, commitEntry.metas.map(_.rasAns), false.B) 177209c6f1ddSLingrui98 // val rasWrongs = rasCheck(commitEntry, commitEntry.metas.map(_.rasAns), true.B) 17731ca0e4f3SYinan Xu 1774cd365d4cSrvcoresjw val perfEvents = Seq( 1775cd365d4cSrvcoresjw ("bpu_s2_redirect ", bpu_s2_redirect), 1776cb4f77ceSLingrui98 ("bpu_s3_redirect ", bpu_s3_redirect), 1777cd365d4cSrvcoresjw ("bpu_to_ftq_stall ", enq.valid && ~enq.ready), 1778cd365d4cSrvcoresjw ("mispredictRedirect ", perf_redirect.valid && RedirectLevel.flushAfter === perf_redirect.bits.level), 1779cd365d4cSrvcoresjw ("replayRedirect ", perf_redirect.valid && RedirectLevel.flushItself(perf_redirect.bits.level)), 1780cd365d4cSrvcoresjw ("predecodeRedirect ", fromIfuRedirect.valid), 1781cd365d4cSrvcoresjw ("to_ifu_bubble ", io.toIfu.req.ready && !io.toIfu.req.valid), 1782cd365d4cSrvcoresjw ("from_bpu_real_bubble ", !enq.valid && enq.ready && allowBpuIn), 1783cd365d4cSrvcoresjw ("BpInstr ", PopCount(mbpInstrs)), 1784cd365d4cSrvcoresjw ("BpBInstr ", PopCount(mbpBRights | mbpBWrongs)), 1785cd365d4cSrvcoresjw ("BpRight ", PopCount(mbpRights)), 1786cd365d4cSrvcoresjw ("BpWrong ", PopCount(mbpWrongs)), 1787cd365d4cSrvcoresjw ("BpBRight ", PopCount(mbpBRights)), 1788cd365d4cSrvcoresjw ("BpBWrong ", PopCount(mbpBWrongs)), 1789cd365d4cSrvcoresjw ("BpJRight ", PopCount(mbpJRights)), 1790cd365d4cSrvcoresjw ("BpJWrong ", PopCount(mbpJWrongs)), 1791cd365d4cSrvcoresjw ("BpIRight ", PopCount(mbpIRights)), 1792cd365d4cSrvcoresjw ("BpIWrong ", PopCount(mbpIWrongs)), 1793cd365d4cSrvcoresjw ("BpCRight ", PopCount(mbpCRights)), 1794cd365d4cSrvcoresjw ("BpCWrong ", PopCount(mbpCWrongs)), 1795cd365d4cSrvcoresjw ("BpRRight ", PopCount(mbpRRights)), 1796cd365d4cSrvcoresjw ("BpRWrong ", PopCount(mbpRWrongs)), 1797cd365d4cSrvcoresjw ("ftb_false_hit ", PopCount(ftb_false_hit)), 1798cf7d6b7aSMuzi ("ftb_hit ", PopCount(ftb_hit)) 1799cd365d4cSrvcoresjw ) 18001ca0e4f3SYinan Xu generatePerfEvent() 180109c6f1ddSLingrui98} 1802