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