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

import chisel3._
import chisel3.util._
import xiangshan._
import utils._

import scala.math.min

L
Lingrui98 已提交
10
trait HasTageParameter extends HasXSParameter with HasBPUParameter{
L
Lingrui98 已提交
11 12 13 14 15 16 17
  //                   Sets  Hist   Tag
  val TableInfo = Seq(( 128,    2,    7),
                      ( 128,    4,    7),
                      ( 256,    8,    8),
                      ( 256,   16,    8),
                      ( 128,   32,    9),
                      ( 128,   64,    9))
G
GouLingrui 已提交
18 19 20 21 22 23
                      // (  64,   64,   11),
                      // (  64,  101,   12),
                      // (  64,  160,   12),
                      // (  64,  254,   13),
                      // (  32,  403,   14),
                      // (  32,  640,   15))
L
Lingrui98 已提交
24
  val TageNTables = TableInfo.size
25
  val UBitPeriod = 2048
L
Lingrui98 已提交
26
  val TageBanks = PredictWidth // FetchWidth
27 28 29 30 31 32
  val TageCtrBits = 3
  val SCHistLens = 0 :: TableInfo.map{ case (_,h,_) => h}.toList
  val SCNTables = 6
  val SCCtrBits = 6
  val SCNRows = 1024
  val SCTableInfo = Seq.fill(SCNTables)((SCNRows, SCCtrBits)) zip SCHistLens map {case ((n, cb), h) => (n, cb, h)}
L
Lingrui98 已提交
33 34
  val TotalBits = TableInfo.map {
    case (s, h, t) => {
35
      s * (1+t+TageCtrBits) * PredictWidth
L
Lingrui98 已提交
36 37
    }
  }.reduce(_+_)
L
Lingrui98 已提交
38 39
}

40
abstract class TageBundle extends XSBundle with HasTageParameter with PredictorUtils
L
Lingrui98 已提交
41
abstract class TageModule extends XSModule with HasTageParameter with PredictorUtils { val debug = false }
L
Lingrui98 已提交
42

L
Lingrui98 已提交
43 44 45



L
Lingrui98 已提交
46
class TageReq extends TageBundle {
L
Lingrui98 已提交
47 48 49
  val pc = UInt(VAddrBits.W)
  val hist = UInt(HistoryLength.W)
  val mask = UInt(PredictWidth.W)
L
Lingrui98 已提交
50 51 52
}

class TageResp extends TageBundle {
53
  val ctr = UInt(TageCtrBits.W)
L
Lingrui98 已提交
54
  val u = UInt(2.W)
L
Lingrui98 已提交
55 56 57
}

class TageUpdate extends TageBundle {
L
Lingrui98 已提交
58
  val pc = UInt(VAddrBits.W)
59
  val fetchIdx = UInt(log2Up(TageBanks).W)
L
Lingrui98 已提交
60 61 62 63 64
  val hist = UInt(HistoryLength.W)
  // update tag and ctr
  val mask = Vec(TageBanks, Bool())
  val taken = Vec(TageBanks, Bool())
  val alloc = Vec(TageBanks, Bool())
65
  val oldCtr = Vec(TageBanks, UInt(TageCtrBits.W))
L
Lingrui98 已提交
66 67 68
  // update u
  val uMask = Vec(TageBanks, Bool())
  val u = Vec(TageBanks, UInt(2.W))
L
Lingrui98 已提交
69 70 71
}

class FakeTageTable() extends TageModule {
L
Lingrui98 已提交
72 73 74 75 76 77
  val io = IO(new Bundle() {
    val req = Input(Valid(new TageReq))
    val resp = Output(Vec(TageBanks, Valid(new TageResp)))
    val update = Input(new TageUpdate)
  })
  io.resp := DontCare
L
Lingrui98 已提交
78 79 80 81

}

class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPeriod: Int) extends TageModule {
L
Lingrui98 已提交
82 83 84 85 86
  val io = IO(new Bundle() {
    val req = Input(Valid(new TageReq))
    val resp = Output(Vec(TageBanks, Valid(new TageResp)))
    val update = Input(new TageUpdate)
  })
87
  // override val debug = true
L
Lingrui98 已提交
88
  // bypass entries for tage update
89
  val wrBypassEntries = 8
L
Lingrui98 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

  def compute_folded_hist(hist: UInt, l: Int) = {
    val nChunks = (histLen + l - 1) / l
    val hist_chunks = (0 until nChunks) map {i =>
      hist(min((i+1)*l, histLen)-1, i*l)
    }
    hist_chunks.reduce(_^_)
  }

