Btb.scala 7.7 KB
Newer Older
L
Lingrui98 已提交
1 2 3 4 5 6 7 8 9 10
package xiangshan.frontend

import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.backend.ALUOpType
import utils._
import chisel3.util.experimental.BoringUtils
import xiangshan.backend.decode.XSTrap

L
Lingrui98 已提交
11 12
trait BTBParams extends HasXSParameter {
  val nRows = BtbSize / (PredictWidth * BtbWays)
L
Lingrui98 已提交
13
  val offsetLen = 13
L
Lingrui98 已提交
14
  val extendedNRows = nRows
L
Lingrui98 已提交
15 16
}

17
class BtbDataEntry extends XSBundle with BTBParams {
L
Lingrui98 已提交
18
  val offset = SInt(offsetLen.W)
L
Lingrui98 已提交
19
  val extended = Bool()
L
Lingrui98 已提交
20 21
}

22 23 24 25 26 27 28 29 30 31
object BtbDataEntry {
  def apply(offset: SInt, extended: Bool) = {
    val e = Wire(new BtbDataEntry)
    e.offset := offset
    e.extended := extended
    e
  }
}

class BtbMetaEntry() extends XSBundle with BTBParams {
L
Lingrui98 已提交
32 33 34 35 36
  val valid = Bool()
  // TODO: don't need full length of tag
  val tag = UInt((VAddrBits - log2Up(BtbSize) - 1).W)
  val btbType = UInt(2.W)
  val isRVC = Bool()
37 38 39 40 41 42 43 44 45 46 47
}

object BtbMetaEntry {
  def apply(tag: UInt, btbType: UInt, isRVC: Bool) = {
    val e = Wire(new BtbMetaEntry)
    e.valid := true.B
    e.tag := tag
    e.btbType := btbType
    e.isRVC := isRVC
    e
  }
L
Lingrui98 已提交
48 49
}

L
Lingrui98 已提交
50 51
class BTB extends BasePredictor with BTBParams{
  class BTBResp extends Resp {
L
Lingrui98 已提交
52 53
    val targets = Vec(PredictWidth, UInt(VAddrBits.W))
    val hits = Vec(PredictWidth, Bool())
L
Lingrui98 已提交
54 55 56 57
    val types = Vec(PredictWidth, UInt(2.W))
    val isRVC = Vec(PredictWidth, Bool())
  }
  class BTBMeta extends Meta {
L
Lingrui98 已提交
58
    val writeWay =  Vec(PredictWidth, UInt(log2Up(BtbWays).W))
L
Lingrui98 已提交
59
  }
L
Lingrui98 已提交
60 61
  class BTBFromOthers extends FromOthers {}
  
L
Lingrui98 已提交
62 63 64 65
  class BTBIO extends DefaultBasePredictorIO {
    val resp = Output(new BTBResp)
    val meta = Output(new BTBMeta)
  }
L
Lingrui98 已提交
66
  override val io = IO(new BTBIO)
L
Lingrui98 已提交
67
  val btbAddr = new TableAddr(log2Up(BtbSize), BtbBanks)
L
Lingrui98 已提交
68

L
Lingrui98 已提交
69
  val pcLatch = RegEnable(io.pc.bits, io.pc.valid)
L
Lingrui98 已提交
70

L
Lingrui98 已提交
71 72
  val data = List.fill(BtbWays) {
    List.fill(BtbBanks) {
73
      Module(new SRAMTemplate(new BtbDataEntry, set = nRows, shouldReset = true, holdRead = true))
L
Lingrui98 已提交
74 75
    }
  }
L
Lingrui98 已提交
76 77
  val meta = List.fill(BtbWays) {
    List.fill(BtbBanks) {
78
      Module(new SRAMTemplate(new BtbMetaEntry, set = nRows, shouldReset = true, holdRead = true))
L
Lingrui98 已提交
79 80
    }
  }
L
Lingrui98 已提交
81
  val edata = Module(new SRAMTemplate(UInt(VAddrBits.W), set = extendedNRows, shouldReset = true, holdRead = true))
L
Lingrui98 已提交
82 83

  // BTB read requests
L
Lingrui98 已提交
84 85
  val baseBank = btbAddr.getBank(io.pc.bits)

L
Lingrui98 已提交
86
  val realMask = circularShiftRight(io.inMask, BtbBanks, baseBank)
L
Lingrui98 已提交
87 88

  // those banks whose indexes are less than baseBank are in the next row
L
Lingrui98 已提交
89
  val isInNextRow = VecInit((0 until BtbBanks).map(_.U < baseBank))
L
Lingrui98 已提交
90 91

