summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorducky2015-12-11 12:47:44 -0800
committerducky2015-12-11 12:53:39 -0800
commit5859d231859c6a8b9c234e7a71cbc85e5d75f61b (patch)
treef8115324c12c54a3077517f5b6b997cc16951c64
parent20951ecdbcb81c194ddcdd1e8241b1bdd647dd9f (diff)
Add support for printf and asserts, add testbench for asserts and printf
-rw-r--r--src/main/scala/Chisel/CoreUtil.scala27
-rw-r--r--src/main/scala/Chisel/Module.scala4
-rw-r--r--src/main/scala/Chisel/firrtl/Emitter.scala2
-rw-r--r--src/main/scala/Chisel/firrtl/IR.scala2
-rw-r--r--src/test/scala/chiselTests/Assert.scala28
-rw-r--r--src/test/scala/chiselTests/Printf.scala28
6 files changed, 87 insertions, 4 deletions
diff --git a/src/main/scala/Chisel/CoreUtil.scala b/src/main/scala/Chisel/CoreUtil.scala
new file mode 100644
index 00000000..41266cae
--- /dev/null
+++ b/src/main/scala/Chisel/CoreUtil.scala
@@ -0,0 +1,27 @@
+// See LICENSE for license details.
+
+package Chisel
+
+import internal._
+import internal.Builder.pushCommand
+import firrtl._
+
+object assert {
+ 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")
+ }
+ pushCommand(Stop(Node(Builder.dynamicContext.currentModule.get.clock), 1))
+ }
+ }
+}
+
+object printf {
+ def apply(fmt: String, data: Bits*) {
+ pushCommand(Printf(Node(Builder.dynamicContext.currentModule.get.clock),
+ fmt, data.map(Node(_))))
+ }
+}
diff --git a/src/main/scala/Chisel/Module.scala b/src/main/scala/Chisel/Module.scala
index 4284bbc4..05b7dc26 100644
--- a/src/main/scala/Chisel/Module.scala
+++ b/src/main/scala/Chisel/Module.scala
@@ -95,8 +95,4 @@ abstract class Module(_clock: Clock = null, _reset: Bool = null) extends HasId {
_ids.foreach(_._onModuleClose)
this
}
-
- // TODO: actually implement these
- def assert(cond: Bool, msg: String): Unit = {}
- def printf(message: String, args: Bits*): Unit = {}
}
diff --git a/src/main/scala/Chisel/firrtl/Emitter.scala b/src/main/scala/Chisel/firrtl/Emitter.scala
index bcc566c5..1d0f4ddc 100644
--- a/src/main/scala/Chisel/firrtl/Emitter.scala
+++ b/src/main/scala/Chisel/firrtl/Emitter.scala
@@ -19,6 +19,8 @@ private class Emitter(circuit: Circuit) {
case e: Connect => s"${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}"
case e: BulkConnect => s"${e.loc1.fullName(ctx)} <> ${e.loc2.fullName(ctx)}"
case e: ConnectInit => s"onreset ${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}"
+ case e: Stop => s"stop(${e.clk.fullName(ctx)}, ${e.ret})"
+ case e: Printf => s"""printf(${e.clk.fullName(ctx)}, "${e.format}"${e.ids.map(_.fullName(ctx)).fold(""){_ + ", " + _}})"""
case e: DefInstance => {
val modName = moduleMap.getOrElse(e.id.name, e.id.name)
s"inst ${e.name} of $modName"
diff --git a/src/main/scala/Chisel/firrtl/IR.scala b/src/main/scala/Chisel/firrtl/IR.scala
index 458e6ac5..8cc31b54 100644
--- a/src/main/scala/Chisel/firrtl/IR.scala
+++ b/src/main/scala/Chisel/firrtl/IR.scala
@@ -151,6 +151,8 @@ case class WhenEnd() extends Command
case class Connect(loc: Node, exp: Arg) extends Command
case class BulkConnect(loc1: Node, loc2: Node) extends Command
case class ConnectInit(loc: Node, exp: Arg) extends Command
+case class Stop(clk: Arg, ret: Int) extends Command
+case class Printf(clk: Arg, format: String, ids: Seq[Arg]) extends Command
case class Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Arg
case class Port(id: Data, dir: Direction)
diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala
new file mode 100644
index 00000000..31e53f36
--- /dev/null
+++ b/src/test/scala/chiselTests/Assert.scala
@@ -0,0 +1,28 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import org.scalatest._
+import Chisel._
+import Chisel.testers.BasicTester
+
+class FailingAssertTester() extends BasicTester {
+ assert(Bool(false))
+ io.done := Bool(true)
+ io.error := Bool(false)
+}
+
+class SucceedingAssertTester() extends BasicTester {
+ assert(Bool(true))
+ io.done := Bool(true)
+ io.error := Bool(false)
+}
+
+class AssertSpec extends ChiselFlatSpec {
+ "A failing assertion" should "fail the testbench" in {
+ assert(!execute{ new FailingAssertTester })
+ }
+ "A succeeding assertion" should "not fail the testbench" in {
+ assert(execute{ new SucceedingAssertTester })
+ }
+}
diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala
new file mode 100644
index 00000000..e6f5d222
--- /dev/null
+++ b/src/test/scala/chiselTests/Printf.scala
@@ -0,0 +1,28 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import org.scalatest._
+import Chisel._
+import Chisel.testers.BasicTester
+
+class SinglePrintfTester() extends BasicTester {
+ printf("done=%x", io.done)
+ io.done := Bool(true)
+ io.error := Bool(false)
+}
+
+class MultiPrintfTester() extends BasicTester {
+ printf("done=%x error=%x", io.done, io.error)
+ io.done := Bool(true)
+ io.error := Bool(false)
+}
+
+class PrintfSpec extends ChiselFlatSpec {
+ "A printf with a single argument" should "run" in {
+ assert(execute{ new SinglePrintfTester })
+ }
+ "A printf with multiple arguments" should "run" in {
+ assert(execute{ new MultiPrintfTester })
+ }
+}