  def compute_tag_and_hash(unhashed_idx: UInt, hist: UInt) = {
    val idx_history = compute_folded_hist(hist, log2Ceil(nRows))
    val idx = (unhashed_idx ^ idx_history)(log2Ceil(nRows)-1,0)
    val tag_history = compute_folded_hist(hist, tagLen)
    // Use another part of pc to make tags
    val tag = ((unhashed_idx >> log2Ceil(nRows)) ^ tag_history)(tagLen-1,0)
    (idx, tag)
  }

108
  def inc_ctr(ctr: UInt, taken: Bool): UInt = satUpdate(ctr, TageCtrBits, taken)
L
Lingrui98 已提交
109

L
Lingrui98 已提交
110 111 112 113 114 115 116 117
  val doing_reset = RegInit(true.B)
  val reset_idx = RegInit(0.U(log2Ceil(nRows).W))
  reset_idx := reset_idx + doing_reset
  when (reset_idx === (nRows-1).U) { doing_reset := false.B }

  class TageEntry() extends TageBundle {
    val valid = Bool()
    val tag = UInt(tagLen.W)
118
    val ctr = UInt(TageCtrBits.W)
L
Lingrui98 已提交
119 120
  }

121
  val tageEntrySz = 1 + tagLen + TageCtrBits
L
Lingrui98 已提交
122

L
Lingrui98 已提交
123
  // use real address to index
124 125
  // val unhashed_idxes = VecInit((0 until TageBanks).map(b => ((io.req.bits.pc >> 1.U) + b.U) >> log2Up(TageBanks).U))
  val unhashed_idx = io.req.bits.pc >> 1.U
L
Lingrui98 已提交
126

127 128 129 130
  // val idxes_and_tags = (0 until TageBanks).map(b => compute_tag_and_hash(unhashed_idxes(b.U), io.req.bits.hist))
  val (idx, tag) = compute_tag_and_hash(unhashed_idx, io.req.bits.hist)
  // val idxes = VecInit(idxes_and_tags.map(_._1))
  // val tags = VecInit(idxes_and_tags.map(_._2))
L
Lingrui98 已提交
131

132 133
  val idxLatch = RegEnable(idx, enable=io.req.valid)
  val tagLatch = RegEnable(tag, enable=io.req.valid)
L
Lingrui98 已提交
134 135 136 137 138

  val hi_us = List.fill(TageBanks)(Module(new SRAMTemplate(Bool(), set=nRows, shouldReset=false, holdRead=true, singlePort=false)))
  val lo_us = List.fill(TageBanks)(Module(new SRAMTemplate(Bool(), set=nRows, shouldReset=false, holdRead=true, singlePort=false)))
  val table = List.fill(TageBanks)(Module(new SRAMTemplate(new TageEntry, set=nRows, shouldReset=false, holdRead=true, singlePort=false)))

L
Lingrui98 已提交
139 140 141
  val hi_us_r = WireInit(0.U.asTypeOf(Vec(TageBanks, Bool())))
  val lo_us_r = WireInit(0.U.asTypeOf(Vec(TageBanks, Bool())))
  val table_r = WireInit(0.U.asTypeOf(Vec(TageBanks, new TageEntry)))
L
Lingrui98 已提交
142

L
Lingrui98 已提交
143
  val baseBank = io.req.bits.pc(log2Up(TageBanks), 1)
144
  val baseBankLatch = RegEnable(baseBank, enable=io.req.valid)
L
Lingrui98 已提交
145

146
  val bankIdxInOrder = VecInit((0 until TageBanks).map(b => (baseBankLatch +& b.U)(log2Up(TageBanks)-1, 0)))
L
Lingrui98 已提交
147

L
Lingrui98 已提交
148
  val realMask = circularShiftLeft(io.req.bits.mask, TageBanks, baseBank)
L
Lingrui98 已提交
149
  val maskLatch = RegEnable(io.req.bits.mask, enable=io.req.valid)
L
Lingrui98 已提交
150

L
Lingrui98 已提交
151 152
  (0 until TageBanks).map(
    b => {
L
Lingrui98 已提交
153 154 155 156 157 158 159
      Seq(hi_us, lo_us, table).map(
        t => {
          t(b).reset := reset.asBool
          t(b).io.r.req.valid := io.req.valid && realMask(b)
          t(b).io.r.req.bits.setIdx := idx
        }
      )
L
Lingrui98 已提交
160

161 162 163
      hi_us_r(b) := hi_us(b).io.r.resp.data(0)
      lo_us_r(b) := lo_us(b).io.r.resp.data(0)
      table_r(b) := table(b).io.r.resp.data(0)
L
Lingrui98 已提交
164 165 166
    }
  )

167
  val req_rhits = VecInit((0 until TageBanks).map(b => table_r(bankIdxInOrder(b)).valid && table_r(bankIdxInOrder(b)).tag === tagLatch))
L
Lingrui98 已提交
168 169

  (0 until TageBanks).map(b => {
L
Lingrui98 已提交
170
    io.resp(b).valid := req_rhits(b) && maskLatch(b)
171 172
    io.resp(b).bits.ctr := table_r(bankIdxInOrder(b)).ctr
    io.resp(b).bits.u := Cat(hi_us_r(bankIdxInOrder(b)),lo_us_r(bankIdxInOrder(b)))
L
Lingrui98 已提交
173 174 175 176 177 178 179 180 181 182 183
  })


