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

import chisel3._
import chisel3.util._
import xiangshan._
import utils._
L
Lingrui98 已提交
7
import chisel3.experimental.chiselName
8 9 10 11
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import firrtl.stage.RunFirrtlTransformAnnotation
import firrtl.transforms.RenameModules
import freechips.rocketchip.transforms.naming.RenameDesiredNames
L
Lingrui98 已提交
12 13

import scala.math.min
L
Lingrui98 已提交
14
import scala.util.matching.Regex
L
Lingrui98 已提交
15

16
trait HasTageParameter extends HasXSParameter with HasBPUParameter with HasIFUConst {
L
Lingrui98 已提交
17 18 19 20 21 22 23
  //                   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 已提交
24 25 26 27 28 29
                      // (  64,   64,   11),
                      // (  64,  101,   12),
                      // (  64,  160,   12),
                      // (  64,  254,   13),
                      // (  32,  403,   14),
                      // (  32,  640,   15))
L
Lingrui98 已提交
30
  val TageNTables = TableInfo.size
31
  val UBitPeriod = 2048
L
Lingrui98 已提交
32
  val TageBanks = PredictWidth // FetchWidth
33
  val TageCtrBits = 3
L
Lingrui98 已提交
34

L
Lingrui98 已提交
35 36
  val TotalBits = TableInfo.map {
    case (s, h, t) => {
37
      s * (1+t+TageCtrBits) * PredictWidth
L
Lingrui98 已提交
38 39
    }
  }.reduce(_+_)
L
Lingrui98 已提交
40 41
}

L
Lingrui98 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54
trait HasFoldedHistory {
  val histLen: Int
  def compute_folded_hist(hist: UInt, l: Int) = {
    if (histLen > 0) {
      val nChunks = (histLen + l - 1) / l
      val hist_chunks = (0 until nChunks) map {i =>
        hist(min((i+1)*l, histLen)-1, i*l)
      }
      ParallelXOR(hist_chunks)
    }
    else 0.U
  }
}
L
Lingrui98 已提交
55

L
Lingrui98 已提交
56 57 58 59 60 61 62
abstract class TageBundle extends XSBundle
  with HasIFUConst with HasTageParameter
  with PredictorUtils
abstract class TageModule extends XSModule
  with HasIFUConst with HasTageParameter
  with PredictorUtils
  { val debug = true }
L
Lingrui98 已提交
63 64


L
Lingrui98 已提交
65
class TageReq extends TageBundle {
L
Lingrui98 已提交
66 67 68
  val pc = UInt(VAddrBits.W)
  val hist = UInt(HistoryLength.W)
  val mask = UInt(PredictWidth.W)
L
Lingrui98 已提交
69 70 71
}

class TageResp extends TageBundle {
72
  val ctr = UInt(TageCtrBits.W)
L
Lingrui98 已提交
73
  val u = UInt(2.W)
L
Lingrui98 已提交
74 75 76
}

class TageUpdate extends TageBundle {
L
Lingrui98 已提交
77 78 79 80 81 82
  val pc = UInt(VAddrBits.W)
  val hist = UInt(HistoryLength.W)
  // update tag and ctr
  val mask = Vec(TageBanks, Bool())
  val taken = Vec(TageBanks, Bool())
  val alloc = Vec(TageBanks, Bool())
83
  val oldCtr = Vec(TageBanks, UInt(TageCtrBits.W))
L
Lingrui98 已提交
84 85 86
  // update u
  val uMask = Vec(TageBanks, Bool())
  val u = Vec(TageBanks, UInt(2.W))
L
Lingrui98 已提交
87 88 89
}

class FakeTageTable() extends TageModule {
L
Lingrui98 已提交
90 91 92 93 94 95
  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 已提交
96 97

}
L
Lingrui98 已提交
98
@chiselName
L
Lingrui98 已提交
99 100
class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPeriod: Int)
  extends TageModule with HasFoldedHistory {
L
Lingrui98 已提交
101 102 103 104 105
  val io = IO(new Bundle() {
    val req = Input(Valid(new TageReq))
    val resp = Output(Vec(TageBanks, Valid(new TageResp)))
    val update = Input(new TageUpdate)
  })
106
  // override val debug = true
L
Lingrui98 已提交
107
  // bypass entries for tage update
L
Lingrui98 已提交
108
  val wrBypassEntries = 4
L
Lingrui98 已提交
109 110 111 112 113 114 115 116 117 118

  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)
  }

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

