1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* 4* XiangShan is licensed under Mulan PSL v2. 5* You can use this software according to the terms and conditions of the Mulan PSL v2. 6* You may obtain a copy of Mulan PSL v2 at: 7* http://license.coscl.org.cn/MulanPSL2 8* 9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12* 13* See the Mulan PSL v2 for more details. 14***************************************************************************************/ 15 16package xiangshan.frontend 17 18import chipsalliance.rocketchip.config.Parameters 19import chisel3._ 20import chisel3.util._ 21import utils._ 22import xiangshan._ 23import chisel3.experimental.chiselName 24 25trait HasBPUParameter extends HasXSParameter { 26 val BPUDebug = true && !env.FPGAPlatform 27 val EnableCFICommitLog = true 28 val EnbaleCFIPredLog = true 29 val EnableBPUTimeRecord = (EnableCFICommitLog || EnbaleCFIPredLog) && !env.FPGAPlatform 30 val EnableCommit = false 31} 32 33class TableAddr(val idxBits: Int, val banks: Int)(implicit p: Parameters) extends XSBundle with HasIFUConst { 34 def tagBits = VAddrBits - idxBits - instOffsetBits 35 36 val tag = UInt(tagBits.W) 37 val idx = UInt(idxBits.W) 38 val offset = UInt(instOffsetBits.W) 39 40 def fromUInt(x: UInt) = x.asTypeOf(UInt(VAddrBits.W)).asTypeOf(this) 41 def getTag(x: UInt) = fromUInt(x).tag 42 def getIdx(x: UInt) = fromUInt(x).idx 43 def getBank(x: UInt) = getIdx(x)(log2Up(banks) - 1, 0) 44 def getBankIdx(x: UInt) = getIdx(x)(idxBits - 1, log2Up(banks)) 45} 46 47class PredictorResponse(implicit p: Parameters) extends XSBundle { 48 class UbtbResp extends XSBundle { 49 // the valid bits indicates whether a target is hit 50 val targets = Vec(PredictWidth, UInt(VAddrBits.W)) 51 val hits = Vec(PredictWidth, Bool()) 52 val takens = Vec(PredictWidth, Bool()) 53 val brMask = Vec(PredictWidth, Bool()) 54 val is_RVC = Vec(PredictWidth, Bool()) 55 } 56 class BtbResp extends XSBundle { 57 // the valid bits indicates whether a target is hit 58 val targets = Vec(PredictWidth, UInt(VAddrBits.W)) 59 val hits = Vec(PredictWidth, Bool()) 60 val isBrs = Vec(PredictWidth, Bool()) 61 val isRVC = Vec(PredictWidth, Bool()) 62 } 63 class BimResp extends XSBundle { 64 val ctrs = Vec(PredictWidth, UInt(2.W)) 65 } 66 class TageResp extends XSBundle { 67 // the valid bits indicates whether a prediction is hit 68 val takens = Vec(PredictWidth, Bool()) 69 val hits = Vec(PredictWidth, Bool()) 70 } 71 class LoopResp extends XSBundle { 72 val exit = Vec(PredictWidth, Bool()) 73 } 74 75 val ubtb = new UbtbResp 76 val btb = new BtbResp 77 val bim = new BimResp 78 val tage = new TageResp 79 val loop = new LoopResp 80} 81 82trait PredictorUtils { 83 // circular shifting 84 def circularShiftLeft(source: UInt, len: Int, shamt: UInt): UInt = { 85 val res = Wire(UInt(len.W)) 86 val higher = source << shamt 87 val lower = source >> (len.U - shamt) 88 res := higher | lower 89 res 90 } 91 92 def circularShiftRight(source: UInt, len: Int, shamt: UInt): UInt = { 93 val res = Wire(UInt(len.W)) 94 val higher = source << (len.U - shamt) 95 val lower = source >> shamt 96 res := higher | lower 97 res 98 } 99 100 // To be verified 101 def satUpdate(old: UInt, len: Int, taken: Bool): UInt = { 102 val oldSatTaken = old === ((1 << len)-1).U 103 val oldSatNotTaken = old === 0.U 104 Mux(oldSatTaken && taken, ((1 << len)-1).U, 105 Mux(oldSatNotTaken && !taken, 0.U, 106 Mux(taken, old + 1.U, old - 1.U))) 107 } 108 109 def signedSatUpdate(old: SInt, len: Int, taken: Bool): SInt = { 110 val oldSatTaken = old === ((1 << (len-1))-1).S 111 val oldSatNotTaken = old === (-(1 << (len-1))).S 112 Mux(oldSatTaken && taken, ((1 << (len-1))-1).S, 113 Mux(oldSatNotTaken && !taken, (-(1 << (len-1))).S, 114 Mux(taken, old + 1.S, old - 1.S))) 115 } 116} 117 118trait HasIFUFire { this: MultiIOModule => 119 val fires = IO(Input(Vec(4, Bool()))) 120 val s1_fire = fires(0) 121 val s2_fire = fires(1) 122 val s3_fire = fires(2) 123 val out_fire = fires(3) 124} 125 126trait HasCtrl { this: BasePredictor => 127 val ctrl = IO(Input(new BPUCtrl)) 128} 129 130abstract class BasePredictor(implicit p: Parameters) extends XSModule 131 with HasBPUParameter with HasIFUConst with PredictorUtils 132 with HasIFUFire with HasCtrl { 133 val metaLen = 0 134 135 // An implementation MUST extend the IO bundle with a response 136 // and the special input from other predictors, as well as 137 // the metas to store in BRQ 138 abstract class Resp extends XSBundle {} 139 abstract class FromOthers extends XSBundle {} 140 abstract class Meta extends XSBundle {} 141 142 class DefaultBasePredictorIO extends XSBundle { 143 val pc = Flipped(ValidIO(UInt(VAddrBits.W))) 144 val hist = Input(UInt(HistoryLength.W)) 145 val inMask = Input(UInt(PredictWidth.W)) 146 val update = Flipped(ValidIO(new FtqEntry)) 147 } 148 val io = new DefaultBasePredictorIO 149 val in_ready = IO(Output(Bool())) 150 in_ready := true.B 151 val debug = true 152} 153 154class BrInfo(implicit p: Parameters) extends XSBundle { 155 val metas = Vec(PredictWidth, new BpuMeta) 156 val rasSp = UInt(log2Ceil(RasSize).W) 157 val rasTop = new RASEntry 158 val specCnt = Vec(PredictWidth, UInt(10.W)) 159} 160class BPUStageIO(implicit p: Parameters) extends XSBundle { 161 val pc = UInt(VAddrBits.W) 162 val mask = UInt(PredictWidth.W) 163 val resp = new PredictorResponse 164 val brInfo = new BrInfo 165} 166 167 168abstract class BPUStage(implicit p: Parameters) extends XSModule with HasBPUParameter 169 with HasIFUConst with HasIFUFire { 170 class DefaultIO extends XSBundle { 171 val in = Input(new BPUStageIO) 172 val inFire = Input(Bool()) 173 val pred = Output(new BranchPrediction) // to ifu 174 val out = Output(new BPUStageIO) // to the next stage 175 val outFire = Input(Bool()) 176 177 val debug_hist = Input(UInt((if (BPUDebug) (HistoryLength) else 0).W)) 178 } 179 val io = IO(new DefaultIO) 180 181 val inLatch = RegEnable(io.in, io.inFire) 182 183 // Each stage has its own logic to decide 184 // takens, brMask, jalMask, targets and hasHalfRVI 185 val takens = Wire(Vec(PredictWidth, Bool())) 186 val brMask = Wire(Vec(PredictWidth, Bool())) 187 val jalMask = Wire(Vec(PredictWidth, Bool())) 188 val targets = Wire(Vec(PredictWidth, UInt(VAddrBits.W))) 189 val hasHalfRVI = Wire(Bool()) 190 191 io.pred <> DontCare 192 io.pred.takens := takens.asUInt 193 io.pred.brMask := brMask.asUInt 194 io.pred.jalMask := jalMask.asUInt 195 io.pred.targets := targets 196 io.pred.hasHalfRVI := hasHalfRVI 197 198 io.out <> DontCare 199 io.out.pc := inLatch.pc 200 io.out.mask := inLatch.mask 201 io.out.resp <> inLatch.resp 202 io.out.brInfo := inLatch.brInfo 203 204 if (BPUDebug) { 205 val jmpIdx = io.pred.jmpIdx 206 val taken = io.pred.taken 207 val target = Mux(taken, io.pred.targets(jmpIdx), snpc(inLatch.pc)) 208 XSDebug("in(%d): pc=%x, mask=%b\n", io.inFire, io.in.pc, io.in.mask) 209 XSDebug("inLatch: pc=%x, mask=%b\n", inLatch.pc, inLatch.mask) 210 XSDebug("out(%d): pc=%x, mask=%b, taken=%d, jmpIdx=%d, target=%x, hasHalfRVI=%d\n", 211 io.outFire, io.out.pc, io.out.mask, taken, jmpIdx, target, hasHalfRVI) 212 //val p = io.pred 213 } 214} 215 216@chiselName 217class BPUStage1(implicit p: Parameters) extends BPUStage { 218 219 // ubtb is accessed with inLatch pc in s1, 220 // so we use io.in instead of inLatch 221 val ubtbResp = io.in.resp.ubtb 222 // the read operation is already masked, so we do not need to mask here 223 takens := VecInit((0 until PredictWidth).map(i => ubtbResp.takens(i))) 224 // notTakens := VecInit((0 until PredictWidth).map(i => ubtbResp.hits(i) && !ubtbResp.takens(i) && ubtbResp.brMask(i))) 225 brMask := ubtbResp.brMask 226 jalMask := DontCare 227 targets := ubtbResp.targets 228 229 hasHalfRVI := ubtbResp.hits(PredictWidth-1) && !ubtbResp.is_RVC(PredictWidth-1) && HasCExtension.B 230 231 // resp and brInfo are from the components, 232 // so it does not need to be latched 233 io.out.resp <> io.in.resp 234 io.out.brInfo := io.in.brInfo 235 236 // For perf counters 237 if (!env.FPGAPlatform && env.EnablePerfDebug) { 238 io.out.brInfo.metas.zipWithIndex.foreach{case (meta, i) => 239 // record ubtb pred result 240 meta.ubtbAns.hit := ubtbResp.hits(i) 241 meta.ubtbAns.taken := ubtbResp.takens(i) 242 meta.ubtbAns.target := ubtbResp.targets(i) 243 } 244 } 245 246 if (BPUDebug) { 247 XSDebug(io.outFire, "outPred using ubtb resp: hits:%b, takens:%b, notTakens:%b, isRVC:%b\n", 248 ubtbResp.hits.asUInt, ubtbResp.takens.asUInt, ~ubtbResp.takens.asUInt & brMask.asUInt, ubtbResp.is_RVC.asUInt) 249 } 250 if (EnableBPUTimeRecord) { 251 io.out.brInfo.metas.map(_.debug_ubtb_cycle := GTimer()) 252 } 253} 254@chiselName 255class BPUStage2(implicit p: Parameters) extends BPUStage { 256 // Use latched response from s1 257 val btbResp = inLatch.resp.btb 258 val bimResp = inLatch.resp.bim 259 takens := VecInit((0 until PredictWidth).map(i => btbResp.hits(i) && (btbResp.isBrs(i) && bimResp.ctrs(i)(1) || !btbResp.isBrs(i)))) 260 targets := btbResp.targets 261 brMask := VecInit((0 until PredictWidth).map(i => btbResp.isBrs(i) && btbResp.hits(i))) 262 jalMask := DontCare 263 264 hasHalfRVI := btbResp.hits(PredictWidth-1) && !btbResp.isRVC(PredictWidth-1) && HasCExtension.B 265 266 // For perf counters 267 if (!env.FPGAPlatform && env.EnablePerfDebug) { 268 io.out.brInfo.metas.zipWithIndex.foreach{case (meta, i) => 269 // record btb pred result 270 meta.btbAns.hit := btbResp.hits(i) 271 meta.btbAns.taken := takens(i) 272 meta.btbAns.target := btbResp.targets(i) 273 } 274 } 275 276 if (BPUDebug) { 277 XSDebug(io.outFire, "outPred using btb&bim resp: hits:%b, ctrTakens:%b\n", 278 btbResp.hits.asUInt, VecInit(bimResp.ctrs.map(_(1))).asUInt) 279 } 280 if (EnableBPUTimeRecord) { 281 io.out.brInfo.metas.map(_.debug_btb_cycle := GTimer()) 282 } 283} 284@chiselName 285class BPUStage3(implicit p: Parameters) extends BPUStage { 286 class S3IO extends XSBundle { 287 val predecode = Input(new Predecode) 288 val redirect = Flipped(ValidIO(new Redirect)) 289 val ctrl = Input(new BPUCtrl) 290 } 291 val s3IO = IO(new S3IO) 292 // TAGE has its own pipelines and the 293 // response comes directly from s3, 294 // so we do not use those from inLatch 295 val tageResp = io.in.resp.tage 296 val tageTakens = tageResp.takens 297 298 val loopResp = io.in.resp.loop.exit 299 300 val pdMask = s3IO.predecode.mask 301 val pdLastHalf = s3IO.predecode.lastHalf 302 val pds = s3IO.predecode.pd 303 304 val btbResp = WireInit(inLatch.resp.btb) 305 val btbHits = WireInit(btbResp.hits.asUInt) 306 val bimTakens = VecInit(inLatch.resp.bim.ctrs.map(_(1))) 307 308 val brs = pdMask & Reverse(Cat(pds.map(_.isBr))) 309 val jals = pdMask & Reverse(Cat(pds.map(_.isJal))) 310 val jalrs = pdMask & Reverse(Cat(pds.map(_.isJalr))) 311 val calls = pdMask & Reverse(Cat(pds.map(_.isCall))) 312 val rets = pdMask & Reverse(Cat(pds.map(_.isRet))) 313 val RVCs = pdMask & Reverse(Cat(pds.map(_.isRVC))) 314 315 val callIdx = PriorityEncoder(calls) 316 val retIdx = PriorityEncoder(rets) 317 318 val brPred = (if(EnableBPD) tageTakens else bimTakens).asUInt 319 val loopRes = (if (EnableLoop) loopResp else VecInit(Fill(PredictWidth, 0.U(1.W)))).asUInt 320 val brTakens = ((brs & brPred) & ~loopRes) 321 // we should provide btb resp as well 322 btbHits := btbResp.hits.asUInt 323 324 // predict taken only if btb has a target, jal and br targets will be provided by IFU 325 takens := VecInit((0 until PredictWidth).map(i => jalrs(i) && btbHits(i) || (jals(i) || brTakens(i)))) 326 327 328 targets := inLatch.resp.btb.targets 329 330 brMask := WireInit(brs.asTypeOf(Vec(PredictWidth, Bool()))) 331 jalMask := WireInit(jals.asTypeOf(Vec(PredictWidth, Bool()))) 332 333 hasHalfRVI := pdLastHalf && HasCExtension.B 334 335 //RAS 336 if(EnableRAS){ 337 val ras = Module(new RAS) 338 ras.io <> DontCare 339 ras.io.pc.bits := packetAligned(inLatch.pc) 340 ras.io.pc.valid := io.outFire//predValid 341 ras.io.is_ret := rets.orR && (retIdx === io.pred.jmpIdx) 342 ras.io.callIdx.valid := calls.orR && (callIdx === io.pred.jmpIdx) 343 ras.io.callIdx.bits := callIdx 344 ras.io.isRVC := (calls & RVCs).orR //TODO: this is ugly 345 ras.io.isLastHalfRVI := s3IO.predecode.hasLastHalfRVI 346 ras.io.redirect := s3IO.redirect 347 ras.fires <> fires 348 ras.ctrl := s3IO.ctrl 349 350 for(i <- 0 until PredictWidth){ 351 io.out.brInfo.rasSp := ras.io.meta.rasSp 352 io.out.brInfo.rasTop := ras.io.meta.rasTop 353 } 354 val rasEn = s3IO.ctrl.ras_enable 355 takens := VecInit((0 until PredictWidth).map(i => { 356 (jalrs(i) && btbHits(i)) || 357 jals(i) || brTakens(i) || 358 (rasEn && rets(i)) || 359 (!rasEn && rets(i) && btbHits(i)) 360 } 361 )) 362 363 for (i <- 0 until PredictWidth) { 364 when(rets(i)){ 365 targets(i) := ras.io.out.target 366 } 367 } 368 369 // For perf counters 370 if (!env.FPGAPlatform && env.EnablePerfDebug) { 371 io.out.brInfo.metas.zipWithIndex.foreach{case (meta, i) => 372 // record tage pred result 373 meta.tageAns.hit := tageResp.hits(i) 374 meta.tageAns.taken := tageResp.takens(i) 375 meta.tageAns.target := DontCare 376 377 // record ras pred result 378 meta.rasAns.hit := true.B 379 meta.rasAns.taken := true.B 380 meta.rasAns.target := ras.io.out.target 381 382 // record loop pred result 383 meta.loopAns.hit := loopRes(i) 384 meta.loopAns.taken := false.B 385 meta.loopAns.target := DontCare 386 } 387 } 388 } 389 390 391 // Wrap tage resp and tage meta in 392 // This is ugly 393 io.out.resp.tage <> io.in.resp.tage 394 io.out.resp.loop <> io.in.resp.loop 395 for (i <- 0 until PredictWidth) { 396 io.out.brInfo.metas(i).tageMeta := io.in.brInfo.metas(i).tageMeta 397 io.out.brInfo.specCnt(i) := io.in.brInfo.specCnt(i) 398 } 399 400 if (BPUDebug) { 401 XSDebug(io.inFire, "predecode: pc:%x, mask:%b\n", inLatch.pc, s3IO.predecode.mask) 402 for (i <- 0 until PredictWidth) { 403 val pd = s3IO.predecode.pd(i) 404 XSDebug(io.inFire && s3IO.predecode.mask(i), "predecode(%d): brType:%d, br:%d, jal:%d, jalr:%d, call:%d, ret:%d, RVC:%d, excType:%d\n", 405 i.U, pd.brType, pd.isBr, pd.isJal, pd.isJalr, pd.isCall, pd.isRet, pd.isRVC, pd.excType) 406 } 407 XSDebug(p"brs:${Binary(brs)} jals:${Binary(jals)} jalrs:${Binary(jalrs)} calls:${Binary(calls)} rets:${Binary(rets)} rvcs:${Binary(RVCs)}\n") 408 XSDebug(p"callIdx:${callIdx} retIdx:${retIdx}\n") 409 XSDebug(p"brPred:${Binary(brPred)} loopRes:${Binary(loopRes)} brTakens:${Binary(brTakens)}\n") 410 } 411 412 if (EnbaleCFIPredLog) { 413 val out = io.out 414 XSDebug(io.outFire, p"cfi_pred: fetchpc(${Hexadecimal(out.pc)}) mask(${out.mask}) brmask(${brMask.asUInt}) hist(${Hexadecimal(io.debug_hist)})\n") 415 } 416 417 if (EnableBPUTimeRecord) { 418 io.out.brInfo.metas.map(_.debug_tage_cycle := GTimer()) 419 } 420} 421 422trait BranchPredictorComponents extends HasXSParameter { 423 val ubtb = Module(new MicroBTB) 424 val btb = Module(new BTB) 425 val bim = Module(new BIM) 426 val tage = (if(EnableBPD) { if (EnableSC) Module(new Tage_SC) 427 else Module(new Tage) } 428 else { Module(new FakeTage) }) 429 val loop = Module(new LoopPredictor) 430 val preds = Seq(ubtb, btb, bim, tage, loop) 431 preds.map(_.io := DontCare) 432} 433 434class BPUReq(implicit p: Parameters) extends XSBundle { 435 val pc = UInt(VAddrBits.W) 436 val hist = UInt(HistoryLength.W) 437 val inMask = UInt(PredictWidth.W) 438} 439 440class BPUCtrl(implicit p: Parameters) extends XSBundle { 441 val ubtb_enable = Bool() 442 val btb_enable = Bool() 443 val bim_enable = Bool() 444 val tage_enable = Bool() 445 val sc_enable = Bool() 446 val ras_enable = Bool() 447 val loop_enable = Bool() 448} 449 450abstract class BaseBPU(implicit p: Parameters) extends XSModule with BranchPredictorComponents 451 with HasBPUParameter with HasIFUConst { 452 val io = IO(new Bundle() { 453 // from backend 454 val redirect = Flipped(ValidIO(new Redirect)) 455 val ctrl = Input(new BPUCtrl) 456 val commit = Flipped(ValidIO(new FtqEntry)) 457 // from if1 458 val in = Input(new BPUReq) 459 val inFire = Input(Vec(4, Bool())) 460 // to if1 461 val in_ready = Output(Bool()) 462 // to if2/if3/if4 463 val out = Vec(3, Output(new BranchPrediction)) 464 // from if4 465 val predecode = Input(new Predecode) 466 // to if4, some bpu info used for updating 467 val brInfo = Output(new BrInfo) 468 }) 469 470 preds.map(p => { 471 p.io.update <> io.commit 472 p.fires <> io.inFire 473 p.ctrl <> io.ctrl 474 }) 475 476 io.in_ready := preds.map(p => p.in_ready).reduce(_&&_) 477 478 val s1 = Module(new BPUStage1) 479 val s2 = Module(new BPUStage2) 480 val s3 = Module(new BPUStage3) 481 482 Seq(s1, s2, s3).foreach(s => s.fires <> io.inFire) 483 484 val s1_fire = io.inFire(0) 485 val s2_fire = io.inFire(1) 486 val s3_fire = io.inFire(2) 487 val s4_fire = io.inFire(3) 488 489 s1.io.in <> DontCare 490 s2.io.in <> s1.io.out 491 s3.io.in <> s2.io.out 492 493 s1.io.inFire := s1_fire 494 s2.io.inFire := s2_fire 495 s3.io.inFire := s3_fire 496 497 s1.io.outFire := s2_fire 498 s2.io.outFire := s3_fire 499 s3.io.outFire := s4_fire 500 501 io.out(0) <> s1.io.pred 502 io.out(1) <> s2.io.pred 503 io.out(2) <> s3.io.pred 504 505 io.brInfo := s3.io.out.brInfo 506 507 if (BPUDebug) { 508 XSDebug(io.inFire(3), "bpuMeta sent!\n") 509 for (i <- 0 until PredictWidth) { 510 val b = io.brInfo.metas(i) 511 XSDebug(io.inFire(3), "brInfo(%d): btbWrWay:%d, bimCtr:%d\n", 512 i.U, b.btbWriteWay, b.bimCtr) 513 val t = b.tageMeta 514 XSDebug(io.inFire(3), " tageMeta: pvder(%d):%d, altDiffers:%d, pvderU:%d, pvderCtr:%d, allocate(%d):%d\n", 515 t.provider.valid, t.provider.bits, t.altDiffers, t.providerU, t.providerCtr, t.allocate.valid, t.allocate.bits) 516 } 517 } 518 val debug_verbose = false 519} 520 521 522class FakeBPU(implicit p: Parameters) extends BaseBPU { 523 io.out.foreach(i => { 524 // Provide not takens 525 i <> DontCare 526 i.takens := 0.U 527 }) 528 io.brInfo <> DontCare 529} 530@chiselName 531class BPU(implicit p: Parameters) extends BaseBPU { 532 533 //**********************Stage 1****************************// 534 535 val s1_resp_in = Wire(new PredictorResponse) 536 val s1_brInfo_in = Wire(new BrInfo) 537 538 s1_resp_in.tage := DontCare 539 s1_resp_in.loop := DontCare 540 s1_brInfo_in := DontCare 541 542 val s1_inLatch = RegEnable(io.in, s1_fire) 543 ubtb.io.pc.valid := s2_fire 544 ubtb.io.pc.bits := s1_inLatch.pc 545 ubtb.io.inMask := s1_inLatch.inMask 546 547 548 549 // Wrap ubtb response into resp_in and brInfo_in 550 s1_resp_in.ubtb <> ubtb.io.out 551 for (i <- 0 until PredictWidth) { 552 s1_brInfo_in.metas(i).ubtbHit := ubtb.io.out.hits(i) 553 } 554 555 btb.io.pc.valid := s1_fire 556 btb.io.pc.bits := io.in.pc 557 btb.io.inMask := io.in.inMask 558 559 560 561 // Wrap btb response into resp_in and brInfo_in 562 s1_resp_in.btb <> btb.io.resp 563 for (i <- 0 until PredictWidth) { 564 s1_brInfo_in.metas(i).btbWriteWay := btb.io.meta.writeWay(i) 565 s1_brInfo_in.metas(i).btbHit := btb.io.meta.hits(i) 566 } 567 568 bim.io.pc.valid := s1_fire 569 bim.io.pc.bits := io.in.pc 570 bim.io.inMask := io.in.inMask 571 572 573 // Wrap bim response into resp_in and brInfo_in 574 s1_resp_in.bim <> bim.io.resp 575 for (i <- 0 until PredictWidth) { 576 s1_brInfo_in.metas(i).bimCtr := bim.io.meta.ctrs(i) 577 } 578 579 580 s1.io.inFire := s1_fire 581 s1.io.in.pc := io.in.pc 582 s1.io.in.mask := io.in.inMask 583 s1.io.in.resp <> s1_resp_in 584 s1.io.in.brInfo <> s1_brInfo_in 585 586 val s1_hist = RegEnable(io.in.hist, enable=s1_fire) 587 val s2_hist = RegEnable(s1_hist, enable=s2_fire) 588 val s3_hist = RegEnable(s2_hist, enable=s3_fire) 589 590 s1.io.debug_hist := s1_hist 591 s2.io.debug_hist := s2_hist 592 s3.io.debug_hist := s3_hist 593 594 //**********************Stage 2****************************// 595 tage.io.pc.valid := s2_fire 596 tage.io.pc.bits := s2.io.in.pc // PC from s1 597 tage.io.hist := s1_hist // The inst is from s1 598 tage.io.inMask := s2.io.in.mask 599 tage.io.bim <> s1.io.out.resp.bim // Use bim results from s1 600 601 //**********************Stage 3****************************// 602 // Wrap tage response and meta into s3.io.in.bits 603 // This is ugly 604 605 loop.io.pc.valid := s2_fire 606 loop.io.if3_fire := s3_fire 607 loop.io.pc.bits := s2.io.in.pc 608 loop.io.inMask := io.predecode.mask 609 loop.io.respIn.taken := s3.io.pred.taken 610 loop.io.respIn.jmpIdx := s3.io.pred.jmpIdx 611 loop.io.redirect := s3.s3IO.redirect 612 613 614 s3.io.in.resp.tage <> tage.io.resp 615 s3.io.in.resp.loop <> loop.io.resp 616 for (i <- 0 until PredictWidth) { 617 s3.io.in.brInfo.metas(i).tageMeta := tage.io.meta(i) 618 s3.io.in.brInfo.specCnt(i) := loop.io.meta.specCnts(i) 619 } 620 621 s3.s3IO.predecode <> io.predecode 622 s3.s3IO.redirect <> io.redirect 623 s3.s3IO.ctrl <> io.ctrl 624 625 626 if (BPUDebug) { 627 if (debug_verbose) { 628 val uo = ubtb.io.out 629 XSDebug("debug: ubtb hits:%b, takens:%b, notTakens:%b\n", uo.hits.asUInt, uo.takens.asUInt, ~uo.takens.asUInt & uo.brMask.asUInt) 630 val bio = bim.io.resp 631 XSDebug("debug: bim takens:%b\n", VecInit(bio.ctrs.map(_(1))).asUInt) 632 val bo = btb.io.resp 633 XSDebug("debug: btb hits:%b\n", bo.hits.asUInt) 634 } 635 } 636 637 638 639 if (EnableCFICommitLog) { 640 val buValid = io.commit.valid 641 val buinfo = io.commit.bits 642 for (i <- 0 until PredictWidth) { 643 val cfi_idx = buinfo.cfiIndex 644 val isTaken = cfi_idx.valid && cfi_idx.bits === i.U 645 val isCfi = buinfo.valids(i) && (buinfo.br_mask(i) || cfi_idx.valid && cfi_idx.bits === i.U) 646 val isBr = buinfo.br_mask(i) 647 val pc = packetAligned(buinfo.ftqPC) + (i * instBytes).U - Mux((i==0).B && buinfo.hasLastPrev, 2.U, 0.U) 648 val tage_cycle = buinfo.metas(i).debug_tage_cycle 649 XSDebug(buValid && isCfi, p"cfi_update: isBr(${isBr}) pc(${Hexadecimal(pc)}) taken(${isTaken}) mispred(${buinfo.mispred(i)}) cycle($tage_cycle) hist(${Hexadecimal(buinfo.predHist.asUInt)})\n") 650 } 651 } 652 653} 654 655object BPU{ 656 def apply(enableBPU: Boolean = true)(implicit p: Parameters) = { 657 if(enableBPU) { 658 val BPU = Module(new BPU) 659 BPU 660 } 661 else { 662 val FakeBPU = Module(new FakeBPU) 663 FakeBPU 664 } 665 } 666} 667