uBTB.scala 5.8 KB
Newer Older
Z
zoujr 已提交
1 2
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
L
Lingrui98 已提交
3
* Copyright (c) 2020-2021 Peng Cheng Laboratory
Z
zoujr 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

package xiangshan.frontend

import chipsalliance.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
import utils._
import xiangshan._
import chisel3.experimental.chiselName
Z
zoujr 已提交
25
import xiangshan.cache.mmu.CAMTemplate
Z
zoujr 已提交
26

L
Lingrui98 已提交
27
trait MicroBTBParams extends HasBPUParameter {
28
  val numWays = 512
Z
zoujr 已提交
29
  val tagSize = 20
30 31
  // val lowerBitSize = 20
  val untaggedBits = log2Ceil(numWays) + instOffsetBits
L
Lingrui98 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
  def ubtbAddr = new TableAddr(log2Up(numWays), 1)
}

class MicroBTBEntry(implicit p: Parameters) extends XSBundle with MicroBTBParams {
  val valid = Bool()
  val tag = UInt(tagSize.W)
  val slot_valids = Vec(totalSlot, Bool())
  val offsets = Vec(totalSlot, UInt(log2Ceil(PredictWidth).W))
  val targets = Vec(totalSlot, UInt(VAddrBits.W))
  val fallThroughAddr = UInt(VAddrBits.W)
  val oversize = Bool()
  val last_is_br = Bool()
  def brValids = VecInit(slot_valids.init :+ (slot_valids.last && last_is_br))
  def jmpValid = VecInit(slot_valids.last && !last_is_br)
  def fromBpuUpdateBundle(u: BranchPredictionUpdate) = {
    this.valid := true.B
    this.tag := ubtbAddr.getTag(u.pc)
    this.slot_valids := VecInit(u.ftb_entry.brSlots.map(_.valid) :+ u.ftb_entry.tailSlot.valid)
    this.offsets := u.ftb_entry.getOffsetVec
    this.targets := u.ftb_entry.getTargetVec(u.pc)
    this.fallThroughAddr := u.ftb_entry.getFallThrough(u.pc)
    this.oversize := u.ftb_entry.oversize
    this.last_is_br := u.ftb_entry.tailSlot.sharing
  }
Z
zoujr 已提交
56 57 58 59
}

@chiselName
class MicroBTB(implicit p: Parameters) extends BasePredictor
60
  with MicroBTBParams with HasPerfEvents
