1*09c6f1ddSLingrui98/*************************************************************************************** 2*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*09c6f1ddSLingrui98* 5*09c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2. 6*09c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*09c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at: 8*09c6f1ddSLingrui98* http://license.coscl.org.cn/MulanPSL2 9*09c6f1ddSLingrui98* 10*09c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*09c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*09c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*09c6f1ddSLingrui98* 14*09c6f1ddSLingrui98* See the Mulan PSL v2 for more details. 15*09c6f1ddSLingrui98***************************************************************************************/ 16*09c6f1ddSLingrui98 17*09c6f1ddSLingrui98package xiangshan.frontend 18*09c6f1ddSLingrui98 19*09c6f1ddSLingrui98import chipsalliance.rocketchip.config.Parameters 20*09c6f1ddSLingrui98import chisel3._ 21*09c6f1ddSLingrui98import chisel3.util._ 22*09c6f1ddSLingrui98import utils.{AsyncDataModuleTemplate, CircularQueuePtr, DataModuleTemplate, HasCircularQueuePtrHelper, SRAMTemplate, SyncDataModuleTemplate, XSDebug, XSPerfAccumulate, XSError} 23*09c6f1ddSLingrui98import xiangshan._ 24*09c6f1ddSLingrui98import scala.tools.nsc.doc.model.Val 25*09c6f1ddSLingrui98import utils.{ParallelPriorityMux, ParallelPriorityEncoder} 26*09c6f1ddSLingrui98import xiangshan.backend.{CtrlToFtqIO} 27*09c6f1ddSLingrui98import firrtl.annotations.MemoryLoadFileType 28*09c6f1ddSLingrui98 29*09c6f1ddSLingrui98class FtqPtr(implicit p: Parameters) extends CircularQueuePtr[FtqPtr]( 30*09c6f1ddSLingrui98 p => p(XSCoreParamsKey).FtqSize 31*09c6f1ddSLingrui98){ 32*09c6f1ddSLingrui98 override def cloneType = (new FtqPtr).asInstanceOf[this.type] 33*09c6f1ddSLingrui98} 34*09c6f1ddSLingrui98 35*09c6f1ddSLingrui98object FtqPtr { 36*09c6f1ddSLingrui98 def apply(f: Bool, v: UInt)(implicit p: Parameters): FtqPtr = { 37*09c6f1ddSLingrui98 val ptr = Wire(new FtqPtr) 38*09c6f1ddSLingrui98 ptr.flag := f 39*09c6f1ddSLingrui98 ptr.value := v 40*09c6f1ddSLingrui98 ptr 41*09c6f1ddSLingrui98 } 42*09c6f1ddSLingrui98 def inverse(ptr: FtqPtr)(implicit p: Parameters): FtqPtr = { 43*09c6f1ddSLingrui98 apply(!ptr.flag, ptr.value) 44*09c6f1ddSLingrui98 } 45*09c6f1ddSLingrui98} 46*09c6f1ddSLingrui98 47*09c6f1ddSLingrui98class FtqNRSRAM[T <: Data](gen: T, numRead: Int)(implicit p: Parameters) extends XSModule { 48*09c6f1ddSLingrui98 49*09c6f1ddSLingrui98 val io = IO(new Bundle() { 50*09c6f1ddSLingrui98 val raddr = Input(Vec(numRead, UInt(log2Up(FtqSize).W))) 51*09c6f1ddSLingrui98 val ren = Input(Vec(numRead, Bool())) 52*09c6f1ddSLingrui98 val rdata = Output(Vec(numRead, gen)) 53*09c6f1ddSLingrui98 val waddr = Input(UInt(log2Up(FtqSize).W)) 54*09c6f1ddSLingrui98 val wen = Input(Bool()) 55*09c6f1ddSLingrui98 val wdata = Input(gen) 56*09c6f1ddSLingrui98 }) 57*09c6f1ddSLingrui98 58*09c6f1ddSLingrui98 for(i <- 0 until numRead){ 59*09c6f1ddSLingrui98 val sram = Module(new SRAMTemplate(gen, FtqSize)) 60*09c6f1ddSLingrui98 sram.io.r.req.valid := io.ren(i) 61*09c6f1ddSLingrui98 sram.io.r.req.bits.setIdx := io.raddr(i) 62*09c6f1ddSLingrui98 io.rdata(i) := sram.io.r.resp.data(0) 63*09c6f1ddSLingrui98 sram.io.w.req.valid := io.wen 64*09c6f1ddSLingrui98 sram.io.w.req.bits.setIdx := io.waddr 65*09c6f1ddSLingrui98 sram.io.w.req.bits.data := VecInit(io.wdata) 66*09c6f1ddSLingrui98 } 67*09c6f1ddSLingrui98 68*09c6f1ddSLingrui98} 69*09c6f1ddSLingrui98 70*09c6f1ddSLingrui98class Ftq_RF_Components(implicit p: Parameters) extends XSBundle with BPUUtils { 71*09c6f1ddSLingrui98 // TODO: move pftAddr, oversize, carry to another mem 72*09c6f1ddSLingrui98 val startAddr = UInt(VAddrBits.W) 73*09c6f1ddSLingrui98 val nextRangeAddr = UInt(VAddrBits.W) 74*09c6f1ddSLingrui98 val pftAddr = UInt((log2Ceil(PredictWidth)+1).W) 75*09c6f1ddSLingrui98 val isNextMask = Vec(PredictWidth, Bool()) 76*09c6f1ddSLingrui98 val oversize = Bool() 77*09c6f1ddSLingrui98 val carry = Bool() 78*09c6f1ddSLingrui98 def getPc(offset: UInt) = { 79*09c6f1ddSLingrui98 def getHigher(pc: UInt) = pc(VAddrBits-1, log2Ceil(PredictWidth)+instOffsetBits) 80*09c6f1ddSLingrui98 def getOffset(pc: UInt) = pc(log2Ceil(PredictWidth)+instOffsetBits-1, instOffsetBits) 81*09c6f1ddSLingrui98 Cat(getHigher(Mux(isNextMask(offset), nextRangeAddr, startAddr)), 82*09c6f1ddSLingrui98 getOffset(startAddr)+offset, 0.U(instOffsetBits.W)) 83*09c6f1ddSLingrui98 } 84*09c6f1ddSLingrui98 def getFallThrough() = { 85*09c6f1ddSLingrui98 getFallThroughAddr(this.startAddr, this.carry, this.pftAddr) 86*09c6f1ddSLingrui98 } 87*09c6f1ddSLingrui98 def fallThroughError() = { 88*09c6f1ddSLingrui98 !carry && startAddr(instOffsetBits+log2Ceil(PredictWidth), instOffsetBits) > pftAddr 89*09c6f1ddSLingrui98 } 90*09c6f1ddSLingrui98 def fromBranchPrediction(resp: BranchPredictionBundle) = { 91*09c6f1ddSLingrui98 this.startAddr := resp.pc 92*09c6f1ddSLingrui98 this.nextRangeAddr := resp.pc + (FetchWidth * 4).U 93*09c6f1ddSLingrui98 this.pftAddr := resp.ftb_entry.pftAddr 94*09c6f1ddSLingrui98 this.isNextMask := VecInit((0 until PredictWidth).map(i => 95*09c6f1ddSLingrui98 (resp.pc(log2Ceil(PredictWidth), 1) +& i.U)(log2Ceil(PredictWidth)).asBool() 96*09c6f1ddSLingrui98 )) 97*09c6f1ddSLingrui98 this.oversize := resp.ftb_entry.oversize 98*09c6f1ddSLingrui98 this.carry := resp.ftb_entry.carry 99*09c6f1ddSLingrui98 this 100*09c6f1ddSLingrui98 } 101*09c6f1ddSLingrui98 override def toPrintable: Printable = { 102*09c6f1ddSLingrui98 p"startAddr:${Hexadecimal(startAddr)}, fallThru:${Hexadecimal(getFallThrough())}" 103*09c6f1ddSLingrui98 } 104*09c6f1ddSLingrui98} 105*09c6f1ddSLingrui98 106*09c6f1ddSLingrui98class Ftq_pd_Entry(implicit p: Parameters) extends XSBundle { 107*09c6f1ddSLingrui98 val brMask = Vec(PredictWidth, Bool()) 108*09c6f1ddSLingrui98 val jmpInfo = ValidUndirectioned(Vec(3, Bool())) 109*09c6f1ddSLingrui98 val jmpOffset = UInt(log2Ceil(PredictWidth).W) 110*09c6f1ddSLingrui98 val jalTarget = UInt(VAddrBits.W) 111*09c6f1ddSLingrui98 val rvcMask = Vec(PredictWidth, Bool()) 112*09c6f1ddSLingrui98 def hasJal = jmpInfo.valid && !jmpInfo.bits(0) 113*09c6f1ddSLingrui98 def hasJalr = jmpInfo.valid && jmpInfo.bits(0) 114*09c6f1ddSLingrui98 def hasCall = jmpInfo.valid && jmpInfo.bits(1) 115*09c6f1ddSLingrui98 def hasRet = jmpInfo.valid && jmpInfo.bits(2) 116*09c6f1ddSLingrui98 117*09c6f1ddSLingrui98 def fromPdWb(pdWb: PredecodeWritebackBundle) = { 118*09c6f1ddSLingrui98 val pds = pdWb.pd 119*09c6f1ddSLingrui98 this.brMask := VecInit(pds.map(pd => pd.isBr && pd.valid)) 120*09c6f1ddSLingrui98 this.jmpInfo.valid := VecInit(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid)).asUInt.orR 121*09c6f1ddSLingrui98 this.jmpInfo.bits := ParallelPriorityMux(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid), 122*09c6f1ddSLingrui98 pds.map(pd => VecInit(pd.isJalr, pd.isCall, pd.isRet))) 123*09c6f1ddSLingrui98 this.jmpOffset := ParallelPriorityEncoder(pds.map(pd => (pd.isJal || pd.isJalr) && pd.valid)) 124*09c6f1ddSLingrui98 this.rvcMask := VecInit(pds.map(pd => pd.isRVC)) 125*09c6f1ddSLingrui98 this.jalTarget := pdWb.jalTarget 126*09c6f1ddSLingrui98 } 127*09c6f1ddSLingrui98 128*09c6f1ddSLingrui98 def toPd(offset: UInt) = { 129*09c6f1ddSLingrui98 require(offset.getWidth == log2Ceil(PredictWidth)) 130*09c6f1ddSLingrui98 val pd = Wire(new PreDecodeInfo) 131*09c6f1ddSLingrui98 pd.valid := true.B 132*09c6f1ddSLingrui98 pd.isRVC := rvcMask(offset) 133*09c6f1ddSLingrui98 val isBr = brMask(offset) 134*09c6f1ddSLingrui98 val isJalr = offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(0) 135*09c6f1ddSLingrui98 pd.brType := Cat(offset === jmpOffset && jmpInfo.valid, isJalr || isBr) 136*09c6f1ddSLingrui98 pd.isCall := offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(1) 137*09c6f1ddSLingrui98 pd.isRet := offset === jmpOffset && jmpInfo.valid && jmpInfo.bits(2) 138*09c6f1ddSLingrui98 pd 139*09c6f1ddSLingrui98 } 140*09c6f1ddSLingrui98} 141*09c6f1ddSLingrui98 142*09c6f1ddSLingrui98 143*09c6f1ddSLingrui98 144*09c6f1ddSLingrui98class Ftq_Redirect_SRAMEntry(implicit p: Parameters) extends XSBundle with HasBPUConst { 145*09c6f1ddSLingrui98 val rasSp = UInt(log2Ceil(RasSize).W) 146*09c6f1ddSLingrui98 val rasEntry = new RASEntry 147*09c6f1ddSLingrui98 val specCnt = Vec(numBr, UInt(10.W)) 148*09c6f1ddSLingrui98 val ghist = new GlobalHistory 149*09c6f1ddSLingrui98 val phist = UInt(PathHistoryLength.W) 150*09c6f1ddSLingrui98 val phNewBit = UInt(1.W) 151*09c6f1ddSLingrui98 152*09c6f1ddSLingrui98 def fromBranchPrediction(resp: BranchPredictionBundle) = { 153*09c6f1ddSLingrui98 this.rasSp := resp.rasSp 154*09c6f1ddSLingrui98 this.rasEntry := resp.rasTop 155*09c6f1ddSLingrui98 this.specCnt := resp.specCnt 156*09c6f1ddSLingrui98 this.ghist := resp.ghist 157*09c6f1ddSLingrui98 this.phist := resp.phist 158*09c6f1ddSLingrui98 this.phNewBit := resp.pc(instOffsetBits) 159*09c6f1ddSLingrui98 this 160*09c6f1ddSLingrui98 } 161*09c6f1ddSLingrui98} 162*09c6f1ddSLingrui98 163*09c6f1ddSLingrui98class Ftq_1R_SRAMEntry(implicit p: Parameters) extends XSBundle with HasBPUConst { 164*09c6f1ddSLingrui98 val meta = UInt(MaxMetaLength.W) 165*09c6f1ddSLingrui98} 166*09c6f1ddSLingrui98 167*09c6f1ddSLingrui98class Ftq_Pred_Info(implicit p: Parameters) extends XSBundle { 168*09c6f1ddSLingrui98 val target = UInt(VAddrBits.W) 169*09c6f1ddSLingrui98 val cfiIndex = ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)) 170*09c6f1ddSLingrui98} 171*09c6f1ddSLingrui98 172*09c6f1ddSLingrui98class FtqEntry(implicit p: Parameters) extends XSBundle with HasBPUConst { 173*09c6f1ddSLingrui98 val startAddr = UInt(VAddrBits.W) 174*09c6f1ddSLingrui98 val fallThruAddr = UInt(VAddrBits.W) 175*09c6f1ddSLingrui98 val isNextMask = Vec(PredictWidth, Bool()) 176*09c6f1ddSLingrui98 177*09c6f1ddSLingrui98 val meta = UInt(MaxMetaLength.W) 178*09c6f1ddSLingrui98 179*09c6f1ddSLingrui98 val rasSp = UInt(log2Ceil(RasSize).W) 180*09c6f1ddSLingrui98 val rasEntry = new RASEntry 181*09c6f1ddSLingrui98 val hist = new GlobalHistory 182*09c6f1ddSLingrui98 val specCnt = Vec(numBr, UInt(10.W)) 183*09c6f1ddSLingrui98 184*09c6f1ddSLingrui98 val valids = Vec(PredictWidth, Bool()) 185*09c6f1ddSLingrui98 val brMask = Vec(PredictWidth, Bool()) 186*09c6f1ddSLingrui98 // isJalr, isCall, isRet 187*09c6f1ddSLingrui98 val jmpInfo = ValidUndirectioned(Vec(3, Bool())) 188*09c6f1ddSLingrui98 val jmpOffset = UInt(log2Ceil(PredictWidth).W) 189*09c6f1ddSLingrui98 190*09c6f1ddSLingrui98 val mispredVec = Vec(PredictWidth, Bool()) 191*09c6f1ddSLingrui98 val cfiIndex = ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)) 192*09c6f1ddSLingrui98 val target = UInt(VAddrBits.W) 193*09c6f1ddSLingrui98} 194*09c6f1ddSLingrui98 195*09c6f1ddSLingrui98class FtqRead[T <: Data](private val gen: T)(implicit p: Parameters) extends XSBundle { 196*09c6f1ddSLingrui98 val ptr = Output(new FtqPtr) 197*09c6f1ddSLingrui98 val offset = Output(UInt(log2Ceil(PredictWidth).W)) 198*09c6f1ddSLingrui98 val data = Input(gen) 199*09c6f1ddSLingrui98 def apply(ptr: FtqPtr, offset: UInt) = { 200*09c6f1ddSLingrui98 this.ptr := ptr 201*09c6f1ddSLingrui98 this.offset := offset 202*09c6f1ddSLingrui98 this.data 203*09c6f1ddSLingrui98 } 204*09c6f1ddSLingrui98 override def cloneType = (new FtqRead(gen)).asInstanceOf[this.type] 205*09c6f1ddSLingrui98} 206*09c6f1ddSLingrui98 207*09c6f1ddSLingrui98 208*09c6f1ddSLingrui98class FtqToBpuIO(implicit p: Parameters) extends XSBundle { 209*09c6f1ddSLingrui98 val redirect = Valid(new BranchPredictionRedirect) 210*09c6f1ddSLingrui98 val update = Valid(new BranchPredictionUpdate) 211*09c6f1ddSLingrui98 val enq_ptr = Output(new FtqPtr) 212*09c6f1ddSLingrui98} 213*09c6f1ddSLingrui98 214*09c6f1ddSLingrui98class FtqToIfuIO(implicit p: Parameters) extends XSBundle with HasCircularQueuePtrHelper { 215*09c6f1ddSLingrui98 val req = Decoupled(new FetchRequestBundle) 216*09c6f1ddSLingrui98 val redirect = Valid(new Redirect) 217*09c6f1ddSLingrui98 val flushFromBpu = new Bundle { 218*09c6f1ddSLingrui98 // when ifu pipeline is not stalled, 219*09c6f1ddSLingrui98 // a packet from bpu s3 can reach f1 at most 220*09c6f1ddSLingrui98 val s2 = Valid(new FtqPtr) 221*09c6f1ddSLingrui98 val s3 = Valid(new FtqPtr) 222*09c6f1ddSLingrui98 def shouldFlushBy(src: Valid[FtqPtr], idx_to_flush: FtqPtr) = { 223*09c6f1ddSLingrui98 src.valid && !isAfter(src.bits, idx_to_flush) 224*09c6f1ddSLingrui98 } 225*09c6f1ddSLingrui98 def shouldFlushByStage2(idx: FtqPtr) = shouldFlushBy(s2, idx) 226*09c6f1ddSLingrui98 def shouldFlushByStage3(idx: FtqPtr) = shouldFlushBy(s3, idx) 227*09c6f1ddSLingrui98 } 228*09c6f1ddSLingrui98} 229*09c6f1ddSLingrui98 230*09c6f1ddSLingrui98trait HasBackendRedirectInfo extends HasXSParameter { 231*09c6f1ddSLingrui98 def numRedirect = exuParameters.JmpCnt + exuParameters.AluCnt + 1 232*09c6f1ddSLingrui98 def isLoadReplay(r: Valid[Redirect]) = r.bits.flushItself() 233*09c6f1ddSLingrui98} 234*09c6f1ddSLingrui98 235*09c6f1ddSLingrui98class FtqToCtrlIO(implicit p: Parameters) extends XSBundle with HasBackendRedirectInfo { 236*09c6f1ddSLingrui98 val pc_reads = Vec(1 + numRedirect + 1 + 1, Flipped(new FtqRead(UInt(VAddrBits.W)))) 237*09c6f1ddSLingrui98 val target_read = Flipped(new FtqRead(UInt(VAddrBits.W))) 238*09c6f1ddSLingrui98 def getJumpPcRead = pc_reads.head 239*09c6f1ddSLingrui98 def getRedirectPcRead = VecInit(pc_reads.tail.dropRight(2)) 240*09c6f1ddSLingrui98 def getMemPredPcRead = pc_reads.init.last 241*09c6f1ddSLingrui98 def getRoqFlushPcRead = pc_reads.last 242*09c6f1ddSLingrui98} 243*09c6f1ddSLingrui98 244*09c6f1ddSLingrui98 245*09c6f1ddSLingrui98class FTBEntryGen(implicit p: Parameters) extends XSModule with HasBackendRedirectInfo with HasBPUParameter { 246*09c6f1ddSLingrui98 val io = IO(new Bundle { 247*09c6f1ddSLingrui98 val start_addr = Input(UInt(VAddrBits.W)) 248*09c6f1ddSLingrui98 val old_entry = Input(new FTBEntry) 249*09c6f1ddSLingrui98 val pd = Input(new Ftq_pd_Entry) 250*09c6f1ddSLingrui98 val cfiIndex = Flipped(Valid(UInt(log2Ceil(PredictWidth).W))) 251*09c6f1ddSLingrui98 val target = Input(UInt(VAddrBits.W)) 252*09c6f1ddSLingrui98 val hit = Input(Bool()) 253*09c6f1ddSLingrui98 val mispredict_vec = Input(Vec(PredictWidth, Bool())) 254*09c6f1ddSLingrui98 255*09c6f1ddSLingrui98 val new_entry = Output(new FTBEntry) 256*09c6f1ddSLingrui98 val new_br_insert_pos = Output(Vec(numBr, Bool())) 257*09c6f1ddSLingrui98 val taken_mask = Output(Vec(numBr, Bool())) 258*09c6f1ddSLingrui98 val mispred_mask = Output(Vec(numBr+1, Bool())) 259*09c6f1ddSLingrui98 260*09c6f1ddSLingrui98 // for perf counters 261*09c6f1ddSLingrui98 val is_init_entry = Output(Bool()) 262*09c6f1ddSLingrui98 val is_old_entry = Output(Bool()) 263*09c6f1ddSLingrui98 val is_new_br = Output(Bool()) 264*09c6f1ddSLingrui98 val is_jalr_target_modified = Output(Bool()) 265*09c6f1ddSLingrui98 val is_always_taken_modified = Output(Bool()) 266*09c6f1ddSLingrui98 val is_br_full = Output(Bool()) 267*09c6f1ddSLingrui98 }) 268*09c6f1ddSLingrui98 269*09c6f1ddSLingrui98 // no mispredictions detected at predecode 270*09c6f1ddSLingrui98 val hit = io.hit 271*09c6f1ddSLingrui98 val pd = io.pd 272*09c6f1ddSLingrui98 273*09c6f1ddSLingrui98 val init_entry = WireInit(0.U.asTypeOf(new FTBEntry)) 274*09c6f1ddSLingrui98 275*09c6f1ddSLingrui98 276*09c6f1ddSLingrui98 val cfi_is_br = pd.brMask(io.cfiIndex.bits) && io.cfiIndex.valid 277*09c6f1ddSLingrui98 val entry_has_jmp = pd.jmpInfo.valid 278*09c6f1ddSLingrui98 val new_jmp_is_jal = entry_has_jmp && !pd.jmpInfo.bits(0) && io.cfiIndex.valid 279*09c6f1ddSLingrui98 val new_jmp_is_jalr = entry_has_jmp && pd.jmpInfo.bits(0) && io.cfiIndex.valid 280*09c6f1ddSLingrui98 val new_jmp_is_call = entry_has_jmp && pd.jmpInfo.bits(1) && io.cfiIndex.valid 281*09c6f1ddSLingrui98 val new_jmp_is_ret = entry_has_jmp && pd.jmpInfo.bits(2) && io.cfiIndex.valid 282*09c6f1ddSLingrui98 val last_jmp_rvi = entry_has_jmp && pd.jmpOffset === (PredictWidth-1).U && !pd.rvcMask.last 283*09c6f1ddSLingrui98 val last_br_rvi = cfi_is_br && io.cfiIndex.bits === (PredictWidth-1).U && !pd.rvcMask.last 284*09c6f1ddSLingrui98 285*09c6f1ddSLingrui98 val cfi_is_jal = io.cfiIndex.bits === pd.jmpOffset && new_jmp_is_jal 286*09c6f1ddSLingrui98 val cfi_is_jalr = io.cfiIndex.bits === pd.jmpOffset && new_jmp_is_jalr 287*09c6f1ddSLingrui98 288*09c6f1ddSLingrui98 def carryPos = log2Ceil(PredictWidth)+instOffsetBits+1 289*09c6f1ddSLingrui98 def getLower(pc: UInt) = pc(carryPos-1, instOffsetBits) 290*09c6f1ddSLingrui98 // if not hit, establish a new entry 291*09c6f1ddSLingrui98 init_entry.valid := true.B 292*09c6f1ddSLingrui98 // tag is left for ftb to assign 293*09c6f1ddSLingrui98 init_entry.brValids(0) := cfi_is_br 294*09c6f1ddSLingrui98 init_entry.brOffset(0) := io.cfiIndex.bits 295*09c6f1ddSLingrui98 init_entry.setByBrTarget(0, io.start_addr, io.target) 296*09c6f1ddSLingrui98 init_entry.always_taken(0) := cfi_is_br // set to always taken on init 297*09c6f1ddSLingrui98 init_entry.always_taken(1) := false.B 298*09c6f1ddSLingrui98 init_entry.jmpOffset := pd.jmpOffset 299*09c6f1ddSLingrui98 init_entry.jmpValid := new_jmp_is_jal || new_jmp_is_jalr 300*09c6f1ddSLingrui98 init_entry.setByJmpTarget(io.start_addr, Mux(cfi_is_jalr, io.target, pd.jalTarget)) 301*09c6f1ddSLingrui98 val jmpPft = getLower(io.start_addr) +& pd.jmpOffset +& Mux(pd.rvcMask(pd.jmpOffset), 1.U, 2.U) 302*09c6f1ddSLingrui98 init_entry.pftAddr := Mux(entry_has_jmp, jmpPft, getLower(io.start_addr) + ((FetchWidth*4)>>instOffsetBits).U + Mux(last_br_rvi, 1.U, 0.U)) 303*09c6f1ddSLingrui98 init_entry.carry := Mux(entry_has_jmp, jmpPft(carryPos-instOffsetBits), io.start_addr(carryPos-1)) 304*09c6f1ddSLingrui98 init_entry.isJalr := new_jmp_is_jalr 305*09c6f1ddSLingrui98 init_entry.isCall := new_jmp_is_call 306*09c6f1ddSLingrui98 init_entry.isRet := new_jmp_is_ret 307*09c6f1ddSLingrui98 init_entry.last_is_rvc := Mux(entry_has_jmp, pd.rvcMask(pd.jmpOffset), pd.rvcMask.last) 308*09c6f1ddSLingrui98 309*09c6f1ddSLingrui98 init_entry.oversize := last_br_rvi || last_jmp_rvi 310*09c6f1ddSLingrui98 311*09c6f1ddSLingrui98 // if hit, check whether a new cfi(only br is possible) is detected 312*09c6f1ddSLingrui98 val oe = io.old_entry 313*09c6f1ddSLingrui98 val br_recorded_vec = VecInit((oe.brValids zip oe.brOffset).map { 314*09c6f1ddSLingrui98 case (v, off) => v && (off === io.cfiIndex.bits) 315*09c6f1ddSLingrui98 }) 316*09c6f1ddSLingrui98 val br_recorded = br_recorded_vec.asUInt.orR 317*09c6f1ddSLingrui98 val is_new_br = cfi_is_br && !br_recorded 318*09c6f1ddSLingrui98 val br_full = oe.brValids.asUInt.andR // all slots have brs 319*09c6f1ddSLingrui98 val new_br_offset = io.cfiIndex.bits 320*09c6f1ddSLingrui98 // vec(i) means new br will be inserted BEFORE old br(i) 321*09c6f1ddSLingrui98 val new_br_insert_onehot = VecInit((0 until numBr).map{ 322*09c6f1ddSLingrui98 i => i match { 323*09c6f1ddSLingrui98 case 0 => !oe.brValids(0) || new_br_offset < oe.brOffset(0) 324*09c6f1ddSLingrui98 case idx => oe.brValids(idx-1) && new_br_offset > oe.brOffset(idx-1) && 325*09c6f1ddSLingrui98 (!oe.brValids(idx) || new_br_offset < oe.brOffset(idx)) 326*09c6f1ddSLingrui98 } 327*09c6f1ddSLingrui98 }) 328*09c6f1ddSLingrui98 329*09c6f1ddSLingrui98 val old_entry_modified = WireInit(io.old_entry) 330*09c6f1ddSLingrui98 val (new_br_lower, new_br_tar_stat) = old_entry_modified.getBrLowerStatByTarget(io.start_addr, io.target) 331*09c6f1ddSLingrui98 for (i <- 0 until numBr) { 332*09c6f1ddSLingrui98 old_entry_modified.brOffset(i) := Mux(new_br_insert_onehot(i), new_br_offset, 333*09c6f1ddSLingrui98 Mux(oe.brOffset(i) < new_br_offset, oe.brOffset(i), 334*09c6f1ddSLingrui98 (if (i != 0) oe.brOffset(i-1) else oe.brOffset(i)))) 335*09c6f1ddSLingrui98 old_entry_modified.brLowers(i) := Mux(new_br_insert_onehot(i), new_br_lower, 336*09c6f1ddSLingrui98 Mux(oe.brOffset(i) < new_br_offset, oe.brLowers(i), 337*09c6f1ddSLingrui98 (if (i != 0) oe.brLowers(i-1) else oe.brLowers(i)))) 338*09c6f1ddSLingrui98 old_entry_modified.brTarStats(i) := Mux(new_br_insert_onehot(i), new_br_tar_stat, 339*09c6f1ddSLingrui98 Mux(oe.brOffset(i) < new_br_offset, oe.brTarStats(i), 340*09c6f1ddSLingrui98 (if (i != 0) oe.brTarStats(i-1) else oe.brTarStats(i)))) 341*09c6f1ddSLingrui98 old_entry_modified.always_taken(i) := Mux(new_br_insert_onehot(i), true.B, 342*09c6f1ddSLingrui98 Mux(oe.brOffset(i) < new_br_offset, false.B, 343*09c6f1ddSLingrui98 (if (i != 0) oe.always_taken(i-1) else oe.always_taken(i)))) 344*09c6f1ddSLingrui98 } 345*09c6f1ddSLingrui98 old_entry_modified.brValids := VecInit((oe.brValids zip new_br_insert_onehot).map{case (v1, v2) => v1 || v2}) 346*09c6f1ddSLingrui98 347*09c6f1ddSLingrui98 // in this case, pft_addr should be the addrs of the last br in packet 348*09c6f1ddSLingrui98 val pft_need_to_change = is_new_br && br_full 349*09c6f1ddSLingrui98 // it should either be the given last br or the new br 350*09c6f1ddSLingrui98 when (pft_need_to_change) { 351*09c6f1ddSLingrui98 val new_pft_offset = Mux(new_br_insert_onehot.asUInt.orR, oe.brOffset.last, new_br_offset) 352*09c6f1ddSLingrui98 old_entry_modified.pftAddr := getLower(io.start_addr) + new_pft_offset 353*09c6f1ddSLingrui98 old_entry_modified.last_is_rvc := pd.rvcMask(new_pft_offset - 1.U) // TODO: fix this 354*09c6f1ddSLingrui98 old_entry_modified.carry := (getLower(io.start_addr) +& new_pft_offset).head(1).asBool 355*09c6f1ddSLingrui98 old_entry_modified.oversize := false.B 356*09c6f1ddSLingrui98 old_entry_modified.jmpValid := false.B 357*09c6f1ddSLingrui98 old_entry_modified.isCall := false.B 358*09c6f1ddSLingrui98 old_entry_modified.isRet := false.B 359*09c6f1ddSLingrui98 } 360*09c6f1ddSLingrui98 361*09c6f1ddSLingrui98 val old_entry_jmp_target_modified = WireInit(oe) 362*09c6f1ddSLingrui98 val jalr_mispredicted = cfi_is_jalr && io.mispredict_vec(io.pd.jmpOffset) 363*09c6f1ddSLingrui98 when (jalr_mispredicted) { 364*09c6f1ddSLingrui98 old_entry_jmp_target_modified.setByJmpTarget(io.start_addr, io.target) 365*09c6f1ddSLingrui98 old_entry_jmp_target_modified.always_taken := 0.U.asTypeOf(Vec(numBr, Bool())) 366*09c6f1ddSLingrui98 } 367*09c6f1ddSLingrui98 368*09c6f1ddSLingrui98 val old_entry_always_taken = WireInit(oe) 369*09c6f1ddSLingrui98 val always_taken_modified_vec = Wire(Vec(numBr, Bool())) // whether modified or not 370*09c6f1ddSLingrui98 for (i <- 0 until numBr) { 371*09c6f1ddSLingrui98 old_entry_always_taken.always_taken(i) := 372*09c6f1ddSLingrui98 oe.always_taken(i) && io.cfiIndex.valid && oe.brValids(i) && io.cfiIndex.bits === oe.brOffset(i) 373*09c6f1ddSLingrui98 always_taken_modified_vec(i) := oe.always_taken(i) && !(io.cfiIndex.valid && oe.brValids(i) && io.cfiIndex.bits === oe.brOffset(i)) 374*09c6f1ddSLingrui98 } 375*09c6f1ddSLingrui98 val always_taken_modified = always_taken_modified_vec.reduce(_||_) 376*09c6f1ddSLingrui98 377*09c6f1ddSLingrui98 378*09c6f1ddSLingrui98 379*09c6f1ddSLingrui98 val derived_from_old_entry = 380*09c6f1ddSLingrui98 Mux(is_new_br, old_entry_modified, 381*09c6f1ddSLingrui98 Mux(jalr_mispredicted, old_entry_jmp_target_modified, old_entry_always_taken)) 382*09c6f1ddSLingrui98 383*09c6f1ddSLingrui98 384*09c6f1ddSLingrui98 io.new_entry := Mux(!hit, init_entry, derived_from_old_entry) 385*09c6f1ddSLingrui98 386*09c6f1ddSLingrui98 io.new_br_insert_pos := new_br_insert_onehot 387*09c6f1ddSLingrui98 io.taken_mask := VecInit((io.new_entry.brOffset zip io.new_entry.brValids).map{ 388*09c6f1ddSLingrui98 case (off, v) => io.cfiIndex.bits === off && io.cfiIndex.valid && v 389*09c6f1ddSLingrui98 }) 390*09c6f1ddSLingrui98 for (i <- 0 until numBr) { 391*09c6f1ddSLingrui98 io.mispred_mask(i) := io.new_entry.brValids(i) && io.mispredict_vec(io.new_entry.brOffset(i)) 392*09c6f1ddSLingrui98 } 393*09c6f1ddSLingrui98 io.mispred_mask.last := io.new_entry.jmpValid && io.mispredict_vec(pd.jmpOffset) 394*09c6f1ddSLingrui98 395*09c6f1ddSLingrui98 // for perf counters 396*09c6f1ddSLingrui98 io.is_init_entry := !hit 397*09c6f1ddSLingrui98 io.is_old_entry := hit && !is_new_br && !jalr_mispredicted && !always_taken_modified 398*09c6f1ddSLingrui98 io.is_new_br := hit && is_new_br 399*09c6f1ddSLingrui98 io.is_jalr_target_modified := hit && jalr_mispredicted 400*09c6f1ddSLingrui98 io.is_always_taken_modified := hit && always_taken_modified 401*09c6f1ddSLingrui98 io.is_br_full := hit && is_new_br && br_full 402*09c6f1ddSLingrui98} 403*09c6f1ddSLingrui98 404*09c6f1ddSLingrui98class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper 405*09c6f1ddSLingrui98 with HasBackendRedirectInfo with BPUUtils with HasBPUConst { 406*09c6f1ddSLingrui98 val io = IO(new Bundle { 407*09c6f1ddSLingrui98 val fromBpu = Flipped(new BpuToFtqIO) 408*09c6f1ddSLingrui98 val fromIfu = Flipped(new IfuToFtqIO) 409*09c6f1ddSLingrui98 val fromBackend = Flipped(new CtrlToFtqIO) 410*09c6f1ddSLingrui98 411*09c6f1ddSLingrui98 val toBpu = new FtqToBpuIO 412*09c6f1ddSLingrui98 val toIfu = new FtqToIfuIO 413*09c6f1ddSLingrui98 val toBackend = new FtqToCtrlIO 414*09c6f1ddSLingrui98 415*09c6f1ddSLingrui98 val bpuInfo = new Bundle { 416*09c6f1ddSLingrui98 val bpRight = Output(UInt(XLEN.W)) 417*09c6f1ddSLingrui98 val bpWrong = Output(UInt(XLEN.W)) 418*09c6f1ddSLingrui98 } 419*09c6f1ddSLingrui98 }) 420*09c6f1ddSLingrui98 io.bpuInfo := DontCare 421*09c6f1ddSLingrui98 422*09c6f1ddSLingrui98 val roqFlush = io.fromBackend.roqFlush 423*09c6f1ddSLingrui98 val stage2Redirect = io.fromBackend.stage2Redirect 424*09c6f1ddSLingrui98 val stage3Redirect = io.fromBackend.stage3Redirect 425*09c6f1ddSLingrui98 426*09c6f1ddSLingrui98 val stage2Flush = stage2Redirect.valid || roqFlush.valid 427*09c6f1ddSLingrui98 val backendFlush = stage2Flush || RegNext(stage2Flush) 428*09c6f1ddSLingrui98 val ifuFlush = Wire(Bool()) 429*09c6f1ddSLingrui98 430*09c6f1ddSLingrui98 val flush = stage2Flush || RegNext(stage2Flush) 431*09c6f1ddSLingrui98 432*09c6f1ddSLingrui98 val allowBpuIn, allowToIfu = WireInit(false.B) 433*09c6f1ddSLingrui98 val flushToIfu = !allowToIfu 434*09c6f1ddSLingrui98 allowBpuIn := !ifuFlush && !roqFlush.valid && !stage2Redirect.valid && !stage3Redirect.valid 435*09c6f1ddSLingrui98 allowToIfu := !ifuFlush && !roqFlush.valid && !stage2Redirect.valid && !stage3Redirect.valid 436*09c6f1ddSLingrui98 437*09c6f1ddSLingrui98 val bpuPtr, ifuPtr, ifuWbPtr, commPtr = RegInit(FtqPtr(false.B, 0.U)) 438*09c6f1ddSLingrui98 val validEntries = distanceBetween(bpuPtr, commPtr) 439*09c6f1ddSLingrui98 440*09c6f1ddSLingrui98 // ********************************************************************** 441*09c6f1ddSLingrui98 // **************************** enq from bpu **************************** 442*09c6f1ddSLingrui98 // ********************************************************************** 443*09c6f1ddSLingrui98 val new_entry_ready = validEntries < FtqSize.U 444*09c6f1ddSLingrui98 io.fromBpu.resp.ready := new_entry_ready 445*09c6f1ddSLingrui98 446*09c6f1ddSLingrui98 val bpu_s2_resp = io.fromBpu.resp.bits.s2 447*09c6f1ddSLingrui98 val bpu_s3_resp = io.fromBpu.resp.bits.s3 448*09c6f1ddSLingrui98 val bpu_s2_redirect = bpu_s2_resp.valid && bpu_s2_resp.hasRedirect 449*09c6f1ddSLingrui98 val bpu_s3_redirect = bpu_s3_resp.valid && bpu_s3_resp.hasRedirect 450*09c6f1ddSLingrui98 451*09c6f1ddSLingrui98 io.toBpu.enq_ptr := bpuPtr 452*09c6f1ddSLingrui98 val enq_fire = io.fromBpu.resp.fire() && allowBpuIn // from bpu s1 453*09c6f1ddSLingrui98 val bpu_in_fire = (io.fromBpu.resp.fire() || bpu_s2_redirect || bpu_s3_redirect) && allowBpuIn 454*09c6f1ddSLingrui98 455*09c6f1ddSLingrui98 val bpu_in_resp = WireInit(io.fromBpu.resp.bits.selectedResp) 456*09c6f1ddSLingrui98 val bpu_in_stage = WireInit(io.fromBpu.resp.bits.selectedRespIdx) 457*09c6f1ddSLingrui98 val bpu_in_resp_ptr = Mux(bpu_in_stage === BP_S1, bpuPtr, bpu_in_resp.ftq_idx) 458*09c6f1ddSLingrui98 val bpu_in_resp_idx = bpu_in_resp_ptr.value 459*09c6f1ddSLingrui98 460*09c6f1ddSLingrui98 // read ports: jumpPc + redirects + loadPred + roqFlush + ifuReq1 + ifuReq2 + commitUpdate 461*09c6f1ddSLingrui98 val ftq_pc_mem = Module(new SyncDataModuleTemplate(new Ftq_RF_Components, FtqSize, 1+numRedirect+2+1+1+1, 1)) 462*09c6f1ddSLingrui98 // resp from uBTB 463*09c6f1ddSLingrui98 ftq_pc_mem.io.wen(0) := bpu_in_fire 464*09c6f1ddSLingrui98 ftq_pc_mem.io.waddr(0) := bpu_in_resp_idx 465*09c6f1ddSLingrui98 ftq_pc_mem.io.wdata(0).fromBranchPrediction(bpu_in_resp) 466*09c6f1ddSLingrui98 467*09c6f1ddSLingrui98 // ifuRedirect + backendRedirect + commit 468*09c6f1ddSLingrui98 val ftq_redirect_sram = Module(new FtqNRSRAM(new Ftq_Redirect_SRAMEntry, 1+1+1)) 469*09c6f1ddSLingrui98 // these info is intended to enq at the last stage of bpu 470*09c6f1ddSLingrui98 ftq_redirect_sram.io.wen := io.fromBpu.resp.bits.lastStage.valid 471*09c6f1ddSLingrui98 ftq_redirect_sram.io.waddr := io.fromBpu.resp.bits.lastStage.ftq_idx.value 472*09c6f1ddSLingrui98 ftq_redirect_sram.io.wdata.fromBranchPrediction(io.fromBpu.resp.bits.lastStage) 473*09c6f1ddSLingrui98 474*09c6f1ddSLingrui98 val ftq_meta_1r_sram = Module(new FtqNRSRAM(new Ftq_1R_SRAMEntry, 1)) 475*09c6f1ddSLingrui98 // these info is intended to enq at the last stage of bpu 476*09c6f1ddSLingrui98 ftq_meta_1r_sram.io.wen := io.fromBpu.resp.bits.lastStage.valid 477*09c6f1ddSLingrui98 ftq_meta_1r_sram.io.waddr := io.fromBpu.resp.bits.lastStage.ftq_idx.value 478*09c6f1ddSLingrui98 ftq_meta_1r_sram.io.wdata.meta := io.fromBpu.resp.bits.meta 479*09c6f1ddSLingrui98 // ifuRedirect + backendRedirect + commit 480*09c6f1ddSLingrui98 val ftb_entry_mem = Module(new SyncDataModuleTemplate(new FTBEntry, FtqSize, 1+1+1, 1)) 481*09c6f1ddSLingrui98 ftb_entry_mem.io.wen(0) := io.fromBpu.resp.bits.lastStage.valid 482*09c6f1ddSLingrui98 ftb_entry_mem.io.waddr(0) := io.fromBpu.resp.bits.lastStage.ftq_idx.value 483*09c6f1ddSLingrui98 ftb_entry_mem.io.wdata(0) := io.fromBpu.resp.bits.lastStage.ftb_entry 484*09c6f1ddSLingrui98 485*09c6f1ddSLingrui98 486*09c6f1ddSLingrui98 // multi-write 487*09c6f1ddSLingrui98 val update_target = Reg(Vec(FtqSize, UInt(VAddrBits.W))) 488*09c6f1ddSLingrui98 val cfiIndex_vec = Reg(Vec(FtqSize, ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))) 489*09c6f1ddSLingrui98 val mispredict_vec = Reg(Vec(FtqSize, Vec(PredictWidth, Bool()))) 490*09c6f1ddSLingrui98 val pred_stage = Reg(Vec(FtqSize, UInt(2.W))) 491*09c6f1ddSLingrui98 492*09c6f1ddSLingrui98 val c_invalid :: c_valid :: c_commited :: Nil = Enum(3) 493*09c6f1ddSLingrui98 val commitStateQueue = RegInit(VecInit(Seq.fill(FtqSize) { 494*09c6f1ddSLingrui98 VecInit(Seq.fill(PredictWidth)(c_invalid)) 495*09c6f1ddSLingrui98 })) 496*09c6f1ddSLingrui98 497*09c6f1ddSLingrui98 val f_to_send :: f_sent :: Nil = Enum(2) 498*09c6f1ddSLingrui98 val entry_fetch_status = RegInit(VecInit(Seq.fill(FtqSize)(f_sent))) 499*09c6f1ddSLingrui98 500*09c6f1ddSLingrui98 val h_not_hit :: h_false_hit :: h_hit :: Nil = Enum(3) 501*09c6f1ddSLingrui98 val entry_hit_status = RegInit(VecInit(Seq.fill(FtqSize)(h_not_hit))) 502*09c6f1ddSLingrui98 503*09c6f1ddSLingrui98 504*09c6f1ddSLingrui98 when (bpu_in_fire) { 505*09c6f1ddSLingrui98 entry_fetch_status(bpu_in_resp_idx) := f_to_send 506*09c6f1ddSLingrui98 commitStateQueue(bpu_in_resp_idx) := VecInit(Seq.fill(PredictWidth)(c_invalid)) 507*09c6f1ddSLingrui98 cfiIndex_vec(bpu_in_resp_idx) := bpu_in_resp.genCfiIndex 508*09c6f1ddSLingrui98 mispredict_vec(bpu_in_resp_idx) := WireInit(VecInit(Seq.fill(PredictWidth)(false.B))) 509*09c6f1ddSLingrui98 update_target(bpu_in_resp_idx) := bpu_in_resp.target 510*09c6f1ddSLingrui98 pred_stage(bpu_in_resp_idx) := bpu_in_stage 511*09c6f1ddSLingrui98 } 512*09c6f1ddSLingrui98 513*09c6f1ddSLingrui98 bpuPtr := bpuPtr + enq_fire 514*09c6f1ddSLingrui98 ifuPtr := ifuPtr + io.toIfu.req.fire 515*09c6f1ddSLingrui98 516*09c6f1ddSLingrui98 // only use ftb result to assign hit status 517*09c6f1ddSLingrui98 when (bpu_s2_resp.valid) { 518*09c6f1ddSLingrui98 entry_hit_status(bpu_s2_resp.ftq_idx.value) := Mux(bpu_s2_resp.preds.hit, h_hit, h_not_hit) 519*09c6f1ddSLingrui98 } 520*09c6f1ddSLingrui98 521*09c6f1ddSLingrui98 522*09c6f1ddSLingrui98 io.toIfu.flushFromBpu.s2.valid := bpu_s2_resp.valid && bpu_s2_resp.hasRedirect 523*09c6f1ddSLingrui98 io.toIfu.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx 524*09c6f1ddSLingrui98 when (bpu_s2_resp.valid && bpu_s2_resp.hasRedirect) { 525*09c6f1ddSLingrui98 bpuPtr := bpu_s2_resp.ftq_idx + 1.U 526*09c6f1ddSLingrui98 // only when ifuPtr runs ahead of bpu s2 resp should we recover it 527*09c6f1ddSLingrui98 when (!isBefore(ifuPtr, bpu_s2_resp.ftq_idx)) { 528*09c6f1ddSLingrui98 ifuPtr := bpu_s2_resp.ftq_idx 529*09c6f1ddSLingrui98 } 530*09c6f1ddSLingrui98 } 531*09c6f1ddSLingrui98 532*09c6f1ddSLingrui98 io.toIfu.flushFromBpu.s3.valid := bpu_s3_resp.valid && bpu_s3_resp.hasRedirect 533*09c6f1ddSLingrui98 io.toIfu.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx 534*09c6f1ddSLingrui98 when (bpu_s3_resp.valid && bpu_s3_resp.hasRedirect) { 535*09c6f1ddSLingrui98 bpuPtr := bpu_s3_resp.ftq_idx + 1.U 536*09c6f1ddSLingrui98 // only when ifuPtr runs ahead of bpu s2 resp should we recover it 537*09c6f1ddSLingrui98 when (!isBefore(ifuPtr, bpu_s3_resp.ftq_idx)) { 538*09c6f1ddSLingrui98 ifuPtr := bpu_s3_resp.ftq_idx 539*09c6f1ddSLingrui98 } 540*09c6f1ddSLingrui98 XSError(true.B, "\ns3_redirect mechanism not implemented!\n") 541*09c6f1ddSLingrui98 } 542*09c6f1ddSLingrui98 543*09c6f1ddSLingrui98 XSError(isBefore(bpuPtr, ifuPtr) && !isFull(bpuPtr, ifuPtr), "\nifuPtr is before bpuPtr!\n") 544*09c6f1ddSLingrui98 545*09c6f1ddSLingrui98 // **************************************************************** 546*09c6f1ddSLingrui98 // **************************** to ifu **************************** 547*09c6f1ddSLingrui98 // **************************************************************** 548*09c6f1ddSLingrui98 val bpu_in_bypass_buf = RegEnable(ftq_pc_mem.io.wdata(0), enable=bpu_in_fire) 549*09c6f1ddSLingrui98 val bpu_in_bypass_ptr = RegNext(bpu_in_resp_ptr) 550*09c6f1ddSLingrui98 val last_cycle_bpu_in = RegNext(bpu_in_fire) 551*09c6f1ddSLingrui98 val last_cycle_to_ifu_fire = RegNext(io.toIfu.req.fire) 552*09c6f1ddSLingrui98 553*09c6f1ddSLingrui98 // read pc and target 554*09c6f1ddSLingrui98 ftq_pc_mem.io.raddr.init.init.last := ifuPtr.value 555*09c6f1ddSLingrui98 ftq_pc_mem.io.raddr.init.last := (ifuPtr+1.U).value 556*09c6f1ddSLingrui98 557*09c6f1ddSLingrui98 val toIfuReq = Wire(chiselTypeOf(io.toIfu.req)) 558*09c6f1ddSLingrui98 559*09c6f1ddSLingrui98 toIfuReq.valid := allowToIfu && entry_fetch_status(ifuPtr.value) === f_to_send && ifuPtr =/= bpuPtr 560*09c6f1ddSLingrui98 toIfuReq.bits.ftqIdx := ifuPtr 561*09c6f1ddSLingrui98 toIfuReq.bits.target := update_target(ifuPtr.value) 562*09c6f1ddSLingrui98 toIfuReq.bits.ftqOffset := cfiIndex_vec(ifuPtr.value) 563*09c6f1ddSLingrui98 toIfuReq.bits.fallThruError := false.B 564*09c6f1ddSLingrui98 565*09c6f1ddSLingrui98 when (last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr) { 566*09c6f1ddSLingrui98 toIfuReq.bits.fromFtqPcBundle(bpu_in_bypass_buf) 567*09c6f1ddSLingrui98 }.elsewhen (last_cycle_to_ifu_fire) { 568*09c6f1ddSLingrui98 toIfuReq.bits.fromFtqPcBundle(ftq_pc_mem.io.rdata.init.last) 569*09c6f1ddSLingrui98 }.otherwise { 570*09c6f1ddSLingrui98 toIfuReq.bits.fromFtqPcBundle(ftq_pc_mem.io.rdata.init.init.last) 571*09c6f1ddSLingrui98 } 572*09c6f1ddSLingrui98 573*09c6f1ddSLingrui98 io.toIfu.req <> toIfuReq 574*09c6f1ddSLingrui98 575*09c6f1ddSLingrui98 // when fall through is smaller in value than start address, there must be a false hit 576*09c6f1ddSLingrui98 when (toIfuReq.bits.fallThroughError() && entry_hit_status(ifuPtr.value) === h_hit) { 577*09c6f1ddSLingrui98 when (io.toIfu.req.fire && 578*09c6f1ddSLingrui98 !(bpu_s2_redirect && bpu_s2_resp.ftq_idx === ifuPtr) && 579*09c6f1ddSLingrui98 !(bpu_s3_redirect && bpu_s3_resp.ftq_idx === ifuPtr) 580*09c6f1ddSLingrui98 ) { 581*09c6f1ddSLingrui98 entry_hit_status(ifuPtr.value) := h_false_hit 582*09c6f1ddSLingrui98 } 583*09c6f1ddSLingrui98 io.toIfu.req.bits.fallThruAddr := toIfuReq.bits.startAddr + (FetchWidth*4).U 584*09c6f1ddSLingrui98 io.toIfu.req.bits.fallThruError := true.B 585*09c6f1ddSLingrui98 XSDebug(true.B, "fallThruError! start:%x, fallThru:%x\n", toIfuReq.bits.startAddr, toIfuReq.bits.fallThruAddr) 586*09c6f1ddSLingrui98 } 587*09c6f1ddSLingrui98 588*09c6f1ddSLingrui98 val ifu_req_should_be_flushed = 589*09c6f1ddSLingrui98 io.toIfu.flushFromBpu.shouldFlushByStage2(toIfuReq.bits.ftqIdx) || 590*09c6f1ddSLingrui98 io.toIfu.flushFromBpu.shouldFlushByStage3(toIfuReq.bits.ftqIdx) 591*09c6f1ddSLingrui98 592*09c6f1ddSLingrui98 when (io.toIfu.req.fire && !ifu_req_should_be_flushed) { 593*09c6f1ddSLingrui98 entry_fetch_status(ifuPtr.value) := f_sent 594*09c6f1ddSLingrui98 } 595*09c6f1ddSLingrui98 596*09c6f1ddSLingrui98 597*09c6f1ddSLingrui98 // ********************************************************************* 598*09c6f1ddSLingrui98 // **************************** wb from ifu **************************** 599*09c6f1ddSLingrui98 // ********************************************************************* 600*09c6f1ddSLingrui98 val pdWb = io.fromIfu.pdWb 601*09c6f1ddSLingrui98 val pds = pdWb.bits.pd 602*09c6f1ddSLingrui98 val ifu_wb_valid = pdWb.valid 603*09c6f1ddSLingrui98 val ifu_wb_idx = pdWb.bits.ftqIdx.value 604*09c6f1ddSLingrui98 // read ports: commit update 605*09c6f1ddSLingrui98 val ftq_pd_mem = Module(new SyncDataModuleTemplate(new Ftq_pd_Entry, FtqSize, 1, 1)) 606*09c6f1ddSLingrui98 ftq_pd_mem.io.wen(0) := ifu_wb_valid 607*09c6f1ddSLingrui98 ftq_pd_mem.io.waddr(0) := pdWb.bits.ftqIdx.value 608*09c6f1ddSLingrui98 ftq_pd_mem.io.wdata(0).fromPdWb(pdWb.bits) 609*09c6f1ddSLingrui98 610*09c6f1ddSLingrui98 val hit_pd_valid = entry_hit_status(ifu_wb_idx) === h_hit && ifu_wb_valid 611*09c6f1ddSLingrui98 val hit_pd_mispred = hit_pd_valid && pdWb.bits.misOffset.valid 612*09c6f1ddSLingrui98 val hit_pd_mispred_reg = RegNext(hit_pd_mispred, init=false.B) 613*09c6f1ddSLingrui98 val pd_reg = RegEnable(pds, enable = pdWb.valid) 614*09c6f1ddSLingrui98 val start_pc_reg = RegEnable(pdWb.bits.pc(0), enable = pdWb.valid) 615*09c6f1ddSLingrui98 val wb_idx_reg = RegEnable(ifu_wb_idx, enable = pdWb.valid) 616*09c6f1ddSLingrui98 617*09c6f1ddSLingrui98 when (ifu_wb_valid) { 618*09c6f1ddSLingrui98 val comm_stq_wen = VecInit(pds.map(_.valid).zip(pdWb.bits.instrRange).map{ 619*09c6f1ddSLingrui98 case (v, inRange) => v && inRange 620*09c6f1ddSLingrui98 }) 621*09c6f1ddSLingrui98 (commitStateQueue(ifu_wb_idx) zip comm_stq_wen).map{ 622*09c6f1ddSLingrui98 case (qe, v) => when (v) { qe := c_valid } 623*09c6f1ddSLingrui98 } 624*09c6f1ddSLingrui98 } 625*09c6f1ddSLingrui98 626*09c6f1ddSLingrui98 ifuWbPtr := ifuWbPtr + ifu_wb_valid 627*09c6f1ddSLingrui98 628*09c6f1ddSLingrui98 ftb_entry_mem.io.raddr.head := ifu_wb_idx 629*09c6f1ddSLingrui98 val has_false_hit = WireInit(false.B) 630*09c6f1ddSLingrui98 when (RegNext(hit_pd_valid)) { 631*09c6f1ddSLingrui98 // check for false hit 632*09c6f1ddSLingrui98 val pred_ftb_entry = ftb_entry_mem.io.rdata.head 633*09c6f1ddSLingrui98 // we check cfis that bpu predicted 634*09c6f1ddSLingrui98 val br_false_hit = (pred_ftb_entry.brValids zip pred_ftb_entry.brOffset).map{ 635*09c6f1ddSLingrui98 case (v, offset) => v && !(pd_reg(offset).valid && pd_reg(offset).isBr) 636*09c6f1ddSLingrui98 }.reduce(_||_) 637*09c6f1ddSLingrui98 638*09c6f1ddSLingrui98 val jmpOffset = pred_ftb_entry.jmpOffset 639*09c6f1ddSLingrui98 val jmp_pd = pd_reg(jmpOffset) 640*09c6f1ddSLingrui98 val jal_false_hit = pred_ftb_entry.jmpValid && 641*09c6f1ddSLingrui98 ((pred_ftb_entry.isJal && !(jmp_pd.valid && jmp_pd.isJal)) || 642*09c6f1ddSLingrui98 (pred_ftb_entry.isJalr && !(jmp_pd.valid && jmp_pd.isJalr)) || 643*09c6f1ddSLingrui98 (pred_ftb_entry.isCall && !(jmp_pd.valid && jmp_pd.isCall)) || 644*09c6f1ddSLingrui98 (pred_ftb_entry.isRet && !(jmp_pd.valid && jmp_pd.isRet)) 645*09c6f1ddSLingrui98 ) 646*09c6f1ddSLingrui98 647*09c6f1ddSLingrui98 has_false_hit := br_false_hit || jal_false_hit || hit_pd_mispred_reg 648*09c6f1ddSLingrui98 } 649*09c6f1ddSLingrui98 650*09c6f1ddSLingrui98 when (has_false_hit) { 651*09c6f1ddSLingrui98 entry_hit_status(wb_idx_reg) := h_false_hit 652*09c6f1ddSLingrui98 } 653*09c6f1ddSLingrui98 654*09c6f1ddSLingrui98 655*09c6f1ddSLingrui98 // ********************************************************************** 656*09c6f1ddSLingrui98 // **************************** backend read **************************** 657*09c6f1ddSLingrui98 // ********************************************************************** 658*09c6f1ddSLingrui98 659*09c6f1ddSLingrui98 // pc reads 660*09c6f1ddSLingrui98 for ((req, i) <- io.toBackend.pc_reads.zipWithIndex) { 661*09c6f1ddSLingrui98 ftq_pc_mem.io.raddr(i) := req.ptr.value 662*09c6f1ddSLingrui98 req.data := ftq_pc_mem.io.rdata(i).getPc(RegNext(req.offset)) 663*09c6f1ddSLingrui98 } 664*09c6f1ddSLingrui98 // target read 665*09c6f1ddSLingrui98 io.toBackend.target_read.data := RegNext(update_target(io.toBackend.target_read.ptr.value)) 666*09c6f1ddSLingrui98 667*09c6f1ddSLingrui98 // ******************************************************************************* 668*09c6f1ddSLingrui98 // **************************** redirect from backend **************************** 669*09c6f1ddSLingrui98 // ******************************************************************************* 670*09c6f1ddSLingrui98 671*09c6f1ddSLingrui98 // redirect read cfiInfo, couples to redirectGen s2 672*09c6f1ddSLingrui98 ftq_redirect_sram.io.ren.init.last := io.fromBackend.stage2Redirect.valid 673*09c6f1ddSLingrui98 ftq_redirect_sram.io.raddr.init.last := io.fromBackend.stage2Redirect.bits.ftqIdx.value 674*09c6f1ddSLingrui98 675*09c6f1ddSLingrui98 ftb_entry_mem.io.raddr.init.last := io.fromBackend.stage2Redirect.bits.ftqIdx.value 676*09c6f1ddSLingrui98 677*09c6f1ddSLingrui98 val stage3CfiInfo = ftq_redirect_sram.io.rdata.init.last 678*09c6f1ddSLingrui98 val fromBackendRedirect = WireInit(io.fromBackend.stage3Redirect) 679*09c6f1ddSLingrui98 val backendRedirectCfi = fromBackendRedirect.bits.cfiUpdate 680*09c6f1ddSLingrui98 backendRedirectCfi.fromFtqRedirectSram(stage3CfiInfo) 681*09c6f1ddSLingrui98 682*09c6f1ddSLingrui98 val r_ftb_entry = ftb_entry_mem.io.rdata.init.last 683*09c6f1ddSLingrui98 val r_ftqOffset = fromBackendRedirect.bits.ftqOffset 684*09c6f1ddSLingrui98 685*09c6f1ddSLingrui98 when (entry_hit_status(fromBackendRedirect.bits.ftqIdx.value) === h_hit) { 686*09c6f1ddSLingrui98 backendRedirectCfi.shift := PopCount(r_ftb_entry.getBrMaskByOffset(r_ftqOffset)) +& 687*09c6f1ddSLingrui98 (backendRedirectCfi.pd.isBr && !r_ftb_entry.brIsSaved(r_ftqOffset) && 688*09c6f1ddSLingrui98 !(r_ftb_entry.brValids(numBr-1) && r_ftqOffset > r_ftb_entry.brOffset(numBr-1))) 689*09c6f1ddSLingrui98 690*09c6f1ddSLingrui98 backendRedirectCfi.addIntoHist := backendRedirectCfi.pd.isBr && (r_ftb_entry.brIsSaved(r_ftqOffset) || 691*09c6f1ddSLingrui98 !(r_ftb_entry.brValids(numBr-1) && r_ftqOffset > r_ftb_entry.brOffset(numBr-1))) 692*09c6f1ddSLingrui98 }.otherwise { 693*09c6f1ddSLingrui98 backendRedirectCfi.shift := (backendRedirectCfi.pd.isBr && backendRedirectCfi.taken).asUInt 694*09c6f1ddSLingrui98 backendRedirectCfi.addIntoHist := backendRedirectCfi.pd.isBr.asUInt 695*09c6f1ddSLingrui98 } 696*09c6f1ddSLingrui98 697*09c6f1ddSLingrui98 698*09c6f1ddSLingrui98 // *************************************************************************** 699*09c6f1ddSLingrui98 // **************************** redirect from ifu **************************** 700*09c6f1ddSLingrui98 // *************************************************************************** 701*09c6f1ddSLingrui98 val fromIfuRedirect = WireInit(0.U.asTypeOf(Valid(new Redirect))) 702*09c6f1ddSLingrui98 fromIfuRedirect.valid := pdWb.valid && pdWb.bits.misOffset.valid && !backendFlush 703*09c6f1ddSLingrui98 fromIfuRedirect.bits.ftqIdx := pdWb.bits.ftqIdx 704*09c6f1ddSLingrui98 fromIfuRedirect.bits.ftqOffset := pdWb.bits.misOffset.bits 705*09c6f1ddSLingrui98 fromIfuRedirect.bits.level := RedirectLevel.flushAfter 706*09c6f1ddSLingrui98 707*09c6f1ddSLingrui98 val ifuRedirectCfiUpdate = fromIfuRedirect.bits.cfiUpdate 708*09c6f1ddSLingrui98 ifuRedirectCfiUpdate.pc := pdWb.bits.pc(pdWb.bits.misOffset.bits) 709*09c6f1ddSLingrui98 ifuRedirectCfiUpdate.pd := pdWb.bits.pd(pdWb.bits.misOffset.bits) 710*09c6f1ddSLingrui98 ifuRedirectCfiUpdate.predTaken := cfiIndex_vec(pdWb.bits.ftqIdx.value).valid 711*09c6f1ddSLingrui98 ifuRedirectCfiUpdate.target := pdWb.bits.target 712*09c6f1ddSLingrui98 ifuRedirectCfiUpdate.taken := pdWb.bits.cfiOffset.valid 713*09c6f1ddSLingrui98 ifuRedirectCfiUpdate.isMisPred := pdWb.bits.misOffset.valid 714*09c6f1ddSLingrui98 715*09c6f1ddSLingrui98 val ifuRedirectReg = RegNext(fromIfuRedirect, init=0.U.asTypeOf(Valid(new Redirect))) 716*09c6f1ddSLingrui98 val ifuRedirectToBpu = WireInit(ifuRedirectReg) 717*09c6f1ddSLingrui98 ifuFlush := fromIfuRedirect.valid || ifuRedirectToBpu.valid 718*09c6f1ddSLingrui98 719*09c6f1ddSLingrui98 ftq_redirect_sram.io.ren.head := fromIfuRedirect.valid 720*09c6f1ddSLingrui98 ftq_redirect_sram.io.raddr.head := fromIfuRedirect.bits.ftqIdx.value 721*09c6f1ddSLingrui98 722*09c6f1ddSLingrui98 ftb_entry_mem.io.raddr.head := fromIfuRedirect.bits.ftqIdx.value 723*09c6f1ddSLingrui98 724*09c6f1ddSLingrui98 val toBpuCfi = ifuRedirectToBpu.bits.cfiUpdate 725*09c6f1ddSLingrui98 toBpuCfi.fromFtqRedirectSram(ftq_redirect_sram.io.rdata.head) 726*09c6f1ddSLingrui98 when (ifuRedirectReg.bits.cfiUpdate.pd.isRet) { 727*09c6f1ddSLingrui98 toBpuCfi.target := toBpuCfi.rasEntry.retAddr 728*09c6f1ddSLingrui98 } 729*09c6f1ddSLingrui98 730*09c6f1ddSLingrui98 // ********************************************************************* 731*09c6f1ddSLingrui98 // **************************** wb from exu **************************** 732*09c6f1ddSLingrui98 // ********************************************************************* 733*09c6f1ddSLingrui98 734*09c6f1ddSLingrui98 def extractRedirectInfo(wb: Valid[Redirect]) = { 735*09c6f1ddSLingrui98 val ftqIdx = wb.bits.ftqIdx.value 736*09c6f1ddSLingrui98 val ftqOffset = wb.bits.ftqOffset 737*09c6f1ddSLingrui98 val taken = wb.bits.cfiUpdate.taken 738*09c6f1ddSLingrui98 val mispred = wb.bits.cfiUpdate.isMisPred 739*09c6f1ddSLingrui98 (wb.valid, ftqIdx, ftqOffset, taken, mispred) 740*09c6f1ddSLingrui98 } 741*09c6f1ddSLingrui98 742*09c6f1ddSLingrui98 // fix mispredict entry 743*09c6f1ddSLingrui98 val lastIsMispredict = RegNext( 744*09c6f1ddSLingrui98 stage2Redirect.valid && stage2Redirect.bits.level === RedirectLevel.flushAfter, init = false.B 745*09c6f1ddSLingrui98 ) 746*09c6f1ddSLingrui98 747*09c6f1ddSLingrui98 def updateCfiInfo(redirect: Valid[Redirect], isBackend: Boolean = true) = { 748*09c6f1ddSLingrui98 val (r_valid, r_idx, r_offset, r_taken, r_mispred) = extractRedirectInfo(redirect) 749*09c6f1ddSLingrui98 val cfiIndex_bits_wen = r_valid && r_taken && r_offset < cfiIndex_vec(r_idx).bits 750*09c6f1ddSLingrui98 val cfiIndex_valid_wen = r_valid && r_offset === cfiIndex_vec(r_idx).bits 751*09c6f1ddSLingrui98 when (cfiIndex_bits_wen || cfiIndex_valid_wen) { 752*09c6f1ddSLingrui98 cfiIndex_vec(r_idx).valid := cfiIndex_bits_wen || cfiIndex_valid_wen && r_taken 753*09c6f1ddSLingrui98 } 754*09c6f1ddSLingrui98 when (cfiIndex_bits_wen) { 755*09c6f1ddSLingrui98 cfiIndex_vec(r_idx).bits := r_offset 756*09c6f1ddSLingrui98 } 757*09c6f1ddSLingrui98 update_target(r_idx) := redirect.bits.cfiUpdate.target 758*09c6f1ddSLingrui98 if (isBackend) { 759*09c6f1ddSLingrui98 mispredict_vec(r_idx)(r_offset) := r_mispred 760*09c6f1ddSLingrui98 } 761*09c6f1ddSLingrui98 } 762*09c6f1ddSLingrui98 763*09c6f1ddSLingrui98 when(stage3Redirect.valid && lastIsMispredict) { 764*09c6f1ddSLingrui98 updateCfiInfo(stage3Redirect) 765*09c6f1ddSLingrui98 }.elsewhen (ifuRedirectToBpu.valid) { 766*09c6f1ddSLingrui98 updateCfiInfo(ifuRedirectToBpu, isBackend=false) 767*09c6f1ddSLingrui98 } 768*09c6f1ddSLingrui98 769*09c6f1ddSLingrui98 // *********************************************************************************** 770*09c6f1ddSLingrui98 // **************************** flush ptr and state queue **************************** 771*09c6f1ddSLingrui98 // *********************************************************************************** 772*09c6f1ddSLingrui98 773*09c6f1ddSLingrui98 class RedirectInfo extends Bundle { 774*09c6f1ddSLingrui98 val valid = Bool() 775*09c6f1ddSLingrui98 val ftqIdx = new FtqPtr 776*09c6f1ddSLingrui98 val ftqOffset = UInt(4.W) 777*09c6f1ddSLingrui98 val flushItSelf = Bool() 778*09c6f1ddSLingrui98 def apply(redirect: Valid[Redirect]) = { 779*09c6f1ddSLingrui98 this.valid := redirect.valid 780*09c6f1ddSLingrui98 this.ftqIdx := redirect.bits.ftqIdx 781*09c6f1ddSLingrui98 this.ftqOffset := redirect.bits.ftqOffset 782*09c6f1ddSLingrui98 this.flushItSelf := RedirectLevel.flushItself(redirect.bits.level) 783*09c6f1ddSLingrui98 this 784*09c6f1ddSLingrui98 } 785*09c6f1ddSLingrui98 } 786*09c6f1ddSLingrui98 val redirectVec = Wire(Vec(3, new RedirectInfo)) 787*09c6f1ddSLingrui98 val roqRedirect = Wire(Valid(new Redirect)) 788*09c6f1ddSLingrui98 roqRedirect := DontCare 789*09c6f1ddSLingrui98 roqRedirect.valid := roqFlush.valid 790*09c6f1ddSLingrui98 roqRedirect.bits.ftqIdx := roqFlush.bits.ftqIdx 791*09c6f1ddSLingrui98 roqRedirect.bits.ftqOffset := roqFlush.bits.ftqOffset 792*09c6f1ddSLingrui98 roqRedirect.bits.level := RedirectLevel.flush 793*09c6f1ddSLingrui98 794*09c6f1ddSLingrui98 redirectVec.zip(Seq(roqRedirect, stage2Redirect, fromIfuRedirect)).map { 795*09c6f1ddSLingrui98 case (ve, r) => ve(r) 796*09c6f1ddSLingrui98 } 797*09c6f1ddSLingrui98 798*09c6f1ddSLingrui98 // when redirect, we should reset ptrs and status queues 799*09c6f1ddSLingrui98 when(redirectVec.map(r => r.valid).reduce(_||_)){ 800*09c6f1ddSLingrui98 val r = PriorityMux(redirectVec.map(r => (r.valid -> r))) 801*09c6f1ddSLingrui98 val notIfu = redirectVec.dropRight(1).map(r => r.valid).reduce(_||_) 802*09c6f1ddSLingrui98 val (idx, offset, flushItSelf) = (r.ftqIdx, r.ftqOffset, r.flushItSelf) 803*09c6f1ddSLingrui98 val next = idx + 1.U 804*09c6f1ddSLingrui98 bpuPtr := next 805*09c6f1ddSLingrui98 ifuPtr := next 806*09c6f1ddSLingrui98 ifuWbPtr := next 807*09c6f1ddSLingrui98 when (notIfu) { 808*09c6f1ddSLingrui98 commitStateQueue(idx.value).zipWithIndex.foreach({ case (s, i) => 809*09c6f1ddSLingrui98 when(i.U > offset || i.U === offset && flushItSelf){ 810*09c6f1ddSLingrui98 s := c_invalid 811*09c6f1ddSLingrui98 } 812*09c6f1ddSLingrui98 }) 813*09c6f1ddSLingrui98 } 814*09c6f1ddSLingrui98 } 815*09c6f1ddSLingrui98 816*09c6f1ddSLingrui98 // only the valid bit is actually needed 817*09c6f1ddSLingrui98 io.toIfu.redirect := DontCare 818*09c6f1ddSLingrui98 io.toIfu.redirect.valid := stage2Flush 819*09c6f1ddSLingrui98 820*09c6f1ddSLingrui98 // commit 821*09c6f1ddSLingrui98 for (c <- io.fromBackend.roq_commits) { 822*09c6f1ddSLingrui98 when(c.valid) { 823*09c6f1ddSLingrui98 commitStateQueue(c.bits.ftqIdx.value)(c.bits.ftqOffset) := c_commited 824*09c6f1ddSLingrui98 } 825*09c6f1ddSLingrui98 } 826*09c6f1ddSLingrui98 827*09c6f1ddSLingrui98 // **************************************************************** 828*09c6f1ddSLingrui98 // **************************** to bpu **************************** 829*09c6f1ddSLingrui98 // **************************************************************** 830*09c6f1ddSLingrui98 831*09c6f1ddSLingrui98 io.toBpu.redirect <> Mux(fromBackendRedirect.valid, fromBackendRedirect, ifuRedirectToBpu) 832*09c6f1ddSLingrui98 833*09c6f1ddSLingrui98 val canCommit = commPtr =/= ifuWbPtr && 834*09c6f1ddSLingrui98 Cat(commitStateQueue(commPtr.value).map(s => { 835*09c6f1ddSLingrui98 s === c_invalid || s === c_commited 836*09c6f1ddSLingrui98 })).andR() 837*09c6f1ddSLingrui98 838*09c6f1ddSLingrui98 // commit reads 839*09c6f1ddSLingrui98 ftq_pc_mem.io.raddr.last := commPtr.value 840*09c6f1ddSLingrui98 val commit_pc_bundle = ftq_pc_mem.io.rdata.last 841*09c6f1ddSLingrui98 ftq_pd_mem.io.raddr.last := commPtr.value 842*09c6f1ddSLingrui98 val commit_pd = ftq_pd_mem.io.rdata.last 843*09c6f1ddSLingrui98 ftq_redirect_sram.io.ren.last := canCommit 844*09c6f1ddSLingrui98 ftq_redirect_sram.io.raddr.last := commPtr.value 845*09c6f1ddSLingrui98 val commit_spec_meta = ftq_redirect_sram.io.rdata.last 846*09c6f1ddSLingrui98 ftq_meta_1r_sram.io.ren(0) := canCommit 847*09c6f1ddSLingrui98 ftq_meta_1r_sram.io.raddr(0) := commPtr.value 848*09c6f1ddSLingrui98 val commit_meta = ftq_meta_1r_sram.io.rdata(0) 849*09c6f1ddSLingrui98 ftb_entry_mem.io.raddr.last := commPtr.value 850*09c6f1ddSLingrui98 val commit_ftb_entry = ftb_entry_mem.io.rdata.last 851*09c6f1ddSLingrui98 852*09c6f1ddSLingrui98 // need one cycle to read mem and srams 853*09c6f1ddSLingrui98 val do_commit = RegNext(canCommit, init=false.B) 854*09c6f1ddSLingrui98 val do_commit_ptr = RegNext(commPtr) 855*09c6f1ddSLingrui98 when (canCommit) { commPtr := commPtr + 1.U } 856*09c6f1ddSLingrui98 val commit_state = RegNext(commitStateQueue(commPtr.value)) 857*09c6f1ddSLingrui98 val commit_cfi = WireInit(RegNext(cfiIndex_vec(commPtr.value))) 858*09c6f1ddSLingrui98 when (commit_state(commit_cfi.bits) =/= c_commited) { 859*09c6f1ddSLingrui98 commit_cfi.valid := false.B 860*09c6f1ddSLingrui98 } 861*09c6f1ddSLingrui98 862*09c6f1ddSLingrui98 val commit_mispredict = VecInit((RegNext(mispredict_vec(commPtr.value)) zip commit_state).map { 863*09c6f1ddSLingrui98 case (mis, state) => mis && state === c_commited 864*09c6f1ddSLingrui98 }) 865*09c6f1ddSLingrui98 val commit_hit = RegNext(entry_hit_status(commPtr.value)) 866*09c6f1ddSLingrui98 val commit_target = RegNext(update_target(commPtr.value)) 867*09c6f1ddSLingrui98 val commit_valid = commit_hit === h_hit || commit_cfi.valid // hit or taken 868*09c6f1ddSLingrui98 869*09c6f1ddSLingrui98 870*09c6f1ddSLingrui98 io.toBpu.update := DontCare 871*09c6f1ddSLingrui98 io.toBpu.update.valid := commit_valid && do_commit 872*09c6f1ddSLingrui98 val update = io.toBpu.update.bits 873*09c6f1ddSLingrui98 update.false_hit := commit_hit === h_false_hit 874*09c6f1ddSLingrui98 update.pc := commit_pc_bundle.startAddr 875*09c6f1ddSLingrui98 update.preds.hit := commit_hit === h_hit || commit_hit === h_false_hit 876*09c6f1ddSLingrui98 update.meta := commit_meta.meta 877*09c6f1ddSLingrui98 update.fromFtqRedirectSram(commit_spec_meta) 878*09c6f1ddSLingrui98 879*09c6f1ddSLingrui98 val commit_real_hit = commit_hit === h_hit 880*09c6f1ddSLingrui98 val update_ftb_entry = update.ftb_entry 881*09c6f1ddSLingrui98 882*09c6f1ddSLingrui98 val ftbEntryGen = Module(new FTBEntryGen).io 883*09c6f1ddSLingrui98 ftbEntryGen.start_addr := commit_pc_bundle.startAddr 884*09c6f1ddSLingrui98 ftbEntryGen.old_entry := commit_ftb_entry 885*09c6f1ddSLingrui98 ftbEntryGen.pd := commit_pd 886*09c6f1ddSLingrui98 ftbEntryGen.cfiIndex := commit_cfi 887*09c6f1ddSLingrui98 ftbEntryGen.target := commit_target 888*09c6f1ddSLingrui98 ftbEntryGen.hit := commit_real_hit 889*09c6f1ddSLingrui98 ftbEntryGen.mispredict_vec := commit_mispredict 890*09c6f1ddSLingrui98 891*09c6f1ddSLingrui98 update_ftb_entry := ftbEntryGen.new_entry 892*09c6f1ddSLingrui98 update.new_br_insert_pos := ftbEntryGen.new_br_insert_pos 893*09c6f1ddSLingrui98 update.mispred_mask := ftbEntryGen.mispred_mask 894*09c6f1ddSLingrui98 update.old_entry := ftbEntryGen.is_old_entry 895*09c6f1ddSLingrui98 update.preds.taken_mask := ftbEntryGen.taken_mask 896*09c6f1ddSLingrui98 897*09c6f1ddSLingrui98 // ****************************************************************************** 898*09c6f1ddSLingrui98 // **************************** commit perf counters **************************** 899*09c6f1ddSLingrui98 // ****************************************************************************** 900*09c6f1ddSLingrui98 901*09c6f1ddSLingrui98 val commit_inst_mask = VecInit(commit_state.map(c => c === c_commited && do_commit)).asUInt 902*09c6f1ddSLingrui98 val commit_mispred_mask = commit_mispredict.asUInt 903*09c6f1ddSLingrui98 val commit_not_mispred_mask = ~commit_mispred_mask 904*09c6f1ddSLingrui98 905*09c6f1ddSLingrui98 val commit_br_mask = commit_pd.brMask.asUInt 906*09c6f1ddSLingrui98 val commit_jmp_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.jmpInfo.valid.asTypeOf(UInt(1.W))) 907*09c6f1ddSLingrui98 val commit_cfi_mask = (commit_br_mask | commit_jmp_mask) 908*09c6f1ddSLingrui98 909*09c6f1ddSLingrui98 val mbpInstrs = commit_inst_mask & commit_cfi_mask 910*09c6f1ddSLingrui98 911*09c6f1ddSLingrui98 val mbpRights = mbpInstrs & commit_not_mispred_mask 912*09c6f1ddSLingrui98 val mbpWrongs = mbpInstrs & commit_mispred_mask 913*09c6f1ddSLingrui98 914*09c6f1ddSLingrui98 io.bpuInfo.bpRight := PopCount(mbpRights) 915*09c6f1ddSLingrui98 io.bpuInfo.bpWrong := PopCount(mbpWrongs) 916*09c6f1ddSLingrui98 917*09c6f1ddSLingrui98 // Cfi Info 918*09c6f1ddSLingrui98 for (i <- 0 until PredictWidth) { 919*09c6f1ddSLingrui98 val pc = commit_pc_bundle.startAddr + (i * instBytes).U 920*09c6f1ddSLingrui98 val v = commit_state(i) === c_commited 921*09c6f1ddSLingrui98 val isBr = commit_pd.brMask(i) 922*09c6f1ddSLingrui98 val isJmp = commit_pd.jmpInfo.valid && commit_pd.jmpOffset === i.U 923*09c6f1ddSLingrui98 val isCfi = isBr || isJmp 924*09c6f1ddSLingrui98 val isTaken = commit_cfi.valid && commit_cfi.bits === i.U 925*09c6f1ddSLingrui98 val misPred = commit_mispredict(i) 926*09c6f1ddSLingrui98 val ghist = commit_spec_meta.ghist.predHist 927*09c6f1ddSLingrui98 val predCycle = commit_meta.meta(63, 0) 928*09c6f1ddSLingrui98 val target = commit_target 929*09c6f1ddSLingrui98 930*09c6f1ddSLingrui98 val brIdx = OHToUInt(Reverse(Cat(update_ftb_entry.brValids.zip(update_ftb_entry.brOffset).map{case(v, offset) => v && offset === i.U}))) 931*09c6f1ddSLingrui98 val inFtbEntry = update_ftb_entry.brValids.zip(update_ftb_entry.brOffset).map{case(v, offset) => v && offset === i.U}.reduce(_||_) 932*09c6f1ddSLingrui98 val addIntoHist = ((commit_hit === h_hit) && inFtbEntry) || ((!(commit_hit === h_hit) && i.U === commit_cfi.bits && isBr && commit_cfi.valid)) 933*09c6f1ddSLingrui98 XSDebug(v && do_commit && isCfi, p"cfi_update: isBr(${isBr}) pc(${Hexadecimal(pc)}) " + 934*09c6f1ddSLingrui98 p"taken(${isTaken}) mispred(${misPred}) cycle($predCycle) hist(${Hexadecimal(ghist)}) " + 935*09c6f1ddSLingrui98 p"startAddr(${Hexadecimal(commit_pc_bundle.startAddr)}) AddIntoHist(${addIntoHist}) " + 936*09c6f1ddSLingrui98 p"brInEntry(${inFtbEntry}) brIdx(${brIdx}) target(${Hexadecimal(target)})\n") 937*09c6f1ddSLingrui98 } 938*09c6f1ddSLingrui98 939*09c6f1ddSLingrui98 val enq = io.fromBpu.resp 940*09c6f1ddSLingrui98 val perf_redirect = io.fromBackend.stage2Redirect 941*09c6f1ddSLingrui98 942*09c6f1ddSLingrui98 XSPerfAccumulate("entry", validEntries) 943*09c6f1ddSLingrui98 XSPerfAccumulate("bpu_to_ftq_stall", enq.valid && !enq.ready) 944*09c6f1ddSLingrui98 XSPerfAccumulate("mispredictRedirect", perf_redirect.valid && RedirectLevel.flushAfter === perf_redirect.bits.level) 945*09c6f1ddSLingrui98 XSPerfAccumulate("replayRedirect", perf_redirect.valid && RedirectLevel.flushItself(perf_redirect.bits.level)) 946*09c6f1ddSLingrui98 XSPerfAccumulate("predecodeRedirect", fromIfuRedirect.valid) 947*09c6f1ddSLingrui98 948*09c6f1ddSLingrui98 XSPerfAccumulate("to_ifu_bubble", io.toIfu.req.ready && !io.toIfu.req.valid) 949*09c6f1ddSLingrui98 950*09c6f1ddSLingrui98 XSPerfAccumulate("to_ifu_stall", io.toIfu.req.valid && !io.toIfu.req.ready) 951*09c6f1ddSLingrui98 XSPerfAccumulate("from_bpu_real_bubble", !enq.valid && enq.ready && allowBpuIn) 952*09c6f1ddSLingrui98 953*09c6f1ddSLingrui98 val from_bpu = io.fromBpu.resp.bits 954*09c6f1ddSLingrui98 def in_entry_len_map_gen(resp: BranchPredictionBundle)(stage: String) = { 955*09c6f1ddSLingrui98 val entry_len = (resp.ftb_entry.getFallThrough(resp.pc) - resp.pc) >> instOffsetBits 956*09c6f1ddSLingrui98 val entry_len_recording_vec = (1 to PredictWidth+1).map(i => entry_len === i.U) 957*09c6f1ddSLingrui98 val entry_len_map = (1 to PredictWidth+1).map(i => 958*09c6f1ddSLingrui98 f"${stage}_ftb_entry_len_$i" -> (entry_len_recording_vec(i-1) && resp.valid) 959*09c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 960*09c6f1ddSLingrui98 entry_len_map 961*09c6f1ddSLingrui98 } 962*09c6f1ddSLingrui98 val s1_entry_len_map = in_entry_len_map_gen(from_bpu.s1)("s1") 963*09c6f1ddSLingrui98 val s2_entry_len_map = in_entry_len_map_gen(from_bpu.s2)("s2") 964*09c6f1ddSLingrui98 val s3_entry_len_map = in_entry_len_map_gen(from_bpu.s3)("s3") 965*09c6f1ddSLingrui98 966*09c6f1ddSLingrui98 val to_ifu = io.toIfu.req.bits 967*09c6f1ddSLingrui98 val to_ifu_entry_len = (to_ifu.fallThruAddr - to_ifu.startAddr) >> instOffsetBits 968*09c6f1ddSLingrui98 val to_ifu_entry_len_recording_vec = (1 to PredictWidth+1).map(i => to_ifu_entry_len === i.U) 969*09c6f1ddSLingrui98 val to_ifu_entry_len_map = (1 to PredictWidth+1).map(i => 970*09c6f1ddSLingrui98 f"to_ifu_ftb_entry_len_$i" -> (to_ifu_entry_len_recording_vec(i-1) && io.toIfu.req.fire) 971*09c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 972*09c6f1ddSLingrui98 973*09c6f1ddSLingrui98 974*09c6f1ddSLingrui98 975*09c6f1ddSLingrui98 val commit_num_inst_recording_vec = (1 to PredictWidth).map(i => PopCount(commit_inst_mask) === i.U) 976*09c6f1ddSLingrui98 val commit_num_inst_map = (1 to PredictWidth).map(i => 977*09c6f1ddSLingrui98 f"commit_num_inst_$i" -> (commit_num_inst_recording_vec(i-1) && do_commit) 978*09c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 979*09c6f1ddSLingrui98 980*09c6f1ddSLingrui98 981*09c6f1ddSLingrui98 982*09c6f1ddSLingrui98 val commit_jal_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasJal.asTypeOf(UInt(1.W))) 983*09c6f1ddSLingrui98 val commit_jalr_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasJalr.asTypeOf(UInt(1.W))) 984*09c6f1ddSLingrui98 val commit_call_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasCall.asTypeOf(UInt(1.W))) 985*09c6f1ddSLingrui98 val commit_ret_mask = UIntToOH(commit_pd.jmpOffset) & Fill(PredictWidth, commit_pd.hasRet.asTypeOf(UInt(1.W))) 986*09c6f1ddSLingrui98 987*09c6f1ddSLingrui98 988*09c6f1ddSLingrui98 val mbpBRights = mbpRights & commit_br_mask 989*09c6f1ddSLingrui98 val mbpJRights = mbpRights & commit_jal_mask 990*09c6f1ddSLingrui98 val mbpIRights = mbpRights & commit_jalr_mask 991*09c6f1ddSLingrui98 val mbpCRights = mbpRights & commit_call_mask 992*09c6f1ddSLingrui98 val mbpRRights = mbpRights & commit_ret_mask 993*09c6f1ddSLingrui98 994*09c6f1ddSLingrui98 val mbpBWrongs = mbpWrongs & commit_br_mask 995*09c6f1ddSLingrui98 val mbpJWrongs = mbpWrongs & commit_jal_mask 996*09c6f1ddSLingrui98 val mbpIWrongs = mbpWrongs & commit_jalr_mask 997*09c6f1ddSLingrui98 val mbpCWrongs = mbpWrongs & commit_call_mask 998*09c6f1ddSLingrui98 val mbpRWrongs = mbpWrongs & commit_ret_mask 999*09c6f1ddSLingrui98 1000*09c6f1ddSLingrui98 val update_valid = io.toBpu.update.valid 1001*09c6f1ddSLingrui98 def u(cond: Bool) = update_valid && cond 1002*09c6f1ddSLingrui98 val ftb_false_hit = u(update.false_hit) 1003*09c6f1ddSLingrui98 val ftb_hit = u(commit_hit === h_hit) 1004*09c6f1ddSLingrui98 1005*09c6f1ddSLingrui98 val ftb_new_entry = u(ftbEntryGen.is_init_entry) 1006*09c6f1ddSLingrui98 val ftb_new_entry_only_br = ftb_new_entry && !update.ftb_entry.jmpValid 1007*09c6f1ddSLingrui98 val ftb_new_entry_only_jmp = ftb_new_entry && !update.ftb_entry.brValids(0) 1008*09c6f1ddSLingrui98 val ftb_new_entry_has_br_and_jmp = ftb_new_entry && update.ftb_entry.brValids(0) && update.ftb_entry.jmpValid 1009*09c6f1ddSLingrui98 1010*09c6f1ddSLingrui98 val ftb_old_entry = u(ftbEntryGen.is_old_entry) 1011*09c6f1ddSLingrui98 1012*09c6f1ddSLingrui98 val ftb_modified_entry = u(ftbEntryGen.is_new_br || ftbEntryGen.is_jalr_target_modified || ftbEntryGen.is_always_taken_modified) 1013*09c6f1ddSLingrui98 val ftb_modified_entry_new_br = u(ftbEntryGen.is_new_br) 1014*09c6f1ddSLingrui98 val ftb_modified_entry_jalr_target_modified = u(ftbEntryGen.is_jalr_target_modified) 1015*09c6f1ddSLingrui98 val ftb_modified_entry_br_full = ftb_modified_entry && ftbEntryGen.is_br_full 1016*09c6f1ddSLingrui98 val ftb_modified_entry_always_taken = ftb_modified_entry && ftbEntryGen.is_always_taken_modified 1017*09c6f1ddSLingrui98 1018*09c6f1ddSLingrui98 val ftb_entry_len = (ftbEntryGen.new_entry.getFallThrough(update.pc) - update.pc) >> instOffsetBits 1019*09c6f1ddSLingrui98 val ftb_entry_len_recording_vec = (1 to PredictWidth+1).map(i => ftb_entry_len === i.U) 1020*09c6f1ddSLingrui98 val ftb_init_entry_len_map = (1 to PredictWidth+1).map(i => 1021*09c6f1ddSLingrui98 f"ftb_init_entry_len_$i" -> (ftb_entry_len_recording_vec(i-1) && ftb_new_entry) 1022*09c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 1023*09c6f1ddSLingrui98 val ftb_modified_entry_len_map = (1 to PredictWidth+1).map(i => 1024*09c6f1ddSLingrui98 f"ftb_modified_entry_len_$i" -> (ftb_entry_len_recording_vec(i-1) && ftb_modified_entry) 1025*09c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 1026*09c6f1ddSLingrui98 1027*09c6f1ddSLingrui98 val ftq_occupancy_map = (0 to FtqSize).map(i => 1028*09c6f1ddSLingrui98 f"ftq_has_entry_$i" ->( validEntries === i.U) 1029*09c6f1ddSLingrui98 ).foldLeft(Map[String, UInt]())(_+_) 1030*09c6f1ddSLingrui98 1031*09c6f1ddSLingrui98 val perfCountsMap = Map( 1032*09c6f1ddSLingrui98 "BpInstr" -> PopCount(mbpInstrs), 1033*09c6f1ddSLingrui98 "BpBInstr" -> PopCount(mbpBRights | mbpBWrongs), 1034*09c6f1ddSLingrui98 "BpRight" -> PopCount(mbpRights), 1035*09c6f1ddSLingrui98 "BpWrong" -> PopCount(mbpWrongs), 1036*09c6f1ddSLingrui98 "BpBRight" -> PopCount(mbpBRights), 1037*09c6f1ddSLingrui98 "BpBWrong" -> PopCount(mbpBWrongs), 1038*09c6f1ddSLingrui98 "BpJRight" -> PopCount(mbpJRights), 1039*09c6f1ddSLingrui98 "BpJWrong" -> PopCount(mbpJWrongs), 1040*09c6f1ddSLingrui98 "BpIRight" -> PopCount(mbpIRights), 1041*09c6f1ddSLingrui98 "BpIWrong" -> PopCount(mbpIWrongs), 1042*09c6f1ddSLingrui98 "BpCRight" -> PopCount(mbpCRights), 1043*09c6f1ddSLingrui98 "BpCWrong" -> PopCount(mbpCWrongs), 1044*09c6f1ddSLingrui98 "BpRRight" -> PopCount(mbpRRights), 1045*09c6f1ddSLingrui98 "BpRWrong" -> PopCount(mbpRWrongs), 1046*09c6f1ddSLingrui98 1047*09c6f1ddSLingrui98 "ftb_false_hit" -> PopCount(ftb_false_hit), 1048*09c6f1ddSLingrui98 "ftb_hit" -> PopCount(ftb_hit), 1049*09c6f1ddSLingrui98 "ftb_new_entry" -> PopCount(ftb_new_entry), 1050*09c6f1ddSLingrui98 "ftb_new_entry_only_br" -> PopCount(ftb_new_entry_only_br), 1051*09c6f1ddSLingrui98 "ftb_new_entry_only_jmp" -> PopCount(ftb_new_entry_only_jmp), 1052*09c6f1ddSLingrui98 "ftb_new_entry_has_br_and_jmp" -> PopCount(ftb_new_entry_has_br_and_jmp), 1053*09c6f1ddSLingrui98 "ftb_old_entry" -> PopCount(ftb_old_entry), 1054*09c6f1ddSLingrui98 "ftb_modified_entry" -> PopCount(ftb_modified_entry), 1055*09c6f1ddSLingrui98 "ftb_modified_entry_new_br" -> PopCount(ftb_modified_entry_new_br), 1056*09c6f1ddSLingrui98 "ftb_jalr_target_modified" -> PopCount(ftb_modified_entry_jalr_target_modified), 1057*09c6f1ddSLingrui98 "ftb_modified_entry_br_full" -> PopCount(ftb_modified_entry_br_full), 1058*09c6f1ddSLingrui98 "ftb_modified_entry_always_taken" -> PopCount(ftb_modified_entry_always_taken) 1059*09c6f1ddSLingrui98 ) ++ ftb_init_entry_len_map ++ ftb_modified_entry_len_map ++ s1_entry_len_map ++ 1060*09c6f1ddSLingrui98 s2_entry_len_map ++ s3_entry_len_map ++ 1061*09c6f1ddSLingrui98 to_ifu_entry_len_map ++ commit_num_inst_map ++ ftq_occupancy_map 1062*09c6f1ddSLingrui98 1063*09c6f1ddSLingrui98 for((key, value) <- perfCountsMap) { 1064*09c6f1ddSLingrui98 XSPerfAccumulate(key, value) 1065*09c6f1ddSLingrui98 } 1066*09c6f1ddSLingrui98 1067*09c6f1ddSLingrui98 // --------------------------- Debug -------------------------------- 1068*09c6f1ddSLingrui98 // XSDebug(enq_fire, p"enq! " + io.fromBpu.resp.bits.toPrintable) 1069*09c6f1ddSLingrui98 XSDebug(io.toIfu.req.fire, p"fire to ifu " + io.toIfu.req.bits.toPrintable) 1070*09c6f1ddSLingrui98 XSDebug(do_commit, p"deq! [ptr] $do_commit_ptr\n") 1071*09c6f1ddSLingrui98 XSDebug(true.B, p"[bpuPtr] $bpuPtr, [ifuPtr] $ifuPtr, [ifuWbPtr] $ifuWbPtr [commPtr] $commPtr\n") 1072*09c6f1ddSLingrui98 XSDebug(true.B, p"[in] v:${io.fromBpu.resp.valid} r:${io.fromBpu.resp.ready} " + 1073*09c6f1ddSLingrui98 p"[out] v:${io.toIfu.req.valid} r:${io.toIfu.req.ready}\n") 1074*09c6f1ddSLingrui98 XSDebug(do_commit, p"[deq info] cfiIndex: $commit_cfi, $commit_pc_bundle, target: ${Hexadecimal(commit_target)}\n") 1075*09c6f1ddSLingrui98 1076*09c6f1ddSLingrui98 // def ubtbCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 1077*09c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 1078*09c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 1079*09c6f1ddSLingrui98 // Mux(valid && pd.isBr, 1080*09c6f1ddSLingrui98 // isWrong ^ Mux(ans.hit.asBool, 1081*09c6f1ddSLingrui98 // Mux(ans.taken.asBool, taken && ans.target === commitEntry.target, 1082*09c6f1ddSLingrui98 // !taken), 1083*09c6f1ddSLingrui98 // !taken), 1084*09c6f1ddSLingrui98 // false.B) 1085*09c6f1ddSLingrui98 // } 1086*09c6f1ddSLingrui98 // } 1087*09c6f1ddSLingrui98 1088*09c6f1ddSLingrui98 // def btbCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 1089*09c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 1090*09c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 1091*09c6f1ddSLingrui98 // Mux(valid && pd.isBr, 1092*09c6f1ddSLingrui98 // isWrong ^ Mux(ans.hit.asBool, 1093*09c6f1ddSLingrui98 // Mux(ans.taken.asBool, taken && ans.target === commitEntry.target, 1094*09c6f1ddSLingrui98 // !taken), 1095*09c6f1ddSLingrui98 // !taken), 1096*09c6f1ddSLingrui98 // false.B) 1097*09c6f1ddSLingrui98 // } 1098*09c6f1ddSLingrui98 // } 1099*09c6f1ddSLingrui98 1100*09c6f1ddSLingrui98 // def tageCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 1101*09c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 1102*09c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 1103*09c6f1ddSLingrui98 // Mux(valid && pd.isBr, 1104*09c6f1ddSLingrui98 // isWrong ^ (ans.taken.asBool === taken), 1105*09c6f1ddSLingrui98 // false.B) 1106*09c6f1ddSLingrui98 // } 1107*09c6f1ddSLingrui98 // } 1108*09c6f1ddSLingrui98 1109*09c6f1ddSLingrui98 // def loopCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 1110*09c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 1111*09c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 1112*09c6f1ddSLingrui98 // Mux(valid && (pd.isBr) && ans.hit.asBool, 1113*09c6f1ddSLingrui98 // isWrong ^ (!taken), 1114*09c6f1ddSLingrui98 // false.B) 1115*09c6f1ddSLingrui98 // } 1116*09c6f1ddSLingrui98 // } 1117*09c6f1ddSLingrui98 1118*09c6f1ddSLingrui98 // def rasCheck(commit: FtqEntry, predAns: Seq[PredictorAnswer], isWrong: Bool) = { 1119*09c6f1ddSLingrui98 // commit.valids.zip(commit.pd).zip(predAns).zip(commit.takens).map { 1120*09c6f1ddSLingrui98 // case (((valid, pd), ans), taken) => 1121*09c6f1ddSLingrui98 // Mux(valid && pd.isRet.asBool /*&& taken*/ && ans.hit.asBool, 1122*09c6f1ddSLingrui98 // isWrong ^ (ans.target === commitEntry.target), 1123*09c6f1ddSLingrui98 // false.B) 1124*09c6f1ddSLingrui98 // } 1125*09c6f1ddSLingrui98 // } 1126*09c6f1ddSLingrui98 1127*09c6f1ddSLingrui98 // val ubtbRights = ubtbCheck(commitEntry, commitEntry.metas.map(_.ubtbAns), false.B) 1128*09c6f1ddSLingrui98 // val ubtbWrongs = ubtbCheck(commitEntry, commitEntry.metas.map(_.ubtbAns), true.B) 1129*09c6f1ddSLingrui98 // // btb and ubtb pred jal and jalr as well 1130*09c6f1ddSLingrui98 // val btbRights = btbCheck(commitEntry, commitEntry.metas.map(_.btbAns), false.B) 1131*09c6f1ddSLingrui98 // val btbWrongs = btbCheck(commitEntry, commitEntry.metas.map(_.btbAns), true.B) 1132*09c6f1ddSLingrui98 // val tageRights = tageCheck(commitEntry, commitEntry.metas.map(_.tageAns), false.B) 1133*09c6f1ddSLingrui98 // val tageWrongs = tageCheck(commitEntry, commitEntry.metas.map(_.tageAns), true.B) 1134*09c6f1ddSLingrui98 1135*09c6f1ddSLingrui98 // val loopRights = loopCheck(commitEntry, commitEntry.metas.map(_.loopAns), false.B) 1136*09c6f1ddSLingrui98 // val loopWrongs = loopCheck(commitEntry, commitEntry.metas.map(_.loopAns), true.B) 1137*09c6f1ddSLingrui98 1138*09c6f1ddSLingrui98 // val rasRights = rasCheck(commitEntry, commitEntry.metas.map(_.rasAns), false.B) 1139*09c6f1ddSLingrui98 // val rasWrongs = rasCheck(commitEntry, commitEntry.metas.map(_.rasAns), true.B) 1140*09c6f1ddSLingrui98 1141*09c6f1ddSLingrui98}