1/*************************************************************************************** 2 * Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3 * Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 4 * Copyright (c) 2020-2021 Peng Cheng Laboratory 5 * 6 * XiangShan is licensed under Mulan PSL v2. 7 * You can use this software according to the terms and conditions of the Mulan PSL v2. 8 * You may obtain a copy of Mulan PSL v2 at: 9 * http://license.coscl.org.cn/MulanPSL2 10 * 11 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 12 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14 * 15 * See the Mulan PSL v2 for more details. 16 ***************************************************************************************/ 17 18package xiangshan.backend.rob 19 20import org.chipsalliance.cde.config.Parameters 21import chisel3.{Mem, Mux, Vec, _} 22import chisel3.util._ 23import difftest._ 24import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 25import utility._ 26import utils._ 27import xiangshan._ 28import xiangshan.backend.BackendParams 29import xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput, UopIdx} 30import xiangshan.backend.fu.{FuConfig, FuType} 31import xiangshan.frontend.FtqPtr 32import xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr} 33import xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput} 34import xiangshan.backend.ctrlblock.{DebugLSIO, DebugLsInfo, LsTopdownInfo} 35import xiangshan.backend.fu.NewCSR.CSREvents.TargetPCBundle 36import xiangshan.backend.fu.vector.Bundles.{Nf, VLmul, VSew, VType} 37import xiangshan.backend.rename.SnapshotGenerator 38import xiangshan.backend.trace._ 39 40import scala.collection.immutable.Nil 41 42 43 44object RobBundles extends HasCircularQueuePtrHelper { 45 46 class RobEntryBundle(implicit p: Parameters) extends XSBundle { 47 48 // data begin 49 val vls = Bool() 50 // some instructions are not allowed to trigger interrupts 51 // They have side effects on the states of the processor before they write back 52 val interrupt_safe = Bool() 53 val fpWen = Bool() 54 val rfWen = Bool() 55 val wflags = Bool() 56 val dirtyVs = Bool() 57 val commitType = CommitType() 58 val ftqIdx = new FtqPtr 59 val ftqOffset = UInt(log2Up(PredictWidth).W) 60 val isRVC = Bool() 61 val isVset = Bool() 62 val isHls = Bool() 63 val instrSize = UInt(log2Ceil(RenameWidth + 1).W) 64 // data end 65 66 // trace 67 val traceBlockInPipe = new TracePipe(IretireWidthInPipe) 68 // status begin 69 val valid = Bool() 70 val fflags = UInt(5.W) 71 val mmio = Bool() 72 // store will be commited if both sta & std have been writebacked 73 val stdWritebacked = Bool() 74 val vxsat = Bool() 75 val realDestSize = UInt(log2Up(MaxUopSize + 1).W) 76 val uopNum = UInt(log2Up(MaxUopSize + 1).W) 77 val needFlush = Bool() 78 // status end 79 80 // debug_begin 81 val debug_pc = OptionWrapper(backendParams.debugEn, UInt(VAddrBits.W)) 82 val debug_instr = OptionWrapper(backendParams.debugEn, UInt(32.W)) 83 val debug_ldest = OptionWrapper(backendParams.basicDebugEn, UInt(LogicRegsWidth.W)) 84 val debug_pdest = OptionWrapper(backendParams.basicDebugEn, UInt(PhyRegIdxWidth.W)) 85 val debug_fuType = OptionWrapper(backendParams.debugEn, FuType()) 86 // debug_end 87 88 def isWritebacked: Bool = !uopNum.orR && stdWritebacked 89 def isUopWritebacked: Bool = !uopNum.orR 90 91 } 92 93 class RobCommitEntryBundle(implicit p: Parameters) extends XSBundle { 94 val walk_v = Bool() 95 val commit_v = Bool() 96 val commit_w = Bool() 97 val realDestSize = UInt(log2Up(MaxUopSize + 1).W) 98 val interrupt_safe = Bool() 99 val wflags = Bool() 100 val fflags = UInt(5.W) 101 val vxsat = Bool() 102 val isRVC = Bool() 103 val isVset = Bool() 104 val isHls = Bool() 105 val isVls = Bool() 106 val vls = Bool() 107 val mmio = Bool() 108 val commitType = CommitType() 109 val ftqIdx = new FtqPtr 110 val ftqOffset = UInt(log2Up(PredictWidth).W) 111 val instrSize = UInt(log2Ceil(RenameWidth + 1).W) 112 val fpWen = Bool() 113 val rfWen = Bool() 114 val needFlush = Bool() 115 // trace 116 val traceBlockInPipe = new TracePipe(IretireWidthInPipe) 117 // debug_begin 118 val debug_pc = OptionWrapper(backendParams.debugEn, UInt(VAddrBits.W)) 119 val debug_instr = OptionWrapper(backendParams.debugEn, UInt(32.W)) 120 val debug_ldest = OptionWrapper(backendParams.basicDebugEn, UInt(LogicRegsWidth.W)) 121 val debug_pdest = OptionWrapper(backendParams.basicDebugEn, UInt(PhyRegIdxWidth.W)) 122 val debug_otherPdest = OptionWrapper(backendParams.basicDebugEn, Vec(7, UInt(PhyRegIdxWidth.W))) 123 val debug_fuType = OptionWrapper(backendParams.debugEn, FuType()) 124 // debug_end 125 val dirtyFs = Bool() 126 val dirtyVs = Bool() 127 } 128 129 def connectEnq(robEntry: RobEntryBundle, robEnq: DynInst): Unit = { 130 robEntry.wflags := robEnq.wfflags 131 robEntry.commitType := robEnq.commitType 132 robEntry.ftqIdx := robEnq.ftqPtr 133 robEntry.ftqOffset := robEnq.ftqOffset 134 robEntry.isRVC := robEnq.preDecodeInfo.isRVC 135 robEntry.isVset := robEnq.isVset 136 robEntry.isHls := robEnq.isHls 137 robEntry.instrSize := robEnq.instrSize 138 robEntry.rfWen := robEnq.rfWen 139 robEntry.fpWen := robEnq.dirtyFs 140 robEntry.dirtyVs := robEnq.dirtyVs 141 // flushPipe needFlush but not exception 142 robEntry.needFlush := robEnq.hasException || robEnq.flushPipe 143 // trace 144 robEntry.traceBlockInPipe := robEnq.traceBlockInPipe 145 robEntry.debug_pc.foreach(_ := robEnq.pc) 146 robEntry.debug_instr.foreach(_ := robEnq.instr) 147 robEntry.debug_ldest.foreach(_ := robEnq.ldest) 148 robEntry.debug_pdest.foreach(_ := robEnq.pdest) 149 robEntry.debug_fuType.foreach(_ := robEnq.fuType) 150 } 151 152 def connectCommitEntry(robCommitEntry: RobCommitEntryBundle, robEntry: RobEntryBundle): Unit = { 153 robCommitEntry.walk_v := robEntry.valid 154 robCommitEntry.commit_v := robEntry.valid 155 robCommitEntry.commit_w := (robEntry.uopNum === 0.U) && (robEntry.stdWritebacked === true.B) 156 robCommitEntry.realDestSize := robEntry.realDestSize 157 robCommitEntry.interrupt_safe := robEntry.interrupt_safe 158 robCommitEntry.rfWen := robEntry.rfWen 159 robCommitEntry.fpWen := robEntry.fpWen 160 robCommitEntry.fflags := robEntry.fflags 161 robCommitEntry.wflags := robEntry.wflags 162 robCommitEntry.vxsat := robEntry.vxsat 163 robCommitEntry.isRVC := robEntry.isRVC 164 robCommitEntry.isVset := robEntry.isVset 165 robCommitEntry.isHls := robEntry.isHls 166 robCommitEntry.isVls := robEntry.vls 167 robCommitEntry.vls := robEntry.vls 168 robCommitEntry.mmio := robEntry.mmio 169 robCommitEntry.ftqIdx := robEntry.ftqIdx 170 robCommitEntry.ftqOffset := robEntry.ftqOffset 171 robCommitEntry.commitType := robEntry.commitType 172 robCommitEntry.instrSize := robEntry.instrSize 173 robCommitEntry.dirtyFs := robEntry.fpWen || robEntry.wflags 174 robCommitEntry.dirtyVs := robEntry.dirtyVs 175 robCommitEntry.needFlush := robEntry.needFlush 176 robCommitEntry.traceBlockInPipe := robEntry.traceBlockInPipe 177 robCommitEntry.debug_pc.foreach(_ := robEntry.debug_pc.get) 178 robCommitEntry.debug_instr.foreach(_ := robEntry.debug_instr.get) 179 robCommitEntry.debug_ldest.foreach(_ := robEntry.debug_ldest.get) 180 robCommitEntry.debug_pdest.foreach(_ := robEntry.debug_pdest.get) 181 robCommitEntry.debug_fuType.foreach(_ := robEntry.debug_fuType.get) 182 } 183} 184 185import RobBundles._ 186 187class RobPtr(entries: Int) extends CircularQueuePtr[RobPtr]( 188 entries 189) with HasCircularQueuePtrHelper { 190 191 def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).RobSize) 192 193 def needFlush(redirect: Valid[Redirect]): Bool = { 194 val flushItself = redirect.bits.flushItself() && this === redirect.bits.robIdx 195 redirect.valid && (flushItself || isAfter(this, redirect.bits.robIdx)) 196 } 197 198 def needFlush(redirect: Seq[Valid[Redirect]]): Bool = VecInit(redirect.map(needFlush)).asUInt.orR 199 200 def lineHeadPtr(implicit p: Parameters): RobPtr = { 201 val CommitWidth = p(XSCoreParamsKey).CommitWidth 202 val out = Wire(new RobPtr) 203 out.flag := this.flag 204 out.value := Cat(this.value(this.PTR_WIDTH-1, log2Up(CommitWidth)), 0.U(log2Up(CommitWidth).W)) 205 out 206 } 207 208} 209 210object RobPtr { 211 def apply(f: Bool, v: UInt)(implicit p: Parameters): RobPtr = { 212 val ptr = Wire(new RobPtr) 213 ptr.flag := f 214 ptr.value := v 215 ptr 216 } 217} 218 219class RobCSRIO(implicit p: Parameters) extends XSBundle { 220 val intrBitSet = Input(Bool()) 221 val trapTarget = Input(new TargetPCBundle) 222 val isXRet = Input(Bool()) 223 val wfiEvent = Input(Bool()) 224 val criticalErrorState = Input(Bool()) 225 226 val fflags = Output(Valid(UInt(5.W))) 227 val vxsat = Output(Valid(Bool())) 228 val vstart = Output(Valid(UInt(XLEN.W))) 229 val dirty_fs = Output(Bool()) 230 val dirty_vs = Output(Bool()) 231 val perfinfo = new Bundle { 232 val retiredInstr = Output(UInt(7.W)) 233 } 234} 235 236class RobLsqIO(implicit p: Parameters) extends XSBundle { 237 val lcommit = Output(UInt(log2Up(CommitWidth + 1).W)) 238 val scommit = Output(UInt(log2Up(CommitWidth + 1).W)) 239 val pendingMMIOld = Output(Bool()) 240 val pendingld = Output(Bool()) 241 val pendingst = Output(Bool()) 242 // set when vector store at the head of ROB 243 val pendingVst = Output(Bool()) 244 val commit = Output(Bool()) 245 val pendingPtr = Output(new RobPtr) 246 val pendingPtrNext = Output(new RobPtr) 247 248 val mmio = Input(Vec(LoadPipelineWidth, Bool())) 249 // Todo: what's this? 250 val uop = Input(Vec(LoadPipelineWidth, new DynInst)) 251} 252 253class RobEnqIO(implicit p: Parameters) extends XSBundle { 254 val canAccept = Output(Bool()) 255 val canAcceptForDispatch = Output(Bool()) 256 val isEmpty = Output(Bool()) 257 // valid vector, for robIdx gen and walk 258 val needAlloc = Vec(RenameWidth, Input(Bool())) 259 val req = Vec(RenameWidth, Flipped(ValidIO(new DynInst))) 260 val resp = Vec(RenameWidth, Output(new RobPtr)) 261} 262 263class RobCoreTopDownIO(implicit p: Parameters) extends XSBundle { 264 val robHeadVaddr = Valid(UInt(VAddrBits.W)) 265 val robHeadPaddr = Valid(UInt(PAddrBits.W)) 266} 267 268class RobDispatchTopDownIO extends Bundle { 269 val robTrueCommit = Output(UInt(64.W)) 270 val robHeadLsIssue = Output(Bool()) 271} 272 273class RobDebugRollingIO extends Bundle { 274 val robTrueCommit = Output(UInt(64.W)) 275} 276 277class RobExceptionInfo(implicit p: Parameters) extends XSBundle { 278 // val valid = Bool() 279 val robIdx = new RobPtr 280 val ftqPtr = new FtqPtr 281 val ftqOffset = UInt(log2Up(PredictWidth).W) 282 // set 1 if there is 1 exists in exceptionVec 283 val hasException = Bool() 284 // This signal is valid iff currentValid is true 285 // 0: is execute exception, 1: is fetch exception 286 val isEnqExcp = Bool() 287 val exceptionVec = ExceptionVec() 288 val isFetchMalAddr = Bool() 289 val flushPipe = Bool() 290 val isVset = Bool() 291 val replayInst = Bool() // redirect to that inst itself 292 val singleStep = Bool() // TODO add frontend hit beneath 293 val crossPageIPFFix = Bool() 294 val trigger = TriggerAction() 295 // if vstart is udpated by vector unit 296 val vstartEn = Bool() 297 val vstart = UInt(XLEN.W) 298 val vuopIdx = UopIdx() 299 val isVecLoad = Bool() 300 val isVlm = Bool() 301 val isStrided = Bool() 302 val isIndexed = Bool() 303 val isWhole = Bool() 304 val nf = Nf() 305 val vsew = VSew() 306 val veew = VSew() 307 val vlmul = VLmul() 308 309 def has_exception = hasException || flushPipe || singleStep || replayInst || TriggerAction.isDmode(trigger) 310 def not_commit = hasException || singleStep || replayInst || TriggerAction.isDmode(trigger) 311 // only exceptions are allowed to writeback when enqueue 312 def can_writeback = hasException || singleStep || TriggerAction.isDmode(trigger) 313} 314 315class RobFlushInfo(implicit p: Parameters) extends XSBundle { 316 val ftqIdx = new FtqPtr 317 val robIdx = new RobPtr 318 val ftqOffset = UInt(log2Up(PredictWidth).W) 319 val replayInst = Bool() 320} 321