xref: /XiangShan/src/main/scala/xiangshan/Bundle.scala (revision a338f247f5f511d724980d1141df13b75c049f83)
1package xiangshan
2
3import chisel3._
4import chisel3.util._
5import xiangshan.backend.roq.RoqPtr
6import xiangshan.backend.decode.{ImmUnion, WaitTableParameters, XDecode}
7import xiangshan.mem.{LqPtr, SqPtr}
8import xiangshan.frontend.PreDecodeInfoForDebug
9import xiangshan.frontend.PreDecodeInfo
10import xiangshan.frontend.HasBPUParameter
11import xiangshan.frontend.PreDecodeInfo
12import xiangshan.frontend.HasTageParameter
13import xiangshan.frontend.HasSCParameter
14import xiangshan.frontend.HasIFUConst
15import xiangshan.frontend.GlobalHistory
16import xiangshan.frontend.RASEntry
17import xiangshan.frontend.BPUCtrl
18import utils._
19
20import scala.math.max
21import Chisel.experimental.chiselName
22import chipsalliance.rocketchip.config.Parameters
23import xiangshan.backend.ftq.FtqPtr
24
25// Fetch FetchWidth x 32-bit insts from Icache
26class FetchPacket(implicit p: Parameters) extends XSBundle with WaitTableParameters {
27  val instrs = Vec(PredictWidth, UInt(32.W))
28  val mask = UInt(PredictWidth.W)
29  val pdmask = UInt(PredictWidth.W)
30  // val pc = UInt(VAddrBits.W)
31  val pc = Vec(PredictWidth, UInt(VAddrBits.W))
32  val foldpc = Vec(PredictWidth, UInt(WaitTableAddrWidth.W))
33  val pd = Vec(PredictWidth, new PreDecodeInfo)
34  val ipf = Bool()
35  val acf = Bool()
36  val crossPageIPFFix = Bool()
37  val pred_taken = UInt(PredictWidth.W)
38  val ftqPtr = new FtqPtr
39}
40
41class ValidUndirectioned[T <: Data](gen: T) extends Bundle {
42  val valid = Bool()
43  val bits = gen.cloneType.asInstanceOf[T]
44
45  override def cloneType = new ValidUndirectioned(gen).asInstanceOf[this.type]
46}
47
48object ValidUndirectioned {
49  def apply[T <: Data](gen: T) = {
50    new ValidUndirectioned[T](gen)
51  }
52}
53
54class SCMeta(val useSC: Boolean)(implicit p: Parameters) extends XSBundle with HasSCParameter {
55  val tageTaken = if (useSC) Bool() else UInt(0.W)
56  val scUsed = if (useSC) Bool() else UInt(0.W)
57  val scPred = if (useSC) Bool() else UInt(0.W)
58  // Suppose ctrbits of all tables are identical
59  val ctrs = if (useSC) Vec(SCNTables, SInt(SCCtrBits.W)) else Vec(SCNTables, SInt(0.W))
60}
61
62class TageMeta(implicit p: Parameters) extends XSBundle with HasTageParameter {
63  val provider = ValidUndirectioned(UInt(log2Ceil(TageNTables).W))
64  val altDiffers = Bool()
65  val providerU = UInt(2.W)
66  val providerCtr = UInt(3.W)
67  val allocate = ValidUndirectioned(UInt(log2Ceil(TageNTables).W))
68  val taken = Bool()
69  val scMeta = new SCMeta(EnableSC)
70}
71
72@chiselName
73class BranchPrediction(implicit p: Parameters) extends XSBundle with HasIFUConst {
74  // val redirect = Bool()
75  val takens = UInt(PredictWidth.W)
76  // val jmpIdx = UInt(log2Up(PredictWidth).W)
77  val brMask = UInt(PredictWidth.W)
78  val jalMask = UInt(PredictWidth.W)
79  val targets = Vec(PredictWidth, UInt(VAddrBits.W))
80
81  // half RVI could only start at the end of a packet
82  val hasHalfRVI = Bool()
83
84  def brNotTakens = (~takens & brMask)
85
86  def sawNotTakenBr = VecInit((0 until PredictWidth).map(i =>
87    (if (i == 0) false.B else ParallelORR(brNotTakens(i - 1, 0)))))
88
89  // if not taken before the half RVI inst
90  def saveHalfRVI = hasHalfRVI && !(ParallelORR(takens(PredictWidth - 2, 0)))
91
92  // could get PredictWidth-1 when only the first bank is valid
93  def jmpIdx = ParallelPriorityEncoder(takens)
94
95  // only used when taken
96  def target = {
97    val generator = new PriorityMuxGenerator[UInt]
98    generator.register(takens.asBools, targets, List.fill(PredictWidth)(None))
99    generator()
100  }
101
102  def taken = ParallelORR(takens)
103
104  def takenOnBr = taken && ParallelPriorityMux(takens, brMask.asBools)
105
106  def hasNotTakenBrs = Mux(taken, ParallelPriorityMux(takens, sawNotTakenBr), ParallelORR(brNotTakens))
107}
108
109class PredictorAnswer(implicit p: Parameters) extends XSBundle {
110  val hit    = if (!env.FPGAPlatform) Bool() else UInt(0.W)
111  val taken  = if (!env.FPGAPlatform) Bool() else UInt(0.W)
112  val target = if (!env.FPGAPlatform) UInt(VAddrBits.W) else UInt(0.W)
113}
114
115class BpuMeta(implicit p: Parameters) extends XSBundle with HasBPUParameter {
116  val btbWriteWay = UInt(log2Up(BtbWays).W)
117  val btbHit = Bool()
118  val bimCtr = UInt(2.W)
119  val tageMeta = new TageMeta
120  // for global history
121
122  val debug_ubtb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
123  val debug_btb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
124  val debug_tage_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
125
126  val predictor = if (BPUDebug) UInt(log2Up(4).W) else UInt(0.W) // Mark which component this prediction comes from {ubtb, btb, tage, loopPredictor}
127
128  val ubtbHit = if (BPUDebug) UInt(1.W) else UInt(0.W)
129
130  val ubtbAns = new PredictorAnswer
131  val btbAns = new PredictorAnswer
132  val tageAns = new PredictorAnswer
133  val rasAns = new PredictorAnswer
134  val loopAns = new PredictorAnswer
135
136  // def apply(histPtr: UInt, tageMeta: TageMeta, rasSp: UInt, rasTopCtr: UInt) = {
137  //   this.histPtr := histPtr
138  //   this.tageMeta := tageMeta
139  //   this.rasSp := rasSp
140  //   this.rasTopCtr := rasTopCtr
141  //   this.asUInt
142  // }
143  def size = 0.U.asTypeOf(this).getWidth
144
145  def fromUInt(x: UInt) = x.asTypeOf(this)
146}
147
148class Predecode(implicit p: Parameters) extends XSBundle with HasIFUConst {
149  val hasLastHalfRVI = Bool()
150  val mask = UInt(PredictWidth.W)
151  val lastHalf = Bool()
152  val pd = Vec(PredictWidth, (new PreDecodeInfo))
153}
154
155class CfiUpdateInfo(implicit p: Parameters) extends XSBundle with HasBPUParameter {
156  // from backend
157  val pc = UInt(VAddrBits.W)
158  // frontend -> backend -> frontend
159  val pd = new PreDecodeInfo
160  val rasSp = UInt(log2Up(RasSize).W)
161  val rasEntry = new RASEntry
162  val hist = new GlobalHistory
163  val predHist = new GlobalHistory
164  val specCnt = Vec(PredictWidth, UInt(10.W))
165  // need pipeline update
166  val sawNotTakenBranch = Bool()
167  val predTaken = Bool()
168  val target = UInt(VAddrBits.W)
169  val taken = Bool()
170  val isMisPred = Bool()
171}
172
173// Dequeue DecodeWidth insts from Ibuffer
174class CtrlFlow(implicit p: Parameters) extends XSBundle with WaitTableParameters {
175  val instr = UInt(32.W)
176  val pc = UInt(VAddrBits.W)
177  val foldpc = UInt(WaitTableAddrWidth.W)
178  val exceptionVec = ExceptionVec()
179  val intrVec = Vec(12, Bool())
180  val pd = new PreDecodeInfo
181  val pred_taken = Bool()
182  val crossPageIPFFix = Bool()
183  val loadWaitBit = Bool() // load inst should not be executed until all former store addr calcuated
184  val ftqPtr = new FtqPtr
185  val ftqOffset = UInt(log2Up(PredictWidth).W)
186}
187
188class FtqEntry(implicit p: Parameters) extends XSBundle {
189  // fetch pc, pc of each inst could be generated by concatenation
190  val ftqPC = UInt(VAddrBits.W)
191  val lastPacketPC = ValidUndirectioned(UInt(VAddrBits.W))
192  // prediction metas
193  val hist = new GlobalHistory
194  val predHist = new GlobalHistory
195  val rasSp = UInt(log2Ceil(RasSize).W)
196  val rasTop = new RASEntry()
197  val specCnt = Vec(PredictWidth, UInt(10.W))
198  val metas = Vec(PredictWidth, new BpuMeta)
199
200  val cfiIsCall, cfiIsRet, cfiIsJalr, cfiIsRVC = Bool()
201  val rvc_mask = Vec(PredictWidth, Bool())
202  val br_mask = Vec(PredictWidth, Bool())
203  val cfiIndex = ValidUndirectioned(UInt(log2Up(PredictWidth).W))
204  val valids = Vec(PredictWidth, Bool())
205
206  // backend update
207  val mispred = Vec(PredictWidth, Bool())
208  val target = UInt(VAddrBits.W)
209
210  // For perf counters
211  val pd = Vec(PredictWidth, new PreDecodeInfoForDebug(!env.FPGAPlatform))
212
213  def takens = VecInit((0 until PredictWidth).map(i => cfiIndex.valid && cfiIndex.bits === i.U))
214  def hasLastPrev = lastPacketPC.valid
215
216  override def toPrintable: Printable = {
217    p"ftqPC: ${Hexadecimal(ftqPC)} lastPacketPC: ${Hexadecimal(lastPacketPC.bits)} hasLastPrev:$hasLastPrev " +
218      p"rasSp:$rasSp specCnt:$specCnt brmask:${Binary(Cat(br_mask))} rvcmask:${Binary(Cat(rvc_mask))} " +
219      p"valids:${Binary(valids.asUInt())} cfi valid: ${cfiIndex.valid} " +
220      p"cfi index: ${cfiIndex.bits} isCall:$cfiIsCall isRet:$cfiIsRet isJalr:$cfiIsJalr, isRvc:$cfiIsRVC " +
221      p"mispred:${Binary(Cat(mispred))} target:${Hexadecimal(target)}\n"
222  }
223
224}
225
226
227class FPUCtrlSignals(implicit p: Parameters) extends XSBundle {
228  val isAddSub = Bool() // swap23
229  val typeTagIn = UInt(2.W)
230  val typeTagOut = UInt(2.W)
231  val fromInt = Bool()
232  val wflags = Bool()
233  val fpWen = Bool()
234  val fmaCmd = UInt(2.W)
235  val div = Bool()
236  val sqrt = Bool()
237  val fcvt = Bool()
238  val typ = UInt(2.W)
239  val fmt = UInt(2.W)
240  val ren3 = Bool() //TODO: remove SrcType.fp
241  val rm = UInt(3.W)
242}
243
244// Decode DecodeWidth insts at Decode Stage
245class CtrlSignals(implicit p: Parameters) extends XSBundle {
246  val src1Type, src2Type, src3Type = SrcType()
247  val lsrc1, lsrc2, lsrc3 = UInt(5.W)
248  val ldest = UInt(5.W)
249  val fuType = FuType()
250  val fuOpType = FuOpType()
251  val rfWen = Bool()
252  val fpWen = Bool()
253  val isXSTrap = Bool()
254  val noSpecExec = Bool() // wait forward
255  val blockBackward = Bool() // block backward
256  val flushPipe = Bool() // This inst will flush all the pipe when commit, like exception but can commit
257  val isRVF = Bool()
258  val selImm = SelImm()
259  val imm = UInt(ImmUnion.maxLen.W)
260  val commitType = CommitType()
261  val fpu = new FPUCtrlSignals
262  val isMove = Bool()
263
264  def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = {
265    val decoder = freechips.rocketchip.rocket.DecodeLogic(inst, XDecode.decodeDefault, table)
266    val signals =
267      Seq(src1Type, src2Type, src3Type, fuType, fuOpType, rfWen, fpWen,
268        isXSTrap, noSpecExec, blockBackward, flushPipe, isRVF, selImm)
269    signals zip decoder map { case (s, d) => s := d }
270    commitType := DontCare
271    this
272  }
273}
274
275class CfCtrl(implicit p: Parameters) extends XSBundle {
276  val cf = new CtrlFlow
277  val ctrl = new CtrlSignals
278}
279
280class PerfDebugInfo(implicit p: Parameters) extends XSBundle {
281  val src1MoveElim = Bool()
282  val src2MoveElim = Bool()
283  // val fetchTime = UInt(64.W)
284  val renameTime = UInt(64.W)
285  val dispatchTime = UInt(64.W)
286  val issueTime = UInt(64.W)
287  val writebackTime = UInt(64.W)
288  // val commitTime = UInt(64.W)
289}
290
291// Separate LSQ
292class LSIdx(implicit p: Parameters) extends XSBundle {
293  val lqIdx = new LqPtr
294  val sqIdx = new SqPtr
295}
296
297// CfCtrl -> MicroOp at Rename Stage
298class MicroOp(implicit p: Parameters) extends CfCtrl {
299  val psrc1, psrc2, psrc3, pdest, old_pdest = UInt(PhyRegIdxWidth.W)
300  val src1State, src2State, src3State = SrcState()
301  val roqIdx = new RoqPtr
302  val lqIdx = new LqPtr
303  val sqIdx = new SqPtr
304  val diffTestDebugLrScValid = Bool()
305  val debugInfo = new PerfDebugInfo
306  def needRfRPort(index: Int, rfType: Int) : Bool = {
307    (index, rfType) match {
308      case (0, 0) => ctrl.src1Type === SrcType.reg && ctrl.lsrc1 =/= 0.U && src1State === SrcState.rdy
309      case (1, 0) => ctrl.src2Type === SrcType.reg && ctrl.lsrc2 =/= 0.U && src1State === SrcState.rdy
310      case (0, 1) => ctrl.src1Type === SrcType.fp && src1State === SrcState.rdy
311      case (1, 1) => ctrl.src2Type === SrcType.fp && src1State === SrcState.rdy
312      case (2, 1) => ctrl.src3Type === SrcType.fp && src1State === SrcState.rdy
313      case _ => false.B
314    }
315  }
316}
317
318class Redirect(implicit p: Parameters) extends XSBundle {
319  val roqIdx = new RoqPtr
320  val ftqIdx = new FtqPtr
321  val ftqOffset = UInt(log2Up(PredictWidth).W)
322  val level = RedirectLevel()
323  val interrupt = Bool()
324  val cfiUpdate = new CfiUpdateInfo
325
326
327  // def isUnconditional() = RedirectLevel.isUnconditional(level)
328  def flushItself() = RedirectLevel.flushItself(level)
329  // def isException() = RedirectLevel.isException(level)
330}
331
332class Dp1ToDp2IO(implicit p: Parameters) extends XSBundle {
333  val intDqToDp2 = Vec(dpParams.IntDqDeqWidth, DecoupledIO(new MicroOp))
334  val fpDqToDp2 = Vec(dpParams.FpDqDeqWidth, DecoupledIO(new MicroOp))
335  val lsDqToDp2 = Vec(dpParams.LsDqDeqWidth, DecoupledIO(new MicroOp))
336}
337
338class ReplayPregReq(implicit p: Parameters) extends XSBundle {
339  // NOTE: set isInt and isFp both to 'false' when invalid
340  val isInt = Bool()
341  val isFp = Bool()
342  val preg = UInt(PhyRegIdxWidth.W)
343}
344
345class DebugBundle(implicit p: Parameters) extends XSBundle {
346  val isMMIO = Bool()
347  val isPerfCnt = Bool()
348  val paddr = UInt(PAddrBits.W)
349}
350
351class ExuInput(implicit p: Parameters) extends XSBundle {
352  val uop = new MicroOp
353  val src1, src2, src3 = UInt((XLEN + 1).W)
354}
355
356class ExuOutput(implicit p: Parameters) extends XSBundle {
357  val uop = new MicroOp
358  val data = UInt((XLEN + 1).W)
359  val fflags = UInt(5.W)
360  val redirectValid = Bool()
361  val redirect = new Redirect
362  val debug = new DebugBundle
363}
364
365class ExternalInterruptIO(implicit p: Parameters) extends XSBundle {
366  val mtip = Input(Bool())
367  val msip = Input(Bool())
368  val meip = Input(Bool())
369}
370
371class CSRSpecialIO(implicit p: Parameters) extends XSBundle {
372  val exception = Flipped(ValidIO(new MicroOp))
373  val isInterrupt = Input(Bool())
374  val memExceptionVAddr = Input(UInt(VAddrBits.W))
375  val trapTarget = Output(UInt(VAddrBits.W))
376  val externalInterrupt = new ExternalInterruptIO
377  val interrupt = Output(Bool())
378}
379
380class ExceptionInfo(implicit p: Parameters) extends XSBundle {
381  val uop = new MicroOp
382  val isInterrupt = Bool()
383}
384
385class RoqCommitInfo(implicit p: Parameters) extends XSBundle {
386  val ldest = UInt(5.W)
387  val rfWen = Bool()
388  val fpWen = Bool()
389  val wflags = Bool()
390  val commitType = CommitType()
391  val pdest = UInt(PhyRegIdxWidth.W)
392  val old_pdest = UInt(PhyRegIdxWidth.W)
393  val ftqIdx = new FtqPtr
394  val ftqOffset = UInt(log2Up(PredictWidth).W)
395
396  // these should be optimized for synthesis verilog
397  val pc = UInt(VAddrBits.W)
398}
399
400class RoqCommitIO(implicit p: Parameters) extends XSBundle {
401  val isWalk = Output(Bool())
402  val valid = Vec(CommitWidth, Output(Bool()))
403  val info = Vec(CommitWidth, Output(new RoqCommitInfo))
404
405  def hasWalkInstr = isWalk && valid.asUInt.orR
406
407  def hasCommitInstr = !isWalk && valid.asUInt.orR
408}
409
410class TlbFeedback(implicit p: Parameters) extends XSBundle {
411  val rsIdx = UInt(log2Up(IssQueSize).W)
412  val hit = Bool()
413  val flushState = Bool()
414}
415
416class RSFeedback(implicit p: Parameters) extends TlbFeedback
417
418class FrontendToBackendIO(implicit p: Parameters) extends XSBundle {
419  // to backend end
420  val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
421  val fetchInfo = DecoupledIO(new FtqEntry)
422  // from backend
423  val redirect_cfiUpdate = Flipped(ValidIO(new Redirect))
424  val commit_cfiUpdate = Flipped(ValidIO(new FtqEntry))
425  val ftqEnqPtr = Input(new FtqPtr)
426  val ftqLeftOne = Input(Bool())
427}
428
429class TlbCsrBundle(implicit p: Parameters) extends XSBundle {
430  val satp = new Bundle {
431    val mode = UInt(4.W) // TODO: may change number to parameter
432    val asid = UInt(16.W)
433    val ppn = UInt(44.W) // just use PAddrBits - 3 - vpnnLen
434  }
435  val priv = new Bundle {
436    val mxr = Bool()
437    val sum = Bool()
438    val imode = UInt(2.W)
439    val dmode = UInt(2.W)
440  }
441
442  override def toPrintable: Printable = {
443    p"Satp mode:0x${Hexadecimal(satp.mode)} asid:0x${Hexadecimal(satp.asid)} ppn:0x${Hexadecimal(satp.ppn)} " +
444      p"Priv mxr:${priv.mxr} sum:${priv.sum} imode:${priv.imode} dmode:${priv.dmode}"
445  }
446}
447
448class SfenceBundle(implicit p: Parameters) extends XSBundle {
449  val valid = Bool()
450  val bits = new Bundle {
451    val rs1 = Bool()
452    val rs2 = Bool()
453    val addr = UInt(VAddrBits.W)
454  }
455
456  override def toPrintable: Printable = {
457    p"valid:0x${Hexadecimal(valid)} rs1:${bits.rs1} rs2:${bits.rs2} addr:${Hexadecimal(bits.addr)}"
458  }
459}
460
461class WaitTableUpdateReq(implicit p: Parameters) extends XSBundle with WaitTableParameters {
462  val valid = Bool()
463  val waddr = UInt(WaitTableAddrWidth.W)
464  val wdata = Bool() // true.B by default
465}
466
467class PerfInfoIO extends Bundle {
468  val clean = Input(Bool())
469  val dump = Input(Bool())
470}
471
472class CustomCSRCtrlIO(implicit p: Parameters) extends XSBundle {
473  // Prefetcher
474  val l1plus_pf_enable = Output(Bool())
475  val l2_pf_enable = Output(Bool())
476  // Labeled XiangShan
477  val dsid = Output(UInt(8.W)) // TODO: DsidWidth as parameter
478  // Load violation predictor
479  val lvpred_disable = Output(Bool())
480  val no_spec_load = Output(Bool())
481  val waittable_timeout = Output(UInt(5.W))
482  // Branch predictor
483  val bp_ctrl = Output(new BPUCtrl)
484  // Memory Block
485  val sbuffer_threshold = Output(UInt(4.W))
486  // Rename
487  val move_elim_enable = Output(Bool())
488}
489