  val clear_u_ctr = RegInit(0.U((log2Ceil(uBitPeriod) + log2Ceil(nRows) + 1).W))
  when (doing_reset) { clear_u_ctr := 1.U } .otherwise { clear_u_ctr := clear_u_ctr + 1.U }

  val doing_clear_u = clear_u_ctr(log2Ceil(uBitPeriod)-1,0) === 0.U
  val doing_clear_u_hi = doing_clear_u && clear_u_ctr(log2Ceil(uBitPeriod) + log2Ceil(nRows)) === 1.U
  val doing_clear_u_lo = doing_clear_u && clear_u_ctr(log2Ceil(uBitPeriod) + log2Ceil(nRows)) === 0.U
  val clear_u_idx = clear_u_ctr >> log2Ceil(uBitPeriod)

184 185
  // Use fetchpc to compute hash
  val (update_idx, update_tag) = compute_tag_and_hash((io.update.pc >> 1.U) - io.update.fetchIdx, io.update.hist)
L
Lingrui98 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

  val update_wdata = Wire(Vec(TageBanks, new TageEntry))


  (0 until TageBanks).map(b => {
    table(b).io.w.req.valid := io.update.mask(b) || doing_reset
    table(b).io.w.req.bits.setIdx := Mux(doing_reset, reset_idx, update_idx)
    table(b).io.w.req.bits.data := Mux(doing_reset, 0.U.asTypeOf(new TageEntry), update_wdata(b))
  })

  val update_hi_wdata = Wire(Vec(TageBanks, Bool()))
  (0 until TageBanks).map(b => {
    hi_us(b).io.w.req.valid := io.update.uMask(b) || doing_reset || doing_clear_u_hi
    hi_us(b).io.w.req.bits.setIdx := Mux(doing_reset, reset_idx, Mux(doing_clear_u_hi, clear_u_idx, update_idx))
    hi_us(b).io.w.req.bits.data := Mux(doing_reset || doing_clear_u_hi, 0.U, update_hi_wdata(b))
  })

  val update_lo_wdata = Wire(Vec(TageBanks, Bool()))
  (0 until TageBanks).map(b => {
    lo_us(b).io.w.req.valid := io.update.uMask(b) || doing_reset || doing_clear_u_lo
    lo_us(b).io.w.req.bits.setIdx := Mux(doing_reset, reset_idx, Mux(doing_clear_u_lo, clear_u_idx, update_idx))
    lo_us(b).io.w.req.bits.data := Mux(doing_reset || doing_clear_u_lo, 0.U, update_lo_wdata(b))
  })

  val wrbypass_tags    = Reg(Vec(wrBypassEntries, UInt(tagLen.W)))
  val wrbypass_idxs    = Reg(Vec(wrBypassEntries, UInt(log2Ceil(nRows).W)))
212
  val wrbypass_ctrs    = Reg(Vec(wrBypassEntries, Vec(TageBanks, UInt(TageCtrBits.W))))
L
Lingrui98 已提交
213
  val wrbypass_ctr_valids = Reg(Vec(wrBypassEntries, Vec(TageBanks, Bool())))
L
Lingrui98 已提交
214 215
  val wrbypass_enq_idx = RegInit(0.U(log2Ceil(wrBypassEntries).W))

L
Lingrui98 已提交
216 217
  when (reset.asBool) { wrbypass_ctr_valids.foreach(_.foreach(_ := false.B))}

L
Lingrui98 已提交
218 219 220 221 222
  val wrbypass_hits    = VecInit((0 until wrBypassEntries) map { i =>
    !doing_reset &&
    wrbypass_tags(i) === update_tag &&
    wrbypass_idxs(i) === update_idx
  })
223

224 225 226 227 228
  val wrbypass_rhits   = VecInit((0 until wrBypassEntries) map { i =>
    io.req.valid &&
    wrbypass_tags(i) === tag &&
    wrbypass_idxs(i) === idx
  })
229

230 231 232 233 234
  val wrbypass_hit      = wrbypass_hits.reduce(_||_)
  val wrbypass_rhit     = wrbypass_rhits.reduce(_||_)
  val wrbypass_hit_idx  = PriorityEncoder(wrbypass_hits)
  val wrbypass_rhit_idx = PriorityEncoder(wrbypass_rhits)

235 236 237 238 239 240 241 242 243 244 245
  val wrbypass_rctr_hits = VecInit((0 until TageBanks).map( b => wrbypass_ctr_valids(wrbypass_rhit_idx)(b)))

  val rhit_ctrs = RegEnable(wrbypass_ctrs(wrbypass_rhit_idx), wrbypass_rhit)

  when (RegNext(wrbypass_rhit)) {
    for (b <- 0 until TageBanks) {
      when (RegNext(wrbypass_rctr_hits(b.U + baseBank))) {
        io.resp(b).bits.ctr := rhit_ctrs(bankIdxInOrder(b))
      }
    }
  }
246 247


L
Lingrui98 已提交
248
  val updateBank = PriorityEncoder(io.update.mask)
L
Lingrui98 已提交
249 250 251 252 253 254