L
Lingrui98 已提交
121 122 123
  class TageEntry() extends TageBundle {
    val valid = Bool()
    val tag = UInt(tagLen.W)
124
    val ctr = UInt(TageCtrBits.W)
L
Lingrui98 已提交
125 126
  }

127
  val tageEntrySz = instOffsetBits + tagLen + TageCtrBits
L
Lingrui98 已提交
128

129 130 131 132 133
  def getUnhashedIdx(pc: UInt) = pc >> (instOffsetBits+log2Ceil(TageBanks))

  val if2_packetAlignedPC = packetAligned(io.req.bits.pc)
  val if2_unhashed_idx = getUnhashedIdx(io.req.bits.pc)

134 135
  val (if2_idx, if2_tag) = compute_tag_and_hash(if2_unhashed_idx, io.req.bits.hist)
  val (if3_idx, if3_tag) = (RegEnable(if2_idx, io.req.valid), RegEnable(if2_tag, io.req.valid))
L
Lingrui98 已提交
136

137 138 139
  val hi_us = Module(new SRAMTemplate(Bool(), set=nRows, way=TageBanks, shouldReset=true, holdRead=true, singlePort=false))
  val lo_us = Module(new SRAMTemplate(Bool(), set=nRows, way=TageBanks, shouldReset=true, holdRead=true, singlePort=false))
  val table = Module(new SRAMTemplate(new TageEntry, set=nRows, way=TageBanks, shouldReset=true, holdRead=true, singlePort=false))
L
Lingrui98 已提交
140 141 142 143 144 145 146 147 148 149 150

  table.io.r.req.valid := io.req.valid
  hi_us.io.r.req.valid := io.req.valid
  lo_us.io.r.req.valid := io.req.valid
  table.io.r.req.bits.setIdx := if2_idx
  hi_us.io.r.req.bits.setIdx := if2_idx
  lo_us.io.r.req.bits.setIdx := if2_idx

  val if3_hi_us_r = hi_us.io.r.resp.data
  val if3_lo_us_r = lo_us.io.r.resp.data
  val if3_table_r = table.io.r.resp.data
L
Lingrui98 已提交
151

152 153
  val if2_mask = io.req.bits.mask
  val if3_mask = RegEnable(if2_mask, enable=io.req.valid)
L
Lingrui98 已提交
154

155
  val if3_req_rhits = VecInit((0 until TageBanks).map(b => {
156
    if3_table_r(b).valid && if3_table_r(b).tag === if3_tag
L
Lingrui98 已提交
157 158
  }))
  
L
Lingrui98 已提交
159
  (0 until TageBanks).map(b => {
160 161 162
    io.resp(b).valid := if3_req_rhits(b) && if3_mask(b)
    io.resp(b).bits.ctr := if3_table_r(b).ctr
    io.resp(b).bits.u := Cat(if3_hi_us_r(b),if3_lo_us_r(b))
L
Lingrui98 已提交
163 164 165 166
  })


  val clear_u_ctr = RegInit(0.U((log2Ceil(uBitPeriod) + log2Ceil(nRows) + 1).W))
167
  clear_u_ctr := clear_u_ctr + 1.U
L
Lingrui98 已提交
168 169 170 171 172 173

  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)

174
  // Use fetchpc to compute hash
175
  val (update_idx, update_tag) = compute_tag_and_hash(getUnhashedIdx(io.update.pc), io.update.hist)
L
Lingrui98 已提交
176 177 178

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

L
Lingrui98 已提交
179
  table.io.w.apply(
180
    valid = io.update.mask.asUInt.orR,
181 182
    data = update_wdata,
    setIdx = update_idx,
L
Lingrui98 已提交
183 184
    waymask = io.update.mask.asUInt
  )
