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

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


L
LinJiawei 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
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)
  }

  // this.age <= that.age
  final def <= (that: BrqPtr): Bool = {
    Mux(this.flag === that.flag,
      this.value > that.value,
      this.value < that.value
    )
  }

  def needBrFlush(redirectTag: BrqPtr): Bool = this <= redirectTag

  def needFlush(redirect: Valid[Redirect]): Bool = {
    val redirectTag = redirect.bits.brTag
//    assert(!(
//      redirect.valid &&
//        !redirect.bits.isException &&
//        (flag=/=redirectTag.flag) &&
//        (this.value===redirectTag.value)
//      )
//    )
    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
  }
}

60

L
LinJiawei 已提交
61
class Brq extends XSModule {
62
  val io = IO(new Bundle() {
63
    // interrupt/exception happen, flush Brq
64
    val roqRedirect = Input(Valid(new Redirect))
65
    // receive branch/jump calculated target
L
LinJiawei 已提交
66
    val exuRedirect = Vec(exuConfig.AluCnt + exuConfig.BruCnt, Flipped(ValidIO(new ExuOutput)))
67
    // from decode, branch insts enq
68
    val enqReqs = Vec(DecodeWidth, Flipped(DecoupledIO(new CfCtrl)))
69
    // to decode
L
LinJiawei 已提交
70
    val brTags = Output(Vec(DecodeWidth, new BrqPtr))
L
LinJiawei 已提交
71 72
    // to roq
    val out = ValidIO(new ExuOutput)
73
    // misprediction, flush pipeline
74 75
    val redirect = Output(Valid(new Redirect))
  })
L
LinJiawei 已提交
76

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

  val brQueue = Reg(Vec(BrqSize, new BrqEntry))
L
LinJiawei 已提交
83 84
  val wbFlags = RegInit(VecInit(Seq.fill(BrqSize)(false.B)))

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

L
LinJiawei 已提交
87 88
  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 已提交
89 90 91


  // dequeue
L
LinJiawei 已提交
92
  val headIdx = headPtr.value
L
LinJiawei 已提交
93 94 95 96 97 98 99 100
  val deqValid = wbFlags(headIdx)
  val deqEntry = brQueue(headIdx)

  val headPtrNext = WireInit(headPtr + deqValid)
  when(deqValid){
    wbFlags(headIdx) := false.B
  }
  headPtr := headPtrNext
L
LinJiawei 已提交
101 102 103 104
  io.redirect.valid := deqValid && (deqEntry.npc =/= deqEntry.exuOut.redirect.target)
  io.redirect.bits := deqEntry.exuOut.redirect
  io.out.valid := deqValid
  io.out.bits := deqEntry.exuOut
L
LinJiawei 已提交
105 106 107 108

  // branch insts enq
  var full = WireInit(isFull(headPtrNext, tailPtr))
  var tailPtrNext = WireInit(tailPtr)
L
LinJiawei 已提交
109
  for((enq, brTag) <- io.enqReqs.zip(io.brTags)){
L
LinJiawei 已提交
110
    enq.ready := !full
L
LinJiawei 已提交
111
    brTag := tailPtrNext
112
    // TODO: check rvc and use predict npc
L
LinJiawei 已提交
113
    when(enq.fire()){ brQueue(tailPtrNext.value).npc := enq.bits.cf.pc + 4.U }
L
LinJiawei 已提交
114 115 116 117 118 119 120
    tailPtrNext = tailPtrNext + enq.fire()
    full = isFull(tailPtrNext, headPtrNext)
  }
  tailPtr := tailPtrNext

  // exu write back
  for(exuWb <- io.exuRedirect){
L
LinJiawei 已提交
121
    when(exuWb.valid){
L
LinJiawei 已提交
122 123
      wbFlags(exuWb.bits.uop.brTag.value) := true.B
      brQueue(exuWb.bits.uop.brTag.value).exuOut := exuWb.bits
L
LinJiawei 已提交
124 125 126 127 128 129
    }
  }

  // when redirect, reset all regs
  when(io.roqRedirect.valid || io.redirect.valid){
    wbFlags.foreach(_ := false.B)
Y
Yinan Xu 已提交
130 131 132
    val resetPtr  = io.redirect.bits.brTag + true.B
    headPtr := resetPtr
    tailPtr := resetPtr
L
LinJiawei 已提交
133
  }
L
LinJiawei 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146




  // 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){
    XSInfo(
      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 已提交
147
        p" brTag:${io.brTags(i)}\n"
L
LinJiawei 已提交
148 149 150 151
    )
  }

  XSInfo(debug_roq_redirect, "roq redirect, flush brq\n")
L
LinJiawei 已提交
152
  XSInfo(debug_brq_redirect, p"brq redirect, target:${Hexadecimal(io.redirect.bits.target)} flptr:${io.redirect.bits.freelistAllocPtr}\n")
153
}