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 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)

View File

@ -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

View File

@ -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))

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) val dut = Module(LazyModule(new TLFuzzRAM).module)
io.finished := dut.io.finished io.finished := dut.io.finished
} }

View File

@ -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
}) })

View File

@ -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 }
} }

View File

@ -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
} }