diff options
| author | ducky | 2015-12-11 14:25:42 -0800 |
|---|---|---|
| committer | ducky | 2015-12-11 17:16:30 -0800 |
| commit | dbd072172f6312893e1922e48ed768ae0fab9a89 (patch) | |
| tree | c3a0f10dd286ae2bba50c31b987ab39c45189898 /src/main/scala/Chisel | |
| parent | bffc67c2bbeb107d2ff9903aa35e85fbb7da73f9 (diff) | |
Refactor tests to use stop() and assert() instead of io.error/io.done
Gate assert, printf, stop by reset
Fix testbenches that never worked
Change simulation prints to display cycle at which test was signaled to end, not when simulator stops
Better documentation for Counter
Diffstat (limited to 'src/main/scala/Chisel')
| -rw-r--r-- | src/main/scala/Chisel/CoreUtil.scala | 47 | ||||
| -rw-r--r-- | src/main/scala/Chisel/testers/BasicTester.scala | 18 | ||||
| -rw-r--r-- | src/main/scala/Chisel/util/Counter.scala | 6 |
3 files changed, 54 insertions, 17 deletions
diff --git a/src/main/scala/Chisel/CoreUtil.scala b/src/main/scala/Chisel/CoreUtil.scala index 41266cae..aaca404b 100644 --- a/src/main/scala/Chisel/CoreUtil.scala +++ b/src/main/scala/Chisel/CoreUtil.scala @@ -7,21 +7,52 @@ import internal.Builder.pushCommand import firrtl._ object assert { + /** Checks for a condition to be valid in the circuit at all times. If the + * condition evaluates to false, the circuit simulation stops with an error. + * + * Does not fire when in reset (defined as the encapsulating Module's + * reset). If your definition of reset is not the encapsulating Module's + * reset, you will need to gate this externally. + * + * May be called outside of a Module (like defined in a function), so + * functions using assert make the standard Module assumptions (single clock + * and single reset). + * + * @param cond condition, assertion fires (simulation fails) when false + * @param message optional message to print when the assertion fires + */ def apply(cond: Bool, message: String="") { - when(!cond) { - if (message.isEmpty()) { - printf(s"Assertion failed: (TODO: code / lineno)") - } else { - printf(s"Assertion failed: (TODO: code / lineno): $message") + when (!Builder.dynamicContext.currentModule.get.reset) { + when(!cond) { + if (message.isEmpty()) { + printf(s"Assertion failed: (TODO: code / lineno)") + } else { + printf(s"Assertion failed: (TODO: code / lineno): $message") + } + pushCommand(Stop(Node(Builder.dynamicContext.currentModule.get.clock), 1)) } - pushCommand(Stop(Node(Builder.dynamicContext.currentModule.get.clock), 1)) } } } object printf { + /** Prints a message in simulation. + * + * Does not fire when in reset (defined as the encapsulating Module's + * reset). If your definition of reset is not the encapsulating Module's + * reset, you will need to gate this externally. + * + * May be called outside of a Module (like defined in a function), so + * functions using printf make the standard Module assumptions (single clock + * and single reset). + * + * @param fmt printf format string + * @param data format string varargs containing data to print + */ def apply(fmt: String, data: Bits*) { - pushCommand(Printf(Node(Builder.dynamicContext.currentModule.get.clock), - fmt, data.map(Node(_)))) + when (!Builder.dynamicContext.currentModule.get.reset) { + pushCommand(Printf(Node(Builder.dynamicContext.currentModule.get.clock), + fmt, data.map((d: Bits) => d.ref))) + } } } diff --git a/src/main/scala/Chisel/testers/BasicTester.scala b/src/main/scala/Chisel/testers/BasicTester.scala index fecbe2a9..1079727c 100644 --- a/src/main/scala/Chisel/testers/BasicTester.scala +++ b/src/main/scala/Chisel/testers/BasicTester.scala @@ -8,18 +8,20 @@ import internal.Builder.pushCommand import firrtl._ class BasicTester extends Module { - val io = new Bundle { - val done = Bool() - val error = UInt(width = 4) - } - io.done := Bool(false) - io.error := UInt(0) + // The testbench has no IOs, rather it should communicate using printf, assert, and stop. + val io = new Bundle() def popCount(n: Long): Int = n.toBinaryString.count(_=='1') - /** Ends the test, reporting success. + /** Ends the test reporting success. + * + * Does not fire when in reset (defined as the encapsulating Module's + * reset). If your definition of reset is not the encapsulating Module's + * reset, you will need to gate this externally. */ def stop() { - pushCommand(Stop(Node(clock), 0)) + when (!reset) { + pushCommand(Stop(Node(clock), 0)) + } } } diff --git a/src/main/scala/Chisel/util/Counter.scala b/src/main/scala/Chisel/util/Counter.scala index e4a8e95b..356cedc8 100644 --- a/src/main/scala/Chisel/util/Counter.scala +++ b/src/main/scala/Chisel/util/Counter.scala @@ -3,10 +3,14 @@ package Chisel /** A counter module - * @param n The maximum value of the counter, does not have to be power of 2 + * @param n number of counts before the counter resets (or one more than the + * maximum output value of the counter), need not be a power of two */ class Counter(val n: Int) { val value = if (n == 1) UInt(0) else Reg(init=UInt(0, log2Up(n))) + /** Increment the counter this cycle. Returns whether the counter is at its + * maximum (and will wrap around on the next inc() call). + */ def inc(): Bool = { if (n == 1) { Bool(true) |
