Brq.scala 9.5 KB
Newer Older
1 2 3 4 5
package xiangshan.backend.brq

import chisel3._
import chisel3.util._
import xiangshan._
L
LinJiawei 已提交
6
import utils._
L
LinJiawei 已提交
7
import chisel3.ExcitingUtils._
8 9


L
LinJiawei 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
class BrqPtr extends XSBundle {

  val flag = Bool()
  val value = UInt(BrTagWidth.W)

  final def + (inc: Bool): BrqPtr = {
    Mux(inc && (value === (BrqSize-1).U),
      BrqPtr(!flag, 0.U),
      BrqPtr(flag, value + inc)
    )
  }

  final def === (that: BrqPtr): Bool = {
    (this.value===that.value) && (this.flag===that.flag)
  }

26 27
  // this.age < that.age
  final def < (that: BrqPtr): Bool = {
L
LinJiawei 已提交
28 29 30 31 32 33
    Mux(this.flag === that.flag,
      this.value > that.value,
      this.value < that.value
    )
  }

34
  def needBrFlush(redirectTag: BrqPtr): Bool = this < redirectTag
L
LinJiawei 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

  def needFlush(redirect: Valid[Redirect]): Bool = {
    redirect.valid && (redirect.bits.isException || needBrFlush(redirect.bits.brTag))
  }

  override def toPrintable: Printable = p"f:$flag v:$value"

}

object BrqPtr {
  def apply(f: Bool, v: UInt): BrqPtr = {
    val ptr = Wire(new BrqPtr)
    ptr.flag := f
    ptr.value := v
    ptr
  }
}

L
LinJiawei 已提交
53 54 55 56
class BrqIO extends XSBundle{
  // interrupt/exception happen, flush Brq
  val roqRedirect = Input(Valid(new Redirect))
  // receive branch/jump calculated target
L
LinJiawei 已提交
57
  val exuRedirect = Vec(exuParameters.AluCnt + exuParameters.JmpCnt, Flipped(ValidIO(new ExuOutput)))
L
LinJiawei 已提交
58 59 60 61 62 63 64 65
  // from decode, branch insts enq
  val enqReqs = Vec(DecodeWidth, Flipped(DecoupledIO(new CfCtrl)))
  // to decode
  val brTags = Output(Vec(DecodeWidth, new BrqPtr))
  // to roq
  val out = ValidIO(new ExuOutput)
  // misprediction, flush pipeline
  val redirect = Output(Valid(new Redirect))
66 67
  // commit cnt of branch instr
  val bcommit = Input(UInt(BrTagWidth.W))
68 69
  // in order dequeue to train bpd
  val inOrderBrInfo = Output(new RedirectInfo)
L
LinJiawei 已提交
70
}
71

L
LinJiawei 已提交
72
class Brq extends XSModule {
L
LinJiawei 已提交
73 74
  val io = IO(new BrqIO)

75
  class BrqEntry extends Bundle {
L
LinJiawei 已提交
76
    val ptrFlag = Bool()
77
    val npc = UInt(VAddrBits.W)
L
LinJiawei 已提交
78
    val misPred = Bool()
L
LinJiawei 已提交
79
    val exuOut = new ExuOutput
80 81
  }

82 83
  val s_idle :: s_wb :: s_commited :: Nil  =
    List.tabulate(3)(i => (1 << i).U(3.W).asTypeOf(new StateQueueEntry))
L
LinJiawei 已提交
84

85 86 87 88
  class StateQueueEntry extends Bundle{
    val isCommit = Bool()
    val isWb = Bool()
    val isIdle = Bool()
L
LinJiawei 已提交
89 90
  }

91
  val brCommitCnt = RegInit(0.U(BrTagWidth.W))
92
  val brQueue = Reg(Vec(BrqSize, new BrqEntry))
93
  val stateQueue = RegInit(VecInit(Seq.fill(BrqSize)(s_idle)))
L
LinJiawei 已提交
94

L
LinJiawei 已提交
95
  val headPtr, tailPtr = RegInit(BrqPtr(false.B, 0.U))
L
LinJiawei 已提交
96

L
LinJiawei 已提交
97 98
  def isEmpty(ptr1: BrqPtr, ptr2: BrqPtr): Bool = ptr1 === ptr2
  def isFull(ptr1: BrqPtr, ptr2: BrqPtr): Bool = (ptr1.flag=/=ptr2.flag) && (ptr1.value===ptr2.value)
L
LinJiawei 已提交
99 100 101