  for (w <- 0 until TageBanks) {
    update_wdata(w).ctr   := Mux(io.update.alloc(w),
      Mux(io.update.taken(w), 4.U,
                              3.U
      ),
L
Lingrui98 已提交
255 256 257 258
      Mux(wrbypass_hit && wrbypass_ctr_valids(wrbypass_hit_idx)(w),
            inc_ctr(wrbypass_ctrs(wrbypass_hit_idx)(w), io.update.taken(w)),
            inc_ctr(io.update.oldCtr(w), io.update.taken(w))
      )
L
Lingrui98 已提交
259 260 261 262 263 264 265 266 267 268
    )
    update_wdata(w).valid := true.B
    update_wdata(w).tag   := update_tag

    update_hi_wdata(w)    := io.update.u(w)(1)
    update_lo_wdata(w)    := io.update.u(w)(0)
  }

  when (io.update.mask.reduce(_||_)) {
    when (wrbypass_hits.reduce(_||_)) {
L
Lingrui98 已提交
269 270
      wrbypass_ctrs(wrbypass_hit_idx)(updateBank) := update_wdata(updateBank).ctr
      wrbypass_ctr_valids(wrbypass_enq_idx)(updateBank) := true.B
L
Lingrui98 已提交
271
    } .otherwise {
L
Lingrui98 已提交
272
      wrbypass_ctrs(wrbypass_enq_idx)(updateBank) := update_wdata(updateBank).ctr
273
      (0 until TageBanks).foreach(b => wrbypass_ctr_valids(wrbypass_enq_idx)(b) := false.B) // reset valid bits
L
Lingrui98 已提交
274
      wrbypass_ctr_valids(wrbypass_enq_idx)(updateBank) := true.B
L
Lingrui98 已提交
275 276 277 278 279
      wrbypass_tags(wrbypass_enq_idx) := update_tag
      wrbypass_idxs(wrbypass_enq_idx) := update_idx
      wrbypass_enq_idx := (wrbypass_enq_idx + 1.U)(log2Ceil(wrBypassEntries)-1,0)
    }
  }
280

281
  if (BPUDebug && debug) {
L
Lingrui98 已提交
282 283 284 285 286 287 288 289
    val u = io.update
    val b = PriorityEncoder(u.mask)
    val ub = PriorityEncoder(u.uMask)
    XSDebug(io.req.valid, "tableReq: pc=0x%x, hist=%x, idx=%d, tag=%x, baseBank=%d, mask=%b, realMask=%b\n",
      io.req.bits.pc, io.req.bits.hist, idx, tag, baseBank, io.req.bits.mask, realMask)
    for (i <- 0 until TageBanks) {
      XSDebug(RegNext(io.req.valid) && req_rhits(i), "TageTableResp[%d]: idx=%d, hit:%d, ctr:%d, u:%d\n", i.U, idxLatch, req_rhits(i), io.resp(i).bits.ctr, io.resp(i).bits.u)
    }
290

L
Lingrui98 已提交
291 292 293 294 295 296 297 298 299 300
    XSDebug(RegNext(io.req.valid), "TageTableResp: hits:%b, maskLatch is %b\n", req_rhits.asUInt, maskLatch)
    XSDebug(RegNext(io.req.valid) && !req_rhits.reduce(_||_), "TageTableResp: no hits!\n")

    XSDebug(io.update.mask.reduce(_||_), "update Table: pc:%x, fetchIdx:%d, hist:%x, bank:%d, taken:%d, alloc:%d, oldCtr:%d\n",
      u.pc, u.fetchIdx, u.hist, b, u.taken(b), u.alloc(b), u.oldCtr(b))
    XSDebug(io.update.mask.reduce(_||_), "update Table: writing tag:%b, ctr%d in idx:%d\n",
      update_wdata(b).tag, update_wdata(b).ctr, update_idx)
    XSDebug(io.update.mask.reduce(_||_), "update u: pc:%x, fetchIdx:%d, hist:%x, bank:%d, writing in u:%b\n",
      u.pc, u.fetchIdx, u.hist, ub, io.update.u(ub))

301 302 303 304 305 306 307 308 309 310 311 312 313
    val updateBank = PriorityEncoder(io.update.mask)
    XSDebug(wrbypass_hit && wrbypass_ctr_valids(wrbypass_hit_idx)(updateBank),
      "wrbypass hits, wridx:%d, tag:%x, idx:%d, hitctr:%d, bank:%d\n",
      wrbypass_hit_idx, update_tag, update_idx, wrbypass_ctrs(wrbypass_hit_idx)(updateBank), updateBank)

    when (wrbypass_rhit && wrbypass_ctr_valids(wrbypass_rhit_idx).reduce(_||_)) {
      for (b <- 0 until TageBanks) {
        XSDebug(wrbypass_ctr_valids(wrbypass_rhit_idx)(b),
          "wrbypass rhits, wridx:%d, tag:%x, idx:%d, hitctr:%d, bank:%d\n",
          wrbypass_rhit_idx, tag, idx, wrbypass_ctrs(wrbypass_rhit_idx)(b), b.U)
      }
    }

L
Lingrui98 已提交
314 315 316 317 318 319 320
    // ------------------------------Debug-------------------------------------
    val valids = Reg(Vec(TageBanks, Vec(nRows, Bool())))
    when (reset.asBool) { valids.foreach(b => b.foreach(r => r := false.B)) }
    (0 until TageBanks).map( b => { when (io.update.mask(b)) { valids(b)(update_idx) := true.B }})
    XSDebug("Table usage:------------------------\n")
    (0 until TageBanks).map( b => { XSDebug("Bank(%d): %d out of %d rows are valid\n", b.U, PopCount(valids(b)), nRows.U)})
  }
L
Lingrui98 已提交
321

L
Lingrui98 已提交
322 323
}

