uBTB.scala 13.6 KB
Newer Older
1 2 3 4 5
package xiangshan.frontend

import chisel3._
import chisel3.util._
import utils._
Fa_wang's avatar
Fa_wang 已提交
6
import xiangshan._
L
Lingrui98 已提交
7
import chisel3.experimental.chiselName
8

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

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

    val extended_stat = false
17 18
}

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

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

J
jinyue110 已提交
35
    class MicroBTBBranchInfo extends Meta
36
    {
J
jinyue110 已提交
37
        val writeWay = Vec(PredictWidth,UInt(log2Ceil(nWays).W))
38 39
        val hits = Vec(PredictWidth,Bool())
    }
J
jinyue110 已提交
40
    val out_ubtb_br_info = Wire(new MicroBTBBranchInfo)
41
    override val metaLen = out_ubtb_br_info.asUInt.getWidth
42

J
jinyue110 已提交
43
    class MicroBTBIO extends DefaultBasePredictorIO
44 45
    {
        val out = Output(new MicroBTBResp)   //
J
jinyue110 已提交
46
        val uBTBBranchInfo = Output(new MicroBTBBranchInfo)
47 48
    }

49
    override val debug = true
50
    override val io = IO(new MicroBTBIO)
J
jinyue110 已提交
51
    io.uBTBBranchInfo <> out_ubtb_br_info
52

53
    def getTag(pc: UInt) = (pc >> untaggedBits)(tagSize-1, 0)
54
    def getBank(pc: UInt) = pc(log2Ceil(PredictWidth) ,1)
J
jinyue110 已提交
55

56 57 58 59 60 61 62 63 64 65 66
    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)
    }

    class MicroBTBEntry extends XSBundle
    {
67
        val lower = UInt(lowerBitsSize.W)
68 69
    }

L
Lingrui98 已提交
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    // val uBTBMeta = RegInit((0.U).asTypeOf(Vec(nWays, Vec(PredictWidth, new MicroBTBMeta))))
    // val uBTB = Reg(Vec(nWays, Vec(PredictWidth, new MicroBTBEntry)))

    // class UBTBMem[T <: Data](gen: T, nWays: Int) extends XSModule {
    //     class UBTBBundleR[T <: Data](private val gen: T, val way: Int) extends Bundle {
    //         val data = Output(Vec(way, gen))
    //     }
    //     class UBTBReadBus[T <: Data](private val gen: T, val way: Int) {
    //         val resp = Output(new UBTBBundleR(gen, way))
    //     }
    //     class UBTBWriteBus[T <: Data](private val gen: T, val set: Int, val way: Int) extends Bundle {
    //         val req = 
    //     }
    //     val io = IO(new Bundle {
    //         val wen = Input(Bool())
    //         val wWay = Input(UInt(log2Up(nWays).W))
    //         val wRow = Input(UInt(log2Up(PredictWidth).W))
    //         val wdata = Input(new T)
    //         val entries = Output(Vec(nWays, Vec(PredictWidth, gen)))
    //     })
    //     val mem = RegInit((0.U).asTypeOf(Vec(nWays, Vec(PredictWidth, new T))))
    //     io.entries := mem
    //     when (io.wen) {
    //         mem(wWay)(wRow) := wdata
    //     }
    // }

97 98 99 100 101 102
    class MetaOutput extends XSBundle {
        val is_Br = Bool()
        val is_RVC = Bool()
        val pred = UInt(2.W)
    }

L
Lingrui98 已提交
103
    @chiselName