  // dequeue
L
LinJiawei 已提交
102
  val headIdx = headPtr.value
103

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
  val skipMask = Cat(stateQueue.zipWithIndex.map({
    case (s, i) => (s.isWb && !brQueue(i).misPred) || s.isCommit
  }).reverse)

  /*
      example: headIdx       = 2
               headIdxOH     = 00000100
               headIdxMaskHI = 11111100
               headIdxMaskLo = 00000011
               skipMask      = 00111101
               commitIdxHi   =  6
               commitIdxLo   =        0
               commitIdx     =  6
   */
  val headIdxOH = UIntToOH(headIdx)
  val headIdxMaskHiVec = Wire(Vec(BrqSize, Bool()))
  for(i <- headIdxMaskHiVec.indices){
    headIdxMaskHiVec(i) := { if(i==0) headIdxOH(i) else headIdxMaskHiVec(i-1) || headIdxOH(i) }
122
  }
123 124
  val headIdxMaskHi = headIdxMaskHiVec.asUInt()
  val headIdxMaskLo = (~headIdxMaskHi).asUInt()
L
LinJiawei 已提交
125

L
LinJiawei 已提交
126 127
  val commitIdxHi = PriorityEncoder((~skipMask).asUInt() & headIdxMaskHi)
  val (commitIdxLo, findLo) = PriorityEncoderWithFlag((~skipMask).asUInt() & headIdxMaskLo)
L
LinJiawei 已提交
128

L
LinJiawei 已提交
129 130
  val skipHi = (skipMask | headIdxMaskLo) === Fill(BrqSize, 1.U(1.W))
  val useLo = skipHi && findLo
131

L
LinJiawei 已提交
132
  val commitIdx = Mux(stateQueue(commitIdxHi).isWb && brQueue(commitIdxHi).misPred,
133
    commitIdxHi,
L
LinJiawei 已提交
134
    Mux(useLo && stateQueue(commitIdxLo).isWb && brQueue(commitIdxLo).misPred,
135 136
      commitIdxLo,
      headIdx
L
LinJiawei 已提交
137
    )
138 139
  )

L
LinJiawei 已提交
140
  val commitIsHead = commitIdx===headIdx
141
  val deqValid = !stateQueue(headIdx).isIdle && commitIsHead && brCommitCnt=/=0.U
142
  val commitValid = stateQueue(commitIdx).isWb
L
LinJiawei 已提交
143 144
  val commitEntry = brQueue(commitIdx)

145 146 147 148
  brCommitCnt := brCommitCnt + io.bcommit - deqValid

  XSDebug(p"brCommitCnt:$brCommitCnt\n")
  assert(brCommitCnt+io.bcommit >= deqValid)
149 150 151
  io.inOrderBrInfo.valid := deqValid
  io.inOrderBrInfo.misPred := commitEntry.misPred
  io.inOrderBrInfo.redirect := commitEntry.exuOut.redirect
L
LinJiawei 已提交
152

L
LinJiawei 已提交
153 154 155 156 157 158
//  XSDebug(
//    p"commitIdxHi:$commitIdxHi ${Binary(headIdxMaskHi)} ${Binary(skipMask)}\n"
//  )
//  XSDebug(
//    p"commitIdxLo:$commitIdxLo ${Binary(headIdxMaskLo)} ${Binary(skipMask)}\n"
//  )
L
LinJiawei 已提交
159 160
  XSDebug(p"headIdx:$headIdx commitIdx:$commitIdx\n")
  XSDebug(p"headPtr:$headPtr tailPtr:$tailPtr\n")
161
  XSDebug("")
L
LinJiawei 已提交
162
  stateQueue.reverse.map(s =>{
163 164 165 166 167
    XSDebug(false, s.isIdle, "-")
    XSDebug(false, s.isWb, "w")
    XSDebug(false, s.isCommit, "c")
  })
  XSDebug(false, true.B, "\n")
L
LinJiawei 已提交
168 169