324
abstract class BaseTage extends BasePredictor with HasTageParameter {
L
Lingrui98 已提交
325
  class TAGEResp extends Resp {
326 327
    val takens = Vec(PredictWidth, Bool())
    val hits = Vec(PredictWidth, Bool())
L
Lingrui98 已提交
328
  }
329
  class TAGEMeta extends Meta{
L
Lingrui98 已提交
330 331 332 333 334 335
  }
  class FromBIM extends FromOthers {
    val ctrs = Vec(PredictWidth, UInt(2.W))
  }
  class TageIO extends DefaultBasePredictorIO {
    val resp = Output(new TAGEResp)
L
Lingrui98 已提交
336
    val meta = Output(Vec(PredictWidth, new TageMeta))
L
Lingrui98 已提交
337 338 339 340
    val bim = Input(new FromBIM)
    val s3Fire = Input(Bool())
  }

L
Lingrui98 已提交
341
  override val io = IO(new TageIO)
342
}
L
Lingrui98 已提交
343

344
class FakeTage extends BaseTage {
L
Lingrui98 已提交
345 346
  io.resp <> DontCare
  io.meta <> DontCare
L
Lingrui98 已提交
347 348 349
}


350
class Tage extends BaseTage {
L
Lingrui98 已提交
351 352 353 354

  val tables = TableInfo.map {
    case (nRows, histLen, tagLen) => {
      val t = if(EnableBPD) Module(new TageTable(nRows, histLen, tagLen, UBitPeriod)) else Module(new FakeTageTable)
355
      t.io.req.valid := io.pc.valid && !io.flush
L
Lingrui98 已提交
356 357 358 359 360 361 362
      t.io.req.bits.pc := io.pc.bits
      t.io.req.bits.hist := io.hist
      t.io.req.bits.mask := io.inMask
      t
    }
  }

363 364
  val scTables = SCTableInfo.map {
    case (nRows, ctrBits, histLen) => {
L
Lingrui98 已提交
365
      val t = if (EnableSC) Module(new SCTable(nRows/TageBanks, ctrBits, histLen)) else Module(new FakeSCTable)
366 367 368 369 370 371 372 373 374
      val req = t.io.req
      req.valid := io.pc.valid && !io.flush
      req.bits.pc := io.pc.bits
      req.bits.hist := io.hist
      req.bits.mask := io.inMask
      t
    }
  }

L
Lingrui98 已提交
375
  val scThreshold = RegInit(SCThreshold(5))
376 377 378
  val useThreshold = WireInit(scThreshold.thres)
  val updateThreshold = WireInit((useThreshold << 3) + 21.U)

L
Lingrui98 已提交
379
  // override val debug = true
380

L
Lingrui98 已提交
381
  // Keep the table responses to process in s3
L
Lingrui98 已提交
382
  val resps = VecInit(tables.map(t => RegEnable(t.io.resp, enable=io.s3Fire)))
383
  val scResps = VecInit(scTables.map(t => RegEnable(t.io.resp, enable=io.s3Fire)))
L
Lingrui98 已提交
384
  // val flushLatch = RegNext(io.flush)
L
Lingrui98 已提交
385 386 387 388 389 390 391

  val s2_bim = RegEnable(io.bim, enable=io.pc.valid) // actually it is s2Fire
  val s3_bim = RegEnable(s2_bim, enable=io.s3Fire)

  val debug_pc_s2 = RegEnable(io.pc.bits, enable=io.pc.valid)
  val debug_pc_s3 = RegEnable(debug_pc_s2, enable=io.s3Fire)

392 393 394
  val debug_hist_s2 = RegEnable(io.hist, enable=io.pc.valid)
  val debug_hist_s3 = RegEnable(debug_hist_s2, enable=io.s3Fire)

L
Lingrui98 已提交
395 396 397 398
  val u = io.update.bits.ui
  val updateValid = io.update.valid
  val updateHist = io.update.bits.hist

L
Lingrui98 已提交
399
  val updateIsBr = u.pd.isBr
L
Lingrui98 已提交
400
  val updateMeta = u.brInfo.tageMeta
L
Lingrui98 已提交
401
  val updateMisPred = u.isMisPred && updateIsBr
L
Lingrui98 已提交
402 403 404 405 406

