1
0

[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:
Henry Cook 2016-09-21 13:05:22 -07:00 committed by GitHub
parent 12d0c00822
commit 335e866176
7 changed files with 54 additions and 55 deletions

View File

@ -6,7 +6,7 @@ import uncore.devices.NTiles
import uncore.constants._
import junctions._
import rocket._
import util.Timer
import util.SimpleTimer
import scala.util.Random
import cde.{Parameters, Field}
@ -59,7 +59,7 @@ class UncachedTileLinkGenerator(id: Int)
when (io.mem.grant.fire()) { sending := Bool(true) }
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")
io.status.finished := (state === s_finished)
@ -132,7 +132,7 @@ class HellaCacheGenerator(id: Int)
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")
io.status.timeout.valid := timeout
io.status.timeout.bits := UInt(id)

View File

@ -6,7 +6,7 @@ import uncore.constants._
import uncore.agents._
import uncore.util._
import junctions.HasAddrMapParameters
import util.{ParameterizedBundle, Timer}
import util.{ParameterizedBundle, SimpleTimer}
import rocket.HellaCacheIO
import cde.{Parameters, Field}
@ -760,7 +760,7 @@ class RegressionTest(implicit p: Parameters) extends GroundTest()(p) {
}
when (start) { start := Bool(false) }
val timeout = Timer(5000, start, cur_finished)
val timeout = SimpleTimer(5000, start, cur_finished)
assert(!timeout, "Regression timed out")
io.status.finished := all_done

View File

@ -81,7 +81,6 @@ class ROMSlave(contents: Seq[Byte])(implicit val p: Parameters) extends Module
}
class ROMSlaveTest(implicit p: Parameters) extends UnitTest {
implicit val testName = "ROMSlaveTest"
val romdata = Seq(
BigInt("01234567deadbeef", 16),
BigInt("ab32fee8d00dfeed", 16))

View File

@ -254,7 +254,7 @@ class TLFuzzRAM extends LazyModule
}
}
class TLFuzzRAMTest extends UnitTest {
class TLFuzzRAMTest extends UnitTest(500000) {
val dut = Module(LazyModule(new TLFuzzRAM).module)
io.finished := dut.io.finished
}

View File

@ -20,7 +20,6 @@ class WithJunctionsUnitTests extends Config(
Module(new junctions.NastiMemoryDemuxTest()(p)),
Module(new junctions.HastiTest()(p)))
}
case UnitTestTimeout => 50000
case _ => throw new CDEMatchError
})
@ -37,7 +36,6 @@ class WithUncoreUnitTests extends Config(
Module(new uncore.devices.TileLinkRAMTest()(p)),
Module(new uncore.tilelink2.TLFuzzRAMTest))
}
case UnitTestTimeout => 500000
case _ => throw new CDEMatchError
})

View File

@ -2,7 +2,7 @@ package unittest
import Chisel._
import cde.{Field, Parameters}
import util.Timer
import util.SimpleTimer
trait HasUnitTestIO {
val io = new Bundle {
@ -11,14 +11,16 @@ trait HasUnitTestIO {
}
}
abstract class UnitTest extends Module with HasUnitTestIO {
when (io.start) {
printf(s"Started UnitTest ${this.getClass.getSimpleName}\n")
}
abstract class UnitTest(val timeout: Int = 4096) extends Module with HasUnitTestIO {
val testName = this.getClass.getSimpleName
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 UnitTestTimeout extends Field[Int]
class UnitTestSuite(implicit p: Parameters) extends Module {
val io = new Bundle {
@ -27,33 +29,14 @@ class UnitTestSuite(implicit p: Parameters) extends Module {
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 test_idx = Reg(init = UInt(0, log2Up(tests.size)))
val test_finished = Vec(tests.map(_.io.finished))
val tests_finished = Vec(tests.map(_.io.finished)).reduce(_&&_)
when (state === s_idle) { 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)
}
}
tests.foreach { _.io.start := (state === s_start) }
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 }
}

View File

@ -18,17 +18,14 @@ class Timer(initCount: Int, maxInflight: Int) extends Module {
val countdown = Reg(UInt(width = log2Up(initCount)))
val active = inflight.reduce(_ || _)
when (active) {
countdown := countdown - UInt(1)
}
when (active) { countdown := countdown - UInt(1) }
when (io.start.valid) {
inflight(io.start.bits) := Bool(true)
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.bits := PriorityEncoder(inflight)
@ -37,18 +34,41 @@ class Timer(initCount: Int, maxInflight: Int) extends Module {
"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 = {
val timer = Module(new Timer(initCount, 1))
timer.io.start.valid := start
timer.io.start.bits := UInt(0)
timer.io.stop.valid := stop
timer.io.stop.bits := UInt(0)
timer.io.timeout.valid
val timer = Module(new SimpleTimer(initCount))
timer.io.start := start
timer.io.stop := stop
timer.io.timeout
}
}
/** Timer with a statically-specified period. */
/** Timer with a dynamically-specified period. */
class DynamicTimer(w: Int) extends Module {
val io = new Bundle {
val start = Bool(INPUT)
@ -71,4 +91,3 @@ class DynamicTimer(w: Int) extends Module {
io.timeout := countdown === UInt(0) && active
}