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