1*09c6f1ddSLingrui98/*************************************************************************************** 2*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*09c6f1ddSLingrui98* 5*09c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2. 6*09c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*09c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at: 8*09c6f1ddSLingrui98* http://license.coscl.org.cn/MulanPSL2 9*09c6f1ddSLingrui98* 10*09c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*09c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*09c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*09c6f1ddSLingrui98* 14*09c6f1ddSLingrui98* See the Mulan PSL v2 for more details. 15*09c6f1ddSLingrui98***************************************************************************************/ 16*09c6f1ddSLingrui98 17*09c6f1ddSLingrui98package xiangshan.frontend 18*09c6f1ddSLingrui98 19*09c6f1ddSLingrui98import chipsalliance.rocketchip.config.Parameters 20*09c6f1ddSLingrui98import chisel3._ 21*09c6f1ddSLingrui98import chisel3.util._ 22*09c6f1ddSLingrui98import xiangshan._ 23*09c6f1ddSLingrui98import utils._ 24*09c6f1ddSLingrui98import chisel3.experimental.chiselName 25*09c6f1ddSLingrui98 26*09c6f1ddSLingrui98trait BimParams extends HasXSParameter { 27*09c6f1ddSLingrui98 val bimSize = 2048 28*09c6f1ddSLingrui98 val bypassEntries = 4 29*09c6f1ddSLingrui98} 30*09c6f1ddSLingrui98 31*09c6f1ddSLingrui98@chiselName 32*09c6f1ddSLingrui98class BIM(implicit p: Parameters) extends BasePredictor with BimParams with BPUUtils { 33*09c6f1ddSLingrui98 val bimAddr = new TableAddr(log2Up(bimSize), 1) 34*09c6f1ddSLingrui98 35*09c6f1ddSLingrui98 val bim = Module(new SRAMTemplate(UInt(2.W), set = bimSize, way=numBr, shouldReset = false, holdRead = true)) 36*09c6f1ddSLingrui98 37*09c6f1ddSLingrui98 val doing_reset = RegInit(true.B) 38*09c6f1ddSLingrui98 val resetRow = RegInit(0.U(log2Ceil(bimSize).W)) 39*09c6f1ddSLingrui98 resetRow := resetRow + doing_reset 40*09c6f1ddSLingrui98 when (resetRow === (bimSize-1).U) { doing_reset := false.B } 41*09c6f1ddSLingrui98 42*09c6f1ddSLingrui98 val s0_idx = bimAddr.getIdx(s0_pc) 43*09c6f1ddSLingrui98 44*09c6f1ddSLingrui98 bim.io.r.req.valid := io.s0_fire 45*09c6f1ddSLingrui98 bim.io.r.req.bits.setIdx := s0_idx 46*09c6f1ddSLingrui98 47*09c6f1ddSLingrui98 io.in.ready := bim.io.r.req.ready 48*09c6f1ddSLingrui98 io.s1_ready := bim.io.r.req.ready 49*09c6f1ddSLingrui98 50*09c6f1ddSLingrui98 val s1_read = bim.io.r.resp.data 51*09c6f1ddSLingrui98 52*09c6f1ddSLingrui98 io.out.resp := io.in.bits.resp_in(0) 53*09c6f1ddSLingrui98 54*09c6f1ddSLingrui98 val s1_latch_taken_mask = VecInit(Cat((0 until numBr reverse).map(i => s1_read(i)(1))).asBools()) 55*09c6f1ddSLingrui98 val s1_latch_meta = s1_read.asUInt() 56*09c6f1ddSLingrui98 override val meta_size = s1_latch_meta.getWidth 57*09c6f1ddSLingrui98 58*09c6f1ddSLingrui98 io.out.resp.s1.preds.taken_mask := s1_latch_taken_mask 59*09c6f1ddSLingrui98 io.out.resp.s2.preds.taken_mask := RegEnable(s1_latch_taken_mask, 0.U.asTypeOf(Vec(numBr, Bool())), io.s1_fire) 60*09c6f1ddSLingrui98 61*09c6f1ddSLingrui98 io.out.resp.s3.preds.taken_mask := RegEnable(RegEnable(s1_latch_taken_mask, io.s1_fire), io.s2_fire) 62*09c6f1ddSLingrui98 io.out.s3_meta := RegEnable(RegEnable(s1_latch_meta, io.s1_fire), io.s2_fire) 63*09c6f1ddSLingrui98 64*09c6f1ddSLingrui98 // Update logic 65*09c6f1ddSLingrui98 val u_valid = RegNext(io.update.valid) 66*09c6f1ddSLingrui98 val update = RegNext(io.update.bits) 67*09c6f1ddSLingrui98 68*09c6f1ddSLingrui98 val u_idx = bimAddr.getIdx(update.pc) 69*09c6f1ddSLingrui98 70*09c6f1ddSLingrui98 // Bypass logic 71*09c6f1ddSLingrui98 val wrbypass_ctrs = RegInit(0.U.asTypeOf(Vec(bypassEntries, Vec(numBr, UInt(2.W))))) 72*09c6f1ddSLingrui98 val wrbypass_ctr_valids = RegInit(0.U.asTypeOf(Vec(bypassEntries, Vec(numBr, Bool())))) 73*09c6f1ddSLingrui98 val wrbypass_idx = RegInit(0.U.asTypeOf(Vec(bypassEntries, UInt(log2Up(bimSize).W)))) 74*09c6f1ddSLingrui98 val wrbypass_enq_ptr = RegInit(0.U(log2Up(bypassEntries).W)) 75*09c6f1ddSLingrui98 76*09c6f1ddSLingrui98 val wrbypass_hits = VecInit((0 until bypassEntries).map(i => 77*09c6f1ddSLingrui98 !doing_reset && wrbypass_idx(i) === u_idx)) 78*09c6f1ddSLingrui98 val wrbypass_hit = wrbypass_hits.reduce(_||_) 79*09c6f1ddSLingrui98 val wrbypass_hit_idx = PriorityEncoder(wrbypass_hits) 80*09c6f1ddSLingrui98 81*09c6f1ddSLingrui98 val oldCtrs = VecInit((0 until numBr).map(i => 82*09c6f1ddSLingrui98 Mux(wrbypass_hit && wrbypass_ctr_valids(wrbypass_hit_idx)(i), 83*09c6f1ddSLingrui98 wrbypass_ctrs(wrbypass_hit_idx)(i), update.meta(2*i+1, 2*i)))) 84*09c6f1ddSLingrui98 85*09c6f1ddSLingrui98 val newTakens = update.preds.taken_mask 86*09c6f1ddSLingrui98 val newCtrs = VecInit((0 until numBr).map(i => 87*09c6f1ddSLingrui98 satUpdate(oldCtrs(i), 2, newTakens(i)) 88*09c6f1ddSLingrui98 )) 89*09c6f1ddSLingrui98 90*09c6f1ddSLingrui98 val update_mask = LowerMask(PriorityEncoderOH(update.preds.taken_mask.asUInt)) 91*09c6f1ddSLingrui98 val need_to_update = VecInit((0 until numBr).map(i => u_valid && update.ftb_entry.brValids(i) && update_mask(i))) 92*09c6f1ddSLingrui98 93*09c6f1ddSLingrui98 when (reset.asBool) { wrbypass_ctr_valids.foreach(_ := VecInit(Seq.fill(numBr)(false.B)))} 94*09c6f1ddSLingrui98 95*09c6f1ddSLingrui98 for (i <- 0 until numBr) { 96*09c6f1ddSLingrui98 when(need_to_update.reduce(_||_)) { 97*09c6f1ddSLingrui98 when(wrbypass_hit) { 98*09c6f1ddSLingrui98 when(need_to_update(i)) { 99*09c6f1ddSLingrui98 wrbypass_ctrs(wrbypass_hit_idx)(i) := newCtrs(i) 100*09c6f1ddSLingrui98 wrbypass_ctr_valids(wrbypass_hit_idx)(i) := true.B 101*09c6f1ddSLingrui98 } 102*09c6f1ddSLingrui98 }.otherwise { 103*09c6f1ddSLingrui98 wrbypass_ctr_valids(wrbypass_enq_ptr)(i) := false.B 104*09c6f1ddSLingrui98 when(need_to_update(i)) { 105*09c6f1ddSLingrui98 wrbypass_ctrs(wrbypass_enq_ptr)(i) := newCtrs(i) 106*09c6f1ddSLingrui98 wrbypass_ctr_valids(wrbypass_enq_ptr)(i) := true.B 107*09c6f1ddSLingrui98 } 108*09c6f1ddSLingrui98 } 109*09c6f1ddSLingrui98 } 110*09c6f1ddSLingrui98 } 111*09c6f1ddSLingrui98 112*09c6f1ddSLingrui98 when (need_to_update.reduce(_||_) && !wrbypass_hit) { 113*09c6f1ddSLingrui98 wrbypass_idx(wrbypass_enq_ptr) := u_idx 114*09c6f1ddSLingrui98 wrbypass_enq_ptr := (wrbypass_enq_ptr + 1.U)(log2Up(bypassEntries)-1, 0) 115*09c6f1ddSLingrui98 } 116*09c6f1ddSLingrui98 117*09c6f1ddSLingrui98 bim.io.w.apply( 118*09c6f1ddSLingrui98 valid = need_to_update.asUInt.orR || doing_reset, 119*09c6f1ddSLingrui98 data = Mux(doing_reset, VecInit(Seq.fill(numBr)(2.U(2.W))), newCtrs), 120*09c6f1ddSLingrui98 setIdx = Mux(doing_reset, resetRow, u_idx), 121*09c6f1ddSLingrui98 waymask = Mux(doing_reset, Fill(numBr, 1.U(1.W)).asUInt(), need_to_update.asUInt()) 122*09c6f1ddSLingrui98 ) 123*09c6f1ddSLingrui98 124*09c6f1ddSLingrui98 val latch_s0_fire = RegNext(io.s0_fire) 125*09c6f1ddSLingrui98 126*09c6f1ddSLingrui98 XSDebug(doing_reset, "Doing reset...\n") 127*09c6f1ddSLingrui98 128*09c6f1ddSLingrui98 XSDebug(io.s0_fire, "req_pc=%x, req_idx=%d\n", s0_pc, s0_idx) 129*09c6f1ddSLingrui98 130*09c6f1ddSLingrui98 for(i <- 0 until numBr) { 131*09c6f1ddSLingrui98 XSDebug(latch_s0_fire, "last_cycle req %d: ctr=%b\n", i.U, s1_read(i)) 132*09c6f1ddSLingrui98 } 133*09c6f1ddSLingrui98 134*09c6f1ddSLingrui98 XSDebug(u_valid, "update_pc=%x, update_idx=%d, is_br=%b\n", update.pc, u_idx, update.ftb_entry.brValids.asUInt) 135*09c6f1ddSLingrui98 136*09c6f1ddSLingrui98 XSDebug(u_valid, "newTakens=%b\n", newTakens.asUInt) 137*09c6f1ddSLingrui98 138*09c6f1ddSLingrui98 for(i <- 0 until numBr) { 139*09c6f1ddSLingrui98 XSDebug(u_valid, "oldCtrs%d=%b\n", i.U, oldCtrs(i)) 140*09c6f1ddSLingrui98 } 141*09c6f1ddSLingrui98 142*09c6f1ddSLingrui98 for(i <- 0 until numBr) { 143*09c6f1ddSLingrui98 XSDebug(u_valid, "newCtrs%d=%b\n", i.U, newCtrs(i)) 144*09c6f1ddSLingrui98 } 145*09c6f1ddSLingrui98 146*09c6f1ddSLingrui98} 147