Tage.scala 26.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 34 35 36 37 38
  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 已提交
39 40
  val TotalBits = TableInfo.map {
    case (s, h, t) => {
41
      s * (1+t+TageCtrBits) * PredictWidth
L
Lingrui98 已提交
42 43
    }
  }.reduce(_+_)
L
Lingrui98 已提交
44 45
}

46
abstract class TageBundle extends XSBundle with HasTageParameter with PredictorUtils
47
abstract class TageModule extends XSModule with HasTageParameter with PredictorUtils { val debug = true }
L
Lingrui98 已提交
48

L
Lingrui98 已提交
49 50 51



L
Lingrui98 已提交
52
class TageReq extends TageBundle {
L
Lingrui98 已提交
53 54 55
  val pc = UInt(VAddrBits.W)
  val hist = UInt(HistoryLength.W)
  val mask = UInt(PredictWidth.W)
L
Lingrui98 已提交
56 57 58
}

class TageResp extends TageBundle {
59
  val ctr = UInt(TageCtrBits.W)
L
Lingrui98 已提交
60
  val u = UInt(2.W)
L
Lingrui98 已提交
61 62 63
}

class TageUpdate extends TageBundle {
L
Lingrui98 已提交
64 65 66 67 68 69
  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())
70
  val oldCtr = Vec(TageBanks, UInt(TageCtrBits.W))
L
Lingrui98 已提交
71 72 73
  // update u
  val uMask = Vec(TageBanks, Bool())
  val u = Vec(TageBanks, UInt(2.W))
L
Lingrui98 已提交
74 75 76
}

class FakeTageTable() extends TageModule {
L
Lingrui98 已提交
77 78 79 80 81 82
  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 已提交
83 84

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

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

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

L
Lingrui98 已提交
115 116 117 118 119 120 121 122
  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)
123
    val ctr = UInt(TageCtrBits.W)
L
Lingrui98 已提交
124 125
  }

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

128 129 130 131 132
  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)

133 134
  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 已提交
135

L
Lingrui98 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
  class HL_Bank (val nRows: Int = nRows) extends TageModule {
    val io = IO(new Bundle {
      val r = new Bundle {
        val req = Flipped(ValidIO(new Bundle {
          val setIdx = UInt(log2Ceil(nRows).W)
        }))
        val resp = new Bundle {
          val data = Output(Bool())
        }
      }
      val w = new Bundle {
        val req = Flipped(ValidIO(new Bundle {
          val setIdx = UInt(log2Ceil(nRows).W)
          val data = Bool()
        }))
      }
    })

    val mem = Mem(nRows, Bool())
    // 1-cycle latency just as SyncReadMem
    io.r.resp.data := RegEnable(mem.read(io.r.req.bits.setIdx), enable=io.r.req.valid)
    when (io.w.req.valid) {
      mem.write(io.w.req.bits.setIdx, io.w.req.bits.data)
    }
  }

  val hi_us = List.fill(TageBanks)(Module(new HL_Bank(nRows)))
  val lo_us = List.fill(TageBanks)(Module(new HL_Bank(nRows)))
164
  val table = List.fill(TageBanks)(Module(new SRAMTemplate(new TageEntry, set=nRows, shouldReset=false, holdRead=true, singlePort=false)))
L
Lingrui98 已提交
165

166 167 168
  val if3_hi_us_r = WireInit(0.U.asTypeOf(Vec(TageBanks, Bool())))
  val if3_lo_us_r = WireInit(0.U.asTypeOf(Vec(TageBanks, Bool())))
  val if3_table_r = WireInit(0.U.asTypeOf(Vec(TageBanks, new TageEntry)))
L
Lingrui98 已提交
169

170 171
  val if2_mask = io.req.bits.mask
  val if3_mask = RegEnable(if2_mask, enable=io.req.valid)
L
Lingrui98 已提交
172

L
Lingrui98 已提交
173 174