  val headPtrNext = WireInit(headPtr + deqValid)
170 171 172 173 174
  stateQueue(commitIdx):= Mux(deqValid,
    s_idle,
    Mux(commitValid,
      s_commited,
      stateQueue(commitIdx)
L
LinJiawei 已提交
175 176 177
    )
  )

L
LinJiawei 已提交
178
  headPtr := headPtrNext
179
  io.redirect.valid := commitValid && commitEntry.misPred && !io.roqRedirect.valid
L
LinJiawei 已提交
180 181 182 183 184 185
  io.redirect.bits := commitEntry.exuOut.redirect
  io.out.valid := commitValid
  io.out.bits := commitEntry.exuOut
  XSInfo(io.out.valid,
    p"commit branch to roq, mispred:${io.redirect.valid} pc=${Hexadecimal(io.out.bits.uop.cf.pc)}\n"
  )
L
LinJiawei 已提交
186 187 188 189

  // branch insts enq
  var full = WireInit(isFull(headPtrNext, tailPtr))
  var tailPtrNext = WireInit(tailPtr)
L
LinJiawei 已提交
190
  for((enq, brTag) <- io.enqReqs.zip(io.brTags)){
L
LinJiawei 已提交
191
    enq.ready := !full
L
LinJiawei 已提交
192
    brTag := tailPtrNext
L
LinJiawei 已提交
193
    when(enq.fire()){
194
      brQueue(tailPtrNext.value).npc := enq.bits.cf.pnpc
L
LinJiawei 已提交
195 196
      brQueue(tailPtrNext.value).ptrFlag := tailPtrNext.flag
    }
197

L
LinJiawei 已提交
198 199 200 201 202 203 204
    tailPtrNext = tailPtrNext + enq.fire()
    full = isFull(tailPtrNext, headPtrNext)
  }
  tailPtr := tailPtrNext

  // exu write back
  for(exuWb <- io.exuRedirect){
L
LinJiawei 已提交
205
    when(exuWb.valid){
L
LinJiawei 已提交
206 207 208
      val wbIdx = exuWb.bits.redirect.brTag.value
      XSInfo(
        p"exu write back: brTag:${exuWb.bits.redirect.brTag}" +
209
          p" pc=${Hexadecimal(exuWb.bits.uop.cf.pc)} pnpc=${Hexadecimal(brQueue(wbIdx).npc)} target=${Hexadecimal(exuWb.bits.redirect.target)}\n"
L
LinJiawei 已提交
210
      )
211
      stateQueue(wbIdx) := s_wb
L
LinJiawei 已提交
212 213
      brQueue(wbIdx).exuOut := exuWb.bits
      brQueue(wbIdx).misPred := brQueue(wbIdx).npc =/= exuWb.bits.redirect.target
214 215 216 217 218 219 220 221 222
      // brQueue(wbIdx).exuOut.redirect.hist := exuWb.bits.uop.cf.hist
      // brQueue(wbIdx).exuOut.redirect.btbVictimWay := exuWb.bits.uop.cf.btbVictimWay
      // brQueue(wbIdx).exuOut.redirect.btbPredCtr := exuWb.bits.uop.cf.btbPredCtr
      // brQueue(wbIdx).exuOut.redirect.btbHitWay := exuWb.bits.uop.cf.btbHitWay
      // brQueue(wbIdx).exuOut.redirect.tageMeta := exuWb.bits.uop.cf.tageMeta
      // brQueue(wbIdx).exuOut.redirect.rasSp := exuWb.bits.uop.cf.rasSp
      // brQueue(wbIdx).exuOut.redirect.rasTopCtr := exuWb.bits.uop.cf.rasTopCtr
      // brQueue(wbIdx).exuOut.redirect.fetchIdx := exuWb.bits.uop.cf.fetchOffset << 2.U
      brQueue(wbIdx).exuOut.redirect := exuWb.bits.redirect
L
LinJiawei 已提交
223 224 225
    }
  }

L
LinJiawei 已提交
226 227
  when(io.roqRedirect.valid){
    // exception
228
    stateQueue.foreach(_ := s_idle)
L
LinJiawei 已提交
229 230
    headPtr := BrqPtr(false.B, 0.U)
    tailPtr := BrqPtr(false.B, 0.U)
231
    brCommitCnt := 0.U
L
LinJiawei 已提交
232 233 234 235 236
  }.elsewhen(io.redirect.valid){
    // misprediction
    stateQueue.zipWithIndex.foreach({case(s, i) =>
      val ptr = BrqPtr(brQueue(i).ptrFlag, i.U)
      when(ptr.needBrFlush(io.redirect.bits.brTag)){
237
        s := s_idle
L
LinJiawei 已提交
238 239 240
      }
    })
    tailPtr := io.redirect.bits.brTag + true.B
L
LinJiawei 已提交
241
  }
L
LinJiawei 已提交
242 243 244 245 246 247 248 249 250 251




