BrqTest.scala 3.6 KB
Newer Older
L
LinJiawei 已提交
1 2 3 4 5 6 7 8 9
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
L
LinJiawei 已提交
10
import utils.XSLog
L
LinJiawei 已提交
11 12 13 14 15 16 17 18 19 20 21
import xiangshan._
import xiangshan.testutils._
import xiangshan.testutils.TestCaseGenerator._

import scala.util.Random

class BrqTest extends FlatSpec
  with ChiselScalatestTester
  with Matchers
  with ParallelTestExecution
  with HasPartialDecoupledDriver {
L
LinJiawei 已提交
22
  it should "redirect out-of-order, dequeue in-order" in {
23
    XSLog.generateLog = true
L
LinJiawei 已提交
24

L
LinJiawei 已提交
25 26
    test(new Brq {
      AddSinks()
27
    }).withAnnotations(Seq()) { c =>
L
LinJiawei 已提交
28 29 30

      def genEnqReq(x: => DecoupledIO[CfCtrl], pc: Long) = {
        chiselTypeOf(x.bits).Lit(
L
LinJiawei 已提交
31 32
          _.cf.pc -> pc.U,
          _.cf.pnpc -> (pc+4).U
L
LinJiawei 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
        )
      }

      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)
54
      val misPred = 6
L
LinJiawei 已提交
55 56
      println(s"enqTags:$enqTags misPredTag:$misPred")
      enqTags = enqTags.take(misPred + 1)
L
LinJiawei 已提交
57
      var commitTags, deqTags = List[Int]()
L
LinJiawei 已提交
58

L
LinJiawei 已提交
59
      def checkCommit = {
L
LinJiawei 已提交
60
        if (c.io.out.valid.peek().litToBoolean) {
L
LinJiawei 已提交
61 62 63 64 65 66 67
          commitTags = commitTags :+ c.io.redirect.bits.brTag.value.peek().litValue().toInt
          println(s"====commited tags:$commitTags====")
        }
      }
      def checkDeq =  {
        if(c.io.inOrderBrInfo.valid.peek().litToBoolean){
          deqTags = deqTags :+ c.io.inOrderBrInfo.redirect.brTag.value.peek().litValue().toInt
L
LinJiawei 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
          println(s"====deq tags:$deqTags====")
        }
      }


      println("====Start random write back====")
      val wbPort = c.io.exuRedirect.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)
        )
L
LinJiawei 已提交
85
        checkCommit
L
LinJiawei 已提交
86 87 88
        c.clock.step(1)
        wbPort.valid.poke(false.B)
        for (i <- 0 until Random.nextInt(3)) {
L
LinJiawei 已提交
89
          checkCommit
L
LinJiawei 已提交
90 91 92
          c.clock.step(1)
        }
      }
L
LinJiawei 已提交
93
      c.io.bcommit.poke((misPred+1).U)
94 95
      c.clock.step(1)
      c.io.bcommit.poke(0.U)
L
LinJiawei 已提交
96
      while (deqTags.size != misPred+1) {
L
LinJiawei 已提交
97
        checkCommit
L
LinJiawei 已提交
98 99 100 101 102 103
        checkDeq
        c.clock.step(1)
      }

      c.clock.step(10)

L
LinJiawei 已提交
104 105
      val left = commitTags.takeWhile(x => x!=misPred)
      val right = commitTags.dropWhile(x => x!=misPred).drop(1)
L
LinJiawei 已提交
106

L
LinJiawei 已提交
107 108
      println(s"commited before mispred: $left")
      println(s"commited after mispred: $right")
L
LinJiawei 已提交
109

L
LinJiawei 已提交
110
      def isValidCommitSeq(in: Seq[Int]): Boolean = {
L
LinJiawei 已提交
111 112 113 114 115
        for(i <- 1 until in.size){
          if(in(i) == in(i-1)) return false
        }
        true
      }
L
LinJiawei 已提交
116 117 118
      assert(isValidCommitSeq(left) && isValidCommitSeq(right))

      println(s"deq tags: $deqTags")
L
LinJiawei 已提交
119

L
LinJiawei 已提交
120 121 122 123
      def isValidDeqSeq(in: Seq[Int]): Boolean = {
         in.zipWithIndex.map(x => x._1==x._2).reduce(_&&_)
      }
      assert(isValidDeqSeq(deqTags))
L
LinJiawei 已提交
124 125 126
    }
  }
}