L
Lingrui98 已提交
104
    class UBTBMetaBank(nWays: Int) extends XSModule {
L
Lingrui98 已提交
105 106 107 108
        val io = IO(new Bundle {
            val wen = Input(Bool())
            val wWay = Input(UInt(log2Up(nWays).W))
            val wdata = Input(new MicroBTBMeta)
109 110 111
            val rtag = Input(UInt(tagSize.W))
            val rdata = Output(new MetaOutput)
            val hit_ohs = Output(Vec(nWays, Bool()))
J
jinyue110 已提交
112
            val hit_way = Output(UInt(log2Up(nWays).W))
113 114 115
            val allocatable_way = Valid(UInt(log2Up(nWays).W))
            val rWay = Input(UInt(log2Up(nWays).W))
            val rpred = Output(UInt(2.W))
L
Lingrui98 已提交
116
        })
117 118 119 120 121 122
        val mem = Mem(nWays, new MicroBTBMeta)
        val rentries = VecInit((0 until nWays) map (i => mem(i)))
        val hit_ohs = VecInit(rentries map (e => e.valid && e.tag === io.rtag))
        val hit_way = PriorityEncoder(hit_ohs)
        val hit_entry = rentries(hit_way)
        io.hit_ohs := hit_ohs
J
jinyue110 已提交
123
        io.hit_way := hit_way
124 125 126 127 128 129 130 131
        io.rdata.is_Br  := hit_entry.is_Br
        io.rdata.is_RVC := hit_entry.is_RVC
        io.rdata.pred   := hit_entry.pred
        val entry_emptys = VecInit(rentries.map(e => !e.valid))
        val allocatable = ParallelOR(entry_emptys)
        io.allocatable_way.bits := PriorityEncoder(entry_emptys)
        io.allocatable_way.valid := allocatable
        io.rpred := rentries(io.rWay).pred
L
Lingrui98 已提交
132
        when (io.wen) {
133
            mem.write(io.wWay, io.wdata)
L
Lingrui98 已提交
134 135 136
        }
    }

L
Lingrui98 已提交
137
    @chiselName
L
Lingrui98 已提交
138
    class UBTBDataBank(nWays: Int) extends XSModule {
L
Lingrui98 已提交
139 140 141 142
        val io = IO(new Bundle {
            val wen = Input(Bool())
            val wWay = Input(UInt(log2Up(nWays).W))
            val wdata = Input(new MicroBTBEntry)
143 144
            val rWay = Input(UInt(log2Up(nWays).W))
            val rdata = Output(new MicroBTBEntry)
L
Lingrui98 已提交
145
        })
146 147 148
        val mem = Mem(nWays, new MicroBTBEntry)
        val rentries = VecInit((0 until nWays) map (i => mem(i)))
        io.rdata := rentries(io.rWay)
L
Lingrui98 已提交
149
        when (io.wen) {
150
            mem.write(io.wWay, io.wdata)
L
Lingrui98 已提交
151 152 153
        }
    }

154 155 156 157
    val metaBanks = Seq.fill(PredictWidth)(Module(new UBTBMetaBank(nWays)))
    val dataBanks = Seq.fill(PredictWidth)(Module(new UBTBDataBank(nWays)))
    val metas = VecInit(metaBanks.map(_.io))
    val datas = VecInit(dataBanks.map(_.io))
L
Lingrui98 已提交
158

159 160
    val uBTBMeta = VecInit(metas.map(m => m.rdata))
    val uBTB     = VecInit(datas.map(d => d.rdata))
161

L
Lingrui98 已提交
162 163 164 165 166
    val do_reset = RegInit(true.B)
    val reset_way = RegInit(0.U(log2Ceil(nWays).W))
    when (do_reset) { reset_way := reset_way + 1.U }
    when (reset_way === nWays.U) { do_reset := false.B }

167 168
    //uBTB read
    //tag is bank align
J
jinyue110 已提交
169 170 171 172 173
    val bankAlignedPC = bankAligned(io.pc.bits)
    val startsAtOddBank = bankInGroup(bankAlignedPC)(0).asBool
    


J
jinyue110 已提交
174
    val read_valid = io.pc.valid
J
jinyue110 已提交
175 176
    val read_req_tag = getTag(bankAlignedPC)
    val next_tag = read_req_tag + 1.U