L
Lingrui98 已提交
175 176
  (0 until TageBanks).map(
    b => {
177
      hi_us(b).io.r.req.valid := io.req.valid && if2_mask(b)
178
      hi_us(b).io.r.req.bits.setIdx := if2_idx
L
Lingrui98 已提交
179

180
      lo_us(b).io.r.req.valid := io.req.valid && if2_mask(b)
181
      lo_us(b).io.r.req.bits.setIdx := if2_idx
L
Lingrui98 已提交
182 183

      table(b).reset := reset.asBool
184
      table(b).io.r.req.valid := io.req.valid && if2_mask(b)
185
      table(b).io.r.req.bits.setIdx := if2_idx
L
Lingrui98 已提交
186

187 188 189
      if3_hi_us_r(b) := hi_us(b).io.r.resp.data
      if3_lo_us_r(b) := lo_us(b).io.r.resp.data
      if3_table_r(b) := table(b).io.r.resp.data(0)
L
Lingrui98 已提交
190 191 192
    }
  )

193
  val if3_req_rhits = VecInit((0 until TageBanks).map(b => {
194
    if3_table_r(b).valid && if3_table_r(b).tag === if3_tag
L
Lingrui98 已提交
195 196
  }))
  
L
Lingrui98 已提交
197
  (0 until TageBanks).map(b => {
198 199 200
    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 已提交
201 202 203 204 205 206 207 208 209 210 211
  })


  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)

212
  // Use fetchpc to compute hash
213
  val (update_idx, update_tag) = compute_tag_and_hash(getUnhashedIdx(io.update.pc), io.update.hist)
L
Lingrui98 已提交
214 215 216 217 218 219 220

  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)
221
    table(b).io.w.req.bits.data := VecInit(Mux(doing_reset, 0.U.asTypeOf(new TageEntry), update_wdata(b)))
L
Lingrui98 已提交
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
  })

  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)))
240
  val wrbypass_ctrs    = Reg(Vec(wrBypassEntries, Vec(TageBanks, UInt(TageCtrBits.W))))
L
Lingrui98 已提交
241
  val wrbypass_ctr_valids = Reg(Vec(wrBypassEntries, Vec(TageBanks, Bool())))
L
Lingrui98 已提交
242 243
  val wrbypass_enq_idx = RegInit(0.U(log2Ceil(wrBypassEntries).W))

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

L
Lingrui98 已提交
246 247 248 249 250
  val wrbypass_hits    = VecInit((0 until wrBypassEntries) map { i =>
    !doing_reset &&
    wrbypass_tags(i) === update_tag &&
    wrbypass_idxs(i) === update_idx
  })
251 252


253
  val wrbypass_hit      = wrbypass_hits.reduce(_||_)
L
Lingrui98 已提交
254
  // val wrbypass_rhit     = wrbypass_rhits.reduce(_||_)
255
  val wrbypass_hit_idx  = PriorityEncoder(wrbypass_hits)
L
Lingrui98 已提交
256
  // val wrbypass_rhit_idx = PriorityEncoder(wrbypass_rhits)
257

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

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

L
Lingrui98 已提交
262 263 264
  // when (RegNext(wrbypass_rhit)) {
  //   for (b <- 0 until TageBanks) {
  //     when (RegNext(wrbypass_rctr_hits(b.U + baseBank))) {
265
  //       io.resp(b).bits.ctr := rhit_ctrs(if3_bankIdxInOrder(b))
L
Lingrui98 已提交
266 267 268
  //     }
  //   }
  // }
269 270


L
Lingrui98 已提交
271
  val updateBank = PriorityEncoder(io.update.mask)
L
Lingrui98 已提交
272 273 274 275 276 277

  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 已提交
278 279 280 281
      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 已提交
282 283 284 285 286 287 288 289 290 291
    )
    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 已提交
292
      wrbypass_ctrs(wrbypass_hit_idx)(updateBank) := update_wdata(updateBank).ctr
293
      wrbypass_ctr_valids(wrbypass_hit_idx)(updateBank) := true.B
L
Lingrui98 已提交
294
    } .otherwise {
L
Lingrui98 已提交
295
      wrbypass_ctrs(wrbypass_enq_idx)(updateBank) := update_wdata(updateBank).ctr
296
      (0 until TageBanks).foreach(b => wrbypass_ctr_valids(wrbypass_enq_idx)(b) := false.B) // reset valid bits
L
Lingrui98 已提交
297
      wrbypass_ctr_valids(wrbypass_enq_idx)(updateBank) := true.B
L
Lingrui98 已提交
298 299 300 301 302
      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)
    }
  }
303

