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