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. 1509c6f1ddSLingrui98***************************************************************************************/ 1609c6f1ddSLingrui98 1709c6f1ddSLingrui98package xiangshan.frontend 1809c6f1ddSLingrui98 1909c6f1ddSLingrui98import chisel3._ 2009c6f1ddSLingrui98import chisel3.util._ 21cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters 223c02ee8fSwakafaimport utility._ 23cf7d6b7aSMuziimport utility.ChiselDB 24cf7d6b7aSMuziimport utils._ 2509c6f1ddSLingrui98import xiangshan._ 261ca0e4f3SYinan Xuimport xiangshan.backend.CtrlToFtqIO 272e1be6e1SSteve Gouimport xiangshan.backend.decode.ImmUnion 28cf7d6b7aSMuziimport xiangshan.frontend.icache._ 2951532d8bSGuokai Chen 3051532d8bSGuokai Chenclass FtqDebugBundle extends Bundle { 3151532d8bSGuokai Chen val pc = UInt(39.W) 3251532d8bSGuokai Chen val target = UInt(39.W) 3351532d8bSGuokai Chen val isBr = Bool() 3451532d8bSGuokai Chen val isJmp = Bool() 3551532d8bSGuokai Chen val isCall = Bool() 3651532d8bSGuokai Chen val isRet = Bool() 3751532d8bSGuokai Chen val misPred = Bool() 3851532d8bSGuokai Chen val isTaken = Bool() 3951532d8bSGuokai Chen val predStage = UInt(2.W) 4051532d8bSGuokai Chen} 4109c6f1ddSLingrui98 423b739f49SXuan Huclass FtqPtr(entries: Int) extends CircularQueuePtr[FtqPtr]( 433b739f49SXuan Hu entries 4409c6f1ddSLingrui98 ) { 453b739f49SXuan Hu def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).FtqSize) 4609c6f1ddSLingrui98} 4709c6f1ddSLingrui98 4809c6f1ddSLingrui98object FtqPtr { 4909c6f1ddSLingrui98 def apply(f: Bool, v: UInt)(implicit p: Parameters): FtqPtr = { 5009c6f1ddSLingrui98 val ptr = Wire(new FtqPtr) 5109c6f1ddSLingrui98 ptr.flag := f 5209c6f1ddSLingrui98 ptr.value := v 5309c6f1ddSLingrui98 ptr 5409c6f1ddSLingrui98 } 55cf7d6b7aSMuzi def inverse(ptr: FtqPtr)(implicit p: Parameters): FtqPtr = 5609c6f1ddSLingrui98 apply(!ptr.flag, ptr.value) 5709c6f1ddSLingrui98} 5809c6f1ddSLingrui98 5909c6f1ddSLingrui98class FtqNRSRAM[T <: Data](gen: T, numRead: Int)(implicit p: Parameters) extends XSModule { 6009c6f1ddSLingrui98 6109c6f1ddSLingrui98 val io = IO(new Bundle() { 6209c6f1ddSLingrui98 val raddr = Input(Vec(numRead, UInt(log2Up(FtqSize).W))) 6309c6f1ddSLingrui98 val ren = Input(Vec(numRead, Bool())) 6409c6f1ddSLingrui98 val rdata = Output(Vec(numRead, gen)) 6509c6f1ddSLingrui98 val waddr = Input(UInt(log2Up(FtqSize).W)) 6609c6f1ddSLingrui98 val wen = Input(Bool()) 6709c6f1ddSLingrui98 val wdata = Input(gen) 6809c6f1ddSLingrui98 }) 6909c6f1ddSLingrui98 7009c6f1ddSLingrui98 for (i <- 0 until numRead) { 7109c6f1ddSLingrui98 val sram = Module(new SRAMTemplate(gen, FtqSize)) 7209c6f1ddSLingrui98 sram.io.r.req.valid := io.ren(i) 7309c6f1ddSLingrui98 sram.io.r.req.bits.setIdx := io.raddr(i) 7409c6f1ddSLingrui98 io.rdata(i) := sram.io.r.resp.data(0) 7509c6f1ddSLingrui98 sram.io.w.req.valid := io.wen 7609c6f1ddSLingrui98 sram.io.w.req.bits.setIdx := io.waddr 7709c6f1ddSLingrui98 sram.io.w.req.bits.data := VecInit(io.wdata) 7809c6f1ddSLingrui98 } 7909c6f1ddSLingrui98 8009c6f1ddSLingrui98} 8109c6f1ddSLingrui98 8209c6f1ddSLingrui98class Ftq_RF_Components(implicit p: Parameters) extends XSBundle with BPUUtils { 8309c6f1ddSLingrui98 val startAddr = UInt(VAddrBits.W) 84b37e4b45SLingrui98 val nextLineAddr = UInt(VAddrBits.W) 8509c6f1ddSLingrui98 val isNextMask = Vec(PredictWidth, Bool()) 86b37e4b45SLingrui98 val fallThruError = Bool() 87b37e4b45SLingrui98 // val carry = Bool() 8809c6f1ddSLingrui98 def getPc(offset: UInt) = { 8985215037SLingrui98 def getHigher(pc: UInt) = pc(VAddrBits - 1, log2Ceil(PredictWidth) + instOffsetBits + 1) 9085215037SLingrui98 def getOffset(pc: UInt) = pc(log2Ceil(PredictWidth) + instOffsetBits, instOffsetBits) 91cf7d6b7aSMuzi Cat( 92cf7d6b7aSMuzi getHigher(Mux(isNextMask(offset) && startAddr(log2Ceil(PredictWidth) + instOffsetBits), nextLineAddr, startAddr)), 93cf7d6b7aSMuzi getOffset(startAddr) + offset, 94cf7d6b7aSMuzi 0.U(instOffsetBits.W) 95cf7d6b7aSMuzi ) 9609c6f1ddSLingrui98 } 9709c6f1ddSLingrui98 def fromBranchPrediction(resp: BranchPredictionBundle) = { 98a229ab6cSLingrui98 def carryPos(addr: UInt) = addr(instOffsetBits + log2Ceil(PredictWidth) + 1) 99adc0b8dfSGuokai Chen this.startAddr := resp.pc(3) 100adc0b8dfSGuokai Chen this.nextLineAddr := resp.pc(3) + (FetchWidth * 4 * 2).U // may be broken on other configs 10109c6f1ddSLingrui98 this.isNextMask := VecInit((0 until PredictWidth).map(i => 102935edac4STang Haojin (resp.pc(3)(log2Ceil(PredictWidth), 1) +& i.U)(log2Ceil(PredictWidth)).asBool 10309c6f1ddSLingrui98 )) 104adc0b8dfSGuokai Chen this.fallThruError := resp.fallThruError(3) 10509c6f1ddSLingrui98 this 10609c6f1ddSLingrui98 } 107cf7d6b7aSMuzi override def toPrintable: Printable = 108b37e4b45SLingrui98 p"startAddr:${Hexadecimal(startAddr)}" 10909c6f1ddSLingrui98} 11009c6f1ddSLingrui98 11109c6f1ddSLingrui98class Ftq_pd_Entry(implicit p: Parameters) extends XSBundle { 11209c6f1ddSLingrui98 val brMask = Vec(PredictWidth, Bool()) 11309c6f1ddSLingrui98 val jmpInfo = ValidUndirectioned(Vec(3, Bool())) 11409c6f1ddSLingrui98 val jmpOffset = UInt(log2Ceil(PredictWidth).W) 11509c6f1ddSLingrui98 val jalTarget = UInt(VAddrBits.W) 11609c6f1ddSLingrui98 val rvcMask = Vec(PredictWidth, Bool()) 11709c6f1ddSLingrui98 def hasJal = jmpInfo.valid && !jmpInfo.bits(0) 11809c6f1ddSLingrui98 def hasJalr = jmpInfo.valid && jmpInfo.bits(0) 11909c6f1ddSLingrui98 def hasCall = jmpInfo.valid && jmpInfo.bits(1) 12009c6f1ddSLingrui98 def hasRet = jmpInfo.valid && jmpInfo.bits(2) 12109c6f1ddSLingrui98 12209c6f1ddSLingrui98 def fromPdWb(pdWb: PredecodeWritebackBundle) = { 12309c6f1ddSLingrui98 val pds = pdWb.pd 12409c6f1ddSLingrui98 this.brMask := VecInit(pds.map(pd => pd.isBr && pd.valid)) 12509c6f1ddSLingrui98 this.jmpInfo.valid := VecInit(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid)).asUInt.orR 126cf7d6b7aSMuzi this.jmpInfo.bits := ParallelPriorityMux( 127cf7d6b7aSMuzi pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid), 128cf7d6b7aSMuzi pds.map(pd => VecInit(pd.isJalr, pd.isCall, pd.isRet)) 129cf7d6b7aSMuzi ) 13009c6f1ddSLingrui98 this.jmpOffset := ParallelPriorityEncoder(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid)) 13109c6f1ddSLingrui98 this.rvcMask := VecInit(pds.map(pd => pd.isRVC)) 13209c6f1ddSLingrui98 this.jalTarget := pdWb.jalTarget 13309c6f1ddSLingrui98 } 13409c6f1ddSLingrui98 13509c6f1ddSLingrui98 def toPd(offset: UInt) = { 13609c6f1ddSLingrui98 require(offset.getWidth == log2Ceil(PredictWidth)) 13709c6f1ddSLingrui98 val pd = Wire(new PreDecodeInfo) 13809c6f1ddSLingrui98 pd.valid := true.B 13909c6f1ddSLingrui98 pd.isRVC := rvcMask(offset) 14009c6f1ddSLingrui98 val isBr = brMask(offset) 14109c6f1ddSLingrui98 val isJalr = offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(0) 14209c6f1ddSLingrui98 pd.brType := Cat(offset === jmpOffset && jmpInfo.valid, isJalr || isBr) 14309c6f1ddSLingrui98 pd.isCall := offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(1) 14409c6f1ddSLingrui98 pd.isRet := offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(2) 14509c6f1ddSLingrui98 pd 14609c6f1ddSLingrui98 } 14709c6f1ddSLingrui98} 14809c6f1ddSLingrui98 149f9c51548Sssszwicclass PrefetchPtrDB(implicit p: Parameters) extends Bundle { 150f9c51548Sssszwic val fromFtqPtr = UInt(log2Up(p(XSCoreParamsKey).FtqSize).W) 151f9c51548Sssszwic val fromIfuPtr = UInt(log2Up(p(XSCoreParamsKey).FtqSize).W) 152f9c51548Sssszwic} 15309c6f1ddSLingrui98 1543711cf36S小造xu_zhclass Ftq_Redirect_SRAMEntry(implicit p: Parameters) extends SpeculativeInfo { 155abdc3a32Sxu_zh val sc_disagree = if (!env.FPGAPlatform) Some(Vec(numBr, Bool())) else None 1563711cf36S小造xu_zh} 15709c6f1ddSLingrui98 15809c6f1ddSLingrui98class Ftq_1R_SRAMEntry(implicit p: Parameters) extends XSBundle with HasBPUConst { 15909c6f1ddSLingrui98 val meta = UInt(MaxMetaLength.W) 160deb3a97eSGao-Zeyu val ftb_entry = new FTBEntry 16109c6f1ddSLingrui98} 16209c6f1ddSLingrui98 16309c6f1ddSLingrui98class Ftq_Pred_Info(implicit p: Parameters) extends XSBundle { 16409c6f1ddSLingrui98 val target = UInt(VAddrBits.W) 16509c6f1ddSLingrui98 val cfiIndex = ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)) 16609c6f1ddSLingrui98} 16709c6f1ddSLingrui98 16809c6f1ddSLingrui98class FtqRead[T <: Data](private val gen: T)(implicit p: Parameters) extends XSBundle { 16954c6d89dSxiaofeibao-xjtu val valid = Output(Bool()) 17009c6f1ddSLingrui98 val ptr = Output(new FtqPtr) 17109c6f1ddSLingrui98 val offset = Output(UInt(log2Ceil(PredictWidth).W)) 17209c6f1ddSLingrui98 val data = Input(gen) 17354c6d89dSxiaofeibao-xjtu def apply(valid: Bool, ptr: FtqPtr, offset: UInt) = { 17454c6d89dSxiaofeibao-xjtu this.valid := valid 17509c6f1ddSLingrui98 this.ptr := ptr 17609c6f1ddSLingrui98 this.offset := offset 17709c6f1ddSLingrui98 this.data 17809c6f1ddSLingrui98 } 17909c6f1ddSLingrui98} 18009c6f1ddSLingrui98 18109c6f1ddSLingrui98class FtqToBpuIO(implicit p: Parameters) extends XSBundle { 18209c6f1ddSLingrui98 val redirect = Valid(new BranchPredictionRedirect) 18309c6f1ddSLingrui98 val update = Valid(new BranchPredictionUpdate) 18409c6f1ddSLingrui98 val enq_ptr = Output(new FtqPtr) 185fd3aa057SYuandongliang val redirctFromIFU = Output(Bool()) 18609c6f1ddSLingrui98} 18709c6f1ddSLingrui98 1882c9f4a9fSxu_zhclass BpuFlushInfo(implicit p: Parameters) extends XSBundle with HasCircularQueuePtrHelper { 18909c6f1ddSLingrui98 // when ifu pipeline is not stalled, 19009c6f1ddSLingrui98 // a packet from bpu s3 can reach f1 at most 19109c6f1ddSLingrui98 val s2 = Valid(new FtqPtr) 192cb4f77ceSLingrui98 val s3 = Valid(new FtqPtr) 193cf7d6b7aSMuzi def shouldFlushBy(src: Valid[FtqPtr], idx_to_flush: FtqPtr) = 19409c6f1ddSLingrui98 src.valid && !isAfter(src.bits, idx_to_flush) 19509c6f1ddSLingrui98 def shouldFlushByStage2(idx: FtqPtr) = shouldFlushBy(s2, idx) 196cb4f77ceSLingrui98 def shouldFlushByStage3(idx: FtqPtr) = shouldFlushBy(s3, idx) 19709c6f1ddSLingrui98} 1982c9f4a9fSxu_zh 1992c9f4a9fSxu_zhclass FtqToIfuIO(implicit p: Parameters) extends XSBundle { 2002c9f4a9fSxu_zh val req = Decoupled(new FetchRequestBundle) 2012c9f4a9fSxu_zh val redirect = Valid(new BranchPredictionRedirect) 2022c9f4a9fSxu_zh val topdown_redirect = Valid(new BranchPredictionRedirect) 2032c9f4a9fSxu_zh val flushFromBpu = new BpuFlushInfo 20409c6f1ddSLingrui98} 20509c6f1ddSLingrui98 2062c9f4a9fSxu_zhclass FtqToICacheIO(implicit p: Parameters) extends XSBundle { 207c5c5edaeSJenius // NOTE: req.bits must be prepare in T cycle 208c5c5edaeSJenius // while req.valid is set true in T + 1 cycle 209c5c5edaeSJenius val req = Decoupled(new FtqToICacheRequestBundle) 210c5c5edaeSJenius} 211c5c5edaeSJenius 2122c9f4a9fSxu_zhclass FtqToPrefetchIO(implicit p: Parameters) extends XSBundle { 213b92f8445Sssszwic val req = Decoupled(new FtqICacheInfo) 2142c9f4a9fSxu_zh val flushFromBpu = new BpuFlushInfo 215b92f8445Sssszwic} 216b92f8445Sssszwic 21709c6f1ddSLingrui98trait HasBackendRedirectInfo extends HasXSParameter { 21809c6f1ddSLingrui98 def isLoadReplay(r: Valid[Redirect]) = r.bits.flushItself() 21909c6f1ddSLingrui98} 22009c6f1ddSLingrui98 22109c6f1ddSLingrui98class FtqToCtrlIO(implicit p: Parameters) extends XSBundle with HasBackendRedirectInfo { 222b56f947eSYinan Xu // write to backend pc mem 223b56f947eSYinan Xu val pc_mem_wen = Output(Bool()) 224f533cba7SHuSipeng val pc_mem_waddr = Output(UInt(log2Ceil(FtqSize).W)) 225b56f947eSYinan Xu val pc_mem_wdata = Output(new Ftq_RF_Components) 226873dc383SLingrui98 // newest target 2276022c595SsinceforYy val newest_entry_en = Output(Bool()) 228873dc383SLingrui98 val newest_entry_target = Output(UInt(VAddrBits.W)) 229873dc383SLingrui98 val newest_entry_ptr = Output(new FtqPtr) 23009c6f1ddSLingrui98} 23109c6f1ddSLingrui98 23209c6f1ddSLingrui98class FTBEntryGen(implicit p: Parameters) extends XSModule with HasBackendRedirectInfo with HasBPUParameter { 23309c6f1ddSLingrui98 val io = IO(new Bundle { 23409c6f1ddSLingrui98 val start_addr = Input(UInt(VAddrBits.W)) 23509c6f1ddSLingrui98 val old_entry = Input(new FTBEntry) 23609c6f1ddSLingrui98 val pd = Input(new Ftq_pd_Entry) 23709c6f1ddSLingrui98 val cfiIndex = Flipped(Valid(UInt(log2Ceil(PredictWidth).W))) 23809c6f1ddSLingrui98 val target = Input(UInt(VAddrBits.W)) 23909c6f1ddSLingrui98 val hit = Input(Bool()) 24009c6f1ddSLingrui98 val mispredict_vec = Input(Vec(PredictWidth, Bool())) 24109c6f1ddSLingrui98 24209c6f1ddSLingrui98 val new_entry = Output(new FTBEntry) 24309c6f1ddSLingrui98 val new_br_insert_pos = Output(Vec(numBr, Bool())) 24409c6f1ddSLingrui98 val taken_mask = Output(Vec(numBr, Bool())) 245803124a6SLingrui98 val jmp_taken = Output(Bool()) 24609c6f1ddSLingrui98 val mispred_mask = Output(Vec(numBr + 1, Bool())) 24709c6f1ddSLingrui98 24809c6f1ddSLingrui98 // for perf counters 24909c6f1ddSLingrui98 val is_init_entry = Output(Bool()) 25009c6f1ddSLingrui98 val is_old_entry = Output(Bool()) 25109c6f1ddSLingrui98 val is_new_br = Output(Bool()) 25209c6f1ddSLingrui98 val is_jalr_target_modified = Output(Bool()) 253*dcf4211fSYuandongliang val is_strong_bias_modified = Output(Bool()) 25409c6f1ddSLingrui98 val is_br_full = Output(Bool()) 25509c6f1ddSLingrui98 }) 25609c6f1ddSLingrui98 25709c6f1ddSLingrui98 // no mispredictions detected at predecode 25809c6f1ddSLingrui98 val hit = io.hit 25909c6f1ddSLingrui98 val pd = io.pd 26009c6f1ddSLingrui98 26109c6f1ddSLingrui98 val init_entry = WireInit(0.U.asTypeOf(new FTBEntry)) 26209c6f1ddSLingrui98 26309c6f1ddSLingrui98 val cfi_is_br = pd.brMask(io.cfiIndex.bits) && io.cfiIndex.valid 26409c6f1ddSLingrui98 val entry_has_jmp = pd.jmpInfo.valid 26509c6f1ddSLingrui98 val new_jmp_is_jal = entry_has_jmp && !pd.jmpInfo.bits(0) && io.cfiIndex.valid 26609c6f1ddSLingrui98 val new_jmp_is_jalr = entry_has_jmp && pd.jmpInfo.bits(0) && io.cfiIndex.valid 26709c6f1ddSLingrui98 val new_jmp_is_call = entry_has_jmp && pd.jmpInfo.bits(1) && io.cfiIndex.valid 26809c6f1ddSLingrui98 val new_jmp_is_ret = entry_has_jmp && pd.jmpInfo.bits(2) && io.cfiIndex.valid 26909c6f1ddSLingrui98 val last_jmp_rvi = entry_has_jmp && pd.jmpOffset === (PredictWidth - 1).U && !pd.rvcMask.last 270a60a2901SLingrui98 // val last_br_rvi = cfi_is_br && io.cfiIndex.bits === (PredictWidth-1).U && !pd.rvcMask.last 27109c6f1ddSLingrui98 27209c6f1ddSLingrui98 val cfi_is_jal = io.cfiIndex.bits === pd.jmpOffset && new_jmp_is_jal 27309c6f1ddSLingrui98 val cfi_is_jalr = io.cfiIndex.bits === pd.jmpOffset && new_jmp_is_jalr 27409c6f1ddSLingrui98 275a60a2901SLingrui98 def carryPos = log2Ceil(PredictWidth) + instOffsetBits 27609c6f1ddSLingrui98 def getLower(pc: UInt) = pc(carryPos - 1, instOffsetBits) 27709c6f1ddSLingrui98 // if not hit, establish a new entry 27809c6f1ddSLingrui98 init_entry.valid := true.B 27909c6f1ddSLingrui98 // tag is left for ftb to assign 280eeb5ff92SLingrui98 281eeb5ff92SLingrui98 // case br 282eeb5ff92SLingrui98 val init_br_slot = init_entry.getSlotForBr(0) 283eeb5ff92SLingrui98 when(cfi_is_br) { 284eeb5ff92SLingrui98 init_br_slot.valid := true.B 285eeb5ff92SLingrui98 init_br_slot.offset := io.cfiIndex.bits 286b37e4b45SLingrui98 init_br_slot.setLowerStatByTarget(io.start_addr, io.target, numBr == 1) 287*dcf4211fSYuandongliang init_entry.strong_bias(0) := true.B // set to strong bias on init 288eeb5ff92SLingrui98 } 289eeb5ff92SLingrui98 290eeb5ff92SLingrui98 // case jmp 291eeb5ff92SLingrui98 when(entry_has_jmp) { 292eeb5ff92SLingrui98 init_entry.tailSlot.offset := pd.jmpOffset 293eeb5ff92SLingrui98 init_entry.tailSlot.valid := new_jmp_is_jal || new_jmp_is_jalr 294eeb5ff92SLingrui98 init_entry.tailSlot.setLowerStatByTarget(io.start_addr, Mux(cfi_is_jalr, io.target, pd.jalTarget), isShare = false) 295*dcf4211fSYuandongliang init_entry.strong_bias(numBr - 1) := new_jmp_is_jalr // set strong bias for the jalr on init 296eeb5ff92SLingrui98 } 297eeb5ff92SLingrui98 29809c6f1ddSLingrui98 val jmpPft = getLower(io.start_addr) +& pd.jmpOffset +& Mux(pd.rvcMask(pd.jmpOffset), 1.U, 2.U) 299a60a2901SLingrui98 init_entry.pftAddr := Mux(entry_has_jmp && !last_jmp_rvi, jmpPft, getLower(io.start_addr)) 300a60a2901SLingrui98 init_entry.carry := Mux(entry_has_jmp && !last_jmp_rvi, jmpPft(carryPos - instOffsetBits), true.B) 30109c6f1ddSLingrui98 init_entry.isJalr := new_jmp_is_jalr 30209c6f1ddSLingrui98 init_entry.isCall := new_jmp_is_call 30309c6f1ddSLingrui98 init_entry.isRet := new_jmp_is_ret 304f4ebc4b2SLingrui98 // that means fall thru points to the middle of an inst 305ae409b75SSteve Gou init_entry.last_may_be_rvi_call := pd.jmpOffset === (PredictWidth - 1).U && !pd.rvcMask(pd.jmpOffset) 30609c6f1ddSLingrui98 30709c6f1ddSLingrui98 // if hit, check whether a new cfi(only br is possible) is detected 30809c6f1ddSLingrui98 val oe = io.old_entry 309eeb5ff92SLingrui98 val br_recorded_vec = oe.getBrRecordedVec(io.cfiIndex.bits) 31009c6f1ddSLingrui98 val br_recorded = br_recorded_vec.asUInt.orR 31109c6f1ddSLingrui98 val is_new_br = cfi_is_br && !br_recorded 31209c6f1ddSLingrui98 val new_br_offset = io.cfiIndex.bits 31309c6f1ddSLingrui98 // vec(i) means new br will be inserted BEFORE old br(i) 314eeb5ff92SLingrui98 val allBrSlotsVec = oe.allSlotsForBr 31509c6f1ddSLingrui98 val new_br_insert_onehot = VecInit((0 until numBr).map { 316cf7d6b7aSMuzi i => 317cf7d6b7aSMuzi i match { 318eeb5ff92SLingrui98 case 0 => 319eeb5ff92SLingrui98 !allBrSlotsVec(0).valid || new_br_offset < allBrSlotsVec(0).offset 320eeb5ff92SLingrui98 case idx => 321eeb5ff92SLingrui98 allBrSlotsVec(idx - 1).valid && new_br_offset > allBrSlotsVec(idx - 1).offset && 322eeb5ff92SLingrui98 (!allBrSlotsVec(idx).valid || new_br_offset < allBrSlotsVec(idx).offset) 32309c6f1ddSLingrui98 } 32409c6f1ddSLingrui98 }) 32509c6f1ddSLingrui98 32609c6f1ddSLingrui98 val old_entry_modified = WireInit(io.old_entry) 32709c6f1ddSLingrui98 for (i <- 0 until numBr) { 328eeb5ff92SLingrui98 val slot = old_entry_modified.allSlotsForBr(i) 329eeb5ff92SLingrui98 when(new_br_insert_onehot(i)) { 330eeb5ff92SLingrui98 slot.valid := true.B 331eeb5ff92SLingrui98 slot.offset := new_br_offset 332b37e4b45SLingrui98 slot.setLowerStatByTarget(io.start_addr, io.target, i == numBr - 1) 333*dcf4211fSYuandongliang old_entry_modified.strong_bias(i) := true.B 334eeb5ff92SLingrui98 }.elsewhen(new_br_offset > oe.allSlotsForBr(i).offset) { 335*dcf4211fSYuandongliang old_entry_modified.strong_bias(i) := false.B 336eeb5ff92SLingrui98 // all other fields remain unchanged 337eeb5ff92SLingrui98 }.otherwise { 338eeb5ff92SLingrui98 // case i == 0, remain unchanged 339eeb5ff92SLingrui98 if (i != 0) { 340b37e4b45SLingrui98 val noNeedToMoveFromFormerSlot = (i == numBr - 1).B && !oe.brSlots.last.valid 341eeb5ff92SLingrui98 when(!noNeedToMoveFromFormerSlot) { 342eeb5ff92SLingrui98 slot.fromAnotherSlot(oe.allSlotsForBr(i - 1)) 343*dcf4211fSYuandongliang old_entry_modified.strong_bias(i) := oe.strong_bias(i) 34409c6f1ddSLingrui98 } 345eeb5ff92SLingrui98 } 346eeb5ff92SLingrui98 } 347eeb5ff92SLingrui98 } 34809c6f1ddSLingrui98 349eeb5ff92SLingrui98 // two circumstances: 350eeb5ff92SLingrui98 // 1. oe: | br | j |, new br should be in front of j, thus addr of j should be new pft 351eeb5ff92SLingrui98 // 2. oe: | br | br |, new br could be anywhere between, thus new pft is the addr of either 352eeb5ff92SLingrui98 // the previous last br or the new br 353eeb5ff92SLingrui98 val may_have_to_replace = oe.noEmptySlotForNewBr 354eeb5ff92SLingrui98 val pft_need_to_change = is_new_br && may_have_to_replace 35509c6f1ddSLingrui98 // it should either be the given last br or the new br 35609c6f1ddSLingrui98 when(pft_need_to_change) { 357eeb5ff92SLingrui98 val new_pft_offset = 358cf7d6b7aSMuzi Mux(!new_br_insert_onehot.asUInt.orR, new_br_offset, oe.allSlotsForBr.last.offset) 359eeb5ff92SLingrui98 360710a8720SLingrui98 // set jmp to invalid 36109c6f1ddSLingrui98 old_entry_modified.pftAddr := getLower(io.start_addr) + new_pft_offset 36209c6f1ddSLingrui98 old_entry_modified.carry := (getLower(io.start_addr) +& new_pft_offset).head(1).asBool 363f4ebc4b2SLingrui98 old_entry_modified.last_may_be_rvi_call := false.B 36409c6f1ddSLingrui98 old_entry_modified.isCall := false.B 36509c6f1ddSLingrui98 old_entry_modified.isRet := false.B 366eeb5ff92SLingrui98 old_entry_modified.isJalr := false.B 36709c6f1ddSLingrui98 } 36809c6f1ddSLingrui98 36909c6f1ddSLingrui98 val old_entry_jmp_target_modified = WireInit(oe) 370710a8720SLingrui98 val old_target = oe.tailSlot.getTarget(io.start_addr) // may be wrong because we store only 20 lowest bits 371b37e4b45SLingrui98 val old_tail_is_jmp = !oe.tailSlot.sharing 372eeb5ff92SLingrui98 val jalr_target_modified = cfi_is_jalr && (old_target =/= io.target) && old_tail_is_jmp // TODO: pass full jalr target 3733bcae573SLingrui98 when(jalr_target_modified) { 37409c6f1ddSLingrui98 old_entry_jmp_target_modified.setByJmpTarget(io.start_addr, io.target) 375*dcf4211fSYuandongliang old_entry_jmp_target_modified.strong_bias := 0.U.asTypeOf(Vec(numBr, Bool())) 37609c6f1ddSLingrui98 } 37709c6f1ddSLingrui98 378*dcf4211fSYuandongliang val old_entry_strong_bias = WireInit(oe) 379*dcf4211fSYuandongliang val strong_bias_modified_vec = Wire(Vec(numBr, Bool())) // whether modified or not 38009c6f1ddSLingrui98 for (i <- 0 until numBr) { 381*dcf4211fSYuandongliang when(br_recorded_vec(0)) { 382*dcf4211fSYuandongliang old_entry_strong_bias.strong_bias(0) := 383*dcf4211fSYuandongliang oe.strong_bias(0) && io.cfiIndex.valid && oe.brValids(0) && io.cfiIndex.bits === oe.brOffset(0) 384*dcf4211fSYuandongliang }.elsewhen(br_recorded_vec(numBr - 1)) { 385*dcf4211fSYuandongliang old_entry_strong_bias.strong_bias(0) := false.B 386*dcf4211fSYuandongliang old_entry_strong_bias.strong_bias(numBr - 1) := 387*dcf4211fSYuandongliang oe.strong_bias(numBr - 1) && io.cfiIndex.valid && oe.brValids(numBr - 1) && io.cfiIndex.bits === oe.brOffset( 388*dcf4211fSYuandongliang numBr - 1 389*dcf4211fSYuandongliang ) 39009c6f1ddSLingrui98 } 391*dcf4211fSYuandongliang strong_bias_modified_vec(i) := oe.strong_bias(i) && oe.brValids(i) && !old_entry_strong_bias.strong_bias(i) 392*dcf4211fSYuandongliang } 393*dcf4211fSYuandongliang val strong_bias_modified = strong_bias_modified_vec.reduce(_ || _) 39409c6f1ddSLingrui98 39509c6f1ddSLingrui98 val derived_from_old_entry = 396*dcf4211fSYuandongliang Mux(is_new_br, old_entry_modified, Mux(jalr_target_modified, old_entry_jmp_target_modified, old_entry_strong_bias)) 39709c6f1ddSLingrui98 39809c6f1ddSLingrui98 io.new_entry := Mux(!hit, init_entry, derived_from_old_entry) 39909c6f1ddSLingrui98 40009c6f1ddSLingrui98 io.new_br_insert_pos := new_br_insert_onehot 40109c6f1ddSLingrui98 io.taken_mask := VecInit((io.new_entry.brOffset zip io.new_entry.brValids).map { 40209c6f1ddSLingrui98 case (off, v) => io.cfiIndex.bits === off && io.cfiIndex.valid && v 40309c6f1ddSLingrui98 }) 404803124a6SLingrui98 io.jmp_taken := io.new_entry.jmpValid && io.new_entry.tailSlot.offset === io.cfiIndex.bits 40509c6f1ddSLingrui98 for (i <- 0 until numBr) { 40609c6f1ddSLingrui98 io.mispred_mask(i) := io.new_entry.brValids(i) && io.mispredict_vec(io.new_entry.brOffset(i)) 40709c6f1ddSLingrui98 } 40809c6f1ddSLingrui98 io.mispred_mask.last := io.new_entry.jmpValid && io.mispredict_vec(pd.jmpOffset) 40909c6f1ddSLingrui98 41009c6f1ddSLingrui98 // for perf counters 41109c6f1ddSLingrui98 io.is_init_entry := !hit 412*dcf4211fSYuandongliang io.is_old_entry := hit && !is_new_br && !jalr_target_modified && !strong_bias_modified 41309c6f1ddSLingrui98 io.is_new_br := hit && is_new_br 4143bcae573SLingrui98 io.is_jalr_target_modified := hit && jalr_target_modified 415*dcf4211fSYuandongliang io.is_strong_bias_modified := hit && strong_bias_modified 416eeb5ff92SLingrui98 io.is_br_full := hit && is_new_br && may_have_to_replace 41709c6f1ddSLingrui98} 41809c6f1ddSLingrui98 419c5c5edaeSJeniusclass FtqPcMemWrapper(numOtherReads: Int)(implicit p: Parameters) extends XSModule with HasBackendRedirectInfo { 420c5c5edaeSJenius val io = IO(new Bundle { 421c5c5edaeSJenius val ifuPtr_w = Input(new FtqPtr) 422c5c5edaeSJenius val ifuPtrPlus1_w = Input(new FtqPtr) 4236bf9b30dSLingrui98 val ifuPtrPlus2_w = Input(new FtqPtr) 424b92f8445Sssszwic val pfPtr_w = Input(new FtqPtr) 425b92f8445Sssszwic val pfPtrPlus1_w = Input(new FtqPtr) 426c5c5edaeSJenius val commPtr_w = Input(new FtqPtr) 4276bf9b30dSLingrui98 val commPtrPlus1_w = Input(new FtqPtr) 428c5c5edaeSJenius val ifuPtr_rdata = Output(new Ftq_RF_Components) 429c5c5edaeSJenius val ifuPtrPlus1_rdata = Output(new Ftq_RF_Components) 4306bf9b30dSLingrui98 val ifuPtrPlus2_rdata = Output(new Ftq_RF_Components) 431b92f8445Sssszwic val pfPtr_rdata = Output(new Ftq_RF_Components) 432b92f8445Sssszwic val pfPtrPlus1_rdata = Output(new Ftq_RF_Components) 433c5c5edaeSJenius val commPtr_rdata = Output(new Ftq_RF_Components) 4346bf9b30dSLingrui98 val commPtrPlus1_rdata = Output(new Ftq_RF_Components) 435c5c5edaeSJenius 436c5c5edaeSJenius val wen = Input(Bool()) 437c5c5edaeSJenius val waddr = Input(UInt(log2Ceil(FtqSize).W)) 438c5c5edaeSJenius val wdata = Input(new Ftq_RF_Components) 439c5c5edaeSJenius }) 440c5c5edaeSJenius 4416bf9b30dSLingrui98 val num_pc_read = numOtherReads + 5 442cf7d6b7aSMuzi val mem = Module(new SyncDataModuleTemplate(new Ftq_RF_Components, FtqSize, num_pc_read, 1, "FtqPC")) 443c5c5edaeSJenius mem.io.wen(0) := io.wen 444c5c5edaeSJenius mem.io.waddr(0) := io.waddr 445c5c5edaeSJenius mem.io.wdata(0) := io.wdata 446c5c5edaeSJenius 4476bf9b30dSLingrui98 // read one cycle ahead for ftq local reads 448cf7d6b7aSMuzi val raddr_vec = VecInit(Seq( 449cf7d6b7aSMuzi io.ifuPtr_w.value, 450cf7d6b7aSMuzi io.ifuPtrPlus1_w.value, 451cf7d6b7aSMuzi io.ifuPtrPlus2_w.value, 452cf7d6b7aSMuzi io.pfPtr_w.value, 453cf7d6b7aSMuzi io.pfPtrPlus1_w.value, 454cf7d6b7aSMuzi io.commPtrPlus1_w.value, 455cf7d6b7aSMuzi io.commPtr_w.value 456cf7d6b7aSMuzi )) 457c5c5edaeSJenius 458c5c5edaeSJenius mem.io.raddr := raddr_vec 459c5c5edaeSJenius 460b92f8445Sssszwic io.ifuPtr_rdata := mem.io.rdata.dropRight(6).last 461b92f8445Sssszwic io.ifuPtrPlus1_rdata := mem.io.rdata.dropRight(5).last 462b92f8445Sssszwic io.ifuPtrPlus2_rdata := mem.io.rdata.dropRight(4).last 463b92f8445Sssszwic io.pfPtr_rdata := mem.io.rdata.dropRight(3).last 464b92f8445Sssszwic io.pfPtrPlus1_rdata := mem.io.rdata.dropRight(2).last 4656bf9b30dSLingrui98 io.commPtrPlus1_rdata := mem.io.rdata.dropRight(1).last 466c5c5edaeSJenius io.commPtr_rdata := mem.io.rdata.last 467c5c5edaeSJenius} 468c5c5edaeSJenius 46909c6f1ddSLingrui98class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper 470e30430c2SJay with HasBackendRedirectInfo with BPUUtils with HasBPUConst with HasPerfEvents 471e30430c2SJay with HasICacheParameters { 47209c6f1ddSLingrui98 val io = IO(new Bundle { 47309c6f1ddSLingrui98 val fromBpu = Flipped(new BpuToFtqIO) 47409c6f1ddSLingrui98 val fromIfu = Flipped(new IfuToFtqIO) 47509c6f1ddSLingrui98 val fromBackend = Flipped(new CtrlToFtqIO) 47609c6f1ddSLingrui98 47709c6f1ddSLingrui98 val toBpu = new FtqToBpuIO 47809c6f1ddSLingrui98 val toIfu = new FtqToIfuIO 479c5c5edaeSJenius val toICache = new FtqToICacheIO 48009c6f1ddSLingrui98 val toBackend = new FtqToCtrlIO 481b92f8445Sssszwic val toPrefetch = new FtqToPrefetchIO 482b92f8445Sssszwic val icacheFlush = Output(Bool()) 4837052722fSJay 48409c6f1ddSLingrui98 val bpuInfo = new Bundle { 48509c6f1ddSLingrui98 val bpRight = Output(UInt(XLEN.W)) 48609c6f1ddSLingrui98 val bpWrong = Output(UInt(XLEN.W)) 48709c6f1ddSLingrui98 } 4881d1e6d4dSJenius 4891d1e6d4dSJenius val mmioCommitRead = Flipped(new mmioCommitRead) 490d2b20d1aSTang Haojin 491d2b20d1aSTang Haojin // for perf 492d2b20d1aSTang Haojin val ControlBTBMissBubble = Output(Bool()) 493d2b20d1aSTang Haojin val TAGEMissBubble = Output(Bool()) 494d2b20d1aSTang Haojin val SCMissBubble = Output(Bool()) 495d2b20d1aSTang Haojin val ITTAGEMissBubble = Output(Bool()) 496d2b20d1aSTang Haojin val RASMissBubble = Output(Bool()) 49709c6f1ddSLingrui98 }) 49809c6f1ddSLingrui98 io.bpuInfo := DontCare 49909c6f1ddSLingrui98 500d2b20d1aSTang Haojin val topdown_stage = RegInit(0.U.asTypeOf(new FrontendTopDownBundle)) 501d2b20d1aSTang Haojin // only driven by clock, not valid-ready 502d2b20d1aSTang Haojin topdown_stage := io.fromBpu.resp.bits.topdown_info 503d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info := topdown_stage 504d2b20d1aSTang Haojin 505d2b20d1aSTang Haojin val ifuRedirected = RegInit(VecInit(Seq.fill(FtqSize)(false.B))) 506d2b20d1aSTang Haojin 50742dddaceSXuan Hu // io.fromBackend.ftqIdxAhead: bju(BjuCnt) + ldReplay + exception 50842dddaceSXuan Hu val ftqIdxAhead = VecInit(Seq.tabulate(FtqRedirectAheadNum)(i => io.fromBackend.ftqIdxAhead(i))) // only bju 50942dddaceSXuan Hu val ftqIdxSelOH = io.fromBackend.ftqIdxSelOH.bits(FtqRedirectAheadNum - 1, 0) 510bace178aSGao-Zeyu 511bace178aSGao-Zeyu val aheadValid = ftqIdxAhead.map(_.valid).reduce(_ | _) && !io.fromBackend.redirect.valid 512bace178aSGao-Zeyu val realAhdValid = io.fromBackend.redirect.valid && (ftqIdxSelOH > 0.U) && RegNext(aheadValid) 513d2b20d1aSTang Haojin val backendRedirect = Wire(Valid(new BranchPredictionRedirect)) 5141c6fc24aSEaston Man val backendRedirectReg = Wire(Valid(new BranchPredictionRedirect)) 5151c6fc24aSEaston Man backendRedirectReg.valid := RegNext(Mux(realAhdValid, false.B, backendRedirect.valid)) 5161c6fc24aSEaston Man backendRedirectReg.bits := RegEnable(backendRedirect.bits, backendRedirect.valid) 517bace178aSGao-Zeyu val fromBackendRedirect = Wire(Valid(new BranchPredictionRedirect)) 518bace178aSGao-Zeyu fromBackendRedirect := Mux(realAhdValid, backendRedirect, backendRedirectReg) 51909c6f1ddSLingrui98 520df5b4b8eSYinan Xu val stage2Flush = backendRedirect.valid 52109c6f1ddSLingrui98 val backendFlush = stage2Flush || RegNext(stage2Flush) 52209c6f1ddSLingrui98 val ifuFlush = Wire(Bool()) 52309c6f1ddSLingrui98 52409c6f1ddSLingrui98 val flush = stage2Flush || RegNext(stage2Flush) 52509c6f1ddSLingrui98 52609c6f1ddSLingrui98 val allowBpuIn, allowToIfu = WireInit(false.B) 52709c6f1ddSLingrui98 val flushToIfu = !allowToIfu 528bace178aSGao-Zeyu allowBpuIn := !ifuFlush && !backendRedirect.valid && !backendRedirectReg.valid 529bace178aSGao-Zeyu allowToIfu := !ifuFlush && !backendRedirect.valid && !backendRedirectReg.valid 53009c6f1ddSLingrui98 531f56177cbSJenius def copyNum = 5 532b92f8445Sssszwic val bpuPtr, ifuPtr, pfPtr, ifuWbPtr, commPtr, robCommPtr = RegInit(FtqPtr(false.B, 0.U)) 533c9bc5480SLingrui98 val ifuPtrPlus1 = RegInit(FtqPtr(false.B, 1.U)) 5346bf9b30dSLingrui98 val ifuPtrPlus2 = RegInit(FtqPtr(false.B, 2.U)) 535b92f8445Sssszwic val pfPtrPlus1 = RegInit(FtqPtr(false.B, 1.U)) 5366bf9b30dSLingrui98 val commPtrPlus1 = RegInit(FtqPtr(false.B, 1.U)) 537f56177cbSJenius val copied_ifu_ptr = Seq.fill(copyNum)(RegInit(FtqPtr(false.B, 0.U))) 538dc270d3bSJenius val copied_bpu_ptr = Seq.fill(copyNum)(RegInit(FtqPtr(false.B, 0.U))) 5396bf9b30dSLingrui98 require(FtqSize >= 4) 540c5c5edaeSJenius val ifuPtr_write = WireInit(ifuPtr) 541c5c5edaeSJenius val ifuPtrPlus1_write = WireInit(ifuPtrPlus1) 5426bf9b30dSLingrui98 val ifuPtrPlus2_write = WireInit(ifuPtrPlus2) 543b92f8445Sssszwic val pfPtr_write = WireInit(pfPtr) 544b92f8445Sssszwic val pfPtrPlus1_write = WireInit(pfPtrPlus1) 545c5c5edaeSJenius val ifuWbPtr_write = WireInit(ifuWbPtr) 546c5c5edaeSJenius val commPtr_write = WireInit(commPtr) 5476bf9b30dSLingrui98 val commPtrPlus1_write = WireInit(commPtrPlus1) 54889cc69c1STang Haojin val robCommPtr_write = WireInit(robCommPtr) 549c5c5edaeSJenius ifuPtr := ifuPtr_write 550c5c5edaeSJenius ifuPtrPlus1 := ifuPtrPlus1_write 5516bf9b30dSLingrui98 ifuPtrPlus2 := ifuPtrPlus2_write 552b92f8445Sssszwic pfPtr := pfPtr_write 553b92f8445Sssszwic pfPtrPlus1 := pfPtrPlus1_write 554c5c5edaeSJenius ifuWbPtr := ifuWbPtr_write 555c5c5edaeSJenius commPtr := commPtr_write 556f83ef67eSLingrui98 commPtrPlus1 := commPtrPlus1_write 557f56177cbSJenius copied_ifu_ptr.map { ptr => 558f56177cbSJenius ptr := ifuPtr_write 559f56177cbSJenius dontTouch(ptr) 560f56177cbSJenius } 56189cc69c1STang Haojin robCommPtr := robCommPtr_write 56209c6f1ddSLingrui98 val validEntries = distanceBetween(bpuPtr, commPtr) 56343aca6c2SGuokai Chen val canCommit = Wire(Bool()) 56409c6f1ddSLingrui98 565c1b28b66STang Haojin // Instruction page fault and instruction access fault are sent from backend with redirect requests. 566c1b28b66STang Haojin // When IPF and IAF are sent, backendPcFaultIfuPtr points to the FTQ entry whose first instruction 567c1b28b66STang Haojin // raises IPF or IAF, which is ifuWbPtr_write or IfuPtr_write. 568c1b28b66STang Haojin // Only when IFU has written back that FTQ entry can backendIpf and backendIaf be false because this 569c1b28b66STang Haojin // makes sure that IAF and IPF are correctly raised instead of being flushed by redirect requests. 570c1b28b66STang Haojin val backendIpf = RegInit(false.B) 571c1b28b66STang Haojin val backendIgpf = RegInit(false.B) 572c1b28b66STang Haojin val backendIaf = RegInit(false.B) 573c1b28b66STang Haojin val backendPcFaultPtr = RegInit(FtqPtr(false.B, 0.U)) 574c1b28b66STang Haojin when(fromBackendRedirect.valid) { 575c1b28b66STang Haojin backendIpf := fromBackendRedirect.bits.cfiUpdate.backendIPF 576c1b28b66STang Haojin backendIgpf := fromBackendRedirect.bits.cfiUpdate.backendIGPF 577c1b28b66STang Haojin backendIaf := fromBackendRedirect.bits.cfiUpdate.backendIAF 578cf7d6b7aSMuzi when( 579cf7d6b7aSMuzi fromBackendRedirect.bits.cfiUpdate.backendIPF || fromBackendRedirect.bits.cfiUpdate.backendIGPF || fromBackendRedirect.bits.cfiUpdate.backendIAF 580cf7d6b7aSMuzi ) { 581c1b28b66STang Haojin backendPcFaultPtr := ifuWbPtr_write 582c1b28b66STang Haojin } 583c1b28b66STang Haojin }.elsewhen(ifuWbPtr =/= backendPcFaultPtr) { 584c1b28b66STang Haojin backendIpf := false.B 585c1b28b66STang Haojin backendIgpf := false.B 586c1b28b66STang Haojin backendIaf := false.B 587c1b28b66STang Haojin } 588c1b28b66STang Haojin 58909c6f1ddSLingrui98 // ********************************************************************** 59009c6f1ddSLingrui98 // **************************** enq from bpu **************************** 59109c6f1ddSLingrui98 // ********************************************************************** 59243aca6c2SGuokai Chen val new_entry_ready = validEntries < FtqSize.U || canCommit 59309c6f1ddSLingrui98 io.fromBpu.resp.ready := new_entry_ready 59409c6f1ddSLingrui98 59509c6f1ddSLingrui98 val bpu_s2_resp = io.fromBpu.resp.bits.s2 596cb4f77ceSLingrui98 val bpu_s3_resp = io.fromBpu.resp.bits.s3 597adc0b8dfSGuokai Chen val bpu_s2_redirect = bpu_s2_resp.valid(3) && bpu_s2_resp.hasRedirect(3) 598adc0b8dfSGuokai Chen val bpu_s3_redirect = bpu_s3_resp.valid(3) && bpu_s3_resp.hasRedirect(3) 59909c6f1ddSLingrui98 60009c6f1ddSLingrui98 io.toBpu.enq_ptr := bpuPtr 601935edac4STang Haojin val enq_fire = io.fromBpu.resp.fire && allowBpuIn // from bpu s1 602935edac4STang Haojin val bpu_in_fire = (io.fromBpu.resp.fire || bpu_s2_redirect || bpu_s3_redirect) && allowBpuIn 60309c6f1ddSLingrui98 604b37e4b45SLingrui98 val bpu_in_resp = io.fromBpu.resp.bits.selectedResp 605adc0b8dfSGuokai Chen val bpu_in_stage = io.fromBpu.resp.bits.selectedRespIdxForFtq 60609c6f1ddSLingrui98 val bpu_in_resp_ptr = Mux(bpu_in_stage === BP_S1, bpuPtr, bpu_in_resp.ftq_idx) 60709c6f1ddSLingrui98 val bpu_in_resp_idx = bpu_in_resp_ptr.value 60809c6f1ddSLingrui98 609b92f8445Sssszwic // read ports: pfReq1 + pfReq2 ++ ifuReq1 + ifuReq2 + ifuReq3 + commitUpdate2 + commitUpdate 610b92f8445Sssszwic val ftq_pc_mem = Module(new FtqPcMemWrapper(2)) 6116bf9b30dSLingrui98 // resp from uBTB 612c5c5edaeSJenius ftq_pc_mem.io.wen := bpu_in_fire 613c5c5edaeSJenius ftq_pc_mem.io.waddr := bpu_in_resp_idx 614c5c5edaeSJenius ftq_pc_mem.io.wdata.fromBranchPrediction(bpu_in_resp) 61509c6f1ddSLingrui98 61609c6f1ddSLingrui98 // ifuRedirect + backendRedirect + commit 617cf7d6b7aSMuzi val ftq_redirect_mem = Module(new SyncDataModuleTemplate( 618cf7d6b7aSMuzi new Ftq_Redirect_SRAMEntry, 619cf7d6b7aSMuzi FtqSize, 620cf7d6b7aSMuzi IfuRedirectNum + FtqRedirectAheadNum + 1, 621cf7d6b7aSMuzi 1, 622cf7d6b7aSMuzi hasRen = true 623cf7d6b7aSMuzi )) 62409c6f1ddSLingrui98 // these info is intended to enq at the last stage of bpu 625deb3a97eSGao-Zeyu ftq_redirect_mem.io.wen(0) := io.fromBpu.resp.bits.lastStage.valid(3) 626deb3a97eSGao-Zeyu ftq_redirect_mem.io.waddr(0) := io.fromBpu.resp.bits.lastStage.ftq_idx.value 627deb3a97eSGao-Zeyu ftq_redirect_mem.io.wdata(0) := io.fromBpu.resp.bits.last_stage_spec_info 628deb3a97eSGao-Zeyu println(f"ftq redirect MEM: entry ${ftq_redirect_mem.io.wdata(0).getWidth} * ${FtqSize} * 3") 62909c6f1ddSLingrui98 63009c6f1ddSLingrui98 val ftq_meta_1r_sram = Module(new FtqNRSRAM(new Ftq_1R_SRAMEntry, 1)) 63109c6f1ddSLingrui98 // these info is intended to enq at the last stage of bpu 632adc0b8dfSGuokai Chen ftq_meta_1r_sram.io.wen := io.fromBpu.resp.bits.lastStage.valid(3) 63309c6f1ddSLingrui98 ftq_meta_1r_sram.io.waddr := io.fromBpu.resp.bits.lastStage.ftq_idx.value 634c2d1ec7dSLingrui98 ftq_meta_1r_sram.io.wdata.meta := io.fromBpu.resp.bits.last_stage_meta 635deb3a97eSGao-Zeyu ftq_meta_1r_sram.io.wdata.ftb_entry := io.fromBpu.resp.bits.last_stage_ftb_entry 63695a47398SGao-Zeyu // ifuRedirect + backendRedirect (commit moved to ftq_meta_1r_sram) 637cf7d6b7aSMuzi val ftb_entry_mem = Module(new SyncDataModuleTemplate( 638cf7d6b7aSMuzi new FTBEntry_FtqMem, 639cf7d6b7aSMuzi FtqSize, 640cf7d6b7aSMuzi IfuRedirectNum + FtqRedirectAheadNum, 641cf7d6b7aSMuzi 1, 642cf7d6b7aSMuzi hasRen = true 643cf7d6b7aSMuzi )) 644adc0b8dfSGuokai Chen ftb_entry_mem.io.wen(0) := io.fromBpu.resp.bits.lastStage.valid(3) 64509c6f1ddSLingrui98 ftb_entry_mem.io.waddr(0) := io.fromBpu.resp.bits.lastStage.ftq_idx.value 646c2d1ec7dSLingrui98 ftb_entry_mem.io.wdata(0) := io.fromBpu.resp.bits.last_stage_ftb_entry 64709c6f1ddSLingrui98 64809c6f1ddSLingrui98 // multi-write 649b0ed7239SLingrui98 val update_target = Reg(Vec(FtqSize, UInt(VAddrBits.W))) // could be taken target or fallThrough //TODO: remove this 6506bf9b30dSLingrui98 val newest_entry_target = Reg(UInt(VAddrBits.W)) 6511c6fc24aSEaston Man val newest_entry_target_modified = RegInit(false.B) 6526bf9b30dSLingrui98 val newest_entry_ptr = Reg(new FtqPtr) 6531c6fc24aSEaston Man val newest_entry_ptr_modified = RegInit(false.B) 65409c6f1ddSLingrui98 val cfiIndex_vec = Reg(Vec(FtqSize, ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))) 65509c6f1ddSLingrui98 val mispredict_vec = Reg(Vec(FtqSize, Vec(PredictWidth, Bool()))) 65609c6f1ddSLingrui98 val pred_stage = Reg(Vec(FtqSize, UInt(2.W))) 657209a4cafSSteve Gou val pred_s1_cycle = if (!env.FPGAPlatform) Some(Reg(Vec(FtqSize, UInt(64.W)))) else None 65809c6f1ddSLingrui98 65991346769SMuzi val c_empty :: c_toCommit :: c_committed :: c_flushed :: Nil = Enum(4) 6601c6fc24aSEaston Man val commitStateQueueReg = RegInit(VecInit(Seq.fill(FtqSize) { 66191346769SMuzi VecInit(Seq.fill(PredictWidth)(c_empty)) 66209c6f1ddSLingrui98 })) 6631c6fc24aSEaston Man val commitStateQueueEnable = WireInit(VecInit(Seq.fill(FtqSize)(false.B))) 6641c6fc24aSEaston Man val commitStateQueueNext = WireInit(commitStateQueueReg) 6651c6fc24aSEaston Man 6661c6fc24aSEaston Man for (f <- 0 until FtqSize) { 6671c6fc24aSEaston Man when(commitStateQueueEnable(f)) { 6681c6fc24aSEaston Man commitStateQueueReg(f) := commitStateQueueNext(f) 6691c6fc24aSEaston Man } 6701c6fc24aSEaston Man } 67109c6f1ddSLingrui98 67209c6f1ddSLingrui98 val f_to_send :: f_sent :: Nil = Enum(2) 67309c6f1ddSLingrui98 val entry_fetch_status = RegInit(VecInit(Seq.fill(FtqSize)(f_sent))) 67409c6f1ddSLingrui98 67509c6f1ddSLingrui98 val h_not_hit :: h_false_hit :: h_hit :: Nil = Enum(3) 67609c6f1ddSLingrui98 val entry_hit_status = RegInit(VecInit(Seq.fill(FtqSize)(h_not_hit))) 67709c6f1ddSLingrui98 678f63797a4SLingrui98 // modify registers one cycle later to cut critical path 679f63797a4SLingrui98 val last_cycle_bpu_in = RegNext(bpu_in_fire) 6801c6fc24aSEaston Man val last_cycle_bpu_in_ptr = RegEnable(bpu_in_resp_ptr, bpu_in_fire) 6816bf9b30dSLingrui98 val last_cycle_bpu_in_idx = last_cycle_bpu_in_ptr.value 6821c6fc24aSEaston Man val last_cycle_bpu_target = RegEnable(bpu_in_resp.getTarget(3), bpu_in_fire) 6831c6fc24aSEaston Man val last_cycle_cfiIndex = RegEnable(bpu_in_resp.cfiIndex(3), bpu_in_fire) 6841c6fc24aSEaston Man val last_cycle_bpu_in_stage = RegEnable(bpu_in_stage, bpu_in_fire) 685f56177cbSJenius 6867be982afSLingrui98 def extra_copyNum_for_commitStateQueue = 2 6871c6fc24aSEaston Man val copied_last_cycle_bpu_in = 6881c6fc24aSEaston Man VecInit(Seq.fill(copyNum + extra_copyNum_for_commitStateQueue)(RegNext(bpu_in_fire))) 6891c6fc24aSEaston Man val copied_last_cycle_bpu_in_ptr_for_ftq = 6901c6fc24aSEaston Man VecInit(Seq.fill(extra_copyNum_for_commitStateQueue)(RegEnable(bpu_in_resp_ptr, bpu_in_fire))) 691f56177cbSJenius 6921c6fc24aSEaston Man newest_entry_target_modified := false.B 6931c6fc24aSEaston Man newest_entry_ptr_modified := false.B 694f63797a4SLingrui98 when(last_cycle_bpu_in) { 695f63797a4SLingrui98 entry_fetch_status(last_cycle_bpu_in_idx) := f_to_send 696f63797a4SLingrui98 cfiIndex_vec(last_cycle_bpu_in_idx) := last_cycle_cfiIndex 697f63797a4SLingrui98 pred_stage(last_cycle_bpu_in_idx) := last_cycle_bpu_in_stage 6986bf9b30dSLingrui98 699b0ed7239SLingrui98 update_target(last_cycle_bpu_in_idx) := last_cycle_bpu_target // TODO: remove this 7001c6fc24aSEaston Man newest_entry_target_modified := true.B 7016bf9b30dSLingrui98 newest_entry_target := last_cycle_bpu_target 7021c6fc24aSEaston Man newest_entry_ptr_modified := true.B 7036bf9b30dSLingrui98 newest_entry_ptr := last_cycle_bpu_in_ptr 70409c6f1ddSLingrui98 } 70509c6f1ddSLingrui98 7067be982afSLingrui98 // reduce fanout by delay write for a cycle 7077be982afSLingrui98 when(RegNext(last_cycle_bpu_in)) { 7081c6fc24aSEaston Man mispredict_vec(RegEnable(last_cycle_bpu_in_idx, last_cycle_bpu_in)) := 7091c6fc24aSEaston Man WireInit(VecInit(Seq.fill(PredictWidth)(false.B))) 7107be982afSLingrui98 } 7117be982afSLingrui98 712209a4cafSSteve Gou // record s1 pred cycles 713cf7d6b7aSMuzi pred_s1_cycle.map { vec => 714209a4cafSSteve Gou when(bpu_in_fire && (bpu_in_stage === BP_S1)) { 715209a4cafSSteve Gou vec(bpu_in_resp_ptr.value) := bpu_in_resp.full_pred(0).predCycle.getOrElse(0.U) 716209a4cafSSteve Gou } 717cf7d6b7aSMuzi } 718209a4cafSSteve Gou 7197be982afSLingrui98 // reduce fanout using copied last_cycle_bpu_in and copied last_cycle_bpu_in_ptr 7207be982afSLingrui98 val copied_last_cycle_bpu_in_for_ftq = copied_last_cycle_bpu_in.takeRight(extra_copyNum_for_commitStateQueue) 7217be982afSLingrui98 copied_last_cycle_bpu_in_for_ftq.zip(copied_last_cycle_bpu_in_ptr_for_ftq).zipWithIndex.map { 7227be982afSLingrui98 case ((in, ptr), i) => 7237be982afSLingrui98 when(in) { 7247be982afSLingrui98 val perSetEntries = FtqSize / extra_copyNum_for_commitStateQueue // 32 7257be982afSLingrui98 require(FtqSize % extra_copyNum_for_commitStateQueue == 0) 7267be982afSLingrui98 for (j <- 0 until perSetEntries) { 7279361b0c5SLingrui98 when(ptr.value === (i * perSetEntries + j).U) { 72891346769SMuzi commitStateQueueNext(i * perSetEntries + j) := VecInit(Seq.fill(PredictWidth)(c_empty)) 7291c6fc24aSEaston Man // Clock gating optimization, use 1 gate cell to control a row 7301c6fc24aSEaston Man commitStateQueueEnable(i * perSetEntries + j) := true.B 7317be982afSLingrui98 } 7327be982afSLingrui98 } 7337be982afSLingrui98 } 7349361b0c5SLingrui98 } 7357be982afSLingrui98 73609c6f1ddSLingrui98 bpuPtr := bpuPtr + enq_fire 737dc270d3bSJenius copied_bpu_ptr.map(_ := bpuPtr + enq_fire) 738c9bc5480SLingrui98 when(io.toIfu.req.fire && allowToIfu) { 739c5c5edaeSJenius ifuPtr_write := ifuPtrPlus1 7406bf9b30dSLingrui98 ifuPtrPlus1_write := ifuPtrPlus2 7416bf9b30dSLingrui98 ifuPtrPlus2_write := ifuPtrPlus2 + 1.U 742c9bc5480SLingrui98 } 743b92f8445Sssszwic when(io.toPrefetch.req.fire && allowToIfu) { 744b92f8445Sssszwic pfPtr_write := pfPtrPlus1 745b92f8445Sssszwic pfPtrPlus1_write := pfPtrPlus1 + 1.U 746b92f8445Sssszwic } 74709c6f1ddSLingrui98 74809c6f1ddSLingrui98 // only use ftb result to assign hit status 749adc0b8dfSGuokai Chen when(bpu_s2_resp.valid(3)) { 750adc0b8dfSGuokai Chen entry_hit_status(bpu_s2_resp.ftq_idx.value) := Mux(bpu_s2_resp.full_pred(3).hit, h_hit, h_not_hit) 75109c6f1ddSLingrui98 } 75209c6f1ddSLingrui98 7532f4a3aa4SLingrui98 io.toIfu.flushFromBpu.s2.valid := bpu_s2_redirect 75409c6f1ddSLingrui98 io.toIfu.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx 755b92f8445Sssszwic io.toPrefetch.flushFromBpu.s2.valid := bpu_s2_redirect 756b92f8445Sssszwic io.toPrefetch.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx 757adc0b8dfSGuokai Chen when(bpu_s2_redirect) { 75809c6f1ddSLingrui98 bpuPtr := bpu_s2_resp.ftq_idx + 1.U 759dc270d3bSJenius copied_bpu_ptr.map(_ := bpu_s2_resp.ftq_idx + 1.U) 76009c6f1ddSLingrui98 // only when ifuPtr runs ahead of bpu s2 resp should we recover it 76109c6f1ddSLingrui98 when(!isBefore(ifuPtr, bpu_s2_resp.ftq_idx)) { 762c5c5edaeSJenius ifuPtr_write := bpu_s2_resp.ftq_idx 763c5c5edaeSJenius ifuPtrPlus1_write := bpu_s2_resp.ftq_idx + 1.U 7646bf9b30dSLingrui98 ifuPtrPlus2_write := bpu_s2_resp.ftq_idx + 2.U 76509c6f1ddSLingrui98 } 766b92f8445Sssszwic when(!isBefore(pfPtr, bpu_s2_resp.ftq_idx)) { 767b92f8445Sssszwic pfPtr_write := bpu_s2_resp.ftq_idx 768b92f8445Sssszwic pfPtrPlus1_write := bpu_s2_resp.ftq_idx + 1.U 769b92f8445Sssszwic } 77009c6f1ddSLingrui98 } 77109c6f1ddSLingrui98 772cb4f77ceSLingrui98 io.toIfu.flushFromBpu.s3.valid := bpu_s3_redirect 773cb4f77ceSLingrui98 io.toIfu.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx 774b92f8445Sssszwic io.toPrefetch.flushFromBpu.s3.valid := bpu_s3_redirect 775b92f8445Sssszwic io.toPrefetch.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx 776adc0b8dfSGuokai Chen when(bpu_s3_redirect) { 777cb4f77ceSLingrui98 bpuPtr := bpu_s3_resp.ftq_idx + 1.U 778dc270d3bSJenius copied_bpu_ptr.map(_ := bpu_s3_resp.ftq_idx + 1.U) 779cb4f77ceSLingrui98 // only when ifuPtr runs ahead of bpu s2 resp should we recover it 780cb4f77ceSLingrui98 when(!isBefore(ifuPtr, bpu_s3_resp.ftq_idx)) { 781c5c5edaeSJenius ifuPtr_write := bpu_s3_resp.ftq_idx 782c5c5edaeSJenius ifuPtrPlus1_write := bpu_s3_resp.ftq_idx + 1.U 7836bf9b30dSLingrui98 ifuPtrPlus2_write := bpu_s3_resp.ftq_idx + 2.U 784cb4f77ceSLingrui98 } 785b92f8445Sssszwic when(!isBefore(pfPtr, bpu_s3_resp.ftq_idx)) { 786b92f8445Sssszwic pfPtr_write := bpu_s3_resp.ftq_idx 787b92f8445Sssszwic pfPtrPlus1_write := bpu_s3_resp.ftq_idx + 1.U 788b92f8445Sssszwic } 789cb4f77ceSLingrui98 } 790cb4f77ceSLingrui98 79109c6f1ddSLingrui98 XSError(isBefore(bpuPtr, ifuPtr) && !isFull(bpuPtr, ifuPtr), "\nifuPtr is before bpuPtr!\n") 792b92f8445Sssszwic XSError(isBefore(bpuPtr, pfPtr) && !isFull(bpuPtr, pfPtr), "\npfPtr is before bpuPtr!\n") 7932448f137SGuokai Chen XSError(isBefore(ifuWbPtr, commPtr) && !isFull(ifuWbPtr, commPtr), "\ncommPtr is before ifuWbPtr!\n") 79409c6f1ddSLingrui98 795cf7d6b7aSMuzi (0 until copyNum).map(i => XSError(copied_bpu_ptr(i) =/= bpuPtr, "\ncopiedBpuPtr is different from bpuPtr!\n")) 796dc270d3bSJenius 79709c6f1ddSLingrui98 // **************************************************************** 79809c6f1ddSLingrui98 // **************************** to ifu **************************** 79909c6f1ddSLingrui98 // **************************************************************** 800f22cf846SJenius // 0 for ifu, and 1-4 for ICache 801935edac4STang Haojin val bpu_in_bypass_buf = RegEnable(ftq_pc_mem.io.wdata, bpu_in_fire) 802935edac4STang Haojin val copied_bpu_in_bypass_buf = VecInit(Seq.fill(copyNum)(RegEnable(ftq_pc_mem.io.wdata, bpu_in_fire))) 803f56177cbSJenius val bpu_in_bypass_buf_for_ifu = bpu_in_bypass_buf 8041c6fc24aSEaston Man val bpu_in_bypass_ptr = RegEnable(bpu_in_resp_ptr, bpu_in_fire) 80509c6f1ddSLingrui98 val last_cycle_to_ifu_fire = RegNext(io.toIfu.req.fire) 806b92f8445Sssszwic val last_cycle_to_pf_fire = RegNext(io.toPrefetch.req.fire) 80709c6f1ddSLingrui98 8081c6fc24aSEaston Man val copied_bpu_in_bypass_ptr = VecInit(Seq.fill(copyNum)(RegEnable(bpu_in_resp_ptr, bpu_in_fire))) 809f56177cbSJenius val copied_last_cycle_to_ifu_fire = VecInit(Seq.fill(copyNum)(RegNext(io.toIfu.req.fire))) 81088bc4f90SLingrui98 81109c6f1ddSLingrui98 // read pc and target 8126bf9b30dSLingrui98 ftq_pc_mem.io.ifuPtr_w := ifuPtr_write 8136bf9b30dSLingrui98 ftq_pc_mem.io.ifuPtrPlus1_w := ifuPtrPlus1_write 8146bf9b30dSLingrui98 ftq_pc_mem.io.ifuPtrPlus2_w := ifuPtrPlus2_write 815b92f8445Sssszwic ftq_pc_mem.io.pfPtr_w := pfPtr_write 816b92f8445Sssszwic ftq_pc_mem.io.pfPtrPlus1_w := pfPtrPlus1_write 8176bf9b30dSLingrui98 ftq_pc_mem.io.commPtr_w := commPtr_write 8186bf9b30dSLingrui98 ftq_pc_mem.io.commPtrPlus1_w := commPtrPlus1_write 819c5c5edaeSJenius 8205ff19bd8SLingrui98 io.toIfu.req.bits.ftqIdx := ifuPtr 821f63797a4SLingrui98 822f56177cbSJenius val toICachePcBundle = Wire(Vec(copyNum, new Ftq_RF_Components)) 823dc270d3bSJenius val toICacheEntryToSend = Wire(Vec(copyNum, Bool())) 8243e1dbb17SMuzi val nextCycleToPrefetchPcBundle = Wire(new Ftq_RF_Components) 8253e1dbb17SMuzi val nextCycleToPrefetchEntryToSend = Wire(Bool()) 8263e1dbb17SMuzi val toPrefetchPcBundle = RegNext(nextCycleToPrefetchPcBundle) 8273e1dbb17SMuzi val toPrefetchEntryToSend = RegNext(nextCycleToPrefetchEntryToSend) 828b37e4b45SLingrui98 val toIfuPcBundle = Wire(new Ftq_RF_Components) 829f63797a4SLingrui98 val entry_is_to_send = WireInit(entry_fetch_status(ifuPtr.value) === f_to_send) 830f63797a4SLingrui98 val entry_ftq_offset = WireInit(cfiIndex_vec(ifuPtr.value)) 8316bf9b30dSLingrui98 val entry_next_addr = Wire(UInt(VAddrBits.W)) 832b004fa13SJenius 833f56177cbSJenius val pc_mem_ifu_ptr_rdata = VecInit(Seq.fill(copyNum)(RegNext(ftq_pc_mem.io.ifuPtr_rdata))) 834f56177cbSJenius val pc_mem_ifu_plus1_rdata = VecInit(Seq.fill(copyNum)(RegNext(ftq_pc_mem.io.ifuPtrPlus1_rdata))) 835b0ed7239SLingrui98 val diff_entry_next_addr = WireInit(update_target(ifuPtr.value)) // TODO: remove this 836f63797a4SLingrui98 837cf7d6b7aSMuzi val copied_ifu_plus1_to_send = VecInit(Seq.fill(copyNum)(RegNext( 838cf7d6b7aSMuzi entry_fetch_status(ifuPtrPlus1.value) === f_to_send 839cf7d6b7aSMuzi ) || RegNext(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtrPlus1))) 840cf7d6b7aSMuzi val copied_ifu_ptr_to_send = VecInit(Seq.fill(copyNum)(RegNext( 841cf7d6b7aSMuzi entry_fetch_status(ifuPtr.value) === f_to_send 842cf7d6b7aSMuzi ) || RegNext(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr))) 843dc270d3bSJenius 844f56177cbSJenius for (i <- 0 until copyNum) { 845f56177cbSJenius when(copied_last_cycle_bpu_in(i) && copied_bpu_in_bypass_ptr(i) === copied_ifu_ptr(i)) { 846f56177cbSJenius toICachePcBundle(i) := copied_bpu_in_bypass_buf(i) 847dc270d3bSJenius toICacheEntryToSend(i) := true.B 848f56177cbSJenius }.elsewhen(copied_last_cycle_to_ifu_fire(i)) { 849f56177cbSJenius toICachePcBundle(i) := pc_mem_ifu_plus1_rdata(i) 850dc270d3bSJenius toICacheEntryToSend(i) := copied_ifu_plus1_to_send(i) 851f56177cbSJenius }.otherwise { 852f56177cbSJenius toICachePcBundle(i) := pc_mem_ifu_ptr_rdata(i) 853dc270d3bSJenius toICacheEntryToSend(i) := copied_ifu_ptr_to_send(i) 854f56177cbSJenius } 855f56177cbSJenius } 856f56177cbSJenius 8573e1dbb17SMuzi // Calculate requests sent to prefetcher one cycle in advance to cut critical path 8583e1dbb17SMuzi when(bpu_in_fire && bpu_in_resp_ptr === pfPtr_write) { 8593e1dbb17SMuzi nextCycleToPrefetchPcBundle := ftq_pc_mem.io.wdata 8603e1dbb17SMuzi nextCycleToPrefetchEntryToSend := true.B 8613e1dbb17SMuzi }.elsewhen(io.toPrefetch.req.fire) { 8623e1dbb17SMuzi nextCycleToPrefetchPcBundle := ftq_pc_mem.io.pfPtrPlus1_rdata 8633e1dbb17SMuzi nextCycleToPrefetchEntryToSend := entry_fetch_status(pfPtrPlus1.value) === f_to_send || 8643e1dbb17SMuzi last_cycle_bpu_in && bpu_in_bypass_ptr === pfPtrPlus1 865b92f8445Sssszwic }.otherwise { 8663e1dbb17SMuzi nextCycleToPrefetchPcBundle := ftq_pc_mem.io.pfPtr_rdata 8673e1dbb17SMuzi nextCycleToPrefetchEntryToSend := entry_fetch_status(pfPtr.value) === f_to_send || 8683e1dbb17SMuzi last_cycle_bpu_in && bpu_in_bypass_ptr === pfPtr // reduce potential bubbles 869b92f8445Sssszwic } 870b92f8445Sssszwic 871873dc383SLingrui98 // TODO: reconsider target address bypass logic 87209c6f1ddSLingrui98 when(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr) { 87388bc4f90SLingrui98 toIfuPcBundle := bpu_in_bypass_buf_for_ifu 874f678dd91SSteve Gou entry_is_to_send := true.B 8756bf9b30dSLingrui98 entry_next_addr := last_cycle_bpu_target 876f63797a4SLingrui98 entry_ftq_offset := last_cycle_cfiIndex 877b0ed7239SLingrui98 diff_entry_next_addr := last_cycle_bpu_target // TODO: remove this 87809c6f1ddSLingrui98 }.elsewhen(last_cycle_to_ifu_fire) { 879c5c5edaeSJenius toIfuPcBundle := RegNext(ftq_pc_mem.io.ifuPtrPlus1_rdata) 880c5c5edaeSJenius entry_is_to_send := RegNext(entry_fetch_status(ifuPtrPlus1.value) === f_to_send) || 881cf7d6b7aSMuzi RegNext(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtrPlus1) // reduce potential bubbles 882cf7d6b7aSMuzi entry_next_addr := Mux( 883cf7d6b7aSMuzi last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtrPlus1, 88488bc4f90SLingrui98 bpu_in_bypass_buf_for_ifu.startAddr, 885cf7d6b7aSMuzi Mux(ifuPtr === newest_entry_ptr, newest_entry_target, RegNext(ftq_pc_mem.io.ifuPtrPlus2_rdata.startAddr)) 886cf7d6b7aSMuzi ) // ifuPtr+2 887c5c5edaeSJenius }.otherwise { 888c5c5edaeSJenius toIfuPcBundle := RegNext(ftq_pc_mem.io.ifuPtr_rdata) 88928f2cf58SLingrui98 entry_is_to_send := RegNext(entry_fetch_status(ifuPtr.value) === f_to_send) || 89028f2cf58SLingrui98 RegNext(last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr) // reduce potential bubbles 891cf7d6b7aSMuzi entry_next_addr := Mux( 892cf7d6b7aSMuzi last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtrPlus1, 89388bc4f90SLingrui98 bpu_in_bypass_buf_for_ifu.startAddr, 894cf7d6b7aSMuzi Mux(ifuPtr === newest_entry_ptr, newest_entry_target, RegNext(ftq_pc_mem.io.ifuPtrPlus1_rdata.startAddr)) 895cf7d6b7aSMuzi ) // ifuPtr+1 89609c6f1ddSLingrui98 } 89709c6f1ddSLingrui98 898f678dd91SSteve Gou io.toIfu.req.valid := entry_is_to_send && ifuPtr =/= bpuPtr 899f63797a4SLingrui98 io.toIfu.req.bits.nextStartAddr := entry_next_addr 900f63797a4SLingrui98 io.toIfu.req.bits.ftqOffset := entry_ftq_offset 901b37e4b45SLingrui98 io.toIfu.req.bits.fromFtqPcBundle(toIfuPcBundle) 902c5c5edaeSJenius 903c5c5edaeSJenius io.toICache.req.valid := entry_is_to_send && ifuPtr =/= bpuPtr 904cf7d6b7aSMuzi io.toICache.req.bits.readValid.zipWithIndex.map { case (copy, i) => 905cf7d6b7aSMuzi copy := toICacheEntryToSend(i) && copied_ifu_ptr(i) =/= copied_bpu_ptr(i) 906cf7d6b7aSMuzi } 907b92f8445Sssszwic io.toICache.req.bits.pcMemRead.zipWithIndex.foreach { case (copy, i) => 908b92f8445Sssszwic copy.fromFtqPcBundle(toICachePcBundle(i)) 909b92f8445Sssszwic copy.ftqIdx := ifuPtr 910b92f8445Sssszwic } 911c1b28b66STang Haojin io.toICache.req.bits.backendIpf := backendIpf && backendPcFaultPtr === ifuPtr 912c1b28b66STang Haojin io.toICache.req.bits.backendIgpf := backendIgpf && backendPcFaultPtr === ifuPtr 913c1b28b66STang Haojin io.toICache.req.bits.backendIaf := backendIaf && backendPcFaultPtr === ifuPtr 914b92f8445Sssszwic 915b92f8445Sssszwic io.toPrefetch.req.valid := toPrefetchEntryToSend && pfPtr =/= bpuPtr 916b92f8445Sssszwic io.toPrefetch.req.bits.fromFtqPcBundle(toPrefetchPcBundle) 917b92f8445Sssszwic io.toPrefetch.req.bits.ftqIdx := pfPtr 918b004fa13SJenius // io.toICache.req.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr 919b004fa13SJenius // io.toICache.req.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) => 920b004fa13SJenius // bypassWrtie.startAddr := bpu_in_bypass_buf.tail(i).startAddr 921b004fa13SJenius // bypassWrtie.nextlineStart := bpu_in_bypass_buf.tail(i).nextLineAddr 922b004fa13SJenius // } 923f22cf846SJenius 924b0ed7239SLingrui98 // TODO: remove this 925cf7d6b7aSMuzi XSError( 926cf7d6b7aSMuzi io.toIfu.req.valid && diff_entry_next_addr =/= entry_next_addr, 927cf7d6b7aSMuzi p"\nifu_req_target wrong! ifuPtr: ${ifuPtr}, entry_next_addr: ${Hexadecimal(entry_next_addr)} diff_entry_next_addr: ${Hexadecimal(diff_entry_next_addr)}\n" 928cf7d6b7aSMuzi ) 929b0ed7239SLingrui98 93009c6f1ddSLingrui98 // when fall through is smaller in value than start address, there must be a false hit 931b37e4b45SLingrui98 when(toIfuPcBundle.fallThruError && entry_hit_status(ifuPtr.value) === h_hit) { 93209c6f1ddSLingrui98 when(io.toIfu.req.fire && 933cb4f77ceSLingrui98 !(bpu_s2_redirect && bpu_s2_resp.ftq_idx === ifuPtr) && 934cf7d6b7aSMuzi !(bpu_s3_redirect && bpu_s3_resp.ftq_idx === ifuPtr)) { 93509c6f1ddSLingrui98 entry_hit_status(ifuPtr.value) := h_false_hit 936352db50aSLingrui98 // XSError(true.B, "FTB false hit by fallThroughError, startAddr: %x, fallTHru: %x\n", io.toIfu.req.bits.startAddr, io.toIfu.req.bits.nextStartAddr) 93709c6f1ddSLingrui98 } 938cf7d6b7aSMuzi XSDebug( 939cf7d6b7aSMuzi true.B, 940cf7d6b7aSMuzi "fallThruError! start:%x, fallThru:%x\n", 941cf7d6b7aSMuzi io.toIfu.req.bits.startAddr, 942cf7d6b7aSMuzi io.toIfu.req.bits.nextStartAddr 943cf7d6b7aSMuzi ) 94409c6f1ddSLingrui98 } 94509c6f1ddSLingrui98 946cf7d6b7aSMuzi XSPerfAccumulate( 947cf7d6b7aSMuzi f"fall_through_error_to_ifu", 948cf7d6b7aSMuzi toIfuPcBundle.fallThruError && entry_hit_status(ifuPtr.value) === h_hit && 949cf7d6b7aSMuzi io.toIfu.req.fire && !(bpu_s2_redirect && bpu_s2_resp.ftq_idx === ifuPtr) && !(bpu_s3_redirect && bpu_s3_resp.ftq_idx === ifuPtr) 950cf7d6b7aSMuzi ) 951a60a2901SLingrui98 95209c6f1ddSLingrui98 val ifu_req_should_be_flushed = 953cb4f77ceSLingrui98 io.toIfu.flushFromBpu.shouldFlushByStage2(io.toIfu.req.bits.ftqIdx) || 954cb4f77ceSLingrui98 io.toIfu.flushFromBpu.shouldFlushByStage3(io.toIfu.req.bits.ftqIdx) 95509c6f1ddSLingrui98 95609c6f1ddSLingrui98 when(io.toIfu.req.fire && !ifu_req_should_be_flushed) { 95709c6f1ddSLingrui98 entry_fetch_status(ifuPtr.value) := f_sent 95809c6f1ddSLingrui98 } 95909c6f1ddSLingrui98 96009c6f1ddSLingrui98 // ********************************************************************* 96109c6f1ddSLingrui98 // **************************** wb from ifu **************************** 96209c6f1ddSLingrui98 // ********************************************************************* 96309c6f1ddSLingrui98 val pdWb = io.fromIfu.pdWb 96409c6f1ddSLingrui98 val pds = pdWb.bits.pd 96509c6f1ddSLingrui98 val ifu_wb_valid = pdWb.valid 96609c6f1ddSLingrui98 val ifu_wb_idx = pdWb.bits.ftqIdx.value 96709c6f1ddSLingrui98 // read ports: commit update 968cf7d6b7aSMuzi val ftq_pd_mem = 969cf7d6b7aSMuzi Module(new SyncDataModuleTemplate(new Ftq_pd_Entry, FtqSize, FtqRedirectAheadNum + 1, 1, hasRen = true)) 97009c6f1ddSLingrui98 ftq_pd_mem.io.wen(0) := ifu_wb_valid 97109c6f1ddSLingrui98 ftq_pd_mem.io.waddr(0) := pdWb.bits.ftqIdx.value 97209c6f1ddSLingrui98 ftq_pd_mem.io.wdata(0).fromPdWb(pdWb.bits) 97309c6f1ddSLingrui98 97409c6f1ddSLingrui98 val hit_pd_valid = entry_hit_status(ifu_wb_idx) === h_hit && ifu_wb_valid 97509c6f1ddSLingrui98 val hit_pd_mispred = hit_pd_valid && pdWb.bits.misOffset.valid 97609c6f1ddSLingrui98 val hit_pd_mispred_reg = RegNext(hit_pd_mispred, init = false.B) 977005e809bSJiuyang Liu val pd_reg = RegEnable(pds, pdWb.valid) 978005e809bSJiuyang Liu val start_pc_reg = RegEnable(pdWb.bits.pc(0), pdWb.valid) 979005e809bSJiuyang Liu val wb_idx_reg = RegEnable(ifu_wb_idx, pdWb.valid) 98009c6f1ddSLingrui98 98109c6f1ddSLingrui98 when(ifu_wb_valid) { 98209c6f1ddSLingrui98 val comm_stq_wen = VecInit(pds.map(_.valid).zip(pdWb.bits.instrRange).map { 98309c6f1ddSLingrui98 case (v, inRange) => v && inRange 98409c6f1ddSLingrui98 }) 9851c6fc24aSEaston Man commitStateQueueEnable(ifu_wb_idx) := true.B 9861c6fc24aSEaston Man (commitStateQueueNext(ifu_wb_idx) zip comm_stq_wen).map { 9871c6fc24aSEaston Man case (qe, v) => when(v) { 98891346769SMuzi qe := c_toCommit 9891c6fc24aSEaston Man } 99009c6f1ddSLingrui98 } 99109c6f1ddSLingrui98 } 99209c6f1ddSLingrui98 993c5c5edaeSJenius when(ifu_wb_valid) { 994c5c5edaeSJenius ifuWbPtr_write := ifuWbPtr + 1.U 995c5c5edaeSJenius } 99609c6f1ddSLingrui98 997f21bbcb2SGuokai Chen XSError(ifu_wb_valid && isAfter(pdWb.bits.ftqIdx, ifuPtr), "IFU returned a predecode before its req, check IFU") 998f21bbcb2SGuokai Chen 9991c6fc24aSEaston Man ftb_entry_mem.io.ren.get.head := ifu_wb_valid 100009c6f1ddSLingrui98 ftb_entry_mem.io.raddr.head := ifu_wb_idx 100109c6f1ddSLingrui98 val has_false_hit = WireInit(false.B) 100209c6f1ddSLingrui98 when(RegNext(hit_pd_valid)) { 100309c6f1ddSLingrui98 // check for false hit 100409c6f1ddSLingrui98 val pred_ftb_entry = ftb_entry_mem.io.rdata.head 1005eeb5ff92SLingrui98 val brSlots = pred_ftb_entry.brSlots 1006eeb5ff92SLingrui98 val tailSlot = pred_ftb_entry.tailSlot 100709c6f1ddSLingrui98 // we check cfis that bpu predicted 100809c6f1ddSLingrui98 1009eeb5ff92SLingrui98 // bpu predicted branches but denied by predecode 1010eeb5ff92SLingrui98 val br_false_hit = 1011eeb5ff92SLingrui98 brSlots.map { 1012eeb5ff92SLingrui98 s => s.valid && !(pd_reg(s.offset).valid && pd_reg(s.offset).isBr) 1013eeb5ff92SLingrui98 }.reduce(_ || _) || 1014b37e4b45SLingrui98 (tailSlot.valid && pred_ftb_entry.tailSlot.sharing && 1015eeb5ff92SLingrui98 !(pd_reg(tailSlot.offset).valid && pd_reg(tailSlot.offset).isBr)) 1016eeb5ff92SLingrui98 1017eeb5ff92SLingrui98 val jmpOffset = tailSlot.offset 101809c6f1ddSLingrui98 val jmp_pd = pd_reg(jmpOffset) 101909c6f1ddSLingrui98 val jal_false_hit = pred_ftb_entry.jmpValid && 102009c6f1ddSLingrui98 ((pred_ftb_entry.isJal && !(jmp_pd.valid && jmp_pd.isJal)) || 102109c6f1ddSLingrui98 (pred_ftb_entry.isJalr && !(jmp_pd.valid && jmp_pd.isJalr)) || 102209c6f1ddSLingrui98 (pred_ftb_entry.isCall && !(jmp_pd.valid && jmp_pd.isCall)) || 1023cf7d6b7aSMuzi (pred_ftb_entry.isRet && !(jmp_pd.valid && jmp_pd.isRet))) 102409c6f1ddSLingrui98 102509c6f1ddSLingrui98 has_false_hit := br_false_hit || jal_false_hit || hit_pd_mispred_reg 102665fddcf0Szoujr XSDebug(has_false_hit, "FTB false hit by br or jal or hit_pd, startAddr: %x\n", pdWb.bits.pc(0)) 102765fddcf0Szoujr 1028352db50aSLingrui98 // assert(!has_false_hit) 102909c6f1ddSLingrui98 } 103009c6f1ddSLingrui98 103109c6f1ddSLingrui98 when(has_false_hit) { 103209c6f1ddSLingrui98 entry_hit_status(wb_idx_reg) := h_false_hit 103309c6f1ddSLingrui98 } 103409c6f1ddSLingrui98 103509c6f1ddSLingrui98 // ******************************************************************************* 103609c6f1ddSLingrui98 // **************************** redirect from backend **************************** 103709c6f1ddSLingrui98 // ******************************************************************************* 103809c6f1ddSLingrui98 103909c6f1ddSLingrui98 // redirect read cfiInfo, couples to redirectGen s2 104095a47398SGao-Zeyu // ftqIdxAhead(0-3) => ftq_redirect_mem(1-4), reuse ftq_redirect_mem(1) 1041bace178aSGao-Zeyu val ftq_redirect_rdata = Wire(Vec(FtqRedirectAheadNum, new Ftq_Redirect_SRAMEntry)) 1042deb3a97eSGao-Zeyu val ftb_redirect_rdata = Wire(Vec(FtqRedirectAheadNum, new FTBEntry_FtqMem)) 1043c776f0d5Smy-mayfly 1044c776f0d5Smy-mayfly val ftq_pd_rdata = Wire(Vec(FtqRedirectAheadNum, new Ftq_pd_Entry)) 104595a47398SGao-Zeyu for (i <- 1 until FtqRedirectAheadNum) { 104695a47398SGao-Zeyu ftq_redirect_mem.io.ren.get(i + IfuRedirectNum) := ftqIdxAhead(i).valid 104795a47398SGao-Zeyu ftq_redirect_mem.io.raddr(i + IfuRedirectNum) := ftqIdxAhead(i).bits.value 104895a47398SGao-Zeyu ftb_entry_mem.io.ren.get(i + IfuRedirectNum) := ftqIdxAhead(i).valid 104995a47398SGao-Zeyu ftb_entry_mem.io.raddr(i + IfuRedirectNum) := ftqIdxAhead(i).bits.value 1050c776f0d5Smy-mayfly 1051c776f0d5Smy-mayfly ftq_pd_mem.io.ren.get(i) := ftqIdxAhead(i).valid 1052c776f0d5Smy-mayfly ftq_pd_mem.io.raddr(i) := ftqIdxAhead(i).bits.value 10539342624fSGao-Zeyu } 105495a47398SGao-Zeyu ftq_redirect_mem.io.ren.get(IfuRedirectNum) := Mux(aheadValid, ftqIdxAhead(0).valid, backendRedirect.valid) 1055cf7d6b7aSMuzi ftq_redirect_mem.io.raddr(IfuRedirectNum) := Mux( 1056cf7d6b7aSMuzi aheadValid, 1057cf7d6b7aSMuzi ftqIdxAhead(0).bits.value, 1058cf7d6b7aSMuzi backendRedirect.bits.ftqIdx.value 1059cf7d6b7aSMuzi ) 106095a47398SGao-Zeyu ftb_entry_mem.io.ren.get(IfuRedirectNum) := Mux(aheadValid, ftqIdxAhead(0).valid, backendRedirect.valid) 1061cf7d6b7aSMuzi ftb_entry_mem.io.raddr(IfuRedirectNum) := Mux( 1062cf7d6b7aSMuzi aheadValid, 1063cf7d6b7aSMuzi ftqIdxAhead(0).bits.value, 1064cf7d6b7aSMuzi backendRedirect.bits.ftqIdx.value 1065cf7d6b7aSMuzi ) 1066bace178aSGao-Zeyu 1067c776f0d5Smy-mayfly ftq_pd_mem.io.ren.get(0) := Mux(aheadValid, ftqIdxAhead(0).valid, backendRedirect.valid) 1068c776f0d5Smy-mayfly ftq_pd_mem.io.raddr(0) := Mux(aheadValid, ftqIdxAhead(0).bits.value, backendRedirect.bits.ftqIdx.value) 1069c776f0d5Smy-mayfly 1070bace178aSGao-Zeyu for (i <- 0 until FtqRedirectAheadNum) { 107195a47398SGao-Zeyu ftq_redirect_rdata(i) := ftq_redirect_mem.io.rdata(i + IfuRedirectNum) 107295a47398SGao-Zeyu ftb_redirect_rdata(i) := ftb_entry_mem.io.rdata(i + IfuRedirectNum) 1073c776f0d5Smy-mayfly 1074c776f0d5Smy-mayfly ftq_pd_rdata(i) := ftq_pd_mem.io.rdata(i) 1075bace178aSGao-Zeyu } 1076cf7d6b7aSMuzi val stage3CfiInfo = 1077cf7d6b7aSMuzi Mux(realAhdValid, Mux1H(ftqIdxSelOH, ftq_redirect_rdata), ftq_redirect_mem.io.rdata(IfuRedirectNum)) 1078c776f0d5Smy-mayfly val stage3PdInfo = Mux(realAhdValid, Mux1H(ftqIdxSelOH, ftq_pd_rdata), ftq_pd_mem.io.rdata(0)) 107909c6f1ddSLingrui98 val backendRedirectCfi = fromBackendRedirect.bits.cfiUpdate 108009c6f1ddSLingrui98 backendRedirectCfi.fromFtqRedirectSram(stage3CfiInfo) 1081c776f0d5Smy-mayfly backendRedirectCfi.pd := stage3PdInfo.toPd(fromBackendRedirect.bits.ftqOffset) 108209c6f1ddSLingrui98 108395a47398SGao-Zeyu val r_ftb_entry = Mux(realAhdValid, Mux1H(ftqIdxSelOH, ftb_redirect_rdata), ftb_entry_mem.io.rdata(IfuRedirectNum)) 108409c6f1ddSLingrui98 val r_ftqOffset = fromBackendRedirect.bits.ftqOffset 108509c6f1ddSLingrui98 1086d2b20d1aSTang Haojin backendRedirectCfi.br_hit := r_ftb_entry.brIsSaved(r_ftqOffset) 1087d2b20d1aSTang Haojin backendRedirectCfi.jr_hit := r_ftb_entry.isJalr && r_ftb_entry.tailSlot.offset === r_ftqOffset 10883711cf36S小造xu_zh // FIXME: not portable 1089abdc3a32Sxu_zh val sc_disagree = stage3CfiInfo.sc_disagree.getOrElse(VecInit(Seq.fill(numBr)(false.B))) 1090cf7d6b7aSMuzi backendRedirectCfi.sc_hit := backendRedirectCfi.br_hit && Mux( 1091cf7d6b7aSMuzi r_ftb_entry.brSlots(0).offset === r_ftqOffset, 1092cf7d6b7aSMuzi sc_disagree(0), 1093cf7d6b7aSMuzi sc_disagree(1) 1094cf7d6b7aSMuzi ) 1095d2b20d1aSTang Haojin 109609c6f1ddSLingrui98 when(entry_hit_status(fromBackendRedirect.bits.ftqIdx.value) === h_hit) { 109709c6f1ddSLingrui98 backendRedirectCfi.shift := PopCount(r_ftb_entry.getBrMaskByOffset(r_ftqOffset)) +& 109809c6f1ddSLingrui98 (backendRedirectCfi.pd.isBr && !r_ftb_entry.brIsSaved(r_ftqOffset) && 1099eeb5ff92SLingrui98 !r_ftb_entry.newBrCanNotInsert(r_ftqOffset)) 110009c6f1ddSLingrui98 110109c6f1ddSLingrui98 backendRedirectCfi.addIntoHist := backendRedirectCfi.pd.isBr && (r_ftb_entry.brIsSaved(r_ftqOffset) || 1102eeb5ff92SLingrui98 !r_ftb_entry.newBrCanNotInsert(r_ftqOffset)) 110309c6f1ddSLingrui98 }.otherwise { 110409c6f1ddSLingrui98 backendRedirectCfi.shift := (backendRedirectCfi.pd.isBr && backendRedirectCfi.taken).asUInt 110509c6f1ddSLingrui98 backendRedirectCfi.addIntoHist := backendRedirectCfi.pd.isBr.asUInt 110609c6f1ddSLingrui98 } 110709c6f1ddSLingrui98 110809c6f1ddSLingrui98 // *************************************************************************** 110909c6f1ddSLingrui98 // **************************** redirect from ifu **************************** 111009c6f1ddSLingrui98 // *************************************************************************** 1111d2b20d1aSTang Haojin val fromIfuRedirect = WireInit(0.U.asTypeOf(Valid(new BranchPredictionRedirect))) 111209c6f1ddSLingrui98 fromIfuRedirect.valid := pdWb.valid && pdWb.bits.misOffset.valid && !backendFlush 111309c6f1ddSLingrui98 fromIfuRedirect.bits.ftqIdx := pdWb.bits.ftqIdx 111409c6f1ddSLingrui98 fromIfuRedirect.bits.ftqOffset := pdWb.bits.misOffset.bits 111509c6f1ddSLingrui98 fromIfuRedirect.bits.level := RedirectLevel.flushAfter 1116d2b20d1aSTang Haojin fromIfuRedirect.bits.BTBMissBubble := true.B 1117d2b20d1aSTang Haojin fromIfuRedirect.bits.debugIsMemVio := false.B 1118d2b20d1aSTang Haojin fromIfuRedirect.bits.debugIsCtrl := false.B 111909c6f1ddSLingrui98 112009c6f1ddSLingrui98 val ifuRedirectCfiUpdate = fromIfuRedirect.bits.cfiUpdate 112109c6f1ddSLingrui98 ifuRedirectCfiUpdate.pc := pdWb.bits.pc(pdWb.bits.misOffset.bits) 112209c6f1ddSLingrui98 ifuRedirectCfiUpdate.pd := pdWb.bits.pd(pdWb.bits.misOffset.bits) 112309c6f1ddSLingrui98 ifuRedirectCfiUpdate.predTaken := cfiIndex_vec(pdWb.bits.ftqIdx.value).valid 112409c6f1ddSLingrui98 ifuRedirectCfiUpdate.target := pdWb.bits.target 112509c6f1ddSLingrui98 ifuRedirectCfiUpdate.taken := pdWb.bits.cfiOffset.valid 112609c6f1ddSLingrui98 ifuRedirectCfiUpdate.isMisPred := pdWb.bits.misOffset.valid 112709c6f1ddSLingrui98 11281c6fc24aSEaston Man val ifuRedirectReg = RegNextWithEnable(fromIfuRedirect, hasInit = true) 112909c6f1ddSLingrui98 val ifuRedirectToBpu = WireInit(ifuRedirectReg) 113009c6f1ddSLingrui98 ifuFlush := fromIfuRedirect.valid || ifuRedirectToBpu.valid 113109c6f1ddSLingrui98 113216a171eeSEaston Man ftq_redirect_mem.io.ren.get.head := fromIfuRedirect.valid 1133deb3a97eSGao-Zeyu ftq_redirect_mem.io.raddr.head := fromIfuRedirect.bits.ftqIdx.value 113409c6f1ddSLingrui98 113509c6f1ddSLingrui98 val toBpuCfi = ifuRedirectToBpu.bits.cfiUpdate 1136deb3a97eSGao-Zeyu toBpuCfi.fromFtqRedirectSram(ftq_redirect_mem.io.rdata.head) 1137f1267a13SEaston Man when(ifuRedirectReg.bits.cfiUpdate.pd.isRet && ifuRedirectReg.bits.cfiUpdate.pd.valid) { 1138c89b4642SGuokai Chen toBpuCfi.target := toBpuCfi.topAddr 113909c6f1ddSLingrui98 } 114009c6f1ddSLingrui98 1141d2b20d1aSTang Haojin when(ifuRedirectReg.valid) { 1142d2b20d1aSTang Haojin ifuRedirected(ifuRedirectReg.bits.ftqIdx.value) := true.B 1143d2b20d1aSTang Haojin }.elsewhen(RegNext(pdWb.valid)) { 1144d2b20d1aSTang Haojin // if pdWb and no redirect, set to false 1145d2b20d1aSTang Haojin ifuRedirected(last_cycle_bpu_in_ptr.value) := false.B 1146d2b20d1aSTang Haojin } 1147d2b20d1aSTang Haojin 11486022c595SsinceforYy // ********************************************************************** 11496022c595SsinceforYy // ***************************** to backend ***************************** 11506022c595SsinceforYy // ********************************************************************** 11516022c595SsinceforYy // to backend pc mem / target 11526022c595SsinceforYy io.toBackend.pc_mem_wen := RegNext(last_cycle_bpu_in) 1153f533cba7SHuSipeng io.toBackend.pc_mem_waddr := RegEnable(last_cycle_bpu_in_idx, last_cycle_bpu_in) 11546022c595SsinceforYy io.toBackend.pc_mem_wdata := RegEnable(bpu_in_bypass_buf_for_ifu, last_cycle_bpu_in) 11556022c595SsinceforYy 11566022c595SsinceforYy // num cycle is fixed 11576022c595SsinceforYy val newest_entry_en: Bool = RegNext(last_cycle_bpu_in || backendRedirect.valid || ifuRedirectToBpu.valid) 11586022c595SsinceforYy io.toBackend.newest_entry_en := RegNext(newest_entry_en) 11596022c595SsinceforYy io.toBackend.newest_entry_ptr := RegEnable(newest_entry_ptr, newest_entry_en) 11606022c595SsinceforYy io.toBackend.newest_entry_target := RegEnable(newest_entry_target, newest_entry_en) 11616022c595SsinceforYy 116209c6f1ddSLingrui98 // ********************************************************************* 116309c6f1ddSLingrui98 // **************************** wb from exu **************************** 116409c6f1ddSLingrui98 // ********************************************************************* 116509c6f1ddSLingrui98 1166d2b20d1aSTang Haojin backendRedirect.valid := io.fromBackend.redirect.valid 1167d2b20d1aSTang Haojin backendRedirect.bits.connectRedirect(io.fromBackend.redirect.bits) 1168d2b20d1aSTang Haojin backendRedirect.bits.BTBMissBubble := false.B 1169d2b20d1aSTang Haojin 117009c6f1ddSLingrui98 def extractRedirectInfo(wb: Valid[Redirect]) = { 11716bf9b30dSLingrui98 val ftqPtr = wb.bits.ftqIdx 117209c6f1ddSLingrui98 val ftqOffset = wb.bits.ftqOffset 117309c6f1ddSLingrui98 val taken = wb.bits.cfiUpdate.taken 117409c6f1ddSLingrui98 val mispred = wb.bits.cfiUpdate.isMisPred 11756bf9b30dSLingrui98 (wb.valid, ftqPtr, ftqOffset, taken, mispred) 117609c6f1ddSLingrui98 } 117709c6f1ddSLingrui98 117809c6f1ddSLingrui98 // fix mispredict entry 117909c6f1ddSLingrui98 val lastIsMispredict = RegNext( 1180cf7d6b7aSMuzi backendRedirect.valid && backendRedirect.bits.level === RedirectLevel.flushAfter, 1181cf7d6b7aSMuzi init = false.B 118209c6f1ddSLingrui98 ) 118309c6f1ddSLingrui98 118409c6f1ddSLingrui98 def updateCfiInfo(redirect: Valid[Redirect], isBackend: Boolean = true) = { 11856bf9b30dSLingrui98 val (r_valid, r_ptr, r_offset, r_taken, r_mispred) = extractRedirectInfo(redirect) 11866bf9b30dSLingrui98 val r_idx = r_ptr.value 118709c6f1ddSLingrui98 val cfiIndex_bits_wen = r_valid && r_taken && r_offset < cfiIndex_vec(r_idx).bits 118809c6f1ddSLingrui98 val cfiIndex_valid_wen = r_valid && r_offset === cfiIndex_vec(r_idx).bits 118909c6f1ddSLingrui98 when(cfiIndex_bits_wen || cfiIndex_valid_wen) { 119009c6f1ddSLingrui98 cfiIndex_vec(r_idx).valid := cfiIndex_bits_wen || cfiIndex_valid_wen && r_taken 11913f88c020SGuokai Chen }.elsewhen(r_valid && !r_taken && r_offset =/= cfiIndex_vec(r_idx).bits) { 11923f88c020SGuokai Chen cfiIndex_vec(r_idx).valid := false.B 119309c6f1ddSLingrui98 } 119409c6f1ddSLingrui98 when(cfiIndex_bits_wen) { 119509c6f1ddSLingrui98 cfiIndex_vec(r_idx).bits := r_offset 119609c6f1ddSLingrui98 } 11971c6fc24aSEaston Man newest_entry_target_modified := true.B 11986bf9b30dSLingrui98 newest_entry_target := redirect.bits.cfiUpdate.target 11991c6fc24aSEaston Man newest_entry_ptr_modified := true.B 1200873dc383SLingrui98 newest_entry_ptr := r_ptr 12011c6fc24aSEaston Man 1202b0ed7239SLingrui98 update_target(r_idx) := redirect.bits.cfiUpdate.target // TODO: remove this 120309c6f1ddSLingrui98 if (isBackend) { 120409c6f1ddSLingrui98 mispredict_vec(r_idx)(r_offset) := r_mispred 120509c6f1ddSLingrui98 } 120609c6f1ddSLingrui98 } 120709c6f1ddSLingrui98 1208bace178aSGao-Zeyu when(fromBackendRedirect.valid) { 1209bace178aSGao-Zeyu updateCfiInfo(fromBackendRedirect) 121009c6f1ddSLingrui98 }.elsewhen(ifuRedirectToBpu.valid) { 121109c6f1ddSLingrui98 updateCfiInfo(ifuRedirectToBpu, isBackend = false) 121209c6f1ddSLingrui98 } 121309c6f1ddSLingrui98 1214bace178aSGao-Zeyu when(fromBackendRedirect.valid) { 1215bace178aSGao-Zeyu when(fromBackendRedirect.bits.ControlRedirectBubble) { 1216d2b20d1aSTang Haojin when(fromBackendRedirect.bits.ControlBTBMissBubble) { 1217d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.BTBMissBubble.id) := true.B 1218d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.BTBMissBubble.id) := true.B 1219d2b20d1aSTang Haojin }.elsewhen(fromBackendRedirect.bits.TAGEMissBubble) { 1220d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.TAGEMissBubble.id) := true.B 1221d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.TAGEMissBubble.id) := true.B 1222d2b20d1aSTang Haojin }.elsewhen(fromBackendRedirect.bits.SCMissBubble) { 1223d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.SCMissBubble.id) := true.B 1224d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.SCMissBubble.id) := true.B 1225d2b20d1aSTang Haojin }.elsewhen(fromBackendRedirect.bits.ITTAGEMissBubble) { 1226d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.ITTAGEMissBubble.id) := true.B 1227d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.ITTAGEMissBubble.id) := true.B 1228d2b20d1aSTang Haojin }.elsewhen(fromBackendRedirect.bits.RASMissBubble) { 1229d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.RASMissBubble.id) := true.B 1230d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.RASMissBubble.id) := true.B 1231d2b20d1aSTang Haojin } 1232d2b20d1aSTang Haojin 12339342624fSGao-Zeyu }.elsewhen(backendRedirect.bits.MemVioRedirectBubble) { 1234d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.MemVioRedirectBubble.id) := true.B 1235d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.MemVioRedirectBubble.id) := true.B 1236d2b20d1aSTang Haojin }.otherwise { 1237d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.OtherRedirectBubble.id) := true.B 1238d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.OtherRedirectBubble.id) := true.B 1239d2b20d1aSTang Haojin } 1240d2b20d1aSTang Haojin }.elsewhen(ifuRedirectReg.valid) { 1241d2b20d1aSTang Haojin topdown_stage.reasons(TopDownCounters.BTBMissBubble.id) := true.B 1242d2b20d1aSTang Haojin io.toIfu.req.bits.topdown_info.reasons(TopDownCounters.BTBMissBubble.id) := true.B 1243d2b20d1aSTang Haojin } 1244d2b20d1aSTang Haojin 1245d2b20d1aSTang Haojin io.ControlBTBMissBubble := fromBackendRedirect.bits.ControlBTBMissBubble 1246d2b20d1aSTang Haojin io.TAGEMissBubble := fromBackendRedirect.bits.TAGEMissBubble 1247d2b20d1aSTang Haojin io.SCMissBubble := fromBackendRedirect.bits.SCMissBubble 1248d2b20d1aSTang Haojin io.ITTAGEMissBubble := fromBackendRedirect.bits.ITTAGEMissBubble 1249d2b20d1aSTang Haojin io.RASMissBubble := fromBackendRedirect.bits.RASMissBubble 1250d2b20d1aSTang Haojin 125109c6f1ddSLingrui98 // *********************************************************************************** 125209c6f1ddSLingrui98 // **************************** flush ptr and state queue **************************** 125309c6f1ddSLingrui98 // *********************************************************************************** 125409c6f1ddSLingrui98 1255df5b4b8eSYinan Xu val redirectVec = VecInit(backendRedirect, fromIfuRedirect) 125609c6f1ddSLingrui98 125709c6f1ddSLingrui98 // when redirect, we should reset ptrs and status queues 1258b92f8445Sssszwic io.icacheFlush := redirectVec.map(r => r.valid).reduce(_ || _) 1259b92f8445Sssszwic XSPerfAccumulate("icacheFlushFromBackend", backendRedirect.valid) 1260b92f8445Sssszwic XSPerfAccumulate("icacheFlushFromIFU", fromIfuRedirect.valid) 126109c6f1ddSLingrui98 when(redirectVec.map(r => r.valid).reduce(_ || _)) { 1262cf7d6b7aSMuzi val r = PriorityMux(redirectVec.map(r => r.valid -> r.bits)) 126309c6f1ddSLingrui98 val notIfu = redirectVec.dropRight(1).map(r => r.valid).reduce(_ || _) 12642f4a3aa4SLingrui98 val (idx, offset, flushItSelf) = (r.ftqIdx, r.ftqOffset, RedirectLevel.flushItself(r.level)) 126509c6f1ddSLingrui98 val next = idx + 1.U 126609c6f1ddSLingrui98 bpuPtr := next 1267dc270d3bSJenius copied_bpu_ptr.map(_ := next) 1268c5c5edaeSJenius ifuPtr_write := next 1269c5c5edaeSJenius ifuWbPtr_write := next 1270c5c5edaeSJenius ifuPtrPlus1_write := idx + 2.U 12716bf9b30dSLingrui98 ifuPtrPlus2_write := idx + 3.U 1272b92f8445Sssszwic pfPtr_write := next 1273b92f8445Sssszwic pfPtrPlus1_write := idx + 2.U 12743f88c020SGuokai Chen } 12753f88c020SGuokai Chen when(RegNext(redirectVec.map(r => r.valid).reduce(_ || _))) { 1276cf7d6b7aSMuzi val r = PriorityMux(redirectVec.map(r => r.valid -> r.bits)) 12773f88c020SGuokai Chen val notIfu = redirectVec.dropRight(1).map(r => r.valid).reduce(_ || _) 12783f88c020SGuokai Chen val (idx, offset, flushItSelf) = (r.ftqIdx, r.ftqOffset, RedirectLevel.flushItself(r.level)) 12793f88c020SGuokai Chen when(RegNext(notIfu)) { 12801c6fc24aSEaston Man commitStateQueueEnable(RegNext(idx.value)) := true.B 1281cf7d6b7aSMuzi commitStateQueueNext(RegNext(idx.value)).zipWithIndex.foreach { case (s, i) => 128291346769SMuzi when(i.U > RegNext(offset)) { 128391346769SMuzi s := c_empty 128491346769SMuzi } 128591346769SMuzi when(i.U === RegNext(offset) && RegNext(flushItSelf)) { 128691346769SMuzi s := c_flushed 128709c6f1ddSLingrui98 } 128809c6f1ddSLingrui98 } 128909c6f1ddSLingrui98 } 1290cf7d6b7aSMuzi } 12913f88c020SGuokai Chen 129209c6f1ddSLingrui98 // only the valid bit is actually needed 1293df5b4b8eSYinan Xu io.toIfu.redirect.bits := backendRedirect.bits 129409c6f1ddSLingrui98 io.toIfu.redirect.valid := stage2Flush 1295d2b20d1aSTang Haojin io.toIfu.topdown_redirect := fromBackendRedirect 129609c6f1ddSLingrui98 129709c6f1ddSLingrui98 // commit 12989aca92b9SYinan Xu for (c <- io.fromBackend.rob_commits) { 129909c6f1ddSLingrui98 when(c.valid) { 13001c6fc24aSEaston Man commitStateQueueEnable(c.bits.ftqIdx.value) := true.B 130191346769SMuzi commitStateQueueNext(c.bits.ftqIdx.value)(c.bits.ftqOffset) := c_committed 130288825c5cSYinan Xu // TODO: remove this 130388825c5cSYinan Xu // For instruction fusions, we also update the next instruction 1304c3abb8b6SYinan Xu when(c.bits.commitType === 4.U) { 130591346769SMuzi commitStateQueueNext(c.bits.ftqIdx.value)(c.bits.ftqOffset + 1.U) := c_committed 1306c3abb8b6SYinan Xu }.elsewhen(c.bits.commitType === 5.U) { 130791346769SMuzi commitStateQueueNext(c.bits.ftqIdx.value)(c.bits.ftqOffset + 2.U) := c_committed 1308c3abb8b6SYinan Xu }.elsewhen(c.bits.commitType === 6.U) { 130988825c5cSYinan Xu val index = (c.bits.ftqIdx + 1.U).value 13101c6fc24aSEaston Man commitStateQueueEnable(index) := true.B 131191346769SMuzi commitStateQueueNext(index)(0) := c_committed 1312c3abb8b6SYinan Xu }.elsewhen(c.bits.commitType === 7.U) { 131388825c5cSYinan Xu val index = (c.bits.ftqIdx + 1.U).value 13141c6fc24aSEaston Man commitStateQueueEnable(index) := true.B 131591346769SMuzi commitStateQueueNext(index)(1) := c_committed 131688825c5cSYinan Xu } 131709c6f1ddSLingrui98 } 131809c6f1ddSLingrui98 } 131909c6f1ddSLingrui98 132009c6f1ddSLingrui98 // **************************************************************** 132109c6f1ddSLingrui98 // **************************** to bpu **************************** 132209c6f1ddSLingrui98 // **************************************************************** 132309c6f1ddSLingrui98 1324fd3aa057SYuandongliang io.toBpu.redirctFromIFU := ifuRedirectToBpu.valid 132551981c77SbugGenerator io.toBpu.redirect := Mux(fromBackendRedirect.valid, fromBackendRedirect, ifuRedirectToBpu) 1326209a4cafSSteve Gou val dummy_s1_pred_cycle_vec = VecInit(List.tabulate(FtqSize)(_ => 0.U(64.W))) 1327cf7d6b7aSMuzi val redirect_latency = 1328cf7d6b7aSMuzi GTimer() - pred_s1_cycle.getOrElse(dummy_s1_pred_cycle_vec)(io.toBpu.redirect.bits.ftqIdx.value) + 1.U 1329209a4cafSSteve Gou XSPerfHistogram("backend_redirect_latency", redirect_latency, fromBackendRedirect.valid, 0, 60, 1) 1330cf7d6b7aSMuzi XSPerfHistogram( 1331cf7d6b7aSMuzi "ifu_redirect_latency", 1332cf7d6b7aSMuzi redirect_latency, 1333cf7d6b7aSMuzi !fromBackendRedirect.valid && ifuRedirectToBpu.valid, 1334cf7d6b7aSMuzi 0, 1335cf7d6b7aSMuzi 60, 1336cf7d6b7aSMuzi 1 1337cf7d6b7aSMuzi ) 133809c6f1ddSLingrui98 1339cf7d6b7aSMuzi XSError( 1340cf7d6b7aSMuzi io.toBpu.redirect.valid && isBefore(io.toBpu.redirect.bits.ftqIdx, commPtr), 1341cf7d6b7aSMuzi "Ftq received a redirect after its commit, check backend or replay" 1342cf7d6b7aSMuzi ) 134309c6f1ddSLingrui98 134402f21c16SLingrui98 val may_have_stall_from_bpu = Wire(Bool()) 134502f21c16SLingrui98 val bpu_ftb_update_stall = RegInit(0.U(2.W)) // 2-cycle stall, so we need 3 states 134602f21c16SLingrui98 may_have_stall_from_bpu := bpu_ftb_update_stall =/= 0.U 13479230e379SMuzi 13489230e379SMuzi val validInstructions = commitStateQueueReg(commPtr.value).map(s => s === c_toCommit || s === c_committed) 13499230e379SMuzi val lastInstructionStatus = PriorityMux(validInstructions.reverse.zip(commitStateQueueReg(commPtr.value).reverse)) 13509230e379SMuzi val firstInstructionFlushed = commitStateQueueReg(commPtr.value)(0) === c_flushed 13519230e379SMuzi canCommit := commPtr =/= ifuWbPtr && !may_have_stall_from_bpu && 13529230e379SMuzi (isAfter(robCommPtr, commPtr) || 13539230e379SMuzi validInstructions.reduce(_ || _) && lastInstructionStatus === c_committed) 13549230e379SMuzi val canMoveCommPtr = commPtr =/= ifuWbPtr && !may_have_stall_from_bpu && 13559230e379SMuzi (isAfter(robCommPtr, commPtr) || 13569230e379SMuzi validInstructions.reduce(_ || _) && lastInstructionStatus === c_committed || 13579230e379SMuzi firstInstructionFlushed) 135891346769SMuzi 135991346769SMuzi when(io.fromBackend.rob_commits.map(_.valid).reduce(_ | _)) { 1360cf7d6b7aSMuzi robCommPtr_write := ParallelPriorityMux( 1361cf7d6b7aSMuzi io.fromBackend.rob_commits.map(_.valid).reverse, 1362cf7d6b7aSMuzi io.fromBackend.rob_commits.map(_.bits.ftqIdx).reverse 1363cf7d6b7aSMuzi ) 13649230e379SMuzi }.elsewhen(isAfter(commPtr, robCommPtr)) { 136591346769SMuzi robCommPtr_write := commPtr 136691346769SMuzi }.otherwise { 136791346769SMuzi robCommPtr_write := robCommPtr 136891346769SMuzi } 136909c6f1ddSLingrui98 1370ba5ba1dcSmy-mayfly /** 1371ba5ba1dcSmy-mayfly ************************************************************************************* 1372ba5ba1dcSmy-mayfly * MMIO instruction fetch is allowed only if MMIO is the oldest instruction. 1373ba5ba1dcSmy-mayfly ************************************************************************************* 1374ba5ba1dcSmy-mayfly */ 13751d1e6d4dSJenius val mmioReadPtr = io.mmioCommitRead.mmioFtqPtr 13769230e379SMuzi val mmioLastCommit = isAfter(commPtr, mmioReadPtr) || 13779230e379SMuzi commPtr === mmioReadPtr && validInstructions.reduce(_ || _) && lastInstructionStatus === c_committed 13781d1e6d4dSJenius io.mmioCommitRead.mmioLastCommit := RegNext(mmioLastCommit) 13791d1e6d4dSJenius 138009c6f1ddSLingrui98 // commit reads 1381c5c5edaeSJenius val commit_pc_bundle = RegNext(ftq_pc_mem.io.commPtr_rdata) 138281101dc4SLingrui98 val commit_target = 1383cf7d6b7aSMuzi Mux( 1384cf7d6b7aSMuzi RegNext(commPtr === newest_entry_ptr), 13851c6fc24aSEaston Man RegEnable(newest_entry_target, newest_entry_target_modified), 1386cf7d6b7aSMuzi RegNext(ftq_pc_mem.io.commPtrPlus1_rdata.startAddr) 1387cf7d6b7aSMuzi ) 13881c6fc24aSEaston Man ftq_pd_mem.io.ren.get.last := canCommit 138909c6f1ddSLingrui98 ftq_pd_mem.io.raddr.last := commPtr.value 139009c6f1ddSLingrui98 val commit_pd = ftq_pd_mem.io.rdata.last 139116a171eeSEaston Man ftq_redirect_mem.io.ren.get.last := canCommit 1392deb3a97eSGao-Zeyu ftq_redirect_mem.io.raddr.last := commPtr.value 1393deb3a97eSGao-Zeyu val commit_spec_meta = ftq_redirect_mem.io.rdata.last 139409c6f1ddSLingrui98 ftq_meta_1r_sram.io.ren(0) := canCommit 139509c6f1ddSLingrui98 ftq_meta_1r_sram.io.raddr(0) := commPtr.value 1396deb3a97eSGao-Zeyu val commit_meta = ftq_meta_1r_sram.io.rdata(0).meta 1397deb3a97eSGao-Zeyu val commit_ftb_entry = ftq_meta_1r_sram.io.rdata(0).ftb_entry 139809c6f1ddSLingrui98 139909c6f1ddSLingrui98 // need one cycle to read mem and srams 14001c6fc24aSEaston Man val do_commit_ptr = RegEnable(commPtr, canCommit) 14015371700eSzoujr val do_commit = RegNext(canCommit, init = false.B) 14029230e379SMuzi when(canMoveCommPtr) { 14036bf9b30dSLingrui98 commPtr_write := commPtrPlus1 14046bf9b30dSLingrui98 commPtrPlus1_write := commPtrPlus1 + 1.U 14056bf9b30dSLingrui98 } 14061c6fc24aSEaston Man val commit_state = RegEnable(commitStateQueueReg(commPtr.value), canCommit) 14075371700eSzoujr val can_commit_cfi = WireInit(cfiIndex_vec(commPtr.value)) 1408d4fcfc3eSGuokai Chen val do_commit_cfi = WireInit(cfiIndex_vec(do_commit_ptr.value)) 14093f88c020SGuokai Chen // 14103f88c020SGuokai Chen // when (commitStateQueue(commPtr.value)(can_commit_cfi.bits) =/= c_commited) { 14113f88c020SGuokai Chen // can_commit_cfi.valid := false.B 14123f88c020SGuokai Chen // } 14131c6fc24aSEaston Man val commit_cfi = RegEnable(can_commit_cfi, canCommit) 141491346769SMuzi val debug_cfi = commitStateQueueReg(do_commit_ptr.value)(do_commit_cfi.bits) =/= c_committed && do_commit_cfi.valid 141509c6f1ddSLingrui98 1416cf7d6b7aSMuzi val commit_mispredict: Vec[Bool] = 1417cf7d6b7aSMuzi VecInit((RegEnable(mispredict_vec(commPtr.value), canCommit) zip commit_state).map { 141891346769SMuzi case (mis, state) => mis && state === c_committed 141909c6f1ddSLingrui98 }) 142091346769SMuzi val commit_instCommited: Vec[Bool] = VecInit(commit_state.map(_ === c_committed)) // [PredictWidth] 14215371700eSzoujr val can_commit_hit = entry_hit_status(commPtr.value) 14221c6fc24aSEaston Man val commit_hit = RegEnable(can_commit_hit, canCommit) 14231c6fc24aSEaston Man val diff_commit_target = RegEnable(update_target(commPtr.value), canCommit) // TODO: remove this 14241c6fc24aSEaston Man val commit_stage = RegEnable(pred_stage(commPtr.value), canCommit) 142509c6f1ddSLingrui98 val commit_valid = commit_hit === h_hit || commit_cfi.valid // hit or taken 142609c6f1ddSLingrui98 14275371700eSzoujr val to_bpu_hit = can_commit_hit === h_hit || can_commit_hit === h_false_hit 142802f21c16SLingrui98 switch(bpu_ftb_update_stall) { 142902f21c16SLingrui98 is(0.U) { 143002f21c16SLingrui98 when(can_commit_cfi.valid && !to_bpu_hit && canCommit) { 143102f21c16SLingrui98 bpu_ftb_update_stall := 2.U // 2-cycle stall 143202f21c16SLingrui98 } 143302f21c16SLingrui98 } 143402f21c16SLingrui98 is(2.U) { 143502f21c16SLingrui98 bpu_ftb_update_stall := 1.U 143602f21c16SLingrui98 } 143702f21c16SLingrui98 is(1.U) { 143802f21c16SLingrui98 bpu_ftb_update_stall := 0.U 143902f21c16SLingrui98 } 144002f21c16SLingrui98 is(3.U) { 144102f21c16SLingrui98 XSError(true.B, "bpu_ftb_update_stall should be 0, 1 or 2") 144202f21c16SLingrui98 } 144302f21c16SLingrui98 } 144409c6f1ddSLingrui98 1445b0ed7239SLingrui98 // TODO: remove this 1446b0ed7239SLingrui98 XSError(do_commit && diff_commit_target =/= commit_target, "\ncommit target should be the same as update target\n") 1447b0ed7239SLingrui98 1448b2f6ed0aSSteve Gou // update latency stats 1449b2f6ed0aSSteve Gou val update_latency = GTimer() - pred_s1_cycle.getOrElse(dummy_s1_pred_cycle_vec)(do_commit_ptr.value) + 1.U 1450b2f6ed0aSSteve Gou XSPerfHistogram("bpu_update_latency", update_latency, io.toBpu.update.valid, 0, 64, 2) 1451b2f6ed0aSSteve Gou 145209c6f1ddSLingrui98 io.toBpu.update := DontCare 145309c6f1ddSLingrui98 io.toBpu.update.valid := commit_valid && do_commit 145409c6f1ddSLingrui98 val update = io.toBpu.update.bits 145509c6f1ddSLingrui98 update.false_hit := commit_hit === h_false_hit 145609c6f1ddSLingrui98 update.pc := commit_pc_bundle.startAddr 1457deb3a97eSGao-Zeyu update.meta := commit_meta 1458803124a6SLingrui98 update.cfi_idx := commit_cfi 14598ffcd86aSLingrui98 update.full_target := commit_target 1460edc18578SLingrui98 update.from_stage := commit_stage 1461c2d1ec7dSLingrui98 update.spec_info := commit_spec_meta 14623f88c020SGuokai Chen XSError(commit_valid && do_commit && debug_cfi, "\ncommit cfi can be non c_commited\n") 146309c6f1ddSLingrui98 146409c6f1ddSLingrui98 val commit_real_hit = commit_hit === h_hit 146509c6f1ddSLingrui98 val update_ftb_entry = update.ftb_entry 146609c6f1ddSLingrui98 146709c6f1ddSLingrui98 val ftbEntryGen = Module(new FTBEntryGen).io 146809c6f1ddSLingrui98 ftbEntryGen.start_addr := commit_pc_bundle.startAddr 146909c6f1ddSLingrui98 ftbEntryGen.old_entry := commit_ftb_entry 147009c6f1ddSLingrui98 ftbEntryGen.pd := commit_pd 147109c6f1ddSLingrui98 ftbEntryGen.cfiIndex := commit_cfi 147209c6f1ddSLingrui98 ftbEntryGen.target := commit_target 147309c6f1ddSLingrui98 ftbEntryGen.hit := commit_real_hit 147409c6f1ddSLingrui98 ftbEntryGen.mispredict_vec := commit_mispredict 147509c6f1ddSLingrui98 147609c6f1ddSLingrui98 update_ftb_entry := ftbEntryGen.new_entry 147709c6f1ddSLingrui98 update.new_br_insert_pos := ftbEntryGen.new_br_insert_pos 147809c6f1ddSLingrui98 update.mispred_mask := ftbEntryGen.mispred_mask 147909c6f1ddSLingrui98 update.old_entry := ftbEntryGen.is_old_entry 1480edc18578SLingrui98 update.pred_hit := commit_hit === h_hit || commit_hit === h_false_hit 1481803124a6SLingrui98 update.br_taken_mask := ftbEntryGen.taken_mask 1482cc2d1573SEaston Man update.br_committed := (ftbEntryGen.new_entry.brValids zip ftbEntryGen.new_entry.brOffset) map { 1483cc2d1573SEaston Man case (valid, offset) => valid && commit_instCommited(offset) 1484cc2d1573SEaston Man } 1485803124a6SLingrui98 update.jmp_taken := ftbEntryGen.jmp_taken 1486b37e4b45SLingrui98 1487803124a6SLingrui98 // update.full_pred.fromFtbEntry(ftbEntryGen.new_entry, update.pc) 1488803124a6SLingrui98 // update.full_pred.jalr_target := commit_target 1489803124a6SLingrui98 // update.full_pred.hit := true.B 1490803124a6SLingrui98 // when (update.full_pred.is_jalr) { 1491803124a6SLingrui98 // update.full_pred.targets.last := commit_target 1492803124a6SLingrui98 // } 149309c6f1ddSLingrui98 149409c6f1ddSLingrui98 // ****************************************************************************** 149509c6f1ddSLingrui98 // **************************** commit perf counters **************************** 149609c6f1ddSLingrui98 // ****************************************************************************** 149709c6f1ddSLingrui98 149891346769SMuzi val commit_inst_mask = VecInit(commit_state.map(c => c === c_committed && do_commit)).asUInt 149909c6f1ddSLingrui98 val commit_mispred_mask = commit_mispredict.asUInt 150009c6f1ddSLingrui98 val commit_not_mispred_mask = ~commit_mispred_mask 150109c6f1ddSLingrui98 150209c6f1ddSLingrui98 val commit_br_mask = commit_pd.brMask.asUInt 150309c6f1ddSLingrui98 val commit_jmp_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.jmpInfo.valid.asTypeOf(UInt(1.W))) 1504cf7d6b7aSMuzi val commit_cfi_mask = commit_br_mask | commit_jmp_mask 150509c6f1ddSLingrui98 150609c6f1ddSLingrui98 val mbpInstrs = commit_inst_mask & commit_cfi_mask 150709c6f1ddSLingrui98 150809c6f1ddSLingrui98 val mbpRights = mbpInstrs & commit_not_mispred_mask 150909c6f1ddSLingrui98 val mbpWrongs = mbpInstrs & commit_mispred_mask 151009c6f1ddSLingrui98 151109c6f1ddSLingrui98 io.bpuInfo.bpRight := PopCount(mbpRights) 151209c6f1ddSLingrui98 io.bpuInfo.bpWrong := PopCount(mbpWrongs) 151309c6f1ddSLingrui98 1514b92f8445Sssszwic val hartId = p(XSCoreParamsKey).HartId 1515c686adcdSYinan Xu val isWriteFTQTable = Constantin.createRecord(s"isWriteFTQTable$hartId") 1516c686adcdSYinan Xu val ftqBranchTraceDB = ChiselDB.createTable(s"FTQTable$hartId", new FtqDebugBundle) 151709c6f1ddSLingrui98 // Cfi Info 151809c6f1ddSLingrui98 for (i <- 0 until PredictWidth) { 151909c6f1ddSLingrui98 val pc = commit_pc_bundle.startAddr + (i * instBytes).U 152091346769SMuzi val v = commit_state(i) === c_committed 152109c6f1ddSLingrui98 val isBr = commit_pd.brMask(i) 152209c6f1ddSLingrui98 val isJmp = commit_pd.jmpInfo.valid && commit_pd.jmpOffset === i.U 152309c6f1ddSLingrui98 val isCfi = isBr || isJmp 152409c6f1ddSLingrui98 val isTaken = commit_cfi.valid && commit_cfi.bits === i.U 152509c6f1ddSLingrui98 val misPred = commit_mispredict(i) 1526c2ad24ebSLingrui98 // val ghist = commit_spec_meta.ghist.predHist 1527c2ad24ebSLingrui98 val histPtr = commit_spec_meta.histPtr 1528deb3a97eSGao-Zeyu val predCycle = commit_meta(63, 0) 152909c6f1ddSLingrui98 val target = commit_target 153009c6f1ddSLingrui98 1531cf7d6b7aSMuzi val brIdx = OHToUInt(Reverse(Cat(update_ftb_entry.brValids.zip(update_ftb_entry.brOffset).map { case (v, offset) => 1532cf7d6b7aSMuzi v && offset === i.U 1533cf7d6b7aSMuzi }))) 1534cf7d6b7aSMuzi val inFtbEntry = update_ftb_entry.brValids.zip(update_ftb_entry.brOffset).map { case (v, offset) => 1535cf7d6b7aSMuzi v && offset === i.U 1536cf7d6b7aSMuzi }.reduce(_ || _) 1537cf7d6b7aSMuzi val addIntoHist = 1538cf7d6b7aSMuzi ((commit_hit === h_hit) && inFtbEntry) || (!(commit_hit === h_hit) && i.U === commit_cfi.bits && isBr && commit_cfi.valid) 1539cf7d6b7aSMuzi XSDebug( 1540cf7d6b7aSMuzi v && do_commit && isCfi, 1541cf7d6b7aSMuzi p"cfi_update: isBr(${isBr}) pc(${Hexadecimal(pc)}) " + 1542c2ad24ebSLingrui98 p"taken(${isTaken}) mispred(${misPred}) cycle($predCycle) hist(${histPtr.value}) " + 154309c6f1ddSLingrui98 p"startAddr(${Hexadecimal(commit_pc_bundle.startAddr)}) AddIntoHist(${addIntoHist}) " + 1544cf7d6b7aSMuzi p"brInEntry(${inFtbEntry}) brIdx(${brIdx}) target(${Hexadecimal(target)})\n" 1545cf7d6b7aSMuzi ) 154651532d8bSGuokai Chen 154751532d8bSGuokai Chen val logbundle = Wire(new FtqDebugBundle) 154851532d8bSGuokai Chen logbundle.pc := pc 154951532d8bSGuokai Chen logbundle.target := target 155051532d8bSGuokai Chen logbundle.isBr := isBr 155151532d8bSGuokai Chen logbundle.isJmp := isJmp 155251532d8bSGuokai Chen logbundle.isCall := isJmp && commit_pd.hasCall 155351532d8bSGuokai Chen logbundle.isRet := isJmp && commit_pd.hasRet 155451532d8bSGuokai Chen logbundle.misPred := misPred 155551532d8bSGuokai Chen logbundle.isTaken := isTaken 155651532d8bSGuokai Chen logbundle.predStage := commit_stage 155751532d8bSGuokai Chen 155851532d8bSGuokai Chen ftqBranchTraceDB.log( 155951532d8bSGuokai Chen data = logbundle /* hardware of type T */, 1560da3bf434SMaxpicca-Li en = isWriteFTQTable.orR && v && do_commit && isCfi, 156151532d8bSGuokai Chen site = "FTQ" + p(XSCoreParamsKey).HartId.toString, 156251532d8bSGuokai Chen clock = clock, 156351532d8bSGuokai Chen reset = reset 156451532d8bSGuokai Chen ) 156509c6f1ddSLingrui98 } 156609c6f1ddSLingrui98 156709c6f1ddSLingrui98 val enq = io.fromBpu.resp 15682e1be6e1SSteve Gou val perf_redirect = backendRedirect 156909c6f1ddSLingrui98 157009c6f1ddSLingrui98 XSPerfAccumulate("entry", validEntries) 157109c6f1ddSLingrui98 XSPerfAccumulate("bpu_to_ftq_stall", enq.valid && !enq.ready) 157209c6f1ddSLingrui98 XSPerfAccumulate("mispredictRedirect", perf_redirect.valid && RedirectLevel.flushAfter === perf_redirect.bits.level) 157309c6f1ddSLingrui98 XSPerfAccumulate("replayRedirect", perf_redirect.valid && RedirectLevel.flushItself(perf_redirect.bits.level)) 157409c6f1ddSLingrui98 XSPerfAccumulate("predecodeRedirect", fromIfuRedirect.valid) 157509c6f1ddSLingrui98 157609c6f1ddSLingrui98 XSPerfAccumulate("to_ifu_bubble", io.toIfu.req.ready && !io.toIfu.req.valid) 157709c6f1ddSLingrui98 157809c6f1ddSLingrui98 XSPerfAccumulate("to_ifu_stall", io.toIfu.req.valid && !io.toIfu.req.ready) 157909c6f1ddSLingrui98 XSPerfAccumulate("from_bpu_real_bubble", !enq.valid && enq.ready && allowBpuIn) 158012cedb6fSLingrui98 XSPerfAccumulate("bpu_to_ifu_bubble", bpuPtr === ifuPtr) 1581cf7d6b7aSMuzi XSPerfAccumulate( 1582cf7d6b7aSMuzi "bpu_to_ifu_bubble_when_ftq_full", 1583cf7d6b7aSMuzi (bpuPtr === ifuPtr) && isFull(bpuPtr, commPtr) && io.toIfu.req.ready 1584cf7d6b7aSMuzi ) 158509c6f1ddSLingrui98 1586bace178aSGao-Zeyu XSPerfAccumulate("redirectAhead_ValidNum", ftqIdxAhead.map(_.valid).reduce(_ | _)) 15879342624fSGao-Zeyu XSPerfAccumulate("fromBackendRedirect_ValidNum", io.fromBackend.redirect.valid) 15889342624fSGao-Zeyu XSPerfAccumulate("toBpuRedirect_ValidNum", io.toBpu.redirect.valid) 15899342624fSGao-Zeyu 159009c6f1ddSLingrui98 val from_bpu = io.fromBpu.resp.bits 159109c6f1ddSLingrui98 val to_ifu = io.toIfu.req.bits 159209c6f1ddSLingrui98 1593209a4cafSSteve Gou XSPerfHistogram("commit_num_inst", PopCount(commit_inst_mask), do_commit, 0, PredictWidth + 1, 1) 159409c6f1ddSLingrui98 159509c6f1ddSLingrui98 val commit_jal_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasJal.asTypeOf(UInt(1.W))) 159609c6f1ddSLingrui98 val commit_jalr_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasJalr.asTypeOf(UInt(1.W))) 159709c6f1ddSLingrui98 val commit_call_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasCall.asTypeOf(UInt(1.W))) 159809c6f1ddSLingrui98 val commit_ret_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasRet.asTypeOf(UInt(1.W))) 159909c6f1ddSLingrui98 160009c6f1ddSLingrui98 val mbpBRights = mbpRights & commit_br_mask 160109c6f1ddSLingrui98 val mbpJRights = mbpRights & commit_jal_mask 160209c6f1ddSLingrui98 val mbpIRights = mbpRights & commit_jalr_mask 160309c6f1ddSLingrui98 val mbpCRights = mbpRights & commit_call_mask 160409c6f1ddSLingrui98 val mbpRRights = mbpRights & commit_ret_mask 160509c6f1ddSLingrui98 160609c6f1ddSLingrui98 val mbpBWrongs = mbpWrongs & commit_br_mask 160709c6f1ddSLingrui98 val mbpJWrongs = mbpWrongs & commit_jal_mask 160809c6f1ddSLingrui98 val mbpIWrongs = mbpWrongs & commit_jalr_mask 160909c6f1ddSLingrui98 val mbpCWrongs = mbpWrongs & commit_call_mask 161009c6f1ddSLingrui98 val mbpRWrongs = mbpWrongs & commit_ret_mask 161109c6f1ddSLingrui98 16121d7e5011SLingrui98 val commit_pred_stage = RegNext(pred_stage(commPtr.value)) 16131d7e5011SLingrui98 1614cf7d6b7aSMuzi def pred_stage_map(src: UInt, name: String) = 16151d7e5011SLingrui98 (0 until numBpStages).map(i => 16161d7e5011SLingrui98 f"${name}_stage_${i + 1}" -> PopCount(src.asBools.map(_ && commit_pred_stage === BP_STAGES(i))) 16171d7e5011SLingrui98 ).foldLeft(Map[String, UInt]())(_ + _) 16181d7e5011SLingrui98 16191d7e5011SLingrui98 val mispred_stage_map = pred_stage_map(mbpWrongs, "mispredict") 16201d7e5011SLingrui98 val br_mispred_stage_map = pred_stage_map(mbpBWrongs, "br_mispredict") 16211d7e5011SLingrui98 val jalr_mispred_stage_map = pred_stage_map(mbpIWrongs, "jalr_mispredict") 16221d7e5011SLingrui98 val correct_stage_map = pred_stage_map(mbpRights, "correct") 16231d7e5011SLingrui98 val br_correct_stage_map = pred_stage_map(mbpBRights, "br_correct") 16241d7e5011SLingrui98 val jalr_correct_stage_map = pred_stage_map(mbpIRights, "jalr_correct") 16251d7e5011SLingrui98 162609c6f1ddSLingrui98 val update_valid = io.toBpu.update.valid 162709c6f1ddSLingrui98 def u(cond: Bool) = update_valid && cond 162809c6f1ddSLingrui98 val ftb_false_hit = u(update.false_hit) 162965fddcf0Szoujr // assert(!ftb_false_hit) 163009c6f1ddSLingrui98 val ftb_hit = u(commit_hit === h_hit) 163109c6f1ddSLingrui98 163209c6f1ddSLingrui98 val ftb_new_entry = u(ftbEntryGen.is_init_entry) 1633b37e4b45SLingrui98 val ftb_new_entry_only_br = ftb_new_entry && !update_ftb_entry.jmpValid 1634b37e4b45SLingrui98 val ftb_new_entry_only_jmp = ftb_new_entry && !update_ftb_entry.brValids(0) 1635b37e4b45SLingrui98 val ftb_new_entry_has_br_and_jmp = ftb_new_entry && update_ftb_entry.brValids(0) && update_ftb_entry.jmpValid 163609c6f1ddSLingrui98 163709c6f1ddSLingrui98 val ftb_old_entry = u(ftbEntryGen.is_old_entry) 163809c6f1ddSLingrui98 1639cf7d6b7aSMuzi val ftb_modified_entry = 1640*dcf4211fSYuandongliang u(ftbEntryGen.is_new_br || ftbEntryGen.is_jalr_target_modified || ftbEntryGen.is_strong_bias_modified) 164109c6f1ddSLingrui98 val ftb_modified_entry_new_br = u(ftbEntryGen.is_new_br) 1642d2b20d1aSTang Haojin val ftb_modified_entry_ifu_redirected = u(ifuRedirected(do_commit_ptr.value)) 164309c6f1ddSLingrui98 val ftb_modified_entry_jalr_target_modified = u(ftbEntryGen.is_jalr_target_modified) 164409c6f1ddSLingrui98 val ftb_modified_entry_br_full = ftb_modified_entry && ftbEntryGen.is_br_full 1645*dcf4211fSYuandongliang val ftb_modified_entry_strong_bias = ftb_modified_entry && ftbEntryGen.is_strong_bias_modified 164609c6f1ddSLingrui98 1647209a4cafSSteve Gou def getFtbEntryLen(pc: UInt, entry: FTBEntry) = (entry.getFallThrough(pc) - pc) >> instOffsetBits 1648209a4cafSSteve Gou val gen_ftb_entry_len = getFtbEntryLen(update.pc, ftbEntryGen.new_entry) 1649209a4cafSSteve Gou XSPerfHistogram("ftb_init_entry_len", gen_ftb_entry_len, ftb_new_entry, 0, PredictWidth + 1, 1) 1650209a4cafSSteve Gou XSPerfHistogram("ftb_modified_entry_len", gen_ftb_entry_len, ftb_modified_entry, 0, PredictWidth + 1, 1) 1651209a4cafSSteve Gou val s3_ftb_entry_len = getFtbEntryLen(from_bpu.s3.pc(0), from_bpu.last_stage_ftb_entry) 1652209a4cafSSteve Gou XSPerfHistogram("s3_ftb_entry_len", s3_ftb_entry_len, from_bpu.s3.valid(0), 0, PredictWidth + 1, 1) 165309c6f1ddSLingrui98 1654209a4cafSSteve Gou XSPerfHistogram("ftq_has_entry", validEntries, true.B, 0, FtqSize + 1, 1) 165509c6f1ddSLingrui98 165609c6f1ddSLingrui98 val perfCountsMap = Map( 165709c6f1ddSLingrui98 "BpInstr" -> PopCount(mbpInstrs), 165809c6f1ddSLingrui98 "BpBInstr" -> PopCount(mbpBRights | mbpBWrongs), 165909c6f1ddSLingrui98 "BpRight" -> PopCount(mbpRights), 166009c6f1ddSLingrui98 "BpWrong" -> PopCount(mbpWrongs), 166109c6f1ddSLingrui98 "BpBRight" -> PopCount(mbpBRights), 166209c6f1ddSLingrui98 "BpBWrong" -> PopCount(mbpBWrongs), 166309c6f1ddSLingrui98 "BpJRight" -> PopCount(mbpJRights), 166409c6f1ddSLingrui98 "BpJWrong" -> PopCount(mbpJWrongs), 166509c6f1ddSLingrui98 "BpIRight" -> PopCount(mbpIRights), 166609c6f1ddSLingrui98 "BpIWrong" -> PopCount(mbpIWrongs), 166709c6f1ddSLingrui98 "BpCRight" -> PopCount(mbpCRights), 166809c6f1ddSLingrui98 "BpCWrong" -> PopCount(mbpCWrongs), 166909c6f1ddSLingrui98 "BpRRight" -> PopCount(mbpRRights), 167009c6f1ddSLingrui98 "BpRWrong" -> PopCount(mbpRWrongs), 167109c6f1ddSLingrui98 "ftb_false_hit" -> PopCount(ftb_false_hit), 167209c6f1ddSLingrui98 "ftb_hit" -> PopCount(ftb_hit), 167309c6f1ddSLingrui98 "ftb_new_entry" -> PopCount(ftb_new_entry), 167409c6f1ddSLingrui98 "ftb_new_entry_only_br" -> PopCount(ftb_new_entry_only_br), 167509c6f1ddSLingrui98 "ftb_new_entry_only_jmp" -> PopCount(ftb_new_entry_only_jmp), 167609c6f1ddSLingrui98 "ftb_new_entry_has_br_and_jmp" -> PopCount(ftb_new_entry_has_br_and_jmp), 167709c6f1ddSLingrui98 "ftb_old_entry" -> PopCount(ftb_old_entry), 167809c6f1ddSLingrui98 "ftb_modified_entry" -> PopCount(ftb_modified_entry), 167909c6f1ddSLingrui98 "ftb_modified_entry_new_br" -> PopCount(ftb_modified_entry_new_br), 168009c6f1ddSLingrui98 "ftb_jalr_target_modified" -> PopCount(ftb_modified_entry_jalr_target_modified), 168109c6f1ddSLingrui98 "ftb_modified_entry_br_full" -> PopCount(ftb_modified_entry_br_full), 1682*dcf4211fSYuandongliang "ftb_modified_entry_strong_bias" -> PopCount(ftb_modified_entry_strong_bias) 1683209a4cafSSteve Gou ) ++ mispred_stage_map ++ br_mispred_stage_map ++ jalr_mispred_stage_map ++ 16841d7e5011SLingrui98 correct_stage_map ++ br_correct_stage_map ++ jalr_correct_stage_map 168509c6f1ddSLingrui98 168609c6f1ddSLingrui98 for ((key, value) <- perfCountsMap) { 168709c6f1ddSLingrui98 XSPerfAccumulate(key, value) 168809c6f1ddSLingrui98 } 168909c6f1ddSLingrui98 169009c6f1ddSLingrui98 // --------------------------- Debug -------------------------------- 169109c6f1ddSLingrui98 // XSDebug(enq_fire, p"enq! " + io.fromBpu.resp.bits.toPrintable) 169209c6f1ddSLingrui98 XSDebug(io.toIfu.req.fire, p"fire to ifu " + io.toIfu.req.bits.toPrintable) 169309c6f1ddSLingrui98 XSDebug(do_commit, p"deq! [ptr] $do_commit_ptr\n") 169409c6f1ddSLingrui98 XSDebug(true.B, p"[bpuPtr] $bpuPtr, [ifuPtr] $ifuPtr, [ifuWbPtr] $ifuWbPtr [commPtr] $commPtr\n") 1695cf7d6b7aSMuzi XSDebug( 1696cf7d6b7aSMuzi true.B, 1697cf7d6b7aSMuzi p"[in] v:${io.fromBpu.resp.valid} r:${io.fromBpu.resp.ready} " + 1698cf7d6b7aSMuzi p"[out] v:${io.toIfu.req.valid} r:${io.toIfu.req.ready}\n" 1699cf7d6b7aSMuzi ) 170009c6f1ddSLingrui98 XSDebug(do_commit, p"[deq info] cfiIndex: $commit_cfi, $commit_pc_bundle, target: ${Hexadecimal(commit_target)}\n") 170109c6f1ddSLingrui98 170209c6f1ddSLingrui98 // def ubtbCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 170309c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 170409c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 170509c6f1ddSLingrui98 // Mux(valid && pd.isBr, 170609c6f1ddSLingrui98 // isWrong ^ Mux(ans.hit.asBool, 170709c6f1ddSLingrui98 // Mux(ans.taken.asBool, taken && ans.target === commitEntry.target, 170809c6f1ddSLingrui98 // !taken), 170909c6f1ddSLingrui98 // !taken), 171009c6f1ddSLingrui98 // false.B) 171109c6f1ddSLingrui98 // } 171209c6f1ddSLingrui98 // } 171309c6f1ddSLingrui98 171409c6f1ddSLingrui98 // def btbCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 171509c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 171609c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 171709c6f1ddSLingrui98 // Mux(valid && pd.isBr, 171809c6f1ddSLingrui98 // isWrong ^ Mux(ans.hit.asBool, 171909c6f1ddSLingrui98 // Mux(ans.taken.asBool, taken && ans.target === commitEntry.target, 172009c6f1ddSLingrui98 // !taken), 172109c6f1ddSLingrui98 // !taken), 172209c6f1ddSLingrui98 // false.B) 172309c6f1ddSLingrui98 // } 172409c6f1ddSLingrui98 // } 172509c6f1ddSLingrui98 172609c6f1ddSLingrui98 // def tageCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 172709c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 172809c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 172909c6f1ddSLingrui98 // Mux(valid && pd.isBr, 173009c6f1ddSLingrui98 // isWrong ^ (ans.taken.asBool === taken), 173109c6f1ddSLingrui98 // false.B) 173209c6f1ddSLingrui98 // } 173309c6f1ddSLingrui98 // } 173409c6f1ddSLingrui98 173509c6f1ddSLingrui98 // def loopCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 173609c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 173709c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 173809c6f1ddSLingrui98 // Mux(valid && (pd.isBr) && ans.hit.asBool, 173909c6f1ddSLingrui98 // isWrong ^ (!taken), 174009c6f1ddSLingrui98 // false.B) 174109c6f1ddSLingrui98 // } 174209c6f1ddSLingrui98 // } 174309c6f1ddSLingrui98 174409c6f1ddSLingrui98 // def rasCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 174509c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 174609c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 174709c6f1ddSLingrui98 // Mux(valid && pd.isRet.asBool /*&& taken*/ && ans.hit.asBool, 174809c6f1ddSLingrui98 // isWrong ^ (ans.target === commitEntry.target), 174909c6f1ddSLingrui98 // false.B) 175009c6f1ddSLingrui98 // } 175109c6f1ddSLingrui98 // } 175209c6f1ddSLingrui98 175309c6f1ddSLingrui98 // val ubtbRights = ubtbCheck(commitEntry, commitEntry.metas.map(_.ubtbAns), false.B) 175409c6f1ddSLingrui98 // val ubtbWrongs = ubtbCheck(commitEntry, commitEntry.metas.map(_.ubtbAns), true.B) 175509c6f1ddSLingrui98 // // btb and ubtb pred jal and jalr as well 175609c6f1ddSLingrui98 // val btbRights = btbCheck(commitEntry, commitEntry.metas.map(_.btbAns), false.B) 175709c6f1ddSLingrui98 // val btbWrongs = btbCheck(commitEntry, commitEntry.metas.map(_.btbAns), true.B) 175809c6f1ddSLingrui98 // val tageRights = tageCheck(commitEntry, commitEntry.metas.map(_.tageAns), false.B) 175909c6f1ddSLingrui98 // val tageWrongs = tageCheck(commitEntry, commitEntry.metas.map(_.tageAns), true.B) 176009c6f1ddSLingrui98 176109c6f1ddSLingrui98 // val loopRights = loopCheck(commitEntry, commitEntry.metas.map(_.loopAns), false.B) 176209c6f1ddSLingrui98 // val loopWrongs = loopCheck(commitEntry, commitEntry.metas.map(_.loopAns), true.B) 176309c6f1ddSLingrui98 176409c6f1ddSLingrui98 // val rasRights = rasCheck(commitEntry, commitEntry.metas.map(_.rasAns), false.B) 176509c6f1ddSLingrui98 // val rasWrongs = rasCheck(commitEntry, commitEntry.metas.map(_.rasAns), true.B) 17661ca0e4f3SYinan Xu 1767cd365d4cSrvcoresjw val perfEvents = Seq( 1768cd365d4cSrvcoresjw ("bpu_s2_redirect ", bpu_s2_redirect), 1769cb4f77ceSLingrui98 ("bpu_s3_redirect ", bpu_s3_redirect), 1770cd365d4cSrvcoresjw ("bpu_to_ftq_stall ", enq.valid && ~enq.ready), 1771cd365d4cSrvcoresjw ("mispredictRedirect ", perf_redirect.valid && RedirectLevel.flushAfter === perf_redirect.bits.level), 1772cd365d4cSrvcoresjw ("replayRedirect ", perf_redirect.valid && RedirectLevel.flushItself(perf_redirect.bits.level)), 1773cd365d4cSrvcoresjw ("predecodeRedirect ", fromIfuRedirect.valid), 1774cd365d4cSrvcoresjw ("to_ifu_bubble ", io.toIfu.req.ready && !io.toIfu.req.valid), 1775cd365d4cSrvcoresjw ("from_bpu_real_bubble ", !enq.valid && enq.ready && allowBpuIn), 1776cd365d4cSrvcoresjw ("BpInstr ", PopCount(mbpInstrs)), 1777cd365d4cSrvcoresjw ("BpBInstr ", PopCount(mbpBRights | mbpBWrongs)), 1778cd365d4cSrvcoresjw ("BpRight ", PopCount(mbpRights)), 1779cd365d4cSrvcoresjw ("BpWrong ", PopCount(mbpWrongs)), 1780cd365d4cSrvcoresjw ("BpBRight ", PopCount(mbpBRights)), 1781cd365d4cSrvcoresjw ("BpBWrong ", PopCount(mbpBWrongs)), 1782cd365d4cSrvcoresjw ("BpJRight ", PopCount(mbpJRights)), 1783cd365d4cSrvcoresjw ("BpJWrong ", PopCount(mbpJWrongs)), 1784cd365d4cSrvcoresjw ("BpIRight ", PopCount(mbpIRights)), 1785cd365d4cSrvcoresjw ("BpIWrong ", PopCount(mbpIWrongs)), 1786cd365d4cSrvcoresjw ("BpCRight ", PopCount(mbpCRights)), 1787cd365d4cSrvcoresjw ("BpCWrong ", PopCount(mbpCWrongs)), 1788cd365d4cSrvcoresjw ("BpRRight ", PopCount(mbpRRights)), 1789cd365d4cSrvcoresjw ("BpRWrong ", PopCount(mbpRWrongs)), 1790cd365d4cSrvcoresjw ("ftb_false_hit ", PopCount(ftb_false_hit)), 1791cf7d6b7aSMuzi ("ftb_hit ", PopCount(ftb_hit)) 1792cd365d4cSrvcoresjw ) 17931ca0e4f3SYinan Xu generatePerfEvent() 179409c6f1ddSLingrui98} 1795