xref: /XiangShan/src/main/scala/xiangshan/Bundle.scala (revision 16470009a5e283f3d50228cd0fa891babbc9c8f3)
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 btbWriteWay = UInt(log2Up(BtbWays).W)
124  val bimCtr = UInt(2.W)
125  val tageMeta = new TageMeta
126  // for global history
127
128  val debug_ubtb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
129  val debug_btb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
130  val debug_tage_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W)
131
132  val predictor = if (BPUDebug) UInt(log2Up(4).W) else UInt(0.W) // Mark which component this prediction comes from {ubtb, btb, tage, loopPredictor}
133
134  val ubtbAns = new PredictorAnswer
135  val btbAns = new PredictorAnswer
136  val tageAns = new PredictorAnswer
137  val rasAns = new PredictorAnswer
138  val loopAns = new PredictorAnswer
139
140  // def apply(histPtr: UInt, tageMeta: TageMeta, rasSp: UInt, rasTopCtr: UInt) = {
141  //   this.histPtr := histPtr
142  //   this.tageMeta := tageMeta
143  //   this.rasSp := rasSp
144  //   this.rasTopCtr := rasTopCtr
145  //   this.asUInt
146  // }
147  def size = 0.U.asTypeOf(this).getWidth
148
149  def fromUInt(x: UInt) = x.asTypeOf(this)
150}
151
152class Predecode extends XSBundle with HasIFUConst {
153  val hasLastHalfRVI = Bool()
154  val mask = UInt(PredictWidth.W)
155  val lastHalf = Bool()
156  val pd = Vec(PredictWidth, (new PreDecodeInfo))
157}
158
159class CfiUpdateInfo extends XSBundle with HasBPUParameter {
160  // from backend
161  val pc = UInt(VAddrBits.W)
162  // frontend -> backend -> frontend
163  val pd = new PreDecodeInfo
164  val rasSp = UInt(log2Up(RasSize).W)
165  val rasEntry = new RASEntry
166  val hist = new GlobalHistory
167  val predHist = new GlobalHistory
168  val specCnt = Vec(PredictWidth, UInt(10.W))
169  // need pipeline update
170  val sawNotTakenBranch = Bool()
171  val predTaken = Bool()
172  val target = UInt(VAddrBits.W)
173  val taken = Bool()
174  val isMisPred = Bool()
175}
176
177// Dequeue DecodeWidth insts from Ibuffer
178class CtrlFlow extends XSBundle with WaitTableParameters {
179  val instr = UInt(32.W)
180  val pc = UInt(VAddrBits.W)
181  val foldpc = UInt(WaitTableAddrWidth.W)
182  val exceptionVec = ExceptionVec()
183  val intrVec = Vec(12, Bool())
184  val pd = new PreDecodeInfo
185  val pred_taken = Bool()
186  val crossPageIPFFix = Bool()
187  val loadWaitBit = Bool() // load inst should not be executed until all former store addr calcuated
188  val ftqPtr = new FtqPtr
189  val ftqOffset = UInt(log2Up(PredictWidth).W)
190}
191
192class FtqEntry extends XSBundle {
193  // fetch pc, pc of each inst could be generated by concatenation
194  val ftqPC = UInt(VAddrBits.W)
195  val lastPacketPC = ValidUndirectioned(UInt(VAddrBits.W))
196  // prediction metas
197  val hist = new GlobalHistory
198  val predHist = new GlobalHistory
199  val rasSp = UInt(log2Ceil(RasSize).W)
200  val rasTop = new RASEntry()
201  val specCnt = Vec(PredictWidth, UInt(10.W))
202  val metas = Vec(PredictWidth, new BpuMeta)
203
204  val cfiIsCall, cfiIsRet, cfiIsRVC = Bool()
205  val rvc_mask = Vec(PredictWidth, Bool())
206  val br_mask = Vec(PredictWidth, Bool())
207  val cfiIndex = ValidUndirectioned(UInt(log2Up(PredictWidth).W))
208  val valids = Vec(PredictWidth, Bool())
209
210  // backend update
211  val mispred = Vec(PredictWidth, Bool())
212  val target = UInt(VAddrBits.W)
213
214  // For perf counters
215  val pd = Vec(PredictWidth, new PreDecodeInfoForDebug(!env.FPGAPlatform))
216
217  def takens = VecInit((0 until PredictWidth).map(i => cfiIndex.valid && cfiIndex.bits === i.U))
218  def hasLastPrev = lastPacketPC.valid
219
220  override def toPrintable: Printable = {
221    p"ftqPC: ${Hexadecimal(ftqPC)} lastPacketPC: ${Hexadecimal(lastPacketPC.bits)} hasLastPrev:$hasLastPrev " +
222      p"rasSp:$rasSp specCnt:$specCnt brmask:${Binary(Cat(br_mask))} rvcmask:${Binary(Cat(rvc_mask))} " +
223      p"valids:${Binary(valids.asUInt())} cfi valid: ${cfiIndex.valid} " +
224      p"cfi index: ${cfiIndex.bits} isCall:$cfiIsCall isRet:$cfiIsRet isRvc:$cfiIsRVC " +
225      p"mispred:${Binary(Cat(mispred))} target:${Hexadecimal(target)}\n"
226  }
227
228}
229
230
231class FPUCtrlSignals extends XSBundle {
232  val isAddSub = Bool() // swap23
233  val typeTagIn = UInt(2.W)
234  val typeTagOut = UInt(2.W)
235  val fromInt = Bool()
236  val wflags = Bool()
237  val fpWen = Bool()
238  val fmaCmd = UInt(2.W)
239  val div = Bool()
240  val sqrt = Bool()
241  val fcvt = Bool()
242  val typ = UInt(2.W)
243  val fmt = UInt(2.W)
244  val ren3 = Bool() //TODO: remove SrcType.fp
245  val rm = UInt(3.W)
246}
247
248// Decode DecodeWidth insts at Decode Stage
249class CtrlSignals extends XSBundle {
250  val src1Type, src2Type, src3Type = SrcType()
251  val lsrc1, lsrc2, lsrc3 = UInt(5.W)
252  val ldest = UInt(5.W)
253  val fuType = FuType()
254  val fuOpType = FuOpType()
255  val rfWen = Bool()
256  val fpWen = Bool()
257  val isXSTrap = Bool()
258  val noSpecExec = Bool() // wait forward
259  val blockBackward = Bool() // block backward
260  val flushPipe = Bool() // This inst will flush all the pipe when commit, like exception but can commit
261  val isRVF = Bool()
262  val selImm = SelImm()
263  val imm = UInt(ImmUnion.maxLen.W)
264  val commitType = CommitType()
265  val fpu = new FPUCtrlSignals
266
267  def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = {
268    val decoder = freechips.rocketchip.rocket.DecodeLogic(inst, XDecode.decodeDefault, table)
269    val signals =
270      Seq(src1Type, src2Type, src3Type, fuType, fuOpType, rfWen, fpWen,
271        isXSTrap, noSpecExec, blockBackward, flushPipe, isRVF, selImm)
272    signals zip decoder map { case (s, d) => s := d }
273    commitType := DontCare
274    this
275  }
276}
277
278class CfCtrl extends XSBundle {
279  val cf = new CtrlFlow
280  val ctrl = new CtrlSignals
281}
282
283class PerfDebugInfo extends XSBundle {
284  // val fetchTime = UInt(64.W)
285  val renameTime = UInt(64.W)
286  val dispatchTime = UInt(64.W)
287  val issueTime = UInt(64.W)
288  val writebackTime = UInt(64.W)
289  // val commitTime = UInt(64.W)
290}
291
292// Separate LSQ
293class LSIdx extends XSBundle {
294  val lqIdx = new LqPtr
295  val sqIdx = new SqPtr
296}
297
298// CfCtrl -> MicroOp at Rename Stage
299class MicroOp extends CfCtrl {
300  val psrc1, psrc2, psrc3, pdest, old_pdest = UInt(PhyRegIdxWidth.W)
301  val src1State, src2State, src3State = SrcState()
302  val roqIdx = new RoqPtr
303  val lqIdx = new LqPtr
304  val sqIdx = new SqPtr
305  val diffTestDebugLrScValid = Bool()
306  val debugInfo = new PerfDebugInfo
307}
308
309class Redirect extends XSBundle {
310  val roqIdx = new RoqPtr
311  val ftqIdx = new FtqPtr
312  val ftqOffset = UInt(log2Up(PredictWidth).W)
313  val level = RedirectLevel()
314  val interrupt = Bool()
315  val cfiUpdate = new CfiUpdateInfo
316
317
318  // def isUnconditional() = RedirectLevel.isUnconditional(level)
319  def flushItself() = RedirectLevel.flushItself(level)
320  // def isException() = RedirectLevel.isException(level)
321}
322
323class Dp1ToDp2IO extends XSBundle {
324  val intDqToDp2 = Vec(dpParams.IntDqDeqWidth, DecoupledIO(new MicroOp))
325  val fpDqToDp2 = Vec(dpParams.FpDqDeqWidth, DecoupledIO(new MicroOp))
326  val lsDqToDp2 = Vec(dpParams.LsDqDeqWidth, DecoupledIO(new MicroOp))
327}
328
329class ReplayPregReq extends XSBundle {
330  // NOTE: set isInt and isFp both to 'false' when invalid
331  val isInt = Bool()
332  val isFp = Bool()
333  val preg = UInt(PhyRegIdxWidth.W)
334}
335
336class DebugBundle extends XSBundle {
337  val isMMIO = Bool()
338  val isPerfCnt = Bool()
339  val paddr = UInt(PAddrBits.W)
340}
341
342class ExuInput extends XSBundle {
343  val uop = new MicroOp
344  val src1, src2, src3 = UInt((XLEN + 1).W)
345}
346
347class ExuOutput extends XSBundle {
348  val uop = new MicroOp
349  val data = UInt((XLEN + 1).W)
350  val fflags = UInt(5.W)
351  val redirectValid = Bool()
352  val redirect = new Redirect
353  val debug = new DebugBundle
354}
355
356class ExternalInterruptIO extends XSBundle {
357  val mtip = Input(Bool())
358  val msip = Input(Bool())
359  val meip = Input(Bool())
360}
361
362class CSRSpecialIO extends XSBundle {
363  val exception = Flipped(ValidIO(new MicroOp))
364  val isInterrupt = Input(Bool())
365  val memExceptionVAddr = Input(UInt(VAddrBits.W))
366  val trapTarget = Output(UInt(VAddrBits.W))
367  val externalInterrupt = new ExternalInterruptIO
368  val interrupt = Output(Bool())
369}
370
371class ExceptionInfo extends XSBundle {
372  val uop = new MicroOp
373  val isInterrupt = Bool()
374}
375
376class RoqCommitInfo extends XSBundle {
377  val ldest = UInt(5.W)
378  val rfWen = Bool()
379  val fpWen = Bool()
380  val wflags = Bool()
381  val commitType = CommitType()
382  val pdest = UInt(PhyRegIdxWidth.W)
383  val old_pdest = UInt(PhyRegIdxWidth.W)
384  val ftqIdx = new FtqPtr
385  val ftqOffset = UInt(log2Up(PredictWidth).W)
386
387  // these should be optimized for synthesis verilog
388  val pc = UInt(VAddrBits.W)
389}
390
391class RoqCommitIO extends XSBundle {
392  val isWalk = Output(Bool())
393  val valid = Vec(CommitWidth, Output(Bool()))
394  val info = Vec(CommitWidth, Output(new RoqCommitInfo))
395
396  def hasWalkInstr = isWalk && valid.asUInt.orR
397
398  def hasCommitInstr = !isWalk && valid.asUInt.orR
399}
400
401class TlbFeedback extends XSBundle {
402  val rsIdx = UInt(log2Up(IssQueSize).W)
403  val hit = Bool()
404}
405
406class RSFeedback extends TlbFeedback
407
408class FrontendToBackendIO 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 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 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 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 DifftestBundle extends XSBundle {
458  val fromSbuffer = new Bundle() {
459    val sbufferResp = Output(Bool())
460    val sbufferAddr = Output(UInt(64.W))
461    val sbufferData = Output(Vec(64, UInt(8.W)))
462    val sbufferMask = Output(UInt(64.W))
463  }
464  val fromSQ = new Bundle() {
465    val storeCommit = Output(UInt(2.W))
466    val storeAddr   = Output(Vec(2, UInt(64.W)))
467    val storeData   = Output(Vec(2, UInt(64.W)))
468    val storeMask   = Output(Vec(2, UInt(8.W)))
469  }
470  val fromXSCore = new Bundle() {
471    val r = Output(Vec(64, UInt(XLEN.W)))
472  }
473  val fromCSR = new Bundle() {
474    val intrNO = Output(UInt(64.W))
475    val cause = Output(UInt(64.W))
476    val priviledgeMode = Output(UInt(2.W))
477    val mstatus = Output(UInt(64.W))
478    val sstatus = Output(UInt(64.W))
479    val mepc = Output(UInt(64.W))
480    val sepc = Output(UInt(64.W))
481    val mtval = Output(UInt(64.W))
482    val stval = Output(UInt(64.W))
483    val mtvec = Output(UInt(64.W))
484    val stvec = Output(UInt(64.W))
485    val mcause = Output(UInt(64.W))
486    val scause = Output(UInt(64.W))
487    val satp = Output(UInt(64.W))
488    val mip = Output(UInt(64.W))
489    val mie = Output(UInt(64.W))
490    val mscratch = Output(UInt(64.W))
491    val sscratch = Output(UInt(64.W))
492    val mideleg = Output(UInt(64.W))
493    val medeleg = Output(UInt(64.W))
494  }
495  val fromRoq = new Bundle() {
496    val commit = Output(UInt(32.W))
497    val thisPC = Output(UInt(XLEN.W))
498    val thisINST = Output(UInt(32.W))
499    val skip = Output(UInt(32.W))
500    val wen = Output(UInt(32.W))
501    val wdata = Output(Vec(CommitWidth, UInt(XLEN.W))) // set difftest width to 6
502    val wdst = Output(Vec(CommitWidth, UInt(32.W))) // set difftest width to 6
503    val wpc = Output(Vec(CommitWidth, UInt(XLEN.W))) // set difftest width to 6
504    val lpaddr = Output(Vec(CommitWidth, UInt(64.W)))
505    val ltype = Output(Vec(CommitWidth, UInt(32.W)))
506    val lfu = Output(Vec(CommitWidth, UInt(4.W)))
507    val isRVC = Output(UInt(32.W))
508    val scFailed = Output(Bool())
509  }
510  val fromAtomic = new Bundle() {
511    val atomicResp = Output(Bool())
512    val atomicAddr = Output(UInt(64.W))
513    val atomicData = Output(UInt(64.W))
514    val atomicMask = Output(UInt(8.W))
515    val atomicFuop = Output(UInt(8.W))
516    val atomicOut  = Output(UInt(64.W))
517  }
518  val fromPtw = new Bundle() {
519    val ptwResp = Output(Bool())
520    val ptwAddr = Output(UInt(64.W))
521    val ptwData = Output(Vec(4, UInt(64.W)))
522  }
523}
524
525class TrapIO extends XSBundle {
526  val valid = Output(Bool())
527  val code = Output(UInt(3.W))
528  val pc = Output(UInt(VAddrBits.W))
529  val cycleCnt = Output(UInt(XLEN.W))
530  val instrCnt = Output(UInt(XLEN.W))
531}
532
533class PerfInfoIO extends XSBundle {
534  val clean = Input(Bool())
535  val dump = Input(Bool())
536}
537
538class CustomCSRCtrlIO extends XSBundle {
539  // Prefetcher
540  val l1plus_pf_enable = Output(Bool())
541  val l2_pf_enable = Output(Bool())
542  val dsid = Output(UInt(8.W)) // TODO: DsidWidth as parameter
543  // Load violation predict
544  val lvpred_disable = Output(Bool())
545  val no_spec_load = Output(Bool())
546  val waittable_timeout = Output(UInt(5.W))
547  // Branch predicter
548  val bp_ctrl = Output(new BPUCtrl)
549}