Z
zoujr 已提交
61
{
L
Lingrui98 已提交
62
  
63

64 65
  class MicroBTBOutMeta extends XSBundle {
    val hit = Bool()
Z
zoujr 已提交
66 67
  }

L
Lingrui98 已提交
68

69

70
  override val meta_size = WireInit(0.U.asTypeOf(new MicroBTBOutMeta)).getWidth // TODO: ReadResp shouldn't save useless members
Z
zoujr 已提交
71

L
Lingrui98 已提交
72
  class UBTBBank(val nWays: Int)(implicit p: Parameters) extends XSModule with BPUUtils {
Z
zoujr 已提交
73
    val io = IO(new Bundle {
74
      val read_pc = Flipped(DecoupledIO(UInt(VAddrBits.W))) // TODO: Add ready
75
      // val read_taken_mask = Input(Vec(numBr, Bool()))
76
      val read_entry = Output(new MicroBTBEntry)
L
Lingrui98 已提交
77
      val read_hit = Output(Bool())
Z
zoujr 已提交
78

L
Lingrui98 已提交
79 80
      val update_valid = Input(Bool())
      val update_write_entry = Input(new MicroBTBEntry)
81
      val update_pc = Input(UInt(VAddrBits.W))
Z
zoujr 已提交
82 83
    })

84
    val dataMem = Module(new SRAMTemplate(new MicroBTBEntry, set = numWays, way = 1, shouldReset = true, holdRead = true, singlePort = true))
Z
zoujr 已提交
85

86 87
    val read_pc = RegNext(io.read_pc.bits)
    val read_tag = ubtbAddr.getTag(read_pc)(tagSize-1,0)
Z
zoujr 已提交
88

89 90
    dataMem.io.r.req.valid := io.read_pc.valid
    dataMem.io.r.req.bits.setIdx := ubtbAddr.getIdx(io.read_pc.bits)
Z
zoujr 已提交
91

92
    io.read_pc.ready := dataMem.io.r.req.ready
Z
zoujr 已提交
93

94
    val hit_entry = dataMem.io.r.resp.data(0)
L
Lingrui98 已提交
95
    val hit = hit_entry.valid && hit_entry.tag === read_tag
96

L
Lingrui98 已提交
97 98
    io.read_entry := hit_entry
    io.read_hit := hit
99

100
    dataMem.io.w.apply(io.update_valid, io.update_write_entry, ubtbAddr.getIdx(io.update_pc), io.update_valid)
Z
zoujr 已提交
101

Z
zoujr 已提交
102
  } // uBTBBank
Z
zoujr 已提交
103

L
Lingrui98 已提交
104 105 106
  val ubtbBank = Module(new UBTBBank(numWays))
  val bank = ubtbBank.io
  val read_entry = bank.read_entry
107
  val outMeta = Wire(new MicroBTBOutMeta)
Z
zoujr 已提交
108

109
  XSDebug(p"uBTB entry, read_pc=${Hexadecimal(s0_pc)}\n")
Z
zoujr 已提交
110

111 112
  bank.read_pc.valid := io.s0_fire
  bank.read_pc.bits := s0_pc
Z
zoujr 已提交
113

114
  io.s1_ready := bank.read_pc.ready
Z
zoujr 已提交
115

Z
zoujr 已提交
116 117
  io.out.resp := io.in.bits.resp_in(0)
  io.out.resp.s1.pc := s1_pc
L
Lingrui98 已提交
118
  io.out.resp.s1.preds.hit := bank.read_hit
L
Lingrui98 已提交
119 120
  io.out.resp.s1.ftb_entry := DontCare
  io.out.resp.s1.preds.fromMicroBTBEntry(read_entry)
L
Lingrui98 已提交
121 122

  outMeta.hit := bank.read_hit
L
Lingrui98 已提交
123
  io.out.last_stage_meta := RegEnable(outMeta.asUInt, io.s1_fire)
Z
zoujr 已提交
124 125 126 127 128

  // Update logic
  val update = RegNext(io.update.bits)
  val u_valid = RegNext(io.update.valid)
  val u_pc = update.pc
Z
zoujr 已提交
129
  val u_taken = update.preds.taken
130
  val u_br_taken_mask = update.preds.br_taken_mask
131
  val u_meta = update.meta.asTypeOf(new MicroBTBOutMeta)
Z
zoujr 已提交
132

133
  val u_tag = ubtbAddr.getTag(u_pc)
L
Lingrui98 已提交
134

135 136
  bank.update_valid := u_valid && u_taken && ((u_meta.hit && !update.old_entry) || !u_meta.hit)
  bank.update_pc := u_pc
L
Lingrui98 已提交
137
  bank.update_write_entry.fromBpuUpdateBundle(update)
Z
zoujr 已提交
138

L
Lingrui98 已提交
139 140
  XSDebug("req_v=%b, req_pc=%x, hit=%b\n", io.s1_fire, s1_pc, bank.read_hit)
  XSDebug("target=%x, real_taken_mask=%b, taken_mask=%b, brValids=%b, jmpValid=%b\n",
L
Lingrui98 已提交
141
    io.out.resp.s1.target, io.out.resp.s1.real_slot_taken_mask.asUInt, io.out.resp.s1.preds.br_taken_mask.asUInt, read_entry.brValids.asUInt, read_entry.jmpValid.asUInt)
Z
zoujr 已提交
142

L
Lingrui98 已提交
143
  XSDebug(u_valid, "[update]Update from ftq\n")
144
  XSDebug(u_valid, "[update]update_pc=%x, tag=%x\n", u_pc, ubtbAddr.getTag(u_pc))
L
Lingrui98 已提交
145
  XSDebug(u_valid, "[update]taken_mask=%b, brValids=%b, jmpValid=%b\n",
146
    u_br_taken_mask.asUInt, update.ftb_entry.brValids.asUInt, update.ftb_entry.jmpValid)
Z
zoujr 已提交
147

L
Lingrui98 已提交
148 149
  XSPerfAccumulate("ubtb_read_hits", RegNext(io.s1_fire) && bank.read_hit)
  XSPerfAccumulate("ubtb_read_misses", RegNext(io.s1_fire) && !bank.read_hit)
150

L
Lingrui98 已提交
151 152
  XSPerfAccumulate("ubtb_commit_hits", u_valid && u_meta.hit)
  XSPerfAccumulate("ubtb_commit_misses", u_valid && !u_meta.hit)
Z
zoujr 已提交
153

154
  val perfEvents = Seq(
155 156
    ("ubtb_commit_hit       ", u_valid &&  u_meta.hit),
    ("ubtb_commit_miss      ", u_valid && !u_meta.hit),
157
  )
158
  generatePerfEvent()
Z
zoujr 已提交
159
}