From 5859d231859c6a8b9c234e7a71cbc85e5d75f61b Mon Sep 17 00:00:00 2001 From: ducky Date: Fri, 11 Dec 2015 12:47:44 -0800 Subject: Add support for printf and asserts, add testbench for asserts and printf --- src/main/scala/Chisel/CoreUtil.scala | 27 +++++++++++++++++++++++++++ src/main/scala/Chisel/Module.scala | 4 ---- src/main/scala/Chisel/firrtl/Emitter.scala | 2 ++ src/main/scala/Chisel/firrtl/IR.scala | 2 ++ src/test/scala/chiselTests/Assert.scala | 28 ++++++++++++++++++++++++++++ src/test/scala/chiselTests/Printf.scala | 28 ++++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 src/main/scala/Chisel/CoreUtil.scala create mode 100644 src/test/scala/chiselTests/Assert.scala create mode 100644 src/test/scala/chiselTests/Printf.scala (limited to 'src') 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 }) + } +} -- cgit v1.2.3