304
  if (BPUDebug && debug) {
L
Lingrui98 已提交
305 306 307
    val u = io.update
    val b = PriorityEncoder(u.mask)
    val ub = PriorityEncoder(u.uMask)
308 309 310 311
    val idx = if2_idx
    val tag = if2_tag
    XSDebug(io.req.valid, "tableReq: pc=0x%x, hist=%x, idx=%d, tag=%x, mask=%b, mask=%b\n",
      io.req.bits.pc, io.req.bits.hist, idx, tag, io.req.bits.mask, if2_mask)
L
Lingrui98 已提交
312
    for (i <- 0 until TageBanks) {
313 314
      XSDebug(RegNext(io.req.valid) && if3_req_rhits(i), "TageTableResp[%d]: idx=%d, hit:%d, ctr:%d, u:%d\n",
        i.U, if3_idx, if3_req_rhits(i), io.resp(i).bits.ctr, io.resp(i).bits.u)
L
Lingrui98 已提交
315
    }
316

317
    XSDebug(RegNext(io.req.valid), "TageTableResp: hits:%b, maskLatch is %b\n", if3_req_rhits.asUInt, if3_mask)
318
    XSDebug(RegNext(io.req.valid) && !if3_req_rhits.reduce(_||_), "TageTableResp: no hits!\n")
L
Lingrui98 已提交
319

L
Lingrui98 已提交
320 321
    XSDebug(io.update.mask.reduce(_||_), "update Table: pc:%x, hist:%x, bank:%d, taken:%d, alloc:%d, oldCtr:%d\n",
      u.pc, u.hist, b, u.taken(b), u.alloc(b), u.oldCtr(b))
L
Lingrui98 已提交
322 323
    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)
L
Lingrui98 已提交
324 325
    XSDebug(io.update.mask.reduce(_||_), "update u: pc:%x, hist:%x, bank:%d, writing in u:%b\n",
      u.pc, u.hist, ub, io.update.u(ub))
L
Lingrui98 已提交
326

327 328 329 330 331
    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)

L
Lingrui98 已提交
332 333 334 335 336 337 338
    // 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)
    //   }
    // }
339

L
Lingrui98 已提交
340 341 342 343 344 345 346
    // ------------------------------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 已提交
347

L
Lingrui98 已提交
348 349
}

350
abstract class BaseTage extends BasePredictor with HasTageParameter {
L
Lingrui98 已提交
351
  class TAGEResp extends Resp {
352 353
    val takens = Vec(PredictWidth, Bool())
    val hits = Vec(PredictWidth, Bool())
L
Lingrui98 已提交
354
  }
355
  class TAGEMeta extends Meta{
L
Lingrui98 已提交
356 357 358 359 360 361
  }
  class FromBIM extends FromOthers {
    val ctrs = Vec(PredictWidth, UInt(2.W))
  }
  class TageIO extends DefaultBasePredictorIO {
    val resp = Output(new TAGEResp)
L
Lingrui98 已提交
362
    val meta = Output(Vec(PredictWidth, new TageMeta))
L
Lingrui98 已提交
363 364 365 366
    val bim = Input(new FromBIM)
    val s3Fire = Input(Bool())
  }

L
Lingrui98 已提交
367
  override val io = IO(new TageIO)
368
}
L
Lingrui98 已提交
369

370
class FakeTage extends BaseTage {
L
Lingrui98 已提交
371 372
  io.resp <> DontCare
  io.meta <> DontCare
L
Lingrui98 已提交
373 374
}

L
Lingrui98 已提交
375
@chiselName
376
class Tage extends BaseTage {
L
Lingrui98 已提交
377 378

  val tables = TableInfo.map {
379
    case (nRows, histLen, tagLen) =>
L
Lingrui98 已提交
380
      val t = if(EnableBPD) Module(new TageTable(nRows, histLen, tagLen, UBitPeriod)) else Module(new FakeTageTable)
L
Lingrui98 已提交
381
      t.io.req.valid := io.pc.valid
L
Lingrui98 已提交
382 383 384 385 386 387
      t.io.req.bits.pc := io.pc.bits
      t.io.req.bits.hist := io.hist
      t.io.req.bits.mask := io.inMask
      t
  }

388 389
  val scTables = SCTableInfo.map {
    case (nRows, ctrBits, histLen) => {
L
Lingrui98 已提交
390
      val t = if (EnableSC) Module(new SCTable(nRows/TageBanks, ctrBits, histLen)) else Module(new FakeSCTable)
391
      val req = t.io.req
L
Lingrui98 已提交
392
      req.valid := io.pc.valid
393 394 395
      req.bits.pc := io.pc.bits
      req.bits.hist := io.hist
      req.bits.mask := io.inMask
L
Lingrui98 已提交
396
      if (!EnableSC) {t.io.update := DontCare}
397 398 399 400
      t
    }
  }

L
Lingrui98 已提交
401
  val scThreshold = RegInit(SCThreshold(5))
402 403 404
  val useThreshold = WireInit(scThreshold.thres)
  val updateThreshold = WireInit((useThreshold << 3) + 21.U)

405
  override val debug = true
406

L
Lingrui98 已提交
407
  // Keep the table responses to process in s3
L
Lingrui98 已提交
408 409
  // 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 已提交
410 411 412
  
