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} 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.vector.Bundles.VType 36import xiangshan.backend.rename.SnapshotGenerator 37 38import scala.collection.immutable.Nil 39 40 41 42object RobBundles extends HasCircularQueuePtrHelper { 43 44 class RobEntryBundle(implicit p: Parameters) extends XSBundle { 45 46 // data begin 47 val vls = Bool() 48 // some instructions are not allowed to trigger interrupts 49 // They have side effects on the states of the processor before they write back 50 val interrupt_safe = Bool() 51 val fpWen = Bool() 52 val rfWen = Bool() 53 val wflags = Bool() 54 val dirtyVs = Bool() 55 val commitType = CommitType() 56 val ftqIdx = new FtqPtr 57 val ftqOffset = UInt(log2Up(PredictWidth).W) 58 val isRVC = Bool() 59 val isVset = Bool() 60 val isHls = Bool() 61 val instrSize = UInt(log2Ceil(RenameWidth + 1).W) 62 val loadWaitBit = Bool() // for perfEvents 63 val eliminatedMove = Bool() // for perfEvents 64 // data end 65 66 // status begin 67 val valid = Bool() 68 val fflags = UInt(5.W) 69 val mmio = Bool() 70 // store will be commited if both sta & std have been writebacked 71 val stdWritebacked = Bool() 72 val vxsat = Bool() 73 val realDestSize = UInt(log2Up(MaxUopSize + 1).W) 74 val uopNum = UInt(log2Up(MaxUopSize + 1).W) 75 val commitTrigger = Bool() 76 val needFlush = Bool() 77 // status end 78 79 // debug_begin 80 val debug_pc = OptionWrapper(backendParams.debugEn, UInt(VAddrBits.W)) 81 val debug_instr = OptionWrapper(backendParams.debugEn, UInt(32.W)) 82 val debug_ldest = OptionWrapper(backendParams.debugEn, UInt(LogicRegsWidth.W)) 83 val debug_pdest = OptionWrapper(backendParams.debugEn, UInt(PhyRegIdxWidth.W)) 84 val debug_fuType = OptionWrapper(backendParams.debugEn, FuType()) 85 // debug_end 86 87 def isWritebacked: Bool = !uopNum.orR && stdWritebacked 88 def isUopWritebacked: Bool = !uopNum.orR 89 90 } 91 92 class RobCommitEntryBundle(implicit p: Parameters) extends XSBundle { 93 val walk_v = Bool() 94 val commit_v = Bool() 95 val commit_w = Bool() 96 val realDestSize = UInt(log2Up(MaxUopSize + 1).W) 97 val interrupt_safe = Bool() 98 val wflags = Bool() 99 val fflags = UInt(5.W) 100 val vxsat = Bool() 101 val isRVC = Bool() 102 val isVset = Bool() 103 val isHls = Bool() 104 val commitType = CommitType() 105 val ftqIdx = new FtqPtr 106 val ftqOffset = UInt(log2Up(PredictWidth).W) 107 val instrSize = UInt(log2Ceil(RenameWidth + 1).W) 108 val fpWen = Bool() 109 val rfWen = Bool() 110 val loadWaitBit = Bool() // for perfEvents 111 val isMove = Bool() // for perfEvents 112 val needFlush = Bool() 113 // debug_begin 114 val debug_pc = OptionWrapper(backendParams.debugEn, UInt(VAddrBits.W)) 115 val debug_instr = OptionWrapper(backendParams.debugEn, UInt(32.W)) 116 val debug_ldest = OptionWrapper(backendParams.debugEn, UInt(LogicRegsWidth.W)) 117 val debug_pdest = OptionWrapper(backendParams.debugEn, UInt(PhyRegIdxWidth.W)) 118 val debug_fuType = OptionWrapper(backendParams.debugEn, FuType()) 119 // debug_end 120 val dirtyFs = Bool() 121 val dirtyVs = Bool() 122 } 123 124 def connectEnq(robEntry: RobEntryBundle, robEnq: DynInst): Unit = { 125 robEntry.wflags := robEnq.wfflags 126 robEntry.commitType := robEnq.commitType 127 robEntry.ftqIdx := robEnq.ftqPtr 128 robEntry.ftqOffset := robEnq.ftqOffset 129 robEntry.isRVC := robEnq.preDecodeInfo.isRVC 130 robEntry.isVset := robEnq.isVset 131 robEntry.isHls := robEnq.isHls 132 robEntry.instrSize := robEnq.instrSize 133 robEntry.rfWen := robEnq.rfWen 134 robEntry.fpWen := robEnq.dirtyFs 135 robEntry.dirtyVs := robEnq.dirtyVs 136 robEntry.loadWaitBit := robEnq.loadWaitBit 137 robEntry.eliminatedMove := robEnq.eliminatedMove 138 // flushPipe needFlush but not exception 139 robEntry.needFlush := robEnq.hasException || robEnq.flushPipe 140 robEntry.debug_pc.foreach(_ := robEnq.pc) 141 robEntry.debug_instr.foreach(_ := robEnq.instr) 142 robEntry.debug_ldest.foreach(_ := robEnq.ldest) 143 robEntry.debug_pdest.foreach(_ := robEnq.pdest) 144 robEntry.debug_fuType.foreach(_ := robEnq.fuType) 145 } 146 147 def connectCommitEntry(robCommitEntry: RobCommitEntryBundle, robEntry: RobEntryBundle): Unit = { 148 robCommitEntry.walk_v := robEntry.valid 149 robCommitEntry.commit_v := robEntry.valid 150 robCommitEntry.commit_w := (robEntry.uopNum === 0.U) && (robEntry.stdWritebacked === true.B) 151 robCommitEntry.realDestSize := robEntry.realDestSize 152 robCommitEntry.interrupt_safe := robEntry.interrupt_safe 153 robCommitEntry.rfWen := robEntry.rfWen 154 robCommitEntry.fpWen := robEntry.fpWen 155 robCommitEntry.fflags := robEntry.fflags 156 robCommitEntry.wflags := robEntry.wflags 157 robCommitEntry.vxsat := robEntry.vxsat 158 robCommitEntry.isRVC := robEntry.isRVC 159 robCommitEntry.isVset := robEntry.isVset 160 robCommitEntry.isHls := robEntry.isHls 161 robCommitEntry.ftqIdx := robEntry.ftqIdx 162 robCommitEntry.ftqOffset := robEntry.ftqOffset 163 robCommitEntry.commitType := robEntry.commitType 164 robCommitEntry.instrSize := robEntry.instrSize 165 robCommitEntry.loadWaitBit := robEntry.loadWaitBit 166 robCommitEntry.isMove := robEntry.eliminatedMove 167 robCommitEntry.dirtyFs := robEntry.fpWen || robEntry.wflags 168 robCommitEntry.dirtyVs := robEntry.dirtyVs 169 robCommitEntry.needFlush := robEntry.needFlush 170 robCommitEntry.debug_pc.foreach(_ := robEntry.debug_pc.get) 171 robCommitEntry.debug_instr.foreach(_ := robEntry.debug_instr.get) 172 robCommitEntry.debug_ldest.foreach(_ := robEntry.debug_ldest.get) 173 robCommitEntry.debug_pdest.foreach(_ := robEntry.debug_pdest.get) 174 robCommitEntry.debug_fuType.foreach(_ := robEntry.debug_fuType.get) 175 } 176} 177 178import RobBundles._ 179 180class RobPtr(entries: Int) extends CircularQueuePtr[RobPtr]( 181 entries 182) with HasCircularQueuePtrHelper { 183 184 def this()(implicit p: Parameters) = this(p(XSCoreParamsKey).RobSize) 185 186 def needFlush(redirect: Valid[Redirect]): Bool = { 187 val flushItself = redirect.bits.flushItself() && this === redirect.bits.robIdx 188 redirect.valid && (flushItself || isAfter(this, redirect.bits.robIdx)) 189 } 190 191 def needFlush(redirect: Seq[Valid[Redirect]]): Bool = VecInit(redirect.map(needFlush)).asUInt.orR 192 193 def lineHeadPtr(implicit p: Parameters): RobPtr = { 194 val CommitWidth = p(XSCoreParamsKey).CommitWidth 195 val out = Wire(new RobPtr) 196 out.flag := this.flag 197 out.value := Cat(this.value(this.PTR_WIDTH-1, log2Up(CommitWidth)), 0.U(log2Up(CommitWidth).W)) 198 out 199 } 200 201} 202 203object RobPtr { 204 def apply(f: Bool, v: UInt)(implicit p: Parameters): RobPtr = { 205 val ptr = Wire(new RobPtr) 206 ptr.flag := f 207 ptr.value := v 208 ptr 209 } 210} 211 212class RobCSRIO(implicit p: Parameters) extends XSBundle { 213 val intrBitSet = Input(Bool()) 214 val trapTarget = Input(UInt(VAddrBits.W)) 215 val isXRet = Input(Bool()) 216 val wfiEvent = Input(Bool()) 217 218 val fflags = Output(Valid(UInt(5.W))) 219 val vxsat = Output(Valid(Bool())) 220 val vstart = Output(Valid(UInt(XLEN.W))) 221 val dirty_fs = Output(Bool()) 222 val dirty_vs = Output(Bool()) 223 val perfinfo = new Bundle { 224 val retiredInstr = Output(UInt(3.W)) 225 } 226} 227 228class RobLsqIO(implicit p: Parameters) extends XSBundle { 229 val lcommit = Output(UInt(log2Up(CommitWidth + 1).W)) 230 val scommit = Output(UInt(log2Up(CommitWidth + 1).W)) 231 val pendingld = Output(Bool()) 232 val pendingst = Output(Bool()) 233 // set when vector store at the head of ROB 234 val pendingVst = Output(Bool()) 235 val commit = Output(Bool()) 236 val pendingPtr = Output(new RobPtr) 237 val pendingPtrNext = Output(new RobPtr) 238 239 val mmio = Input(Vec(LoadPipelineWidth, Bool())) 240 // Todo: what's this? 241 val uop = Input(Vec(LoadPipelineWidth, new DynInst)) 242} 243 244class RobEnqIO(implicit p: Parameters) extends XSBundle { 245 val canAccept = Output(Bool()) 246 val isEmpty = Output(Bool()) 247 // valid vector, for robIdx gen and walk 248 val needAlloc = Vec(RenameWidth, Input(Bool())) 249 val req = Vec(RenameWidth, Flipped(ValidIO(new DynInst))) 250 val resp = Vec(RenameWidth, Output(new RobPtr)) 251} 252 253class RobCoreTopDownIO(implicit p: Parameters) extends XSBundle { 254 val robHeadVaddr = Valid(UInt(VAddrBits.W)) 255 val robHeadPaddr = Valid(UInt(PAddrBits.W)) 256} 257 258class RobDispatchTopDownIO extends Bundle { 259 val robTrueCommit = Output(UInt(64.W)) 260 val robHeadLsIssue = Output(Bool()) 261} 262 263class RobDebugRollingIO extends Bundle { 264 val robTrueCommit = Output(UInt(64.W)) 265} 266 267class RobExceptionInfo(implicit p: Parameters) extends XSBundle { 268 // val valid = Bool() 269 val robIdx = new RobPtr 270 val ftqPtr = new FtqPtr 271 val ftqOffset = UInt(log2Up(PredictWidth).W) 272 // set 1 if there is 1 exists in exceptionVec 273 val hasException = Bool() 274 val exceptionVec = ExceptionVec() 275 val flushPipe = Bool() 276 val isVset = Bool() 277 val replayInst = Bool() // redirect to that inst itself 278 val singleStep = Bool() // TODO add frontend hit beneath 279 val crossPageIPFFix = Bool() 280 val trigger = new TriggerCf 281 val vstartEn = Bool() 282 val vstart = UInt(XLEN.W) 283 284 def has_exception = hasException || flushPipe || singleStep || replayInst || trigger.canFire 285 def not_commit = hasException || singleStep || replayInst || trigger.canFire 286 // only exceptions are allowed to writeback when enqueue 287 def can_writeback = hasException || singleStep || trigger.canFire 288} 289 290class RobFlushInfo(implicit p: Parameters) extends XSBundle { 291 val ftqIdx = new FtqPtr 292 val robIdx = new RobPtr 293 val ftqOffset = UInt(log2Up(PredictWidth).W) 294 val replayInst = Bool() 295} 296