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

import chisel3._
import chisel3.util._
import xiangshan._
L
LinJiawei 已提交
6
import utils._
G
GouLingrui 已提交
7
import chisel3.util.experimental.BoringUtils
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 66
  // 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))
}
67

L
LinJiawei 已提交
68
class Brq extends XSModule {
L
LinJiawei 已提交
69 70 71 72
  val io = IO(new BrqIO)

  def redirctWindowSize: Int = BrqSize/2
  require(redirctWindowSize <= BrqSize && redirctWindowSize > 0)
L
LinJiawei 已提交
73

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

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

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

90
  val brQueue = Reg(Vec(BrqSize, new BrqEntry))
91
  val stateQueue = RegInit(VecInit(Seq.fill(BrqSize)(s_idle)))
L
LinJiawei 已提交
92

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

L
LinJiawei 已提交
95 96
  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 已提交
97 98 99


  // dequeue
L
LinJiawei 已提交
100
  val headIdx = headPtr.value
L
LinJiawei 已提交
101
  var commitIdx = WireInit(headIdx)
102 103 104 105 106 107

  def needCheckNext(idx: UInt): Bool = {
    (stateQueue(idx).isWb && !brQueue(idx).misPred) || stateQueue(idx).isCommit
  }

  var checkNext = WireInit(needCheckNext(headIdx))
L
LinJiawei 已提交
108 109 110

  for(i <- 1 until redirctWindowSize){
    val idx = commitIdx + i.U
111
    val commitThis = checkNext && stateQueue(idx).isWb && brQueue(idx).misPred
L
LinJiawei 已提交
112 113 114 115
    commitIdx = Mux(commitThis,
      idx,
      commitIdx
    )
116
    checkNext = checkNext && needCheckNext(idx)
L
LinJiawei 已提交
117 118 119
  }

  val commitIsHead = commitIdx===headIdx
120 121
  val deqValid = !stateQueue(headIdx).isIdle && commitIsHead
  val commitValid = stateQueue(commitIdx).isWb
L
LinJiawei 已提交
122 123 124 125 126
  val commitEntry = brQueue(commitIdx)


  XSDebug(p"headIdx:$headIdx commitIdx:$commitIdx\n")
  XSDebug(p"headPtr:$headPtr tailPtr:$tailPtr\n")
127 128 129 130 131 132 133
  XSDebug("")
  stateQueue.map(s =>{
    XSDebug(false, s.isIdle, "-")
    XSDebug(false, s.isWb, "w")
    XSDebug(false, s.isCommit, "c")
  })
  XSDebug(false, true.B, "\n")
L
LinJiawei 已提交
134 135

  val headPtrNext = WireInit(headPtr + deqValid)
136 137 138 139 140
  stateQueue(commitIdx):= Mux(deqValid,
    s_idle,
    Mux(commitValid,
      s_commited,
      stateQueue(commitIdx)
L
LinJiawei 已提交
141 142 143
    )
  )

L
LinJiawei 已提交
144
  headPtr := headPtrNext
L
LinJiawei 已提交
145 146 147 148 149 150 151
  io.redirect.valid := commitValid && commitEntry.misPred
  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 已提交
152 153 154 155

  // branch insts enq
  var full = WireInit(isFull(headPtrNext, tailPtr))
  var tailPtrNext = WireInit(tailPtr)
L
LinJiawei 已提交
156
  for((enq, brTag) <- io.enqReqs.zip(io.brTags)){
L
LinJiawei 已提交
157
    enq.ready := !full
L
LinJiawei 已提交
158
    brTag := tailPtrNext
L
LinJiawei 已提交
159
    when(enq.fire()){
160
      brQueue(tailPtrNext.value).npc := enq.bits.cf.pnpc
L
LinJiawei 已提交
161 162
      brQueue(tailPtrNext.value).ptrFlag := tailPtrNext.flag
    }
163

L
LinJiawei 已提交
164 165 166 167 168 169 170
    tailPtrNext = tailPtrNext + enq.fire()
    full = isFull(tailPtrNext, headPtrNext)
  }
  tailPtr := tailPtrNext