L
Lingrui98 已提交
185 186

  val update_hi_wdata = Wire(Vec(TageBanks, Bool()))
L
Lingrui98 已提交
187
  hi_us.io.w.apply(
188 189 190 191
    valid = io.update.uMask.asUInt.orR || doing_clear_u_hi,
    data = Mux(doing_clear_u_hi, 0.U.asTypeOf(Vec(TageBanks, Bool())), update_hi_wdata),
    setIdx = Mux(doing_clear_u_hi, clear_u_idx, update_idx),
    waymask = Mux(doing_clear_u_hi, Fill(TageBanks, "b1".U), io.update.uMask.asUInt)
L
Lingrui98 已提交
192
  )
L
Lingrui98 已提交
193 194

  val update_lo_wdata = Wire(Vec(TageBanks, Bool()))
L
Lingrui98 已提交
195
  lo_us.io.w.apply(
196 197 198 199
    valid = io.update.uMask.asUInt.orR || doing_clear_u_lo,
    data = Mux(doing_clear_u_lo, 0.U.asTypeOf(Vec(TageBanks, Bool())), update_lo_wdata),
    setIdx = Mux(doing_clear_u_lo, clear_u_idx, update_idx),
    waymask = Mux(doing_clear_u_lo, Fill(TageBanks, "b1".U), io.update.uMask.asUInt)
L
Lingrui98 已提交
200
  )
L
Lingrui98 已提交
201

J
Jay 已提交
202 203 204 205
  val wrbypass_tags    = RegInit(0.U.asTypeOf(Vec(wrBypassEntries, UInt(tagLen.W))))
  val wrbypass_idxs    = RegInit(0.U.asTypeOf(Vec(wrBypassEntries, UInt(log2Ceil(nRows).W))))
  val wrbypass_ctrs    = RegInit(0.U.asTypeOf(Vec(wrBypassEntries, Vec(TageBanks, UInt(TageCtrBits.W)))))
  val wrbypass_ctr_valids = RegInit(0.U.asTypeOf(Vec(wrBypassEntries, Vec(TageBanks, Bool()))))
L
Lingrui98 已提交
206 207
  val wrbypass_enq_idx = RegInit(0.U(log2Ceil(wrBypassEntries).W))

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

L
Lingrui98 已提交
210 211 212 213
  val wrbypass_hits    = VecInit((0 until wrBypassEntries) map { i =>
    wrbypass_tags(i) === update_tag &&
    wrbypass_idxs(i) === update_idx
  })
214 215


216
  val wrbypass_hit      = wrbypass_hits.reduce(_||_)
L
Lingrui98 已提交
217
  // val wrbypass_rhit     = wrbypass_rhits.reduce(_||_)
218
  val wrbypass_hit_idx  = ParallelPriorityEncoder(wrbypass_hits)
L
Lingrui98 已提交
219
  // val wrbypass_rhit_idx = PriorityEncoder(wrbypass_rhits)
220

L
Lingrui98 已提交
221
  // val wrbypass_rctr_hits = VecInit((0 until TageBanks).map( b => wrbypass_ctr_valids(wrbypass_rhit_idx)(b)))
222

L
Lingrui98 已提交
223
  // val rhit_ctrs = RegEnable(wrbypass_ctrs(wrbypass_rhit_idx), wrbypass_rhit)
224

L
Lingrui98 已提交
225 226 227
  // when (RegNext(wrbypass_rhit)) {
  //   for (b <- 0 until TageBanks) {
  //     when (RegNext(wrbypass_rctr_hits(b.U + baseBank))) {
228
  //       io.resp(b).bits.ctr := rhit_ctrs(if3_bankIdxInOrder(b))
L
Lingrui98 已提交
229 230 231
  //     }
  //   }
  // }
232 233


L
Lingrui98 已提交
234
  val updateBank = PriorityEncoder(io.update.mask)
L
Lingrui98 已提交
235 236 237 238 239 240

  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 已提交
