export more detailed status data from GroundTest
This commit is contained in:
parent
e194677087
commit
18967642de
@ -43,5 +43,7 @@ class CacheFillTest(implicit p: Parameters) extends GroundTest()(p)
|
|||||||
when (state === s_prefetch && round_done) { state := s_retrieve }
|
when (state === s_prefetch && round_done) { state := s_retrieve }
|
||||||
when (state === s_retrieve && round_done) { state := s_finished }
|
when (state === s_retrieve && round_done) { state := s_finished }
|
||||||
|
|
||||||
io.finished := (state === s_finished)
|
io.status.finished := (state === s_finished)
|
||||||
|
io.status.timeout.valid := Bool(false)
|
||||||
|
io.status.error.valid := Bool(false)
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,7 @@ class ComparatorClient(val target: Long)(implicit val p: Parameters) extends Mod
|
|||||||
val tl = new ClientUncachedTileLinkIO()
|
val tl = new ClientUncachedTileLinkIO()
|
||||||
val out = Decoupled(new Grant)
|
val out = Decoupled(new Grant)
|
||||||
val finished = Bool(OUTPUT)
|
val finished = Bool(OUTPUT)
|
||||||
|
val timeout = Bool(OUTPUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
val xacts = tlMaxClientXacts
|
val xacts = tlMaxClientXacts
|
||||||
@ -295,15 +296,18 @@ class ComparatorClient(val target: Long)(implicit val p: Parameters) extends Mod
|
|||||||
timer.io.stop.valid := io.tl.grant.fire() && io.tl.grant.bits.first()
|
timer.io.stop.valid := io.tl.grant.fire() && io.tl.grant.bits.first()
|
||||||
timer.io.stop.bits := io.tl.grant.bits.client_xact_id
|
timer.io.stop.bits := io.tl.grant.bits.client_xact_id
|
||||||
assert(!timer.io.timeout, "Comparator TL client timed out")
|
assert(!timer.io.timeout, "Comparator TL client timed out")
|
||||||
|
io.timeout := timer.io.timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComparatorSink(implicit val p: Parameters) extends Module
|
class ComparatorSink(implicit val p: Parameters) extends Module
|
||||||
with HasComparatorParameters
|
with HasComparatorParameters
|
||||||
with HasTileLinkParameters
|
with HasTileLinkParameters
|
||||||
|
with HasGroundTestConstants
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val in = Vec(nTargets, Decoupled(new Grant)).flip
|
val in = Vec(nTargets, Decoupled(new Grant)).flip
|
||||||
val finished = Bool(OUTPUT)
|
val finished = Bool(OUTPUT)
|
||||||
|
val error = Valid(UInt(width = errorCodeBits))
|
||||||
}
|
}
|
||||||
|
|
||||||
// could use a smaller Queue here, but would couple targets flow controls together
|
// could use a smaller Queue here, but would couple targets flow controls together
|
||||||
@ -321,10 +325,23 @@ class ComparatorSink(implicit val p: Parameters) extends Module
|
|||||||
printf("%d: %x =/= %x, g_type = %x\n", idx, base.data, g.data, g.g_type)
|
printf("%d: %x =/= %x, g_type = %x\n", idx, base.data, g.data, g.g_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val assert_conds = Seq(
|
||||||
|
g.is_builtin_type,
|
||||||
|
base.g_type === g.g_type,
|
||||||
|
base.addr_beat === g.addr_beat || !g.hasData(),
|
||||||
|
base.data === g.data || !g.hasData())
|
||||||
|
|
||||||
assert (g.is_builtin_type, "grant not builtin")
|
assert (g.is_builtin_type, "grant not builtin")
|
||||||
assert (base.g_type === g.g_type, "g_type mismatch")
|
assert (base.g_type === g.g_type, "g_type mismatch")
|
||||||
assert (base.addr_beat === g.addr_beat || !g.hasData(), "addr_beat mismatch")
|
assert (base.addr_beat === g.addr_beat || !g.hasData(), "addr_beat mismatch")
|
||||||
assert (base.data === g.data || !g.hasData(), "data mismatch")
|
assert (base.data === g.data || !g.hasData(), "data mismatch")
|
||||||
|
|
||||||
|
assert_conds.zipWithIndex.foreach { case (cond, i) =>
|
||||||
|
when (cond) {
|
||||||
|
io.error.valid := Bool(true)
|
||||||
|
io.error.bits := UInt(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
when (all_valid) {
|
when (all_valid) {
|
||||||
// Skip the results generated by the block wiping
|
// Skip the results generated by the block wiping
|
||||||
@ -355,6 +372,13 @@ class ComparatorCore(implicit p: Parameters) extends GroundTest()(p)
|
|||||||
sink.io.in(index) <> client.io.out
|
sink.io.in(index) <> client.io.out
|
||||||
client
|
client
|
||||||
}
|
}
|
||||||
|
val client_timeouts = clients.map(_.io.timeout)
|
||||||
|
|
||||||
io.finished := source.io.finished && sink.io.finished && clients.map(_.io.finished).reduce(_ && _)
|
io.status.finished := source.io.finished && sink.io.finished && clients.map(_.io.finished).reduce(_ && _)
|
||||||
|
io.status.timeout.valid := client_timeouts.reduce(_ || _)
|
||||||
|
io.status.timeout.bits := MuxCase(UInt(0),
|
||||||
|
client_timeouts.zipWithIndex.map {
|
||||||
|
case (timeout, i) => (timeout -> UInt(i))
|
||||||
|
})
|
||||||
|
io.status.error := sink.io.error
|
||||||
}
|
}
|
||||||
|
@ -1,231 +0,0 @@
|
|||||||
package groundtest
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
import uncore.tilelink._
|
|
||||||
import uncore.devices._
|
|
||||||
import uncore.devices.DmaRequest._
|
|
||||||
import uncore.util._
|
|
||||||
import uncore.constants._
|
|
||||||
import rocket._
|
|
||||||
import junctions.{PAddrBits, HasAddrMapParameters}
|
|
||||||
import cde.{Parameters, Field}
|
|
||||||
import scala.math.max
|
|
||||||
|
|
||||||
case class DmaTestCase(source: Int, dest: Int, length: Int)
|
|
||||||
|
|
||||||
object DmaTestCases {
|
|
||||||
def apply(cases: (Int, Int, Int) *): Seq[DmaTestCase] = {
|
|
||||||
cases.toSeq.map {
|
|
||||||
case (source, dest, length) => DmaTestCase(source, dest, length)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case class DmaStreamTestConfig(
|
|
||||||
source: Int, dest: Int, len: Int, size: Int)
|
|
||||||
|
|
||||||
case object DmaTestSet extends Field[Seq[DmaTestCase]]
|
|
||||||
case object DmaTestDataStart extends Field[Int]
|
|
||||||
case object DmaTestDataStride extends Field[Int]
|
|
||||||
|
|
||||||
case object DmaStreamTestSettings extends Field[DmaStreamTestConfig]
|
|
||||||
|
|
||||||
class DmaStatusReg(implicit val p: Parameters) extends Module
|
|
||||||
with HasDmaParameters with HasTileLinkParameters {
|
|
||||||
|
|
||||||
val io = new Bundle {
|
|
||||||
val csr = (new RoCCCSRs).flip
|
|
||||||
val incr_outstanding = Bool(INPUT)
|
|
||||||
val xact_outstanding = Bool(OUTPUT)
|
|
||||||
val resp_status = UInt(OUTPUT, dmaStatusBits)
|
|
||||||
}
|
|
||||||
|
|
||||||
val status_reg = Reg(UInt(width = dmaStatusBits))
|
|
||||||
|
|
||||||
val outstanding_cnt = TwoWayCounter(
|
|
||||||
io.incr_outstanding, io.csr.wen, tlMaxClientXacts)
|
|
||||||
|
|
||||||
when (io.csr.wen) { status_reg := io.csr.wdata }
|
|
||||||
|
|
||||||
io.xact_outstanding := outstanding_cnt > UInt(0)
|
|
||||||
io.resp_status := status_reg
|
|
||||||
io.csr.rdata(0) := status_reg
|
|
||||||
}
|
|
||||||
|
|
||||||
class DmaStreamTest(implicit p: Parameters) extends GroundTest()(p)
|
|
||||||
with HasDmaParameters with HasCoreParameters with HasAddrMapParameters {
|
|
||||||
val (s_start :: s_setup_req :: s_setup_wait ::
|
|
||||||
s_stream_out :: s_stream_in :: s_stream_wait ::
|
|
||||||
s_check_req :: s_check_wait :: s_done :: Nil) = Enum(Bits(), 9)
|
|
||||||
val state = Reg(init = s_start)
|
|
||||||
val lo_base = addrMap("devices:loopback").start
|
|
||||||
val conf = p(DmaStreamTestSettings)
|
|
||||||
|
|
||||||
val test_data = Vec.tabulate(conf.len) { i => UInt(i * 8, conf.size * 8) }
|
|
||||||
|
|
||||||
val (req_index, req_done) = Counter(io.cache.head.req.fire(), conf.len)
|
|
||||||
val (resp_index, resp_done) = Counter(io.cache.head.resp.fire(), conf.len)
|
|
||||||
|
|
||||||
val out_req = ClientDmaRequest(
|
|
||||||
cmd = DMA_CMD_SOUT,
|
|
||||||
src_start = UInt(conf.source),
|
|
||||||
dst_start = UInt(lo_base),
|
|
||||||
segment_size = UInt(conf.len * conf.size),
|
|
||||||
word_size = UInt(log2Up(conf.size)))
|
|
||||||
|
|
||||||
val in_req = ClientDmaRequest(
|
|
||||||
cmd = DMA_CMD_SIN,
|
|
||||||
src_start = UInt(lo_base),
|
|
||||||
dst_start = UInt(conf.dest),
|
|
||||||
segment_size = UInt(conf.len * conf.size),
|
|
||||||
word_size = UInt(log2Up(conf.size)))
|
|
||||||
|
|
||||||
val frontend = Module(new DmaFrontend)
|
|
||||||
frontend.io.cpu.req.valid := (state === s_stream_out) || (state === s_stream_in)
|
|
||||||
frontend.io.cpu.req.bits := Mux(state === s_stream_out, out_req, in_req)
|
|
||||||
|
|
||||||
io.ptw.head <> frontend.io.ptw
|
|
||||||
io.mem.head <> frontend.io.mem
|
|
||||||
|
|
||||||
val status_reg = Module(new DmaStatusReg)
|
|
||||||
//status_reg.io.csr <> io.csr
|
|
||||||
status_reg.io.incr_outstanding := frontend.io.incr_outstanding
|
|
||||||
|
|
||||||
val cache_addr_base = Mux(state === s_setup_req, UInt(conf.source), UInt(conf.dest))
|
|
||||||
val cache_req = io.cache.head.req
|
|
||||||
|
|
||||||
cache_req.valid := (state === s_setup_req) || (state === s_check_req)
|
|
||||||
cache_req.bits.addr := cache_addr_base + Cat(req_index, UInt(0, log2Up(conf.size)))
|
|
||||||
cache_req.bits.data := test_data(req_index)
|
|
||||||
cache_req.bits.typ := UInt(log2Up(conf.size))
|
|
||||||
cache_req.bits.cmd := Mux(state === s_setup_req, M_XWR, M_XRD)
|
|
||||||
|
|
||||||
when (state === s_start) { state := s_setup_req }
|
|
||||||
when (state === s_setup_req && req_done) { state := s_setup_wait }
|
|
||||||
when (state === s_check_req && req_done) { state := s_check_wait }
|
|
||||||
when (state === s_setup_wait && resp_done) { state := s_stream_out }
|
|
||||||
when (state === s_check_wait && resp_done) { state := s_done }
|
|
||||||
|
|
||||||
when (frontend.io.cpu.req.fire()) {
|
|
||||||
state := Mux(state === s_stream_out, s_stream_in, s_stream_wait)
|
|
||||||
}
|
|
||||||
|
|
||||||
val dma_done = (state === s_stream_wait) &&
|
|
||||||
!frontend.io.busy && !status_reg.io.xact_outstanding
|
|
||||||
|
|
||||||
when (dma_done) { state := s_check_req }
|
|
||||||
|
|
||||||
val resp_data = io.cache.head.resp.bits.data(conf.size * 8 - 1, 0)
|
|
||||||
assert(!io.cache.head.resp.valid || !io.cache.head.resp.bits.has_data ||
|
|
||||||
resp_data === test_data(resp_index),
|
|
||||||
"Result data streamed in does not match data streamed out")
|
|
||||||
assert(!frontend.io.cpu.resp.valid || frontend.io.cpu.resp.bits.status === UInt(0),
|
|
||||||
"Frontend error response")
|
|
||||||
|
|
||||||
io.finished := (state === s_done)
|
|
||||||
}
|
|
||||||
|
|
||||||
class DmaTest(implicit p: Parameters) extends GroundTest()(p)
|
|
||||||
with HasDmaParameters with HasCoreParameters {
|
|
||||||
|
|
||||||
private val testSet = p(DmaTestSet)
|
|
||||||
private val dataStart = p(DmaTestDataStart)
|
|
||||||
private val dataStride = p(DmaTestDataStride)
|
|
||||||
private val wordBits = 32
|
|
||||||
private val wordBytes = wordBits / 8
|
|
||||||
private val pAddrBits = p(PAddrBits)
|
|
||||||
|
|
||||||
val sourceAddrs = Vec(testSet.map(test => UInt(test.source)))
|
|
||||||
val destAddrs = Vec(testSet.map(test => UInt(test.dest)))
|
|
||||||
val transferLengths = Vec(testSet.map(test => UInt(test.length)))
|
|
||||||
val testIdx = Reg(init = UInt(0, log2Up(testSet.size)))
|
|
||||||
|
|
||||||
val (s_start :: s_fill_req :: s_fill_resp :: s_copy_req :: s_copy_wait ::
|
|
||||||
s_check_req :: s_check_resp :: s_finished :: Nil) = Enum(Bits(), 8)
|
|
||||||
val state = Reg(init = s_start)
|
|
||||||
|
|
||||||
val req_data = Reg(UInt(width = wordBits))
|
|
||||||
val req_addr = Reg(UInt(width = pAddrBits))
|
|
||||||
val bytes_left = Reg(UInt(width = pAddrBits))
|
|
||||||
val prefetch = sourceAddrs(testIdx) === destAddrs(testIdx)
|
|
||||||
|
|
||||||
val frontend = Module(new DmaFrontend)
|
|
||||||
frontend.io.cpu.req.valid := (state === s_copy_req)
|
|
||||||
frontend.io.cpu.req.bits := ClientDmaRequest(
|
|
||||||
cmd = Mux(prefetch, DMA_CMD_PFR, DMA_CMD_COPY),
|
|
||||||
src_start = sourceAddrs(testIdx),
|
|
||||||
dst_start = destAddrs(testIdx),
|
|
||||||
segment_size = transferLengths(testIdx))
|
|
||||||
|
|
||||||
io.ptw.head <> frontend.io.ptw
|
|
||||||
io.mem.head <> frontend.io.mem
|
|
||||||
|
|
||||||
val status_reg = Module(new DmaStatusReg)
|
|
||||||
//status_reg.io.csr <> io.csr
|
|
||||||
status_reg.io.incr_outstanding := frontend.io.incr_outstanding
|
|
||||||
|
|
||||||
val dma_done = !frontend.io.busy && !status_reg.io.xact_outstanding
|
|
||||||
|
|
||||||
val cache_resp = io.cache.head.resp
|
|
||||||
val cache_req = io.cache.head.req
|
|
||||||
cache_req.valid := (state === s_fill_req) || (state === s_check_req)
|
|
||||||
cache_req.bits.addr := req_addr
|
|
||||||
cache_req.bits.data := req_data
|
|
||||||
cache_req.bits.typ := MT_W
|
|
||||||
cache_req.bits.cmd := Mux(state === s_fill_req, M_XWR, M_XRD)
|
|
||||||
|
|
||||||
when (state === s_start) {
|
|
||||||
req_addr := sourceAddrs(testIdx)
|
|
||||||
req_data := UInt(dataStart)
|
|
||||||
bytes_left := transferLengths(testIdx)
|
|
||||||
state := s_fill_req
|
|
||||||
}
|
|
||||||
|
|
||||||
when (cache_req.fire()) {
|
|
||||||
req_addr := req_addr + UInt(wordBytes)
|
|
||||||
bytes_left := bytes_left - UInt(wordBytes)
|
|
||||||
state := Mux(state === s_fill_req, s_fill_resp, s_check_resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (state === s_fill_resp && cache_resp.valid) {
|
|
||||||
req_data := req_data + UInt(dataStride)
|
|
||||||
state := Mux(bytes_left === UInt(0), s_copy_req, s_fill_req)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (frontend.io.cpu.req.fire()) { state := s_copy_wait }
|
|
||||||
|
|
||||||
when (state === s_copy_wait && dma_done) {
|
|
||||||
req_addr := destAddrs(testIdx)
|
|
||||||
req_data := UInt(dataStart)
|
|
||||||
bytes_left := transferLengths(testIdx)
|
|
||||||
state := s_check_req
|
|
||||||
}
|
|
||||||
|
|
||||||
when (state === s_check_resp && cache_resp.valid) {
|
|
||||||
req_data := req_data + UInt(dataStride)
|
|
||||||
when (bytes_left > UInt(0)) {
|
|
||||||
state := s_check_req
|
|
||||||
} .elsewhen (testIdx === UInt(testSet.size - 1)) {
|
|
||||||
state := s_finished
|
|
||||||
} .otherwise {
|
|
||||||
testIdx := testIdx + UInt(1)
|
|
||||||
state := s_start
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
io.finished := (state === s_finished)
|
|
||||||
|
|
||||||
testSet.foreach { case DmaTestCase(source, dest, length) =>
|
|
||||||
require(source % wordBytes == 0, "source address must be word-aligned")
|
|
||||||
require(dest % wordBytes == 0, "destination address must be word-aligned")
|
|
||||||
require(length % wordBytes == 0, "transfer length must be word-aligned")
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!cache_resp.valid || !cache_resp.bits.has_data ||
|
|
||||||
cache_resp.bits.data === req_data, "Received data does not match")
|
|
||||||
assert(!frontend.io.cpu.resp.valid || frontend.io.cpu.resp.bits.status === UInt(0),
|
|
||||||
"Frontend error response")
|
|
||||||
|
|
||||||
val cache_timeout = Timer(1000, cache_req.fire(), cache_resp.valid)
|
|
||||||
assert(!cache_timeout, "Memory request timed out")
|
|
||||||
}
|
|
@ -39,7 +39,7 @@ class UncachedTileLinkGenerator(id: Int)
|
|||||||
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val mem = new ClientUncachedTileLinkIO
|
val mem = new ClientUncachedTileLinkIO
|
||||||
val finished = Bool(OUTPUT)
|
val status = new GroundTestStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
val (s_start :: s_put :: s_get :: s_finished :: Nil) = Enum(Bits(), 4)
|
val (s_start :: s_put :: s_get :: s_finished :: Nil) = Enum(Bits(), 4)
|
||||||
@ -61,7 +61,9 @@ class UncachedTileLinkGenerator(id: Int)
|
|||||||
val timeout = Timer(genTimeout, io.mem.acquire.fire(), io.mem.grant.fire())
|
val timeout = Timer(genTimeout, io.mem.acquire.fire(), io.mem.grant.fire())
|
||||||
assert(!timeout, s"Uncached generator ${id} timed out waiting for grant")
|
assert(!timeout, s"Uncached generator ${id} timed out waiting for grant")
|
||||||
|
|
||||||
io.finished := (state === s_finished)
|
io.status.finished := (state === s_finished)
|
||||||
|
io.status.timeout.valid := timeout
|
||||||
|
io.status.timeout.bits := UInt(id)
|
||||||
|
|
||||||
val part_of_full_addr =
|
val part_of_full_addr =
|
||||||
if (log2Ceil(nGens) > 0) {
|
if (log2Ceil(nGens) > 0) {
|
||||||
@ -99,17 +101,22 @@ class UncachedTileLinkGenerator(id: Int)
|
|||||||
operand_size = wordSize,
|
operand_size = wordSize,
|
||||||
alloc = Bool(false))
|
alloc = Bool(false))
|
||||||
|
|
||||||
io.mem.acquire.valid := sending && !io.finished
|
io.mem.acquire.valid := sending && !io.status.finished
|
||||||
io.mem.acquire.bits := Mux(state === s_put, put_acquire, get_acquire)
|
io.mem.acquire.bits := Mux(state === s_put, put_acquire, get_acquire)
|
||||||
io.mem.grant.ready := !sending && !io.finished
|
io.mem.grant.ready := !sending && !io.status.finished
|
||||||
|
|
||||||
def wordFromBeat(addr: UInt, dat: UInt) = {
|
def wordFromBeat(addr: UInt, dat: UInt) = {
|
||||||
val shift = Cat(beatOffset(addr), UInt(0, wordOffset + 3))
|
val shift = Cat(beatOffset(addr), UInt(0, wordOffset + 3))
|
||||||
(dat >> shift)(genWordBits - 1, 0)
|
(dat >> shift)(genWordBits - 1, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!io.mem.grant.valid || state =/= s_get ||
|
val data_mismatch = io.mem.grant.fire() && state === s_get &&
|
||||||
wordFromBeat(full_addr, io.mem.grant.bits.data) === word_data,
|
wordFromBeat(full_addr, io.mem.grant.bits.data) =/= word_data
|
||||||
|
|
||||||
|
io.status.error.valid := data_mismatch
|
||||||
|
io.status.error.bits := UInt(id)
|
||||||
|
|
||||||
|
assert(!data_mismatch,
|
||||||
s"Get received incorrect data in uncached generator ${id}")
|
s"Get received incorrect data in uncached generator ${id}")
|
||||||
|
|
||||||
def beatOffset(addr: UInt) = // TODO zero-width
|
def beatOffset(addr: UInt) = // TODO zero-width
|
||||||
@ -121,11 +128,13 @@ class HellaCacheGenerator(id: Int)
|
|||||||
(implicit p: Parameters) extends L1HellaCacheModule()(p) with HasGeneratorParameters {
|
(implicit p: Parameters) extends L1HellaCacheModule()(p) with HasGeneratorParameters {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val mem = new HellaCacheIO
|
val mem = new HellaCacheIO
|
||||||
val finished = Bool(OUTPUT)
|
val status = new GroundTestStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
val timeout = Timer(genTimeout, io.mem.req.fire(), io.mem.resp.valid)
|
val timeout = Timer(genTimeout, io.mem.req.fire(), io.mem.resp.valid)
|
||||||
assert(!timeout, s"Cached generator ${id} timed out waiting for response")
|
assert(!timeout, s"Cached generator ${id} timed out waiting for response")
|
||||||
|
io.status.timeout.valid := timeout
|
||||||
|
io.status.timeout.bits := UInt(id)
|
||||||
|
|
||||||
val (s_start :: s_write :: s_read :: s_finished :: Nil) = Enum(Bits(), 4)
|
val (s_start :: s_write :: s_read :: s_finished :: Nil) = Enum(Bits(), 4)
|
||||||
val state = Reg(init = s_start)
|
val state = Reg(init = s_start)
|
||||||
@ -143,7 +152,7 @@ class HellaCacheGenerator(id: Int)
|
|||||||
val req_addr = UInt(startAddress) + Cat(req_cnt, part_of_req_addr)
|
val req_addr = UInt(startAddress) + Cat(req_cnt, part_of_req_addr)
|
||||||
val req_data = Cat(UInt(id, log2Up(nGens)), req_addr)
|
val req_data = Cat(UInt(id, log2Up(nGens)), req_addr)
|
||||||
|
|
||||||
io.mem.req.valid := sending && !io.finished
|
io.mem.req.valid := sending && !io.status.finished
|
||||||
io.mem.req.bits.addr := req_addr
|
io.mem.req.bits.addr := req_addr
|
||||||
io.mem.req.bits.data := req_data
|
io.mem.req.bits.data := req_data
|
||||||
io.mem.req.bits.typ := wordSize
|
io.mem.req.bits.typ := wordSize
|
||||||
@ -157,7 +166,7 @@ class HellaCacheGenerator(id: Int)
|
|||||||
|
|
||||||
when (req_wrap) { state := Mux(state === s_write, s_read, s_finished) }
|
when (req_wrap) { state := Mux(state === s_write, s_read, s_finished) }
|
||||||
|
|
||||||
io.finished := (state === s_finished)
|
io.status.finished := (state === s_finished)
|
||||||
|
|
||||||
def data_match(recv: Bits, expected: Bits): Bool = {
|
def data_match(recv: Bits, expected: Bits): Bool = {
|
||||||
val recv_resized = Wire(Bits(width = genWordBits))
|
val recv_resized = Wire(Bits(width = genWordBits))
|
||||||
@ -168,8 +177,13 @@ class HellaCacheGenerator(id: Int)
|
|||||||
recv_resized === exp_resized
|
recv_resized === exp_resized
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!io.mem.resp.valid || !io.mem.resp.bits.has_data ||
|
val data_mismatch = io.mem.resp.valid && io.mem.resp.bits.has_data &&
|
||||||
data_match(io.mem.resp.bits.data, req_data),
|
!data_match(io.mem.resp.bits.data, req_data)
|
||||||
|
|
||||||
|
io.status.error.valid := data_mismatch
|
||||||
|
io.status.error.bits := UInt(id)
|
||||||
|
|
||||||
|
assert(!data_mismatch,
|
||||||
s"Received incorrect data in cached generator ${id}")
|
s"Received incorrect data in cached generator ${id}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,6 +207,6 @@ class GeneratorTest(implicit p: Parameters)
|
|||||||
io.cache <> cached.map(_.io.mem)
|
io.cache <> cached.map(_.io.mem)
|
||||||
io.mem <> uncached.map(_.io.mem)
|
io.mem <> uncached.map(_.io.mem)
|
||||||
|
|
||||||
val gen_finished = cached.map(_.io.finished) ++ uncached.map(_.io.finished)
|
val gen_debug = cached.map(_.io.status) ++ uncached.map(_.io.status)
|
||||||
io.finished := gen_finished.reduce(_ && _)
|
io.status := DebugCombiner(gen_debug)
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class NastiGenerator(id: Int)(implicit val p: Parameters) extends Module
|
|||||||
with HasGeneratorParameters {
|
with HasGeneratorParameters {
|
||||||
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val finished = Bool(OUTPUT)
|
val status = new GroundTestStatus
|
||||||
val mem = new NastiIO
|
val mem = new NastiIO
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ class NastiGenerator(id: Int)(implicit val p: Parameters) extends Module
|
|||||||
io.mem.r.ready := Bool(true)
|
io.mem.r.ready := Bool(true)
|
||||||
io.mem.b.ready := Bool(true)
|
io.mem.b.ready := Bool(true)
|
||||||
|
|
||||||
io.finished := (state === s_finish)
|
io.status.finished := (state === s_finish)
|
||||||
|
|
||||||
val (read_resp_idx, read_resp_done) = Counter(io.mem.r.fire(), maxRequests)
|
val (read_resp_idx, read_resp_done) = Counter(io.mem.r.fire(), maxRequests)
|
||||||
val read_resp_addr = UInt(startAddress) + Cat(read_resp_idx, part_of_addr)
|
val read_resp_addr = UInt(startAddress) + Cat(read_resp_idx, part_of_addr)
|
||||||
@ -73,8 +73,10 @@ class NastiGenerator(id: Int)(implicit val p: Parameters) extends Module
|
|||||||
val read_shift = Cat(read_offset, UInt(0, 3))
|
val read_shift = Cat(read_offset, UInt(0, 3))
|
||||||
val read_data = (io.mem.r.bits.data >> read_shift)(genWordBits - 1, 0)
|
val read_data = (io.mem.r.bits.data >> read_shift)(genWordBits - 1, 0)
|
||||||
|
|
||||||
assert(!io.mem.r.valid || read_data === ref_data(read_resp_idx),
|
val data_mismatch = io.mem.r.valid && read_data =/= ref_data(read_resp_idx)
|
||||||
"NASTI Test: results do not match")
|
assert(!data_mismatch, "NASTI Test: results do not match")
|
||||||
|
io.status.error.valid := data_mismatch
|
||||||
|
io.status.error.bits := UInt(1)
|
||||||
|
|
||||||
when (state === s_start) { state := s_write_addr }
|
when (state === s_start) { state := s_write_addr }
|
||||||
when (io.mem.aw.fire()) { state := s_write_data }
|
when (io.mem.aw.fire()) { state := s_write_data }
|
||||||
@ -96,6 +98,9 @@ class NastiGenerator(id: Int)(implicit val p: Parameters) extends Module
|
|||||||
w_timer.io.stop.valid := io.mem.b.fire()
|
w_timer.io.stop.valid := io.mem.b.fire()
|
||||||
w_timer.io.stop.bits := io.mem.b.bits.id
|
w_timer.io.stop.bits := io.mem.b.bits.id
|
||||||
assert(!w_timer.io.timeout, "NASTI Write timed out")
|
assert(!w_timer.io.timeout, "NASTI Write timed out")
|
||||||
|
|
||||||
|
io.status.timeout.valid := r_timer.io.timeout || w_timer.io.timeout
|
||||||
|
io.status.timeout.bits := Mux(r_timer.io.timeout, UInt(1), UInt(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
class NastiConverterTest(implicit p: Parameters) extends GroundTest()(p)
|
class NastiConverterTest(implicit p: Parameters) extends GroundTest()(p)
|
||||||
@ -112,5 +117,5 @@ class NastiConverterTest(implicit p: Parameters) extends GroundTest()(p)
|
|||||||
|
|
||||||
converter.io.nasti <> test.io.mem
|
converter.io.nasti <> test.io.mem
|
||||||
TileLinkWidthAdapter(io.mem.head, converter.io.tl)
|
TileLinkWidthAdapter(io.mem.head, converter.io.tl)
|
||||||
io.finished := test.io.finished
|
io.status := test.io.status
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ class RegressionIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
|||||||
val cache = new HellaCacheIO
|
val cache = new HellaCacheIO
|
||||||
val mem = new ClientUncachedTileLinkIO
|
val mem = new ClientUncachedTileLinkIO
|
||||||
val finished = Bool(OUTPUT)
|
val finished = Bool(OUTPUT)
|
||||||
|
val errored = Bool(OUTPUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Regression(implicit val p: Parameters)
|
abstract class Regression(implicit val p: Parameters)
|
||||||
@ -178,10 +179,11 @@ class NoAllocPutHitRegression(implicit p: Parameters) extends Regression()(p) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!io.mem.grant.valid || !gnt.hasData() || gnt.data === test_data,
|
val data_mismatch = io.mem.grant.fire() && gnt.hasData() && gnt.data =/= test_data
|
||||||
"NoAllocPutHitRegression: data does not match")
|
assert(!data_mismatch, "NoAllocPutHitRegression: data does not match")
|
||||||
|
|
||||||
io.finished := (state === s_done)
|
io.finished := (state === s_done)
|
||||||
|
io.errored := data_mismatch
|
||||||
|
|
||||||
disableCache()
|
disableCache()
|
||||||
}
|
}
|
||||||
@ -249,9 +251,10 @@ class MixedAllocPutRegression(implicit p: Parameters) extends Regression()(p) {
|
|||||||
|
|
||||||
io.finished := (state === s_done)
|
io.finished := (state === s_done)
|
||||||
|
|
||||||
assert(state =/= s_get_wait || !io.mem.grant.valid ||
|
val data_mismatch = state === s_get_wait && io.mem.grant.fire() &&
|
||||||
io.mem.grant.bits.data === test_data(io.mem.grant.bits.client_xact_id),
|
io.mem.grant.bits.data =/= test_data(io.mem.grant.bits.client_xact_id)
|
||||||
"MixedAllocPutRegression: data mismatch")
|
assert(!data_mismatch, "MixedAllocPutRegression: data mismatch")
|
||||||
|
io.errored := data_mismatch
|
||||||
|
|
||||||
disableCache()
|
disableCache()
|
||||||
}
|
}
|
||||||
@ -347,11 +350,10 @@ class WriteMaskedPutBlockRegression(implicit p: Parameters) extends Regression()
|
|||||||
|
|
||||||
io.finished := (state === s_done)
|
io.finished := (state === s_done)
|
||||||
|
|
||||||
assert(!io.mem.grant.valid ||
|
val data_mismatch = io.mem.grant.fire() && io.mem.grant.bits.hasData() &&
|
||||||
!io.mem.grant.bits.hasData() ||
|
state =/= UInt(0) && io.mem.grant.bits.data =/= get_data
|
||||||
stage === UInt(0) ||
|
assert(!data_mismatch, "WriteMaskedPutBlockRegression: data does not match")
|
||||||
io.mem.grant.bits.data === get_data,
|
io.errored := data_mismatch
|
||||||
"WriteMaskedPutBlockRegression: data does not match")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure a prefetch that hits returns immediately. */
|
/* Make sure a prefetch that hits returns immediately. */
|
||||||
@ -379,6 +381,7 @@ class PrefetchHitRegression(implicit p: Parameters) extends Regression()(p) {
|
|||||||
when (sending && pf_done) { sending := Bool(false) }
|
when (sending && pf_done) { sending := Bool(false) }
|
||||||
|
|
||||||
io.finished := acked.andR
|
io.finished := acked.andR
|
||||||
|
io.errored := Bool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This tests the sort of access the pattern that Hwacha uses.
|
/* This tests the sort of access the pattern that Hwacha uses.
|
||||||
@ -408,8 +411,9 @@ class SequentialSameIdGetRegression(implicit p: Parameters) extends Regression()
|
|||||||
|
|
||||||
io.finished := finished
|
io.finished := finished
|
||||||
|
|
||||||
assert(!io.mem.grant.valid || io.mem.grant.bits.addr_beat === recv_cnt,
|
val beat_mismatch = io.mem.grant.fire() && io.mem.grant.bits.addr_beat =/= recv_cnt
|
||||||
"SequentialSameIdGetRegression: grant received out of order")
|
assert(!beat_mismatch, "SequentialSameIdGetRegression: grant received out of order")
|
||||||
|
io.errored := beat_mismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that a writeback will occur by writing nWays + 1 blocks to the same
|
/* Test that a writeback will occur by writing nWays + 1 blocks to the same
|
||||||
@ -463,9 +467,10 @@ class WritebackRegression(implicit p: Parameters) extends Regression()(p) {
|
|||||||
|
|
||||||
io.finished := (state === s_done)
|
io.finished := (state === s_done)
|
||||||
|
|
||||||
assert(!io.mem.grant.valid || !io.mem.grant.bits.hasData() ||
|
val data_mismatch = io.mem.grant.fire() && io.mem.grant.bits.hasData() &&
|
||||||
io.mem.grant.bits.data === data(ack_cnt),
|
io.mem.grant.bits.data =/= data(ack_cnt)
|
||||||
"WritebackRegression: incorrect data")
|
assert(!data_mismatch, "WritebackRegression: incorrect data")
|
||||||
|
io.errored := data_mismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReleaseRegression(implicit p: Parameters) extends Regression()(p) {
|
class ReleaseRegression(implicit p: Parameters) extends Regression()(p) {
|
||||||
@ -506,9 +511,10 @@ class ReleaseRegression(implicit p: Parameters) extends Regression()(p) {
|
|||||||
|
|
||||||
io.finished := (state === s_done)
|
io.finished := (state === s_done)
|
||||||
|
|
||||||
assert(!io.cache.resp.valid || !io.cache.resp.bits.has_data ||
|
val data_mismatch = io.cache.resp.valid && io.cache.resp.bits.has_data &&
|
||||||
io.cache.resp.bits.data === data(resp_idx),
|
io.cache.resp.bits.data =/= data(resp_idx)
|
||||||
"ReleaseRegression: data mismatch")
|
assert(!data_mismatch, "ReleaseRegression: data mismatch")
|
||||||
|
io.errored := data_mismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
class PutBeforePutBlockRegression(implicit p: Parameters) extends Regression()(p) {
|
class PutBeforePutBlockRegression(implicit p: Parameters) extends Regression()(p) {
|
||||||
@ -548,6 +554,7 @@ class PutBeforePutBlockRegression(implicit p: Parameters) extends Regression()(p
|
|||||||
when (all_acked) { state := s_finished }
|
when (all_acked) { state := s_finished }
|
||||||
|
|
||||||
io.finished := (state === s_finished)
|
io.finished := (state === s_finished)
|
||||||
|
io.errored := Bool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
object RegressionTests {
|
object RegressionTests {
|
||||||
@ -610,6 +617,8 @@ class RegressionTest(implicit p: Parameters) extends GroundTest()(p) {
|
|||||||
io.cache.head.req.valid := regress.io.cache.req.valid
|
io.cache.head.req.valid := regress.io.cache.req.valid
|
||||||
io.cache.head.req.bits := regress.io.cache.req.bits
|
io.cache.head.req.bits := regress.io.cache.req.bits
|
||||||
io.cache.head.invalidate_lr := regress.io.cache.invalidate_lr
|
io.cache.head.invalidate_lr := regress.io.cache.invalidate_lr
|
||||||
|
io.status.error.valid := regress.io.errored
|
||||||
|
io.status.error.bits := UInt(i)
|
||||||
cur_finished := regress.io.finished
|
cur_finished := regress.io.finished
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,11 +629,18 @@ class RegressionTest(implicit p: Parameters) extends GroundTest()(p) {
|
|||||||
}
|
}
|
||||||
when (start) { start := Bool(false) }
|
when (start) { start := Bool(false) }
|
||||||
|
|
||||||
io.finished := all_done
|
|
||||||
|
|
||||||
val timeout = Timer(5000, start, cur_finished)
|
val timeout = Timer(5000, start, cur_finished)
|
||||||
assert(!timeout, "Regression timed out")
|
assert(!timeout, "Regression timed out")
|
||||||
|
|
||||||
|
io.status.finished := all_done
|
||||||
|
io.status.timeout.valid := timeout
|
||||||
|
io.status.timeout.bits := UInt(0)
|
||||||
|
|
||||||
assert(!(all_done && io.mem.head.grant.valid),
|
assert(!(all_done && io.mem.head.grant.valid),
|
||||||
"Getting grant after test completion")
|
"Getting grant after test completion")
|
||||||
|
|
||||||
|
when (all_done) {
|
||||||
|
io.status.error.valid := io.mem.head.grant.valid
|
||||||
|
io.status.error.bits := UInt(regressions.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,11 @@ case class GroundTestTileSettings(
|
|||||||
case object GroundTestKey extends Field[Seq[GroundTestTileSettings]]
|
case object GroundTestKey extends Field[Seq[GroundTestTileSettings]]
|
||||||
case object GroundTestId extends Field[Int]
|
case object GroundTestId extends Field[Int]
|
||||||
|
|
||||||
|
trait HasGroundTestConstants {
|
||||||
|
val timeoutCodeBits = 4
|
||||||
|
val errorCodeBits = 4
|
||||||
|
}
|
||||||
|
|
||||||
trait HasGroundTestParameters extends HasAddrMapParameters {
|
trait HasGroundTestParameters extends HasAddrMapParameters {
|
||||||
implicit val p: Parameters
|
implicit val p: Parameters
|
||||||
val tileId = p(GroundTestId)
|
val tileId = p(GroundTestId)
|
||||||
@ -69,12 +74,18 @@ class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GroundTestStatus extends Bundle with HasGroundTestConstants {
|
||||||
|
val finished = Bool(OUTPUT)
|
||||||
|
val timeout = Valid(UInt(width = timeoutCodeBits))
|
||||||
|
val error = Valid(UInt(width = errorCodeBits))
|
||||||
|
}
|
||||||
|
|
||||||
class GroundTestIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
class GroundTestIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||||
with HasGroundTestParameters {
|
with HasGroundTestParameters {
|
||||||
val cache = Vec(nCached, new HellaCacheIO)
|
val cache = Vec(nCached, new HellaCacheIO)
|
||||||
val mem = Vec(nUncached, new ClientUncachedTileLinkIO)
|
val mem = Vec(nUncached, new ClientUncachedTileLinkIO)
|
||||||
val ptw = Vec(nPTW, new TLBPTWIO)
|
val ptw = Vec(nPTW, new TLBPTWIO)
|
||||||
val finished = Bool(OUTPUT)
|
val status = new GroundTestStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class GroundTest(implicit val p: Parameters) extends Module
|
abstract class GroundTest(implicit val p: Parameters) extends Module
|
||||||
@ -113,7 +124,7 @@ class GroundTestTile(resetSignal: Bool)
|
|||||||
ptwPorts += dcache_io.ptw
|
ptwPorts += dcache_io.ptw
|
||||||
}
|
}
|
||||||
|
|
||||||
when (test.io.finished) { stop() }
|
when (test.io.status.finished) { stop() }
|
||||||
|
|
||||||
if (ptwPorts.size > 0) {
|
if (ptwPorts.size > 0) {
|
||||||
val ptw = Module(new DummyPTW(ptwPorts.size))
|
val ptw = Module(new DummyPTW(ptwPorts.size))
|
||||||
|
@ -178,6 +178,7 @@ class TraceGenerator(id: Int)
|
|||||||
with HasTraceGenParams {
|
with HasTraceGenParams {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val finished = Bool(OUTPUT)
|
val finished = Bool(OUTPUT)
|
||||||
|
val timeout = Bool(OUTPUT)
|
||||||
val mem = new HellaCacheIO
|
val mem = new HellaCacheIO
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,6 +541,7 @@ class TraceGenerator(id: Int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
io.finished := Bool(false)
|
io.finished := Bool(false)
|
||||||
|
io.timeout := timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// =======================
|
// =======================
|
||||||
@ -552,5 +554,8 @@ class GroundTestTraceGenerator(implicit p: Parameters)
|
|||||||
val traceGen = Module(new TraceGenerator(p(GroundTestId)))
|
val traceGen = Module(new TraceGenerator(p(GroundTestId)))
|
||||||
io.cache.head <> traceGen.io.mem
|
io.cache.head <> traceGen.io.mem
|
||||||
|
|
||||||
io.finished := traceGen.io.finished
|
io.status.finished := traceGen.io.finished
|
||||||
|
io.status.timeout.valid := traceGen.io.timeout
|
||||||
|
io.status.timeout.bits := UInt(0)
|
||||||
|
io.status.error.valid := Bool(false)
|
||||||
}
|
}
|
||||||
|
@ -576,10 +576,16 @@ class UnitTestSuite(implicit p: Parameters) extends GroundTest()(p) {
|
|||||||
when (state === s_idle) { state := s_start }
|
when (state === s_idle) { state := s_start }
|
||||||
when (state === s_start) { state := s_wait }
|
when (state === s_start) { state := s_wait }
|
||||||
|
|
||||||
|
io.status.timeout.valid := Bool(false)
|
||||||
tests.zipWithIndex.foreach { case (mod, i) =>
|
tests.zipWithIndex.foreach { case (mod, i) =>
|
||||||
mod.io.start := (state === s_start)
|
mod.io.start := (state === s_start)
|
||||||
val timeout = Timer(1000, mod.io.start, mod.io.finished)
|
val timeout = Timer(1000, mod.io.start, mod.io.finished)
|
||||||
assert(!timeout, s"UnitTest $i timed out")
|
assert(!timeout, s"UnitTest $i timed out")
|
||||||
|
when (timeout) {
|
||||||
|
io.status.timeout.valid := Bool(true)
|
||||||
|
io.status.timeout.bits := UInt(i)
|
||||||
}
|
}
|
||||||
io.finished := tests.map(_.io.finished).reduce(_ && _)
|
}
|
||||||
|
io.status.finished := tests.map(_.io.finished).reduce(_ && _)
|
||||||
|
io.status.error.valid := Bool(false)
|
||||||
}
|
}
|
||||||
|
@ -154,3 +154,26 @@ object Frequency {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object ValidMux {
|
||||||
|
def apply[T <: Data](v1: ValidIO[T], v2: ValidIO[T]*): ValidIO[T] = {
|
||||||
|
apply(v1 +: v2.toSeq)
|
||||||
|
}
|
||||||
|
def apply[T <: Data](valids: Seq[ValidIO[T]]): ValidIO[T] = {
|
||||||
|
val out = Wire(Valid(valids.head.bits))
|
||||||
|
out.valid := valids.map(_.valid).reduce(_ || _)
|
||||||
|
out.bits := MuxCase(valids.head.bits,
|
||||||
|
valids.map(v => (v.valid -> v.bits)))
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object DebugCombiner {
|
||||||
|
def apply(debugs: Seq[GroundTestStatus]): GroundTestStatus = {
|
||||||
|
val out = Wire(new GroundTestStatus)
|
||||||
|
out.finished := debugs.map(_.finished).reduce(_ || _)
|
||||||
|
out.timeout := ValidMux(debugs.map(_.timeout))
|
||||||
|
out.error := ValidMux(debugs.map(_.error))
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user