  // exu write back
  for(exuWb <- io.exuRedirect){
L
LinJiawei 已提交
171
    when(exuWb.valid){
L
LinJiawei 已提交
172 173 174
      val wbIdx = exuWb.bits.redirect.brTag.value
      XSInfo(
        p"exu write back: brTag:${exuWb.bits.redirect.brTag}" +
175
          p" pc=${Hexadecimal(exuWb.bits.uop.cf.pc)} pnpc=${Hexadecimal(brQueue(wbIdx).npc)} target=${Hexadecimal(exuWb.bits.redirect.target)}\n"
L
LinJiawei 已提交
176
      )
177
      stateQueue(wbIdx) := s_wb
L
LinJiawei 已提交
178 179
      brQueue(wbIdx).exuOut := exuWb.bits
      brQueue(wbIdx).misPred := brQueue(wbIdx).npc =/= exuWb.bits.redirect.target
180 181 182 183 184 185 186 187 188
      // 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 已提交
189 190 191
    }
  }

L
LinJiawei 已提交
192 193
  when(io.roqRedirect.valid){
    // exception
194
    stateQueue.foreach(_ := s_idle)
L
LinJiawei 已提交
195 196 197 198 199 200 201
    headPtr := BrqPtr(false.B, 0.U)
    tailPtr := BrqPtr(false.B, 0.U)
  }.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)){
202
        s := s_idle
L
LinJiawei 已提交
203 204 205
      }
    })
    tailPtr := io.redirect.bits.brTag + true.B
L
LinJiawei 已提交
206
  }
L
LinJiawei 已提交
207 208 209 210 211 212 213 214 215 216




  // 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 已提交
217
    XSDebug(
L
LinJiawei 已提交
218 219
      debug_normal_mode,
      p"enq v:${io.enqReqs(i).valid} rdy:${io.enqReqs(i).ready} pc:${Hexadecimal(io.enqReqs(i).bits.cf.pc)}" +
L
LinJiawei 已提交
220
        p" brTag:${io.brTags(i)}\n"
L
LinJiawei 已提交
221 222 223 224
    )
  }

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

L
LinJiawei 已提交
226
  XSInfo(debug_brq_redirect, p"brq redirect, target:${Hexadecimal(io.redirect.bits.target)}\n")
227 228 229 230 231 232 233 234 235 236 237
  val mbpInstr = io.out.fire()
  val mbpRight = io.out.fire() && !commitEntry.misPred
  val mbpWrong = io.out.fire() && commitEntry.misPred
  val mbpBRight = io.out.fire() && !commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.B
  val mbpBWrong = io.out.fire() && commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.B
  val mbpJRight = io.out.fire() && !commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.J
  val mbpJWrong = io.out.fire() && commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.J
  val mbpIRight = io.out.fire() && !commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.I
  val mbpIWrong = io.out.fire() && commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.I
  val mbpRRight = io.out.fire() && !commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.R
  val mbpRWrong = io.out.fire() && commitEntry.misPred && commitEntry.exuOut.redirect._type===BTBtype.R
J
jinyue110 已提交
238
  if(EnableBPU){
239 240 241 242 243 244 245 246 247 248 249
    BoringUtils.addSource(mbpInstr, "MbpInstr")
    BoringUtils.addSource(mbpRight, "MbpRight")
    BoringUtils.addSource(mbpWrong, "MbpWrong")
    BoringUtils.addSource(mbpBRight, "MbpBRight")
    BoringUtils.addSource(mbpBWrong, "MbpBWrong")
    BoringUtils.addSource(mbpJRight, "MbpJRight")
    BoringUtils.addSource(mbpJWrong, "MbpJWrong")
    BoringUtils.addSource(mbpIRight, "MbpIRight")
    BoringUtils.addSource(mbpIWrong, "MbpIWrong")
    BoringUtils.addSource(mbpRRight, "MbpRRight")
    BoringUtils.addSource(mbpRWrong, "MbpRWrong")
J
jinyue110 已提交
250
  }
251
}