提交 e8a11391 编写于 作者: Y YikeZhou

RsDataTest: add a tester for ReservationStationData

RsData: fix log print bug and data/uop-read bug
上级 60d440d1
...@@ -353,15 +353,16 @@ class ReservationStationData ...@@ -353,15 +353,16 @@ class ReservationStationData
val feedback = Flipped(ValidIO(new TlbFeedback)) val feedback = Flipped(ValidIO(new TlbFeedback))
}) })
val uopMem = Module(new SyncDataModuleTemplate(new MicroOp, iqSize, 1, iqSize)) // Data
uopMem.io <> DontCare // ------------------------
uopMem.io.wen.foreach(_ := false.B)
val data = List.tabulate(srcNum)(_ => Module(new SyncDataModuleTemplate(UInt((XLEN + 1).W), iqSize, if (!env.FPGAPlatform) iqSize else 1, iqSize))) val data = List.tabulate(srcNum)(_ => Module(new SyncDataModuleTemplate(UInt((XLEN + 1).W), iqSize, if (!env.FPGAPlatform) iqSize else 1, iqSize)))
data.foreach(_.io <> DontCare) data.foreach(_.io <> DontCare)
data.foreach(_.io.wen.foreach(_ := false.B)) data.foreach(_.io.wen.foreach(_ := false.B))
// data/uop read/write interface // data/uop read/write interface
// ! warning: reading has 1 cycle delay, so input addr is used in next cycle
// luckily, for fpga platform, read port has fixed value
// otherwise, read port has same value as read addr
def dataRead(iqIdx: UInt, srcIdx: Int): UInt = { def dataRead(iqIdx: UInt, srcIdx: Int): UInt = {
if (env.FPGAPlatform) { if (env.FPGAPlatform) {
data(srcIdx).io.raddr(0) := iqIdx data(srcIdx).io.raddr(0) := iqIdx
...@@ -376,8 +377,19 @@ class ReservationStationData ...@@ -376,8 +377,19 @@ class ReservationStationData
data(srcIdx).io.wdata(iqIdx) := wdata data(srcIdx).io.wdata(iqIdx) := wdata
data(srcIdx).io.wen(iqIdx) := true.B data(srcIdx).io.wen(iqIdx) := true.B
} }
// debug data: only for XSDebug log printing!
val debug_data = if (!env.FPGAPlatform) List.tabulate(srcNum)(i => WireInit(VecInit((0 until iqSize).map(j => dataRead(j.U, i))))) else null
// Uop
// ------------------------
val uopMem = Module(new SyncDataModuleTemplate(new MicroOp, iqSize, iqSize, 1))
uopMem.io <> DontCare
uopMem.io.wen.foreach(_ := false.B)
// uop -- read = iqSize write = 1
// uopMem 's read ports have fixed values
uopMem.io.raddr.zipWithIndex.foreach{ case(r, i) => r := i.U }
def uopRead(iqIdx: UInt): MicroOp = { def uopRead(iqIdx: UInt): MicroOp = {
uopMem.io.raddr(iqIdx) := iqIdx
uopMem.io.rdata(iqIdx) uopMem.io.rdata(iqIdx)
} }
def uopWrite(iqIdx: UInt, wdata: MicroOp) = { def uopWrite(iqIdx: UInt, wdata: MicroOp) = {
...@@ -387,7 +399,6 @@ class ReservationStationData ...@@ -387,7 +399,6 @@ class ReservationStationData
} }
val uop = WireInit(VecInit((0 until iqSize).map(i => uopRead(i.U)))) val uop = WireInit(VecInit((0 until iqSize).map(i => uopRead(i.U))))
val debug_data = if (!env.FPGAPlatform) List.tabulate(srcNum)(i => WireInit(VecInit((0 until iqSize).map(j => dataRead(j.U, i))))) else null
val enq = io.ctrl.enqPtr val enq = io.ctrl.enqPtr
val sel = io.ctrl.deqPtr val sel = io.ctrl.deqPtr
...@@ -410,7 +421,7 @@ class ReservationStationData ...@@ -410,7 +421,7 @@ class ReservationStationData
when (enqEnReg) { when (enqEnReg) {
(0 until srcNum).foreach(i => dataWrite(enqPtrReg, i, io.srcRegValue(i))) (0 until srcNum).foreach(i => dataWrite(enqPtrReg, i, io.srcRegValue(i)))
XSDebug(p"${exuCfg.name}: enqPtrReg:${enqPtrReg} pc: ${Hexadecimal(uop(enqPtrReg).cf.pc)}\n") XSDebug(p"${exuCfg.name}: enqPtrReg:${enqPtrReg} pc: ${Hexadecimal(uop(enqPtrReg).cf.pc)}\n")
XSDebug("[srcRegValue] " + List.tabulate(srcNum)(idx => p"src$idx: ${Hexadecimal(io.srcRegValue(idx))}").reduce(_ + " " + _) + "\n") XSDebug(p"[srcRegValue] " + List.tabulate(srcNum)(idx => p"src$idx: ${Hexadecimal(io.srcRegValue(idx))}").reduce((p1, p2) => p1 + " " + p2) + "\n")
} }
def wbHit(uop: MicroOp, src: UInt, srctype: UInt): Bool = { def wbHit(uop: MicroOp, src: UInt, srctype: UInt): Bool = {
...@@ -460,9 +471,9 @@ class ReservationStationData ...@@ -460,9 +471,9 @@ class ReservationStationData
val exuInput = io.deq.bits val exuInput = io.deq.bits
exuInput := DontCare exuInput := DontCare
exuInput.uop := uop(deq) exuInput.uop := uop(deq)
exuInput.src1 := Mux(uop(deq).ctrl.src1Type === SrcType.pc, SignExt(uop(deq).cf.pc, XLEN + 1), dataRead(deq, 0)) exuInput.src1 := Mux(uop(deq).ctrl.src1Type === SrcType.pc, SignExt(uop(deq).cf.pc, XLEN + 1), dataRead(sel.bits, 0))
if (srcNum > 1) exuInput.src2 := Mux(uop(deq).ctrl.src2Type === SrcType.imm, uop(deq).ctrl.imm, dataRead(deq, 1)) if (srcNum > 1) exuInput.src2 := Mux(uop(deq).ctrl.src2Type === SrcType.imm, uop(deq).ctrl.imm, dataRead(sel.bits, 1))
if (srcNum > 2) exuInput.src3 := dataRead(deq, 2) if (srcNum > 2) exuInput.src3 := dataRead(sel.bits, 2)
io.deq.valid := RegNext(sel.valid) io.deq.valid := RegNext(sel.valid)
if (nonBlocked) { assert(RegNext(io.deq.ready), s"${name} if fu wanna fast wakeup, it should not block")} if (nonBlocked) { assert(RegNext(io.deq.ready), s"${name} if fu wanna fast wakeup, it should not block")}
......
package xiangshan.backend.issue
import chisel3._
import chiseltest._
import chisel3.experimental.BundleLiterals._
import chiseltest.experimental.TestOptionBuilder._
import chiseltest.internal.{VerilatorBackendAnnotation, LineCoverageAnnotation, ToggleCoverageAnnotation, UserCoverageAnnotation, StructuralCoverageAnnotation}
import firrtl.stage.RunFirrtlTransformAnnotation
import xstransforms.PrintModuleName
import org.scalatest._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.must.Matchers
import xiangshan.testutils._
import xiangshan.backend.exu.Exu
import scala.util.Random
import xiangshan.MicroOp
import xiangshan.testutils.AddSinks
import xiangshan.XSModule
import xiangshan.SrcState
import xiangshan.SrcType
import xiangshan.HasXSParameter
class RsDataWrapper extends XSModule {
val testTop = Module(new ReservationStationData(Exu.stExeUnitCfg, 1, 1, -1, false))
val io = IO(testTop.io.cloneType)
AddSinks()
io <> testTop.io
}
class ReservationStationDataTest extends AnyFlatSpec
with ChiselScalatestTester
with Matchers
with ParallelTestExecution
with HasPartialDecoupledDriver
with HasXSParameter {
top.Parameters.set(top.Parameters.debugParameters)
val annos = Seq(
VerilatorBackendAnnotation,
RunFirrtlTransformAnnotation(new PrintModuleName)
)
it should "read/write uop and data correctly" in {
test(new RsDataWrapper).withAnnotations(annos) { c =>
def nextSrcRegValue(): UInt = {
(scala.math.abs(Random.nextLong())).U
}
val rounds = IssQueSize
for (i <- 0 until rounds) {
fork {
// disable redirect/broadcastedUop/writeBackedData/extraListenPorts
c.io.broadcastedUops.foreach(_.valid.poke(false.B))
c.io.extraListenPorts.foreach(_.valid.poke(false.B))
c.io.redirect.valid.poke(false.B)
// send ctrl message to enq data
c.io.ctrl.deqPtr.valid.poke(false.B)
c.io.ctrl.enqPtr.poke(i.U)
c.io.ctrl.enqCtrl.valid.poke(true.B)
// build uop
val uop = c.io.ctrl.enqCtrl.bits
uop.cf.pc.poke(2333.U) // pc
uop.ctrl.imm.poke(4567.U) // imm and srcType
uop.ctrl.rfWen.poke(true.B)
uop.ctrl.src1Type.poke(SrcType.reg)
uop.ctrl.src2Type.poke(SrcType.reg)
uop.ctrl.src3Type.poke(SrcType.reg)
uop.psrc1.poke(11.U)
uop.psrc2.poke(22.U)
uop.psrc3.poke(33.U)
uop.pdest.poke(44.U)
uop.src1State.poke(SrcState.rdy)
uop.src2State.poke(SrcState.rdy)
uop.src3State.poke(SrcState.rdy)
// generate random src op
c.io.srcRegValue.foreach(_.poke(nextSrcRegValue()))
c.clock.step(1)
} .fork {
c.io.deq.ready.poke(false.B)
c.clock.step(1)
} .join()
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册