Z
zhanglinjuan 已提交
177
    // val read_mask = circularShiftLeft(io.inMask, PredictWidth, read_req_basebank)
J
jinyue110 已提交
178

179 180 181 182
    
    class ReadRespEntry extends XSBundle
    {
        val is_RVC = Bool()
183
        val target = UInt(VAddrBits.W)
184 185
        val valid = Bool()
        val taken = Bool()
186
        val is_Br = Bool()
187 188
    }
    val read_resp = Wire(Vec(PredictWidth,new ReadRespEntry))
J
jinyue110 已提交
189
    //val read_bank_inOrder = VecInit((0 until PredictWidth).map(b => (read_req_basebank + b.U)(log2Up(PredictWidth)-1,0) ))
190
    // val isInNextRow = VecInit((0 until PredictWidth).map(_.U < read_req_basebank))
191
    
J
jinyue110 已提交
192 193
    (0 until PredictWidth).map{ b => metas(b).rtag := Mux(startsAtOddBank && (b > PredictWidth).B,next_tag,read_req_tag) }
    val read_hit_ohs = (0 until PredictWidth).map{ b => metas(b).hit_ohs }
J
jinyue110 已提交
194
    val read_hit_vec = VecInit(read_hit_ohs.map{oh => ParallelOR(oh).asBool})
J
jinyue110 已提交
195
    val read_hit_ways = (0 until PredictWidth).map{ b => metas(b).hit_way }
196 197
    // val read_hit =  ParallelOR(read_hit_vec).asBool
    // val read_hit_way = PriorityEncoder(ParallelOR(read_hit_ohs.map(_.asUInt)))
198
    
J
jinyue110 已提交
199

J
jinyue110 已提交
200
    (0 until PredictWidth).map(b => datas(b).rWay := read_hit_ways(b))
201

J
jinyue110 已提交
202 203
    val  uBTBMeta_resp = VecInit((0 until PredictWidth).map(b => metas(b).rdata))
    val  btb_resp = VecInit((0 until PredictWidth).map(b => datas(b).rdata))  
J
jinyue110 已提交
204 205 206

    for(i <- 0 until PredictWidth){
        // do not need to decide whether to produce results\
207
        read_resp(i).valid := read_hit_vec(i) && io.inMask(i)
J
jinyue110 已提交
208
        read_resp(i).taken := read_resp(i).valid && uBTBMeta_resp(i).pred(1)
209
        read_resp(i).is_Br  := read_resp(i).valid && uBTBMeta_resp(i).is_Br
210
        read_resp(i).target := Cat(io.pc.bits(VAddrBits-1, lowerBitsSize+1), btb_resp(i).asUInt, 0.U(1.W))
J
jinyue110 已提交
211
        read_resp(i).is_RVC := read_resp(i).valid && uBTBMeta_resp(i).is_RVC
L
Lingrui98 已提交
212 213

        out_ubtb_br_info.hits(i) := read_hit_vec(i)
214 215 216
    }

    //TODO: way alloc algorithm
217 218 219 220
    def alloc_way(valids:UInt ,meta_tags:UInt,req_tag:UInt) = {
        val way = Wire(UInt(log2Up(BtbWays).W))
        val all_valid = valids.andR.asBool
        val tags = Cat(meta_tags,req_tag)
221
        val l = log2Ceil(nWays)
222
        val nChunks = (tags.getWidth + l - 1) / l
223
        val chunks = (0 until nChunks) map { i =>
224
            tags(min((i+1)*l, tags.getWidth)-1, i*l)
225
        }
226 227 228
        way := Mux(all_valid,chunks.reduce(_^_),PriorityEncoder(~valids))
        way
    }
229 230 231 232 233

    // val alloc_ways = read_bank_inOrder.map{ b => 
    //     alloc_way(VecInit(uBTBMeta.map(w => w(b).valid)).asUInt,
    //               VecInit(uBTBMeta.map(w => w(b).tag)).asUInt,
    //               Mux(isInNextRow(b).asBool,read_req_tag + 1.U,read_req_tag))