  val updateMask = WireInit(0.U.asTypeOf(Vec(TageNTables, Vec(TageBanks, Bool()))))
  val updateUMask = WireInit(0.U.asTypeOf(Vec(TageNTables, Vec(TageBanks, Bool()))))
  val updateTaken = Wire(Vec(TageNTables, Vec(TageBanks, Bool())))
  val updateAlloc = Wire(Vec(TageNTables, Vec(TageBanks, Bool())))
407
  val updateOldCtr = Wire(Vec(TageNTables, Vec(TageBanks, UInt(TageCtrBits.W))))
L
Lingrui98 已提交
408 409 410 411 412 413
  val updateU = Wire(Vec(TageNTables, Vec(TageBanks, UInt(2.W))))
  updateTaken := DontCare
  updateAlloc := DontCare
  updateOldCtr := DontCare
  updateU := DontCare

L
Lingrui98 已提交
414 415 416
  val scUpdateMask = WireInit(0.U.asTypeOf(Vec(SCNTables, Vec(TageBanks, Bool()))))
  val scUpdateTagePred = Wire(Bool())
  val scUpdateTaken = Wire(Bool())
417 418 419 420 421 422
  val scUpdateOldCtrs = Wire(Vec(SCNTables, SInt(SCCtrBits.W)))
  scUpdateTagePred := DontCare
  scUpdateTaken := DontCare
  scUpdateOldCtrs := DontCare

  val updateSCMeta = u.brInfo.tageMeta.scMeta
L
Lingrui98 已提交
423
  val updateTageMisPred = updateMeta.taken =/= u.taken && updateIsBr
424

425
  val updateBank = u.pc(log2Ceil(TageBanks), 1)
L
Lingrui98 已提交
426 427 428