  val baseRow = btbAddr.getBankIdx(io.pc.bits)
L
Lingrui98 已提交
92

L
Lingrui98 已提交
93 94
  val nextRowStartsUp = baseRow.andR

L
Lingrui98 已提交
95
  val realRow = VecInit((0 until BtbBanks).map(b => Mux(isInNextRow(b.U), (baseRow+1.U)(log2Up(nRows)-1, 0), baseRow)))
L
Lingrui98 已提交
96

L
Lingrui98 已提交
97
  val realRowLatch = VecInit(realRow.map(RegEnable(_, enable=io.pc.valid)))
L
Lingrui98 已提交
98 99 100

  for (w <- 0 until BtbWays) {
    for (b <- 0 until BtbBanks) {
L
Lingrui98 已提交
101 102
      meta(w)(b).reset                := reset.asBool
      meta(w)(b).io.r.req.valid       := realMask(b) && io.pc.valid
L
Lingrui98 已提交
103
      meta(w)(b).io.r.req.bits.setIdx := realRow(b)
L
Lingrui98 已提交
104 105
      data(w)(b).reset                := reset.asBool
      data(w)(b).io.r.req.valid       := realMask(b) && io.pc.valid
L
Lingrui98 已提交
106 107 108
      data(w)(b).io.r.req.bits.setIdx := realRow(b)
    }
  }
L
Lingrui98 已提交
109 110 111
  edata.reset                := reset.asBool
  edata.io.r.req.valid       := io.pc.valid
  edata.io.r.req.bits.setIdx := realRow(0) // Use the baseRow
L
Lingrui98 已提交
112 113 114 115

  // Entries read from SRAM
  val metaRead = VecInit((0 until BtbWays).map(w => VecInit((0 until BtbBanks).map( b => meta(w)(b).io.r.resp.data(0)))))
  val dataRead = VecInit((0 until BtbWays).map(w => VecInit((0 until BtbBanks).map( b => data(w)(b).io.r.resp.data(0)))))
L
Lingrui98 已提交
116
  val edataRead = edata.io.r.resp.data(0)
L
Lingrui98 已提交
117 118 119

  val baseBankLatch = btbAddr.getBank(pcLatch)
  val baseTag = btbAddr.getTag(pcLatch)
L
Lingrui98 已提交
120

L
Lingrui98 已提交
121
  val tagIncremented = VecInit((0 until BtbBanks).map(b => RegEnable(isInNextRow(b.U) && nextRowStartsUp, io.pc.valid)))
L
Lingrui98 已提交
122 123 124

  val totalHits = VecInit((0 until BtbBanks).map( b => 
    VecInit((0 until BtbWays).map( w =>
L
Lingrui98 已提交
125
      metaRead(w)(b).tag === Mux(tagIncremented(b), baseTag + 1.U, baseTag) && metaRead(w)(b).valid
L
Lingrui98 已提交
126 127
    ))
  ))
L
Lingrui98 已提交
128 129
  val bankHits = VecInit(totalHits.map(_.reduce(_||_)))
  val bankHitWays = VecInit(totalHits.map(PriorityEncoder(_)))
L
Lingrui98 已提交
130

L
Lingrui98 已提交
131 132 133
  val writeWay = VecInit((0 until BtbBanks).map(
    b => Mux(bankHits(b), bankHitWays(b), LFSR64()(0))
  ))
L
Lingrui98 已提交
134

L
Lingrui98 已提交
135
  // e.g: baseBank == 5 => (5, 6,..., 15, 0, 1, 2, 3, 4)
L
Lingrui98 已提交
136
  val bankIdxInOrder = VecInit((0 until BtbBanks).map(b => (baseBankLatch +& b.U)(log2Up(BtbBanks)-1,0)))
L
Lingrui98 已提交
137 138 139


