xref: /XiangShan/src/main/scala/xiangshan/frontend/BPU.scala (revision 708ceed4afe43fb0ea3a52407e46b2794c573634)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan.frontend
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.experimental.chiselName
22import chisel3.util._
23import xiangshan._
24import utils._
25
26import scala.math.min
27
28trait HasBPUConst extends HasXSParameter with HasIFUConst {
29  val MaxMetaLength = 1024 // TODO: Reduce meta length
30  val MaxBasicBlockSize = 32
31  val LHistoryLength = 32
32  val numBr = 2
33  val useBPD = true
34  val useLHist = true
35
36  def BP_S1 = 1.U(2.W)
37  def BP_S2 = 2.U(2.W)
38  def BP_S3 = 3.U(2.W)
39
40
41  val debug = true
42  val resetVector = 0x80000000L//TODO: set reset vec
43  // TODO: Replace log2Up by log2Ceil
44}
45
46trait HasBPUParameter extends HasXSParameter with HasBPUConst {
47  val BPUDebug = true && !env.FPGAPlatform && env.EnablePerfDebug
48  val EnableCFICommitLog = true
49  val EnbaleCFIPredLog = true
50  val EnableBPUTimeRecord = (EnableCFICommitLog || EnbaleCFIPredLog) && !env.FPGAPlatform
51  val EnableCommit = false
52}
53
54class BPUCtrl(implicit p: Parameters) extends XSBundle {
55  val ubtb_enable = Bool()
56  val btb_enable  = Bool()
57  val bim_enable  = Bool()
58  val tage_enable = Bool()
59  val sc_enable   = Bool()
60  val ras_enable  = Bool()
61  val loop_enable = Bool()
62}
63
64trait BPUUtils extends HasXSParameter {
65  // circular shifting
66  def circularShiftLeft(source: UInt, len: Int, shamt: UInt): UInt = {
67    val res = Wire(UInt(len.W))
68    val higher = source << shamt
69    val lower = source >> (len.U - shamt)
70    res := higher | lower
71    res
72  }
73
74  def circularShiftRight(source: UInt, len: Int, shamt: UInt): UInt = {
75    val res = Wire(UInt(len.W))
76    val higher = source << (len.U - shamt)
77    val lower = source >> shamt
78    res := higher | lower
79    res
80  }
81
82  // To be verified
83  def satUpdate(old: UInt, len: Int, taken: Bool): UInt = {
84    val oldSatTaken = old === ((1 << len)-1).U
85    val oldSatNotTaken = old === 0.U
86    Mux(oldSatTaken && taken, ((1 << len)-1).U,
87      Mux(oldSatNotTaken && !taken, 0.U,
88        Mux(taken, old + 1.U, old - 1.U)))
89  }
90
91  def signedSatUpdate(old: SInt, len: Int, taken: Bool): SInt = {
92    val oldSatTaken = old === ((1 << (len-1))-1).S
93    val oldSatNotTaken = old === (-(1 << (len-1))).S
94    Mux(oldSatTaken && taken, ((1 << (len-1))-1).S,
95      Mux(oldSatNotTaken && !taken, (-(1 << (len-1))).S,
96        Mux(taken, old + 1.S, old - 1.S)))
97  }
98
99  def getFallThroughAddr(start: UInt, carry: Bool, pft: UInt) = {
100    val higher = start.head(VAddrBits-log2Ceil(PredictWidth)-instOffsetBits-1)
101    Cat(Mux(carry, higher+1.U, higher), pft, 0.U(instOffsetBits.W))
102  }
103
104  def foldTag(tag: UInt, l: Int): UInt = {
105    val nChunks = (tag.getWidth + l - 1) / l
106    val chunks = (0 until nChunks).map { i =>
107      tag(min((i+1)*l, tag.getWidth)-1, i*l)
108    }
109    ParallelXOR(chunks)
110  }
111}
112
113// class BranchPredictionUpdate(implicit p: Parameters) extends XSBundle with HasBPUConst {
114//   val pc = UInt(VAddrBits.W)
115//   val br_offset = Vec(num_br, UInt(log2Up(MaxBasicBlockSize).W))
116//   val br_mask = Vec(MaxBasicBlockSize, Bool())
117//
118//   val jmp_valid = Bool()
119//   val jmp_type = UInt(3.W)
120//
121//   val is_NextMask = Vec(FetchWidth*2, Bool())
122//
123//   val cfi_idx = Valid(UInt(log2Ceil(MaxBasicBlockSize).W))
124//   val cfi_mispredict = Bool()
125//   val cfi_is_br = Bool()
126//   val cfi_is_jal = Bool()
127//   val cfi_is_jalr = Bool()
128//
129//   val ghist = new GlobalHistory()
130//
131//   val target = UInt(VAddrBits.W)
132//
133//   val meta = UInt(MaxMetaLength.W)
134//   val spec_meta = UInt(MaxMetaLength.W)
135//
136//   def taken = cfi_idx.valid
137// }
138
139class BasePredictorInput (implicit p: Parameters) extends XSBundle with HasBPUConst {
140  def nInputs = 1
141
142  val s0_pc = UInt(VAddrBits.W)
143
144  val ghist = UInt(HistoryLength.W)
145  val phist = UInt(PathHistoryLength.W)
146
147  val resp_in = Vec(nInputs, new BranchPredictionResp)
148  // val toFtq_fire = Bool()
149
150  // val s0_all_ready = Bool()
151}
152
153class BasePredictorOutput (implicit p: Parameters) extends XSBundle with HasBPUConst {
154  val s3_meta = UInt(MaxMetaLength.W) // This is use by composer
155  val resp = new BranchPredictionResp
156
157  // These store in meta, extract in composer
158  // val rasSp = UInt(log2Ceil(RasSize).W)
159  // val rasTop = new RASEntry
160  // val specCnt = Vec(PredictWidth, UInt(10.W))
161}
162
163class BasePredictorIO (implicit p: Parameters) extends XSBundle with HasBPUConst {
164  val in  = Flipped(DecoupledIO(new BasePredictorInput)) // TODO: Remove DecoupledIO
165  // val out = DecoupledIO(new BasePredictorOutput)
166  val out = Output(new BasePredictorOutput)
167  // val flush_out = Valid(UInt(VAddrBits.W))
168
169  // val ctrl = Input(new BPUCtrl())
170
171  val s0_fire = Input(Bool())
172  val s1_fire = Input(Bool())
173  val s2_fire = Input(Bool())
174  val s3_fire = Input(Bool())
175
176  val s1_ready = Output(Bool())
177  val s2_ready = Output(Bool())
178  val s3_ready = Output(Bool())
179
180  val update = Flipped(Valid(new BranchPredictionUpdate))
181  val redirect = Flipped(Valid(new BranchPredictionRedirect))
182}
183
184abstract class BasePredictor(implicit p: Parameters) extends XSModule with HasBPUConst with BPUUtils {
185  val meta_size = 0
186  val spec_meta_size = 0
187
188  val io = IO(new BasePredictorIO())
189
190  io.out.resp := io.in.bits.resp_in(0)
191
192  io.out.s3_meta := 0.U
193
194  io.in.ready := !io.redirect.valid
195
196  io.s1_ready := true.B
197  io.s2_ready := true.B
198  io.s3_ready := true.B
199
200  val s0_pc       = WireInit(io.in.bits.s0_pc) // fetchIdx(io.f0_pc)
201  val s1_pc       = RegEnable(s0_pc, resetVector.U, io.s0_fire)
202  val s2_pc       = RegEnable(s1_pc, io.s1_fire)
203  val s3_pc       = RegEnable(s2_pc, io.s2_fire)
204}
205
206class FakePredictor(implicit p: Parameters) extends BasePredictor {
207  io.in.ready                 := true.B
208  io.out.s3_meta              := 0.U
209  io.out.resp := io.in.bits.resp_in(0)
210}
211
212class BpuToFtqIO(implicit p: Parameters) extends XSBundle {
213  val resp = DecoupledIO(new BpuToFtqBundle())
214}
215
216class PredictorIO(implicit p: Parameters) extends XSBundle {
217  val bpu_to_ftq = new BpuToFtqIO()
218  val ftq_to_bpu = Flipped(new FtqToBpuIO())
219}
220
221class FakeBPU(implicit p: Parameters) extends XSModule with HasBPUConst {
222  val io = IO(new PredictorIO)
223
224  val toFtq_fire = io.bpu_to_ftq.resp.valid && io.bpu_to_ftq.resp.ready
225
226  val s0_pc = RegInit(resetVector.U)
227
228  when(toFtq_fire) {
229    s0_pc := s0_pc + (FetchWidth*4).U
230  }
231
232  when (io.ftq_to_bpu.redirect.valid) {
233    s0_pc := io.ftq_to_bpu.redirect.bits.cfiUpdate.target
234  }
235
236  io.bpu_to_ftq.resp.valid := !reset.asBool() && !io.ftq_to_bpu.redirect.valid
237
238  io.bpu_to_ftq.resp.bits := 0.U.asTypeOf(new BranchPredictionBundle)
239  io.bpu_to_ftq.resp.bits.s1.pc := s0_pc
240  io.bpu_to_ftq.resp.bits.s1.ftb_entry.pftAddr := s0_pc + 32.U
241}
242
243@chiselName
244class Predictor(implicit p: Parameters) extends XSModule with HasBPUConst {
245  val io = IO(new PredictorIO)
246
247  val predictors = Module(if (useBPD) new Composer else new FakePredictor)
248
249  val s0_fire, s1_fire, s2_fire, s3_fire = Wire(Bool())
250  val s1_valid, s2_valid, s3_valid = RegInit(false.B)
251  val s1_ready, s2_ready, s3_ready = Wire(Bool())
252  val s1_components_ready, s2_components_ready, s3_components_ready = Wire(Bool())
253
254  val s0_pc = WireInit(resetVector.U)
255  val s0_pc_reg = RegNext(s0_pc, init=resetVector.U)
256  val s1_pc = RegEnable(s0_pc, s0_fire)
257  val s2_pc = RegEnable(s1_pc, s1_fire)
258  val s3_pc = RegEnable(s2_pc, s2_fire)
259
260  val s0_ghist = WireInit(0.U.asTypeOf(new GlobalHistory))
261  val s0_ghist_reg = RegNext(s0_ghist, init=0.U.asTypeOf(new GlobalHistory))
262  val s1_ghist = RegEnable(s0_ghist, 0.U.asTypeOf(new GlobalHistory), s0_fire)
263  val s2_ghist = RegEnable(s1_ghist, 0.U.asTypeOf(new GlobalHistory), s1_fire)
264  val s3_ghist = RegEnable(s2_ghist, 0.U.asTypeOf(new GlobalHistory), s2_fire)
265
266  val s0_phist = WireInit(0.U(PathHistoryLength.W))
267  val s0_phist_reg = RegNext(s0_phist, init=0.U(PathHistoryLength.W))
268  val s1_phist = RegEnable(s0_phist, 0.U, s0_fire)
269  val s2_phist = RegEnable(s1_phist, 0.U, s1_fire)
270  val s3_phist = RegEnable(s2_phist, 0.U, s2_fire)
271
272  val resp = predictors.io.out.resp
273
274
275  val toFtq_fire = io.bpu_to_ftq.resp.valid && io.bpu_to_ftq.resp.ready
276
277  when(RegNext(reset.asBool) && !reset.asBool) {
278    s0_ghist := 0.U.asTypeOf(new GlobalHistory)
279    s0_phist := 0.U
280    s0_pc := resetVector.U
281  }
282
283  // when(toFtq_fire) {
284    // final_gh := s3_gh.update(io.bpu_to_ftq.resp.bits.ftb_entry.brValids.reduce(_||_) && !io.bpu_to_ftq.resp.bits.preds.taken,
285    //   io.bpu_to_ftq.resp.bits.preds.taken)
286  // }
287
288  val s1_flush, s2_flush, s3_flush = Wire(Bool())
289  val s2_redirect, s3_redirect = Wire(Bool())
290
291  // val s1_bp_resp = predictors.io.out.resp.s1
292  // val s2_bp_resp = predictors.io.out.resp.s2
293  // val s3_bp_resp = predictors.io.out.resp.s3
294
295  // predictors.io := DontCare
296  predictors.io.in.valid := s0_fire
297  predictors.io.in.bits.s0_pc := s0_pc
298  predictors.io.in.bits.ghist := s0_ghist.predHist
299  predictors.io.in.bits.phist := s0_phist
300  predictors.io.in.bits.resp_in(0) := (0.U).asTypeOf(new BranchPredictionResp)
301  // predictors.io.in.bits.resp_in(0).s1.pc := s0_pc
302  // predictors.io.in.bits.toFtq_fire := toFtq_fire
303
304  // predictors.io.out.ready := io.bpu_to_ftq.resp.ready
305
306  // Pipeline logic
307  s2_redirect := false.B
308  s3_redirect := false.B
309
310  s3_flush := io.ftq_to_bpu.redirect.valid
311  s2_flush := s3_flush || s3_redirect
312  s1_flush := s2_flush || s2_redirect
313
314  s1_components_ready := predictors.io.s1_ready
315  s1_ready := s1_fire || !s1_valid
316  s0_fire := !reset.asBool && s1_components_ready && s1_ready
317  predictors.io.s0_fire := s0_fire
318
319  s2_components_ready := predictors.io.s2_ready
320  s2_ready := s2_fire || !s2_valid
321  s1_fire := s1_valid && s2_components_ready && s2_ready && io.bpu_to_ftq.resp.ready
322
323  when(s0_fire)         { s1_valid := true.B  }
324    .elsewhen(s1_flush) { s1_valid := false.B }
325    .elsewhen(s1_fire)  { s1_valid := false.B }
326
327  predictors.io.s1_fire := s1_fire
328
329  s3_components_ready := predictors.io.s3_ready
330  s3_ready := s3_fire || !s3_valid
331  s2_fire := s2_valid && s3_components_ready && s3_ready
332
333  when(s2_flush)                    { s2_valid := false.B }
334    .elsewhen(s1_fire && !s1_flush) { s2_valid := true.B  }
335    .elsewhen(s2_fire)              { s2_valid := false.B }
336
337  predictors.io.s2_fire := s2_fire
338
339  // s3_fire := s3_valid && io.bpu_to_ftq.resp.ready
340  s3_fire := s3_valid
341
342  when(s3_flush)                    { s3_valid := false.B }
343    .elsewhen(s2_fire && !s2_flush) { s3_valid := true.B  }
344    .elsewhen(s3_fire)              { s3_valid := false.B }
345
346  predictors.io.s3_fire := s3_fire
347
348  io.bpu_to_ftq.resp.valid :=
349    s1_valid && s2_components_ready && s2_ready ||
350    s2_fire && s2_redirect ||
351    s3_fire && s3_redirect
352  io.bpu_to_ftq.resp.bits  := BpuToFtqBundle(predictors.io.out.resp)
353  io.bpu_to_ftq.resp.bits.meta  := predictors.io.out.s3_meta
354  io.bpu_to_ftq.resp.bits.s3.ghist  := s3_ghist
355  io.bpu_to_ftq.resp.bits.s3.phist  := s3_phist
356
357  s0_pc := s0_pc_reg
358  s0_ghist := s0_ghist_reg
359  s0_phist := s0_phist_reg
360
361  // History manage
362  // s1
363  val s1_shift = Mux(resp.s1.preds.hit,
364    Mux(resp.s1.real_br_taken_mask.asUInt === 0.U, PopCount(resp.s1.ftb_entry.brValids), PopCount(LowerMaskFromLowest(resp.s1.real_br_taken_mask.asUInt))),
365    0.U((log2Ceil(numBr)+1).W))
366  val s1_taken = Mux(resp.s1.preds.hit, resp.s1.real_br_taken_mask.asUInt =/= 0.U, false.B)
367  val s1_predicted_ghist = s1_ghist.update(s1_shift, s1_taken)
368
369  XSDebug(p"[hit] ${resp.s1.preds.hit} [s1_real_br_taken_mask] ${Binary(resp.s1.real_br_taken_mask.asUInt)} [s1_shift] ${s1_shift} [s1_taken] ${s1_taken}\n")
370  XSDebug(p"s1_predicted_ghist=${Binary(s1_predicted_ghist.predHist)}\n")
371
372  when(s1_valid) {
373    s0_pc := resp.s1.target
374    s0_ghist := s1_predicted_ghist
375    s0_phist := (s1_phist << 1) | s1_pc(instOffsetBits)
376  }
377
378  // s2
379  val s2_shift = Mux(resp.s2.preds.hit,
380    Mux(resp.s2.real_br_taken_mask.asUInt === 0.U, PopCount(resp.s2.ftb_entry.brValids), PopCount(LowerMaskFromLowest(resp.s2.real_br_taken_mask.asUInt))),
381    0.U((log2Ceil(numBr)+1).W))
382  val s2_taken = Mux(resp.s2.preds.hit, resp.s2.real_br_taken_mask.asUInt =/= 0.U, false.B)
383  val s2_predicted_ghist = s2_ghist.update(s2_shift, s2_taken)
384
385  val s2_correct_s1_ghist = s1_ghist =/= s2_predicted_ghist
386  val s2_correct_s0_ghist_reg = s0_ghist_reg =/= s2_predicted_ghist
387
388  val previous_s1_pred_taken = RegEnable(resp.s1.real_taken_mask.asUInt.orR, init=false.B, enable=s1_fire)
389  val s2_pred_taken = resp.s2.real_taken_mask.asUInt.orR
390
391  when(s2_fire) {
392    when((s1_valid && (s1_pc =/= resp.s2.target || s2_correct_s1_ghist)) ||
393      !s1_valid && (s0_pc_reg =/= resp.s2.target || s2_correct_s0_ghist_reg) ||
394      previous_s1_pred_taken =/= s2_pred_taken) {
395      s0_ghist := s2_predicted_ghist
396      s2_redirect := true.B
397      s0_pc := resp.s2.target
398      s0_phist := (s2_phist << 1) | s2_pc(instOffsetBits)
399      XSDebug(p"s1_valid=$s1_valid, s1_pc=${Hexadecimal(s1_pc)}, s2_resp_target=${Hexadecimal(resp.s2.target)}\n")
400      XSDebug(p"s2_correct_s1_ghist=$s2_correct_s1_ghist\n")
401      XSDebug(p"s1_ghist=${Binary(s1_ghist.predHist)}\n")
402      XSDebug(p"s2_predicted_ghist=${Binary(s2_predicted_ghist.predHist)}\n")
403    }
404  }
405
406  val s2_redirect_target = s2_fire && s1_valid && s1_pc =/= resp.s2.target
407  val s2_saw_s1_hit = RegEnable(resp.s1.preds.hit, s1_fire)
408  val s2_redirect_target_both_hit = s2_redirect_target &&  s2_saw_s1_hit &&  resp.s2.preds.hit
409
410  XSPerfAccumulate("s2_redirect_because_s1_not_valid", s2_fire && !s1_valid)
411  XSPerfAccumulate("s2_redirect_because_target_diff", s2_fire && s1_valid && s1_pc =/= resp.s2.target)
412  XSPerfAccumulate("s2_redirect_target_diff_s1_nhit_s2_hit", s2_redirect_target && !s2_saw_s1_hit &&  resp.s2.preds.hit)
413  XSPerfAccumulate("s2_redirect_target_diff_s1_hit_s2_nhit", s2_redirect_target &&  s2_saw_s1_hit && !resp.s2.preds.hit)
414  XSPerfAccumulate("s2_redirect_target_diff_both_hit",  s2_redirect_target &&  s2_saw_s1_hit &&  resp.s2.preds.hit)
415  XSPerfAccumulate("s2_redirect_br_direction_diff",
416    s2_redirect_target_both_hit &&
417    RegEnable(PriorityEncoder(resp.s1.preds.taken_mask), s1_fire) =/= PriorityEncoder(resp.s2.preds.taken_mask))
418  XSPerfAccumulate("s2_redirect_because_ghist_diff", s2_fire && s1_valid && s2_correct_s1_ghist)
419
420  // s3
421  val s3_shift = Mux(resp.s3.preds.hit,
422    Mux(resp.s3.real_br_taken_mask.asUInt === 0.U, PopCount(resp.s3.ftb_entry.brValids), PopCount(LowerMaskFromLowest(resp.s3.real_br_taken_mask.asUInt))),
423    0.U((log2Ceil(numBr)+1).W))
424  val s3_taken = Mux(resp.s3.preds.hit, resp.s3.real_br_taken_mask.asUInt =/= 0.U, false.B)
425  val s3_predicted_ghist = s3_ghist.update(s3_shift, s3_taken)
426
427  val s3_correct_s2_ghist = s2_ghist =/= s3_predicted_ghist
428  val s3_correct_s1_ghist = s1_ghist =/= s3_predicted_ghist
429  val s3_correct_s0_ghist_reg = s0_ghist_reg =/= s3_predicted_ghist
430
431  val previous_s2_pred_taken = RegEnable(resp.s2.real_taken_mask.asUInt.orR, init=false.B, enable=s2_fire)
432  val s3_pred_taken = resp.s3.real_taken_mask.asUInt.orR
433
434  when(s3_fire) {
435    when((s2_valid && (s2_pc =/= resp.s3.target || s3_correct_s2_ghist)) ||
436      (!s2_valid && s1_valid && (s1_pc =/= resp.s3.target || s3_correct_s1_ghist)) ||
437      (!s2_valid && !s1_valid && (s0_pc_reg =/= resp.s3.target || s3_correct_s0_ghist_reg)) ||
438      previous_s2_pred_taken =/= s3_pred_taken) {
439
440      s0_ghist := s3_predicted_ghist
441      s3_redirect := true.B
442      s0_pc := resp.s3.target
443      s0_phist := (s3_phist << 1) | s3_pc(instOffsetBits)
444    }
445  }
446
447  // Send signal tell Ftq override
448  val s2_ftq_idx = RegEnable(io.ftq_to_bpu.enq_ptr, s1_fire)
449  val s3_ftq_idx = RegEnable(s2_ftq_idx, s2_fire)
450
451  io.bpu_to_ftq.resp.bits.s1.valid := s1_fire && !s1_flush
452  io.bpu_to_ftq.resp.bits.s1.hasRedirect := false.B
453  io.bpu_to_ftq.resp.bits.s1.ftq_idx := DontCare
454  io.bpu_to_ftq.resp.bits.s2.valid := s2_fire && !s2_flush
455  io.bpu_to_ftq.resp.bits.s2.hasRedirect := s2_redirect
456  io.bpu_to_ftq.resp.bits.s2.ftq_idx := s2_ftq_idx
457  io.bpu_to_ftq.resp.bits.s3.valid := s3_fire && !s3_flush
458  io.bpu_to_ftq.resp.bits.s3.hasRedirect := s3_redirect
459  io.bpu_to_ftq.resp.bits.s3.ftq_idx := s3_ftq_idx
460
461  val redirect = io.ftq_to_bpu.redirect.bits
462
463  predictors.io.update := io.ftq_to_bpu.update
464  predictors.io.redirect := io.ftq_to_bpu.redirect
465
466  when(io.ftq_to_bpu.redirect.valid) {
467    val oldGh = redirect.cfiUpdate.hist
468
469    val shift = redirect.cfiUpdate.shift
470    val addIntoHist = redirect.cfiUpdate.addIntoHist
471
472    val isBr = redirect.cfiUpdate.pd.isBr
473    val taken = redirect.cfiUpdate.taken
474
475    val updatedGh = oldGh.update(shift, taken && addIntoHist)
476    s0_ghist := updatedGh // TODO: History fix logic
477    s0_pc := redirect.cfiUpdate.target
478    val oldPh = redirect.cfiUpdate.phist
479    val phNewBit = redirect.cfiUpdate.phNewBit
480    s0_phist := (oldPh << 1) | phNewBit
481
482    XSDebug(io.ftq_to_bpu.redirect.valid, p"-------------redirect Repair------------\n")
483    // XSDebug(io.ftq_to_bpu.redirect.valid, p"taken_mask=${Binary(taken_mask.asUInt)}, brValids=${Binary(brValids.asUInt)}\n")
484    XSDebug(io.ftq_to_bpu.redirect.valid, p"isBr: ${isBr}, taken: ${taken}, addIntoHist: ${addIntoHist}, shift: ${shift}\n")
485    XSDebug(io.ftq_to_bpu.redirect.valid, p"oldGh   =${Binary(oldGh.predHist)}\n")
486    XSDebug(io.ftq_to_bpu.redirect.valid, p"updateGh=${Binary(updatedGh.predHist)}\n")
487
488  }
489
490  XSDebug(RegNext(reset.asBool) && !reset.asBool, "Reseting...\n")
491  XSDebug(io.ftq_to_bpu.update.valid, p"Update from ftq\n")
492  XSDebug(io.ftq_to_bpu.redirect.valid, p"Redirect from ftq\n")
493
494  XSDebug("[BP0]                 fire=%d                      pc=%x\n", s0_fire, s0_pc)
495  XSDebug("[BP1] v=%d r=%d cr=%d fire=%d             flush=%d pc=%x\n",
496    s1_valid, s1_ready, s1_components_ready, s1_fire, s1_flush, s1_pc)
497  XSDebug("[BP2] v=%d r=%d cr=%d fire=%d redirect=%d flush=%d pc=%x\n",
498  s2_valid, s2_ready, s2_components_ready, s2_fire, s2_redirect, s2_flush, s2_pc)
499  XSDebug("[BP3] v=%d r=%d cr=%d fire=%d redirect=%d flush=%d pc=%x\n",
500  s3_valid, s3_ready, s3_components_ready, s3_fire, s3_redirect, s3_flush, s3_pc)
501  XSDebug("[FTQ] ready=%d\n", io.bpu_to_ftq.resp.ready)
502  XSDebug("resp.s1.target=%x\n", resp.s1.target)
503  XSDebug("resp.s2.target=%x\n", resp.s2.target)
504  XSDebug("s0_ghist: %b\n", s0_ghist.predHist)
505  XSDebug("s1_ghist: %b\n", s1_ghist.predHist)
506  XSDebug("s2_ghist: %b\n", s2_ghist.predHist)
507  XSDebug("s3_ghist: %b\n", s3_ghist.predHist)
508  XSDebug("s2_predicted_ghist: %b\n", s2_predicted_ghist.predHist)
509  XSDebug("s3_predicted_ghist: %b\n", s3_predicted_ghist.predHist)
510  XSDebug("s3_correct_s2_ghist: %b, s3_correct_s1_ghist: %b, s2_correct_s1_ghist: %b\n",
511  s3_correct_s2_ghist,  s3_correct_s1_ghist,  s2_correct_s1_ghist)
512
513
514  io.ftq_to_bpu.update.bits.display(io.ftq_to_bpu.update.valid)
515  io.ftq_to_bpu.redirect.bits.display(io.ftq_to_bpu.redirect.valid)
516
517
518  XSPerfAccumulate("s2_redirect", s2_redirect)
519  XSPerfAccumulate("s3_redirect", s3_redirect)
520
521}
522