1package xiangshan.frontend 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.utils._ 7import xiangshan.backend.ALUOpType 8import xiangshan.backend.BRUOpType 9import utils._ 10import chisel3.util.experimental.BoringUtils 11import xiangshan.backend.decode.XSTrap 12 13class TableAddr(val idxBits: Int, val banks: Int) extends XSBundle { 14 def tagBits = VAddrBits - idxBits - 1 15 16 val tag = UInt(tagBits.W) 17 val idx = UInt(idxBits.W) 18 val offset = UInt(1.W) 19 20 def fromUInt(x: UInt) = x.asTypeOf(UInt(VAddrBits.W)).asTypeOf(this) 21 def getTag(x: UInt) = fromUInt(x).tag 22 def getIdx(x: UInt) = fromUInt(x).idx 23 def getBank(x: UInt) = getIdx(x)(log2Up(banks) - 1, 0) 24 def getBankIdx(x: UInt) = getIdx(x)(idxBits - 1, log2Up(banks)) 25} 26 27class Stage1To2IO extends XSBundle { 28 val pc = Output(UInt(VAddrBits.W)) 29 val btb = new Bundle { 30 val hits = Output(UInt(FetchWidth.W)) 31 val targets = Output(Vec(FetchWidth, UInt(VAddrBits.W))) 32 } 33 val jbtac = new Bundle { 34 val hitIdx = Output(UInt(FetchWidth.W)) 35 val target = Output(UInt(VAddrBits.W)) 36 } 37 val tage = new Bundle { 38 val hits = Output(UInt(FetchWidth.W)) 39 val takens = Output(Vec(FetchWidth, Bool())) 40 } 41 val hist = Output(Vec(FetchWidth, UInt(HistoryLength.W))) 42 val btbPred = ValidIO(new BranchPrediction) 43} 44 45class BPUStage1 extends XSModule { 46 val io = IO(new Bundle() { 47 val in = new Bundle { val pc = Flipped(Decoupled(UInt(VAddrBits.W))) } 48 // from backend 49 val redirectInfo = Input(new RedirectInfo) 50 // from Stage3 51 val flush = Input(Bool()) 52 val s3RollBackHist = Input(UInt(HistoryLength.W)) 53 val s3Taken = Input(Bool()) 54 // to ifu, quick prediction result 55 val s1OutPred = ValidIO(new BranchPrediction) 56 // to Stage2 57 val out = Decoupled(new Stage1To2IO) 58 }) 59 60 io.in.pc.ready := true.B 61 62 // flush Stage1 when io.flush 63 val flushS1 = BoolStopWatch(io.flush, io.in.pc.fire(), startHighPriority = true) 64 65 // global history register 66 val ghr = RegInit(0.U(HistoryLength.W)) 67 // modify updateGhr and newGhr when updating ghr 68 val updateGhr = WireInit(false.B) 69 val newGhr = WireInit(0.U(HistoryLength.W)) 70 when (updateGhr) { ghr := newGhr } 71 // use hist as global history!!! 72 val hist = Mux(updateGhr, newGhr, ghr) 73 74 // Tage predictor 75 val tage = Module(new FakeTAGE) 76 // val tage = if(EnableBPD) Module(new Tage) else Module(new FakeTAGE) 77 tage.io.req.valid := io.in.pc.fire() 78 tage.io.req.bits.pc := io.in.pc.bits 79 tage.io.req.bits.hist := hist 80 tage.io.redirectInfo <> io.redirectInfo 81 io.out.bits.tage <> tage.io.out 82 io.s1OutPred.bits.tageMeta := tage.io.meta 83 84 // latch pc for 1 cycle latency when reading SRAM 85 val pcLatch = RegEnable(io.in.pc.bits, io.in.pc.fire()) 86 87 val r = io.redirectInfo.redirect 88 val updateFetchpc = r.pc - (r.fetchIdx << 2.U) 89 // BTB 90 val btb = Module(new BTB) 91 btb.io.in.pc <> io.in.pc 92 btb.io.in.pcLatch := pcLatch 93 // TODO: pass real mask in 94 btb.io.in.mask := "b1111111111111111".asUInt 95 btb.io.redirectValid := io.redirectInfo.valid 96 btb.io.flush := io.flush 97 98 // btb.io.update.fetchPC := updateFetchpc 99 // btb.io.update.fetchIdx := r.fetchIdx 100 btb.io.update.pc := r.pc 101 btb.io.update.hit := r.btbHitWay 102 btb.io.update.misPred := io.redirectInfo.misPred 103 // btb.io.update.writeWay := r.btbVictimWay 104 btb.io.update.oldCtr := r.btbPredCtr 105 btb.io.update.taken := r.taken 106 btb.io.update.target := r.brTarget 107 btb.io.update._type := r._type 108 // TODO: add RVC logic 109 btb.io.update.isRVC := DontCare 110 111 val btbHit = btb.io.out.hit 112 val btbTaken = btb.io.out.taken 113 val btbTakenIdx = btb.io.out.takenIdx 114 val btbTakenTarget = btb.io.out.target 115 // val btbWriteWay = btb.io.out.writeWay 116 val btbNotTakens = btb.io.out.notTakens 117 val btbCtrs = VecInit(btb.io.out.dEntries.map(_.pred)) 118 val btbValids = btb.io.out.hits 119 val btbTargets = VecInit(btb.io.out.dEntries.map(_.target)) 120 val btbTypes = VecInit(btb.io.out.dEntries.map(_._type)) 121 122 123 val jbtac = Module(new JBTAC) 124 jbtac.io.in.pc <> io.in.pc 125 jbtac.io.in.pcLatch := pcLatch 126 jbtac.io.in.hist := hist 127 jbtac.io.redirectValid := io.redirectInfo.valid 128 jbtac.io.flush := io.flush 129 130 jbtac.io.update.fetchPC := updateFetchpc 131 jbtac.io.update.fetchIdx := r.fetchIdx << 1 132 jbtac.io.update.misPred := io.redirectInfo.misPred 133 jbtac.io.update._type := r._type 134 jbtac.io.update.target := r.target 135 jbtac.io.update.hist := r.hist 136 137 val jbtacHit = jbtac.io.out.hit 138 val jbtacTarget = jbtac.io.out.target 139 val jbtacHitIdx = jbtac.io.out.hitIdx 140 141 // calculate global history of each instr 142 val firstHist = RegNext(hist) 143 val histShift = Wire(Vec(FetchWidth, UInt(log2Up(FetchWidth).W))) 144 val shift = Wire(Vec(FetchWidth, Vec(FetchWidth, UInt(1.W)))) 145 (0 until FetchWidth).map(i => shift(i) := Mux(!btbNotTakens(i), 0.U, ~LowerMask(UIntToOH(i.U), FetchWidth)).asTypeOf(Vec(FetchWidth, UInt(1.W)))) 146 for (j <- 0 until FetchWidth) { 147 var tmp = 0.U 148 for (i <- 0 until FetchWidth) { 149 tmp = tmp + shift(i)(j) 150 } 151 histShift(j) := tmp 152 } 153 (0 until FetchWidth).map(i => io.s1OutPred.bits.hist(i) := firstHist << histShift(i)) 154 155 // update ghr 156 updateGhr := io.s1OutPred.bits.redirect || io.flush 157 val brJumpIdx = Mux(!(btbHit && btbTaken), 0.U, UIntToOH(btbTakenIdx)) 158 val indirectIdx = Mux(!jbtacHit, 0.U, UIntToOH(jbtacHitIdx)) 159 //val newTaken = Mux(io.redirectInfo.flush(), !(r._type === BTBtype.B && !r.taken), ) 160 newGhr := Mux(io.redirectInfo.flush(), (r.hist << 1.U) | !(r._type === BTBtype.B && !r.taken), 161 Mux(io.flush, Mux(io.s3Taken, (io.s3RollBackHist << 1.U) | 1.U, io.s3RollBackHist), 162 Mux(io.s1OutPred.bits.redirect, (PriorityMux(brJumpIdx | indirectIdx, io.s1OutPred.bits.hist) << 1.U | 1.U), 163 io.s1OutPred.bits.hist(0) << PopCount(btbNotTakens)))) 164 165 // redirect based on BTB and JBTAC 166 // io.out.valid := RegNext(io.in.pc.fire()) && !flushS1u 167 io.out.valid := RegNext(io.in.pc.fire()) && !io.flush 168 169 io.s1OutPred.valid := io.out.valid 170 io.s1OutPred.bits.redirect := btbHit && btbTaken || jbtacHit 171 // io.s1OutPred.bits.instrValid := LowerMask(UIntToOH(btbTakenIdx), FetchWidth) & LowerMask(UIntToOH(jbtacHitIdx), FetchWidth) 172 io.s1OutPred.bits.instrValid := Mux(io.s1OutPred.bits.redirect, LowerMask(LowestBit(brJumpIdx | indirectIdx, FetchWidth), FetchWidth), Fill(FetchWidth, 1.U(1.W))).asTypeOf(Vec(FetchWidth, Bool())) 173 io.s1OutPred.bits.target := Mux(brJumpIdx === LowestBit(brJumpIdx | indirectIdx, FetchWidth), btbTakenTarget, jbtacTarget) 174 // io.s1OutPred.bits.btbVictimWay := btbWriteWay 175 io.s1OutPred.bits.predCtr := btbCtrs 176 io.s1OutPred.bits.btbHitWay := btbHit 177 io.s1OutPred.bits.rasSp := DontCare 178 io.s1OutPred.bits.rasTopCtr := DontCare 179 180 io.out.bits.pc := pcLatch 181 io.out.bits.btb.hits := btbValids.asUInt 182 (0 until FetchWidth).map(i => io.out.bits.btb.targets(i) := btbTargets(i)) 183 io.out.bits.jbtac.hitIdx := UIntToOH(jbtacHitIdx) 184 io.out.bits.jbtac.target := jbtacTarget 185 // TODO: we don't need this repeatedly! 186 io.out.bits.hist := io.s1OutPred.bits.hist 187 io.out.bits.btbPred := io.s1OutPred 188 189 190 191 // debug info 192 XSDebug(true.B, "[BPUS1]in:(%d %d) pc=%x ghr=%b\n", io.in.pc.valid, io.in.pc.ready, io.in.pc.bits, hist) 193 XSDebug(true.B, "[BPUS1]outPred:(%d) pc=0x%x, redirect=%d instrValid=%b tgt=%x\n", 194 io.s1OutPred.valid, pcLatch, io.s1OutPred.bits.redirect, io.s1OutPred.bits.instrValid.asUInt, io.s1OutPred.bits.target) 195 XSDebug(io.flush && io.redirectInfo.flush(), 196 "[BPUS1]flush from backend: pc=%x tgt=%x brTgt=%x _type=%b taken=%d oldHist=%b fetchIdx=%d isExcpt=%d\n", 197 r.pc, r.target, r.brTarget, r._type, r.taken, r.hist, r.fetchIdx, r.isException) 198 XSDebug(io.flush && !io.redirectInfo.flush(), 199 "[BPUS1]flush from Stage3: s3Taken=%d s3RollBackHist=%b\n", io.s3Taken, io.s3RollBackHist) 200 201} 202 203class Stage2To3IO extends Stage1To2IO { 204} 205 206class BPUStage2 extends XSModule { 207 val io = IO(new Bundle() { 208 // flush from Stage3 209 val flush = Input(Bool()) 210 val in = Flipped(Decoupled(new Stage1To2IO)) 211 val out = Decoupled(new Stage2To3IO) 212 }) 213 214 // flush Stage2 when Stage3 or banckend redirects 215 val flushS2 = BoolStopWatch(io.flush, io.in.fire(), startHighPriority = true) 216 val inLatch = RegInit(0.U.asTypeOf(io.in.bits)) 217 when (io.in.fire()) { inLatch := io.in.bits } 218 val validLatch = RegInit(false.B) 219 when (io.flush) { 220 validLatch := false.B 221 }.elsewhen (io.in.fire()) { 222 validLatch := true.B 223 }.elsewhen (io.out.fire()) { 224 validLatch := false.B 225 } 226 227 io.out.valid := !io.flush && !flushS2 && validLatch 228 io.in.ready := !validLatch || io.out.fire() 229 230 // do nothing 231 io.out.bits := inLatch 232 233 // debug info 234 XSDebug(true.B, "[BPUS2]in:(%d %d) pc=%x out:(%d %d) pc=%x\n", 235 io.in.valid, io.in.ready, io.in.bits.pc, io.out.valid, io.out.ready, io.out.bits.pc) 236 XSDebug(true.B, "[BPUS2]validLatch=%d pc=%x\n", validLatch, inLatch.pc) 237 XSDebug(io.flush, "[BPUS2]flush!!!\n") 238} 239 240class BPUStage3 extends XSModule { 241 val io = IO(new Bundle() { 242 val flush = Input(Bool()) 243 val in = Flipped(Decoupled(new Stage2To3IO)) 244 val out = ValidIO(new BranchPrediction) 245 // from icache 246 val predecode = Flipped(ValidIO(new Predecode)) 247 // from backend 248 val redirectInfo = Input(new RedirectInfo) 249 // to Stage1 and Stage2 250 val flushBPU = Output(Bool()) 251 // to Stage1, restore ghr in stage1 when flushBPU is valid 252 val s1RollBackHist = Output(UInt(HistoryLength.W)) 253 val s3Taken = Output(Bool()) 254 }) 255 256 val flushS3 = BoolStopWatch(io.flush, io.in.fire(), startHighPriority = true) 257 val inLatch = RegInit(0.U.asTypeOf(io.in.bits)) 258 val validLatch = RegInit(false.B) 259 when (io.in.fire()) { inLatch := io.in.bits } 260 when (io.flush) { 261 validLatch := false.B 262 }.elsewhen (io.in.fire()) { 263 validLatch := true.B 264 }.elsewhen (io.out.valid) { 265 validLatch := false.B 266 } 267 io.out.valid := validLatch && io.predecode.valid && !flushS3 && !io.flush 268 io.in.ready := !validLatch || io.out.valid 269 270 // RAS 271 // TODO: split retAddr and ctr 272 def rasEntry() = new Bundle { 273 val retAddr = UInt(VAddrBits.W) 274 val ctr = UInt(8.W) // layer of nested call functions 275 } 276 val ras = RegInit(VecInit(Seq.fill(RasSize)(0.U.asTypeOf(rasEntry())))) 277 val sp = Counter(RasSize) 278 val rasTop = ras(sp.value) 279 val rasTopAddr = rasTop.retAddr 280 281 // get the first taken branch/jal/call/jalr/ret in a fetch line 282 // brTakenIdx/jalIdx/callIdx/jalrIdx/retIdx/jmpIdx is one-hot encoded. 283 // brNotTakenIdx indicates all the not-taken branches before the first jump instruction. 284 val brIdx = inLatch.btb.hits & Reverse(Cat(io.predecode.bits.fuOpTypes.map { t => ALUOpType.isBranch(t) }).asUInt) & io.predecode.bits.mask 285 val brTakenIdx = LowestBit(brIdx & inLatch.tage.takens.asUInt, FetchWidth) 286 val jalIdx = LowestBit(inLatch.btb.hits & Reverse(Cat(io.predecode.bits.fuOpTypes.map { t => t === BRUOpType.jal }).asUInt) & io.predecode.bits.mask, FetchWidth) 287 val callIdx = LowestBit(inLatch.btb.hits & io.predecode.bits.mask & Reverse(Cat(io.predecode.bits.fuOpTypes.map { t => t === BRUOpType.call }).asUInt), FetchWidth) 288 val jalrIdx = LowestBit(inLatch.jbtac.hitIdx & io.predecode.bits.mask & Reverse(Cat(io.predecode.bits.fuOpTypes.map { t => t === BRUOpType.jalr }).asUInt), FetchWidth) 289 val retIdx = LowestBit(io.predecode.bits.mask & Reverse(Cat(io.predecode.bits.fuOpTypes.map { t => t === BRUOpType.ret }).asUInt), FetchWidth) 290 291 val jmpIdx = LowestBit(brTakenIdx | jalIdx | callIdx | jalrIdx | retIdx, FetchWidth) 292 val brNotTakenIdx = brIdx & ~inLatch.tage.takens.asUInt & LowerMask(jmpIdx, FetchWidth) & io.predecode.bits.mask 293 294 io.out.bits.redirect := jmpIdx.orR.asBool 295 io.out.bits.target := Mux(jmpIdx === retIdx, rasTopAddr, 296 Mux(jmpIdx === jalrIdx, inLatch.jbtac.target, 297 Mux(jmpIdx === 0.U, inLatch.pc + 32.U, // TODO: RVC 298 PriorityMux(jmpIdx, inLatch.btb.targets)))) 299 io.out.bits.instrValid := Mux(jmpIdx.orR, LowerMask(jmpIdx, FetchWidth), Fill(FetchWidth, 1.U(1.W))).asTypeOf(Vec(FetchWidth, Bool())) 300 // io.out.bits.btbVictimWay := inLatch.btbPred.bits.btbVictimWay 301 io.out.bits.predCtr := inLatch.btbPred.bits.predCtr 302 io.out.bits.btbHitWay := inLatch.btbPred.bits.btbHitWay 303 io.out.bits.tageMeta := inLatch.btbPred.bits.tageMeta 304 //io.out.bits._type := Mux(jmpIdx === retIdx, BTBtype.R, 305 // Mux(jmpIdx === jalrIdx, BTBtype.I, 306 // Mux(jmpIdx === brTakenIdx, BTBtype.B, BTBtype.J))) 307 val firstHist = inLatch.btbPred.bits.hist(0) 308 // there may be several notTaken branches before the first jump instruction, 309 // so we need to calculate how many zeroes should each instruction shift in its global history. 310 // each history is exclusive of instruction's own jump direction. 311 val histShift = Wire(Vec(FetchWidth, UInt(log2Up(FetchWidth).W))) 312 val shift = Wire(Vec(FetchWidth, Vec(FetchWidth, UInt(1.W)))) 313 (0 until FetchWidth).map(i => shift(i) := Mux(!brNotTakenIdx(i), 0.U, ~LowerMask(UIntToOH(i.U), FetchWidth)).asTypeOf(Vec(FetchWidth, UInt(1.W)))) 314 for (j <- 0 until FetchWidth) { 315 var tmp = 0.U 316 for (i <- 0 until FetchWidth) { 317 tmp = tmp + shift(i)(j) 318 } 319 histShift(j) := tmp 320 } 321 (0 until FetchWidth).map(i => io.out.bits.hist(i) := firstHist << histShift(i)) 322 // save ras checkpoint info 323 io.out.bits.rasSp := sp.value 324 io.out.bits.rasTopCtr := rasTop.ctr 325 326 // flush BPU and redirect when target differs from the target predicted in Stage1 327 io.out.bits.redirect := (if(EnableBPD) (inLatch.btbPred.bits.redirect ^ jmpIdx.orR.asBool || 328 inLatch.btbPred.bits.redirect && jmpIdx.orR.asBool && io.out.bits.target =/= inLatch.btbPred.bits.target) 329 else false.B) 330 io.flushBPU := io.out.bits.redirect && io.out.valid 331 332 // speculative update RAS 333 val rasWrite = WireInit(0.U.asTypeOf(rasEntry())) 334 rasWrite.retAddr := inLatch.pc + (OHToUInt(callIdx) << 2.U) + 4.U 335 val allocNewEntry = rasWrite.retAddr =/= rasTopAddr 336 rasWrite.ctr := Mux(allocNewEntry, 1.U, rasTop.ctr + 1.U) 337 when (io.out.valid) { 338 when (jmpIdx === callIdx) { 339 ras(Mux(allocNewEntry, sp.value + 1.U, sp.value)) := rasWrite 340 when (allocNewEntry) { sp.value := sp.value + 1.U } 341 }.elsewhen (jmpIdx === retIdx) { 342 when (rasTop.ctr === 1.U) { 343 sp.value := Mux(sp.value === 0.U, 0.U, sp.value - 1.U) 344 }.otherwise { 345 ras(sp.value) := Cat(rasTop.ctr - 1.U, rasTopAddr).asTypeOf(rasEntry()) 346 } 347 } 348 } 349 // use checkpoint to recover RAS 350 val recoverSp = io.redirectInfo.redirect.rasSp 351 val recoverCtr = io.redirectInfo.redirect.rasTopCtr 352 when (io.redirectInfo.valid && io.redirectInfo.misPred) { 353 sp.value := recoverSp 354 ras(recoverSp) := Cat(recoverCtr, ras(recoverSp).retAddr).asTypeOf(rasEntry()) 355 } 356 357 // roll back global history in S1 if S3 redirects 358 io.s1RollBackHist := Mux(io.s3Taken, PriorityMux(jmpIdx, io.out.bits.hist), io.out.bits.hist(0) << PopCount(brIdx & ~inLatch.tage.takens.asUInt)) 359 // whether Stage3 has a taken jump 360 io.s3Taken := jmpIdx.orR.asBool 361 362 // debug info 363 XSDebug(io.in.fire(), "[BPUS3]in:(%d %d) pc=%x\n", io.in.valid, io.in.ready, io.in.bits.pc) 364 XSDebug(io.out.valid, "[BPUS3]out:%d pc=%x redirect=%d predcdMask=%b instrValid=%b tgt=%x\n", 365 io.out.valid, inLatch.pc, io.out.bits.redirect, io.predecode.bits.mask, io.out.bits.instrValid.asUInt, io.out.bits.target) 366 XSDebug(true.B, "[BPUS3]flushS3=%d\n", flushS3) 367 XSDebug(true.B, "[BPUS3]validLatch=%d predecode.valid=%d\n", validLatch, io.predecode.valid) 368 XSDebug(true.B, "[BPUS3]brIdx=%b brTakenIdx=%b brNTakenIdx=%b jalIdx=%b jalrIdx=%b callIdx=%b retIdx=%b\n", 369 brIdx, brTakenIdx, brNotTakenIdx, jalIdx, jalrIdx, callIdx, retIdx) 370 371 // BPU's TEMP Perf Cnt 372 BoringUtils.addSource(io.out.valid, "MbpS3Cnt") 373 BoringUtils.addSource(io.out.valid && io.out.bits.redirect, "MbpS3TageRed") 374 BoringUtils.addSource(io.out.valid && (inLatch.btbPred.bits.redirect ^ jmpIdx.orR.asBool), "MbpS3TageRedDir") 375 BoringUtils.addSource(io.out.valid && (inLatch.btbPred.bits.redirect 376 && jmpIdx.orR.asBool && (io.out.bits.target =/= inLatch.btbPred.bits.target)), "MbpS3TageRedTar") 377} 378 379class BPU extends XSModule { 380 val io = IO(new Bundle() { 381 // from backend 382 // flush pipeline if misPred and update bpu based on redirect signals from brq 383 val redirectInfo = Input(new RedirectInfo) 384 385 val in = new Bundle { val pc = Flipped(Valid(UInt(VAddrBits.W))) } 386 387 val btbOut = ValidIO(new BranchPrediction) 388 val tageOut = ValidIO(new BranchPrediction) 389 390 // predecode info from icache 391 // TODO: simplify this after implement predecode unit 392 val predecode = Flipped(ValidIO(new Predecode)) 393 }) 394 395 val s1 = Module(new BPUStage1) 396 val s2 = Module(new BPUStage2) 397 val s3 = Module(new BPUStage3) 398 399 s1.io.redirectInfo <> io.redirectInfo 400 s1.io.flush := s3.io.flushBPU || io.redirectInfo.flush() 401 s1.io.in.pc.valid := io.in.pc.valid 402 s1.io.in.pc.bits <> io.in.pc.bits 403 io.btbOut <> s1.io.s1OutPred 404 s1.io.s3RollBackHist := s3.io.s1RollBackHist 405 s1.io.s3Taken := s3.io.s3Taken 406 407 s1.io.out <> s2.io.in 408 s2.io.flush := s3.io.flushBPU || io.redirectInfo.flush() 409 410 s2.io.out <> s3.io.in 411 s3.io.flush := io.redirectInfo.flush() 412 s3.io.predecode <> io.predecode 413 io.tageOut <> s3.io.out 414 s3.io.redirectInfo <> io.redirectInfo 415 416 // TODO: temp and ugly code, when perf counters is added( may after adding CSR), please mv the below counter 417 val bpuPerfCntList = List( 418 ("MbpInstr"," "), 419 ("MbpRight"," "), 420 ("MbpWrong"," "), 421 ("MbpBRight"," "), 422 ("MbpBWrong"," "), 423 ("MbpJRight"," "), 424 ("MbpJWrong"," "), 425 ("MbpIRight"," "), 426 ("MbpIWrong"," "), 427 ("MbpRRight"," "), 428 ("MbpRWrong"," "), 429 ("MbpS3Cnt"," "), 430 ("MbpS3TageRed"," "), 431 ("MbpS3TageRedDir"," "), 432 ("MbpS3TageRedTar"," ") 433 ) 434 435 val bpuPerfCnts = List.fill(bpuPerfCntList.length)(RegInit(0.U(XLEN.W))) 436 val bpuPerfCntConds = List.fill(bpuPerfCntList.length)(WireInit(false.B)) 437 (bpuPerfCnts zip bpuPerfCntConds) map { case (cnt, cond) => { when (cond) { cnt := cnt + 1.U }}} 438 439 for(i <- bpuPerfCntList.indices) { 440 BoringUtils.addSink(bpuPerfCntConds(i), bpuPerfCntList(i)._1) 441 } 442 443 val xsTrap = WireInit(false.B) 444 BoringUtils.addSink(xsTrap, "XSTRAP_BPU") 445 446 // if (!p.FPGAPlatform) { 447 when (xsTrap) { 448 printf("=================BPU's PerfCnt================\n") 449 for(i <- bpuPerfCntList.indices) { 450 printf(bpuPerfCntList(i)._1 + bpuPerfCntList(i)._2 + " <- " + "%d\n", bpuPerfCnts(i)) 451 } 452 } 453 // } 454}