  for (b <- 0 until BtbBanks) {
L
Lingrui98 已提交
140 141 142
    val meta_entry = metaRead(bankHitWays(bankIdxInOrder(b)))(bankIdxInOrder(b))
    val data_entry = dataRead(bankHitWays(bankIdxInOrder(b)))(bankIdxInOrder(b))
    // Use real pc to calculate the target
L
Lingrui98 已提交
143 144
    io.resp.targets(b) := Mux(data_entry.extended, edataRead, (pcLatch.asSInt + (bankIdxInOrder(b.U) << 1).asSInt + data_entry.offset).asUInt)
    io.resp.hits(b)  := bankHits(bankIdxInOrder(b))
L
Lingrui98 已提交
145 146 147
    io.resp.types(b) := meta_entry.btbType
    io.resp.isRVC(b) := meta_entry.isRVC
    io.meta.writeWay(b) := writeWay(bankIdxInOrder(b))
L
Lingrui98 已提交
148 149
  }

L
Lingrui98 已提交
150
  def pdInfoToBTBtype(pd: PreDecodeInfo) = {
L
Lingrui98 已提交
151
    val t = WireInit(0.U(2.W))
L
Lingrui98 已提交
152 153 154 155 156
    when (pd.isJalr) { t := BTBtype.I}
    when (pd.isRet)  { t := BTBtype.R}
    when (pd.isJal)  { t := BTBtype.J}
    when (pd.isBr)   { t := BTBtype.B}
    t
L
Lingrui98 已提交
157
  }
L
Lingrui98 已提交
158 159
  val u = io.update.bits
  
L
Lingrui98 已提交
160 161 162 163 164 165
  val max_offset = Cat(0.B, ~(0.U((offsetLen-1).W))).asSInt
  val min_offset = Cat(1.B,  (0.U((offsetLen-1).W))).asSInt
  val new_target = Mux(u.pd.isBr, u.brTarget, u.target)
  val new_offset = (new_target.asSInt -
    u.pc.asSInt)
  val new_extended = (new_offset > max_offset || new_offset < min_offset)
L
Lingrui98 已提交
166

L
Lingrui98 已提交
167

L
Lingrui98 已提交
168
  val updateWay = u.brInfo.btbWriteWay
L
Lingrui98 已提交
169 170
  val updateBankIdx = btbAddr.getBank(u.pc)
  val updateRow = btbAddr.getBankIdx(u.pc)
171 172
  val metaWrite = BtbMetaEntry(btbAddr.getTag(u.pc), pdInfoToBTBtype(u.pd), u.pd.isRVC)
  val dataWrite = BtbDataEntry(new_offset, new_extended)
L
Lingrui98 已提交
173

L
Lingrui98 已提交
174
  val updateValid = io.update.valid
L
Lingrui98 已提交
175 176 177 178 179 180 181 182 183 184
  // Update btb
  for (w <- 0 until BtbWays) {
    for (b <- 0 until BtbBanks) {
      meta(w)(b).io.w.req.valid := updateValid && b.U === updateBankIdx && w.U === updateWay
      meta(w)(b).io.w.req.bits.setIdx := updateRow
      meta(w)(b).io.w.req.bits.data := metaWrite
      data(w)(b).io.w.req.valid := updateValid && b.U === updateBankIdx && w.U === updateWay
      data(w)(b).io.w.req.bits.setIdx := updateRow
      data(w)(b).io.w.req.bits.data := dataWrite
    }
L
Lingrui98 已提交
185 186
  }

L
Lingrui98 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
  edata.io.w.req.valid := updateValid && new_extended
  edata.io.w.req.bits.setIdx := updateRow
  edata.io.w.req.bits.data := u.target

  val debug_verbose = true

  val validLatch = RegNext(io.pc.valid)
  XSDebug(io.pc.valid, "read: pc=0x%x, baseBank=%d, realMask=%b\n", io.pc.bits, baseBank, realMask)
  XSDebug(validLatch, "read_resp: pc=0x%x, readIdx=%d-------------------------------\n",
    pcLatch, btbAddr.getIdx(pcLatch))
  if (debug_verbose) {
    for (i <- 0 until BtbBanks){
      for (j <- 0 until BtbWays) {
        XSDebug(validLatch && metaRead(j)(i).valid, "read_resp[w=%d][b=%d][r=%d] is valid, tag=0x%x, offset=0x%x, type=%d, isExtend=%d, isRVC=%d\n",
        j.U, i.U, realRowLatch(i), metaRead(j)(i).tag, dataRead(j)(i).offset, metaRead(j)(i).btbType, dataRead(j)(i).extended, metaRead(j)(i).isRVC)
L
Lingrui98 已提交
202 203 204
      }
    }
  }
L
Lingrui98 已提交
205 206 207
  for (i <- 0 until BtbBanks) {
    val idx = bankIdxInOrder(i)
    XSDebug(validLatch && bankHits(i), "resp(%d): bank(%d) hits, tgt=%x, isRVC=%d, type=%d\n",
L
Lingrui98 已提交
208
      i.U, idx, io.resp.targets(i), io.resp.isRVC(i), io.resp.types(i))
L
Lingrui98 已提交
209
  }
L
Lingrui98 已提交
210 211
  XSDebug(updateValid, "update_req: pc=0x%x, target=0x%x, offset=%x, extended=%d, way=%d, bank=%d, row=0x%x\n",
    u.pc, new_target, new_offset, new_extended, updateWay, updateBankIdx, updateRow)
212
}