uBTB.scala 9.2 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._
7

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

10 11
trait MicroBTBPatameter{
    val nWays = 16
12
    val offsetSize = 20
13 14 15 16 17
}

class MicroBTB extends BasePredictor
    with MicroBTBPatameter
{
J
jinyue110 已提交
18 19 20
    val tagSize = VAddrBits - log2Ceil(PredictWidth) - 1

    class MicroBTBResp extends Resp
21
    {
L
Lingrui98 已提交
22 23
        val targets = Vec(PredictWidth, UInt(VAddrBits.W))
        val hits = Vec(PredictWidth, Bool())
24
        val takens = Vec(PredictWidth, Bool())
25
        val brMask = Vec(PredictWidth, Bool())
26
        val is_RVC = Vec(PredictWidth, Bool())
27 28
    }

J
jinyue110 已提交
29
    class MicroBTBBranchInfo extends Meta
30
    {
J
jinyue110 已提交
31
        val writeWay = Vec(PredictWidth,UInt(log2Ceil(nWays).W))
32 33
        val hits = Vec(PredictWidth,Bool())
    }
J
jinyue110 已提交
34
    val out_ubtb_br_info = Wire(new MicroBTBBranchInfo)
35
    override val metaLen = out_ubtb_br_info.asUInt.getWidth
36

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

43
    override val debug = true
44
    override val io = IO(new MicroBTBIO)
J
jinyue110 已提交
45
    io.uBTBBranchInfo <> out_ubtb_br_info
46

Fa_wang's avatar
Fa_wang 已提交
47
    def getTag(pc: UInt) = (pc >> (log2Ceil(PredictWidth) + 1)).asUInt()
48 49 50 51 52 53 54 55 56
    def getBank(pc: UInt) = pc(log2Ceil(PredictWidth) ,1)
    def satUpdate(old: UInt, len: Int, taken: Bool): UInt = {
        val oldSatTaken = old === ((1 << len)-1).U
        val oldSatNotTaken = old === 0.U
        Mux(oldSatTaken && taken, ((1 << len)-1).U,
            Mux(oldSatNotTaken && !taken, 0.U,
            Mux(taken, old + 1.U, old - 1.U)))
    } 

J
jinyue110 已提交
57

58 59 60 61 62 63 64 65 66 67 68 69 70 71
    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
    {
        val offset = SInt(offsetSize.W)
    }

J
jinyue110 已提交
72 73
    val uBTBMeta = RegInit((0.U).asTypeOf(Vec(nWays, Vec(PredictWidth, new MicroBTBMeta))))
    val uBTB = Reg(Vec(nWays, Vec(PredictWidth, new MicroBTBEntry)))
74 75 76

    //uBTB read
    //tag is bank align
J
jinyue110 已提交
77 78 79
    val read_valid = io.pc.valid
    val read_req_tag = getTag(io.pc.bits)
    val read_req_basebank = getBank(io.pc.bits)
Z
zhanglinjuan 已提交
80
    // val read_mask = circularShiftLeft(io.inMask, PredictWidth, read_req_basebank)
J
jinyue110 已提交
81

82 83 84 85
    
    class ReadRespEntry extends XSBundle
    {
        val is_RVC = Bool()
86
        val target = UInt(VAddrBits.W)
87 88
        val valid = Bool()
        val taken = Bool()
89
        val is_Br = Bool()
90 91 92
    }
    val read_resp = Wire(Vec(PredictWidth,new ReadRespEntry))

L
Lingrui98 已提交
93
    val read_bank_inOrder = VecInit((0 until PredictWidth).map(b => (read_req_basebank + b.U)(log2Up(PredictWidth)-1,0) ))
J
jinyue110 已提交
94
    val isInNextRow = VecInit((0 until PredictWidth).map(_.U < read_req_basebank))
95
    val read_hit_ohs = read_bank_inOrder.map{ b =>
96
        VecInit((0 until nWays) map {w => 
97
            Mux(isInNextRow(b),read_req_tag + 1.U,read_req_tag) === uBTBMeta(w)(b).tag
98
        })
99
    }
J
jinyue110 已提交
100 101 102
    val read_hit_vec = VecInit(read_hit_ohs.map{oh => ParallelOR(oh).asBool})
    val read_hit_ways = VecInit(read_hit_ohs.map{oh => PriorityEncoder(oh)})
    val read_hit =  ParallelOR(read_hit_vec).asBool
Fa_wang's avatar
Fa_wang 已提交
103
    val read_hit_way = PriorityEncoder(ParallelOR(read_hit_ohs.map(_.asUInt)))
104
    
J
jinyue110 已提交
105

106 107
    val  uBTBMeta_resp = VecInit((0 until PredictWidth).map(b => uBTBMeta(read_hit_ways(b))(read_bank_inOrder(b))))
    val  btb_resp = VecInit((0 until PredictWidth).map(b => uBTB(read_hit_ways(b))(read_bank_inOrder(b))))  
J
jinyue110 已提交
108 109 110

    for(i <- 0 until PredictWidth){
        // do not need to decide whether to produce results\
Z
zhanglinjuan 已提交
111
        read_resp(i).valid := uBTBMeta_resp(i).valid && read_hit_vec(i) && io.inMask(i)
J
jinyue110 已提交
112
        read_resp(i).taken := read_resp(i).valid && uBTBMeta_resp(i).pred(1)
113
        read_resp(i).is_Br  := read_resp(i).valid && uBTBMeta_resp(i).is_Br
J
jinyue110 已提交
114 115
        read_resp(i).target := ((io.pc.bits).asSInt + (i<<1).S + btb_resp(i).offset).asUInt
        read_resp(i).is_RVC := read_resp(i).valid && uBTBMeta_resp(i).is_RVC
L
Lingrui98 已提交
116 117

        out_ubtb_br_info.hits(i) := read_hit_vec(i)
118 119 120
    }

    //TODO: way alloc algorithm
121 122 123 124
    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)