241 242 243 244
      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 已提交
245 246 247 248 249 250 251
    )
    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)

252 253 254 255 256 257 258 259 260 261 262 263 264 265
    when (io.update.mask.reduce(_||_)) {
      when (wrbypass_hit) {
        when (io.update.mask(w)) {
          wrbypass_ctrs(wrbypass_hit_idx)(w) := update_wdata(w).ctr
          wrbypass_ctr_valids(wrbypass_hit_idx)(w) := true.B
        }
      } .otherwise {
        // reset valid bit first
        wrbypass_ctr_valids(wrbypass_enq_idx)(w) := false.B
        when (io.update.mask(w)) {
          wrbypass_ctr_valids(wrbypass_enq_idx)(w) := true.B
          wrbypass_ctrs(wrbypass_enq_idx)(w) := update_wdata(w).ctr
        }
      }
L
Lingrui98 已提交
266 267
    }
  }
S
Steve Gou 已提交
268
  
269
  when (io.update.mask.reduce(_||_) && !wrbypass_hit) {
S
Steve Gou 已提交
270 271
    wrbypass_tags(wrbypass_enq_idx) := update_tag
    wrbypass_idxs(wrbypass_enq_idx) := update_idx
272 273 274 275
    wrbypass_enq_idx := (wrbypass_enq_idx + 1.U)(log2Ceil(wrBypassEntries)-1,0)
  }


276
  if (BPUDebug && debug) {
L
Lingrui98 已提交
277 278 279
    val u = io.update
    val b = PriorityEncoder(u.mask)
    val ub = PriorityEncoder(u.uMask)
280 281
    val idx = if2_idx
    val tag = if2_tag
282 283 284 285
    XSDebug(io.req.valid, 
      p"tableReq: pc=0x${Hexadecimal(io.req.bits.pc)}, " +
      p"hist=${Hexadecimal(io.req.bits.hist)}, idx=$idx, " +
      p"tag=$tag, mask=${Binary(if2_mask)}\n")
L
Lingrui98 已提交
286
    for (i <- 0 until TageBanks) {
287 288 289 290 291 292 293 294 295 296 297 298 299
      XSDebug(RegNext(io.req.valid && io.req.bits.mask(i)) && if3_req_rhits(i),
        p"TageTableResp[$i]: idx=$if3_idx, hit:${if3_req_rhits(i)}, " +
        p"ctr:${io.resp(i).bits.ctr}, u:${io.resp(i).bits.u}\n")
      XSDebug(io.update.mask(i),
        p"update Table bank $i: pc:${Hexadecimal(u.pc)}, hist:${Hexadecimal(u.hist)}, " +
        p"taken:${u.taken(i)}, alloc:${u.alloc(i)}, oldCtr:${u.oldCtr(i)}\n")
      XSDebug(io.update.mask(i),
        p"update Table bank $i: writing tag:${update_tag}, " +
        p"ctr: ${update_wdata(b).ctr} in idx $update_idx\n")
      val hitCtr = wrbypass_ctrs(wrbypass_hit_idx)(i)
      XSDebug(wrbypass_hit && wrbypass_ctr_valids(wrbypass_hit_idx)(i) && io.update.mask(i),
        p"bank $i wrbypass hit wridx:$wrbypass_hit_idx, idx:$update_idx, tag: $update_tag, " +
        p"ctr:$hitCtr, newCtr:${update_wdata(i).ctr}")
L
Lingrui98 已提交
300
    }
301

302
    XSDebug(RegNext(io.req.valid) && !if3_req_rhits.reduce(_||_), "TageTableResp: no hits!\n")
L
Lingrui98 已提交
303

L
Lingrui98 已提交
304 305 306 307 308 309 310
    // 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)
    //   }
    // }
311

L
Lingrui98 已提交
312 313 314 315 316 317 318
    // ------------------------------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 已提交
319

L
Lingrui98 已提交
320 321
}

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

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

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