  // Debug info
  val debug_roq_redirect = io.roqRedirect.valid
  val debug_brq_redirect = io.redirect.valid && !debug_roq_redirect
  val debug_normal_mode = !(debug_roq_redirect || debug_brq_redirect)

  for(i <- 0 until DecodeWidth){
L
LinJiawei 已提交
252
    XSDebug(
L
LinJiawei 已提交
253 254
      debug_normal_mode,
      p"enq v:${io.enqReqs(i).valid} rdy:${io.enqReqs(i).ready} pc:${Hexadecimal(io.enqReqs(i).bits.cf.pc)}" +
255
        p"pnpc:${Hexadecimal(io.enqReqs(i).bits.cf.pnpc)} brTag:${io.brTags(i)}\n"
L
LinJiawei 已提交
256 257 258 259
    )
  }

  XSInfo(debug_roq_redirect, "roq redirect, flush brq\n")
L
LinJiawei 已提交
260

L
LinJiawei 已提交
261
  XSInfo(debug_brq_redirect, p"brq redirect, target:${Hexadecimal(io.redirect.bits.target)}\n")
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280

  val fire = io.out.fire()
  val predRight = fire && !commitEntry.misPred
  val predWrong = fire && commitEntry.misPred
  val isBType = commitEntry.exuOut.redirect.btbType===BTBtype.B
  val isJType = commitEntry.exuOut.redirect.btbType===BTBtype.J
  val isIType = commitEntry.exuOut.redirect.btbType===BTBtype.I
  val isRType = commitEntry.exuOut.redirect.btbType===BTBtype.R
  val mbpInstr = fire
  val mbpRight = predRight
  val mbpWrong = predWrong
  val mbpBRight = predRight && isBType
  val mbpBWrong = predWrong && isBType
  val mbpJRight = predRight && isJType
  val mbpJWrong = predWrong && isJType
  val mbpIRight = predRight && isIType
  val mbpIWrong = predWrong && isIType
  val mbpRRight = predRight && isRType
  val mbpRWrong = predWrong && isRType
Z
zhanglinjuan 已提交
281

J
jinyue110 已提交
282
  if(EnableBPU){
L
LinJiawei 已提交
283 284 285 286 287 288 289 290 291 292 293
    ExcitingUtils.addSource(mbpInstr, "perfCntCondMbpInstr", Perf)
    ExcitingUtils.addSource(mbpRight, "perfCntCondMbpRight", Perf)
    ExcitingUtils.addSource(mbpWrong, "perfCntCondMbpWrong", Perf)
    ExcitingUtils.addSource(mbpBRight, "perfCntCondMbpBRight", Perf)
    ExcitingUtils.addSource(mbpBWrong, "perfCntCondMbpBWrong", Perf)
    ExcitingUtils.addSource(mbpJRight, "perfCntCondMbpJRight", Perf)
    ExcitingUtils.addSource(mbpJWrong, "perfCntCondMbpJWrong", Perf)
    ExcitingUtils.addSource(mbpIRight, "perfCntCondMbpIRight", Perf)
    ExcitingUtils.addSource(mbpIWrong, "perfCntCondMbpIWrong", Perf)
    ExcitingUtils.addSource(mbpRRight, "perfCntCondMbpRRight", Perf)
    ExcitingUtils.addSource(mbpRWrong, "perfCntCondMbpRWrong", Perf)
J
jinyue110 已提交
294
  }
295
}