125
        val l = log2Ceil(nWays)
126
        val nChunks = (tags.getWidth + l - 1) / l
127
        val chunks = (0 until nChunks) map { i =>
128
            tags(min((i+1)*l, tags.getWidth)-1, i*l)
129
        }
130 131 132 133 134 135 136 137
        way := Mux(all_valid,chunks.reduce(_^_),PriorityEncoder(~valids))
        way
    }
    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))
        
138
    }
139
    (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 已提交
140

141 142 143 144
    //response
    //only when hit and instruction valid and entry valid can output data
    for(i <- 0 until PredictWidth)
    {
145 146 147 148
        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
149
        io.out.brMask(i) := read_resp(i).is_Br
150 151 152 153
    }

    //uBTB update 
    //backend should send fetch pc to update
L
Lingrui98 已提交
154
    val u = io.update.bits.ui
J
jinyue110 已提交
155 156 157 158
    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 已提交
159 160 161
    val update_write_way = u.brInfo.ubtbWriteWay
    val update_hits = u.brInfo.ubtbHits
    val update_taken = u.taken
162 163

    val update_bank = getBank(update_br_pc)
J
jinyue110 已提交
164
    val update_base_bank = getBank(update_fetch_pc)
165
    val update_tag = getTag(update_br_pc)
J
jinyue110 已提交
166 167
    val update_target = Mux(u.pd.isBr, u.brTarget, u.target)
    val update_taget_offset =  update_target.asSInt - update_br_pc.asSInt
L
Lingrui98 已提交
168
    val update_is_BR_or_JAL = (u.pd.brType === BrType.branch) || (u.pd.brType === BrType.jal) 
169 170 171
  
  
    val jalFirstEncountered = !u.isMisPred && !u.brInfo.btbHitJal && (u.pd.brType === BrType.jal)
172 173
    val entry_write_valid = io.update.valid && (u.isMisPred || !u.isMisPred && u.pd.isBr || jalFirstEncountered)//io.update.valid //&& update_is_BR_or_JAL
    val meta_write_valid = io.update.valid && (u.isMisPred || !u.isMisPred && u.pd.isBr || jalFirstEncountered)//io.update.valid //&& update_is_BR_or_JAL
174
    //write btb target when miss prediction
J
jinyue110 已提交
175
    when(entry_write_valid)
176
    {
177
        uBTB(update_write_way)(update_bank).offset := update_taget_offset
178
    }
J
jinyue110 已提交
179
    //write the uBTBMeta
J
jinyue110 已提交
180
    when(meta_write_valid)
181 182
    {
        //commit update
183 184 185 186 187 188
        uBTBMeta(update_write_way)(update_bank).is_Br := u.pd.brType === BrType.branch
        uBTBMeta(update_write_way)(update_bank).is_RVC := u.pd.isRVC
        //(0 until PredictWidth).foreach{b =>  uBTBMeta(update_write_way)(b).valid := false.B}
        uBTBMeta(update_write_way)(update_bank).valid := true.B
        uBTBMeta(update_write_way)(update_bank).tag := update_tag
        uBTBMeta(update_write_way)(update_bank).pred := 
189
        Mux(!update_hits,
J
jinyue110 已提交
190
            Mux(update_taken,3.U,0.U),
191
            satUpdate( uBTBMeta(update_write_way)(update_bank).pred,2,update_taken)
192 193
        )
    }
Z
zhanglinjuan 已提交
194

195
    if (BPUDebug && debug) {
G
GouLingrui 已提交
196
        XSDebug(read_valid,"uBTB read req: pc:0x%x, tag:%x  basebank:%d\n",io.pc.bits,read_req_tag,read_req_basebank)
L
Lingrui98 已提交
197 198
        XSDebug(read_valid,"uBTB read resp:   read_hit_vec:%b, \n",read_hit_vec.asUInt)
        for(i <- 0 until PredictWidth) {
199 200
            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))
L
Lingrui98 已提交
201 202 203 204
        }

        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 | upadate_offset 0x%x\n "
                    ,update_br_pc,update_hits,update_write_way,update_bank,update_br_idx,update_tag,update_taget_offset(offsetSize-1,0))
205 206 207 208 209 210
        XSDebug(meta_write_valid, "uBTB update: update_taken:%d | old_pred:%b | new_pred:%b\n",
            update_taken, uBTBMeta(update_write_way)(update_bank).pred,
            Mux(!update_hits,
                Mux(update_taken,3.U,0.U),
                satUpdate( uBTBMeta(update_write_way)(update_bank).pred,2,update_taken)))

L
Lingrui98 已提交
211
    }
J
jinyue110 已提交
212 213
   
   //bypass:read-after-write 
J
jinyue110 已提交
214 215 216 217 218 219 220 221 222 223 224
//    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))
//         }
//     }
225
}