L
Lingrui98 已提交
347
@chiselName
348
class Tage extends BaseTage {
L
Lingrui98 已提交
349 350

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

360
  override val debug = true
361

L
Lingrui98 已提交
362
  // Keep the table responses to process in s3
L
Lingrui98 已提交
363 364
  // val if4_resps = RegEnable(VecInit(tables.map(t => t.io.resp)), enable=s3_fire)
  // val if4_scResps = RegEnable(VecInit(scTables.map(t => t.io.resp)), enable=s3_fire)
L
Lingrui98 已提交
365 366
  
  val if3_resps = VecInit(tables.map(t => t.io.resp))
L
Lingrui98 已提交
367

L
Lingrui98 已提交
368

L
Lingrui98 已提交
369
  val if3_bim = RegEnable(io.bim, enable=io.pc.valid) // actually it is s2Fire
L
Lingrui98 已提交
370
  val if4_bim = RegEnable(if3_bim, enable=s3_fire)
L
Lingrui98 已提交
371 372

  val debug_pc_s2 = RegEnable(io.pc.bits, enable=io.pc.valid)
L
Lingrui98 已提交
373
  val debug_pc_s3 = RegEnable(debug_pc_s2, enable=s3_fire)
L
Lingrui98 已提交
374

375
  val debug_hist_s2 = RegEnable(io.hist, enable=io.pc.valid)
L
Lingrui98 已提交
376
  val debug_hist_s3 = RegEnable(debug_hist_s2, enable=s3_fire)
377

L
Lingrui98 已提交
378
  val u = io.update.bits
L
Lingrui98 已提交
379 380
  val updateValids = u.valids.map(v => v && io.update.valid)
  val updateHist = u.predHist.asUInt
L
Lingrui98 已提交
381

L
Lingrui98 已提交
382 383 384
  val updateBrMask = u.br_mask
  val updateMetas = VecInit(u.metas.map(_.tageMeta))
  val updateMisPred = u.mispred
L
Lingrui98 已提交
385 386 387 388 389

  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())))
390
  val updateOldCtr = Wire(Vec(TageNTables, Vec(TageBanks, UInt(TageCtrBits.W))))
L
Lingrui98 已提交
391 392 393 394 395 396
  val updateU = Wire(Vec(TageNTables, Vec(TageBanks, UInt(2.W))))
  updateTaken := DontCare
  updateAlloc := DontCare
  updateOldCtr := DontCare
  updateU := DontCare

L
Lingrui98 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410
  val if3_tageTakens = Wire(Vec(TageBanks, Bool()))
  val if3_provideds = Wire(Vec(TageBanks, Bool()))
  val if3_providers = Wire(Vec(TageBanks, UInt(log2Ceil(TageBanks).W)))
  val if3_finalAltPreds = Wire(Vec(TageBanks, Bool()))
  val if3_providerUs = Wire(Vec(TageBanks, UInt(2.W)))
  val if3_providerCtrs = Wire(Vec(TageBanks, UInt(3.W)))

  val if4_tageTakens = RegEnable(if3_tageTakens, s3_fire)
  val if4_provideds = RegEnable(if3_provideds, s3_fire)
  val if4_providers = RegEnable(if3_providers, s3_fire)
  val if4_finalAltPreds = RegEnable(if3_finalAltPreds, s3_fire)
  val if4_providerUs = RegEnable(if3_providerUs, s3_fire)
  val if4_providerCtrs = RegEnable(if3_providerCtrs, s3_fire)

411

L
Lingrui98 已提交
412
  val updateTageMisPreds = VecInit((0 until PredictWidth).map(i => updateMetas(i).taken =/= u.takens(i) && updateBrMask(i)))
413

L
Lingrui98 已提交
414
  // val updateBank = u.pc(log2Ceil(TageBanks)+instOffsetBits-1, instOffsetBits)
