未验证 提交 2be37cbb 编写于 作者: L ljw 提交者: GitHub

Merge pull request #381 from RISCVERS/opt-brq

brq: add needAlloc to optimize timing
......@@ -80,13 +80,11 @@ class CtrlBlock extends XSModule with HasCircularQueuePtrHelper {
io.frontend.cfiUpdateInfo <> brq.io.cfiInfo
decode.io.in <> io.frontend.cfVec
decode.io.toBrq <> brq.io.enqReqs
decode.io.brTags <> brq.io.brTags
decode.io.enqBrq <> brq.io.enq
brq.io.redirect.valid <> redirectValid
brq.io.redirect.bits <> redirect
brq.io.bcommit <> roq.io.bcommit
brq.io.enqReqs <> decode.io.toBrq
brq.io.exuRedirectWb <> io.fromIntBlock.exuRedirect
// pipeline between decode and dispatch
......
......@@ -38,14 +38,18 @@ object BrqPtr extends HasXSParameter {
}
}
class BrqEnqIO extends XSBundle {
val needAlloc = Vec(RenameWidth, Input(Bool()))
val req = Vec(RenameWidth, Flipped(DecoupledIO(new CtrlFlow)))
val resp = Vec(RenameWidth, Output(new BrqPtr))
}
class BrqIO extends XSBundle{
val redirect = Input(ValidIO(new Redirect))
// receive branch/jump calculated target
val exuRedirectWb = Vec(exuParameters.AluCnt + exuParameters.JmpCnt, Flipped(ValidIO(new ExuOutput)))
// from decode, branch insts enq
val enqReqs = Vec(DecodeWidth, Flipped(DecoupledIO(new CfCtrl)))
// to decode
val brTags = Output(Vec(DecodeWidth, new BrqPtr))
val enq = new BrqEnqIO
// to roq
val out = ValidIO(new ExuOutput)
// misprediction, flush pipeline
......@@ -118,22 +122,22 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
val lastCycleRedirect = RegNext(io.redirect.valid)
val validEntries = distanceBetween(tailPtr, headPtr)
for(i <- 0 until DecodeWidth){
val offset = if(i == 0) 0.U else PopCount(io.enqReqs.take(i).map(_.valid))
val offset = if (i == 0) 0.U else PopCount(io.enq.needAlloc.take(i))
val brTag = tailPtr + offset
val idx = brTag.value
io.enqReqs(i).ready := validEntries <= (BrqSize - (i + 1)).U && !lastCycleRedirect
io.brTags(i) := brTag
when (io.enqReqs(i).fire()) {
io.enq.req(i).ready := validEntries <= (BrqSize - (i + 1)).U && !lastCycleRedirect
io.enq.resp(i) := brTag
when (io.enq.req(i).fire()) {
brQueue(idx).ptrFlag := brTag.flag
brQueue(idx).exuOut.brUpdate.pc := io.enqReqs(i).bits.cf.pc
brQueue(idx).exuOut.brUpdate.pnpc := io.enqReqs(i).bits.cf.brUpdate.pnpc
brQueue(idx).exuOut.brUpdate.fetchIdx := io.enqReqs(i).bits.cf.brUpdate.fetchIdx
brQueue(idx).exuOut.brUpdate.pd := io.enqReqs(i).bits.cf.brUpdate.pd
brQueue(idx).exuOut.brUpdate.bpuMeta := io.enqReqs(i).bits.cf.brUpdate.bpuMeta
brQueue(idx).exuOut.brUpdate.pc := io.enq.req(i).bits.pc
brQueue(idx).exuOut.brUpdate.pnpc := io.enq.req(i).bits.brUpdate.pnpc
brQueue(idx).exuOut.brUpdate.fetchIdx := io.enq.req(i).bits.brUpdate.fetchIdx
brQueue(idx).exuOut.brUpdate.pd := io.enq.req(i).bits.brUpdate.pd
brQueue(idx).exuOut.brUpdate.bpuMeta := io.enq.req(i).bits.brUpdate.bpuMeta
stateQueue(idx) := s_idle
}
}
val enqCnt = PopCount(io.enqReqs.map(_.fire()))
val enqCnt = PopCount(io.enq.req.map(_.fire()))
tailPtr := tailPtr + enqCnt
/**
......@@ -194,8 +198,8 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
for(i <- 0 until DecodeWidth){
XSDebug(
debug_normal_mode,
p"enq v:${io.enqReqs(i).valid} rdy:${io.enqReqs(i).ready} pc:${Hexadecimal(io.enqReqs(i).bits.cf.pc)}" +
p" brTag:${io.brTags(i)}\n"
p"enq v:${io.enq.req(i).valid} rdy:${io.enq.req(i).ready} pc:${Hexadecimal(io.enq.req(i).bits.pc)}" +
p" brTag:${io.enq.resp(i)}\n"
)
}
......
......@@ -3,15 +3,13 @@ package xiangshan.backend.decode
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.backend.brq.BrqPtr
import xiangshan.backend.brq.BrqEnqIO
import utils._
class DecodeStage extends XSModule {
val io = IO(new Bundle() {
// enq Brq
val toBrq = Vec(DecodeWidth, DecoupledIO(new CfCtrl))
// get brMask/brTag
val brTags = Input(Vec(DecodeWidth, new BrqPtr))
val enqBrq = Flipped(new BrqEnqIO)
// from Ibuffer
val in = Vec(DecodeWidth, Flipped(DecoupledIO(new CtrlFlow)))
......@@ -19,9 +17,8 @@ class DecodeStage extends XSModule {
// to DecBuffer
val out = Vec(DecodeWidth, DecoupledIO(new CfCtrl))
})
val decoders = Seq.fill(DecodeWidth)(Module(new DecodeUnit))
val decoderToBrq = Wire(Vec(DecodeWidth, new CfCtrl)) // without brTag and brMask
val decoderToDecBuffer = Wire(Vec(DecodeWidth, new CfCtrl)) // with brTag and brMask
// Handshake ---------------------
// 1. if current instruction is valid, then:
......@@ -33,21 +30,23 @@ class DecodeStage extends XSModule {
for (i <- 0 until DecodeWidth) {
decoders(i).io.enq.ctrl_flow <> io.in(i).bits
decoderToBrq(i) := decoders(i).io.deq.cf_ctrl // CfCtrl without bfTag and brMask
decoderToBrq(i).brTag := DontCare
io.toBrq(i).bits := decoderToBrq(i)
decoderToDecBuffer(i) := decoders(i).io.deq.cf_ctrl
decoderToDecBuffer(i).brTag := io.brTags(i)
io.out(i).bits := decoderToDecBuffer(i)
val isMret = decoders(i).io.deq.cf_ctrl.cf.instr === BitPat("b001100000010_00000_000_00000_1110011")
val isSret = decoders(i).io.deq.cf_ctrl.cf.instr === BitPat("b000100000010_00000_000_00000_1110011")
val thisBrqValid = !decoders(i).io.deq.cf_ctrl.cf.brUpdate.pd.notCFI || isMret || isSret
io.in(i).ready := io.out(i).ready && io.toBrq(i).ready
io.out(i).valid := io.in(i).valid && io.toBrq(i).ready
io.toBrq(i).valid := io.in(i).valid && thisBrqValid && io.out(i).ready
XSDebug(io.in(i).valid || io.out(i).valid || io.toBrq(i).valid, "i:%d In(%d %d) Out(%d %d) ToBrq(%d %d) pc:%x instr:%x\n", i.U, io.in(i).valid, io.in(i).ready, io.out(i).valid, io.out(i).ready, io.toBrq(i).valid, io.toBrq(i).ready, io.in(i).bits.pc, io.in(i).bits.instr)
val isMret = io.in(i).bits.instr === BitPat("b001100000010_00000_000_00000_1110011")
val isSret = io.in(i).bits.instr === BitPat("b000100000010_00000_000_00000_1110011")
val thisBrqValid = !io.in(i).bits.brUpdate.pd.notCFI || isMret || isSret
io.enqBrq.needAlloc(i) := thisBrqValid
io.enqBrq.req(i).valid := io.in(i).valid && thisBrqValid && io.out(i).ready
io.enqBrq.req(i).bits := io.in(i).bits
io.out(i).valid := io.in(i).valid && io.enqBrq.req(i).ready
io.out(i).bits := decoders(i).io.deq.cf_ctrl
io.out(i).bits.brTag := io.enqBrq.resp(i)
io.in(i).ready := io.out(i).ready && io.enqBrq.req(i).ready
XSDebug(io.in(i).valid || io.out(i).valid || io.enqBrq.req(i).valid,
"i:%d In(%d %d) Out(%d %d) ToBrq(%d %d) pc:%x instr:%x\n",
i.U, io.in(i).valid, io.in(i).ready, io.out(i).valid, io.out(i).ready,
io.enqBrq.req(i).valid, io.enqBrq.req(i).ready, io.in(i).bits.pc, io.in(i).bits.instr)
}
}
\ No newline at end of file
}
package xiangshan.backend.brq
import org.scalatest._
import chiseltest._
import chisel3._
import chisel3.experimental.BundleLiterals._
import chisel3.util._
import chiseltest.experimental.TestOptionBuilder._
import chiseltest.internal.VerilatorBackendAnnotation
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.must.Matchers
import top.Parameters
import utils.XSLog
import xiangshan._
import xiangshan.testutils._
import xiangshan.testutils.TestCaseGenerator._
import scala.util.Random
class BrqTest extends AnyFlatSpec
with ChiselScalatestTester
with Matchers
with ParallelTestExecution
with HasPartialDecoupledDriver {
it should "redirect out-of-order, dequeue in-order" in {
Parameters.set(Parameters.debugParameters)
test(new Brq {
AddSinks()
}).withAnnotations(Seq()) { c =>
def genEnqReq(x: => DecoupledIO[CfCtrl], pc: Long) = {
chiselTypeOf(x.bits).Lit(
_.cf.pc -> pc.U,
_.cf.brUpdate.pnpc -> (pc+4).U
)
}
def genExuWb(exuRedirect: => Valid[ExuOutput], tagIdx: Int, tagFlag: Boolean, target: Long) = {
chiselTypeOf(exuRedirect.bits).Lit(
_.redirect.brTag.value -> tagIdx.U,
_.redirect.brTag.flag -> tagFlag.B,
_.redirect.target -> target.U
)
}
c.io.enqReqs.head.initSource().setSourceClock(c.clock)
var brqPtrSeq = Seq[(BigInt, Boolean)]()
for (i <- 0 until 10) {
val enqPort = c.io.enqReqs.head
enqPort.enqueuePartial(genEnqReq(enqPort, i * 0x1000))
}
var enqTags = List.tabulate(10)(i => i)
val misPred = 6
println(s"enqTags:$enqTags misPredTag:$misPred")
enqTags = enqTags.take(misPred + 1)
var commitTags, deqTags = List[Int]()
def checkCommit = {
if (c.io.out.valid.peek().litToBoolean) {
commitTags = commitTags :+ c.io.redirect.bits.brTag.value.peek().litValue().toInt
println(s"====commited tags:$commitTags====")
}
}
def checkDeq = {
if(c.io.out.valid.peek().litToBoolean){
deqTags = deqTags :+ c.io.out.bits.uop.brTag.value.peek().litValue().toInt
println(s"====deq tags:$deqTags====")
}
}
println("====Start random write back====")
val wbPort = c.io.exuRedirectWb.head
//-----------------write back-----------------//
while (enqTags.nonEmpty) {
val idx = Random.nextInt(enqTags.size)
val tag = enqTags(idx)
println(s"====write tag:$tag back to Brq====")
enqTags = enqTags.filter(x => x != tag)
wbPort.valid.poke(true.B)
wbPort.bits.pokePartial(
genExuWb(wbPort, tag, tagFlag = false, if (tag == misPred) 0xffff else tag * 0x1000 + 4)
)
checkCommit
c.clock.step(1)
wbPort.valid.poke(false.B)
for (i <- 0 until Random.nextInt(3)) {
checkCommit
c.clock.step(1)
}
}
c.io.bcommit.poke((misPred+1).U)
c.clock.step(1)
c.io.bcommit.poke(0.U)
while (deqTags.size != misPred+1) {
checkCommit
checkDeq
c.clock.step(1)
}
c.clock.step(10)
val left = commitTags.takeWhile(x => x!=misPred)
val right = commitTags.dropWhile(x => x!=misPred).drop(1)
println(s"commited before mispred: $left")
println(s"commited after mispred: $right")
def isValidCommitSeq(in: Seq[Int]): Boolean = {
for(i <- 1 until in.size){
if(in(i) == in(i-1)) return false
}
true
}
assert(isValidCommitSeq(left) && isValidCommitSeq(right))
println(s"deq tags: $deqTags")
def isValidDeqSeq(in: Seq[Int]): Boolean = {
in.zipWithIndex.map(x => x._1==x._2).reduce(_&&_)
}
assert(isValidDeqSeq(deqTags))
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册