uBTB.scala 11.2 KB
Newer Older
1 2
package xiangshan.frontend

3
import chipsalliance.rocketchip.config.Parameters
4 5 6
import chisel3._
import chisel3.util._
import utils._
Fa_wang's avatar
Fa_wang 已提交
7
import xiangshan._
L
Lingrui98 已提交
8
import chisel3.experimental.chiselName
9

J
jinyue110 已提交
10 11
import scala.math.min

12 13
trait MicroBTBPatameter{
    val nWays = 16
14
    val lowerBitsSize = 20
15
    val tagSize = 20
16 17
}

L
Lingrui98 已提交
18
@chiselName
19
class MicroBTB(implicit p: Parameters) extends BasePredictor
20 21
    with MicroBTBPatameter
{
22
    // val tagSize = VAddrBits - log2Ceil(PredictWidth) - 1
23
    val untaggedBits = log2Up(PredictWidth) + instOffsetBits
J
jinyue110 已提交
24 25

    class MicroBTBResp extends Resp
26
    {
L
Lingrui98 已提交
27 28
        val targets = Vec(PredictWidth, UInt(VAddrBits.W))
        val hits = Vec(PredictWidth, Bool())
29
        val takens = Vec(PredictWidth, Bool())
30
        val brMask = Vec(PredictWidth, Bool())
31
        val is_RVC = Vec(PredictWidth, Bool())
32 33
    }

L
Lingrui98 已提交
34
    class MicroBTBBranchInfo extends Meta {}
35

J
jinyue110 已提交
36
    class MicroBTBIO extends DefaultBasePredictorIO
37 38 39 40
    {
        val out = Output(new MicroBTBResp)   //
    }

41
    override val debug = true
42
    override val io = IO(new MicroBTBIO)
43

44
    def getTag(pc: UInt) = (pc >> untaggedBits)(tagSize-1, 0)
45
    def getBank(pc: UInt) = pc(log2Ceil(PredictWidth), instOffsetBits)
J
jinyue110 已提交
46

47 48 49 50 51 52 53 54 55
    class MicroBTBMeta extends XSBundle
    {
        val is_Br = Bool()
        val is_RVC = Bool()
        val valid = Bool()
        val pred = UInt(2.W)
        val tag = UInt(tagSize.W)
    }

L
Lingrui98 已提交
56
    class MicroBTBData extends XSBundle
57
    {
58
        val lower = UInt(lowerBitsSize.W)
59 60
    }

L
Lingrui98 已提交
61
    class ReadResp extends XSBundle
62 63 64
    {
        val valid = Bool()
        val taken = Bool()
L
Lingrui98 已提交
65 66
        val target = UInt(VAddrBits.W)
        val is_RVC = Bool()
67
        val is_Br = Bool()
68
    }
J
jinyue110 已提交
69

L
Lingrui98 已提交
70 71 72 73 74
    class UBTBBank(val nWays: Int) extends XSModule with HasIFUConst {
        val io = IO(new Bundle {
            val read_pc = Flipped(Valid(UInt(VAddrBits.W)))
            val read_resp = Output(new ReadResp)
            val read_hit = Output(Bool())
L
Lingrui98 已提交
75

L
Lingrui98 已提交
76
            val update_write_meta = Flipped(Valid(new MicroBTBMeta))
L
Lingrui98 已提交
77
            val update_write_data = Flipped(Valid(new MicroBTBData))
L
Lingrui98 已提交
78 79 80 81 82 83 84 85 86 87 88 89
            val update_taken = Input(Bool())
        })

        val debug_io = IO(new Bundle {
            val read_hit = Output(Bool())
            val read_hit_way = Output(UInt(log2Ceil(nWays).W))

            val update_hit = Output(Bool())
            val update_hit_way = Output(UInt(log2Ceil(nWays).W))
            val update_write_way = Output(UInt(log2Ceil(nWays).W))
            val update_old_pred = Output(UInt(2.W))
            val update_new_pred = Output(UInt(2.W))
L
Lingrui98 已提交
90
        })
L
Lingrui98 已提交
91 92
        val meta = Module(new AsyncDataModuleTemplate(new MicroBTBMeta, nWays, nWays*2, 1))
        val data = Module(new AsyncDataModuleTemplate(new MicroBTBData, nWays,   nWays, 1))
93

L
Lingrui98 已提交
94 95
        for (w <- 0 until nWays) {
            meta.io.raddr(w) := w.U
L
Lingrui98 已提交
96
            meta.io.raddr(w+nWays) := w.U
L
Lingrui98 已提交
97
            data.io.raddr(w) := w.U
98
        }
L
Lingrui98 已提交
99 100
        
        val rmetas = meta.io.rdata.take(nWays)
L
Lingrui98 已提交
101 102 103 104
        val rdatas = data.io.rdata
        
        val packetAlignedPC = packetAligned(io.read_pc.bits)
        val read_tag = getTag(io.read_pc.bits)
L
Lingrui98 已提交
105
        
L
Lingrui98 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119
        val hits = VecInit(rmetas.map(m => m.valid && m.tag === read_tag))
        val takens = VecInit(rmetas.map(m => m.pred(1)))
        val hit_oh = hits.asUInt
        val hit_and_taken = VecInit((hits zip takens) map {case (h, t) => h && t}).asUInt.orR
        val hit_meta = ParallelMux(hits zip rmetas)
        val hit_data = ParallelMux(hits zip rdatas)
        val target = Cat(io.read_pc.bits(VAddrBits-1, lowerBitsSize+instOffsetBits), hit_data.lower, 0.U(instOffsetBits.W))
        
        val ren = io.read_pc.valid
        io.read_resp.valid := ren
        io.read_resp.is_RVC := ren && hit_meta.is_RVC
        io.read_resp.is_Br := ren && hit_meta.is_Br
        io.read_resp.taken := ren && hit_and_taken
        io.read_resp.target := target
L
Lingrui98 已提交
120
        io.read_hit := hit_oh.orR
L
Lingrui98 已提交
121

L
Lingrui98 已提交
122 123 124 125 126 127 128 129 130 131 132
        debug_io.read_hit := hit_oh.orR
        debug_io.read_hit_way := OHToUInt(hit_oh)
        
        val do_reset = RegInit(true.B)
        val reset_way = RegInit(0.U(log2Ceil(nWays).W))
        when (RegNext(reset.asBool) && !reset.asBool) {
            do_reset := true.B
            reset_way := 0.U
        }
        when (do_reset) { reset_way := reset_way + 1.U }
        when (reset_way === (nWays-1).U) { do_reset := false.B }
L
Lingrui98 已提交
133

L
Lingrui98 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
        val update_rmetas = meta.io.rdata.drop(nWays)
        val update_tag = io.update_write_meta.bits.tag
        val update_hits = VecInit(update_rmetas.map(m => m.valid && m.tag === update_tag))
        val update_hit = update_hits.asUInt.orR
        val update_hit_way = OHToUInt(update_hits.asUInt)
        val update_hit_meta = ParallelMux(update_hits zip update_rmetas)
        val update_old_pred = update_hit_meta.pred
        val update_new_pred =
            Mux(update_hit,
                satUpdate(update_old_pred, 2, io.update_taken),
                Mux(io.update_taken, 3.U, 0.U))
        val update_alloc_way = {
            val source = Cat(VecInit(update_rmetas.map(_.tag)).asUInt, update_tag)
            val l = log2Ceil(nWays)
            val nChunks = (source.getWidth + l - 1) / l
            val chunks = (0 until nChunks) map { i =>
                source(min((i+1)*l, source.getWidth)-1, i*l)
            }
            ParallelXOR(chunks)
        }
        val update_emptys = update_rmetas.map(m => !m.valid)
        val update_has_empty_way = update_emptys.reduce(_||_)
        val update_empty_way = ParallelPriorityEncoder(update_emptys)
        val update_way = Mux(update_hit, update_hit_way, Mux(update_has_empty_way, update_empty_way, update_alloc_way))
    
        meta.io.waddr(0) := Mux(do_reset, reset_way, RegNext(update_way))
        meta.io.wen(0)   := do_reset || RegNext(io.update_write_meta.valid)
        meta.io.wdata(0) := Mux(do_reset,
                                0.U.asTypeOf(new MicroBTBMeta),
                                RegNext(io.update_write_meta.bits))
        meta.io.wdata(0).pred := Mux(do_reset, 0.U(2.W), RegNext(update_new_pred))
        data.io.waddr(0) := Mux(do_reset, reset_way, RegNext(update_way))
        data.io.wen(0)   := do_reset || RegNext(io.update_write_data.valid)
        data.io.wdata(0) := Mux(do_reset,
                                0.U.asTypeOf(new MicroBTBData),
                                RegNext(io.update_write_data.bits))
        
        debug_io.update_hit := update_hit
        debug_io.update_hit_way := update_hit_way
        debug_io.update_write_way := update_way
        debug_io.update_old_pred := update_old_pred
        debug_io.update_new_pred := update_new_pred
L
Lingrui98 已提交
176 177 178 179 180 181
    }

    val ubtbBanks = Seq.fill(PredictWidth)(Module(new UBTBBank(nWays)))
    val banks = VecInit(ubtbBanks.map(_.io))
    
    val read_resps = VecInit(banks.map(b => b.read_resp))
182

L
Lingrui98 已提交
183
    for (b <- 0 until PredictWidth) {
184
        banks(b).read_pc.valid := io.inMask(b)
L
Lingrui98 已提交
185 186 187 188
        banks(b).read_pc.bits := io.pc.bits
        
        //only when hit and instruction valid and entry valid can output data
        io.out.targets(b) := read_resps(b).target
189
        io.out.hits(b)   := banks(b).read_hit && ctrl.ubtb_enable
L
Lingrui98 已提交
190 191 192
        io.out.takens(b) := read_resps(b).taken
        io.out.is_RVC(b) := read_resps(b).is_RVC
        io.out.brMask(b) := read_resps(b).is_Br
193 194 195 196
    }

    //uBTB update 
    //backend should send fetch pc to update
197 198
    val u = RegNext(io.update.bits)
    val update_valid = RegNext(io.update.valid)
L
Lingrui98 已提交
199 200 201 202
    val update_packet_pc = packetAligned(u.ftqPC)
    val update_takens = u.takens

    val update_tag = getTag(update_packet_pc)
L
Lingrui98 已提交
203
    val update_target_lower = u.target(lowerBitsSize-1+instOffsetBits, instOffsetBits)
204
  
L
Lingrui98 已提交
205
    // only when taken should we update target
L
Lingrui98 已提交
206 207
    val data_write_valids = 
        VecInit((0 until PredictWidth).map(i =>
208
            update_valid && u.valids(i) && u.takens(i)))
L
Lingrui98 已提交
209
    val meta_write_valids = 
L
Lingrui98 已提交
210
        VecInit((0 until PredictWidth).map(i =>
211
            update_valid && u.valids(i) && (u.br_mask(i) || u.takens(i))))
L
Lingrui98 已提交
212
        
L
Lingrui98 已提交
213
    val update_write_metas = Wire(Vec(PredictWidth, new MicroBTBMeta))
L
Lingrui98 已提交
214
    val update_write_datas = Wire(Vec(PredictWidth, new MicroBTBData))
L
Lingrui98 已提交
215 216 217 218 219
    for (i <- 0 until PredictWidth) {
        update_write_metas(i).is_Br  := u.br_mask(i)
        update_write_metas(i).is_RVC := u.rvc_mask(i)
        update_write_metas(i).valid  := true.B
        update_write_metas(i).tag    := update_tag
L
Lingrui98 已提交
220
        update_write_metas(i).pred   := DontCare
L
Lingrui98 已提交
221

L
Lingrui98 已提交
222 223 224
        update_write_datas(i).lower := update_target_lower
    }
    
L
Lingrui98 已提交
225
    for (b <- 0 until PredictWidth) {
L
Lingrui98 已提交
226 227 228 229 230
        banks(b).update_write_meta.valid := meta_write_valids(b)
        banks(b).update_write_meta.bits := update_write_metas(b)
        banks(b).update_write_data.valid := data_write_valids(b)
        banks(b).update_write_data.bits := update_write_datas(b)
        banks(b).update_taken := update_takens(b)
L
Lingrui98 已提交
231
    }
232 233

    if (!env.FPGAPlatform) {
234
        XSPerfAccumulate("ubtb_commit_hits",
235 236
            PopCount((u.takens zip u.valids zip u.metas zip u.pd) map {
                case (((t, v), m), pd)  => t && v && m.ubtbHit.asBool && !pd.notCFI && update_valid}))
237
        XSPerfAccumulate("ubtb_commit_misses",
238 239 240
            PopCount((u.takens zip u.valids zip u.metas zip u.pd) map {
                case (((t, v), m), pd)  => t && v && !m.ubtbHit.asBool && !pd.notCFI && update_valid}))
    }
L
Lingrui98 已提交
241
    
242
    if (BPUDebug && debug) {
L
Lingrui98 已提交
243 244 245 246
        val update_pcs  = VecInit((0 until PredictWidth).map(i => update_packet_pc + (i << instOffsetBits).U))
        val update_bank = u.cfiIndex.bits
        val read_valid = io.pc.valid
        val read_req_tag = getTag(io.pc.bits)
L
Lingrui98 已提交
247 248 249 250 251 252 253 254 255 256
        val debug_banks = VecInit(ubtbBanks.map(_.debug_io))
        val read_hit_vec = VecInit(debug_banks.map(b => b.read_hit))
        val read_hit_ways = VecInit(debug_banks.map(b => b.read_hit_way))
        val update_hits = VecInit(debug_banks.map(b => b.update_hit))
        val update_hit_ways = VecInit(debug_banks.map(b => b.update_hit_way))
        val update_write_ways = VecInit(debug_banks.map(b => b.update_write_way))
        val update_old_preds = VecInit(debug_banks.map(b => b.update_old_pred))
        val update_new_preds = VecInit(debug_banks.map(b => b.update_new_pred))
        XSDebug(read_valid,p"uBTB read req: pc:0x${Hexadecimal(io.pc.bits)}, tag:${Hexadecimal(read_req_tag)}\n")
        XSDebug(read_valid,p"uBTB read resp: read_hit_vec:${Binary(read_hit_vec.asUInt)}\n")
L
Lingrui98 已提交
257
        for(i <- 0 until PredictWidth) {
L
Lingrui98 已提交
258 259 260 261 262
            XSDebug(read_valid,
                p"bank($i) hit:${read_hit_vec(i)} way:${read_hit_ways(i)} " +
                p"valid:${read_resps(i).valid} is_RVC:${read_resps(i).is_RVC} " +
                p"taken:${read_resps(i).taken} isBr:${read_resps(i).is_Br} " +
                p"target:0x${Hexadecimal(read_resps(i).target)}\n")
L
Lingrui98 已提交
263
            XSDebug(data_write_valids(i),
L
Lingrui98 已提交
264 265 266 267 268 269 270
                p"uBTB update data($i): update pc:0x${Hexadecimal(update_pcs(i))} " +
                p"update_lower 0x$update_target_lower\n")
            XSDebug(meta_write_valids(i),
                p"update hit:${update_hits(i)} udpate_hit_way:${update_hit_ways(i)} " +
                p"update_write_way:${update_write_ways(i)} update_taken:${update_takens(i)}" +
                p"isBr:${u.br_mask(i)} isRVC:${u.rvc_mask(i)} update_tag:${update_tag}" +
                p"update_pred(${update_old_preds(i)} -> ${update_new_preds(i)}\n")
L
Lingrui98 已提交
271
        }
L
Lingrui98 已提交
272
    }
273
}