xref: /XiangShan/src/main/scala/xiangshan/Bundle.scala (revision 2225d46ebbe2fd16b9b29963c27a7d0385a42709)
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}
307
308class Redirect(implicit p: Parameters) extends XSBundle {
309  val roqIdx = new RoqPtr
310  val ftqIdx = new FtqPtr
311  val ftqOffset = UInt(log2Up(PredictWidth).W)
312  val level = RedirectLevel()
313  val interrupt = Bool()
314  val cfiUpdate = new CfiUpdateInfo
315
316
317  // def isUnconditional() = RedirectLevel.isUnconditional(level)
318  def flushItself() = RedirectLevel.flushItself(level)
319  // def isException() = RedirectLevel.isException(level)
320}
321
322class Dp1ToDp2IO(implicit p: Parameters) extends XSBundle {
323  val intDqToDp2 = Vec(dpParams.IntDqDeqWidth, DecoupledIO(new MicroOp))
324  val fpDqToDp2 = Vec(dpParams.FpDqDeqWidth, DecoupledIO(new MicroOp))
325  val lsDqToDp2 = Vec(dpParams.LsDqDeqWidth, DecoupledIO(new MicroOp))
326}
327
328class ReplayPregReq(implicit p: Parameters) extends XSBundle {
329  // NOTE: set isInt and isFp both to 'false' when invalid
330  val isInt = Bool()
331  val isFp = Bool()
332  val preg = UInt(PhyRegIdxWidth.W)
333}
334
335class DebugBundle(implicit p: Parameters) extends XSBundle {
336  val isMMIO = Bool()
337  val isPerfCnt = Bool()
338  val paddr = UInt(PAddrBits.W)
339}
340
341class ExuInput(implicit p: Parameters) extends XSBundle {
342  val uop = new MicroOp
343  val src1, src2, src3 = UInt((XLEN + 1).W)
344}
345
346class ExuOutput(implicit p: Parameters) extends XSBundle {
347  val uop = new MicroOp
348  val data = UInt((XLEN + 1).W)
349  val fflags = UInt(5.W)
350  val redirectValid = Bool()
351  val redirect = new Redirect
352  val debug = new DebugBundle
353}
354
355class ExternalInterruptIO(implicit p: Parameters) extends XSBundle {
356  val mtip = Input(Bool())
357  val msip = Input(Bool())
358  val meip = Input(Bool())
359}
360
361class CSRSpecialIO(implicit p: Parameters) extends XSBundle {
362  val exception = Flipped(ValidIO(new MicroOp))
363  val isInterrupt = Input(Bool())
364  val memExceptionVAddr = Input(UInt(VAddrBits.W))
365  val trapTarget = Output(UInt(VAddrBits.W))
366  val externalInterrupt = new ExternalInterruptIO
367  val interrupt = Output(Bool())
368}
369
370class ExceptionInfo(implicit p: Parameters) extends XSBundle {
371  val uop = new MicroOp
372  val isInterrupt = Bool()
373}
374
375class RoqCommitInfo(implicit p: Parameters) extends XSBundle {
376  val ldest = UInt(5.W)
377  val rfWen = Bool()
378  val fpWen = Bool()
379  val wflags = Bool()
380  val commitType = CommitType()
381  val pdest = UInt(PhyRegIdxWidth.W)
382  val old_pdest = UInt(PhyRegIdxWidth.W)
383  val ftqIdx = new FtqPtr
384  val ftqOffset = UInt(log2Up(PredictWidth).W)
385
386  // these should be optimized for synthesis verilog
387  val pc = UInt(VAddrBits.W)
388}
389
390class RoqCommitIO(implicit p: Parameters) extends XSBundle {
391  val isWalk = Output(Bool())
392  val valid = Vec(CommitWidth, Output(Bool()))
393  val info = Vec(CommitWidth, Output(new RoqCommitInfo))
394
395  def hasWalkInstr = isWalk && valid.asUInt.orR
396
397  def hasCommitInstr = !isWalk && valid.asUInt.orR
398}
399
400class TlbFeedback(implicit p: Parameters) extends XSBundle {
401  val rsIdx = UInt(log2Up(IssQueSize).W)
402  val hit = Bool()
403  val flushState = Bool()
404}
405
406class RSFeedback(implicit p: Parameters) extends TlbFeedback
407
408class FrontendToBackendIO(implicit p: Parameters) extends XSBundle {
409  // to backend end
410  val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
411  val fetchInfo = DecoupledIO(new FtqEntry)
412  // from backend
413  val redirect_cfiUpdate = Flipped(ValidIO(new Redirect))
414  val commit_cfiUpdate = Flipped(ValidIO(new FtqEntry))
415  val ftqEnqPtr = Input(new FtqPtr)
416  val ftqLeftOne = Input(Bool())
417}
418
419class TlbCsrBundle(implicit p: Parameters) extends XSBundle {
420  val satp = new Bundle {
421    val mode = UInt(4.W) // TODO: may change number to parameter
422    val asid = UInt(16.W)
423    val ppn = UInt(44.W) // just use PAddrBits - 3 - vpnnLen
424  }
425  val priv = new Bundle {
426    val mxr = Bool()
427    val sum = Bool()
428    val imode = UInt(2.W)
429    val dmode = UInt(2.W)
430  }
431
432  override def toPrintable: Printable = {
433    p"Satp mode:0x${Hexadecimal(satp.mode)} asid:0x${Hexadecimal(satp.asid)} ppn:0x${Hexadecimal(satp.ppn)} " +
434      p"Priv mxr:${priv.mxr} sum:${priv.sum} imode:${priv.imode} dmode:${priv.dmode}"
435  }
436}
437
438class SfenceBundle(implicit p: Parameters) extends XSBundle {
439  val valid = Bool()
440  val bits = new Bundle {
441    val rs1 = Bool()
442    val rs2 = Bool()
443    val addr = UInt(VAddrBits.W)
444  }
445
446  override def toPrintable: Printable = {
447    p"valid:0x${Hexadecimal(valid)} rs1:${bits.rs1} rs2:${bits.rs2} addr:${Hexadecimal(bits.addr)}"
448  }
449}
450
451class WaitTableUpdateReq(implicit p: Parameters) extends XSBundle with WaitTableParameters {
452  val valid = Bool()
453  val waddr = UInt(WaitTableAddrWidth.W)
454  val wdata = Bool() // true.B by default
455}
456
457class PerfInfoIO extends Bundle {
458  val clean = Input(Bool())
459  val dump = Input(Bool())
460}
461
462class CustomCSRCtrlIO(implicit p: Parameters) extends XSBundle {
463  // Prefetcher
464  val l1plus_pf_enable = Output(Bool())
465  val l2_pf_enable = Output(Bool())
466  // Labeled XiangShan
467  val dsid = Output(UInt(8.W)) // TODO: DsidWidth as parameter
468  // Load violation predictor
469  val lvpred_disable = Output(Bool())
470  val no_spec_load = Output(Bool())
471  val waittable_timeout = Output(UInt(5.W))
472  // Branch predictor
473  val bp_ctrl = Output(new BPUCtrl)
474  // Memory Block
475  val sbuffer_threshold = Output(UInt(4.W))
476  // Rename
477  val move_elim_enable = Output(Bool())
478}
479