diff options
| author | Albert Magyar | 2019-10-16 01:40:34 -0700 |
|---|---|---|
| committer | Albert Magyar | 2019-10-21 10:02:46 -0700 |
| commit | 24df1cdcc0981f6e32662a42fe01135681db18c4 (patch) | |
| tree | c1836e689123737813622ac24139f8370d0cd719 /src/test/scala/firrtlTests/execution/SimpleExecutionTest.scala | |
| parent | 01b10725163c5bbe239c11f14b6136c737160d34 (diff) | |
Add library for streamlined Verilog execution tests
Diffstat (limited to 'src/test/scala/firrtlTests/execution/SimpleExecutionTest.scala')
| -rw-r--r-- | src/test/scala/firrtlTests/execution/SimpleExecutionTest.scala | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/test/scala/firrtlTests/execution/SimpleExecutionTest.scala b/src/test/scala/firrtlTests/execution/SimpleExecutionTest.scala new file mode 100644 index 00000000..5abeb819 --- /dev/null +++ b/src/test/scala/firrtlTests/execution/SimpleExecutionTest.scala @@ -0,0 +1,84 @@ +package firrtlTests.execution + +import java.io.File + +import firrtl.ir._ +import firrtlTests._ + +sealed trait SimpleTestCommand +case class Step(n: Int) extends SimpleTestCommand +case class Invalidate(expStr: String) extends SimpleTestCommand +case class Poke(expStr: String, value: Int) extends SimpleTestCommand +case class Expect(expStr: String, value: Int) extends SimpleTestCommand + +/** + * This trait defines an interface to run a self-contained test circuit. + */ +trait TestExecution { + def runEmittedDUT(c: Circuit, testDir: File): Unit +} + +/** + * A class that makes it easier to write execution-driven tests. + * + * By combining a DUT body (supplied as a string without an enclosing + * module or circuit) with a sequence of test operations, an + * executable, self-contained Verilog testbench may be automatically + * created and checked. + * + * @note It is necessary to mix in a trait extending TestExecution + * @note The DUT has two implicit ports, "clock" and "reset" + * @note Execution of the command sequences begins after reset is deasserted + * + * @see [[firrtlTests.execution.TestExecution]] + * @see [[firrtlTests.execution.VerilogExecution]] + * + * @example {{{ + * class AndTester extends SimpleExecutionTest with VerilogExecution { + * val body = "reg r : UInt<32>, clock with: (reset => (reset, UInt<32>(0)))" + * val commands = Seq( + * Expect("r", 0), + * Poke("r", 3), + * Step(1), + * Expect("r", 3) + * ) + * } + * }}} + */ +abstract class SimpleExecutionTest extends FirrtlPropSpec { + this: TestExecution => + + /** + * Text representing the body of the DUT. This is useful for testing + * statement-level language features, and cuts out the overhead of + * writing a top-level DUT module and having peeks/pokes point at + * IOs. + */ + val body: String + + /** + * A sequence of commands (peeks, pokes, invalidates, steps) that + * represents how the testbench will progress. The semantics are + * inspired by chisel-testers. + */ + def commands: Seq[SimpleTestCommand] + + private def interpretCommand(eth: ExecutionTestHelper, cmd: SimpleTestCommand) = cmd match { + case Step(n) => eth.step(n) + case Invalidate(expStr) => eth.invalidate(expStr) + case Poke(expStr, value) => eth.poke(expStr, UIntLiteral(value)) + case Expect(expStr, value) => eth.expect(expStr, UIntLiteral(value)) + } + + private def runTest(): Unit = { + val initial = ExecutionTestHelper(body) + val test = commands.foldLeft(initial)(interpretCommand(_, _)) + val testName = this.getClass.getSimpleName + val testDir = createTestDirectory(s"${testName}-generated-src") + runEmittedDUT(test.emit, testDir) + } + + property("Execution of the compiled Verilog for ExecutionTestHelper should succeed") { + runTest() + } +} |
