/*************************************************************************************** * Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) * Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences * Copyright (c) 2020-2021 Peng Cheng Laboratory * * XiangShan is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * http://license.coscl.org.cn/MulanPSL2 * * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * * See the Mulan PSL v2 for more details. ***************************************************************************************/ package xiangshan.backend.rob import org.chipsalliance.cde.config.Parameters import chisel3.{Mem, Mux, Vec, _} import chisel3.util._ import difftest._ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import utility._ import utils._ import xiangshan._ import xiangshan.backend.BackendParams import xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput, UopIdx} import xiangshan.backend.fu.{FuConfig, FuType} import xiangshan.frontend.FtqPtr import xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr} import xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput} import xiangshan.backend.ctrlblock.{DebugLSIO, DebugLsInfo, LsTopdownInfo} import xiangshan.backend.fu.NewCSR.CSREvents.TargetPCBundle import xiangshan.backend.fu.vector.Bundles.{Nf, VLmul, VSew, VType} import xiangshan.backend.rename.SnapshotGenerator import xiangshan.backend.trace._ import scala.collection.immutable.Nil object RobBundles extends HasCircularQueuePtrHelper { class RobEntryBundle(implicit p: Parameters) extends XSBundle { // data begin val vls = Bool() // some instructions are not allowed to trigger interrupts // They have side effects on the states of the processor before they write back val interrupt_safe = Bool() val fpWen = Bool() val rfWen = Bool() val wflags = Bool() val dirtyVs = Bool() val commitType = CommitType() val ftqIdx = new FtqPtr val ftqOffset = UInt(log2Up(PredictWidth).W) val isRVC = Bool() val isVset = Bool() val isHls = Bool() val instrSize = UInt(log2Ceil(RenameWidth + 1).W) // data end // trace val traceBlockInPipe = new TracePipe(IretireWidthInPipe) // status begin val valid = Bool() val fflags = UInt(5.W) val mmio = Bool() // store will be commited if both sta & std have been writebacked val stdWritebacked = Bool() val vxsat = Bool() val realDestSize = UInt(log2Up(MaxUopSize + 1).W) val uopNum = UInt(log2Up(MaxUopSize + 1).W) val needFlush = Bool() // status end // debug_begin val debug_pc = OptionWrapper(backendParams.debugEn, UInt(VAddrBits.W)) val debug_instr = OptionWrapper(backendParams.debugEn, UInt(32.W)) val debug_ldest = OptionWrapper(backendParams.basicDebugEn, UInt(LogicRegsWidth.W)) val debug_pdest = OptionWrapper(backendParams.basicDebugEn, UInt(PhyRegIdxWidth.W)) val debug_fuType = OptionWrapper(backendParams.debugEn, FuType()) // debug_end def isWritebacked: Bool = !uopNum.orR && stdWritebacked def isUopWritebacked: Bool = !uopNum.orR } class RobCommitEntryBundle(implicit p: Parameters) extends XSBundle { val walk_v = Bool() val commit_v = Bool() val commit_w = Bool() val realDestSize = UInt(log2Up(MaxUopSize + 1).W) val interrupt_safe = Bool() val wflags = Bool() val fflags = UInt(5.W) val vxsat = Bool() val isRVC = Bool() val isVset = Bool() val isHls = Bool() val isVls = Bool() val vls = Bool() val mmio = Bool() val commitType = CommitType() val ftqIdx = new FtqPtr val ftqOffset = UInt(log2Up(PredictWidth).W) val instrSize = UInt(log2Ceil(RenameWidth + 1).W) val fpWen = Bool() val rfWen = Bool() val needFlush = Bool() // trace val traceBlockInPipe = new TracePipe(IretireWidthInPipe) // debug_begin val debug_pc = OptionWrapper(backendParams.debugEn, UInt(VAddrBits.W)) val debug_instr = OptionWrapper(backendParams.debugEn, UInt(32.W)) val debug_ldest = OptionWrapper(backendParams.basicDebugEn, UInt(LogicRegsWidth.W)) val debug_pdest = OptionWrapper(backendParams.basicDebugEn, UInt(PhyRegIdxWidth.W)) val debug_fuType = OptionWrapper(backendParams.debugEn, FuType()) // debug_end val dirtyFs = Bool() val dirtyVs = Bool() } def connectEnq(robEntry: RobEntryBundle, robEnq: DynInst): Unit = { robEntry.wflags := robEnq.wfflags robEntry.commitType := robEnq.commitType robEntry.ftqIdx := robEnq.ftqPtr robEntry.ftqOffset := robEnq.ftqOffset robEntry.isRVC := robEnq.preDecodeInfo.isRVC robEntry.isVset := robEnq.isVset robEntry.isHls := robEnq.isHls robEntry.instrSize := robEnq.instrSize robEntry.rfWen := robEnq.rfWen robEntry.fpWen := robEnq.dirtyFs robEntry.dirtyVs := robEnq.dirtyVs // flushPipe needFlush but not exception robEntry.needFlush := robEnq.hasException || robEnq.flushPipe // trace robEntry.traceBlockInPipe := robEnq.traceBlockInPipe robEntry.debug_pc.foreach(_ := robEnq.pc) robEntry.debug_instr.foreach(_ := robEnq.instr) robEntry.debug_ldest.foreach(_ := robEnq.ldest) robEntry.debug_pdest.foreach(_ := robEnq.pdest) robEntry.debug_fuType.foreach(_ := robEnq.fuType) } def connectCommitEntry(robCommitEntry: RobCommitEntryBundle, robEntry: RobEntryBundle): Unit = { robCommitEntry.walk_v := robEntry.valid robCommitEntry.commit_v := robEntry.valid robCommitEntry.commit_w := (robEntry.uopNum === 0.U) && (robEntry.stdWritebacked === true.B) robCommitEntry.realDestSize := robEntry.realDestSize robCommitEntry.interrupt_safe := robEntry.interrupt_safe robCommitEntry.rfWen := robEntry.rfWen robCommitEntry.fpWen := robEntry.fpWen robCommitEntry.fflags := robEntry.fflags robCommitEntry.wflags := robEntry.wflags robCommitEntry.vxsat := robEntry.vxsat robCommitEntry.isRVC := robEntry.isRVC robCommitEntry.isVset := robEntry.isVset robCommitEntry.isHls := robEntry.isHls robCommitEntry.isVls := robEntry.vls robCommitEntry.vls := robEntry.vls robCommitEntry.mmio := robEntry.mmio robCommitEntry.ftqIdx := robEntry.ftqIdx robCommitEntry.ftqOffset := robEntry.ftqOffset robCommitEntry.commitType := robEntry.commitType robCommitEntry.instrSize := robEntry.instrSize robCommitEntry.dirtyFs := robEntry.fpWen || robEntry.wflags robCommitEntry.dirtyVs := robEntry.dirtyVs robCommitEntry.needFlush := robEntry.needFlush robCommitEntry.traceBlockInPipe := robEntry.traceBlockInPipe robCommitEntry.debug_pc.foreach(_ := robEntry.debug_pc.get) robCommitEntry.debug_instr.foreach(_ := robEntry.debug_instr.get) robCommitEntry.debug_ldest.foreach(_ := robEntry.debug_ldest.get) robCommitEntry.debug_pdest.foreach(_ := robEntry.debug_pdest.get) robCommitEntry.debug_fuType.foreach(_ := robEntry.debug_fuType.get) } } import RobBundles._ class RobPtr(entries: Int) extends CircularQueuePtr[RobPtr]( entries ) with HasCircularQueuePtrHelper { def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).RobSize) def needFlush(redirect: Valid[Redirect]): Bool = { val flushItself = redirect.bits.flushItself() && this === redirect.bits.robIdx redirect.valid && (flushItself || isAfter(this, redirect.bits.robIdx)) } def needFlush(redirect: Seq[Valid[Redirect]]): Bool = VecInit(redirect.map(needFlush)).asUInt.orR def lineHeadPtr(implicit p: Parameters): RobPtr = { val CommitWidth = p(XSCoreParamsKey).CommitWidth val out = Wire(new RobPtr) out.flag := this.flag out.value := Cat(this.value(this.PTR_WIDTH-1, log2Up(CommitWidth)), 0.U(log2Up(CommitWidth).W)) out } } object RobPtr { def apply(f: Bool, v: UInt)(implicit p: Parameters): RobPtr = { val ptr = Wire(new RobPtr) ptr.flag := f ptr.value := v ptr } } class RobCSRIO(implicit p: Parameters) extends XSBundle { val intrBitSet = Input(Bool()) val trapTarget = Input(new TargetPCBundle) val isXRet = Input(Bool()) val wfiEvent = Input(Bool()) val criticalErrorState = Input(Bool()) val fflags = Output(Valid(UInt(5.W))) val vxsat = Output(Valid(Bool())) val vstart = Output(Valid(UInt(XLEN.W))) val dirty_fs = Output(Bool()) val dirty_vs = Output(Bool()) val perfinfo = new Bundle { val retiredInstr = Output(UInt(7.W)) } } class RobLsqIO(implicit p: Parameters) extends XSBundle { val lcommit = Output(UInt(log2Up(CommitWidth + 1).W)) val scommit = Output(UInt(log2Up(CommitWidth + 1).W)) val pendingMMIOld = Output(Bool()) val pendingld = Output(Bool()) val pendingst = Output(Bool()) // set when vector store at the head of ROB val pendingVst = Output(Bool()) val commit = Output(Bool()) val pendingPtr = Output(new RobPtr) val pendingPtrNext = Output(new RobPtr) val mmio = Input(Vec(LoadPipelineWidth, Bool())) // Todo: what's this? val uop = Input(Vec(LoadPipelineWidth, new DynInst)) } class RobEnqIO(implicit p: Parameters) extends XSBundle { val canAccept = Output(Bool()) val canAcceptForDispatch = Output(Bool()) val isEmpty = Output(Bool()) // valid vector, for robIdx gen and walk val needAlloc = Vec(RenameWidth, Input(Bool())) val req = Vec(RenameWidth, Flipped(ValidIO(new DynInst))) val resp = Vec(RenameWidth, Output(new RobPtr)) } class RobCoreTopDownIO(implicit p: Parameters) extends XSBundle { val robHeadVaddr = Valid(UInt(VAddrBits.W)) val robHeadPaddr = Valid(UInt(PAddrBits.W)) } class RobDispatchTopDownIO extends Bundle { val robTrueCommit = Output(UInt(64.W)) val robHeadLsIssue = Output(Bool()) } class RobDebugRollingIO extends Bundle { val robTrueCommit = Output(UInt(64.W)) } class RobExceptionInfo(implicit p: Parameters) extends XSBundle { // val valid = Bool() val robIdx = new RobPtr val ftqPtr = new FtqPtr val ftqOffset = UInt(log2Up(PredictWidth).W) // set 1 if there is 1 exists in exceptionVec val hasException = Bool() // This signal is valid iff currentValid is true // 0: is execute exception, 1: is fetch exception val isEnqExcp = Bool() val exceptionVec = ExceptionVec() val isFetchMalAddr = Bool() val flushPipe = Bool() val isVset = Bool() val replayInst = Bool() // redirect to that inst itself val singleStep = Bool() // TODO add frontend hit beneath val crossPageIPFFix = Bool() val trigger = TriggerAction() // if vstart is udpated by vector unit val vstartEn = Bool() val vstart = UInt(XLEN.W) val vuopIdx = UopIdx() val isVecLoad = Bool() val isVlm = Bool() val isStrided = Bool() val isIndexed = Bool() val isWhole = Bool() val nf = Nf() val vsew = VSew() val veew = VSew() val vlmul = VLmul() def has_exception = hasException || flushPipe || singleStep || replayInst || TriggerAction.isDmode(trigger) def not_commit = hasException || singleStep || replayInst || TriggerAction.isDmode(trigger) // only exceptions are allowed to writeback when enqueue def can_writeback = hasException || singleStep || TriggerAction.isDmode(trigger) } class RobFlushInfo(implicit p: Parameters) extends XSBundle { val ftqIdx = new FtqPtr val robIdx = new RobPtr val ftqOffset = UInt(log2Up(PredictWidth).W) val replayInst = Bool() }