uBTB.scala 8.0 KB
Newer Older
1 2 3 4 5 6 7 8
package xiangshan.frontend

import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.backend.ALUOpType
import utils._

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

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

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

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

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

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

44
    override val io = IO(new MicroBTBIO)
J
jinyue110 已提交
45
    io.uBTBBranchInfo <> out_ubtb_br_info
46 47 48 49 50 51 52 53 54 55 56

    def getTag(pc: UInt) = pc >> (log2Ceil(PredictWidth) + 1).U
    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)
80
    val read_mask = io.inMask
J
jinyue110 已提交
81 82

    XSDebug(read_valid,"uBTB read req: pc:0x%x, tag:%x  basebank:%d\n",io.pc.bits,read_req_tag,read_req_basebank)
83 84 85 86
    
    class ReadRespEntry extends XSBundle
    {
        val is_RVC = Bool()
87
        val target = UInt(VAddrBits.W)
88 89
        val valid = Bool()
        val taken = Bool()
90
        val notTaken = Bool()
91 92 93
    }
    val read_resp = Wire(Vec(PredictWidth,new ReadRespEntry))

L
Lingrui98 已提交
94
    val read_bank_inOrder = VecInit((0 until PredictWidth).map(b => (read_req_basebank + b.U)(log2Up(PredictWidth)-1,0) ))
J
jinyue110 已提交
95
    val isInNextRow = VecInit((0 until PredictWidth).map(_.U < read_req_basebank))
96
    val read_hit_ohs = read_bank_inOrder.map{ b =>
97
        VecInit((0 until nWays) map {w => 
J
jinyue110 已提交
98
            Mux(isInNextRow(b),read_req_tag + 1.U,read_req_tag) === uBTBMeta(b)(w).tag
99
        })
100 101
    }

102

J
jinyue110 已提交
103 104 105
    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
106 107
    val read_hit_way = PriorityEncoder(ParallelOR(read_hit_vec.map(_.asUInt)))
    
108
    read_bank_inOrder.foreach{ i =>
L
Lingrui98 已提交
109 110 111 112 113 114 115 116 117 118 119 120
        // do not need to decide whether to produce results
        val  uBTBMeta_resp = uBTBMeta(i)(read_hit_ways(i))
        val  btb_resp = uBTB(i)(read_hit_ways(i))
        var  index = 0
        read_resp(index).valid := uBTBMeta_resp.valid && read_hit_vec(i) && read_mask(index)
        read_resp(index).taken := read_resp(i).valid && uBTBMeta_resp.pred(1)
        read_resp(index).notTaken := read_resp(i).valid && !uBTBMeta_resp.pred(1)
        read_resp(index).target := ((io.pc.bits).asSInt + (index<<1).S + btb_resp.offset).asUInt
        read_resp(index).is_RVC := read_resp(index).valid && uBTBMeta_resp.is_RVC
        index += 1

        out_ubtb_br_info.hits(i) := read_hit_vec(i)
121 122 123
    }

    //TODO: way alloc algorithm
J
jinyue110 已提交
124
    val alloc_way = {
J
jinyue110 已提交
125
        val r_uBTBMetas = Cat(VecInit(uBTBMeta.map(e => VecInit(e.map(_.tag)))).asUInt, (read_req_tag)(tagSize-1,0))
126
        val l = log2Ceil(nWays)
J
jinyue110 已提交
127
        val nChunks = (r_uBTBMetas.getWidth + l - 1) / l
128
        val chunks = (0 until nChunks) map { i =>
J
jinyue110 已提交
129
        r_uBTBMetas(min((i+1)*l, r_uBTBMetas.getWidth)-1, i*l)
130 131 132
        }
        chunks.reduce(_^_)
    }
J
jinyue110 已提交
133
    out_ubtb_br_info.writeWay.map(_:= Mux(read_hit,read_hit_way,alloc_way))
134
    XSDebug(read_valid,"uBTB read resp:   read_hit_vec:%d, read_hit_way:%d  alloc_way:%d\n",read_hit_vec.asUInt,read_hit_way,alloc_way)
