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 chipsalliance.rocketchip.config.Parameters 2009c6f1ddSLingrui98import chisel3._ 2109c6f1ddSLingrui98import chisel3.util._ 2209c6f1ddSLingrui98import utils.{AsyncDataModuleTemplate, CircularQueuePtr, DataModuleTemplate, HasCircularQueuePtrHelper, SRAMTemplate, SyncDataModuleTemplate, XSDebug, XSPerfAccumulate, XSError} 2309c6f1ddSLingrui98import xiangshan._ 2409c6f1ddSLingrui98import scala.tools.nsc.doc.model.Val 2509c6f1ddSLingrui98import utils.{ParallelPriorityMux, ParallelPriorityEncoder} 2609c6f1ddSLingrui98import xiangshan.backend.{CtrlToFtqIO} 2709c6f1ddSLingrui98import firrtl.annotations.MemoryLoadFileType 2809c6f1ddSLingrui98 2909c6f1ddSLingrui98class FtqPtr(implicit p: Parameters) extends CircularQueuePtr[FtqPtr]( 3009c6f1ddSLingrui98 p => p(XSCoreParamsKey).FtqSize 3109c6f1ddSLingrui98){ 3209c6f1ddSLingrui98 override def cloneType = (new FtqPtr).asInstanceOf[this.type] 3309c6f1ddSLingrui98} 3409c6f1ddSLingrui98 3509c6f1ddSLingrui98object FtqPtr { 3609c6f1ddSLingrui98 def apply(f: Bool, v: UInt)(implicit p: Parameters): FtqPtr = { 3709c6f1ddSLingrui98 val ptr = Wire(new FtqPtr) 3809c6f1ddSLingrui98 ptr.flag := f 3909c6f1ddSLingrui98 ptr.value := v 4009c6f1ddSLingrui98 ptr 4109c6f1ddSLingrui98 } 4209c6f1ddSLingrui98 def inverse(ptr: FtqPtr)(implicit p: Parameters): FtqPtr = { 4309c6f1ddSLingrui98 apply(!ptr.flag, ptr.value) 4409c6f1ddSLingrui98 } 4509c6f1ddSLingrui98} 4609c6f1ddSLingrui98 4709c6f1ddSLingrui98class FtqNRSRAM[T <: Data](gen: T, numRead: Int)(implicit p: Parameters) extends XSModule { 4809c6f1ddSLingrui98 4909c6f1ddSLingrui98 val io = IO(new Bundle() { 5009c6f1ddSLingrui98 val raddr = Input(Vec(numRead, UInt(log2Up(FtqSize).W))) 5109c6f1ddSLingrui98 val ren = Input(Vec(numRead, Bool())) 5209c6f1ddSLingrui98 val rdata = Output(Vec(numRead, gen)) 5309c6f1ddSLingrui98 val waddr = Input(UInt(log2Up(FtqSize).W)) 5409c6f1ddSLingrui98 val wen = Input(Bool()) 5509c6f1ddSLingrui98 val wdata = Input(gen) 5609c6f1ddSLingrui98 }) 5709c6f1ddSLingrui98 5809c6f1ddSLingrui98 for(i <- 0 until numRead){ 5909c6f1ddSLingrui98 val sram = Module(new SRAMTemplate(gen, FtqSize)) 6009c6f1ddSLingrui98 sram.io.r.req.valid := io.ren(i) 6109c6f1ddSLingrui98 sram.io.r.req.bits.setIdx := io.raddr(i) 6209c6f1ddSLingrui98 io.rdata(i) := sram.io.r.resp.data(0) 6309c6f1ddSLingrui98 sram.io.w.req.valid := io.wen 6409c6f1ddSLingrui98 sram.io.w.req.bits.setIdx := io.waddr 6509c6f1ddSLingrui98 sram.io.w.req.bits.data := VecInit(io.wdata) 6609c6f1ddSLingrui98 } 6709c6f1ddSLingrui98 6809c6f1ddSLingrui98} 6909c6f1ddSLingrui98 7009c6f1ddSLingrui98class Ftq_RF_Components(implicit p: Parameters) extends XSBundle with BPUUtils { 7109c6f1ddSLingrui98 // TODO: move pftAddr, oversize, carry to another mem 7209c6f1ddSLingrui98 val startAddr = UInt(VAddrBits.W) 7309c6f1ddSLingrui98 val nextRangeAddr = UInt(VAddrBits.W) 7409c6f1ddSLingrui98 val pftAddr = UInt((log2Ceil(PredictWidth)+1).W) 7509c6f1ddSLingrui98 val isNextMask = Vec(PredictWidth, Bool()) 7609c6f1ddSLingrui98 val oversize = Bool() 7709c6f1ddSLingrui98 val carry = Bool() 7809c6f1ddSLingrui98 def getPc(offset: UInt) = { 7909c6f1ddSLingrui98 def getHigher(pc: UInt) = pc(VAddrBits-1, log2Ceil(PredictWidth)+instOffsetBits) 8009c6f1ddSLingrui98 def getOffset(pc: UInt) = pc(log2Ceil(PredictWidth)+instOffsetBits-1, instOffsetBits) 8109c6f1ddSLingrui98 Cat(getHigher(Mux(isNextMask(offset), nextRangeAddr, startAddr)), 8209c6f1ddSLingrui98 getOffset(startAddr)+offset, 0.U(instOffsetBits.W)) 8309c6f1ddSLingrui98 } 8409c6f1ddSLingrui98 def getFallThrough() = { 8509c6f1ddSLingrui98 getFallThroughAddr(this.startAddr, this.carry, this.pftAddr) 8609c6f1ddSLingrui98 } 8709c6f1ddSLingrui98 def fallThroughError() = { 8809c6f1ddSLingrui98 !carry && startAddr(instOffsetBits+log2Ceil(PredictWidth), instOffsetBits) > pftAddr 8909c6f1ddSLingrui98 } 9009c6f1ddSLingrui98 def fromBranchPrediction(resp: BranchPredictionBundle) = { 9109c6f1ddSLingrui98 this.startAddr := resp.pc 9209c6f1ddSLingrui98 this.nextRangeAddr := resp.pc + (FetchWidth * 4).U 9309c6f1ddSLingrui98 this.pftAddr := resp.ftb_entry.pftAddr 9409c6f1ddSLingrui98 this.isNextMask := VecInit((0 until PredictWidth).map(i => 9509c6f1ddSLingrui98 (resp.pc(log2Ceil(PredictWidth), 1) +& i.U)(log2Ceil(PredictWidth)).asBool() 9609c6f1ddSLingrui98 )) 9709c6f1ddSLingrui98 this.oversize := resp.ftb_entry.oversize 9809c6f1ddSLingrui98 this.carry := resp.ftb_entry.carry 9909c6f1ddSLingrui98 this 10009c6f1ddSLingrui98 } 10109c6f1ddSLingrui98 override def toPrintable: Printable = { 10209c6f1ddSLingrui98 p"startAddr:${Hexadecimal(startAddr)}, fallThru:${Hexadecimal(getFallThrough())}" 10309c6f1ddSLingrui98 } 10409c6f1ddSLingrui98} 10509c6f1ddSLingrui98 10609c6f1ddSLingrui98class Ftq_pd_Entry(implicit p: Parameters) extends XSBundle { 10709c6f1ddSLingrui98 val brMask = Vec(PredictWidth, Bool()) 10809c6f1ddSLingrui98 val jmpInfo = ValidUndirectioned(Vec(3, Bool())) 10909c6f1ddSLingrui98 val jmpOffset = UInt(log2Ceil(PredictWidth).W) 11009c6f1ddSLingrui98 val jalTarget = UInt(VAddrBits.W) 11109c6f1ddSLingrui98 val rvcMask = Vec(PredictWidth, Bool()) 11209c6f1ddSLingrui98 def hasJal = jmpInfo.valid && !jmpInfo.bits(0) 11309c6f1ddSLingrui98 def hasJalr = jmpInfo.valid && jmpInfo.bits(0) 11409c6f1ddSLingrui98 def hasCall = jmpInfo.valid && jmpInfo.bits(1) 11509c6f1ddSLingrui98 def hasRet = jmpInfo.valid && jmpInfo.bits(2) 11609c6f1ddSLingrui98 11709c6f1ddSLingrui98 def fromPdWb(pdWb: PredecodeWritebackBundle) = { 11809c6f1ddSLingrui98 val pds = pdWb.pd 11909c6f1ddSLingrui98 this.brMask := VecInit(pds.map(pd => pd.isBr && pd.valid)) 12009c6f1ddSLingrui98 this.jmpInfo.valid := VecInit(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid)).asUInt.orR 12109c6f1ddSLingrui98 this.jmpInfo.bits := ParallelPriorityMux(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid), 12209c6f1ddSLingrui98 pds.map(pd => VecInit(pd.isJalr, pd.isCall, pd.isRet))) 12309c6f1ddSLingrui98 this.jmpOffset := ParallelPriorityEncoder(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid)) 12409c6f1ddSLingrui98 this.rvcMask := VecInit(pds.map(pd => pd.isRVC)) 12509c6f1ddSLingrui98 this.jalTarget := pdWb.jalTarget 12609c6f1ddSLingrui98 } 12709c6f1ddSLingrui98 12809c6f1ddSLingrui98 def toPd(offset: UInt) = { 12909c6f1ddSLingrui98 require(offset.getWidth == log2Ceil(PredictWidth)) 13009c6f1ddSLingrui98 val pd = Wire(new PreDecodeInfo) 13109c6f1ddSLingrui98 pd.valid := true.B 13209c6f1ddSLingrui98 pd.isRVC := rvcMask(offset) 13309c6f1ddSLingrui98 val isBr = brMask(offset) 13409c6f1ddSLingrui98 val isJalr = offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(0) 13509c6f1ddSLingrui98 pd.brType := Cat(offset === jmpOffset && jmpInfo.valid, isJalr || isBr) 13609c6f1ddSLingrui98 pd.isCall := offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(1) 13709c6f1ddSLingrui98 pd.isRet := offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(2) 13809c6f1ddSLingrui98 pd 13909c6f1ddSLingrui98 } 14009c6f1ddSLingrui98} 14109c6f1ddSLingrui98 14209c6f1ddSLingrui98 14309c6f1ddSLingrui98 14409c6f1ddSLingrui98class Ftq_Redirect_SRAMEntry(implicit p: Parameters) extends XSBundle with HasBPUConst { 14509c6f1ddSLingrui98 val rasSp = UInt(log2Ceil(RasSize).W) 14609c6f1ddSLingrui98 val rasEntry = new RASEntry 14709c6f1ddSLingrui98 val specCnt = Vec(numBr, UInt(10.W)) 14809c6f1ddSLingrui98 val ghist = new GlobalHistory 14909c6f1ddSLingrui98 val phist = UInt(PathHistoryLength.W) 15009c6f1ddSLingrui98 val phNewBit = UInt(1.W) 15109c6f1ddSLingrui98 15209c6f1ddSLingrui98 def fromBranchPrediction(resp: BranchPredictionBundle) = { 15309c6f1ddSLingrui98 this.rasSp := resp.rasSp 15409c6f1ddSLingrui98 this.rasEntry := resp.rasTop 15509c6f1ddSLingrui98 this.specCnt := resp.specCnt 15609c6f1ddSLingrui98 this.ghist := resp.ghist 15709c6f1ddSLingrui98 this.phist := resp.phist 15809c6f1ddSLingrui98 this.phNewBit := resp.pc(instOffsetBits) 15909c6f1ddSLingrui98 this 16009c6f1ddSLingrui98 } 16109c6f1ddSLingrui98} 16209c6f1ddSLingrui98 16309c6f1ddSLingrui98class Ftq_1R_SRAMEntry(implicit p: Parameters) extends XSBundle with HasBPUConst { 16409c6f1ddSLingrui98 val meta = UInt(MaxMetaLength.W) 16509c6f1ddSLingrui98} 16609c6f1ddSLingrui98 16709c6f1ddSLingrui98class Ftq_Pred_Info(implicit p: Parameters) extends XSBundle { 16809c6f1ddSLingrui98 val target = UInt(VAddrBits.W) 16909c6f1ddSLingrui98 val cfiIndex = ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)) 17009c6f1ddSLingrui98} 17109c6f1ddSLingrui98 17209c6f1ddSLingrui98class FtqEntry(implicit p: Parameters) extends XSBundle with HasBPUConst { 17309c6f1ddSLingrui98 val startAddr = UInt(VAddrBits.W) 17409c6f1ddSLingrui98 val fallThruAddr = UInt(VAddrBits.W) 17509c6f1ddSLingrui98 val isNextMask = Vec(PredictWidth, Bool()) 17609c6f1ddSLingrui98 17709c6f1ddSLingrui98 val meta = UInt(MaxMetaLength.W) 17809c6f1ddSLingrui98 17909c6f1ddSLingrui98 val rasSp = UInt(log2Ceil(RasSize).W) 18009c6f1ddSLingrui98 val rasEntry = new RASEntry 18109c6f1ddSLingrui98 val hist = new GlobalHistory 18209c6f1ddSLingrui98 val specCnt = Vec(numBr, UInt(10.W)) 18309c6f1ddSLingrui98 18409c6f1ddSLingrui98 val valids = Vec(PredictWidth, Bool()) 18509c6f1ddSLingrui98 val brMask = Vec(PredictWidth, Bool()) 18609c6f1ddSLingrui98 // isJalr, isCall, isRet 18709c6f1ddSLingrui98 val jmpInfo = ValidUndirectioned(Vec(3, Bool())) 18809c6f1ddSLingrui98 val jmpOffset = UInt(log2Ceil(PredictWidth).W) 18909c6f1ddSLingrui98 19009c6f1ddSLingrui98 val mispredVec = Vec(PredictWidth, Bool()) 19109c6f1ddSLingrui98 val cfiIndex = ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)) 19209c6f1ddSLingrui98 val target = UInt(VAddrBits.W) 19309c6f1ddSLingrui98} 19409c6f1ddSLingrui98 19509c6f1ddSLingrui98class FtqRead[T <: Data](private val gen: T)(implicit p: Parameters) extends XSBundle { 19609c6f1ddSLingrui98 val ptr = Output(new FtqPtr) 19709c6f1ddSLingrui98 val offset = Output(UInt(log2Ceil(PredictWidth).W)) 19809c6f1ddSLingrui98 val data = Input(gen) 19909c6f1ddSLingrui98 def apply(ptr: FtqPtr, offset: UInt) = { 20009c6f1ddSLingrui98 this.ptr := ptr 20109c6f1ddSLingrui98 this.offset := offset 20209c6f1ddSLingrui98 this.data 20309c6f1ddSLingrui98 } 20409c6f1ddSLingrui98 override def cloneType = (new FtqRead(gen)).asInstanceOf[this.type] 20509c6f1ddSLingrui98} 20609c6f1ddSLingrui98 20709c6f1ddSLingrui98 20809c6f1ddSLingrui98class FtqToBpuIO(implicit p: Parameters) extends XSBundle { 20909c6f1ddSLingrui98 val redirect = Valid(new BranchPredictionRedirect) 21009c6f1ddSLingrui98 val update = Valid(new BranchPredictionUpdate) 21109c6f1ddSLingrui98 val enq_ptr = Output(new FtqPtr) 21209c6f1ddSLingrui98} 21309c6f1ddSLingrui98 21409c6f1ddSLingrui98class FtqToIfuIO(implicit p: Parameters) extends XSBundle with HasCircularQueuePtrHelper { 21509c6f1ddSLingrui98 val req = Decoupled(new FetchRequestBundle) 21609c6f1ddSLingrui98 val redirect = Valid(new Redirect) 21709c6f1ddSLingrui98 val flushFromBpu = new Bundle { 21809c6f1ddSLingrui98 // when ifu pipeline is not stalled, 21909c6f1ddSLingrui98 // a packet from bpu s3 can reach f1 at most 22009c6f1ddSLingrui98 val s2 = Valid(new FtqPtr) 22109c6f1ddSLingrui98 val s3 = Valid(new FtqPtr) 22209c6f1ddSLingrui98 def shouldFlushBy(src: Valid[FtqPtr], idx_to_flush: FtqPtr) = { 22309c6f1ddSLingrui98 src.valid && !isAfter(src.bits, idx_to_flush) 22409c6f1ddSLingrui98 } 22509c6f1ddSLingrui98 def shouldFlushByStage2(idx: FtqPtr) = shouldFlushBy(s2, idx) 22609c6f1ddSLingrui98 def shouldFlushByStage3(idx: FtqPtr) = shouldFlushBy(s3, idx) 22709c6f1ddSLingrui98 } 22809c6f1ddSLingrui98} 22909c6f1ddSLingrui98 23009c6f1ddSLingrui98trait HasBackendRedirectInfo extends HasXSParameter { 23109c6f1ddSLingrui98 def numRedirect = exuParameters.JmpCnt + exuParameters.AluCnt + 1 23209c6f1ddSLingrui98 def isLoadReplay(r: Valid[Redirect]) = r.bits.flushItself() 23309c6f1ddSLingrui98} 23409c6f1ddSLingrui98 23509c6f1ddSLingrui98class FtqToCtrlIO(implicit p: Parameters) extends XSBundle with HasBackendRedirectInfo { 23609c6f1ddSLingrui98 val pc_reads = Vec(1 + numRedirect + 1 + 1, Flipped(new FtqRead(UInt(VAddrBits.W)))) 23709c6f1ddSLingrui98 val target_read = Flipped(new FtqRead(UInt(VAddrBits.W))) 23809c6f1ddSLingrui98 def getJumpPcRead = pc_reads.head 23909c6f1ddSLingrui98 def getRedirectPcRead = VecInit(pc_reads.tail.dropRight(2)) 24009c6f1ddSLingrui98 def getMemPredPcRead = pc_reads.init.last 241*9aca92b9SYinan Xu def getRobFlushPcRead = pc_reads.last 24209c6f1ddSLingrui98} 24309c6f1ddSLingrui98 24409c6f1ddSLingrui98 24509c6f1ddSLingrui98class FTBEntryGen(implicit p: Parameters) extends XSModule with HasBackendRedirectInfo with HasBPUParameter { 24609c6f1ddSLingrui98 val io = IO(new Bundle { 24709c6f1ddSLingrui98 val start_addr = Input(UInt(VAddrBits.W)) 24809c6f1ddSLingrui98 val old_entry = Input(new FTBEntry) 24909c6f1ddSLingrui98 val pd = Input(new Ftq_pd_Entry) 25009c6f1ddSLingrui98 val cfiIndex = Flipped(Valid(UInt(log2Ceil(PredictWidth).W))) 25109c6f1ddSLingrui98 val target = Input(UInt(VAddrBits.W)) 25209c6f1ddSLingrui98 val hit = Input(Bool()) 25309c6f1ddSLingrui98 val mispredict_vec = Input(Vec(PredictWidth, Bool())) 25409c6f1ddSLingrui98 25509c6f1ddSLingrui98 val new_entry = Output(new FTBEntry) 25609c6f1ddSLingrui98 val new_br_insert_pos = Output(Vec(numBr, Bool())) 25709c6f1ddSLingrui98 val taken_mask = Output(Vec(numBr, Bool())) 25809c6f1ddSLingrui98 val mispred_mask = Output(Vec(numBr+1, Bool())) 25909c6f1ddSLingrui98 26009c6f1ddSLingrui98 // for perf counters 26109c6f1ddSLingrui98 val is_init_entry = Output(Bool()) 26209c6f1ddSLingrui98 val is_old_entry = Output(Bool()) 26309c6f1ddSLingrui98 val is_new_br = Output(Bool()) 26409c6f1ddSLingrui98 val is_jalr_target_modified = Output(Bool()) 26509c6f1ddSLingrui98 val is_always_taken_modified = Output(Bool()) 26609c6f1ddSLingrui98 val is_br_full = Output(Bool()) 26709c6f1ddSLingrui98 }) 26809c6f1ddSLingrui98 26909c6f1ddSLingrui98 // no mispredictions detected at predecode 27009c6f1ddSLingrui98 val hit = io.hit 27109c6f1ddSLingrui98 val pd = io.pd 27209c6f1ddSLingrui98 27309c6f1ddSLingrui98 val init_entry = WireInit(0.U.asTypeOf(new FTBEntry)) 27409c6f1ddSLingrui98 27509c6f1ddSLingrui98 27609c6f1ddSLingrui98 val cfi_is_br = pd.brMask(io.cfiIndex.bits) && io.cfiIndex.valid 27709c6f1ddSLingrui98 val entry_has_jmp = pd.jmpInfo.valid 27809c6f1ddSLingrui98 val new_jmp_is_jal = entry_has_jmp && !pd.jmpInfo.bits(0) && io.cfiIndex.valid 27909c6f1ddSLingrui98 val new_jmp_is_jalr = entry_has_jmp && pd.jmpInfo.bits(0) && io.cfiIndex.valid 28009c6f1ddSLingrui98 val new_jmp_is_call = entry_has_jmp && pd.jmpInfo.bits(1) && io.cfiIndex.valid 28109c6f1ddSLingrui98 val new_jmp_is_ret = entry_has_jmp && pd.jmpInfo.bits(2) && io.cfiIndex.valid 28209c6f1ddSLingrui98 val last_jmp_rvi = entry_has_jmp && pd.jmpOffset === (PredictWidth-1).U && !pd.rvcMask.last 28309c6f1ddSLingrui98 val last_br_rvi = cfi_is_br && io.cfiIndex.bits === (PredictWidth-1).U && !pd.rvcMask.last 28409c6f1ddSLingrui98 28509c6f1ddSLingrui98 val cfi_is_jal = io.cfiIndex.bits === pd.jmpOffset && new_jmp_is_jal 28609c6f1ddSLingrui98 val cfi_is_jalr = io.cfiIndex.bits === pd.jmpOffset && new_jmp_is_jalr 28709c6f1ddSLingrui98 28809c6f1ddSLingrui98 def carryPos = log2Ceil(PredictWidth)+instOffsetBits+1 28909c6f1ddSLingrui98 def getLower(pc: UInt) = pc(carryPos-1, instOffsetBits) 29009c6f1ddSLingrui98 // if not hit, establish a new entry 29109c6f1ddSLingrui98 init_entry.valid := true.B 29209c6f1ddSLingrui98 // tag is left for ftb to assign 29309c6f1ddSLingrui98 init_entry.brValids(0) := cfi_is_br 29409c6f1ddSLingrui98 init_entry.brOffset(0) := io.cfiIndex.bits 29509c6f1ddSLingrui98 init_entry.setByBrTarget(0, io.start_addr, io.target) 29609c6f1ddSLingrui98 init_entry.always_taken(0) := cfi_is_br // set to always taken on init 29709c6f1ddSLingrui98 init_entry.always_taken(1) := false.B 29809c6f1ddSLingrui98 init_entry.jmpOffset := pd.jmpOffset 29909c6f1ddSLingrui98 init_entry.jmpValid := new_jmp_is_jal || new_jmp_is_jalr 30009c6f1ddSLingrui98 init_entry.setByJmpTarget(io.start_addr, Mux(cfi_is_jalr, io.target, pd.jalTarget)) 30109c6f1ddSLingrui98 val jmpPft = getLower(io.start_addr) +& pd.jmpOffset +& Mux(pd.rvcMask(pd.jmpOffset), 1.U, 2.U) 30209c6f1ddSLingrui98 init_entry.pftAddr := Mux(entry_has_jmp, jmpPft, getLower(io.start_addr) + ((FetchWidth*4)>>instOffsetBits).U + Mux(last_br_rvi, 1.U, 0.U)) 30365fddcf0Szoujr init_entry.carry := Mux(entry_has_jmp, jmpPft(carryPos-instOffsetBits), io.start_addr(carryPos-1) || (io.start_addr(carryPos-2, instOffsetBits).andR && last_br_rvi)) 30409c6f1ddSLingrui98 init_entry.isJalr := new_jmp_is_jalr 30509c6f1ddSLingrui98 init_entry.isCall := new_jmp_is_call 30609c6f1ddSLingrui98 init_entry.isRet := new_jmp_is_ret 30709c6f1ddSLingrui98 init_entry.last_is_rvc := Mux(entry_has_jmp, pd.rvcMask(pd.jmpOffset), pd.rvcMask.last) 30809c6f1ddSLingrui98 30909c6f1ddSLingrui98 init_entry.oversize := last_br_rvi || last_jmp_rvi 31009c6f1ddSLingrui98 31109c6f1ddSLingrui98 // if hit, check whether a new cfi(only br is possible) is detected 31209c6f1ddSLingrui98 val oe = io.old_entry 31309c6f1ddSLingrui98 val br_recorded_vec = VecInit((oe.brValids zip oe.brOffset).map { 31409c6f1ddSLingrui98 case (v, off) => v && (off === io.cfiIndex.bits) 31509c6f1ddSLingrui98 }) 31609c6f1ddSLingrui98 val br_recorded = br_recorded_vec.asUInt.orR 31709c6f1ddSLingrui98 val is_new_br = cfi_is_br && !br_recorded 31809c6f1ddSLingrui98 val br_full = oe.brValids.asUInt.andR // all slots have brs 31909c6f1ddSLingrui98 val new_br_offset = io.cfiIndex.bits 32009c6f1ddSLingrui98 // vec(i) means new br will be inserted BEFORE old br(i) 32109c6f1ddSLingrui98 val new_br_insert_onehot = VecInit((0 until numBr).map{ 32209c6f1ddSLingrui98 i => i match { 32309c6f1ddSLingrui98 case 0 => !oe.brValids(0) || new_br_offset < oe.brOffset(0) 32409c6f1ddSLingrui98 case idx => oe.brValids(idx-1) && new_br_offset > oe.brOffset(idx-1) && 32509c6f1ddSLingrui98 (!oe.brValids(idx) || new_br_offset < oe.brOffset(idx)) 32609c6f1ddSLingrui98 } 32709c6f1ddSLingrui98 }) 32809c6f1ddSLingrui98 32909c6f1ddSLingrui98 val old_entry_modified = WireInit(io.old_entry) 33009c6f1ddSLingrui98 val (new_br_lower, new_br_tar_stat) = old_entry_modified.getBrLowerStatByTarget(io.start_addr, io.target) 33109c6f1ddSLingrui98 for (i <- 0 until numBr) { 33209c6f1ddSLingrui98 old_entry_modified.brOffset(i) := Mux(new_br_insert_onehot(i), new_br_offset, 33309c6f1ddSLingrui98 Mux(oe.brOffset(i) < new_br_offset, oe.brOffset(i), 33409c6f1ddSLingrui98 (if (i != 0) oe.brOffset(i-1) else oe.brOffset(i)))) 33509c6f1ddSLingrui98 old_entry_modified.brLowers(i) := Mux(new_br_insert_onehot(i), new_br_lower, 33609c6f1ddSLingrui98 Mux(oe.brOffset(i) < new_br_offset, oe.brLowers(i), 33709c6f1ddSLingrui98 (if (i != 0) oe.brLowers(i-1) else oe.brLowers(i)))) 33809c6f1ddSLingrui98 old_entry_modified.brTarStats(i) := Mux(new_br_insert_onehot(i), new_br_tar_stat, 33909c6f1ddSLingrui98 Mux(oe.brOffset(i) < new_br_offset, oe.brTarStats(i), 34009c6f1ddSLingrui98 (if (i != 0) oe.brTarStats(i-1) else oe.brTarStats(i)))) 34109c6f1ddSLingrui98 old_entry_modified.always_taken(i) := Mux(new_br_insert_onehot(i), true.B, 34209c6f1ddSLingrui98 Mux(oe.brOffset(i) < new_br_offset, false.B, 34309c6f1ddSLingrui98 (if (i != 0) oe.always_taken(i-1) else oe.always_taken(i)))) 34409c6f1ddSLingrui98 } 34509c6f1ddSLingrui98 old_entry_modified.brValids := VecInit((oe.brValids zip new_br_insert_onehot).map{case (v1, v2) => v1 || v2}) 34609c6f1ddSLingrui98 34709c6f1ddSLingrui98 // in this case, pft_addr should be the addrs of the last br in packet 34809c6f1ddSLingrui98 val pft_need_to_change = is_new_br && br_full 34909c6f1ddSLingrui98 // it should either be the given last br or the new br 35009c6f1ddSLingrui98 when (pft_need_to_change) { 35109c6f1ddSLingrui98 val new_pft_offset = Mux(new_br_insert_onehot.asUInt.orR, oe.brOffset.last, new_br_offset) 35209c6f1ddSLingrui98 old_entry_modified.pftAddr := getLower(io.start_addr) + new_pft_offset 35309c6f1ddSLingrui98 old_entry_modified.last_is_rvc := pd.rvcMask(new_pft_offset - 1.U) // TODO: fix this 35409c6f1ddSLingrui98 old_entry_modified.carry := (getLower(io.start_addr) +& new_pft_offset).head(1).asBool 35509c6f1ddSLingrui98 old_entry_modified.oversize := false.B 35609c6f1ddSLingrui98 old_entry_modified.jmpValid := false.B 35709c6f1ddSLingrui98 old_entry_modified.isCall := false.B 35809c6f1ddSLingrui98 old_entry_modified.isRet := false.B 35909c6f1ddSLingrui98 } 36009c6f1ddSLingrui98 36109c6f1ddSLingrui98 val old_entry_jmp_target_modified = WireInit(oe) 3623bcae573SLingrui98 val old_target = oe.getJmpTarget(io.start_addr) 3633bcae573SLingrui98 val jalr_target_modified = cfi_is_jalr && (old_target =/= io.target) // TODO: pass full jalr target 3643bcae573SLingrui98 when (jalr_target_modified) { 36509c6f1ddSLingrui98 old_entry_jmp_target_modified.setByJmpTarget(io.start_addr, io.target) 36609c6f1ddSLingrui98 old_entry_jmp_target_modified.always_taken := 0.U.asTypeOf(Vec(numBr, Bool())) 36709c6f1ddSLingrui98 } 36809c6f1ddSLingrui98 36909c6f1ddSLingrui98 val old_entry_always_taken = WireInit(oe) 37009c6f1ddSLingrui98 val always_taken_modified_vec = Wire(Vec(numBr, Bool())) // whether modified or not 37109c6f1ddSLingrui98 for (i <- 0 until numBr) { 37209c6f1ddSLingrui98 old_entry_always_taken.always_taken(i) := 37309c6f1ddSLingrui98 oe.always_taken(i) && io.cfiIndex.valid && oe.brValids(i) && io.cfiIndex.bits === oe.brOffset(i) 37409c6f1ddSLingrui98 always_taken_modified_vec(i) := oe.always_taken(i) && !(io.cfiIndex.valid && oe.brValids(i) && io.cfiIndex.bits === oe.brOffset(i)) 37509c6f1ddSLingrui98 } 37609c6f1ddSLingrui98 val always_taken_modified = always_taken_modified_vec.reduce(_||_) 37709c6f1ddSLingrui98 37809c6f1ddSLingrui98 37909c6f1ddSLingrui98 38009c6f1ddSLingrui98 val derived_from_old_entry = 38109c6f1ddSLingrui98 Mux(is_new_br, old_entry_modified, 3823bcae573SLingrui98 Mux(jalr_target_modified, old_entry_jmp_target_modified, old_entry_always_taken)) 38309c6f1ddSLingrui98 38409c6f1ddSLingrui98 38509c6f1ddSLingrui98 io.new_entry := Mux(!hit, init_entry, derived_from_old_entry) 38609c6f1ddSLingrui98 38709c6f1ddSLingrui98 io.new_br_insert_pos := new_br_insert_onehot 38809c6f1ddSLingrui98 io.taken_mask := VecInit((io.new_entry.brOffset zip io.new_entry.brValids).map{ 38909c6f1ddSLingrui98 case (off, v) => io.cfiIndex.bits === off && io.cfiIndex.valid && v 39009c6f1ddSLingrui98 }) 39109c6f1ddSLingrui98 for (i <- 0 until numBr) { 39209c6f1ddSLingrui98 io.mispred_mask(i) := io.new_entry.brValids(i) && io.mispredict_vec(io.new_entry.brOffset(i)) 39309c6f1ddSLingrui98 } 39409c6f1ddSLingrui98 io.mispred_mask.last := io.new_entry.jmpValid && io.mispredict_vec(pd.jmpOffset) 39509c6f1ddSLingrui98 39609c6f1ddSLingrui98 // for perf counters 39709c6f1ddSLingrui98 io.is_init_entry := !hit 3983bcae573SLingrui98 io.is_old_entry := hit && !is_new_br && !jalr_target_modified && !always_taken_modified 39909c6f1ddSLingrui98 io.is_new_br := hit && is_new_br 4003bcae573SLingrui98 io.is_jalr_target_modified := hit && jalr_target_modified 40109c6f1ddSLingrui98 io.is_always_taken_modified := hit && always_taken_modified 40209c6f1ddSLingrui98 io.is_br_full := hit && is_new_br && br_full 40309c6f1ddSLingrui98} 40409c6f1ddSLingrui98 40509c6f1ddSLingrui98class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper 40609c6f1ddSLingrui98 with HasBackendRedirectInfo with BPUUtils with HasBPUConst { 40709c6f1ddSLingrui98 val io = IO(new Bundle { 40809c6f1ddSLingrui98 val fromBpu = Flipped(new BpuToFtqIO) 40909c6f1ddSLingrui98 val fromIfu = Flipped(new IfuToFtqIO) 41009c6f1ddSLingrui98 val fromBackend = Flipped(new CtrlToFtqIO) 41109c6f1ddSLingrui98 41209c6f1ddSLingrui98 val toBpu = new FtqToBpuIO 41309c6f1ddSLingrui98 val toIfu = new FtqToIfuIO 41409c6f1ddSLingrui98 val toBackend = new FtqToCtrlIO 41509c6f1ddSLingrui98 41609c6f1ddSLingrui98 val bpuInfo = new Bundle { 41709c6f1ddSLingrui98 val bpRight = Output(UInt(XLEN.W)) 41809c6f1ddSLingrui98 val bpWrong = Output(UInt(XLEN.W)) 41909c6f1ddSLingrui98 } 42009c6f1ddSLingrui98 }) 42109c6f1ddSLingrui98 io.bpuInfo := DontCare 42209c6f1ddSLingrui98 423*9aca92b9SYinan Xu val robFlush = io.fromBackend.robFlush 42409c6f1ddSLingrui98 val stage2Redirect = io.fromBackend.stage2Redirect 42509c6f1ddSLingrui98 val stage3Redirect = io.fromBackend.stage3Redirect 42609c6f1ddSLingrui98 427*9aca92b9SYinan Xu val stage2Flush = stage2Redirect.valid || robFlush.valid 42809c6f1ddSLingrui98 val backendFlush = stage2Flush || RegNext(stage2Flush) 42909c6f1ddSLingrui98 val ifuFlush = Wire(Bool()) 43009c6f1ddSLingrui98 43109c6f1ddSLingrui98 val flush = stage2Flush || RegNext(stage2Flush) 43209c6f1ddSLingrui98 43309c6f1ddSLingrui98 val allowBpuIn, allowToIfu = WireInit(false.B) 43409c6f1ddSLingrui98 val flushToIfu = !allowToIfu 435*9aca92b9SYinan Xu allowBpuIn := !ifuFlush && !robFlush.valid && !stage2Redirect.valid && !stage3Redirect.valid 436*9aca92b9SYinan Xu allowToIfu := !ifuFlush && !robFlush.valid && !stage2Redirect.valid && !stage3Redirect.valid 43709c6f1ddSLingrui98 43809c6f1ddSLingrui98 val bpuPtr, ifuPtr, ifuWbPtr, commPtr = RegInit(FtqPtr(false.B, 0.U)) 43909c6f1ddSLingrui98 val validEntries = distanceBetween(bpuPtr, commPtr) 44009c6f1ddSLingrui98 44109c6f1ddSLingrui98 // ********************************************************************** 44209c6f1ddSLingrui98 // **************************** enq from bpu **************************** 44309c6f1ddSLingrui98 // ********************************************************************** 44409c6f1ddSLingrui98 val new_entry_ready = validEntries < FtqSize.U 44509c6f1ddSLingrui98 io.fromBpu.resp.ready := new_entry_ready 44609c6f1ddSLingrui98 44709c6f1ddSLingrui98 val bpu_s2_resp = io.fromBpu.resp.bits.s2 44809c6f1ddSLingrui98 val bpu_s3_resp = io.fromBpu.resp.bits.s3 44909c6f1ddSLingrui98 val bpu_s2_redirect = bpu_s2_resp.valid && bpu_s2_resp.hasRedirect 45009c6f1ddSLingrui98 val bpu_s3_redirect = bpu_s3_resp.valid && bpu_s3_resp.hasRedirect 45109c6f1ddSLingrui98 45209c6f1ddSLingrui98 io.toBpu.enq_ptr := bpuPtr 45309c6f1ddSLingrui98 val enq_fire = io.fromBpu.resp.fire() && allowBpuIn // from bpu s1 45409c6f1ddSLingrui98 val bpu_in_fire = (io.fromBpu.resp.fire() || bpu_s2_redirect || bpu_s3_redirect) && allowBpuIn 45509c6f1ddSLingrui98 45609c6f1ddSLingrui98 val bpu_in_resp = WireInit(io.fromBpu.resp.bits.selectedResp) 45709c6f1ddSLingrui98 val bpu_in_stage = WireInit(io.fromBpu.resp.bits.selectedRespIdx) 45809c6f1ddSLingrui98 val bpu_in_resp_ptr = Mux(bpu_in_stage === BP_S1, bpuPtr, bpu_in_resp.ftq_idx) 45909c6f1ddSLingrui98 val bpu_in_resp_idx = bpu_in_resp_ptr.value 46009c6f1ddSLingrui98 461*9aca92b9SYinan Xu // read ports: jumpPc + redirects + loadPred + robFlush + ifuReq1 + ifuReq2 + commitUpdate 46209c6f1ddSLingrui98 val ftq_pc_mem = Module(new SyncDataModuleTemplate(new Ftq_RF_Components, FtqSize, 1+numRedirect+2+1+1+1, 1)) 46309c6f1ddSLingrui98 // resp from uBTB 46409c6f1ddSLingrui98 ftq_pc_mem.io.wen(0) := bpu_in_fire 46509c6f1ddSLingrui98 ftq_pc_mem.io.waddr(0) := bpu_in_resp_idx 46609c6f1ddSLingrui98 ftq_pc_mem.io.wdata(0).fromBranchPrediction(bpu_in_resp) 46709c6f1ddSLingrui98 46809c6f1ddSLingrui98 // ifuRedirect + backendRedirect + commit 46909c6f1ddSLingrui98 val ftq_redirect_sram = Module(new FtqNRSRAM(new Ftq_Redirect_SRAMEntry, 1+1+1)) 47009c6f1ddSLingrui98 // these info is intended to enq at the last stage of bpu 47109c6f1ddSLingrui98 ftq_redirect_sram.io.wen := io.fromBpu.resp.bits.lastStage.valid 47209c6f1ddSLingrui98 ftq_redirect_sram.io.waddr := io.fromBpu.resp.bits.lastStage.ftq_idx.value 47309c6f1ddSLingrui98 ftq_redirect_sram.io.wdata.fromBranchPrediction(io.fromBpu.resp.bits.lastStage) 47409c6f1ddSLingrui98 47509c6f1ddSLingrui98 val ftq_meta_1r_sram = Module(new FtqNRSRAM(new Ftq_1R_SRAMEntry, 1)) 47609c6f1ddSLingrui98 // these info is intended to enq at the last stage of bpu 47709c6f1ddSLingrui98 ftq_meta_1r_sram.io.wen := io.fromBpu.resp.bits.lastStage.valid 47809c6f1ddSLingrui98 ftq_meta_1r_sram.io.waddr := io.fromBpu.resp.bits.lastStage.ftq_idx.value 47909c6f1ddSLingrui98 ftq_meta_1r_sram.io.wdata.meta := io.fromBpu.resp.bits.meta 48009c6f1ddSLingrui98 // ifuRedirect + backendRedirect + commit 48109c6f1ddSLingrui98 val ftb_entry_mem = Module(new SyncDataModuleTemplate(new FTBEntry, FtqSize, 1+1+1, 1)) 48209c6f1ddSLingrui98 ftb_entry_mem.io.wen(0) := io.fromBpu.resp.bits.lastStage.valid 48309c6f1ddSLingrui98 ftb_entry_mem.io.waddr(0) := io.fromBpu.resp.bits.lastStage.ftq_idx.value 48409c6f1ddSLingrui98 ftb_entry_mem.io.wdata(0) := io.fromBpu.resp.bits.lastStage.ftb_entry 48509c6f1ddSLingrui98 48609c6f1ddSLingrui98 48709c6f1ddSLingrui98 // multi-write 48809c6f1ddSLingrui98 val update_target = Reg(Vec(FtqSize, UInt(VAddrBits.W))) 48909c6f1ddSLingrui98 val cfiIndex_vec = Reg(Vec(FtqSize, ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))) 49009c6f1ddSLingrui98 val mispredict_vec = Reg(Vec(FtqSize, Vec(PredictWidth, Bool()))) 49109c6f1ddSLingrui98 val pred_stage = Reg(Vec(FtqSize, UInt(2.W))) 49209c6f1ddSLingrui98 49309c6f1ddSLingrui98 val c_invalid :: c_valid :: c_commited :: Nil = Enum(3) 49409c6f1ddSLingrui98 val commitStateQueue = RegInit(VecInit(Seq.fill(FtqSize) { 49509c6f1ddSLingrui98 VecInit(Seq.fill(PredictWidth)(c_invalid)) 49609c6f1ddSLingrui98 })) 49709c6f1ddSLingrui98 49809c6f1ddSLingrui98 val f_to_send :: f_sent :: Nil = Enum(2) 49909c6f1ddSLingrui98 val entry_fetch_status = RegInit(VecInit(Seq.fill(FtqSize)(f_sent))) 50009c6f1ddSLingrui98 50109c6f1ddSLingrui98 val h_not_hit :: h_false_hit :: h_hit :: Nil = Enum(3) 50209c6f1ddSLingrui98 val entry_hit_status = RegInit(VecInit(Seq.fill(FtqSize)(h_not_hit))) 50309c6f1ddSLingrui98 50409c6f1ddSLingrui98 50509c6f1ddSLingrui98 when (bpu_in_fire) { 50609c6f1ddSLingrui98 entry_fetch_status(bpu_in_resp_idx) := f_to_send 50709c6f1ddSLingrui98 commitStateQueue(bpu_in_resp_idx) := VecInit(Seq.fill(PredictWidth)(c_invalid)) 50809c6f1ddSLingrui98 cfiIndex_vec(bpu_in_resp_idx) := bpu_in_resp.genCfiIndex 50909c6f1ddSLingrui98 mispredict_vec(bpu_in_resp_idx) := WireInit(VecInit(Seq.fill(PredictWidth)(false.B))) 51009c6f1ddSLingrui98 update_target(bpu_in_resp_idx) := bpu_in_resp.target 51109c6f1ddSLingrui98 pred_stage(bpu_in_resp_idx) := bpu_in_stage 51209c6f1ddSLingrui98 } 51309c6f1ddSLingrui98 51409c6f1ddSLingrui98 bpuPtr := bpuPtr + enq_fire 51509c6f1ddSLingrui98 ifuPtr := ifuPtr + io.toIfu.req.fire 51609c6f1ddSLingrui98 51709c6f1ddSLingrui98 // only use ftb result to assign hit status 51809c6f1ddSLingrui98 when (bpu_s2_resp.valid) { 51909c6f1ddSLingrui98 entry_hit_status(bpu_s2_resp.ftq_idx.value) := Mux(bpu_s2_resp.preds.hit, h_hit, h_not_hit) 52009c6f1ddSLingrui98 } 52109c6f1ddSLingrui98 52209c6f1ddSLingrui98 52309c6f1ddSLingrui98 io.toIfu.flushFromBpu.s2.valid := bpu_s2_resp.valid && bpu_s2_resp.hasRedirect 52409c6f1ddSLingrui98 io.toIfu.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx 52509c6f1ddSLingrui98 when (bpu_s2_resp.valid && bpu_s2_resp.hasRedirect) { 52609c6f1ddSLingrui98 bpuPtr := bpu_s2_resp.ftq_idx + 1.U 52709c6f1ddSLingrui98 // only when ifuPtr runs ahead of bpu s2 resp should we recover it 52809c6f1ddSLingrui98 when (!isBefore(ifuPtr, bpu_s2_resp.ftq_idx)) { 52909c6f1ddSLingrui98 ifuPtr := bpu_s2_resp.ftq_idx 53009c6f1ddSLingrui98 } 53109c6f1ddSLingrui98 } 53209c6f1ddSLingrui98 53309c6f1ddSLingrui98 io.toIfu.flushFromBpu.s3.valid := bpu_s3_resp.valid && bpu_s3_resp.hasRedirect 53409c6f1ddSLingrui98 io.toIfu.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx 53509c6f1ddSLingrui98 when (bpu_s3_resp.valid && bpu_s3_resp.hasRedirect) { 53609c6f1ddSLingrui98 bpuPtr := bpu_s3_resp.ftq_idx + 1.U 53709c6f1ddSLingrui98 // only when ifuPtr runs ahead of bpu s2 resp should we recover it 53809c6f1ddSLingrui98 when (!isBefore(ifuPtr, bpu_s3_resp.ftq_idx)) { 53909c6f1ddSLingrui98 ifuPtr := bpu_s3_resp.ftq_idx 54009c6f1ddSLingrui98 } 54109c6f1ddSLingrui98 XSError(true.B, "\ns3_redirect mechanism not implemented!\n") 54209c6f1ddSLingrui98 } 54309c6f1ddSLingrui98 54409c6f1ddSLingrui98 XSError(isBefore(bpuPtr, ifuPtr) && !isFull(bpuPtr, ifuPtr), "\nifuPtr is before bpuPtr!\n") 54509c6f1ddSLingrui98 54609c6f1ddSLingrui98 // **************************************************************** 54709c6f1ddSLingrui98 // **************************** to ifu **************************** 54809c6f1ddSLingrui98 // **************************************************************** 54909c6f1ddSLingrui98 val bpu_in_bypass_buf = RegEnable(ftq_pc_mem.io.wdata(0), enable=bpu_in_fire) 55009c6f1ddSLingrui98 val bpu_in_bypass_ptr = RegNext(bpu_in_resp_ptr) 55109c6f1ddSLingrui98 val last_cycle_bpu_in = RegNext(bpu_in_fire) 55209c6f1ddSLingrui98 val last_cycle_to_ifu_fire = RegNext(io.toIfu.req.fire) 55309c6f1ddSLingrui98 55409c6f1ddSLingrui98 // read pc and target 55509c6f1ddSLingrui98 ftq_pc_mem.io.raddr.init.init.last := ifuPtr.value 55609c6f1ddSLingrui98 ftq_pc_mem.io.raddr.init.last := (ifuPtr+1.U).value 55709c6f1ddSLingrui98 55809c6f1ddSLingrui98 val toIfuReq = Wire(chiselTypeOf(io.toIfu.req)) 55909c6f1ddSLingrui98 56009c6f1ddSLingrui98 toIfuReq.valid := allowToIfu && entry_fetch_status(ifuPtr.value) === f_to_send && ifuPtr =/= bpuPtr 56109c6f1ddSLingrui98 toIfuReq.bits.ftqIdx := ifuPtr 56209c6f1ddSLingrui98 toIfuReq.bits.target := update_target(ifuPtr.value) 56309c6f1ddSLingrui98 toIfuReq.bits.ftqOffset := cfiIndex_vec(ifuPtr.value) 56409c6f1ddSLingrui98 toIfuReq.bits.fallThruError := false.B 56509c6f1ddSLingrui98 56609c6f1ddSLingrui98 when (last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr) { 56709c6f1ddSLingrui98 toIfuReq.bits.fromFtqPcBundle(bpu_in_bypass_buf) 56809c6f1ddSLingrui98 }.elsewhen (last_cycle_to_ifu_fire) { 56909c6f1ddSLingrui98 toIfuReq.bits.fromFtqPcBundle(ftq_pc_mem.io.rdata.init.last) 57009c6f1ddSLingrui98 }.otherwise { 57109c6f1ddSLingrui98 toIfuReq.bits.fromFtqPcBundle(ftq_pc_mem.io.rdata.init.init.last) 57209c6f1ddSLingrui98 } 57309c6f1ddSLingrui98 57409c6f1ddSLingrui98 io.toIfu.req <> toIfuReq 57509c6f1ddSLingrui98 57609c6f1ddSLingrui98 // when fall through is smaller in value than start address, there must be a false hit 57709c6f1ddSLingrui98 when (toIfuReq.bits.fallThroughError() && entry_hit_status(ifuPtr.value) === h_hit) { 57809c6f1ddSLingrui98 when (io.toIfu.req.fire && 57909c6f1ddSLingrui98 !(bpu_s2_redirect && bpu_s2_resp.ftq_idx === ifuPtr) && 58009c6f1ddSLingrui98 !(bpu_s3_redirect && bpu_s3_resp.ftq_idx === ifuPtr) 58109c6f1ddSLingrui98 ) { 58209c6f1ddSLingrui98 entry_hit_status(ifuPtr.value) := h_false_hit 58365fddcf0Szoujr XSDebug(true.B, "FTB false hit by fallThroughError, startAddr: %x, fallTHru: %x\n", toIfuReq.bits.startAddr, toIfuReq.bits.fallThruAddr) 58409c6f1ddSLingrui98 } 58509c6f1ddSLingrui98 io.toIfu.req.bits.fallThruAddr := toIfuReq.bits.startAddr + (FetchWidth*4).U 58609c6f1ddSLingrui98 io.toIfu.req.bits.fallThruError := true.B 58709c6f1ddSLingrui98 XSDebug(true.B, "fallThruError! start:%x, fallThru:%x\n", toIfuReq.bits.startAddr, toIfuReq.bits.fallThruAddr) 58809c6f1ddSLingrui98 } 58909c6f1ddSLingrui98 59009c6f1ddSLingrui98 val ifu_req_should_be_flushed = 59109c6f1ddSLingrui98 io.toIfu.flushFromBpu.shouldFlushByStage2(toIfuReq.bits.ftqIdx) || 59209c6f1ddSLingrui98 io.toIfu.flushFromBpu.shouldFlushByStage3(toIfuReq.bits.ftqIdx) 59309c6f1ddSLingrui98 59409c6f1ddSLingrui98 when (io.toIfu.req.fire && !ifu_req_should_be_flushed) { 59509c6f1ddSLingrui98 entry_fetch_status(ifuPtr.value) := f_sent 59609c6f1ddSLingrui98 } 59709c6f1ddSLingrui98 59809c6f1ddSLingrui98 59909c6f1ddSLingrui98 // ********************************************************************* 60009c6f1ddSLingrui98 // **************************** wb from ifu **************************** 60109c6f1ddSLingrui98 // ********************************************************************* 60209c6f1ddSLingrui98 val pdWb = io.fromIfu.pdWb 60309c6f1ddSLingrui98 val pds = pdWb.bits.pd 60409c6f1ddSLingrui98 val ifu_wb_valid = pdWb.valid 60509c6f1ddSLingrui98 val ifu_wb_idx = pdWb.bits.ftqIdx.value 60609c6f1ddSLingrui98 // read ports: commit update 60709c6f1ddSLingrui98 val ftq_pd_mem = Module(new SyncDataModuleTemplate(new Ftq_pd_Entry, FtqSize, 1, 1)) 60809c6f1ddSLingrui98 ftq_pd_mem.io.wen(0) := ifu_wb_valid 60909c6f1ddSLingrui98 ftq_pd_mem.io.waddr(0) := pdWb.bits.ftqIdx.value 61009c6f1ddSLingrui98 ftq_pd_mem.io.wdata(0).fromPdWb(pdWb.bits) 61109c6f1ddSLingrui98 61209c6f1ddSLingrui98 val hit_pd_valid = entry_hit_status(ifu_wb_idx) === h_hit && ifu_wb_valid 61309c6f1ddSLingrui98 val hit_pd_mispred = hit_pd_valid && pdWb.bits.misOffset.valid 61409c6f1ddSLingrui98 val hit_pd_mispred_reg = RegNext(hit_pd_mispred, init=false.B) 61509c6f1ddSLingrui98 val pd_reg = RegEnable(pds, enable = pdWb.valid) 61609c6f1ddSLingrui98 val start_pc_reg = RegEnable(pdWb.bits.pc(0), enable = pdWb.valid) 61709c6f1ddSLingrui98 val wb_idx_reg = RegEnable(ifu_wb_idx, enable = pdWb.valid) 61809c6f1ddSLingrui98 61909c6f1ddSLingrui98 when (ifu_wb_valid) { 62009c6f1ddSLingrui98 val comm_stq_wen = VecInit(pds.map(_.valid).zip(pdWb.bits.instrRange).map{ 62109c6f1ddSLingrui98 case (v, inRange) => v && inRange 62209c6f1ddSLingrui98 }) 62309c6f1ddSLingrui98 (commitStateQueue(ifu_wb_idx) zip comm_stq_wen).map{ 62409c6f1ddSLingrui98 case (qe, v) => when (v) { qe := c_valid } 62509c6f1ddSLingrui98 } 62609c6f1ddSLingrui98 } 62709c6f1ddSLingrui98 62809c6f1ddSLingrui98 ifuWbPtr := ifuWbPtr + ifu_wb_valid 62909c6f1ddSLingrui98 63009c6f1ddSLingrui98 ftb_entry_mem.io.raddr.head := ifu_wb_idx 63109c6f1ddSLingrui98 val has_false_hit = WireInit(false.B) 63209c6f1ddSLingrui98 when (RegNext(hit_pd_valid)) { 63309c6f1ddSLingrui98 // check for false hit 63409c6f1ddSLingrui98 val pred_ftb_entry = ftb_entry_mem.io.rdata.head 63509c6f1ddSLingrui98 // we check cfis that bpu predicted 63609c6f1ddSLingrui98 val br_false_hit = (pred_ftb_entry.brValids zip pred_ftb_entry.brOffset).map{ 63709c6f1ddSLingrui98 case (v, offset) => v && !(pd_reg(offset).valid && pd_reg(offset).isBr) 63809c6f1ddSLingrui98 }.reduce(_||_) 63909c6f1ddSLingrui98 64009c6f1ddSLingrui98 val jmpOffset = pred_ftb_entry.jmpOffset 64109c6f1ddSLingrui98 val jmp_pd = pd_reg(jmpOffset) 64209c6f1ddSLingrui98 val jal_false_hit = pred_ftb_entry.jmpValid && 64309c6f1ddSLingrui98 ((pred_ftb_entry.isJal && !(jmp_pd.valid && jmp_pd.isJal)) || 64409c6f1ddSLingrui98 (pred_ftb_entry.isJalr && !(jmp_pd.valid && jmp_pd.isJalr)) || 64509c6f1ddSLingrui98 (pred_ftb_entry.isCall && !(jmp_pd.valid && jmp_pd.isCall)) || 64609c6f1ddSLingrui98 (pred_ftb_entry.isRet && !(jmp_pd.valid && jmp_pd.isRet)) 64709c6f1ddSLingrui98 ) 64809c6f1ddSLingrui98 64909c6f1ddSLingrui98 has_false_hit := br_false_hit || jal_false_hit || hit_pd_mispred_reg 65065fddcf0Szoujr XSDebug(has_false_hit, "FTB false hit by br or jal or hit_pd, startAddr: %x\n", pdWb.bits.pc(0)) 65165fddcf0Szoujr 65265fddcf0Szoujr // assert(!has_false_hit) 65309c6f1ddSLingrui98 } 65409c6f1ddSLingrui98 65509c6f1ddSLingrui98 when (has_false_hit) { 65609c6f1ddSLingrui98 entry_hit_status(wb_idx_reg) := h_false_hit 65709c6f1ddSLingrui98 } 65809c6f1ddSLingrui98 65909c6f1ddSLingrui98 66009c6f1ddSLingrui98 // ********************************************************************** 66109c6f1ddSLingrui98 // **************************** backend read **************************** 66209c6f1ddSLingrui98 // ********************************************************************** 66309c6f1ddSLingrui98 66409c6f1ddSLingrui98 // pc reads 66509c6f1ddSLingrui98 for ((req, i) <- io.toBackend.pc_reads.zipWithIndex) { 66609c6f1ddSLingrui98 ftq_pc_mem.io.raddr(i) := req.ptr.value 66709c6f1ddSLingrui98 req.data := ftq_pc_mem.io.rdata(i).getPc(RegNext(req.offset)) 66809c6f1ddSLingrui98 } 66909c6f1ddSLingrui98 // target read 67009c6f1ddSLingrui98 io.toBackend.target_read.data := RegNext(update_target(io.toBackend.target_read.ptr.value)) 67109c6f1ddSLingrui98 67209c6f1ddSLingrui98 // ******************************************************************************* 67309c6f1ddSLingrui98 // **************************** redirect from backend **************************** 67409c6f1ddSLingrui98 // ******************************************************************************* 67509c6f1ddSLingrui98 67609c6f1ddSLingrui98 // redirect read cfiInfo, couples to redirectGen s2 67709c6f1ddSLingrui98 ftq_redirect_sram.io.ren.init.last := io.fromBackend.stage2Redirect.valid 67809c6f1ddSLingrui98 ftq_redirect_sram.io.raddr.init.last := io.fromBackend.stage2Redirect.bits.ftqIdx.value 67909c6f1ddSLingrui98 68009c6f1ddSLingrui98 ftb_entry_mem.io.raddr.init.last := io.fromBackend.stage2Redirect.bits.ftqIdx.value 68109c6f1ddSLingrui98 68209c6f1ddSLingrui98 val stage3CfiInfo = ftq_redirect_sram.io.rdata.init.last 68309c6f1ddSLingrui98 val fromBackendRedirect = WireInit(io.fromBackend.stage3Redirect) 68409c6f1ddSLingrui98 val backendRedirectCfi = fromBackendRedirect.bits.cfiUpdate 68509c6f1ddSLingrui98 backendRedirectCfi.fromFtqRedirectSram(stage3CfiInfo) 68609c6f1ddSLingrui98 68709c6f1ddSLingrui98 val r_ftb_entry = ftb_entry_mem.io.rdata.init.last 68809c6f1ddSLingrui98 val r_ftqOffset = fromBackendRedirect.bits.ftqOffset 68909c6f1ddSLingrui98 69009c6f1ddSLingrui98 when (entry_hit_status(fromBackendRedirect.bits.ftqIdx.value) === h_hit) { 69109c6f1ddSLingrui98 backendRedirectCfi.shift := PopCount(r_ftb_entry.getBrMaskByOffset(r_ftqOffset)) +& 69209c6f1ddSLingrui98 (backendRedirectCfi.pd.isBr && !r_ftb_entry.brIsSaved(r_ftqOffset) && 69309c6f1ddSLingrui98 !(r_ftb_entry.brValids(numBr-1) && r_ftqOffset > r_ftb_entry.brOffset(numBr-1))) 69409c6f1ddSLingrui98 69509c6f1ddSLingrui98 backendRedirectCfi.addIntoHist := backendRedirectCfi.pd.isBr && (r_ftb_entry.brIsSaved(r_ftqOffset) || 69609c6f1ddSLingrui98 !(r_ftb_entry.brValids(numBr-1) && r_ftqOffset > r_ftb_entry.brOffset(numBr-1))) 69709c6f1ddSLingrui98 }.otherwise { 69809c6f1ddSLingrui98 backendRedirectCfi.shift := (backendRedirectCfi.pd.isBr && backendRedirectCfi.taken).asUInt 69909c6f1ddSLingrui98 backendRedirectCfi.addIntoHist := backendRedirectCfi.pd.isBr.asUInt 70009c6f1ddSLingrui98 } 70109c6f1ddSLingrui98 70209c6f1ddSLingrui98 70309c6f1ddSLingrui98 // *************************************************************************** 70409c6f1ddSLingrui98 // **************************** redirect from ifu **************************** 70509c6f1ddSLingrui98 // *************************************************************************** 70609c6f1ddSLingrui98 val fromIfuRedirect = WireInit(0.U.asTypeOf(Valid(new Redirect))) 70709c6f1ddSLingrui98 fromIfuRedirect.valid := pdWb.valid && pdWb.bits.misOffset.valid && !backendFlush 70809c6f1ddSLingrui98 fromIfuRedirect.bits.ftqIdx := pdWb.bits.ftqIdx 70909c6f1ddSLingrui98 fromIfuRedirect.bits.ftqOffset := pdWb.bits.misOffset.bits 71009c6f1ddSLingrui98 fromIfuRedirect.bits.level := RedirectLevel.flushAfter 71109c6f1ddSLingrui98 71209c6f1ddSLingrui98 val ifuRedirectCfiUpdate = fromIfuRedirect.bits.cfiUpdate 71309c6f1ddSLingrui98 ifuRedirectCfiUpdate.pc := pdWb.bits.pc(pdWb.bits.misOffset.bits) 71409c6f1ddSLingrui98 ifuRedirectCfiUpdate.pd := pdWb.bits.pd(pdWb.bits.misOffset.bits) 71509c6f1ddSLingrui98 ifuRedirectCfiUpdate.predTaken := cfiIndex_vec(pdWb.bits.ftqIdx.value).valid 71609c6f1ddSLingrui98 ifuRedirectCfiUpdate.target := pdWb.bits.target 71709c6f1ddSLingrui98 ifuRedirectCfiUpdate.taken := pdWb.bits.cfiOffset.valid 71809c6f1ddSLingrui98 ifuRedirectCfiUpdate.isMisPred := pdWb.bits.misOffset.valid 71909c6f1ddSLingrui98 72009c6f1ddSLingrui98 val ifuRedirectReg = RegNext(fromIfuRedirect, init=0.U.asTypeOf(Valid(new Redirect))) 72109c6f1ddSLingrui98 val ifuRedirectToBpu = WireInit(ifuRedirectReg) 72209c6f1ddSLingrui98 ifuFlush := fromIfuRedirect.valid || ifuRedirectToBpu.valid 72309c6f1ddSLingrui98 72409c6f1ddSLingrui98 ftq_redirect_sram.io.ren.head := fromIfuRedirect.valid 72509c6f1ddSLingrui98 ftq_redirect_sram.io.raddr.head := fromIfuRedirect.bits.ftqIdx.value 72609c6f1ddSLingrui98 72709c6f1ddSLingrui98 ftb_entry_mem.io.raddr.head := fromIfuRedirect.bits.ftqIdx.value 72809c6f1ddSLingrui98 72909c6f1ddSLingrui98 val toBpuCfi = ifuRedirectToBpu.bits.cfiUpdate 73009c6f1ddSLingrui98 toBpuCfi.fromFtqRedirectSram(ftq_redirect_sram.io.rdata.head) 73109c6f1ddSLingrui98 when (ifuRedirectReg.bits.cfiUpdate.pd.isRet) { 73209c6f1ddSLingrui98 toBpuCfi.target := toBpuCfi.rasEntry.retAddr 73309c6f1ddSLingrui98 } 73409c6f1ddSLingrui98 73509c6f1ddSLingrui98 // ********************************************************************* 73609c6f1ddSLingrui98 // **************************** wb from exu **************************** 73709c6f1ddSLingrui98 // ********************************************************************* 73809c6f1ddSLingrui98 73909c6f1ddSLingrui98 def extractRedirectInfo(wb: Valid[Redirect]) = { 74009c6f1ddSLingrui98 val ftqIdx = wb.bits.ftqIdx.value 74109c6f1ddSLingrui98 val ftqOffset = wb.bits.ftqOffset 74209c6f1ddSLingrui98 val taken = wb.bits.cfiUpdate.taken 74309c6f1ddSLingrui98 val mispred = wb.bits.cfiUpdate.isMisPred 74409c6f1ddSLingrui98 (wb.valid, ftqIdx, ftqOffset, taken, mispred) 74509c6f1ddSLingrui98 } 74609c6f1ddSLingrui98 74709c6f1ddSLingrui98 // fix mispredict entry 74809c6f1ddSLingrui98 val lastIsMispredict = RegNext( 74909c6f1ddSLingrui98 stage2Redirect.valid && stage2Redirect.bits.level === RedirectLevel.flushAfter, init = false.B 75009c6f1ddSLingrui98 ) 75109c6f1ddSLingrui98 75209c6f1ddSLingrui98 def updateCfiInfo(redirect: Valid[Redirect], isBackend: Boolean = true) = { 75309c6f1ddSLingrui98 val (r_valid, r_idx, r_offset, r_taken, r_mispred) = extractRedirectInfo(redirect) 75409c6f1ddSLingrui98 val cfiIndex_bits_wen = r_valid && r_taken && r_offset < cfiIndex_vec(r_idx).bits 75509c6f1ddSLingrui98 val cfiIndex_valid_wen = r_valid && r_offset === cfiIndex_vec(r_idx).bits 75609c6f1ddSLingrui98 when (cfiIndex_bits_wen || cfiIndex_valid_wen) { 75709c6f1ddSLingrui98 cfiIndex_vec(r_idx).valid := cfiIndex_bits_wen || cfiIndex_valid_wen && r_taken 75809c6f1ddSLingrui98 } 75909c6f1ddSLingrui98 when (cfiIndex_bits_wen) { 76009c6f1ddSLingrui98 cfiIndex_vec(r_idx).bits := r_offset 76109c6f1ddSLingrui98 } 76209c6f1ddSLingrui98 update_target(r_idx) := redirect.bits.cfiUpdate.target 76309c6f1ddSLingrui98 if (isBackend) { 76409c6f1ddSLingrui98 mispredict_vec(r_idx)(r_offset) := r_mispred 76509c6f1ddSLingrui98 } 76609c6f1ddSLingrui98 } 76709c6f1ddSLingrui98 76809c6f1ddSLingrui98 when(stage3Redirect.valid && lastIsMispredict) { 76909c6f1ddSLingrui98 updateCfiInfo(stage3Redirect) 77009c6f1ddSLingrui98 }.elsewhen (ifuRedirectToBpu.valid) { 77109c6f1ddSLingrui98 updateCfiInfo(ifuRedirectToBpu, isBackend=false) 77209c6f1ddSLingrui98 } 77309c6f1ddSLingrui98 77409c6f1ddSLingrui98 // *********************************************************************************** 77509c6f1ddSLingrui98 // **************************** flush ptr and state queue **************************** 77609c6f1ddSLingrui98 // *********************************************************************************** 77709c6f1ddSLingrui98 77809c6f1ddSLingrui98 class RedirectInfo extends Bundle { 77909c6f1ddSLingrui98 val valid = Bool() 78009c6f1ddSLingrui98 val ftqIdx = new FtqPtr 78109c6f1ddSLingrui98 val ftqOffset = UInt(4.W) 78209c6f1ddSLingrui98 val flushItSelf = Bool() 78309c6f1ddSLingrui98 def apply(redirect: Valid[Redirect]) = { 78409c6f1ddSLingrui98 this.valid := redirect.valid 78509c6f1ddSLingrui98 this.ftqIdx := redirect.bits.ftqIdx 78609c6f1ddSLingrui98 this.ftqOffset := redirect.bits.ftqOffset 78709c6f1ddSLingrui98 this.flushItSelf := RedirectLevel.flushItself(redirect.bits.level) 78809c6f1ddSLingrui98 this 78909c6f1ddSLingrui98 } 79009c6f1ddSLingrui98 } 79109c6f1ddSLingrui98 val redirectVec = Wire(Vec(3, new RedirectInfo)) 792*9aca92b9SYinan Xu val robRedirect = Wire(Valid(new Redirect)) 793*9aca92b9SYinan Xu robRedirect := DontCare 794*9aca92b9SYinan Xu robRedirect.valid := robFlush.valid 795*9aca92b9SYinan Xu robRedirect.bits.ftqIdx := robFlush.bits.ftqIdx 796*9aca92b9SYinan Xu robRedirect.bits.ftqOffset := robFlush.bits.ftqOffset 797*9aca92b9SYinan Xu robRedirect.bits.level := RedirectLevel.flush 79809c6f1ddSLingrui98 799*9aca92b9SYinan Xu redirectVec.zip(Seq(robRedirect, stage2Redirect, fromIfuRedirect)).map { 80009c6f1ddSLingrui98 case (ve, r) => ve(r) 80109c6f1ddSLingrui98 } 80209c6f1ddSLingrui98 80309c6f1ddSLingrui98 // when redirect, we should reset ptrs and status queues 80409c6f1ddSLingrui98 when(redirectVec.map(r => r.valid).reduce(_||_)){ 80509c6f1ddSLingrui98 val r = PriorityMux(redirectVec.map(r => (r.valid -> r))) 80609c6f1ddSLingrui98 val notIfu = redirectVec.dropRight(1).map(r => r.valid).reduce(_||_) 80709c6f1ddSLingrui98 val (idx, offset, flushItSelf) = (r.ftqIdx, r.ftqOffset, r.flushItSelf) 80809c6f1ddSLingrui98 val next = idx + 1.U 80909c6f1ddSLingrui98 bpuPtr := next 81009c6f1ddSLingrui98 ifuPtr := next 81109c6f1ddSLingrui98 ifuWbPtr := next 81209c6f1ddSLingrui98 when (notIfu) { 81309c6f1ddSLingrui98 commitStateQueue(idx.value).zipWithIndex.foreach({ case (s, i) => 81409c6f1ddSLingrui98 when(i.U > offset || i.U === offset && flushItSelf){ 81509c6f1ddSLingrui98 s := c_invalid 81609c6f1ddSLingrui98 } 81709c6f1ddSLingrui98 }) 81809c6f1ddSLingrui98 } 81909c6f1ddSLingrui98 } 82009c6f1ddSLingrui98 82109c6f1ddSLingrui98 // only the valid bit is actually needed 82209c6f1ddSLingrui98 io.toIfu.redirect := DontCare 82309c6f1ddSLingrui98 io.toIfu.redirect.valid := stage2Flush 82409c6f1ddSLingrui98 82509c6f1ddSLingrui98 // commit 826*9aca92b9SYinan Xu for (c <- io.fromBackend.rob_commits) { 82709c6f1ddSLingrui98 when(c.valid) { 82809c6f1ddSLingrui98 commitStateQueue(c.bits.ftqIdx.value)(c.bits.ftqOffset) := c_commited 82988825c5cSYinan Xu // TODO: remove this 83088825c5cSYinan Xu // For instruction fusions, we also update the next instruction 83188825c5cSYinan Xu when (c.bits.isFused === 1.U) { 83288825c5cSYinan Xu commitStateQueue(c.bits.ftqIdx.value)(c.bits.ftqOffset + 1.U) := c_commited 83388825c5cSYinan Xu }.elsewhen(c.bits.isFused === 2.U) { 83488825c5cSYinan Xu commitStateQueue(c.bits.ftqIdx.value)(c.bits.ftqOffset + 2.U) := c_commited 83588825c5cSYinan Xu }.elsewhen(c.bits.isFused === 3.U) { 83688825c5cSYinan Xu val index = (c.bits.ftqIdx + 1.U).value 83788825c5cSYinan Xu commitStateQueue(index)(0) := c_commited 83888825c5cSYinan Xu }.elsewhen(c.bits.isFused === 4.U) { 83988825c5cSYinan Xu val index = (c.bits.ftqIdx + 1.U).value 84088825c5cSYinan Xu commitStateQueue(index)(1) := c_commited 84188825c5cSYinan Xu } 84209c6f1ddSLingrui98 } 84309c6f1ddSLingrui98 } 84409c6f1ddSLingrui98 84509c6f1ddSLingrui98 // **************************************************************** 84609c6f1ddSLingrui98 // **************************** to bpu **************************** 84709c6f1ddSLingrui98 // **************************************************************** 84809c6f1ddSLingrui98 84909c6f1ddSLingrui98 io.toBpu.redirect <> Mux(fromBackendRedirect.valid, fromBackendRedirect, ifuRedirectToBpu) 85009c6f1ddSLingrui98 85109c6f1ddSLingrui98 val canCommit = commPtr =/= ifuWbPtr && 85209c6f1ddSLingrui98 Cat(commitStateQueue(commPtr.value).map(s => { 85309c6f1ddSLingrui98 s === c_invalid || s === c_commited 85409c6f1ddSLingrui98 })).andR() 85509c6f1ddSLingrui98 85609c6f1ddSLingrui98 // commit reads 85709c6f1ddSLingrui98 ftq_pc_mem.io.raddr.last := commPtr.value 85809c6f1ddSLingrui98 val commit_pc_bundle = ftq_pc_mem.io.rdata.last 85909c6f1ddSLingrui98 ftq_pd_mem.io.raddr.last := commPtr.value 86009c6f1ddSLingrui98 val commit_pd = ftq_pd_mem.io.rdata.last 86109c6f1ddSLingrui98 ftq_redirect_sram.io.ren.last := canCommit 86209c6f1ddSLingrui98 ftq_redirect_sram.io.raddr.last := commPtr.value 86309c6f1ddSLingrui98 val commit_spec_meta = ftq_redirect_sram.io.rdata.last 86409c6f1ddSLingrui98 ftq_meta_1r_sram.io.ren(0) := canCommit 86509c6f1ddSLingrui98 ftq_meta_1r_sram.io.raddr(0) := commPtr.value 86609c6f1ddSLingrui98 val commit_meta = ftq_meta_1r_sram.io.rdata(0) 86709c6f1ddSLingrui98 ftb_entry_mem.io.raddr.last := commPtr.value 86809c6f1ddSLingrui98 val commit_ftb_entry = ftb_entry_mem.io.rdata.last 86909c6f1ddSLingrui98 87009c6f1ddSLingrui98 // need one cycle to read mem and srams 87109c6f1ddSLingrui98 val do_commit = RegNext(canCommit, init=false.B) 87209c6f1ddSLingrui98 val do_commit_ptr = RegNext(commPtr) 87309c6f1ddSLingrui98 when (canCommit) { commPtr := commPtr + 1.U } 87409c6f1ddSLingrui98 val commit_state = RegNext(commitStateQueue(commPtr.value)) 87509c6f1ddSLingrui98 val commit_cfi = WireInit(RegNext(cfiIndex_vec(commPtr.value))) 87609c6f1ddSLingrui98 when (commit_state(commit_cfi.bits) =/= c_commited) { 87709c6f1ddSLingrui98 commit_cfi.valid := false.B 87809c6f1ddSLingrui98 } 87909c6f1ddSLingrui98 88009c6f1ddSLingrui98 val commit_mispredict = VecInit((RegNext(mispredict_vec(commPtr.value)) zip commit_state).map { 88109c6f1ddSLingrui98 case (mis, state) => mis && state === c_commited 88209c6f1ddSLingrui98 }) 88309c6f1ddSLingrui98 val commit_hit = RegNext(entry_hit_status(commPtr.value)) 88409c6f1ddSLingrui98 val commit_target = RegNext(update_target(commPtr.value)) 88509c6f1ddSLingrui98 val commit_valid = commit_hit === h_hit || commit_cfi.valid // hit or taken 88609c6f1ddSLingrui98 88709c6f1ddSLingrui98 88809c6f1ddSLingrui98 io.toBpu.update := DontCare 88909c6f1ddSLingrui98 io.toBpu.update.valid := commit_valid && do_commit 89009c6f1ddSLingrui98 val update = io.toBpu.update.bits 89109c6f1ddSLingrui98 update.false_hit := commit_hit === h_false_hit 89209c6f1ddSLingrui98 update.pc := commit_pc_bundle.startAddr 89309c6f1ddSLingrui98 update.preds.hit := commit_hit === h_hit || commit_hit === h_false_hit 89409c6f1ddSLingrui98 update.meta := commit_meta.meta 8958ffcd86aSLingrui98 update.full_target := commit_target 89609c6f1ddSLingrui98 update.fromFtqRedirectSram(commit_spec_meta) 89709c6f1ddSLingrui98 89809c6f1ddSLingrui98 val commit_real_hit = commit_hit === h_hit 89909c6f1ddSLingrui98 val update_ftb_entry = update.ftb_entry 90009c6f1ddSLingrui98 90109c6f1ddSLingrui98 val ftbEntryGen = Module(new FTBEntryGen).io 90209c6f1ddSLingrui98 ftbEntryGen.start_addr := commit_pc_bundle.startAddr 90309c6f1ddSLingrui98 ftbEntryGen.old_entry := commit_ftb_entry 90409c6f1ddSLingrui98 ftbEntryGen.pd := commit_pd 90509c6f1ddSLingrui98 ftbEntryGen.cfiIndex := commit_cfi 90609c6f1ddSLingrui98 ftbEntryGen.target := commit_target 90709c6f1ddSLingrui98 ftbEntryGen.hit := commit_real_hit 90809c6f1ddSLingrui98 ftbEntryGen.mispredict_vec := commit_mispredict 90909c6f1ddSLingrui98 91009c6f1ddSLingrui98 update_ftb_entry := ftbEntryGen.new_entry 91109c6f1ddSLingrui98 update.new_br_insert_pos := ftbEntryGen.new_br_insert_pos 91209c6f1ddSLingrui98 update.mispred_mask := ftbEntryGen.mispred_mask 91309c6f1ddSLingrui98 update.old_entry := ftbEntryGen.is_old_entry 91409c6f1ddSLingrui98 update.preds.taken_mask := ftbEntryGen.taken_mask 91509c6f1ddSLingrui98 91609c6f1ddSLingrui98 // ****************************************************************************** 91709c6f1ddSLingrui98 // **************************** commit perf counters **************************** 91809c6f1ddSLingrui98 // ****************************************************************************** 91909c6f1ddSLingrui98 92009c6f1ddSLingrui98 val commit_inst_mask = VecInit(commit_state.map(c => c === c_commited && do_commit)).asUInt 92109c6f1ddSLingrui98 val commit_mispred_mask = commit_mispredict.asUInt 92209c6f1ddSLingrui98 val commit_not_mispred_mask = ~commit_mispred_mask 92309c6f1ddSLingrui98 92409c6f1ddSLingrui98 val commit_br_mask = commit_pd.brMask.asUInt 92509c6f1ddSLingrui98 val commit_jmp_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.jmpInfo.valid.asTypeOf(UInt(1.W))) 92609c6f1ddSLingrui98 val commit_cfi_mask = (commit_br_mask | commit_jmp_mask) 92709c6f1ddSLingrui98 92809c6f1ddSLingrui98 val mbpInstrs = commit_inst_mask & commit_cfi_mask 92909c6f1ddSLingrui98 93009c6f1ddSLingrui98 val mbpRights = mbpInstrs & commit_not_mispred_mask 93109c6f1ddSLingrui98 val mbpWrongs = mbpInstrs & commit_mispred_mask 93209c6f1ddSLingrui98 93309c6f1ddSLingrui98 io.bpuInfo.bpRight := PopCount(mbpRights) 93409c6f1ddSLingrui98 io.bpuInfo.bpWrong := PopCount(mbpWrongs) 93509c6f1ddSLingrui98 93609c6f1ddSLingrui98 // Cfi Info 93709c6f1ddSLingrui98 for (i <- 0 until PredictWidth) { 93809c6f1ddSLingrui98 val pc = commit_pc_bundle.startAddr + (i * instBytes).U 93909c6f1ddSLingrui98 val v = commit_state(i) === c_commited 94009c6f1ddSLingrui98 val isBr = commit_pd.brMask(i) 94109c6f1ddSLingrui98 val isJmp = commit_pd.jmpInfo.valid && commit_pd.jmpOffset === i.U 94209c6f1ddSLingrui98 val isCfi = isBr || isJmp 94309c6f1ddSLingrui98 val isTaken = commit_cfi.valid && commit_cfi.bits === i.U 94409c6f1ddSLingrui98 val misPred = commit_mispredict(i) 94509c6f1ddSLingrui98 val ghist = commit_spec_meta.ghist.predHist 94609c6f1ddSLingrui98 val predCycle = commit_meta.meta(63, 0) 94709c6f1ddSLingrui98 val target = commit_target 94809c6f1ddSLingrui98 94909c6f1ddSLingrui98 val brIdx = OHToUInt(Reverse(Cat(update_ftb_entry.brValids.zip(update_ftb_entry.brOffset).map{case(v, offset) => v && offset === i.U}))) 95009c6f1ddSLingrui98 val inFtbEntry = update_ftb_entry.brValids.zip(update_ftb_entry.brOffset).map{case(v, offset) => v && offset === i.U}.reduce(_||_) 95109c6f1ddSLingrui98 val addIntoHist = ((commit_hit === h_hit) && inFtbEntry) || ((!(commit_hit === h_hit) && i.U === commit_cfi.bits && isBr && commit_cfi.valid)) 95209c6f1ddSLingrui98 XSDebug(v && do_commit && isCfi, p"cfi_update: isBr(${isBr}) pc(${Hexadecimal(pc)}) " + 95309c6f1ddSLingrui98 p"taken(${isTaken}) mispred(${misPred}) cycle($predCycle) hist(${Hexadecimal(ghist)}) " + 95409c6f1ddSLingrui98 p"startAddr(${Hexadecimal(commit_pc_bundle.startAddr)}) AddIntoHist(${addIntoHist}) " + 95509c6f1ddSLingrui98 p"brInEntry(${inFtbEntry}) brIdx(${brIdx}) target(${Hexadecimal(target)})\n") 95609c6f1ddSLingrui98 } 95709c6f1ddSLingrui98 95809c6f1ddSLingrui98 val enq = io.fromBpu.resp 95909c6f1ddSLingrui98 val perf_redirect = io.fromBackend.stage2Redirect 96009c6f1ddSLingrui98 96109c6f1ddSLingrui98 XSPerfAccumulate("entry", validEntries) 96209c6f1ddSLingrui98 XSPerfAccumulate("bpu_to_ftq_stall", enq.valid && !enq.ready) 96309c6f1ddSLingrui98 XSPerfAccumulate("mispredictRedirect", perf_redirect.valid && RedirectLevel.flushAfter === perf_redirect.bits.level) 96409c6f1ddSLingrui98 XSPerfAccumulate("replayRedirect", perf_redirect.valid && RedirectLevel.flushItself(perf_redirect.bits.level)) 96509c6f1ddSLingrui98 XSPerfAccumulate("predecodeRedirect", fromIfuRedirect.valid) 96609c6f1ddSLingrui98 96709c6f1ddSLingrui98 XSPerfAccumulate("to_ifu_bubble", io.toIfu.req.ready && !io.toIfu.req.valid) 96809c6f1ddSLingrui98 96909c6f1ddSLingrui98 XSPerfAccumulate("to_ifu_stall", io.toIfu.req.valid && !io.toIfu.req.ready) 97009c6f1ddSLingrui98 XSPerfAccumulate("from_bpu_real_bubble", !enq.valid && enq.ready && allowBpuIn) 97109c6f1ddSLingrui98 97209c6f1ddSLingrui98 val from_bpu = io.fromBpu.resp.bits 97309c6f1ddSLingrui98 def in_entry_len_map_gen(resp: BranchPredictionBundle)(stage: String) = { 97409c6f1ddSLingrui98 val entry_len = (resp.ftb_entry.getFallThrough(resp.pc) - resp.pc) >> instOffsetBits 97509c6f1ddSLingrui98 val entry_len_recording_vec = (1 to PredictWidth+1).map(i => entry_len === i.U) 97609c6f1ddSLingrui98 val entry_len_map = (1 to PredictWidth+1).map(i => 97709c6f1ddSLingrui98 f"${stage}_ftb_entry_len_$i" -> (entry_len_recording_vec(i-1) && resp.valid) 97809c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 97909c6f1ddSLingrui98 entry_len_map 98009c6f1ddSLingrui98 } 98109c6f1ddSLingrui98 val s1_entry_len_map = in_entry_len_map_gen(from_bpu.s1)("s1") 98209c6f1ddSLingrui98 val s2_entry_len_map = in_entry_len_map_gen(from_bpu.s2)("s2") 98309c6f1ddSLingrui98 val s3_entry_len_map = in_entry_len_map_gen(from_bpu.s3)("s3") 98409c6f1ddSLingrui98 98509c6f1ddSLingrui98 val to_ifu = io.toIfu.req.bits 98609c6f1ddSLingrui98 val to_ifu_entry_len = (to_ifu.fallThruAddr - to_ifu.startAddr) >> instOffsetBits 98709c6f1ddSLingrui98 val to_ifu_entry_len_recording_vec = (1 to PredictWidth+1).map(i => to_ifu_entry_len === i.U) 98809c6f1ddSLingrui98 val to_ifu_entry_len_map = (1 to PredictWidth+1).map(i => 98909c6f1ddSLingrui98 f"to_ifu_ftb_entry_len_$i" -> (to_ifu_entry_len_recording_vec(i-1) && io.toIfu.req.fire) 99009c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 99109c6f1ddSLingrui98 99209c6f1ddSLingrui98 99309c6f1ddSLingrui98 99409c6f1ddSLingrui98 val commit_num_inst_recording_vec = (1 to PredictWidth).map(i => PopCount(commit_inst_mask) === i.U) 99509c6f1ddSLingrui98 val commit_num_inst_map = (1 to PredictWidth).map(i => 99609c6f1ddSLingrui98 f"commit_num_inst_$i" -> (commit_num_inst_recording_vec(i-1) && do_commit) 99709c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 99809c6f1ddSLingrui98 99909c6f1ddSLingrui98 100009c6f1ddSLingrui98 100109c6f1ddSLingrui98 val commit_jal_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasJal.asTypeOf(UInt(1.W))) 100209c6f1ddSLingrui98 val commit_jalr_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasJalr.asTypeOf(UInt(1.W))) 100309c6f1ddSLingrui98 val commit_call_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasCall.asTypeOf(UInt(1.W))) 100409c6f1ddSLingrui98 val commit_ret_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasRet.asTypeOf(UInt(1.W))) 100509c6f1ddSLingrui98 100609c6f1ddSLingrui98 100709c6f1ddSLingrui98 val mbpBRights = mbpRights & commit_br_mask 100809c6f1ddSLingrui98 val mbpJRights = mbpRights & commit_jal_mask 100909c6f1ddSLingrui98 val mbpIRights = mbpRights & commit_jalr_mask 101009c6f1ddSLingrui98 val mbpCRights = mbpRights & commit_call_mask 101109c6f1ddSLingrui98 val mbpRRights = mbpRights & commit_ret_mask 101209c6f1ddSLingrui98 101309c6f1ddSLingrui98 val mbpBWrongs = mbpWrongs & commit_br_mask 101409c6f1ddSLingrui98 val mbpJWrongs = mbpWrongs & commit_jal_mask 101509c6f1ddSLingrui98 val mbpIWrongs = mbpWrongs & commit_jalr_mask 101609c6f1ddSLingrui98 val mbpCWrongs = mbpWrongs & commit_call_mask 101709c6f1ddSLingrui98 val mbpRWrongs = mbpWrongs & commit_ret_mask 101809c6f1ddSLingrui98 101909c6f1ddSLingrui98 val update_valid = io.toBpu.update.valid 102009c6f1ddSLingrui98 def u(cond: Bool) = update_valid && cond 102109c6f1ddSLingrui98 val ftb_false_hit = u(update.false_hit) 102265fddcf0Szoujr // assert(!ftb_false_hit) 102309c6f1ddSLingrui98 val ftb_hit = u(commit_hit === h_hit) 102409c6f1ddSLingrui98 102509c6f1ddSLingrui98 val ftb_new_entry = u(ftbEntryGen.is_init_entry) 102609c6f1ddSLingrui98 val ftb_new_entry_only_br = ftb_new_entry && !update.ftb_entry.jmpValid 102709c6f1ddSLingrui98 val ftb_new_entry_only_jmp = ftb_new_entry && !update.ftb_entry.brValids(0) 102809c6f1ddSLingrui98 val ftb_new_entry_has_br_and_jmp = ftb_new_entry && update.ftb_entry.brValids(0) && update.ftb_entry.jmpValid 102909c6f1ddSLingrui98 103009c6f1ddSLingrui98 val ftb_old_entry = u(ftbEntryGen.is_old_entry) 103109c6f1ddSLingrui98 103209c6f1ddSLingrui98 val ftb_modified_entry = u(ftbEntryGen.is_new_br || ftbEntryGen.is_jalr_target_modified || ftbEntryGen.is_always_taken_modified) 103309c6f1ddSLingrui98 val ftb_modified_entry_new_br = u(ftbEntryGen.is_new_br) 103409c6f1ddSLingrui98 val ftb_modified_entry_jalr_target_modified = u(ftbEntryGen.is_jalr_target_modified) 103509c6f1ddSLingrui98 val ftb_modified_entry_br_full = ftb_modified_entry && ftbEntryGen.is_br_full 103609c6f1ddSLingrui98 val ftb_modified_entry_always_taken = ftb_modified_entry && ftbEntryGen.is_always_taken_modified 103709c6f1ddSLingrui98 103809c6f1ddSLingrui98 val ftb_entry_len = (ftbEntryGen.new_entry.getFallThrough(update.pc) - update.pc) >> instOffsetBits 103909c6f1ddSLingrui98 val ftb_entry_len_recording_vec = (1 to PredictWidth+1).map(i => ftb_entry_len === i.U) 104009c6f1ddSLingrui98 val ftb_init_entry_len_map = (1 to PredictWidth+1).map(i => 104109c6f1ddSLingrui98 f"ftb_init_entry_len_$i" -> (ftb_entry_len_recording_vec(i-1) && ftb_new_entry) 104209c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 104309c6f1ddSLingrui98 val ftb_modified_entry_len_map = (1 to PredictWidth+1).map(i => 104409c6f1ddSLingrui98 f"ftb_modified_entry_len_$i" -> (ftb_entry_len_recording_vec(i-1) && ftb_modified_entry) 104509c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 104609c6f1ddSLingrui98 104709c6f1ddSLingrui98 val ftq_occupancy_map = (0 to FtqSize).map(i => 104809c6f1ddSLingrui98 f"ftq_has_entry_$i" ->( validEntries === i.U) 104909c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 105009c6f1ddSLingrui98 105109c6f1ddSLingrui98 val perfCountsMap = Map( 105209c6f1ddSLingrui98 "BpInstr" -> PopCount(mbpInstrs), 105309c6f1ddSLingrui98 "BpBInstr" -> PopCount(mbpBRights | mbpBWrongs), 105409c6f1ddSLingrui98 "BpRight" -> PopCount(mbpRights), 105509c6f1ddSLingrui98 "BpWrong" -> PopCount(mbpWrongs), 105609c6f1ddSLingrui98 "BpBRight" -> PopCount(mbpBRights), 105709c6f1ddSLingrui98 "BpBWrong" -> PopCount(mbpBWrongs), 105809c6f1ddSLingrui98 "BpJRight" -> PopCount(mbpJRights), 105909c6f1ddSLingrui98 "BpJWrong" -> PopCount(mbpJWrongs), 106009c6f1ddSLingrui98 "BpIRight" -> PopCount(mbpIRights), 106109c6f1ddSLingrui98 "BpIWrong" -> PopCount(mbpIWrongs), 106209c6f1ddSLingrui98 "BpCRight" -> PopCount(mbpCRights), 106309c6f1ddSLingrui98 "BpCWrong" -> PopCount(mbpCWrongs), 106409c6f1ddSLingrui98 "BpRRight" -> PopCount(mbpRRights), 106509c6f1ddSLingrui98 "BpRWrong" -> PopCount(mbpRWrongs), 106609c6f1ddSLingrui98 106709c6f1ddSLingrui98 "ftb_false_hit" -> PopCount(ftb_false_hit), 106809c6f1ddSLingrui98 "ftb_hit" -> PopCount(ftb_hit), 106909c6f1ddSLingrui98 "ftb_new_entry" -> PopCount(ftb_new_entry), 107009c6f1ddSLingrui98 "ftb_new_entry_only_br" -> PopCount(ftb_new_entry_only_br), 107109c6f1ddSLingrui98 "ftb_new_entry_only_jmp" -> PopCount(ftb_new_entry_only_jmp), 107209c6f1ddSLingrui98 "ftb_new_entry_has_br_and_jmp" -> PopCount(ftb_new_entry_has_br_and_jmp), 107309c6f1ddSLingrui98 "ftb_old_entry" -> PopCount(ftb_old_entry), 107409c6f1ddSLingrui98 "ftb_modified_entry" -> PopCount(ftb_modified_entry), 107509c6f1ddSLingrui98 "ftb_modified_entry_new_br" -> PopCount(ftb_modified_entry_new_br), 107609c6f1ddSLingrui98 "ftb_jalr_target_modified" -> PopCount(ftb_modified_entry_jalr_target_modified), 107709c6f1ddSLingrui98 "ftb_modified_entry_br_full" -> PopCount(ftb_modified_entry_br_full), 107809c6f1ddSLingrui98 "ftb_modified_entry_always_taken" -> PopCount(ftb_modified_entry_always_taken) 107909c6f1ddSLingrui98 ) ++ ftb_init_entry_len_map ++ ftb_modified_entry_len_map ++ s1_entry_len_map ++ 108009c6f1ddSLingrui98 s2_entry_len_map ++ s3_entry_len_map ++ 108109c6f1ddSLingrui98 to_ifu_entry_len_map ++ commit_num_inst_map ++ ftq_occupancy_map 108209c6f1ddSLingrui98 108309c6f1ddSLingrui98 for((key, value) <- perfCountsMap) { 108409c6f1ddSLingrui98 XSPerfAccumulate(key, value) 108509c6f1ddSLingrui98 } 108609c6f1ddSLingrui98 108709c6f1ddSLingrui98 // --------------------------- Debug -------------------------------- 108809c6f1ddSLingrui98 // XSDebug(enq_fire, p"enq! " + io.fromBpu.resp.bits.toPrintable) 108909c6f1ddSLingrui98 XSDebug(io.toIfu.req.fire, p"fire to ifu " + io.toIfu.req.bits.toPrintable) 109009c6f1ddSLingrui98 XSDebug(do_commit, p"deq! [ptr] $do_commit_ptr\n") 109109c6f1ddSLingrui98 XSDebug(true.B, p"[bpuPtr] $bpuPtr, [ifuPtr] $ifuPtr, [ifuWbPtr] $ifuWbPtr [commPtr] $commPtr\n") 109209c6f1ddSLingrui98 XSDebug(true.B, p"[in] v:${io.fromBpu.resp.valid} r:${io.fromBpu.resp.ready} " + 109309c6f1ddSLingrui98 p"[out] v:${io.toIfu.req.valid} r:${io.toIfu.req.ready}\n") 109409c6f1ddSLingrui98 XSDebug(do_commit, p"[deq info] cfiIndex: $commit_cfi, $commit_pc_bundle, target: ${Hexadecimal(commit_target)}\n") 109509c6f1ddSLingrui98 109609c6f1ddSLingrui98 // def ubtbCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 109709c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 109809c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 109909c6f1ddSLingrui98 // Mux(valid && pd.isBr, 110009c6f1ddSLingrui98 // isWrong ^ Mux(ans.hit.asBool, 110109c6f1ddSLingrui98 // Mux(ans.taken.asBool, taken && ans.target === commitEntry.target, 110209c6f1ddSLingrui98 // !taken), 110309c6f1ddSLingrui98 // !taken), 110409c6f1ddSLingrui98 // false.B) 110509c6f1ddSLingrui98 // } 110609c6f1ddSLingrui98 // } 110709c6f1ddSLingrui98 110809c6f1ddSLingrui98 // def btbCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 110909c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 111009c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 111109c6f1ddSLingrui98 // Mux(valid && pd.isBr, 111209c6f1ddSLingrui98 // isWrong ^ Mux(ans.hit.asBool, 111309c6f1ddSLingrui98 // Mux(ans.taken.asBool, taken && ans.target === commitEntry.target, 111409c6f1ddSLingrui98 // !taken), 111509c6f1ddSLingrui98 // !taken), 111609c6f1ddSLingrui98 // false.B) 111709c6f1ddSLingrui98 // } 111809c6f1ddSLingrui98 // } 111909c6f1ddSLingrui98 112009c6f1ddSLingrui98 // def tageCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 112109c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 112209c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 112309c6f1ddSLingrui98 // Mux(valid && pd.isBr, 112409c6f1ddSLingrui98 // isWrong ^ (ans.taken.asBool === taken), 112509c6f1ddSLingrui98 // false.B) 112609c6f1ddSLingrui98 // } 112709c6f1ddSLingrui98 // } 112809c6f1ddSLingrui98 112909c6f1ddSLingrui98 // def loopCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 113009c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 113109c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 113209c6f1ddSLingrui98 // Mux(valid && (pd.isBr) && ans.hit.asBool, 113309c6f1ddSLingrui98 // isWrong ^ (!taken), 113409c6f1ddSLingrui98 // false.B) 113509c6f1ddSLingrui98 // } 113609c6f1ddSLingrui98 // } 113709c6f1ddSLingrui98 113809c6f1ddSLingrui98 // def rasCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 113909c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 114009c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 114109c6f1ddSLingrui98 // Mux(valid && pd.isRet.asBool /*&& taken*/ && ans.hit.asBool, 114209c6f1ddSLingrui98 // isWrong ^ (ans.target === commitEntry.target), 114309c6f1ddSLingrui98 // false.B) 114409c6f1ddSLingrui98 // } 114509c6f1ddSLingrui98 // } 114609c6f1ddSLingrui98 114709c6f1ddSLingrui98 // val ubtbRights = ubtbCheck(commitEntry, commitEntry.metas.map(_.ubtbAns), false.B) 114809c6f1ddSLingrui98 // val ubtbWrongs = ubtbCheck(commitEntry, commitEntry.metas.map(_.ubtbAns), true.B) 114909c6f1ddSLingrui98 // // btb and ubtb pred jal and jalr as well 115009c6f1ddSLingrui98 // val btbRights = btbCheck(commitEntry, commitEntry.metas.map(_.btbAns), false.B) 115109c6f1ddSLingrui98 // val btbWrongs = btbCheck(commitEntry, commitEntry.metas.map(_.btbAns), true.B) 115209c6f1ddSLingrui98 // val tageRights = tageCheck(commitEntry, commitEntry.metas.map(_.tageAns), false.B) 115309c6f1ddSLingrui98 // val tageWrongs = tageCheck(commitEntry, commitEntry.metas.map(_.tageAns), true.B) 115409c6f1ddSLingrui98 115509c6f1ddSLingrui98 // val loopRights = loopCheck(commitEntry, commitEntry.metas.map(_.loopAns), false.B) 115609c6f1ddSLingrui98 // val loopWrongs = loopCheck(commitEntry, commitEntry.metas.map(_.loopAns), true.B) 115709c6f1ddSLingrui98 115809c6f1ddSLingrui98 // val rasRights = rasCheck(commitEntry, commitEntry.metas.map(_.rasAns), false.B) 115909c6f1ddSLingrui98 // val rasWrongs = rasCheck(commitEntry, commitEntry.metas.map(_.rasAns), true.B) 116009c6f1ddSLingrui98 116109c6f1ddSLingrui98}