diff options
| -rw-r--r-- | src/main/scala/Chisel/testers/BasicTester.scala | 7 | ||||
| -rw-r--r-- | src/main/scala/Chisel/testers/TesterDriver.scala | 13 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/TesterDriverSpec.scala | 44 |
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 + } + } +} + |
