xref: /XiangShan/src/main/scala/xiangshan/backend/rob/RobBundles.scala (revision 08373300e7dc356da02def6f35eae78b429872a7)
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