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