summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/scala/Chisel/testers/BasicTester.scala7
-rw-r--r--src/main/scala/Chisel/testers/TesterDriver.scala13
-rw-r--r--src/test/scala/chiselTests/TesterDriverSpec.scala44
3 files changed, 63 insertions, 1 deletions
diff --git a/src/main/scala/Chisel/testers/BasicTester.scala b/src/main/scala/Chisel/testers/BasicTester.scala
index 6807a30e..d3e9e7c8 100644
--- a/src/main/scala/Chisel/testers/BasicTester.scala
+++ b/src/main/scala/Chisel/testers/BasicTester.scala
@@ -24,4 +24,11 @@ class BasicTester extends Module {
pushCommand(Stop(Node(clock), 0))
}
}
+
+ /** The finish method provides a hook that subclasses of BasicTester can use to
+ * alter a circuit after their constructor has been called.
+ * For example, a specialized tester subclassing BasicTester could override finish in order to
+ * add flow control logic for a decoupled io port of a device under test
+ */
+ def finish(): Unit = {}
}
diff --git a/src/main/scala/Chisel/testers/TesterDriver.scala b/src/main/scala/Chisel/testers/TesterDriver.scala
index b25b160b..4547f48f 100644
--- a/src/main/scala/Chisel/testers/TesterDriver.scala
+++ b/src/main/scala/Chisel/testers/TesterDriver.scala
@@ -23,7 +23,7 @@ object TesterDriver extends BackendCompilationUtilities {
* frontend, and which can be turned into executables with assertions. */
def execute(t: () => BasicTester, additionalVResources: Seq[String] = Seq()): Boolean = {
// Invoke the chisel compiler to get the circuit's IR
- val circuit = Driver.elaborate(t)
+ val circuit = Driver.elaborate(finishWrapper(t))
// Set up a bunch of file handlers based on a random temp filename,
// plus the quirks of Verilator's naming conventions
@@ -55,4 +55,15 @@ object TesterDriver extends BackendCompilationUtilities {
false
}
}
+ /**
+ * Calls the finish method of an BasicTester or a class that extends it.
+ * The finish method is a hook for code that augments the circuit built in the constructor.
+ */
+ def finishWrapper(test: () => BasicTester): () => BasicTester = {
+ () => {
+ val tester = test()
+ tester.finish()
+ tester
+ }
+ }
}
diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala
new file mode 100644
index 00000000..dfdd07cc
--- /dev/null
+++ b/src/test/scala/chiselTests/TesterDriverSpec.scala
@@ -0,0 +1,44 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import Chisel._
+import Chisel.testers.BasicTester
+
+/** Extend BasicTester with a simple circuit and finish method. TesterDriver will call the
+ * finish method after the FinishTester's constructor has completed, which will alter the
+ * circuit after the constructor has finished.
+ */
+class FinishTester extends BasicTester {
+ val test_wire_width = 2
+ val test_wire_override_value = 3
+
+ val counter = Counter(1)
+
+ when(counter.inc()) {
+ stop()
+ }
+
+ val test_wire = Wire(UInt(1, width = test_wire_width))
+
+ // though we just set test_wire to 1, the assert below will pass because
+ // the finish will change it's value
+ assert(test_wire === UInt(test_wire_override_value))
+
+ /** In finish we use last connect semantics to alter the test_wire in the circuit
+ * with a new value
+ */
+ override def finish(): Unit = {
+ test_wire := UInt(test_wire_override_value)
+ }
+}
+
+class TesterDriverSpec extends ChiselFlatSpec {
+ "TesterDriver calls BasicTester's finish method which" should
+ "allow modifications of test circuit after the tester's constructor is done" in {
+ assertTesterPasses {
+ new FinishTester
+ }
+ }
+}
+