  val if3_resps = VecInit(tables.map(t => t.io.resp))
  val if3_scResps = VecInit(scTables.map(t => t.io.resp))
L
Lingrui98 已提交
413

L
Lingrui98 已提交
414
  val if3_bim = RegEnable(io.bim, enable=io.pc.valid) // actually it is s2Fire
L
Lingrui98 已提交
415
  val if4_bim = RegEnable(if3_bim, enable=s3_fire)
L
Lingrui98 已提交
416 417

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

420
  val debug_hist_s2 = RegEnable(io.hist, enable=io.pc.valid)
L
Lingrui98 已提交
421
  val debug_hist_s3 = RegEnable(debug_hist_s2, enable=s3_fire)
422

L
Lingrui98 已提交
423
  val u = io.update.bits
L
Lingrui98 已提交
424 425
  val updateValids = u.valids.map(v => v && io.update.valid)
  val updateHist = u.predHist.asUInt
L
Lingrui98 已提交
426

L
Lingrui98 已提交
427 428 429
  val updateBrMask = u.br_mask
  val updateMetas = VecInit(u.metas.map(_.tageMeta))
  val updateMisPred = u.mispred
L
Lingrui98 已提交
430 431 432 433 434

  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())))
435
  val updateOldCtr = Wire(Vec(TageNTables, Vec(TageBanks, UInt(TageCtrBits.W))))
L
Lingrui98 已提交
436 437 438 439 440 441
  val updateU = Wire(Vec(TageNTables, Vec(TageBanks, UInt(2.W))))
  updateTaken := DontCare
  updateAlloc := DontCare
  updateOldCtr := DontCare
  updateU := DontCare

L
Lingrui98 已提交
442 443 444
  val scUpdateMask = WireInit(0.U.asTypeOf(Vec(SCNTables, Vec(TageBanks, Bool()))))
  val scUpdateTagePred = Wire(Bool())
  val scUpdateTaken = Wire(Bool())
445 446 447 448 449
  val scUpdateOldCtrs = Wire(Vec(SCNTables, SInt(SCCtrBits.W)))
  scUpdateTagePred := DontCare
  scUpdateTaken := DontCare
  scUpdateOldCtrs := DontCare

L
Lingrui98 已提交
450 451
  val updateSCMetas = VecInit(u.metas.map(_.tageMeta.scMeta))
  val updateTageMisPreds = VecInit((0 until PredictWidth).map(i => updateMetas(i).taken =/= u.takens(i) && updateBrMask(i)))
452

L
Lingrui98 已提交
453
  // val updateBank = u.pc(log2Ceil(TageBanks)+instOffsetBits-1, instOffsetBits)
