uBTB.scala 6.4 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 27

trait MicroBTBParams extends HasXSParameter {
28
  val numWays = 32
Z
zoujr 已提交
29 30
  val tagSize = 20
  val lowerBitSize = 20
Z
zoujr 已提交
31
  val untaggedBits = instOffsetBits
Z
zoujr 已提交
32 33 34 35 36 37
}

@chiselName
class MicroBTB(implicit p: Parameters) extends BasePredictor
  with MicroBTBParams
{
Z
zoujr 已提交
38
  def getTag(pc: UInt)  = (pc >> untaggedBits)(tagSize-1, 0)
Z
zoujr 已提交
39

40 41 42 43
  class MicroBTBMeta extends XSBundle {
    val valid = Bool()
    val tag = UInt(tagSize.W)
  }
44

45 46
  class MicroBTBOutMeta extends XSBundle {
    val hit = Bool()
Z
zoujr 已提交
47 48
  }

L
Lingrui98 已提交
49
  class MicroBTBEntry extends FTBEntry {}
50

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

53
  class UBTBBank(val nWays: Int) extends XSModule with BPUUtils {
Z
zoujr 已提交
54 55
    val io = IO(new Bundle {
      val read_pc = Flipped(Valid(UInt(VAddrBits.W)))
56
      // val read_taken_mask = Input(Vec(numBr, Bool()))
L
Lingrui98 已提交
57 58
      val read_entry = Output(new FTBEntry)
      val read_hit = Output(Bool())
Z
zoujr 已提交
59

L
Lingrui98 已提交
60 61 62
      val update_valid = Input(Bool())
      val update_write_tag = Input(UInt(tagSize.W))
      val update_write_entry = Input(new MicroBTBEntry)
Z
zoujr 已提交
63 64
    })

Z
zoujr 已提交
65
    val tagCam = Module(new CAMTemplate(UInt(tagSize.W), nWays, 2))
L
Lingrui98 已提交
66 67
    val valids = RegInit(VecInit(Seq.fill(nWays)(false.B))) // valids
    val dataMem = Module(new AsyncDataModuleTemplate(new MicroBTBEntry, nWays, 1, 1))
Z
zoujr 已提交
68

Z
zoujr 已提交
69 70
    val read_pc = io.read_pc.bits
    val read_tag = getTag(read_pc)
Z
zoujr 已提交
71

L
Lingrui98 已提交
72
    val hits = VecInit((0 until nWays).map(i => valids(i) && tagCam.io.r.resp(0)(i)))
Z
zoujr 已提交
73 74
    val hit = hits.reduce(_||_)
    val hitWay = OHToUInt(hits)
Z
zoujr 已提交
75

Z
zoujr 已提交
76 77
    dataMem.io.raddr(0) := hitWay

L
Lingrui98 已提交
78
    val hit_entry = Mux(hit, dataMem.io.rdata(0), 0.U.asTypeOf(new MicroBTBEntry))
79

L
Lingrui98 已提交
80 81
    io.read_entry := hit_entry
    io.read_hit := hit
82

L
Lingrui98 已提交
83
    val update_tag = io.update_write_tag
L
Lingrui98 已提交
84
    val update_hits = VecInit((0 until nWays).map(i => valids(i) && tagCam.io.r.resp(1)(i)))
Z
zoujr 已提交
85 86 87
    val update_hit = update_hits.reduce(_||_)
    val update_hitWay = OHToUInt(update_hits)
    
Z
zoujr 已提交
88
    require(tagSize % log2Ceil(nWays) == 0)
89

Z
zoujr 已提交
90 91
    val update_alloc_way = RegInit(0.U(log2Ceil(nWays).W))
    
L
Lingrui98 已提交
92
    when (io.update_valid && !update_hit) {
93
      update_alloc_way := update_alloc_way ^ foldTag(update_tag, log2Ceil(nWays))
Z
zoujr 已提交
94
    }
Z
zoujr 已提交
95

L
Lingrui98 已提交
96
    val update_emptys = valids.map(!_)
Z
zoujr 已提交
97 98
    val update_has_empty_way = update_emptys.reduce(_||_)
    val update_empty_way = ParallelPriorityEncoder(update_emptys)
99 100 101 102 103 104 105 106 107 108 109 110 111 112
    val update_way = Wire(UInt(log2Ceil(nWays).W))
    

    val update_valid_reg = RegNext(io.update_valid)
    val update_way_reg = RegNext(update_way)
    val update_tag_reg = RegNext(update_tag)
    val update_entry_reg = RegNext(io.update_write_entry)

    val update_bypass_valid = update_valid_reg && io.update_valid && update_tag === update_tag_reg
    update_way :=
      Mux(update_bypass_valid, update_way_reg,
        Mux(update_hit, update_hitWay,
          Mux(update_has_empty_way, update_empty_way,
            update_alloc_way)))
Z
zoujr 已提交
113

Z
zoujr 已提交
114 115
    tagCam.io.r.req := VecInit(Seq(read_tag, update_tag))
    
116 117 118
    tagCam.io.w.valid       := update_valid_reg
    tagCam.io.w.bits.index  := update_way_reg
    tagCam.io.w.bits.data   := update_tag_reg
Z
zoujr 已提交
119

120 121
    when (update_valid_reg) {
      valids(update_way_reg) := true.B
L
Lingrui98 已提交
122 123
    }

124 125 126
    dataMem.io.wen(0)   := update_valid_reg
    dataMem.io.waddr(0) := update_way_reg
    dataMem.io.wdata(0) := update_entry_reg
Z
zoujr 已提交
127

Z
zoujr 已提交
128
  } // uBTBBank
Z
zoujr 已提交
129

L
Lingrui98 已提交
130 131 132
  val ubtbBank = Module(new UBTBBank(numWays))
  val bank = ubtbBank.io
  val read_entry = bank.read_entry
133
  val outMeta = Wire(new MicroBTBOutMeta)
Z
zoujr 已提交
134

Z
zoujr 已提交
135 136
  XSDebug(p"uBTB entry, read_pc=${Hexadecimal(s1_pc)}\n")

L
Lingrui98 已提交
137 138
  bank.read_pc.valid := io.s1_fire
  bank.read_pc.bits := s1_pc
Z
zoujr 已提交
139

Z
zoujr 已提交
140 141
  io.out.resp := io.in.bits.resp_in(0)
  io.out.resp.s1.pc := s1_pc
L
Lingrui98 已提交
142 143
  io.out.resp.s1.preds.hit := bank.read_hit
  io.out.resp.s1.ftb_entry := read_entry
144
  io.out.resp.s1.preds.fromFtbEntry(read_entry, s1_pc)
L
Lingrui98 已提交
145 146

  when(!bank.read_hit) {
147 148 149 150
    io.out.resp.s1.ftb_entry.pftAddr := s1_pc(instOffsetBits + log2Ceil(PredictWidth), instOffsetBits) ^ (1 << log2Ceil(PredictWidth)).U
    io.out.resp.s1.ftb_entry.carry := s1_pc(instOffsetBits + log2Ceil(PredictWidth)).asBool
    io.out.resp.s1.ftb_entry.oversize := false.B
  }
151

L
Lingrui98 已提交
152
  outMeta.hit := bank.read_hit
153
  io.out.s3_meta := RegEnable(RegEnable(outMeta.asUInt, io.s1_fire), io.s2_fire)
Z
zoujr 已提交
154 155 156 157 158

  // Update logic
  val update = RegNext(io.update.bits)
  val u_valid = RegNext(io.update.valid)
  val u_pc = update.pc
Z
zoujr 已提交
159
  val u_taken = update.preds.taken
160
  val u_taken_mask = update.preds.taken_mask
161
  val u_meta = update.meta.asTypeOf(new MicroBTBOutMeta)
Z
zoujr 已提交
162 163

  val u_tag = getTag(u_pc)
L
Lingrui98 已提交
164 165 166 167

  bank.update_valid := u_valid && u_taken
  bank.update_write_tag := u_tag
  bank.update_write_entry := update.ftb_entry
Z
zoujr 已提交
168

L
Lingrui98 已提交
169 170 171
  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",
    io.out.resp.s1.target, io.out.resp.s1.real_taken_mask.asUInt, io.out.resp.s1.preds.taken_mask.asUInt, read_entry.brValids.asUInt, read_entry.jmpValid.asUInt)
Z
zoujr 已提交
172

L
Lingrui98 已提交
173 174 175 176
  XSDebug(u_valid, "[update]Update from ftq\n")
  XSDebug(u_valid, "[update]update_pc=%x, tag=%x\n", u_pc, getTag(u_pc))
  XSDebug(u_valid, "[update]taken_mask=%b, brValids=%b, jmpValid=%b\n",
    u_taken_mask.asUInt, update.ftb_entry.brValids.asUInt, update.ftb_entry.jmpValid)
Z
zoujr 已提交
177

L
Lingrui98 已提交
178 179
  XSPerfAccumulate("ubtb_read_hits", RegNext(io.s1_fire) && bank.read_hit)
  XSPerfAccumulate("ubtb_read_misses", RegNext(io.s1_fire) && !bank.read_hit)
180

L
Lingrui98 已提交
181 182
  XSPerfAccumulate("ubtb_commit_hits", u_valid && u_meta.hit)
  XSPerfAccumulate("ubtb_commit_misses", u_valid && !u_meta.hit)
Z
zoujr 已提交
183 184


Z
zoujr 已提交
185
}