J
jinyue110 已提交
135
    for(i <- 0 until PredictWidth) {
136 137
        XSDebug(read_valid,"bank(%d)   hit:%d   way:%d   valid:%d  is_RVC:%d  taken:%d   notTaken:%d   target:0x%x\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).notTaken,read_resp(i).target )
J
jinyue110 已提交
138
    }
139 140 141 142 143 144 145
    //response
    //only when hit and instruction valid and entry valid can output data
    for(i <- 0 until PredictWidth)
    {
        when(read_resp(i).valid)
        {
            io.out.targets(i) := read_resp(i).target
L
Lingrui98 已提交
146
            io.out.hits(i) := true.B
147
            io.out.takens(i) := read_resp(i).taken
148
            io.out.is_RVC(i) := read_resp(i).is_RVC
149
            io.out.notTakens(i) := read_resp(i).notTaken
J
jinyue110 已提交
150
        } .otherwise 
151 152 153 154 155 156 157 158 159
        {
            io.out := (0.U).asTypeOf(new MicroBTBResp)
        }

    }

    //uBTB update 
    //backend should send fetch pc to update
    val update_fetch_pc  = Wire(UInt(VAddrBits.W))//TODO: io.update.bitspc
J
jinyue110 已提交
160
    val update_idx = io.update.bits.fetchIdx
161 162 163 164 165 166 167
    val update_br_offset = update_idx << 1.U
    val update_br_pc = update_fetch_pc + update_br_offset
    val update_write_way = io.update.bits.brInfo.ubtbWriteWay
    val update_hits = io.update.bits.brInfo.ubtbHits
    val update_taken = io.update.bits.taken

    val update_bank = getBank(update_br_pc)
J
jinyue110 已提交
168
    val update_base_bank = getBank(update_fetch_pc)
169 170 171 172
    val update_tag = getTag(update_br_pc)
    val update_taget_offset =  io.update.bits.target.asSInt - update_br_pc.asSInt
    val update_is_BR_or_JAL = (io.update.bits.pd.brType === BrType.branch) || (io.update.bits.pd.brType === BrType.jal) 

J
jinyue110 已提交
173
    val uBTB_write_valid = io.update.valid && io.update.bits.isMisPred && update_is_BR_or_JAL
174 175 176 177 178 179
    val uBTB_Meta_write_valid = io.update.valid && update_is_BR_or_JAL
    //write btb target when miss prediction
    when(uBTB_write_valid)
    {
        uBTB(update_bank)(update_write_way).offset := update_taget_offset
    }
J
jinyue110 已提交
180
    //write the uBTBMeta
181 182 183 184 185 186 187 188 189
    when(uBTB_Meta_write_valid)
    {
        //commit update
        uBTBMeta(update_bank)(update_write_way).is_Br := io.update.bits.pd.brType === BrType.branch
        uBTBMeta(update_bank)(update_write_way).is_RVC := io.update.bits.pd.isRVC
        uBTBMeta(update_bank)(update_write_way).valid := true.B
        uBTBMeta(update_bank)(update_write_way).tag := update_tag
        uBTBMeta(update_bank)(update_write_way).pred := 
        Mux(!update_hits(update_bank),
J
jinyue110 已提交
190
            Mux(update_taken,3.U,0.U),
191 192 193
            satUpdate( uBTBMeta(update_bank)(update_write_way).pred,2,update_taken)
        )
    }
J
jinyue110 已提交
194 195 196
    XSDebug(uBTB_Meta_write_valid,"uBTB update: update fetch pc:0x%x  | real pc:0x%x  | update hits%b  | update_write_way:%d\n",update_fetch_pc,update_br_pc,update_hits,update_write_way)
   
   //bypass:read-after-write 
J
jinyue110 已提交
197 198
    val rawBypassHit = Wire(Vec(PredictWidth, Bool()))
    for( b <- 0 until PredictWidth) {
J
jinyue110 已提交
199
        when(update_bank === b.U && read_hit_vec(b) && uBTB_Meta_write_valid && read_valid
J
jinyue110 已提交
200 201 202 203
            && 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) := io.update.bits.target
            io.out.takens(b) := io.update.bits.taken
204
            io.out.is_RVC(b) := io.update.bits.pd.isRVC
J
jinyue110 已提交
205
            io.out.notTakens(b) := (io.update.bits.pd.brType === BrType.branch) && (!io.out.takens(b))
J
jinyue110 已提交
206
             XSDebug("uBTB bypass hit!\n")
J
jinyue110 已提交
207 208
        }
    }
209
}