[unittest] Parallelize UnitTestSuite (#319)
* [unittest] Parallelize UnitTestSuite so all tests have their own timer, runs until all finish or any timeout. Adds SimpleTimer. * [util] Timer spacing cleanup * [unittest] Remove Config reference to UnitTestTimeout
This commit is contained in:
parent
12d0c00822
commit
335e866176
@ -6,7 +6,7 @@ import uncore.devices.NTiles
|
|||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import junctions._
|
import junctions._
|
||||||
import rocket._
|
import rocket._
|
||||||
import util.Timer
|
import util.SimpleTimer
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ class UncachedTileLinkGenerator(id: Int)
|
|||||||
when (io.mem.grant.fire()) { sending := Bool(true) }
|
when (io.mem.grant.fire()) { sending := Bool(true) }
|
||||||
when (req_wrap) { state := Mux(state === s_put, s_get, s_finished) }
|
when (req_wrap) { state := Mux(state === s_put, s_get, s_finished) }
|
||||||
|
|
||||||
val timeout = Timer(genTimeout, io.mem.acquire.fire(), io.mem.grant.fire())
|
val timeout = SimpleTimer(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.status.finished := (state === s_finished)
|
io.status.finished := (state === s_finished)
|
||||||
@ -132,7 +132,7 @@ class HellaCacheGenerator(id: Int)
|
|||||||
val status = new GroundTestStatus
|
val status = new GroundTestStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
val timeout = Timer(genTimeout, io.mem.req.fire(), io.mem.resp.valid)
|
val timeout = SimpleTimer(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.valid := timeout
|
||||||
io.status.timeout.bits := UInt(id)
|
io.status.timeout.bits := UInt(id)
|
||||||
|
@ -6,7 +6,7 @@ import uncore.constants._
|
|||||||
import uncore.agents._
|
import uncore.agents._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import junctions.HasAddrMapParameters
|
import junctions.HasAddrMapParameters
|
||||||
import util.{ParameterizedBundle, Timer}
|
import util.{ParameterizedBundle, SimpleTimer}
|
||||||
import rocket.HellaCacheIO
|
import rocket.HellaCacheIO
|
||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
|
|
||||||
@ -760,7 +760,7 @@ class RegressionTest(implicit p: Parameters) extends GroundTest()(p) {
|
|||||||
}
|
}
|
||||||
when (start) { start := Bool(false) }
|
when (start) { start := Bool(false) }
|
||||||
|
|
||||||
val timeout = Timer(5000, start, cur_finished)
|
val timeout = SimpleTimer(5000, start, cur_finished)
|
||||||
assert(!timeout, "Regression timed out")
|
assert(!timeout, "Regression timed out")
|
||||||
|
|
||||||
io.status.finished := all_done
|
io.status.finished := all_done
|
||||||
|
@ -81,7 +81,6 @@ class ROMSlave(contents: Seq[Byte])(implicit val p: Parameters) extends Module
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ROMSlaveTest(implicit p: Parameters) extends UnitTest {
|
class ROMSlaveTest(implicit p: Parameters) extends UnitTest {
|
||||||
implicit val testName = "ROMSlaveTest"
|
|
||||||
val romdata = Seq(
|
val romdata = Seq(
|
||||||
BigInt("01234567deadbeef", 16),
|
BigInt("01234567deadbeef", 16),
|
||||||
BigInt("ab32fee8d00dfeed", 16))
|
BigInt("ab32fee8d00dfeed", 16))
|
||||||
|
@ -254,7 +254,7 @@ class TLFuzzRAM extends LazyModule
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TLFuzzRAMTest extends UnitTest {
|
class TLFuzzRAMTest extends UnitTest(500000) {
|
||||||
val dut = Module(LazyModule(new TLFuzzRAM).module)
|
val dut = Module(LazyModule(new TLFuzzRAM).module)
|
||||||
io.finished := dut.io.finished
|
io.finished := dut.io.finished
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ class WithJunctionsUnitTests extends Config(
|
|||||||
Module(new junctions.NastiMemoryDemuxTest()(p)),
|
Module(new junctions.NastiMemoryDemuxTest()(p)),
|
||||||
Module(new junctions.HastiTest()(p)))
|
Module(new junctions.HastiTest()(p)))
|
||||||
}
|
}
|
||||||
case UnitTestTimeout => 50000
|
|
||||||
case _ => throw new CDEMatchError
|
case _ => throw new CDEMatchError
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -37,7 +36,6 @@ class WithUncoreUnitTests extends Config(
|
|||||||
Module(new uncore.devices.TileLinkRAMTest()(p)),
|
Module(new uncore.devices.TileLinkRAMTest()(p)),
|
||||||
Module(new uncore.tilelink2.TLFuzzRAMTest))
|
Module(new uncore.tilelink2.TLFuzzRAMTest))
|
||||||
}
|
}
|
||||||
case UnitTestTimeout => 500000
|
|
||||||
case _ => throw new CDEMatchError
|
case _ => throw new CDEMatchError
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package unittest
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import cde.{Field, Parameters}
|
import cde.{Field, Parameters}
|
||||||
import util.Timer
|
import util.SimpleTimer
|
||||||
|
|
||||||
trait HasUnitTestIO {
|
trait HasUnitTestIO {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
@ -11,14 +11,16 @@ trait HasUnitTestIO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class UnitTest extends Module with HasUnitTestIO {
|
abstract class UnitTest(val timeout: Int = 4096) extends Module with HasUnitTestIO {
|
||||||
when (io.start) {
|
val testName = this.getClass.getSimpleName
|
||||||
printf(s"Started UnitTest ${this.getClass.getSimpleName}\n")
|
|
||||||
}
|
when (io.start) { printf(s"Started UnitTest $testName\n") }
|
||||||
|
|
||||||
|
val timed_out = SimpleTimer(timeout, io.start, io.finished)
|
||||||
|
assert(!timed_out, s"UnitTest $testName timed out")
|
||||||
}
|
}
|
||||||
|
|
||||||
case object UnitTests extends Field[Parameters => Seq[UnitTest]]
|
case object UnitTests extends Field[Parameters => Seq[UnitTest]]
|
||||||
case object UnitTestTimeout extends Field[Int]
|
|
||||||
|
|
||||||
class UnitTestSuite(implicit p: Parameters) extends Module {
|
class UnitTestSuite(implicit p: Parameters) extends Module {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
@ -27,33 +29,14 @@ class UnitTestSuite(implicit p: Parameters) extends Module {
|
|||||||
|
|
||||||
val tests = p(UnitTests)(p)
|
val tests = p(UnitTests)(p)
|
||||||
|
|
||||||
val s_idle :: s_start :: s_wait :: s_done :: Nil = Enum(Bits(), 4)
|
val s_idle :: s_start :: s_busy :: s_done :: Nil = Enum(Bits(), 4)
|
||||||
val state = Reg(init = s_idle)
|
val state = Reg(init = s_idle)
|
||||||
val test_idx = Reg(init = UInt(0, log2Up(tests.size)))
|
val tests_finished = Vec(tests.map(_.io.finished)).reduce(_&&_)
|
||||||
val test_finished = Vec(tests.map(_.io.finished))
|
|
||||||
|
|
||||||
when (state === s_idle) { state := s_start }
|
tests.foreach { _.io.start := (state === s_start) }
|
||||||
when (state === s_start) { state := s_wait }
|
|
||||||
when (state === s_wait && test_finished(test_idx)) {
|
|
||||||
state := s_start
|
|
||||||
test_idx := test_idx + UInt(1)
|
|
||||||
state := Mux(test_idx === UInt(tests.size - 1), s_done, s_start)
|
|
||||||
}
|
|
||||||
|
|
||||||
val timer = Module(new Timer(p(UnitTestTimeout), tests.size))
|
|
||||||
timer.io.start.valid := Bool(false)
|
|
||||||
timer.io.stop.valid := Bool(false)
|
|
||||||
|
|
||||||
tests.zipWithIndex.foreach { case (mod, i) =>
|
|
||||||
mod.io.start := (state === s_start) && test_idx === UInt(i)
|
|
||||||
when (test_idx === UInt(i)) {
|
|
||||||
timer.io.start.valid := mod.io.start
|
|
||||||
timer.io.start.bits := UInt(i)
|
|
||||||
timer.io.stop.valid := mod.io.finished
|
|
||||||
timer.io.stop.bits := UInt(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
io.finished := (state === s_done)
|
io.finished := (state === s_done)
|
||||||
|
|
||||||
assert(!timer.io.timeout.valid, "UnitTest timed out")
|
when (state === s_idle) { state := s_start }
|
||||||
|
when (state === s_start) { state := s_busy }
|
||||||
|
when (state === s_busy && tests_finished) { state := s_done }
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,14 @@ class Timer(initCount: Int, maxInflight: Int) extends Module {
|
|||||||
val countdown = Reg(UInt(width = log2Up(initCount)))
|
val countdown = Reg(UInt(width = log2Up(initCount)))
|
||||||
val active = inflight.reduce(_ || _)
|
val active = inflight.reduce(_ || _)
|
||||||
|
|
||||||
when (active) {
|
when (active) { countdown := countdown - UInt(1) }
|
||||||
countdown := countdown - UInt(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (io.start.valid) {
|
when (io.start.valid) {
|
||||||
inflight(io.start.bits) := Bool(true)
|
inflight(io.start.bits) := Bool(true)
|
||||||
countdown := UInt(initCount - 1)
|
countdown := UInt(initCount - 1)
|
||||||
}
|
}
|
||||||
when (io.stop.valid) {
|
|
||||||
inflight(io.stop.bits) := Bool(false)
|
when (io.stop.valid) { inflight(io.stop.bits) := Bool(false) }
|
||||||
}
|
|
||||||
|
|
||||||
io.timeout.valid := countdown === UInt(0) && active
|
io.timeout.valid := countdown === UInt(0) && active
|
||||||
io.timeout.bits := PriorityEncoder(inflight)
|
io.timeout.bits := PriorityEncoder(inflight)
|
||||||
@ -37,18 +34,41 @@ class Timer(initCount: Int, maxInflight: Int) extends Module {
|
|||||||
"Timer stop for transaction that's not inflight")
|
"Timer stop for transaction that's not inflight")
|
||||||
}
|
}
|
||||||
|
|
||||||
object Timer {
|
/** Simplified Timer with a statically-specified period.
|
||||||
|
* Can be stopped repeatedly, even when not active.
|
||||||
|
*/
|
||||||
|
class SimpleTimer(initCount: Int) extends Module {
|
||||||
|
val io = new Bundle {
|
||||||
|
val start = Bool(INPUT)
|
||||||
|
val stop = Bool(INPUT)
|
||||||
|
val timeout = Bool(OUTPUT)
|
||||||
|
}
|
||||||
|
|
||||||
|
val countdown = Reg(UInt(width = log2Up(initCount)))
|
||||||
|
val active = Reg(Bool())
|
||||||
|
|
||||||
|
when (active) { countdown := countdown - UInt(1) }
|
||||||
|
|
||||||
|
when (io.start) {
|
||||||
|
active := Bool(true)
|
||||||
|
countdown := UInt(initCount - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (io.stop) { active := Bool(false) }
|
||||||
|
|
||||||
|
io.timeout := countdown === UInt(0) && active
|
||||||
|
}
|
||||||
|
|
||||||
|
object SimpleTimer {
|
||||||
def apply(initCount: Int, start: Bool, stop: Bool): Bool = {
|
def apply(initCount: Int, start: Bool, stop: Bool): Bool = {
|
||||||
val timer = Module(new Timer(initCount, 1))
|
val timer = Module(new SimpleTimer(initCount))
|
||||||
timer.io.start.valid := start
|
timer.io.start := start
|
||||||
timer.io.start.bits := UInt(0)
|
timer.io.stop := stop
|
||||||
timer.io.stop.valid := stop
|
timer.io.timeout
|
||||||
timer.io.stop.bits := UInt(0)
|
|
||||||
timer.io.timeout.valid
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Timer with a statically-specified period. */
|
/** Timer with a dynamically-specified period. */
|
||||||
class DynamicTimer(w: Int) extends Module {
|
class DynamicTimer(w: Int) extends Module {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val start = Bool(INPUT)
|
val start = Bool(INPUT)
|
||||||
@ -71,4 +91,3 @@ class DynamicTimer(w: Int) extends Module {
|
|||||||
|
|
||||||
io.timeout := countdown === UInt(0) && active
|
io.timeout := countdown === UInt(0) && active
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user