  // access tag tables and output meta info
  for (w <- 0 until TageBanks) {
L
Lingrui98 已提交
429
    val tageTaken = WireInit(false.B)
L
Lingrui98 已提交
430 431 432 433
    var altPred = s3_bim.ctrs(w)(1)
    val finalAltPred = WireInit(s3_bim.ctrs(w)(1))
    var provided = false.B
    var provider = 0.U
L
Lingrui98 已提交
434
    io.resp.takens(w) := s3_bim.ctrs(w)(1)
L
Lingrui98 已提交
435 436

    for (i <- 0 until TageNTables) {
L
Lingrui98 已提交
437
      val hit = resps(i)(w).valid
L
Lingrui98 已提交
438 439
      val ctr = resps(i)(w).bits.ctr
      when (hit) {
L
Lingrui98 已提交
440
        io.resp.takens(w) := Mux(ctr === 3.U || ctr === 4.U, altPred, ctr(2)) // Use altpred on weak taken
441
        tageTaken := Mux(ctr === 3.U || ctr === 4.U, altPred, ctr(2))
L
Lingrui98 已提交
442 443 444 445 446 447
        finalAltPred := altPred
      }
      provided = provided || hit          // Once hit then provide
      provider = Mux(hit, i.U, provider)  // Use the last hit as provider
      altPred = Mux(hit, ctr(2), altPred) // Save current pred as potential altpred
    }
L
Lingrui98 已提交
448
    io.resp.hits(w) := provided
L
Lingrui98 已提交
449 450
    io.meta(w).provider.valid := provided
    io.meta(w).provider.bits := provider
L
Lingrui98 已提交
451
    io.meta(w).altDiffers := finalAltPred =/= io.resp.takens(w)
L
Lingrui98 已提交
452 453
    io.meta(w).providerU := resps(provider)(w).bits.u
    io.meta(w).providerCtr := resps(provider)(w).bits.ctr
L
Lingrui98 已提交
454
    io.meta(w).taken := tageTaken
L
Lingrui98 已提交
455 456 457 458 459 460 461 462 463 464 465 466 467

    // Create a mask fo tables which did not hit our query, and also contain useless entries
    // and also uses a longer history than the provider
    val allocatableSlots = (VecInit(resps.map(r => !r(w).valid && r(w).bits.u === 0.U)).asUInt &
      ~(LowerMask(UIntToOH(provider), TageNTables) & Fill(TageNTables, provided.asUInt))
    )
    val allocLFSR = LFSR64()(TageNTables - 1, 0)
    val firstEntry = PriorityEncoder(allocatableSlots)
    val maskedEntry = PriorityEncoder(allocatableSlots & allocLFSR)
    val allocEntry = Mux(allocatableSlots(maskedEntry), maskedEntry, firstEntry)
    io.meta(w).allocate.valid := allocatableSlots =/= 0.U
    io.meta(w).allocate.bits := allocEntry

468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
    val scMeta = io.meta(w).scMeta
    scMeta := DontCare
    val scTableSums = VecInit(
      (0 to 1) map { i => {
          // val providerCtr = resps(provider)(w).bits.ctr.zext()
          // val pvdrCtrCentered = (((providerCtr - 4.S) << 1) + 1.S) << 3
          // sum += pvdrCtrCentered
          if (EnableSC) {
            (0 until SCNTables) map { j => 
              scTables(j).getCenteredValue(scResps(j)(w).ctr(i))
            } reduce (_+_) // TODO: rewrite with adder tree
          }
          else 0.S
        }
      }
    )

    if (EnableSC) {
      scMeta.tageTaken := tageTaken
      scMeta.scUsed := provided
L
Lingrui98 已提交
488 489
      scMeta.scPred := tageTaken
      scMeta.sumAbs := 0.U
490 491
      when (provided) {
        val providerCtr = resps(provider)(w).bits.ctr.zext()
L
Lingrui98 已提交
492 493 494
        val pvdrCtrCentered = ((((providerCtr - 4.S) << 1).asSInt + 1.S) << 3).asSInt
        val totalSum = scTableSums(tageTaken.asUInt) + pvdrCtrCentered
        val sumAbs = totalSum.abs().asUInt
495 496
        val sumBelowThreshold = totalSum.abs.asUInt < useThreshold
        val scPred = totalSum >= 0.S
L
Lingrui98 已提交
497 498 499 500 501 502
        scMeta.sumAbs := sumAbs
        scMeta.ctrs   := VecInit(scResps.map(r => r(w).ctr(tageTaken.asUInt)))
        for (i <- 0 until SCNTables) {
          XSDebug(RegNext(io.s3Fire), p"SCTable(${i.U})(${w.U}): ctr:(${scResps(i)(w).ctr(0)},${scResps(i)(w).ctr(1)})\n")
        }
        XSDebug(RegNext(io.s3Fire), p"SC(${w.U}): pvdCtr(${providerCtr}), pvdCentred(${pvdrCtrCentered}), totalSum(${totalSum}), abs(${sumAbs}) useThres(${useThreshold}), scPred(${scPred})\n")
503 504
        // Use prediction from Statistical Corrector
        when (!sumBelowThreshold) {
L
Lingrui98 已提交
505 506
          XSDebug(RegNext(io.s3Fire), p"SC(${w.U}) overriden pred to ${scPred}\n")
          scMeta.scPred := scPred
507 508 509 510
          io.resp.takens(w) := scPred
        }
      }
    }
L
Lingrui98 已提交
511 512

    val isUpdateTaken = updateValid && updateBank === w.U &&
L
Lingrui98 已提交
513 514
      u.taken && updateIsBr
    when (updateIsBr && updateValid && updateBank === w.U) {
L
Lingrui98 已提交
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
      when (updateMeta.provider.valid) {
        val provider = updateMeta.provider.bits

        updateMask(provider)(w) := true.B
        updateUMask(provider)(w) := true.B

        updateU(provider)(w) := Mux(!updateMeta.altDiffers, updateMeta.providerU,
          Mux(updateMisPred, Mux(updateMeta.providerU === 0.U, 0.U, updateMeta.providerU - 1.U),
                              Mux(updateMeta.providerU === 3.U, 3.U, updateMeta.providerU + 1.U))
        )
        updateTaken(provider)(w) := isUpdateTaken
        updateOldCtr(provider)(w) := updateMeta.providerCtr
        updateAlloc(provider)(w) := false.B
      }
    }
  }

L
Lingrui98 已提交
532
  when (updateValid && updateTageMisPred) {
L
Lingrui98 已提交
533 534 535 536
    val idx = updateBank
    val allocate = updateMeta.allocate
    when (allocate.valid) {
      updateMask(allocate.bits)(idx) := true.B
L
Lingrui98 已提交
537
      updateTaken(allocate.bits)(idx) := u.taken
L
Lingrui98 已提交
538 539 540 541 542
      updateAlloc(allocate.bits)(idx) := true.B
      updateUMask(allocate.bits)(idx) := true.B
      updateU(allocate.bits)(idx) := 0.U
    }.otherwise {
      val provider = updateMeta.provider
G
GouLingrui 已提交
543
      val decrMask = Mux(provider.valid, ~LowerMask(UIntToOH(provider.bits), TageNTables), 0.U(TageNTables.W))
L
Lingrui98 已提交
544 545 546 547 548 549 550 551 552
      for (i <- 0 until TageNTables) {
        when (decrMask(i)) {
          updateUMask(i)(idx) := true.B
          updateU(i)(idx) := 0.U
        }
      }
    }
  }

553
  if (EnableSC) {
L
Lingrui98 已提交
554
    when (updateValid && updateSCMeta.scUsed.asBool && updateIsBr) {
555 556
      val scPred = updateSCMeta.scPred
      val tageTaken = updateSCMeta.tageTaken
L
Lingrui98 已提交
557
      val sumAbs = updateSCMeta.sumAbs.asUInt
558 559
      val scOldCtrs = updateSCMeta.ctrs
      when (scPred =/= tageTaken && sumAbs < useThreshold - 2.U) {
L
Lingrui98 已提交
560 561 562
        val newThres = scThreshold.update(scPred =/= u.taken)
        scThreshold := newThres
        XSDebug(p"scThres update: old d${useThreshold} --> new ${newThres.thres}\n")
563 564 565
      }
      when (scPred =/= u.taken || sumAbs < updateThreshold) {
        scUpdateMask.foreach(t => t(updateBank) := true.B)
L
Lingrui98 已提交
566 567
        scUpdateTagePred := tageTaken
        scUpdateTaken := u.taken
568
        (scUpdateOldCtrs zip scOldCtrs).foreach{case (t, c) => t := c}
L
Lingrui98 已提交
569 570
        XSDebug(p"scUpdate: bank(${updateBank}), scPred(${scPred}), tageTaken(${tageTaken}), scSumAbs(${sumAbs}), mispred: sc(${updateMisPred}), tage(${updateTageMisPred})\n")
        XSDebug(p"update: sc: ${updateSCMeta}\n")
571 572 573 574
      }
    }
  }

L
Lingrui98 已提交
575 576 577 578 579 580 581 582 583 584 585
  for (i <- 0 until TageNTables) {
    for (w <- 0 until TageBanks) {
      tables(i).io.update.mask(w) := updateMask(i)(w)
      tables(i).io.update.taken(w) := updateTaken(i)(w)
      tables(i).io.update.alloc(w) := updateAlloc(i)(w)
      tables(i).io.update.oldCtr(w) := updateOldCtr(i)(w)

      tables(i).io.update.uMask(w) := updateUMask(i)(w)
      tables(i).io.update.u(w) := updateU(i)(w)
    }
    // use fetch pc instead of instruction pc
L
Lingrui98 已提交
586 587
    tables(i).io.update.pc := u.pc
    tables(i).io.update.hist := updateHist
588
    tables(i).io.update.fetchIdx := u.brInfo.fetchIdx
L
Lingrui98 已提交
589 590
  }

591
  for (i <- 0 until SCNTables) {
L
Lingrui98 已提交
592 593 594
    scTables(i).io.update.mask := scUpdateMask(i)
    scTables(i).io.update.tagePred := scUpdateTagePred
    scTables(i).io.update.taken    := scUpdateTaken
595 596 597 598 599 600
    scTables(i).io.update.oldCtr   := scUpdateOldCtrs(i)
    scTables(i).io.update.pc := u.pc
    scTables(i).io.update.hist := updateHist
    scTables(i).io.update.fetchIdx := u.brInfo.fetchIdx
  }

L
Lingrui98 已提交
601

L
Lingrui98 已提交
602

603
  if (BPUDebug && debug) {
L
Lingrui98 已提交
604 605 606 607 608 609 610
    val m = updateMeta
    val bri = u.brInfo
    XSDebug(io.pc.valid, "req: pc=0x%x, hist=%x\n", io.pc.bits, io.hist)
    XSDebug(io.s3Fire, "s3Fire:%d, resp: pc=%x, hist=%x\n", io.s3Fire, debug_pc_s2, debug_hist_s2)
    XSDebug(RegNext(io.s3Fire), "s3FireOnLastCycle: resp: pc=%x, hist=%x, hits=%b, takens=%b\n",
      debug_pc_s3, debug_hist_s3, io.resp.hits.asUInt, io.resp.takens.asUInt)
    for (i <- 0 until TageNTables) {
L
Lingrui98 已提交
611
      XSDebug(RegNext(io.s3Fire), "TageTable(%d): valids:%b, resp_ctrs:%b, resp_us:%b\n", i.U, VecInit(resps(i).map(_.valid)).asUInt, Cat(resps(i).map(_.bits.ctr)), Cat(resps(i).map(_.bits.u)))
L
Lingrui98 已提交
612 613 614
    }
    XSDebug(io.update.valid, "update: pc=%x, fetchpc=%x, cycle=%d, hist=%x, taken:%d, misPred:%d, histPtr:%d, bimctr:%d, pvdr(%d):%d, altDiff:%d, pvdrU:%d, pvdrCtr:%d, alloc(%d):%d\n",
      u.pc, u.pc - (bri.fetchIdx << 1.U), bri.debug_tage_cycle,  updateHist, u.taken, u.isMisPred, bri.histPtr, bri.bimCtr, m.provider.valid, m.provider.bits, m.altDiffers, m.providerU, m.providerCtr, m.allocate.valid, m.allocate.bits)
L
Lingrui98 已提交
615 616
    XSDebug(io.update.valid && updateIsBr, p"update: sc: ${updateSCMeta}\n")
    XSDebug(true.B, p"scThres: use(${useThreshold}), update(${updateThreshold})\n")
L
Lingrui98 已提交
617
  }
L
Lingrui98 已提交
618
}