aboutsummaryrefslogtreecommitdiff
path: root/src/test/scala/firrtlTests/execution/SimpleExecutionTest.scala
diff options
context:
space:
mode:
authorAlbert Magyar2019-10-16 01:40:34 -0700
committerAlbert Magyar2019-10-21 10:02:46 -0700
commit24df1cdcc0981f6e32662a42fe01135681db18c4 (patch)
treec1836e689123737813622ac24139f8370d0cd719 /src/test/scala/firrtlTests/execution/SimpleExecutionTest.scala
parent01b10725163c5bbe239c11f14b6136c737160d34 (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.scala84
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()
+ }
+}