234
        
235 236
    // }

J
jinyue110 已提交
237
    val alloc_ways = (0 until PredictWidth).map{ b => 
238
        Mux(metas(b).allocatable_way.valid, metas(b).allocatable_way.bits, LFSR64()(log2Ceil(nWays)-1,0))}
239
    (0 until PredictWidth).map(i => out_ubtb_br_info.writeWay(i) := Mux(read_hit_vec(i).asBool,read_hit_ways(i),alloc_ways(i)))
L
Lingrui98 已提交
240

241 242 243 244
    //response
    //only when hit and instruction valid and entry valid can output data
    for(i <- 0 until PredictWidth)
    {
245 246 247 248
        io.out.targets(i) := read_resp(i).target
        io.out.hits(i) := read_resp(i).valid
        io.out.takens(i) := read_resp(i).taken
        io.out.is_RVC(i) := read_resp(i).is_RVC
249
        io.out.brMask(i) := read_resp(i).is_Br
250 251 252 253
    }

    //uBTB update 
    //backend should send fetch pc to update
L
Lingrui98 已提交
254
    val u = io.update.bits
J
jinyue110 已提交
255 256 257 258
    val update_br_pc  = u.pc
    val update_br_idx = u.fetchIdx
    val update_br_offset = (update_br_idx << 1).asUInt()
    val update_fetch_pc = update_br_pc - update_br_offset
L
Lingrui98 已提交
259 260
    val update_write_way = u.bpuMeta.ubtbWriteWay
    val update_hits = u.bpuMeta.ubtbHits
L
Lingrui98 已提交
261
    val update_taken = u.taken
262 263

    val update_bank = getBank(update_br_pc)
J
jinyue110 已提交
264
    val update_base_bank = getBank(update_fetch_pc)
265
    val update_tag = getTag(update_br_pc)
Y
Yinan Xu 已提交
266
    val update_target = Mux(u.pd.isBr, u.brTarget, u.target)
267
    val update_target_lower = update_target(lowerBitsSize, 1)
L
Lingrui98 已提交
268
    val update_is_BR_or_JAL = (u.pd.brType === BrType.branch) || (u.pd.brType === BrType.jal) 
269 270
  
  
L
Lingrui98 已提交
271
    val jalFirstEncountered = !u.isMisPred && !u.bpuMeta.btbHitJal && (u.pd.brType === BrType.jal)
272 273
    val entry_write_valid = io.update.valid && (u.isMisPred || jalFirstEncountered)//io.update.valid //&& update_is_BR_or_JAL
    val meta_write_valid = io.update.valid && (u.isMisPred || jalFirstEncountered)//io.update.valid //&& update_is_BR_or_JAL
274
    //write btb target when miss prediction
L
Lingrui98 已提交
275 276
    // when(entry_write_valid)
    // {
277
    //     uBTB(update_write_way)(update_bank).offset := update_target_offset
L
Lingrui98 已提交
278
    // }
L
Lingrui98 已提交
279
    for (b <- 0 until PredictWidth) {
L
Lingrui98 已提交
280 281
        datas(b).wen := do_reset || (entry_write_valid && b.U === update_bank)
        datas(b).wWay := Mux(do_reset, reset_way, update_write_way)
282
        datas(b).wdata := Mux(do_reset, 0.U.asTypeOf(new MicroBTBEntry), update_target_lower.asTypeOf(new MicroBTBEntry))
L
Lingrui98 已提交
283 284
    }

L
Lingrui98 已提交
285

286

J
jinyue110 已提交
287
    //write the uBTBMeta
288
    (0 until PredictWidth).map(i => metas(i).rWay := update_write_way)