L
Lingrui98 已提交
454 455 456

  // access tag tables and output meta info
  for (w <- 0 until TageBanks) {
L
Lingrui98 已提交
457 458 459 460 461
    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 已提交
462 463

    for (i <- 0 until TageNTables) {
L
Lingrui98 已提交
464 465
      val hit = if3_resps(i)(w).valid
      val ctr = if3_resps(i)(w).bits.ctr
L
Lingrui98 已提交
466
      when (hit) {
L
Lingrui98 已提交
467 468
        if3_tageTaken := Mux(ctr === 3.U || ctr === 4.U, if3_altPred, ctr(2)) // Use altpred on weak taken
        if3_finalAltPred := if3_altPred
L
Lingrui98 已提交
469
      }
L
Lingrui98 已提交
470 471 472
      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 已提交
473
    }
L
Lingrui98 已提交
474 475 476 477 478 479
    val if4_provided = RegEnable(if3_provided, s3_fire)
    val if4_provider = RegEnable(if3_provider, s3_fire)
    val if4_finalAltPred = RegEnable(if3_finalAltPred, s3_fire)
    val if4_tageTaken = RegEnable(if3_tageTaken, s3_fire)
    val if4_providerU = RegEnable(if3_resps(if3_provider)(w).bits.u, s3_fire)
    val if4_providerCtr = RegEnable(if3_resps(if3_provider)(w).bits.ctr, s3_fire)
L
Lingrui98 已提交
480

L
Lingrui98 已提交
481
    io.resp.hits(w) := if4_provided
L
Lingrui98 已提交
482
    io.resp.takens(w) := if4_tageTaken
L
Lingrui98 已提交
483 484 485
    io.meta(w).provider.valid := if4_provided
    io.meta(w).provider.bits := if4_provider
    io.meta(w).altDiffers := if4_finalAltPred =/= io.resp.takens(w)
L
Lingrui98 已提交
486 487
    io.meta(w).providerU := if4_providerU
    io.meta(w).providerCtr := if4_providerCtr
L
Lingrui98 已提交
488
    io.meta(w).taken := if4_tageTaken
L
Lingrui98 已提交
489 490 491

    // 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 已提交
492
    val allocatableSlots = RegEnable(VecInit(if3_resps.map(r => !r(w).valid && r(w).bits.u === 0.U)).asUInt &
L
Lingrui98 已提交
493
      ~(LowerMask(UIntToOH(if3_provider), TageNTables) & Fill(TageNTables, if3_provided.asUInt)), s3_fire
L
Lingrui98 已提交
494 495 496 497 498 499 500 501
    )
    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

502 503 504 505
    val scMeta = io.meta(w).scMeta
    scMeta := DontCare
    val scTableSums = VecInit(
      (0 to 1) map { i => {
L
Lingrui98 已提交
506
          // val providerCtr = if4_resps(if4_provider)(w).bits.ctr.zext()
507 508 509 510
          // val pvdrCtrCentered = (((providerCtr - 4.S) << 1) + 1.S) << 3
          // sum += pvdrCtrCentered
          if (EnableSC) {
            (0 until SCNTables) map { j => 
L
Lingrui98 已提交
511
              scTables(j).getCenteredValue(RegEnable(if3_scResps(j)(w).ctr(i), s3_fire))
512 513 514 515 516 517 518 519
            } reduce (_+_) // TODO: rewrite with adder tree
          }
          else 0.S
        }
      }
    )

    if (EnableSC) {
L
Lingrui98 已提交
520 521 522
      scMeta.tageTaken := if4_tageTaken
      scMeta.scUsed := if4_provided
      scMeta.scPred := if4_tageTaken
L
Lingrui98 已提交
523
      scMeta.sumAbs := 0.U
L
Lingrui98 已提交
524
      when (if4_provided) {
L
Lingrui98 已提交
525
        val providerCtr = if4_providerCtr.zext()
L
Lingrui98 已提交
526
        val pvdrCtrCentered = ((((providerCtr - 4.S) << 1).asSInt + 1.S) << 3).asSInt
L
Lingrui98 已提交
527
        val totalSum = scTableSums(if4_tageTaken.asUInt) + pvdrCtrCentered
L
Lingrui98 已提交
528
        val sumAbs = totalSum.abs().asUInt
529 530
        val sumBelowThreshold = totalSum.abs.asUInt < useThreshold
        val scPred = totalSum >= 0.S
L
Lingrui98 已提交
531
        scMeta.sumAbs := sumAbs
L
Lingrui98 已提交
532
        scMeta.ctrs   := RegEnable(VecInit(if3_scResps.map(r => r(w).ctr(if3_tageTaken.asUInt))), s3_fire)
L
Lingrui98 已提交
533
        for (i <- 0 until SCNTables) {
L
Lingrui98 已提交
534 535
          val if4_scResps = RegEnable(if3_scResps, s3_fire)
          XSDebug(RegNext(s3_fire), p"SCTable(${i.U})(${w.U}): ctr:(${if4_scResps(i)(w).ctr(0)},${if4_scResps(i)(w).ctr(1)})\n")
L
Lingrui98 已提交
536
        }
L
Lingrui98 已提交
537
        XSDebug(RegNext(s3_fire), p"SC(${w.U}): pvdCtr(${providerCtr}), pvdCentred(${pvdrCtrCentered}), totalSum(${totalSum}), abs(${sumAbs}) useThres(${useThreshold}), scPred(${scPred})\n")
538 539
        // Use prediction from Statistical Corrector
        when (!sumBelowThreshold) {
L
Lingrui98 已提交
540
          XSDebug(RegNext(s3_fire), p"SC(${w.U}) overriden pred to ${scPred}\n")
L
Lingrui98 已提交
541
          scMeta.scPred := scPred
542 543 544 545
          io.resp.takens(w) := scPred
        }
      }
    }
L
Lingrui98 已提交
546

L
Lingrui98 已提交
547 548 549 550 551 552
    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 已提交
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
      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 已提交
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
    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 已提交
584 585 586 587 588
        }
      }
    }
  }

