summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/resources/top.cpp25
-rw-r--r--src/main/scala/Chisel/CoreUtil.scala47
-rw-r--r--src/main/scala/Chisel/testers/BasicTester.scala18
-rw-r--r--src/main/scala/Chisel/util/Counter.scala6
4 files changed, 65 insertions, 31 deletions
diff --git a/src/main/resources/top.cpp b/src/main/resources/top.cpp
index 756b5531..075d7085 100644
--- a/src/main/resources/top.cpp
+++ b/src/main/resources/top.cpp
@@ -23,7 +23,6 @@ double sc_time_stamp () { // Called by $time in Verilog
const long timeout = 100000000L;
int main(int argc, char** argv) {
- vluint32_t done = 0;
Verilated::commandArgs(argc, argv); // Remember args
top = new TOP_TYPE;
@@ -36,11 +35,11 @@ int main(int argc, char** argv) {
#endif
- top->reset = 1;
+ top->reset = 1;
cout << "Starting simulation!\n";
- while (!Verilated::gotFinish() && !done && main_time < timeout) {
+ while (!Verilated::gotFinish() && main_time < timeout) {
if (main_time > 10) {
top->reset = 0; // Deassert reset
}
@@ -54,10 +53,18 @@ int main(int argc, char** argv) {
#if VM_TRACE
if (tfp) tfp->dump (main_time); // Create waveform trace for this timestamp
#endif
- done = top->io__024done;
main_time++; // Time passes...
}
+ if (main_time >= timeout) {
+ cout << "Simulation terminated by timeout at time " << main_time <<
+ " (cycle " << main_time / 10 << ")"<< endl;
+ return -1;
+ } else {
+ cout << "Simulation completed at time " << main_time <<
+ " (cycle " << main_time / 10 << ")"<< endl;
+ }
+
// Run for 10 more clocks
vluint64_t end_time = main_time + 100;
while (main_time < end_time) {
@@ -77,15 +84,5 @@ int main(int argc, char** argv) {
#if VM_TRACE
if (tfp) tfp->close();
#endif
-
- if (main_time >= timeout) {
- cout << "Simulation terminated by timeout at cycle " << main_time << endl;
- return -1;
- } else {
- cout << "Simulation completed at cycle " << main_time << endl;
- int error = top->io__024error;
- cout << "Simulation return value: " << error << endl;
- return error;
- }
}
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)