xref: /XiangShan/src/main/scala/xiangshan/Bundle.scala (revision d471c5ae8f3d7ab46a2f39622fdc3dee5c40be01)
1package xiangshan
2
3import chisel3._
4import chisel3.util._
5import xiangshan.backend.SelImm
6import xiangshan.backend.brq.BrqPtr
7import xiangshan.backend.fu.fpu.Fflags
8import xiangshan.backend.rename.FreeListPtr
9import xiangshan.backend.roq.RoqPtr
10import xiangshan.backend.decode.XDecode
11import xiangshan.mem.{LqPtr, SqPtr}
12import xiangshan.frontend.PreDecodeInfo
13import xiangshan.frontend.HasBPUParameter
14import xiangshan.frontend.HasTageParameter
15import xiangshan.frontend.HasIFUConst
16import xiangshan.frontend.GlobalHistory
17import utils._
18import scala.math.max
19import Chisel.experimental.chiselName
20
21// Fetch FetchWidth x 32-bit insts from Icache
22class FetchPacket extends XSBundle {
23  val instrs = Vec(PredictWidth, UInt(32.W))
24  val mask = UInt(PredictWidth.W)
25  val pdmask = UInt(PredictWidth.W)
26  // val pc = UInt(VAddrBits.W)
27  val pc = Vec(PredictWidth, UInt(VAddrBits.W))
28  val pnpc = Vec(PredictWidth, UInt(VAddrBits.W))
29  val bpuMeta = Vec(PredictWidth, new BpuMeta)
30  val pd = Vec(PredictWidth, new PreDecodeInfo)
31  val ipf = Bool()
32  val acf = Bool()
33  val crossPageIPFFix = Bool()
34  val predTaken = Bool()
35}
36
37class ValidUndirectioned[T <: Data](gen: T) extends Bundle {
38  val valid = Bool()
39  val bits = gen.cloneType.asInstanceOf[T]
40  override def cloneType = new ValidUndirectioned(gen).asInstanceOf[this.type]
41}
42
43object ValidUndirectioned {
44  def apply[T <: Data](gen: T) = {
45    new ValidUndirectioned[T](gen)
46  }
47}
48
49class SCMeta(val useSC: Boolean) extends XSBundle with HasTageParameter {
50  def maxVal = 8 * ((1 << TageCtrBits) - 1) + SCTableInfo.map{case (_,cb,_) => (1 << cb) - 1}.reduce(_+_)
51  def minVal = -(8 * (1 << TageCtrBits) + SCTableInfo.map{case (_,cb,_) => 1 << cb}.reduce(_+_))
52  def sumCtrBits = max(log2Ceil(-minVal), log2Ceil(maxVal+1)) + 1
53  val tageTaken = if (useSC) Bool() else UInt(0.W)
54  val scUsed    = if (useSC) Bool() else UInt(0.W)
55  val scPred    = if (useSC) Bool() else UInt(0.W)
56  // Suppose ctrbits of all tables are identical
57  val ctrs      = if (useSC) Vec(SCNTables, SInt(SCCtrBits.W)) else Vec(SCNTables, SInt(0.W))
58  val sumAbs    = if (useSC) UInt(sumCtrBits.W) else UInt(0.W)
59}
60
61class TageMeta extends XSBundle with HasTageParameter {
62  val provider = ValidUndirectioned(UInt(log2Ceil(TageNTables).W))
63  val altDiffers = Bool()
64  val providerU = UInt(2.W)
65  val providerCtr = UInt(3.W)
66  val allocate = ValidUndirectioned(UInt(log2Ceil(TageNTables).W))
67  val taken = Bool()
68  val scMeta = new SCMeta(EnableSC)
69}
70
71@chiselName
72class BranchPrediction extends XSBundle with HasIFUConst {
73  // val redirect = Bool()
74  val takens = UInt(PredictWidth.W)
75  // val jmpIdx = UInt(log2Up(PredictWidth).W)
76  val brMask = UInt(PredictWidth.W)
77  val jalMask = UInt(PredictWidth.W)
78  val targets = Vec(PredictWidth, UInt(VAddrBits.W))
79
80  // marks the last 2 bytes of this fetch packet
81  // val endsAtTheEndOfFirstBank = Bool()
82  // val endsAtTheEndOfLastBank = Bool()
83
84  // half RVI could only start at the end of a bank
85  val firstBankHasHalfRVI = Bool()
86  val lastBankHasHalfRVI = Bool()
87
88  // assumes that only one of the two conditions could be true
89  def lastHalfRVIMask = Cat(lastBankHasHalfRVI.asUInt, 0.U((bankWidth-1).W), firstBankHasHalfRVI.asUInt, 0.U((bankWidth-1).W)).suggestName("lastHalfRVIMask")
90
91  def lastHalfRVIClearMask = ~lastHalfRVIMask.suggestName("lastHalfRVIClearMask")
92  // is taken from half RVI
93  def lastHalfRVITaken = ((takens(bankWidth-1) && firstBankHasHalfRVI) || (takens(PredictWidth-1) && lastBankHasHalfRVI)).suggestName("lastHalfRVITaken")
94
95  def lastHalfRVIIdx = Mux(firstBankHasHalfRVI, (bankWidth-1).U, (PredictWidth-1).U).suggestName("lastHalfRVIIdx")
96  // should not be used if not lastHalfRVITaken
97  def lastHalfRVITarget = Mux(firstBankHasHalfRVI, targets(bankWidth-1), targets(PredictWidth-1)).suggestName("lastHalfRVITarget")
98
99  def realTakens  = (takens  & lastHalfRVIClearMask).suggestName("realTakens")
100  def realBrMask  = (brMask  & lastHalfRVIClearMask).suggestName("realBrMask")
101  def realJalMask = (jalMask & lastHalfRVIClearMask).suggestName("realJalMask")
102
103  def brNotTakens = (~takens & realBrMask).suggestName("brNotTakens")
104  def sawNotTakenBr = VecInit((0 until PredictWidth).map(i =>
105                       (if (i == 0) false.B else ParallelORR(brNotTakens(i-1,0))))).suggestName("sawNotTakenBr")
106  // def hasNotTakenBrs = (brNotTakens & LowerMaskFromLowest(realTakens)).orR
107  def unmaskedJmpIdx = ParallelPriorityEncoder(takens).suggestName("unmaskedJmpIdx")
108  // if not taken before the half RVI inst
109  def saveHalfRVI = ((firstBankHasHalfRVI && !(ParallelORR(takens(bankWidth-2,0)))) ||
110  (lastBankHasHalfRVI && !(ParallelORR(takens(PredictWidth-2,0))))).suggestName("saveHalfRVI")
111  // could get PredictWidth-1 when only the first bank is valid
112  def jmpIdx = ParallelPriorityEncoder(realTakens).suggestName("jmpIdx")
113  // only used when taken
114  def target = ParallelPriorityMux(realTakens, targets).suggestName("target")
115  def taken = ParallelORR(realTakens).suggestName("taken")
116  def takenOnBr = taken && ParallelPriorityMux(realTakens, realBrMask.asBools).suggestName("takenOnBr")
117  def hasNotTakenBrs = Mux(taken, ParallelPriorityMux(realTakens, sawNotTakenBr), ParallelORR(brNotTakens)).suggestName("hasNotTakenBrs")
118}
119
120class BpuMeta extends XSBundle with HasBPUParameter {
121  val ubtbWriteWay = UInt(log2Up(UBtbWays).W)
122  val ubtbHits = Bool()
123  val btbWriteWay = UInt(log2Up(BtbWays).W)
124  val btbHitJal = Bool()
125  val bimCtr = UInt(2.W)
126  val tageMeta = new TageMeta
127  val rasSp = UInt(log2Up(RasSize).W)
128  val rasTopCtr = UInt(8.W)
129  val rasToqAddr = UInt(VAddrBits.W)
130  val fetchIdx = UInt(log2Up(PredictWidth).W)
131  val specCnt = UInt(10.W)
132  // for global history
133  val predTaken = Bool()
134  val hist = new GlobalHistory
135  val predHist = new GlobalHistory
136  val sawNotTakenBranch = Bool()
137
138  val debug_ubtb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
139  val debug_btb_cycle  = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
140  val debug_tage_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
141
142  // def apply(histPtr: UInt, tageMeta: TageMeta, rasSp: UInt, rasTopCtr: UInt) = {
143  //   this.histPtr := histPtr
144  //   this.tageMeta := tageMeta
145  //   this.rasSp := rasSp
146  //   this.rasTopCtr := rasTopCtr
147  //   this.asUInt
148  // }
149  def size = 0.U.asTypeOf(this).getWidth
150  def fromUInt(x: UInt) = x.asTypeOf(this)
151}
152
153class Predecode extends XSBundle with HasIFUConst {
154  val hasLastHalfRVI = Bool()
155  val mask = UInt(PredictWidth.W)
156  val lastHalf = UInt(nBanksInPacket.W)
157  val pd = Vec(PredictWidth, (new PreDecodeInfo))
158}
159
160class CfiUpdateInfo extends XSBundle {
161  // from backend
162  val pc = UInt(VAddrBits.W)
163  val pnpc = UInt(VAddrBits.W)
164  val fetchIdx = UInt(log2Up(PredictWidth).W)
165  // frontend -> backend -> frontend
166  val pd = new PreDecodeInfo
167  val bpuMeta = new BpuMeta
168
169  // need pipeline update
170  val target = UInt(VAddrBits.W)
171  val brTarget = UInt(VAddrBits.W)
172  val taken = Bool()
173  val isMisPred = Bool()
174  val brTag = new BrqPtr
175  val isReplay = Bool()
176}
177
178// Dequeue DecodeWidth insts from Ibuffer
179class CtrlFlow extends XSBundle {
180  val instr = UInt(32.W)
181  val pc = UInt(VAddrBits.W)
182  val exceptionVec = Vec(16, Bool())
183  val intrVec = Vec(12, Bool())
184  val brUpdate = new CfiUpdateInfo
185  val crossPageIPFFix = Bool()
186}
187
188// Decode DecodeWidth insts at Decode Stage
189class CtrlSignals extends XSBundle {
190  val src1Type, src2Type, src3Type = SrcType()
191  val lsrc1, lsrc2, lsrc3 = UInt(5.W)
192  val ldest = UInt(5.W)
193  val fuType = FuType()
194  val fuOpType = FuOpType()
195  val rfWen = Bool()
196  val fpWen = Bool()
197  val isXSTrap = Bool()
198  val noSpecExec = Bool()  // wait forward
199  val blockBackward  = Bool()  // block backward
200  val flushPipe  = Bool()  // This inst will flush all the pipe when commit, like exception but can commit
201  val isRVF = Bool()
202  val selImm = SelImm()
203  val imm = UInt(XLEN.W)
204  val commitType = CommitType()
205
206  def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = {
207    val decoder = freechips.rocketchip.rocket.DecodeLogic(inst, XDecode.decodeDefault, table)
208    val signals =
209      Seq(src1Type, src2Type, src3Type, fuType, fuOpType, rfWen, fpWen,
210          isXSTrap, noSpecExec, blockBackward, flushPipe, isRVF, selImm)
211    signals zip decoder map { case(s, d) => s := d }
212    commitType := DontCare
213    this
214  }
215}
216
217class CfCtrl extends XSBundle {
218  val cf = new CtrlFlow
219  val ctrl = new CtrlSignals
220  val brTag = new BrqPtr
221}
222
223class LSIdx extends XSBundle {
224  val lqIdx = new LqPtr
225  val sqIdx = new SqPtr
226}
227
228// CfCtrl -> MicroOp at Rename Stage
229class MicroOp extends CfCtrl {
230  val psrc1, psrc2, psrc3, pdest, old_pdest = UInt(PhyRegIdxWidth.W)
231  val src1State, src2State, src3State = SrcState()
232  val roqIdx = new RoqPtr
233  val lqIdx = new LqPtr
234  val sqIdx = new SqPtr
235  val diffTestDebugLrScValid = Bool()
236}
237
238class Redirect extends XSBundle {
239  val roqIdx = new RoqPtr
240  val level = RedirectLevel()
241  val interrupt = Bool()
242  val pc = UInt(VAddrBits.W)
243  val target = UInt(VAddrBits.W)
244  val brTag = new BrqPtr
245
246  def isUnconditional() = RedirectLevel.isUnconditional(level)
247  def flushItself() = RedirectLevel.flushItself(level)
248  def isException() = RedirectLevel.isException(level)
249}
250
251class Dp1ToDp2IO extends XSBundle {
252  val intDqToDp2 = Vec(dpParams.IntDqDeqWidth, DecoupledIO(new MicroOp))
253  val fpDqToDp2 = Vec(dpParams.FpDqDeqWidth, DecoupledIO(new MicroOp))
254  val lsDqToDp2 = Vec(dpParams.LsDqDeqWidth, DecoupledIO(new MicroOp))
255}
256
257class ReplayPregReq extends XSBundle {
258  // NOTE: set isInt and isFp both to 'false' when invalid
259  val isInt = Bool()
260  val isFp = Bool()
261  val preg = UInt(PhyRegIdxWidth.W)
262}
263
264class DebugBundle extends XSBundle{
265  val isMMIO = Bool()
266}
267
268class ExuInput extends XSBundle {
269  val uop = new MicroOp
270  val src1, src2, src3 = UInt((XLEN+1).W)
271}
272
273class ExuOutput extends XSBundle {
274  val uop = new MicroOp
275  val data = UInt((XLEN+1).W)
276  val fflags  = new Fflags
277  val redirectValid = Bool()
278  val redirect = new Redirect
279  val brUpdate = new CfiUpdateInfo
280  val debug = new DebugBundle
281}
282
283class ExternalInterruptIO extends XSBundle {
284  val mtip = Input(Bool())
285  val msip = Input(Bool())
286  val meip = Input(Bool())
287}
288
289class CSRSpecialIO extends XSBundle {
290  val exception = Flipped(ValidIO(new MicroOp))
291  val isInterrupt = Input(Bool())
292  val memExceptionVAddr = Input(UInt(VAddrBits.W))
293  val trapTarget = Output(UInt(VAddrBits.W))
294  val externalInterrupt = new ExternalInterruptIO
295  val interrupt = Output(Bool())
296}
297
298class RoqCommitInfo extends XSBundle {
299  val ldest = UInt(5.W)
300  val rfWen = Bool()
301  val fpWen = Bool()
302  val commitType = CommitType()
303  val pdest = UInt(PhyRegIdxWidth.W)
304  val old_pdest = UInt(PhyRegIdxWidth.W)
305  val lqIdx = new LqPtr
306  val sqIdx = new SqPtr
307
308  // these should be optimized for synthesis verilog
309  val pc = UInt(VAddrBits.W)
310}
311
312class RoqCommitIO extends XSBundle {
313  val isWalk = Output(Bool())
314  val valid = Vec(CommitWidth, Output(Bool()))
315  val info = Vec(CommitWidth, Output(new RoqCommitInfo))
316
317  def hasWalkInstr = isWalk && valid.asUInt.orR
318  def hasCommitInstr = !isWalk && valid.asUInt.orR
319}
320
321class TlbFeedback extends XSBundle {
322  val roqIdx = new RoqPtr
323  val hit = Bool()
324}
325
326class FrontendToBackendIO extends XSBundle {
327  // to backend end
328  val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
329  // from backend
330  val redirect = Flipped(ValidIO(UInt(VAddrBits.W)))
331  // val cfiUpdateInfo = Flipped(ValidIO(new CfiUpdateInfo))
332  val cfiUpdateInfo = Flipped(ValidIO(new CfiUpdateInfo))
333}
334
335class TlbCsrBundle extends XSBundle {
336  val satp = new Bundle {
337    val mode = UInt(4.W) // TODO: may change number to parameter
338    val asid = UInt(16.W)
339    val ppn  = UInt(44.W) // just use PAddrBits - 3 - vpnnLen
340  }
341  val priv = new Bundle {
342    val mxr = Bool()
343    val sum = Bool()
344    val imode = UInt(2.W)
345    val dmode = UInt(2.W)
346  }
347
348  override def toPrintable: Printable = {
349    p"Satp mode:0x${Hexadecimal(satp.mode)} asid:0x${Hexadecimal(satp.asid)} ppn:0x${Hexadecimal(satp.ppn)} " +
350    p"Priv mxr:${priv.mxr} sum:${priv.sum} imode:${priv.imode} dmode:${priv.dmode}"
351  }
352}
353
354class SfenceBundle extends XSBundle {
355  val valid = Bool()
356  val bits = new Bundle {
357    val rs1 = Bool()
358    val rs2 = Bool()
359    val addr = UInt(VAddrBits.W)
360  }
361
362  override def toPrintable: Printable = {
363    p"valid:0x${Hexadecimal(valid)} rs1:${bits.rs1} rs2:${bits.rs2} addr:${Hexadecimal(bits.addr)}"
364  }
365}
366