144c9c1deSEaston Man/*************************************************************************************** 244c9c1deSEaston Man* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 344c9c1deSEaston Man* Copyright (c) 2020-2021 Peng Cheng Laboratory 444c9c1deSEaston Man* 544c9c1deSEaston Man* XiangShan is licensed under Mulan PSL v2. 644c9c1deSEaston Man* You can use this software according to the terms and conditions of the Mulan PSL v2. 744c9c1deSEaston Man* You may obtain a copy of Mulan PSL v2 at: 844c9c1deSEaston Man* http://license.coscl.org.cn/MulanPSL2 944c9c1deSEaston Man* 1044c9c1deSEaston Man* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 1144c9c1deSEaston Man* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 1244c9c1deSEaston Man* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 1344c9c1deSEaston Man* 1444c9c1deSEaston Man* See the Mulan PSL v2 for more details. 1544c9c1deSEaston Man***************************************************************************************/ 1644c9c1deSEaston Man 1744c9c1deSEaston Manpackage xiangshan.frontend 1844c9c1deSEaston Man 1944c9c1deSEaston Manimport chisel3._ 2044c9c1deSEaston Manimport chisel3.util._ 21cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters 2244c9c1deSEaston Manimport utility._ 23cf7d6b7aSMuziimport utils._ 24cf7d6b7aSMuziimport xiangshan._ 2544c9c1deSEaston Manimport xiangshan.ExceptionNO._ 2644c9c1deSEaston Man 27cf7d6b7aSMuziclass IBufPtr(implicit p: Parameters) extends CircularQueuePtr[IBufPtr](p => p(XSCoreParamsKey).IBufSize) {} 2844c9c1deSEaston Man 29cf7d6b7aSMuziclass IBufInBankPtr(implicit p: Parameters) extends CircularQueuePtr[IBufInBankPtr](p => 30cf7d6b7aSMuzi p(XSCoreParamsKey).IBufSize / p(XSCoreParamsKey).IBufNBank 31cf7d6b7aSMuzi ) {} 3244c9c1deSEaston Man 33cf7d6b7aSMuziclass IBufBankPtr(implicit p: Parameters) extends CircularQueuePtr[IBufBankPtr](p => p(XSCoreParamsKey).IBufNBank) {} 3444c9c1deSEaston Man 3544c9c1deSEaston Manclass IBufferIO(implicit p: Parameters) extends XSBundle { 3644c9c1deSEaston Man val flush = Input(Bool()) 3744c9c1deSEaston Man val ControlRedirect = Input(Bool()) 3844c9c1deSEaston Man val ControlBTBMissBubble = Input(Bool()) 3944c9c1deSEaston Man val TAGEMissBubble = Input(Bool()) 4044c9c1deSEaston Man val SCMissBubble = Input(Bool()) 4144c9c1deSEaston Man val ITTAGEMissBubble = Input(Bool()) 4244c9c1deSEaston Man val RASMissBubble = Input(Bool()) 4344c9c1deSEaston Man val MemVioRedirect = Input(Bool()) 4444c9c1deSEaston Man val in = Flipped(DecoupledIO(new FetchToIBuffer)) 4544c9c1deSEaston Man val out = Vec(DecodeWidth, DecoupledIO(new CtrlFlow)) 4644c9c1deSEaston Man val full = Output(Bool()) 4705cc2a4eSXuan Hu val decodeCanAccept = Input(Bool()) 4844c9c1deSEaston Man val stallReason = new StallReasonIO(DecodeWidth) 4944c9c1deSEaston Man} 5044c9c1deSEaston Man 5144c9c1deSEaston Manclass IBufEntry(implicit p: Parameters) extends XSBundle { 5244c9c1deSEaston Man val inst = UInt(32.W) 5344c9c1deSEaston Man val pc = UInt(VAddrBits.W) 5444c9c1deSEaston Man val foldpc = UInt(MemPredPCWidth.W) 5544c9c1deSEaston Man val pd = new PreDecodeInfo 5644c9c1deSEaston Man val pred_taken = Bool() 5744c9c1deSEaston Man val ftqPtr = new FtqPtr 5844c9c1deSEaston Man val ftqOffset = UInt(log2Ceil(PredictWidth).W) 5992c61038SXuan Hu val exceptionType = IBufferExceptionType() 60fbdb359dSMuzi val backendException = Bool() 617e0f64b0SGuanghui Cheng val triggered = TriggerAction() 62948e8159SEaston Man val isLastInFtqEntry = Bool() 63*1592abd1SYan Xu val debug_seqNum = InstSeqNum() 6444c9c1deSEaston Man 6544c9c1deSEaston Man def fromFetch(fetch: FetchToIBuffer, i: Int): IBufEntry = { 6644c9c1deSEaston Man inst := fetch.instrs(i) 6744c9c1deSEaston Man pc := fetch.pc(i) 6844c9c1deSEaston Man foldpc := fetch.foldpc(i) 6944c9c1deSEaston Man pd := fetch.pd(i) 7044c9c1deSEaston Man pred_taken := fetch.ftqOffset(i).valid 7144c9c1deSEaston Man ftqPtr := fetch.ftqPtr 7244c9c1deSEaston Man ftqOffset := fetch.ftqOffset(i).bits 7392c61038SXuan Hu exceptionType := IBufferExceptionType.cvtFromFetchExcpAndCrossPageAndRVCII( 7492c61038SXuan Hu fetch.exceptionType(i), 7592c61038SXuan Hu fetch.crossPageIPFFix(i), 76cf7d6b7aSMuzi fetch.illegalInstr(i) 7792c61038SXuan Hu ) 78fbdb359dSMuzi backendException := fetch.backendException(i) 7944c9c1deSEaston Man triggered := fetch.triggered(i) 80948e8159SEaston Man isLastInFtqEntry := fetch.isLastInFtqEntry(i) 81*1592abd1SYan Xu debug_seqNum := fetch.debug_seqNum(i) 8244c9c1deSEaston Man this 8344c9c1deSEaston Man } 8444c9c1deSEaston Man 8544c9c1deSEaston Man def toCtrlFlow: CtrlFlow = { 8644c9c1deSEaston Man val cf = Wire(new CtrlFlow) 8744c9c1deSEaston Man cf.instr := inst 8844c9c1deSEaston Man cf.pc := pc 8944c9c1deSEaston Man cf.foldpc := foldpc 9044c9c1deSEaston Man cf.exceptionVec := 0.U.asTypeOf(ExceptionVec()) 9192c61038SXuan Hu cf.exceptionVec(instrPageFault) := IBufferExceptionType.isPF(this.exceptionType) 9292c61038SXuan Hu cf.exceptionVec(instrGuestPageFault) := IBufferExceptionType.isGPF(this.exceptionType) 9392c61038SXuan Hu cf.exceptionVec(instrAccessFault) := IBufferExceptionType.isAF(this.exceptionType) 9492c61038SXuan Hu cf.exceptionVec(EX_II) := IBufferExceptionType.isRVCII(this.exceptionType) 95fbdb359dSMuzi cf.backendException := backendException 9644c9c1deSEaston Man cf.trigger := triggered 9744c9c1deSEaston Man cf.pd := pd 9844c9c1deSEaston Man cf.pred_taken := pred_taken 9992c61038SXuan Hu cf.crossPageIPFFix := IBufferExceptionType.isCrossPage(this.exceptionType) 10044c9c1deSEaston Man cf.storeSetHit := DontCare 10144c9c1deSEaston Man cf.waitForRobIdx := DontCare 10244c9c1deSEaston Man cf.loadWaitBit := DontCare 10344c9c1deSEaston Man cf.loadWaitStrict := DontCare 10444c9c1deSEaston Man cf.ssid := DontCare 10544c9c1deSEaston Man cf.ftqPtr := ftqPtr 10644c9c1deSEaston Man cf.ftqOffset := ftqOffset 107948e8159SEaston Man cf.isLastInFtqEntry := isLastInFtqEntry 108*1592abd1SYan Xu cf.debug_seqNum := debug_seqNum 10944c9c1deSEaston Man cf 11044c9c1deSEaston Man } 11192c61038SXuan Hu 11292c61038SXuan Hu object IBufferExceptionType extends NamedUInt(3) { 11392c61038SXuan Hu def None = "b000".U 11492c61038SXuan Hu def NonCrossPF = "b001".U 11592c61038SXuan Hu def NonCrossGPF = "b010".U 11692c61038SXuan Hu def NonCrossAF = "b011".U 11792c61038SXuan Hu // illegal instruction 11892c61038SXuan Hu def rvcII = "b100".U 11992c61038SXuan Hu def CrossPF = "b101".U 12092c61038SXuan Hu def CrossGPF = "b110".U 12192c61038SXuan Hu def CrossAF = "b111".U 12292c61038SXuan Hu 12392c61038SXuan Hu def cvtFromFetchExcpAndCrossPageAndRVCII(fetchExcp: UInt, crossPage: Bool, rvcIll: Bool): UInt = { 12492c61038SXuan Hu require( 12592c61038SXuan Hu fetchExcp.getWidth == ExceptionType.width, 12692c61038SXuan Hu s"The width(${fetchExcp.getWidth}) of fetchExcp should be equal to " + 12792c61038SXuan Hu s"the width(${ExceptionType.width}) of frontend.ExceptionType." 12892c61038SXuan Hu ) 129cf7d6b7aSMuzi MuxCase( 130cf7d6b7aSMuzi 0.U, 131cf7d6b7aSMuzi Seq( 13292c61038SXuan Hu crossPage -> Cat(1.U(1.W), fetchExcp), 133f5b900a2SXuan Hu fetchExcp.orR -> fetchExcp, 134cf7d6b7aSMuzi rvcIll -> this.rvcII 135cf7d6b7aSMuzi ) 136cf7d6b7aSMuzi ) 13792c61038SXuan Hu } 13892c61038SXuan Hu 13992c61038SXuan Hu def isRVCII(uint: UInt): Bool = { 14092c61038SXuan Hu this.checkInputWidth(uint) 14192c61038SXuan Hu uint(2) && uint(1, 0) === 0.U 14292c61038SXuan Hu } 14392c61038SXuan Hu 14492c61038SXuan Hu def isCrossPage(uint: UInt): Bool = { 14592c61038SXuan Hu this.checkInputWidth(uint) 14692c61038SXuan Hu uint(2) && uint(1, 0) =/= 0.U 14792c61038SXuan Hu } 14892c61038SXuan Hu 14992c61038SXuan Hu def isPF(uint: UInt): Bool = uint(1, 0) === this.NonCrossPF(1, 0) 15092c61038SXuan Hu def isGPF(uint: UInt): Bool = uint(1, 0) === this.NonCrossGPF(1, 0) 15192c61038SXuan Hu def isAF(uint: UInt): Bool = uint(1, 0) === this.NonCrossAF(1, 0) 15292c61038SXuan Hu } 15344c9c1deSEaston Man} 15444c9c1deSEaston Man 15544c9c1deSEaston Manclass IBuffer(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper with HasPerfEvents { 15644c9c1deSEaston Man val io = IO(new IBufferIO) 15744c9c1deSEaston Man 15805cc2a4eSXuan Hu // io alias 15905cc2a4eSXuan Hu private val decodeCanAccept = io.decodeCanAccept 16005cc2a4eSXuan Hu 16144c9c1deSEaston Man // Parameter Check 16244c9c1deSEaston Man private val bankSize = IBufSize / IBufNBank 16344c9c1deSEaston Man require(IBufSize % IBufNBank == 0, s"IBufNBank should divide IBufSize, IBufNBank: $IBufNBank, IBufSize: $IBufSize") 164cf7d6b7aSMuzi require( 165cf7d6b7aSMuzi IBufNBank >= DecodeWidth, 166cf7d6b7aSMuzi s"IBufNBank should be equal or larger than DecodeWidth, IBufNBank: $IBufNBank, DecodeWidth: $DecodeWidth" 167cf7d6b7aSMuzi ) 16844c9c1deSEaston Man 16944c9c1deSEaston Man // IBuffer is organized as raw registers 17044c9c1deSEaston Man // This is due to IBuffer is a huge queue, read & write port logic should be precisely controlled 17144c9c1deSEaston Man // . + + E E E - . 17244c9c1deSEaston Man // . + + E E E - . 17344c9c1deSEaston Man // . . + E E E - . 17444c9c1deSEaston Man // . . + E E E E - 17544c9c1deSEaston Man // As shown above, + means enqueue, - means dequeue, E is current content 17644c9c1deSEaston Man // When dequeue, read port is organized like a banked FIFO 17744c9c1deSEaston Man // Dequeue reads no more than 1 entry from each bank sequentially, this can be exploit to reduce area 17844c9c1deSEaston Man // Enqueue writes cannot benefit from this characteristic unless use a SRAM 17944c9c1deSEaston Man // For detail see Enqueue and Dequeue below 18044c9c1deSEaston Man private val ibuf: Vec[IBufEntry] = RegInit(VecInit.fill(IBufSize)(0.U.asTypeOf(new IBufEntry))) 181cf7d6b7aSMuzi private val bankedIBufView: Vec[Vec[IBufEntry]] = VecInit.tabulate(IBufNBank)(bankID => 182cf7d6b7aSMuzi VecInit.tabulate(bankSize)(inBankOffset => ibuf(bankID + inBankOffset * IBufNBank)) 18344c9c1deSEaston Man ) 1848fae59bbSEaston Man 1858fae59bbSEaston Man // Bypass wire 1868fae59bbSEaston Man private val bypassEntries = WireDefault(VecInit.fill(DecodeWidth)(0.U.asTypeOf(Valid(new IBufEntry)))) 1878fae59bbSEaston Man // Normal read wire 1888fae59bbSEaston Man private val deqEntries = WireDefault(VecInit.fill(DecodeWidth)(0.U.asTypeOf(Valid(new IBufEntry)))) 1898fae59bbSEaston Man // Output register 1908fae59bbSEaston Man private val outputEntries = RegInit(VecInit.fill(DecodeWidth)(0.U.asTypeOf(Valid(new IBufEntry)))) 191cf7d6b7aSMuzi private val outputEntriesValidNum = 192cf7d6b7aSMuzi PriorityMuxDefault(outputEntries.map(_.valid).zip(Seq.range(1, DecodeWidth).map(_.U)).reverse.toSeq, 0.U) 1938fae59bbSEaston Man 19444c9c1deSEaston Man // Between Bank 19544c9c1deSEaston Man private val deqBankPtrVec: Vec[IBufBankPtr] = RegInit(VecInit.tabulate(DecodeWidth)(_.U.asTypeOf(new IBufBankPtr))) 19644c9c1deSEaston Man private val deqBankPtr: IBufBankPtr = deqBankPtrVec(0) 19705cc2a4eSXuan Hu private val deqBankPtrVecNext = Wire(deqBankPtrVec.cloneType) 19844c9c1deSEaston Man // Inside Bank 19944c9c1deSEaston Man private val deqInBankPtr: Vec[IBufInBankPtr] = RegInit(VecInit.fill(IBufNBank)(0.U.asTypeOf(new IBufInBankPtr))) 20005cc2a4eSXuan Hu private val deqInBankPtrNext = Wire(deqInBankPtr.cloneType) 20144c9c1deSEaston Man 20244c9c1deSEaston Man val deqPtr = RegInit(0.U.asTypeOf(new IBufPtr)) 20305cc2a4eSXuan Hu val deqPtrNext = Wire(deqPtr.cloneType) 20444c9c1deSEaston Man 20544c9c1deSEaston Man val enqPtrVec = RegInit(VecInit.tabulate(PredictWidth)(_.U.asTypeOf(new IBufPtr))) 20644c9c1deSEaston Man val enqPtr = enqPtrVec(0) 20744c9c1deSEaston Man 2088fae59bbSEaston Man val numTryEnq = WireDefault(0.U) 2098fae59bbSEaston Man val numEnq = Mux(io.in.fire, numTryEnq, 0.U) 2108fae59bbSEaston Man 2118506cfc0Sxiaofeibao // empty and decode can accept insts 2128506cfc0Sxiaofeibao val useBypass = enqPtr === deqPtr && decodeCanAccept 21305cc2a4eSXuan Hu 21405cc2a4eSXuan Hu // The number of decode accepted insts. 21505cc2a4eSXuan Hu // Since decode promises accepting insts in order, use priority encoder to simplify the accumulation. 216a5546049Sxiaofeibao private val numOut = Wire(UInt(log2Ceil(DecodeWidth).W)) 217a5546049Sxiaofeibao private val numDeq = numOut 21805cc2a4eSXuan Hu 21905cc2a4eSXuan Hu // counter current number of valid 22005cc2a4eSXuan Hu val numValid = distanceBetween(enqPtr, deqPtr) 22105cc2a4eSXuan Hu val numValidAfterDeq = numValid - numDeq 22205cc2a4eSXuan Hu // counter next number of valid 22305cc2a4eSXuan Hu val numValidNext = numValid + numEnq - numDeq 22405cc2a4eSXuan Hu val allowEnq = RegInit(true.B) 22505cc2a4eSXuan Hu val numFromFetch = Mux(io.in.valid, PopCount(io.in.bits.enqEnable), 0.U) 22605cc2a4eSXuan Hu 22705cc2a4eSXuan Hu allowEnq := (IBufSize - PredictWidth).U >= numValidNext // Disable when almost full 22844c9c1deSEaston Man 2298fae59bbSEaston Man val enqOffset = VecInit.tabulate(PredictWidth)(i => PopCount(io.in.bits.valid.asBools.take(i))) 2308fae59bbSEaston Man val enqData = VecInit.tabulate(PredictWidth)(i => Wire(new IBufEntry).fromFetch(io.in.bits, i)) 2318fae59bbSEaston Man 232a5546049Sxiaofeibao val outputEntriesIsNotFull = !outputEntries(DecodeWidth - 1).valid 233a5546049Sxiaofeibao when(decodeCanAccept) { 234a5546049Sxiaofeibao numOut := Mux(numValid >= DecodeWidth.U, DecodeWidth.U, numValid) 235a5546049Sxiaofeibao }.elsewhen(outputEntriesIsNotFull) { 236a5546049Sxiaofeibao numOut := Mux(numValid >= DecodeWidth.U - outputEntriesValidNum, DecodeWidth.U - outputEntriesValidNum, numValid) 237a5546049Sxiaofeibao }.otherwise { 238a5546049Sxiaofeibao numOut := 0.U 239a5546049Sxiaofeibao } 240a5546049Sxiaofeibao val numBypass = Wire(UInt(log2Ceil(DecodeWidth).W)) 2418fae59bbSEaston Man // when using bypass, bypassed entries do not enqueue 2428fae59bbSEaston Man when(useBypass) { 2438fae59bbSEaston Man when(numFromFetch >= DecodeWidth.U) { 2448fae59bbSEaston Man numTryEnq := numFromFetch - DecodeWidth.U 245a5546049Sxiaofeibao numBypass := DecodeWidth.U 2468fae59bbSEaston Man }.otherwise { 2478fae59bbSEaston Man numTryEnq := 0.U 248a5546049Sxiaofeibao numBypass := numFromFetch 2498fae59bbSEaston Man } 2508fae59bbSEaston Man }.otherwise { 2518fae59bbSEaston Man numTryEnq := numFromFetch 252a5546049Sxiaofeibao numBypass := 0.U 2538fae59bbSEaston Man } 2548fae59bbSEaston Man 2558fae59bbSEaston Man ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2568fae59bbSEaston Man // Bypass 2578fae59bbSEaston Man ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2588fae59bbSEaston Man bypassEntries.zipWithIndex.foreach { 2598fae59bbSEaston Man case (entry, idx) => 2608fae59bbSEaston Man // Select 2618fae59bbSEaston Man val validOH = Range(0, PredictWidth).map { 2628fae59bbSEaston Man i => 2638fae59bbSEaston Man io.in.bits.valid(i) && 2648fae59bbSEaston Man io.in.bits.enqEnable(i) && 2658fae59bbSEaston Man enqOffset(i) === idx.asUInt 2668fae59bbSEaston Man } // Should be OneHot 2678fae59bbSEaston Man entry.valid := validOH.reduce(_ || _) && io.in.fire && !io.flush 2688fae59bbSEaston Man entry.bits := Mux1H(validOH, enqData) 2698fae59bbSEaston Man 2708fae59bbSEaston Man // Debug Assertion 2719afa8a47STang Haojin XSError(io.in.valid && PopCount(validOH) > 1.asUInt, "validOH is not OneHot") 2728fae59bbSEaston Man } 2738fae59bbSEaston Man 2748fae59bbSEaston Man // => Decode Output 2758fae59bbSEaston Man // clean register output 2768fae59bbSEaston Man io.out zip outputEntries foreach { 2778fae59bbSEaston Man case (io, reg) => 2788fae59bbSEaston Man io.valid := reg.valid 2798fae59bbSEaston Man io.bits := reg.bits.toCtrlFlow 2808fae59bbSEaston Man } 281a5546049Sxiaofeibao (outputEntries zip bypassEntries).zipWithIndex.foreach { 282a5546049Sxiaofeibao case ((out, bypass), i) => 28305cc2a4eSXuan Hu when(decodeCanAccept) { 28405cc2a4eSXuan Hu when(useBypass && io.in.valid) { 2858fae59bbSEaston Man out := bypass 286e778bb8aSxiaofeibao-xjtu }.otherwise { 287a5546049Sxiaofeibao out := deqEntries(i) 2888fae59bbSEaston Man } 289a5546049Sxiaofeibao }.elsewhen(outputEntriesIsNotFull) { 290a5546049Sxiaofeibao out.valid := deqEntries(i).valid 291cf7d6b7aSMuzi out.bits := Mux( 292cf7d6b7aSMuzi i.U < outputEntriesValidNum, 293cf7d6b7aSMuzi out.bits, 294cf7d6b7aSMuzi VecInit(deqEntries.take(i + 1).map(_.bits))(i.U - outputEntriesValidNum) 295cf7d6b7aSMuzi ) 2968fae59bbSEaston Man } 2978fae59bbSEaston Man } 2988fae59bbSEaston Man 29944c9c1deSEaston Man ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30044c9c1deSEaston Man // Enqueue 30144c9c1deSEaston Man ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30244c9c1deSEaston Man io.in.ready := allowEnq 30344c9c1deSEaston Man // Data 30444c9c1deSEaston Man ibuf.zipWithIndex.foreach { 30544c9c1deSEaston Man case (entry, idx) => { 30644c9c1deSEaston Man // Select 30744c9c1deSEaston Man val validOH = Range(0, PredictWidth).map { 3088fae59bbSEaston Man i => 3098fae59bbSEaston Man val useBypassMatch = enqOffset(i) >= DecodeWidth.U && 3108fae59bbSEaston Man enqPtrVec(enqOffset(i) - DecodeWidth.U).value === idx.asUInt 3118fae59bbSEaston Man val normalMatch = enqPtrVec(enqOffset(i)).value === idx.asUInt 3128fae59bbSEaston Man val m = Mux(useBypass, useBypassMatch, normalMatch) // when using bypass, bypassed entries do not enqueue 3138fae59bbSEaston Man 3148fae59bbSEaston Man io.in.bits.valid(i) && io.in.bits.enqEnable(i) && m 31544c9c1deSEaston Man } // Should be OneHot 31644c9c1deSEaston Man val wen = validOH.reduce(_ || _) && io.in.fire && !io.flush 31744c9c1deSEaston Man 31844c9c1deSEaston Man // Write port 31944c9c1deSEaston Man // Each IBuffer entry has a PredictWidth -> 1 Mux 32044c9c1deSEaston Man val writeEntry = Mux1H(validOH, enqData) 32144c9c1deSEaston Man entry := Mux(wen, writeEntry, entry) 32244c9c1deSEaston Man 32344c9c1deSEaston Man // Debug Assertion 32478c76c74STang Haojin XSError(io.in.valid && PopCount(validOH) > 1.asUInt, "validOH is not OneHot") 32544c9c1deSEaston Man } 32644c9c1deSEaston Man } 32744c9c1deSEaston Man // Pointer maintenance 32844c9c1deSEaston Man when(io.in.fire && !io.flush) { 3298fae59bbSEaston Man enqPtrVec := VecInit(enqPtrVec.map(_ + numTryEnq)) 33044c9c1deSEaston Man } 33144c9c1deSEaston Man 33244c9c1deSEaston Man ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33344c9c1deSEaston Man // Dequeue 33444c9c1deSEaston Man ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 335a5546049Sxiaofeibao val outputEntriesValidNumNext = Wire(UInt(log2Ceil(DecodeWidth).W)) 336a5546049Sxiaofeibao XSError(outputEntriesValidNumNext > DecodeWidth.U, "Ibuffer: outputEntriesValidNumNext > DecodeWidth.U") 337a5546049Sxiaofeibao val validVec = UIntToMask(outputEntriesValidNumNext(log2Ceil(DecodeWidth) - 1, 0), DecodeWidth) 338a5546049Sxiaofeibao when(decodeCanAccept) { 339a5546049Sxiaofeibao outputEntriesValidNumNext := Mux(useBypass, numBypass, numDeq) 340a5546049Sxiaofeibao }.elsewhen(outputEntriesIsNotFull) { 341a5546049Sxiaofeibao outputEntriesValidNumNext := outputEntriesValidNum + numDeq 342a5546049Sxiaofeibao }.otherwise { 343a5546049Sxiaofeibao outputEntriesValidNumNext := outputEntriesValidNum 344a5546049Sxiaofeibao } 34544c9c1deSEaston Man // Data 34644c9c1deSEaston Man // Read port 34744c9c1deSEaston Man // 2-stage, IBufNBank * (bankSize -> 1) + IBufNBank -> 1 34844c9c1deSEaston Man // Should be better than IBufSize -> 1 in area, with no significant latency increase 349cf7d6b7aSMuzi private val readStage1: Vec[IBufEntry] = 350cf7d6b7aSMuzi VecInit.tabulate(IBufNBank)(bankID => Mux1H(UIntToOH(deqInBankPtr(bankID).value), bankedIBufView(bankID))) 35144c9c1deSEaston Man for (i <- 0 until DecodeWidth) { 3528fae59bbSEaston Man deqEntries(i).valid := validVec(i) 353a5546049Sxiaofeibao deqEntries(i).bits := Mux1H(UIntToOH(deqBankPtrVec(i).value), readStage1) 35444c9c1deSEaston Man } 35544c9c1deSEaston Man // Pointer maintenance 356ac3c9508SXuan Hu deqBankPtrVecNext := VecInit(deqBankPtrVec.map(_ + numDeq)) 357ac3c9508SXuan Hu deqPtrNext := deqPtr + numDeq 35805cc2a4eSXuan Hu deqInBankPtrNext.zip(deqInBankPtr).zipWithIndex.foreach { 35905cc2a4eSXuan Hu case ((ptrNext, ptr), idx) => { 36044c9c1deSEaston Man // validVec[k] == bankValid[deqBankPtr + k] 36144c9c1deSEaston Man // So bankValid[n] == validVec[n - deqBankPtr] 362cf7d6b7aSMuzi val validIdx = Mux( 363cf7d6b7aSMuzi idx.asUInt >= deqBankPtr.value, 36444c9c1deSEaston Man idx.asUInt - deqBankPtr.value, 36544c9c1deSEaston Man ((idx + IBufNBank).asUInt - deqBankPtr.value)(log2Ceil(IBufNBank) - 1, 0) 36645b8fd86SEaston Man )(log2Ceil(DecodeWidth) - 1, 0) 367a5546049Sxiaofeibao val bankAdvance = numOut > validIdx 36805cc2a4eSXuan Hu ptrNext := Mux(bankAdvance, ptr + 1.U, ptr) 36944c9c1deSEaston Man } 37044c9c1deSEaston Man } 37144c9c1deSEaston Man 37244c9c1deSEaston Man // Flush 37344c9c1deSEaston Man when(io.flush) { 37444c9c1deSEaston Man allowEnq := true.B 37544c9c1deSEaston Man enqPtrVec := enqPtrVec.indices.map(_.U.asTypeOf(new IBufPtr)) 37644c9c1deSEaston Man deqBankPtrVec := deqBankPtrVec.indices.map(_.U.asTypeOf(new IBufBankPtr)) 37744c9c1deSEaston Man deqInBankPtr := VecInit.fill(IBufNBank)(0.U.asTypeOf(new IBufInBankPtr)) 37844c9c1deSEaston Man deqPtr := 0.U.asTypeOf(new IBufPtr()) 3798fae59bbSEaston Man outputEntries.foreach(_.valid := false.B) 38005cc2a4eSXuan Hu }.otherwise { 38105cc2a4eSXuan Hu deqPtr := deqPtrNext 38205cc2a4eSXuan Hu deqInBankPtr := deqInBankPtrNext 38305cc2a4eSXuan Hu deqBankPtrVec := deqBankPtrVecNext 38444c9c1deSEaston Man } 38544c9c1deSEaston Man io.full := !allowEnq 38644c9c1deSEaston Man 38744c9c1deSEaston Man ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38844c9c1deSEaston Man // TopDown 38944c9c1deSEaston Man ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 39044c9c1deSEaston Man val topdown_stage = RegInit(0.U.asTypeOf(new FrontendTopDownBundle)) 39144c9c1deSEaston Man topdown_stage := io.in.bits.topdown_info 39244c9c1deSEaston Man when(io.flush) { 39344c9c1deSEaston Man when(io.ControlRedirect) { 39444c9c1deSEaston Man when(io.ControlBTBMissBubble) { 39544c9c1deSEaston Man topdown_stage.reasons(TopDownCounters.BTBMissBubble.id) := true.B 39644c9c1deSEaston Man }.elsewhen(io.TAGEMissBubble) { 39744c9c1deSEaston Man topdown_stage.reasons(TopDownCounters.TAGEMissBubble.id) := true.B 39844c9c1deSEaston Man }.elsewhen(io.SCMissBubble) { 39944c9c1deSEaston Man topdown_stage.reasons(TopDownCounters.SCMissBubble.id) := true.B 40044c9c1deSEaston Man }.elsewhen(io.ITTAGEMissBubble) { 40144c9c1deSEaston Man topdown_stage.reasons(TopDownCounters.ITTAGEMissBubble.id) := true.B 40244c9c1deSEaston Man }.elsewhen(io.RASMissBubble) { 40344c9c1deSEaston Man topdown_stage.reasons(TopDownCounters.RASMissBubble.id) := true.B 40444c9c1deSEaston Man } 40544c9c1deSEaston Man }.elsewhen(io.MemVioRedirect) { 40644c9c1deSEaston Man topdown_stage.reasons(TopDownCounters.MemVioRedirectBubble.id) := true.B 40744c9c1deSEaston Man }.otherwise { 40844c9c1deSEaston Man topdown_stage.reasons(TopDownCounters.OtherRedirectBubble.id) := true.B 40944c9c1deSEaston Man } 41044c9c1deSEaston Man } 41144c9c1deSEaston Man 41244c9c1deSEaston Man val matchBubble = Wire(UInt(log2Up(TopDownCounters.NumStallReasons.id).W)) 41344c9c1deSEaston Man val deqValidCount = PopCount(validVec.asBools) 41444c9c1deSEaston Man val deqWasteCount = DecodeWidth.U - deqValidCount 41544c9c1deSEaston Man matchBubble := (TopDownCounters.NumStallReasons.id - 1).U - PriorityEncoder(topdown_stage.reasons.reverse) 41644c9c1deSEaston Man 41744c9c1deSEaston Man io.stallReason.reason.map(_ := 0.U) 41844c9c1deSEaston Man for (i <- 0 until DecodeWidth) { 41944c9c1deSEaston Man when(i.U < deqWasteCount) { 42044c9c1deSEaston Man io.stallReason.reason(DecodeWidth - i - 1) := matchBubble 42144c9c1deSEaston Man } 42244c9c1deSEaston Man } 42344c9c1deSEaston Man 42444c9c1deSEaston Man when(!(deqWasteCount === DecodeWidth.U || topdown_stage.reasons.asUInt.orR)) { 42544c9c1deSEaston Man // should set reason for FetchFragmentationStall 42644c9c1deSEaston Man // topdown_stage.reasons(TopDownCounters.FetchFragmentationStall.id) := true.B 42744c9c1deSEaston Man for (i <- 0 until DecodeWidth) { 42844c9c1deSEaston Man when(i.U < deqWasteCount) { 42944c9c1deSEaston Man io.stallReason.reason(DecodeWidth - i - 1) := TopDownCounters.FetchFragBubble.id.U 43044c9c1deSEaston Man } 43144c9c1deSEaston Man } 43244c9c1deSEaston Man } 43344c9c1deSEaston Man 43444c9c1deSEaston Man when(io.stallReason.backReason.valid) { 43544c9c1deSEaston Man io.stallReason.reason.map(_ := io.stallReason.backReason.bits) 43644c9c1deSEaston Man } 43744c9c1deSEaston Man 43844c9c1deSEaston Man // Debug info 43944c9c1deSEaston Man XSError( 44044c9c1deSEaston Man deqPtr.value =/= deqBankPtr.value + deqInBankPtr(deqBankPtr.value).value * IBufNBank.asUInt, 44144c9c1deSEaston Man "Dequeue PTR mismatch" 44244c9c1deSEaston Man ) 44305cc2a4eSXuan Hu XSError(isBefore(enqPtr, deqPtr) && !isFull(enqPtr, deqPtr), "\ndeqPtr is older than enqPtr!\n") 44405cc2a4eSXuan Hu 44544c9c1deSEaston Man XSDebug(io.flush, "IBuffer Flushed\n") 44644c9c1deSEaston Man 4478b33cd30Sklin02 XSDebug(io.in.fire, "Enque:\n") 4488b33cd30Sklin02 XSDebug(io.in.fire, p"MASK=${Binary(io.in.bits.valid)}\n") 44944c9c1deSEaston Man for (i <- 0 until PredictWidth) { 4508b33cd30Sklin02 XSDebug(io.in.fire, p"PC=${Hexadecimal(io.in.bits.pc(i))} ${Hexadecimal(io.in.bits.instrs(i))}\n") 45144c9c1deSEaston Man } 45244c9c1deSEaston Man 45344c9c1deSEaston Man for (i <- 0 until DecodeWidth) { 454cf7d6b7aSMuzi XSDebug( 455cf7d6b7aSMuzi io.out(i).fire, 45644c9c1deSEaston Man p"deq: ${Hexadecimal(io.out(i).bits.instr)} PC=${Hexadecimal(io.out(i).bits.pc)}" + 45744c9c1deSEaston Man p"v=${io.out(i).valid} r=${io.out(i).ready} " + 458cf7d6b7aSMuzi p"excpVec=${Binary(io.out(i).bits.exceptionVec.asUInt)} crossPageIPF=${io.out(i).bits.crossPageIPFFix}\n" 459cf7d6b7aSMuzi ) 46044c9c1deSEaston Man } 46144c9c1deSEaston Man 46205cc2a4eSXuan Hu XSDebug(p"numValid: ${numValid}\n") 46344c9c1deSEaston Man XSDebug(p"EnqNum: ${numEnq}\n") 46444c9c1deSEaston Man XSDebug(p"DeqNum: ${numDeq}\n") 46544c9c1deSEaston Man 46644c9c1deSEaston Man val afterInit = RegInit(false.B) 46744c9c1deSEaston Man val headBubble = RegInit(false.B) 468cf7d6b7aSMuzi when(io.in.fire)(afterInit := true.B) 46944c9c1deSEaston Man when(io.flush) { 47044c9c1deSEaston Man headBubble := true.B 47105cc2a4eSXuan Hu }.elsewhen(numValid =/= 0.U) { 47244c9c1deSEaston Man headBubble := false.B 47344c9c1deSEaston Man } 47405cc2a4eSXuan Hu val instrHungry = afterInit && (numValid === 0.U) && !headBubble 47544c9c1deSEaston Man 47605cc2a4eSXuan Hu QueuePerf(IBufSize, numValid, !allowEnq) 47744c9c1deSEaston Man XSPerfAccumulate("flush", io.flush) 47844c9c1deSEaston Man XSPerfAccumulate("hungry", instrHungry) 47944c9c1deSEaston Man 48005cc2a4eSXuan Hu val ibuffer_IDWidth_hvButNotFull = afterInit && (numValid =/= 0.U) && (numValid < DecodeWidth.U) && !headBubble 48144c9c1deSEaston Man XSPerfAccumulate("ibuffer_IDWidth_hvButNotFull", ibuffer_IDWidth_hvButNotFull) 48227d10d0cSEaston Man 4839cd76b21SZhaoyang You val FrontBubble = Mux(decodeCanAccept && !headBubble, DecodeWidth.U - numOut, 0.U) 48444c9c1deSEaston Man 485e836c770SZhaoyang You val fetchLatency = decodeCanAccept && !headBubble && numOut === 0.U 486e836c770SZhaoyang You 487e836c770SZhaoyang You XSPerfAccumulate("if_fetch_bubble", FrontBubble) 488e836c770SZhaoyang You XSPerfAccumulate("if_fetch_bubble_eq_max", fetchLatency) 489e836c770SZhaoyang You 49044c9c1deSEaston Man val perfEvents = Seq( 49144c9c1deSEaston Man ("IBuffer_Flushed ", io.flush), 49244c9c1deSEaston Man ("IBuffer_hungry ", instrHungry), 49305cc2a4eSXuan Hu ("IBuffer_1_4_valid", (numValid > (0 * (IBufSize / 4)).U) & (numValid < (1 * (IBufSize / 4)).U)), 49405cc2a4eSXuan Hu ("IBuffer_2_4_valid", (numValid >= (1 * (IBufSize / 4)).U) & (numValid < (2 * (IBufSize / 4)).U)), 49505cc2a4eSXuan Hu ("IBuffer_3_4_valid", (numValid >= (2 * (IBufSize / 4)).U) & (numValid < (3 * (IBufSize / 4)).U)), 49605cc2a4eSXuan Hu ("IBuffer_4_4_valid", (numValid >= (3 * (IBufSize / 4)).U) & (numValid < (4 * (IBufSize / 4)).U)), 49705cc2a4eSXuan Hu ("IBuffer_full ", numValid.andR), 498e836c770SZhaoyang You ("Front_Bubble ", FrontBubble), 499e836c770SZhaoyang You ("Fetch_Latency_Bound", fetchLatency) 50044c9c1deSEaston Man ) 50144c9c1deSEaston Man generatePerfEvent() 50244c9c1deSEaston Man} 503