1package xiangshan.frontend 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.backend.ALUOpType 7import utils._ 8import xiangshan.backend.decode.XSTrap 9import chisel3.experimental.chiselName 10 11trait BimParams extends HasXSParameter { 12 val BimBanks = PredictWidth 13 val BimSize = 4096 14 val nRows = BimSize / BimBanks 15 val bypassEntries = 4 16} 17 18@chiselName 19class BIM extends BasePredictor with BimParams{ 20 class BIMResp extends Resp { 21 val ctrs = Vec(PredictWidth, UInt(2.W)) 22 } 23 class BIMMeta extends Meta { 24 val ctrs = Vec(PredictWidth, UInt(2.W)) 25 } 26 class BIMFromOthers extends FromOthers {} 27 28 class BIMIO extends DefaultBasePredictorIO { 29 val resp = Output(new BIMResp) 30 val meta = Output(new BIMMeta) 31 } 32 33 override val io = IO(new BIMIO) 34 35 val bimAddr = new TableAddr(log2Up(BimSize), BimBanks) 36 37 val bankAlignedPC = bankAligned(io.pc.bits) 38 val pcLatch = RegEnable(bankAlignedPC, io.pc.valid) 39 40 val bim = List.fill(BimBanks) { 41 Module(new SRAMTemplate(UInt(2.W), set = nRows, shouldReset = false, holdRead = true)) 42 } 43 44 val doing_reset = RegInit(true.B) 45 val resetRow = RegInit(0.U(log2Ceil(nRows).W)) 46 resetRow := resetRow + doing_reset 47 when (resetRow === (nRows-1).U) { doing_reset := false.B } 48 49 // this bank means cache bank 50 val startsAtOddBank = bankInGroup(bankAlignedPC)(0) 51 52 val baseBank = bimAddr.getBank(bankAlignedPC) 53 val realMask = Mux(startsAtOddBank, 54 Cat(io.inMask(bankWidth-1,0), io.inMask(PredictWidth-1, bankWidth)), 55 io.inMask) 56 57 58 // those banks whose indexes are less than baseBank are in the next row 59 val isInNextRow = VecInit((0 until BimBanks).map(i => Mux(startsAtOddBank, (i < bankWidth).B, false.B))) 60 61 val baseRow = bimAddr.getBankIdx(bankAlignedPC) 62 63 val realRow = VecInit((0 until BimBanks).map(b => Mux(isInNextRow(b), (baseRow+1.U)(log2Up(nRows)-1, 0), baseRow))) 64 65 val realRowLatch = VecInit(realRow.map(RegEnable(_, enable=io.pc.valid))) 66 67 for (b <- 0 until BimBanks) { 68 bim(b).reset := reset.asBool 69 bim(b).io.r.req.valid := realMask(b) && io.pc.valid 70 bim(b).io.r.req.bits.setIdx := realRow(b) 71 } 72 73 val bimRead = VecInit(bim.map(_.io.r.resp.data(0))) 74 75 val baseBankLatch = bimAddr.getBank(pcLatch) 76 val startsAtOddBankLatch = bankInGroup(pcLatch)(0) 77 78 for (b <- 0 until BimBanks) { 79 val realBank = (if (b < bankWidth) Mux(startsAtOddBankLatch, (b+bankWidth).U, b.U) 80 else Mux(startsAtOddBankLatch, (b-bankWidth).U, b.U)) 81 val ctr = bimRead(realBank) 82 io.resp.ctrs(b) := ctr 83 io.meta.ctrs(b) := ctr 84 } 85 86 val u = io.update.bits.ui 87 88 val updateBank = bimAddr.getBank(u.pc) 89 val updateRow = bimAddr.getBankIdx(u.pc) 90 91 92 val wrbypass_ctrs = Reg(Vec(bypassEntries, Vec(BimBanks, UInt(2.W)))) 93 val wrbypass_ctr_valids = Reg(Vec(bypassEntries, Vec(BimBanks, Bool()))) 94 val wrbypass_rows = Reg(Vec(bypassEntries, UInt(log2Up(nRows).W))) 95 val wrbypass_enq_idx = RegInit(0.U(log2Up(bypassEntries).W)) 96 97 val wrbypass_hits = VecInit((0 until bypassEntries).map( i => 98 !doing_reset && wrbypass_rows(i) === updateRow)) 99 val wrbypass_hit = wrbypass_hits.reduce(_||_) 100 val wrbypass_hit_idx = PriorityEncoder(wrbypass_hits) 101 102 val oldCtr = Mux(wrbypass_hit && wrbypass_ctr_valids(wrbypass_hit_idx)(updateBank), wrbypass_ctrs(wrbypass_hit_idx)(updateBank), u.brInfo.bimCtr) 103 val newTaken = u.taken 104 val newCtr = satUpdate(oldCtr, 2, newTaken) 105 // val oldSaturated = newCtr === oldCtr 106 107 val needToUpdate = io.update.valid && u.pd.isBr 108 109 when (reset.asBool) { wrbypass_ctr_valids.foreach(_.foreach(_ := false.B))} 110 111 when (needToUpdate) { 112 when (wrbypass_hit) { 113 wrbypass_ctrs(wrbypass_hit_idx)(updateBank) := newCtr 114 wrbypass_ctr_valids(wrbypass_enq_idx)(updateBank) := true.B 115 } .otherwise { 116 wrbypass_ctrs(wrbypass_hit_idx)(updateBank) := newCtr 117 (0 until BimBanks).foreach(b => wrbypass_ctr_valids(wrbypass_enq_idx)(b) := false.B) // reset valid bits 118 wrbypass_ctr_valids(wrbypass_enq_idx)(updateBank) := true.B 119 wrbypass_rows(wrbypass_enq_idx) := updateRow 120 wrbypass_enq_idx := (wrbypass_enq_idx + 1.U)(log2Up(bypassEntries)-1,0) 121 } 122 } 123 124 for (b <- 0 until BimBanks) { 125 bim(b).io.w.req.valid := needToUpdate && b.U === updateBank || doing_reset 126 bim(b).io.w.req.bits.setIdx := Mux(doing_reset, resetRow, updateRow) 127 bim(b).io.w.req.bits.data := Mux(doing_reset, 2.U(2.W), newCtr) 128 } 129 130 if (BPUDebug && debug) { 131 XSDebug(doing_reset, "Reseting...\n") 132 XSDebug("[update] v=%d pc=%x pnpc=%x tgt=%x brTgt=%x\n", io.update.valid, u.pc, u.pnpc, u.target, u.brTarget) 133 XSDebug("[update] taken=%d isMisPred=%d", u.taken, u.isMisPred) 134 XSDebug(false, true.B, p"brTag=${u.brTag} pd.isBr=${u.pd.isBr} brInfo.bimCtr=${Binary(u.brInfo.bimCtr)}\n") 135 XSDebug("needToUpdate=%d updateBank=%x updateRow=%x newCtr=%b oldCtr=%b\n", needToUpdate, updateBank, updateRow, newCtr, oldCtr) 136 XSDebug("[wrbypass] hit=%d hits=%b\n", wrbypass_hit, wrbypass_hits.asUInt) 137 } 138 139}