L
Lingrui98 已提交
289 290 291 292 293 294 295
    val update_write_meta = Wire(new MicroBTBMeta)
    update_write_meta.is_Br  := u.pd.brType === BrType.branch
    update_write_meta.is_RVC := u.pd.isRVC
    update_write_meta.valid  := true.B
    update_write_meta.tag    := update_tag
    update_write_meta.pred   := Mux(!update_hits,
                                    Mux(update_taken,3.U,0.U),
296
                                    satUpdate( metas(update_bank).rpred,2,update_taken)
L
Lingrui98 已提交
297
                                )
L
Lingrui98 已提交
298 299

    for (b <- 0 until PredictWidth) {
L
Lingrui98 已提交
300 301 302
        metas(b).wen := do_reset || (meta_write_valid && b.U === update_bank)
        metas(b).wWay := Mux(do_reset, reset_way, update_write_way)
        metas(b).wdata := Mux(do_reset, 0.U.asTypeOf(new MicroBTBMeta), update_write_meta)
L
Lingrui98 已提交
303
    }
Z
zhanglinjuan 已提交
304

305
    if (BPUDebug && debug) {
J
jinyue110 已提交
306
        XSDebug(read_valid,"uBTB read req: pc:0x%x, tag:%x  startAtOdd:%d\n",io.pc.bits,read_req_tag,startsAtOddBank)
L
Lingrui98 已提交
307 308 309 310 311 312
        XSDebug(read_valid,"uBTB read resp:   read_hit_vec:%b, \n",read_hit_vec.asUInt)
        for(i <- 0 until PredictWidth) {
            XSDebug(read_valid,"bank(%d)   hit:%d   way:%d   valid:%d  is_RVC:%d  taken:%d   isBr:%d   target:0x%x  alloc_way:%d\n",
                                    i.U,read_hit_vec(i),read_hit_ways(i),read_resp(i).valid,read_resp(i).is_RVC,read_resp(i).taken,read_resp(i).is_Br,read_resp(i).target,out_ubtb_br_info.writeWay(i))
        }

313 314
        XSDebug(meta_write_valid,"uBTB update: update | pc:0x%x  | update hits:%b | | update_write_way:%d  | update_bank: %d| update_br_index:%d | update_tag:%x | update_lower 0x%x\n "
                    ,update_br_pc,update_hits,update_write_way,update_bank,update_br_idx,update_tag,update_target_lower(lowerBitsSize-1,0))
L
Lingrui98 已提交
315 316 317 318 319 320
        XSDebug(meta_write_valid, "uBTB update: update_taken:%d | old_pred:%b | new_pred:%b\n",
            update_taken, metas(update_bank).rpred,
            Mux(!update_hits,
                    Mux(update_taken,3.U,0.U),
                    satUpdate( metas(update_bank).rpred,2,update_taken)
                ))
321

L
Lingrui98 已提交
322
    }
323 324 325 326 327

    if (extended_stat) {
        val high_identical = update_target(VAddrBits-1, lowerBitsSize) =/= update_fetch_pc(VAddrBits-1, lowerBitsSize)
        XSDebug(io.update.valid, "extended_stat: identical %d\n", high_identical)
    }
J
jinyue110 已提交
328 329
   
   //bypass:read-after-write 
J
jinyue110 已提交
330 331 332 333 334 335 336 337 338 339 340
//    for( b <- 0 until PredictWidth) {
//         when(update_bank === b.U && meta_write_valid && read_valid
//             && Mux(b.U < update_base_bank,update_tag===read_req_tag+1.U ,update_tag===read_req_tag))  //read and write is the same fetch-packet
//         {
//             io.out.targets(b) := u.target
//             io.out.takens(b) := u.taken
//             io.out.is_RVC(b) := u.pd.isRVC
//             io.out.notTakens(b) := (u.pd.brType === BrType.branch) && (!io.out.takens(b))
//             XSDebug("uBTB bypass hit! :   hitpc:0x%x |  hitbanck:%d  |  out_target:0x%x\n",io.pc.bits+(b<<1).asUInt(),b.U, io.out.targets(b))
//         }
//     }
341
}