L
Lingrui98 已提交
415 416 417

  // access tag tables and output meta info
  for (w <- 0 until TageBanks) {
L
Lingrui98 已提交
418 419 420 421 422
    val if3_tageTaken = WireInit(if3_bim.ctrs(w)(1).asBool)
    var if3_altPred = if3_bim.ctrs(w)(1)
    val if3_finalAltPred = WireInit(if3_bim.ctrs(w)(1))
    var if3_provided = false.B
    var if3_provider = 0.U
L
Lingrui98 已提交
423 424

    for (i <- 0 until TageNTables) {
L
Lingrui98 已提交
425 426
      val hit = if3_resps(i)(w).valid
      val ctr = if3_resps(i)(w).bits.ctr
L
Lingrui98 已提交
427
      when (hit) {
L
Lingrui98 已提交
428 429
        if3_tageTaken := Mux(ctr === 3.U || ctr === 4.U, if3_altPred, ctr(2)) // Use altpred on weak taken
        if3_finalAltPred := if3_altPred
L
Lingrui98 已提交
430
      }
L
Lingrui98 已提交
431 432 433
      if3_provided = if3_provided || hit          // Once hit then provide
      if3_provider = Mux(hit, i.U, if3_provider)  // Use the last hit as provider
      if3_altPred = Mux(hit, ctr(2), if3_altPred) // Save current pred as potential altpred
L
Lingrui98 已提交
434
    }
L
Lingrui98 已提交
435 436 437 438 439 440 441
    if3_provideds(w) := if3_provided
    if3_providers(w) := if3_provider
    if3_finalAltPreds(w) := if3_finalAltPred
    if3_tageTakens(w) := if3_tageTaken
    if3_providerUs(w) := if3_resps(if3_provider)(w).bits.u
    if3_providerCtrs(w) := if3_resps(if3_provider)(w).bits.ctr

442 443
    io.resp.hits(w) := if4_provideds(w) && ctrl.tage_enable
    io.resp.takens(w) := if4_tageTakens(w) && ctrl.tage_enable
L
Lingrui98 已提交
444
    io.meta(w) := DontCare
L
Lingrui98 已提交
445 446 447 448 449 450
    io.meta(w).provider.valid := if4_provideds(w)
    io.meta(w).provider.bits := if4_providers(w)
    io.meta(w).altDiffers := if4_finalAltPreds(w) =/= io.resp.takens(w)
    io.meta(w).providerU := if4_providerUs(w)
    io.meta(w).providerCtr := if4_providerCtrs(w)
    io.meta(w).taken := if4_tageTakens(w)
L
Lingrui98 已提交
451 452 453

    // 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
L
Lingrui98 已提交
454
    val allocatableSlots = RegEnable(VecInit(if3_resps.map(r => !r(w).valid && r(w).bits.u === 0.U)).asUInt &
L
Lingrui98 已提交
455
      ~(LowerMask(UIntToOH(if3_provider), TageNTables) & Fill(TageNTables, if3_provided.asUInt)), s3_fire
L
Lingrui98 已提交
456 457 458 459 460 461 462 463
    )
    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

L
Lingrui98 已提交
464 465 466 467 468 469
    val updateValid = updateValids(w)
    val updateMeta = updateMetas(w)
    val updateIsBr = updateBrMask(w)
    val isUpdateTaken = updateValid && u.takens(w) && updateIsBr
    val updateMisPred = updateTageMisPreds(w)
    when (updateValid && updateIsBr) {
L
Lingrui98 已提交
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
      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 已提交
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
    when (updateValid && updateMisPred) {
      val allocate = updateMeta.allocate
      when (allocate.valid) {
        updateMask(allocate.bits)(w) := true.B
        updateTaken(allocate.bits)(w) := isUpdateTaken
        updateAlloc(allocate.bits)(w) := true.B
        updateUMask(allocate.bits)(w) := true.B
        updateU(allocate.bits)(w) := 0.U
      }.otherwise {
        val provider = updateMeta.provider
        val decrMask = Mux(provider.valid, ~LowerMask(UIntToOH(provider.bits), TageNTables), 0.U(TageNTables.W))
        for (i <- 0 until TageNTables) {
          when (decrMask(i)) {
            updateUMask(i)(w) := true.B
            updateU(i)(w) := 0.U
          }
L
Lingrui98 已提交
501 502 503 504 505 506 507
        }
      }
    }
  }

  for (i <- 0 until TageNTables) {
    for (w <- 0 until TageBanks) {
L
Lingrui98 已提交
508 509 510 511 512 513 514 515
      tables(i).io.update.mask(w) := RegNext(updateMask(i)(w))
      tables(i).io.update.taken(w) := RegNext(updateTaken(i)(w))
      tables(i).io.update.alloc(w) := RegNext(updateAlloc(i)(w))
      tables(i).io.update.oldCtr(w) := RegNext(updateOldCtr(i)(w))

      tables(i).io.update.uMask(w) := RegNext(updateUMask(i)(w))
      tables(i).io.update.u(w) := RegNext(updateU(i)(w))
      tables(i).io.update.pc := RegNext(packetAligned(u.ftqPC) + (w << instOffsetBits).U)
L
Lingrui98 已提交
516 517
    }
    // use fetch pc instead of instruction pc
L
Lingrui98 已提交
518
    tables(i).io.update.hist := RegNext(updateHist)
L
Lingrui98 已提交
519 520
  }

L
Lingrui98 已提交
521

522
  if (BPUDebug && debug) {
L
Lingrui98 已提交
523 524 525 526 527 528 529 530
    for (b <- 0 until TageBanks) {
      val m = updateMetas(b)
      val bri = u.metas(b)
      XSDebug(updateValids(b), "update(%d): pc=%x, fetchpc=%x, cycle=%d, hist=%x, taken:%d, misPred:%d, bimctr:%d, pvdr(%d):%d, altDiff:%d, pvdrU:%d, pvdrCtr:%d, alloc(%d):%d\n",
        b.U, u.ftqPC, packetAligned(u.ftqPC)+(b << instOffsetBits).U, bri.debug_tage_cycle, updateHist, u.takens(b), u.mispred(b),
        bri.bimCtr, m.provider.valid, m.provider.bits, m.altDiffers, m.providerU, m.providerCtr, m.allocate.valid, m.allocate.bits
      )
    }
L
Lingrui98 已提交
531
    val if4_resps = RegEnable(if3_resps, s3_fire)
L
Lingrui98 已提交
532
    XSDebug(io.pc.valid, "req: pc=0x%x, hist=%x\n", io.pc.bits, io.hist)
L
Lingrui98 已提交
533 534
    XSDebug(s3_fire, "s3Fire:%d, resp: pc=%x, hist=%x\n", s3_fire, debug_pc_s2, debug_hist_s2)
    XSDebug(RegNext(s3_fire), "s3FireOnLastCycle: resp: pc=%x, hist=%x, hits=%b, takens=%b\n",
L
Lingrui98 已提交
535 536
      debug_pc_s3, debug_hist_s3, io.resp.hits.asUInt, io.resp.takens.asUInt)
    for (i <- 0 until TageNTables) {
L
Lingrui98 已提交
537
      XSDebug(RegNext(s3_fire), "TageTable(%d): valids:%b, resp_ctrs:%b, resp_us:%b\n", i.U, VecInit(if4_resps(i).map(_.valid)).asUInt, Cat(if4_resps(i).map(_.bits.ctr)), Cat(if4_resps(i).map(_.bits.u)))
L
Lingrui98 已提交
538
    }
L
Lingrui98 已提交
539 540
    // XSDebug(io.update.valid && updateIsBr, p"update: sc: ${updateSCMeta}\n")
    // XSDebug(true.B, p"scThres: use(${useThreshold}), update(${updateThreshold})\n")
L
Lingrui98 已提交
541
  }
542 543
}

L
Lingrui98 已提交
544 545 546

class Tage_SC extends Tage with HasSC {}

547 548 549 550 551 552 553
object TageTest extends App {
  override def main(args: Array[String]): Unit = {
    (new ChiselStage).execute(args, Seq(
      ChiselGeneratorAnnotation(() => new Tage),
      RunFirrtlTransformAnnotation(new RenameDesiredNames)
    ))
  }
L
Lingrui98 已提交
554
}