L
Lingrui98 已提交
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610

  // if (EnableSC) {
  //   when (updateValid && updateSCMeta.scUsed.asBool && updateIsBr) {
  //     val scPred = updateSCMeta.scPred
  //     val tageTaken = updateSCMeta.tageTaken
  //     val sumAbs = updateSCMeta.sumAbs.asUInt
  //     val scOldCtrs = updateSCMeta.ctrs
  //     when (scPred =/= tageTaken && sumAbs < useThreshold - 2.U) {
  //       val newThres = scThreshold.update(scPred =/= u.taken)
  //       scThreshold := newThres
  //       XSDebug(p"scThres update: old d${useThreshold} --> new ${newThres.thres}\n")
  //     }
  //     when (scPred =/= u.taken || sumAbs < updateThreshold) {
  //       scUpdateMask.foreach(t => t(updateBank) := true.B)
  //       scUpdateTagePred := tageTaken
  //       scUpdateTaken := u.taken
  //       (scUpdateOldCtrs zip scOldCtrs).foreach{case (t, c) => t := c}
  //       XSDebug(p"scUpdate: bank(${updateBank}), scPred(${scPred}), tageTaken(${tageTaken}), scSumAbs(${sumAbs}), mispred: sc(${updateMisPred}), tage(${updateTageMisPred})\n")
  //       XSDebug(p"update: sc: ${updateSCMeta}\n")
  //     }
  //   }
  // }
611

L
Lingrui98 已提交
612 613 614 615 616 617 618 619 620
  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)
621
      tables(i).io.update.pc := packetAligned(u.ftqPC) + (w << instOffsetBits).U
L
Lingrui98 已提交
622 623
    }
    // use fetch pc instead of instruction pc
L
Lingrui98 已提交
624
    tables(i).io.update.hist := updateHist
L
Lingrui98 已提交
625 626
  }

L
Lingrui98 已提交
627 628 629 630 631 632 633 634
  // for (i <- 0 until SCNTables) {
  //   scTables(i).io.update.mask := scUpdateMask(i)
  //   scTables(i).io.update.tagePred := scUpdateTagePred
  //   scTables(i).io.update.taken    := scUpdateTaken
  //   scTables(i).io.update.oldCtr   := scUpdateOldCtrs(i)
  //   scTables(i).io.update.pc := u.pc
  //   scTables(i).io.update.hist := updateHist
  // }
635

L
Lingrui98 已提交
636

L
Lingrui98 已提交
637

638
  if (BPUDebug && debug) {
L
Lingrui98 已提交
639 640 641 642 643 644 645 646
    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 已提交
647
    val if4_resps = RegEnable(if3_resps, s3_fire)
L
Lingrui98 已提交
648
    XSDebug(io.pc.valid, "req: pc=0x%x, hist=%x\n", io.pc.bits, io.hist)
L
Lingrui98 已提交
649 650
    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 已提交
651 652
      debug_pc_s3, debug_hist_s3, io.resp.hits.asUInt, io.resp.takens.asUInt)
    for (i <- 0 until TageNTables) {
L
Lingrui98 已提交
653
      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 已提交
654
    }
L
Lingrui98 已提交
655 656
    // XSDebug(io.update.valid && updateIsBr, p"update: sc: ${updateSCMeta}\n")
    // XSDebug(true.B, p"scThres: use(${useThreshold}), update(${updateThreshold})\n")
L
Lingrui98 已提交
657
  }
658 659 660 661 662 663 664 665 666
}

object TageTest extends App {
  override def main(args: Array[String]): Unit = {
    (new ChiselStage).execute(args, Seq(
      ChiselGeneratorAnnotation(() => new Tage),
      RunFirrtlTransformAnnotation(new RenameDesiredNames)
    ))
  }
L
Lingrui98 已提交
667
}