From 7e5aef460e089b3dfd53ddd181f9384cc25145d7 Mon Sep 17 00:00:00 2001 From: jackkoenig Date: Tue, 20 Sep 2016 16:12:59 -0700 Subject: Add Cookbook tests These tests are intended to be the examples in the Chisel3 Wiki Cookbook. --- src/test/scala/cookbook/Bundle2UInt.scala | 31 ++++++++++++++++++++++++++++ src/test/scala/cookbook/CookbookSpec.scala | 25 ++++++++++++++++++++++ src/test/scala/cookbook/UInt2Bundle.scala | 30 +++++++++++++++++++++++++++ src/test/scala/cookbook/UInt2VecOfBool.scala | 29 ++++++++++++++++++++++++++ src/test/scala/cookbook/VecOfBool2UInt.scala | 28 +++++++++++++++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 src/test/scala/cookbook/Bundle2UInt.scala create mode 100644 src/test/scala/cookbook/CookbookSpec.scala create mode 100644 src/test/scala/cookbook/UInt2Bundle.scala create mode 100644 src/test/scala/cookbook/UInt2VecOfBool.scala create mode 100644 src/test/scala/cookbook/VecOfBool2UInt.scala (limited to 'src') diff --git a/src/test/scala/cookbook/Bundle2UInt.scala b/src/test/scala/cookbook/Bundle2UInt.scala new file mode 100644 index 00000000..d74218a8 --- /dev/null +++ b/src/test/scala/cookbook/Bundle2UInt.scala @@ -0,0 +1,31 @@ +// See LICENSE for license details. + +package cookbook + +import chisel3._ + +/* ### How do I create a UInt from an instance of a Bundle? + * + * Call asUInt on the Bundle instance + */ +class Bundle2UInt extends CookbookTester(0) { + // Example + class MyBundle extends Bundle { + val foo = UInt(width = 4) + val bar = UInt(width = 4) + } + val bundle = Wire(new MyBundle) + bundle.foo := UInt(0xc) + bundle.bar := UInt(0x3) + val uint = bundle.asUInt + printf(p"$uint") // 195 + + // Test + assert(uint === UInt(0xc3)) +} + +class Bundle2UIntSpec extends CookbookSpec { + "Bundle2UInt" should "work" in { + assertTesterPasses { new Bundle2UInt } + } +} diff --git a/src/test/scala/cookbook/CookbookSpec.scala b/src/test/scala/cookbook/CookbookSpec.scala new file mode 100644 index 00000000..b244f3cf --- /dev/null +++ b/src/test/scala/cookbook/CookbookSpec.scala @@ -0,0 +1,25 @@ +// See LICENSE for license details. + +package cookbook + +import chisel3._ +import chisel3.util._ +import chisel3.testers.BasicTester + +import chiselTests.ChiselFlatSpec + +/** Tester for concise cookbook tests + * + * Provides a length of test after which the test will pass + */ +abstract class CookbookTester(length: Int) extends BasicTester { + require(length >= 0, "Simulation length must be non-negative!") + + // No IO allowed, cookbook tests must be self-contained + override final val io = new Bundle { } + + val (cycle, done) = Counter(Bool(true), length) + when (done) { stop() } +} + +abstract class CookbookSpec extends ChiselFlatSpec diff --git a/src/test/scala/cookbook/UInt2Bundle.scala b/src/test/scala/cookbook/UInt2Bundle.scala new file mode 100644 index 00000000..fbf7fe8a --- /dev/null +++ b/src/test/scala/cookbook/UInt2Bundle.scala @@ -0,0 +1,30 @@ +// See LICENSE for license details. + +package cookbook + +import chisel3._ + +/* ### How do I create a Bundle from a UInt? + * + * On an instance of the Bundle, call the method fromBits with the UInt as the argument + */ +class UInt2Bundle extends CookbookTester(0) { + // Example + class MyBundle extends Bundle { + val foo = UInt(width = 4) + val bar = UInt(width = 4) + } + val uint = UInt(0xb4) + val bundle = (new MyBundle).fromBits(uint) + printf(p"$bundle") // Bundle(foo -> 11, bar -> 4) + + // Test + assert(bundle.foo === UInt(0xb)) + assert(bundle.bar === UInt(0x4)) +} + +class UInt2BundleSpec extends CookbookSpec { + "UInt2Bundle" should "work" in { + assertTesterPasses { new UInt2Bundle } + } +} diff --git a/src/test/scala/cookbook/UInt2VecOfBool.scala b/src/test/scala/cookbook/UInt2VecOfBool.scala new file mode 100644 index 00000000..ad4a0334 --- /dev/null +++ b/src/test/scala/cookbook/UInt2VecOfBool.scala @@ -0,0 +1,29 @@ +// See LICENSE for license details. + +package cookbook + +import chisel3._ + +/* ### How do I create a Vec of Bools from a UInt? + * + * Use the builtin function [[chisel3.core.Bits.toBools]] to create a Scala Seq of Bool, + * then wrap the resulting Seq in Vec(...) + */ +class UInt2VecOfBool extends CookbookTester(0) { + // Example + val uint = UInt(0xc) + val vec = Vec(uint.toBools) + printf(p"$vec") // Vec(0, 0, 1, 1) + + // Test + assert(vec(0) === Bool(false)) + assert(vec(1) === Bool(false)) + assert(vec(2) === Bool(true)) + assert(vec(3) === Bool(true)) +} + +class UInt2VecOfBoolSpec extends CookbookSpec { + "UInt2VecOfBool" should "work" in { + assertTesterPasses { new UInt2VecOfBool } + } +} diff --git a/src/test/scala/cookbook/VecOfBool2UInt.scala b/src/test/scala/cookbook/VecOfBool2UInt.scala new file mode 100644 index 00000000..5852120c --- /dev/null +++ b/src/test/scala/cookbook/VecOfBool2UInt.scala @@ -0,0 +1,28 @@ +// See LICENSE for license details. + +package cookbook + +import chisel3._ + +/* ### How do I create a UInt from a Vec of Bool? + * + * Use the builtin function asUInt + */ +class VecOfBool2UInt extends CookbookTester(0) { + // Example + val vec = Vec(Bool(true), Bool(false), Bool(true), Bool(true)) + val uint = vec.asUInt + printf(p"$uint") // 13 + + /* Test + * + * (remember leftmost Bool in Vec is low order bit) + */ + assert(UInt(0xd) === uint) +} + +class VecOfBool2UIntSpec extends CookbookSpec { + "VecOfBool2UInt" should "work" in { + assertTesterPasses { new VecOfBool2UInt } + } +} -- cgit v1.2.3 From 1abe52da025c3935c28d0280abbadf40021d5b3f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 4 Oct 2016 11:02:14 -0700 Subject: Generate a better error message for missing IO() wrapper - fix #305 --- src/test/scala/chiselTests/IOCompatibility.scala | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala index 7bf3dded..552fe776 100644 --- a/src/test/scala/chiselTests/IOCompatibility.scala +++ b/src/test/scala/chiselTests/IOCompatibility.scala @@ -3,6 +3,8 @@ package chiselTests import chisel3._ +import chisel3.core.Binding.BindingException +import org.scalatest._ class IOCSimpleIO extends Bundle { val in = Input(UInt(width=32)) @@ -33,7 +35,7 @@ class IOCModuleWire extends Module { io.out := inc.out } -class IOCompatibilitySpec extends ChiselPropSpec { +class IOCompatibilitySpec extends ChiselPropSpec with Matchers { property("IOCModuleVec should elaborate") { elaborate { new IOCModuleVec(2) } @@ -42,4 +44,16 @@ class IOCompatibilitySpec extends ChiselPropSpec { property("IOCModuleWire should elaborate") { elaborate { new IOCModuleWire } } + + + class IOUnwrapped extends Module { + val io = new IOCSimpleIO + io.out := io.in + } + + property("Unwrapped IO should generate an exception") { + a [BindingException] should be thrownBy { + elaborate(new IOUnwrapped) + } + } } -- cgit v1.2.3 From ffe58abac5f60d785b684bb249aee0153bddea3f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 19 Sep 2016 15:27:52 -0700 Subject: Add sbt-buildinfo support. --- src/main/scala/chisel3/Driver.scala | 4 ++++ src/test/scala/chiselTests/BuildInfoTests.scala | 13 +++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/test/scala/chiselTests/BuildInfoTests.scala (limited to 'src') diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 5e0a3a0f..2216bbbd 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -7,6 +7,7 @@ import java.io._ import internal._ import internal.firrtl._ +import BuildInfo._ trait BackendCompilationUtilities { /** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6. @@ -132,4 +133,7 @@ object Driver extends BackendCompilationUtilities { } def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath } + + val version = BuildInfo.version + val chiselVersionString = BuildInfo.toString } diff --git a/src/test/scala/chiselTests/BuildInfoTests.scala b/src/test/scala/chiselTests/BuildInfoTests.scala new file mode 100644 index 00000000..21eae17c --- /dev/null +++ b/src/test/scala/chiselTests/BuildInfoTests.scala @@ -0,0 +1,13 @@ +package chiselTests + +import org.scalatest.FlatSpec + +//import Chisel._ + +class BuildInfoTests extends FlatSpec { + behavior of "BuildInfoTests" + + it should "provide correct BuildInfo" in { + println(Chisel.Driver.chiselVersionString) + } +} -- cgit v1.2.3 From f98171296f821034cf66ace070bcf179183e833d Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 5 Oct 2016 09:25:07 -0700 Subject: Print Chisel version when Driver object is created. --- src/main/scala/chisel3/Driver.scala | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 2216bbbd..e91b40b4 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -136,4 +136,5 @@ object Driver extends BackendCompilationUtilities { val version = BuildInfo.version val chiselVersionString = BuildInfo.toString + println(chiselVersionString) } -- cgit v1.2.3 From 2979cb900c4f6773210dbe174091c08e13e6c52a Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 6 Oct 2016 09:21:03 -0700 Subject: Update Driver: Check the simulation exit code #281 Merge with master and support checking for failure with an explicit assertion message. --- src/main/scala/chisel3/Driver.scala | 9 ++++++--- src/test/scala/chiselTests/MultiAssign.scala | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 5e0a3a0f..190b36bf 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -86,14 +86,17 @@ trait BackendCompilationUtilities { def executeExpectingFailure( prefix: String, dir: File, - assertionMsg: String = "Assertion failed"): Boolean = { + assertionMsg: String = ""): Boolean = { var triggered = false + val assertionMessageSupplied = assertionMsg != "" val e = Process(s"./V${prefix}", dir) ! ProcessLogger(line => { - triggered = triggered || line.contains(assertionMsg) + triggered = triggered || (assertionMessageSupplied && line.contains(assertionMsg)) System.out.println(line) // scalastyle:ignore regex }) - triggered + // Fail if a line contained an assertion or if we get a non-zero exit code + // or, we get a SIGABRT (assertion failure) and we didn't provide a specific assertion message + triggered || (e != 0 && (e != 134 || !assertionMessageSupplied)) } def executeExpectingSuccess(prefix: String, dir: File): Boolean = { diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index fa4c4898..397ea4c2 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -9,7 +9,8 @@ import chisel3.testers.BasicTester import chisel3.util._ class LastAssignTester() extends BasicTester { - val cnt = Counter(2) + val countOnClockCycles = Bool(true) + val (cnt, wrap) = Counter(countOnClockCycles,2) val test = Wire(UInt.width(4)) assert(test === 7.U) // allow read references before assign references @@ -20,7 +21,7 @@ class LastAssignTester() extends BasicTester { test := 7.U assert(test === 7.U) // this obviously should work - when(cnt.value === 1.U) { + when(cnt === 1.U) { stop() } } -- cgit v1.2.3 From a5aba40349e290c30280df25bc5b0ba848183469 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 6 Oct 2016 10:40:10 -0700 Subject: Add comments; correct Complex definition (use cloneType). --- src/test/scala/chiselTests/ComplexAssign.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 0a1f31cc..c5a23f82 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -11,7 +11,7 @@ import chisel3.util._ class Complex[T <: Data](val re: T, val im: T) extends Bundle { override def cloneType: this.type = - new Complex(re.chiselCloneType, im.chiselCloneType).asInstanceOf[this.type] + new Complex(re.cloneType, im.cloneType).asInstanceOf[this.type] } class ComplexAssign(w: Int) extends Module { -- cgit v1.2.3 From 210bc8ce1cc80f7232a07c5ac8de120e5df300e7 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 6 Oct 2016 11:29:59 -0700 Subject: Remove EnqIO, DeqIO - #308 --- src/main/scala/chisel3/compatibility.scala | 19 ------------------- src/main/scala/chisel3/package.scala | 22 ---------------------- 2 files changed, 41 deletions(-) (limited to 'src') diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index d13fcb06..d0d2ddb4 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -158,25 +158,6 @@ package object Chisel { // scalastyle:ignore package.object.name type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T] val DecoupledIO = chisel3.util.Decoupled val Decoupled = chisel3.util.Decoupled - class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { - def init(): Unit = { - this.noenq() - } - override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] - } - class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { - chisel3.core.Binding.bind(this, chisel3.core.FlippedBinder, "Error: Cannot flip ") - def init(): Unit = { - this.nodeq() - } - override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type] - } - object EnqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) - } - object DeqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) - } type QueueIO[T <: Data] = chisel3.util.QueueIO[T] type Queue[T <: Data] = chisel3.util.Queue[T] val Queue = chisel3.util.Queue diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 17ddd55a..0a57b7de 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -166,28 +166,6 @@ package object chisel3 { // scalastyle:ignore package.object.name val NODIR = chisel3.core.Direction.Unspecified type ChiselException = chisel3.internal.ChiselException - class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { - def init(): Unit = { - this.noenq() - } - override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] - } - class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { - val Data = chisel3.core.Data - Data.setFirrtlDirection(this, Data.getFirrtlDirection(this).flip) - Binding.bind(this, FlippedBinder, "Error: Cannot flip ") - def init(): Unit = { - this.nodeq() - } - override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type] - } - object EnqIO { - def apply[T<:Data](gen: T): EnqIO[T] = new EnqIO(gen) - } - object DeqIO { - def apply[T<:Data](gen: T): DeqIO[T] = new DeqIO(gen) - } - // Debugger/Tester access to internal Chisel data structures and methods. def getDataElements(a: Aggregate): Seq[Element] = { a.allElements -- cgit v1.2.3 From 39e3d05dfcd05bb278e08543be3bbc9204e690ca Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 6 Oct 2016 13:30:31 -0700 Subject: Remove non-standard sbt-buildinfo settings; write buildinfo to firrtl file. --- src/main/scala/chisel3/Driver.scala | 1 - src/main/scala/chisel3/internal/firrtl/Emitter.scala | 2 +- src/test/scala/chiselTests/BuildInfoTests.scala | 13 ------------- 3 files changed, 1 insertion(+), 15 deletions(-) delete mode 100644 src/test/scala/chiselTests/BuildInfoTests.scala (limited to 'src') diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 03f8547e..b0c7aeda 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -139,5 +139,4 @@ object Driver extends BackendCompilationUtilities { val version = BuildInfo.version val chiselVersionString = BuildInfo.toString - println(chiselVersionString) } diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index f1908089..a559ddc5 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -102,7 +102,7 @@ private class Emitter(circuit: Circuit) { private def unindent() { require(indentLevel > 0); indentLevel -= 1 } private def withIndent(f: => Unit) { indent(); f; unindent() } - private val res = new StringBuilder(s"circuit ${circuit.name} : ") + private val res = new StringBuilder(s";${Driver.chiselVersionString}\ncircuit ${circuit.name} : ") withIndent { circuit.components.foreach(c => res ++= emit(c)) } res ++= newline } diff --git a/src/test/scala/chiselTests/BuildInfoTests.scala b/src/test/scala/chiselTests/BuildInfoTests.scala deleted file mode 100644 index 21eae17c..00000000 --- a/src/test/scala/chiselTests/BuildInfoTests.scala +++ /dev/null @@ -1,13 +0,0 @@ -package chiselTests - -import org.scalatest.FlatSpec - -//import Chisel._ - -class BuildInfoTests extends FlatSpec { - behavior of "BuildInfoTests" - - it should "provide correct BuildInfo" in { - println(Chisel.Driver.chiselVersionString) - } -} -- cgit v1.2.3 From 5b8c8fbb169c9e0635bbd7274232390049e7c894 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 6 Oct 2016 16:42:10 -0700 Subject: Breakup the initial emitted string per @ducky64. --- src/main/scala/chisel3/internal/firrtl/Emitter.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index a559ddc5..9c766ec3 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -102,7 +102,9 @@ private class Emitter(circuit: Circuit) { private def unindent() { require(indentLevel > 0); indentLevel -= 1 } private def withIndent(f: => Unit) { indent(); f; unindent() } - private val res = new StringBuilder(s";${Driver.chiselVersionString}\ncircuit ${circuit.name} : ") + private val res = new StringBuilder() + res ++= s";${Driver.chiselVersionString}\n" + res ++= "circuit ${circuit.name} : " withIndent { circuit.components.foreach(c => res ++= emit(c)) } res ++= newline } -- cgit v1.2.3 From 10f170110cd00e7e5e0b428c0490594dac4db225 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 6 Oct 2016 16:46:27 -0700 Subject: Revert "Merge pull request #322 from ucb-bar/deleteEnqIODeqIO" This reverts commit 3ea7faaad0c3e349c531fabc8a75440337bdc235, reversing changes made to 7aea39d4deac62d5477904f4bf4381c3482c41d0. Update chisel-testers before commiting this change (deleting EnqIO/DeqIO). --- src/main/scala/chisel3/compatibility.scala | 19 +++++++++++++++++++ src/main/scala/chisel3/package.scala | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'src') diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index d0d2ddb4..d13fcb06 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -158,6 +158,25 @@ package object Chisel { // scalastyle:ignore package.object.name type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T] val DecoupledIO = chisel3.util.Decoupled val Decoupled = chisel3.util.Decoupled + class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + def init(): Unit = { + this.noenq() + } + override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] + } + class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + chisel3.core.Binding.bind(this, chisel3.core.FlippedBinder, "Error: Cannot flip ") + def init(): Unit = { + this.nodeq() + } + override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type] + } + object EnqIO { + def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) + } + object DeqIO { + def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) + } type QueueIO[T <: Data] = chisel3.util.QueueIO[T] type Queue[T <: Data] = chisel3.util.Queue[T] val Queue = chisel3.util.Queue diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 0a57b7de..17ddd55a 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -166,6 +166,28 @@ package object chisel3 { // scalastyle:ignore package.object.name val NODIR = chisel3.core.Direction.Unspecified type ChiselException = chisel3.internal.ChiselException + class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + def init(): Unit = { + this.noenq() + } + override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] + } + class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + val Data = chisel3.core.Data + Data.setFirrtlDirection(this, Data.getFirrtlDirection(this).flip) + Binding.bind(this, FlippedBinder, "Error: Cannot flip ") + def init(): Unit = { + this.nodeq() + } + override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type] + } + object EnqIO { + def apply[T<:Data](gen: T): EnqIO[T] = new EnqIO(gen) + } + object DeqIO { + def apply[T<:Data](gen: T): DeqIO[T] = new DeqIO(gen) + } + // Debugger/Tester access to internal Chisel data structures and methods. def getDataElements(a: Aggregate): Seq[Element] = { a.allElements -- cgit v1.2.3 From b9e2a664de7cd35ab5cd176350bafed435dc10e9 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 6 Oct 2016 16:55:42 -0700 Subject: Fix typo in emitted string. --- src/main/scala/chisel3/internal/firrtl/Emitter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 9c766ec3..e0daa95c 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -104,7 +104,7 @@ private class Emitter(circuit: Circuit) { private val res = new StringBuilder() res ++= s";${Driver.chiselVersionString}\n" - res ++= "circuit ${circuit.name} : " + res ++= s"circuit ${circuit.name} : " withIndent { circuit.components.foreach(c => res ++= emit(c)) } res ++= newline } -- cgit v1.2.3 From 87606210dd0a15122ea93136a3e9b073674d779e Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 7 Oct 2016 13:25:44 -0700 Subject: Revert "Revert "Merge pull request #322 from ucb-bar/deleteEnqIODeqIO"" This reverts commit 10f170110cd00e7e5e0b428c0490594dac4db225. --- src/main/scala/chisel3/compatibility.scala | 19 ------------------- src/main/scala/chisel3/package.scala | 22 ---------------------- 2 files changed, 41 deletions(-) (limited to 'src') diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index d13fcb06..d0d2ddb4 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -158,25 +158,6 @@ package object Chisel { // scalastyle:ignore package.object.name type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T] val DecoupledIO = chisel3.util.Decoupled val Decoupled = chisel3.util.Decoupled - class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { - def init(): Unit = { - this.noenq() - } - override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] - } - class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { - chisel3.core.Binding.bind(this, chisel3.core.FlippedBinder, "Error: Cannot flip ") - def init(): Unit = { - this.nodeq() - } - override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type] - } - object EnqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) - } - object DeqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) - } type QueueIO[T <: Data] = chisel3.util.QueueIO[T] type Queue[T <: Data] = chisel3.util.Queue[T] val Queue = chisel3.util.Queue diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 17ddd55a..0a57b7de 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -166,28 +166,6 @@ package object chisel3 { // scalastyle:ignore package.object.name val NODIR = chisel3.core.Direction.Unspecified type ChiselException = chisel3.internal.ChiselException - class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { - def init(): Unit = { - this.noenq() - } - override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] - } - class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { - val Data = chisel3.core.Data - Data.setFirrtlDirection(this, Data.getFirrtlDirection(this).flip) - Binding.bind(this, FlippedBinder, "Error: Cannot flip ") - def init(): Unit = { - this.nodeq() - } - override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type] - } - object EnqIO { - def apply[T<:Data](gen: T): EnqIO[T] = new EnqIO(gen) - } - object DeqIO { - def apply[T<:Data](gen: T): DeqIO[T] = new DeqIO(gen) - } - // Debugger/Tester access to internal Chisel data structures and methods. def getDataElements(a: Aggregate): Seq[Element] = { a.allElements -- cgit v1.2.3 From ed872df330cb7dfabdd0e0866176f8f5be8861da Mon Sep 17 00:00:00 2001 From: Scott Beamer Date: Mon, 19 Sep 2016 16:54:16 -0700 Subject: remove trailing whitespace for annotations --- src/main/scala/chisel3/internal/firrtl/Emitter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index e0daa95c..0793fd7d 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -40,7 +40,7 @@ private class Emitter(circuit: Circuit) { s"skip" } e.sourceInfo match { - case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}] " + case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}]" case _: NoSourceInfo => firrtlLine } } -- cgit v1.2.3 From 070a8d724b282d3866da530b5d99ce7646fbf00e Mon Sep 17 00:00:00 2001 From: chick Date: Thu, 29 Sep 2016 00:37:32 -0700 Subject: Implement a standardized execution scheme for chisel Provide support for chisel options Provide support for firrtl options when called as part of chisel compile provide command line support the above options via scopt provide and execution result class that can be used when chisel3 is part of some externally controlled toolchain --- .../scala/chisel3/ChiselExecutionOptions.scala | 34 +++++ src/main/scala/chisel3/Driver.scala | 144 ++++++++++++++++++++- src/main/scala/chisel3/testers/TesterDriver.scala | 35 +++-- src/test/scala/chiselTests/DriverSpec.scala | 33 +++++ src/test/scala/chiselTests/Reg.scala | 1 + 5 files changed, 235 insertions(+), 12 deletions(-) create mode 100644 src/main/scala/chisel3/ChiselExecutionOptions.scala create mode 100644 src/test/scala/chiselTests/DriverSpec.scala (limited to 'src') diff --git a/src/main/scala/chisel3/ChiselExecutionOptions.scala b/src/main/scala/chisel3/ChiselExecutionOptions.scala new file mode 100644 index 00000000..6f58153f --- /dev/null +++ b/src/main/scala/chisel3/ChiselExecutionOptions.scala @@ -0,0 +1,34 @@ +// See LICENSE for license details. + +package chisel3 + +import firrtl.{ExecutionOptionsManager, ComposableOptions} + +//TODO: provide support for running firrtl as separate process, could alternatively be controlled by external driver +//TODO: provide option for not saving chirrtl file, instead calling firrtl with in memory chirrtl +/** + * Options that are specific to chisel. + * + * @param runFirrtlCompiler when true just run chisel, when false run chisel then compile its output with firrtl + * @note this extends FirrtlExecutionOptions which extends CommonOptions providing easy access to down chain options + */ +case class ChiselExecutionOptions( + runFirrtlCompiler: Boolean = true + // var runFirrtlAsProcess: Boolean = false + ) extends ComposableOptions + +trait HasChiselExecutionOptions { + self: ExecutionOptionsManager => + + var chiselOptions = ChiselExecutionOptions() + + parser.note("chisel3 options") + + parser.opt[Unit]("no-run-firrtl") + .abbr("chnrf") + .foreach { _ => + chiselOptions = chiselOptions.copy(runFirrtlCompiler = false) + } + .text("Stop after chisel emits chirrtl file") +} + diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index b0c7aeda..dbd9b464 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -2,11 +2,36 @@ package chisel3 +import chisel3.internal.firrtl.Emitter + import scala.sys.process._ import java.io._ -import internal._ import internal.firrtl._ +import firrtl._ + +/** + * The Driver provides methods to invoke the chisel3 compiler and the firrtl compiler. + * By default firrtl is automatically run after chisel. an [[ExecutionOptionsManager]] + * is needed to manage options. It can parser command line arguments or coordinate + * multiple chisel toolchain tools options. + * + * @example + * {{{ + * val optionsManager = new ExecutionOptionsManager("chisel3") + * with FirrtlExecutionOptions + * with ChiselExecutionOptions { + * commonOptions = CommonOption(targetDirName = "my_target_dir") + * chiselOptions = ChiselExecutionOptions(runFirrtlCompiler = false) + * } + * chisel3.Driver.execute(optionsManager, () => new Dut) + * }}} + * or via command line arguments + * @example {{{ + * args = "--no-run-firrtl --target-dir my-target-dir".split(" +") + * chisel3.execute(args, () => new DUT) + * }}} + */ import BuildInfo._ trait BackendCompilationUtilities { @@ -32,6 +57,32 @@ trait BackendCompilationUtilities { vf } + /** + * like 'firrtlToVerilog' except it runs the process inside the same JVM + * + * @param prefix basename of the file + * @param dir directory where file lives + * @return true if compiler completed successfully + */ + def compileFirrtlToVerilog(prefix: String, dir: File): Boolean = { + val optionsManager = new ExecutionOptionsManager("chisel3") with HasChiselExecutionOptions with HasFirrtlOptions { + commonOptions = CommonOptions(topName = prefix, targetDirName = dir.getAbsolutePath) + firrtlOptions = FirrtlExecutionOptions(compilerName = "verilog") + } + + firrtl.Driver.execute(optionsManager) match { + case _: FirrtlExecutionSuccess => true + case _: FirrtlExecutionFailure => false + } + } + + /** + * compule chirrtl to verilog by using a separate process + * + * @param prefix basename of the file + * @param dir directory where file lives + * @return true if compiler completed successfully + */ def firrtlToVerilog(prefix: String, dir: File): ProcessBuilder = { Process( Seq("firrtl", @@ -105,6 +156,30 @@ trait BackendCompilationUtilities { } } +/** + * This family provides return values from the chisel3 and possibly firrtl compile steps + */ +trait ChiselExecutionResult + +/** + * + * @param circuitOption Optional circuit, has information like circuit name + * @param emitted The emitted Chirrrl text + * @param firrtlResultOption Optional Firrtl result, @see ucb-bar/firrtl for details + */ +case class ChiselExecutionSucccess( + circuitOption: Option[Circuit], + emitted: String, + firrtlResultOption: Option[FirrtlExecutionResult] + ) extends ChiselExecutionResult + +/** + * Getting one of these indicates failure of some sort + * + * @param message a clue perhaps will be provided in the here + */ +case class ChiselExecutionFailure(message: String) extends ChiselExecutionResult + object Driver extends BackendCompilationUtilities { /** Elaborates the Module specified in the gen function into a Circuit @@ -112,7 +187,7 @@ object Driver extends BackendCompilationUtilities { * @param gen a function that creates a Module hierarchy * @return the resulting Chisel IR in the form of a Circuit (TODO: Should be FIRRTL IR) */ - def elaborate[T <: Module](gen: () => T): Circuit = Builder.build(Module(gen())) + def elaborate[T <: Module](gen: () => T): Circuit = internal.Builder.build(Module(gen())) def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) @@ -137,6 +212,71 @@ object Driver extends BackendCompilationUtilities { def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath } + /** + * Run the chisel3 compiler and possibly the firrtl compiler with options specified + * + * @param optionsManager The options specified + * @param dut The device under test + * @return An execution result with useful stuff, or failure with message + */ + def execute( + optionsManager: ExecutionOptionsManager with HasChiselExecutionOptions with HasFirrtlOptions, + dut: () => Module): ChiselExecutionResult = { + val circuit = elaborate(dut) + + // this little hack let's us set the topName with the circuit name if it has not been set from args + optionsManager.setTopNameIfNotSet(circuit.name) + + val firrtlOptions = optionsManager.firrtlOptions + val chiselOptions = optionsManager.chiselOptions + + // use input because firrtl will be reading this + val firrtlString = Emitter.emit(circuit) + val firrtlFileName = firrtlOptions.getInputFileName(optionsManager) + val firrtlFile = new File(firrtlFileName) + + val w = new FileWriter(firrtlFile) + w.write(firrtlString) + w.close() + + val firrtlExecutionResult = if(chiselOptions.runFirrtlCompiler) { + Some(firrtl.Driver.execute(optionsManager)) + } + else { + None + } + ChiselExecutionSucccess(Some(circuit), firrtlString, firrtlExecutionResult) + } + + /** + * Run the chisel3 compiler and possibly the firrtl compiler with options specified via an array of Strings + * + * @param args The options specified, command line style + * @param dut The device under test + * @return An execution result with useful stuff, or failure with message + */ + def execute(args: Array[String], dut: () => Module): ChiselExecutionResult = { + val optionsManager = new ExecutionOptionsManager("chisel3") with HasChiselExecutionOptions with HasFirrtlOptions + + optionsManager.parse(args) match { + case true => + execute(optionsManager, dut) + case _ => + ChiselExecutionFailure("could not parse results") + } + } + + /** + * This is just here as command line way to see what the options are + * It will not successfully run + * TODO: Look into dynamic class loading as way to make this main useful + * + * @param args unused args + */ + def main(args: Array[String]) { + execute(Array("--help"), null) + } + val version = BuildInfo.version val chiselVersionString = BuildInfo.toString } diff --git a/src/main/scala/chisel3/testers/TesterDriver.scala b/src/main/scala/chisel3/testers/TesterDriver.scala index 586fa780..76b9a2e9 100644 --- a/src/main/scala/chisel3/testers/TesterDriver.scala +++ b/src/main/scala/chisel3/testers/TesterDriver.scala @@ -3,15 +3,13 @@ package chisel3.testers import chisel3._ -import scala.io.Source -import scala.sys.process._ import java.io._ object TesterDriver extends BackendCompilationUtilities { /** Copy the contents of a resource to a destination file. */ def copyResourceToFile(name: String, file: File) { - val in = getClass().getResourceAsStream(name) + val in = getClass.getResourceAsStream(name) if (in == null) { throw new FileNotFoundException(s"Resource '$name'") } @@ -22,7 +20,9 @@ object TesterDriver extends BackendCompilationUtilities { /** For use with modules that should successfully be elaborated by the * frontend, and which can be turned into executables with assertions. */ - def execute(t: () => BasicTester, additionalVResources: Seq[String] = Seq()): Boolean = { + def execute(t: () => BasicTester, + additionalVResources: Seq[String] = Seq(), + runFirrtlasProcess: Boolean = false): Boolean = { // Invoke the chisel compiler to get the circuit's IR val circuit = Driver.elaborate(finishWrapper(t)) @@ -46,13 +46,28 @@ object TesterDriver extends BackendCompilationUtilities { out }) - // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe - if ((firrtlToVerilog(target, path) #&& + if(runFirrtlasProcess) { + // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe + if ((firrtlToVerilog(target, path) #&& verilogToCpp(target, target, path, additionalVFiles, cppHarness) #&& - cppToExe(target, path)).! == 0) { - executeExpectingSuccess(target, path) - } else { - false + cppToExe(target, path)).! == 0) { + executeExpectingSuccess(target, path) + } else { + false + } + } + else { + // Compile firrtl + if (!compileFirrtlToVerilog(target, path)) { + return false + } + // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe + if ((verilogToCpp(target, target, path, additionalVFiles, cppHarness) #&& + cppToExe(target, path)).! == 0) { + executeExpectingSuccess(target, path) + } else { + false + } } } /** diff --git a/src/test/scala/chiselTests/DriverSpec.scala b/src/test/scala/chiselTests/DriverSpec.scala new file mode 100644 index 00000000..4f9619e3 --- /dev/null +++ b/src/test/scala/chiselTests/DriverSpec.scala @@ -0,0 +1,33 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ + +import org.scalatest.{Matchers, FreeSpec} + +class DummyModule extends Module { + val io = IO(new Bundle { + val in = UInt(INPUT, 1) + val out = UInt(OUTPUT, 1) + }) + io.out := io.in +} + +class DriverSpec extends FreeSpec with Matchers { + "Driver's execute methods are used to run chisel and firrtl" - { + "options can be picked up from comand line with no args" in { + Driver.execute(Array.empty[String], () => new DummyModule) + } + "options can be picked up from comand line setting top name" in { + Driver.execute(Array("-tn", "dm", "-td", "local-build"), () => new DummyModule) + } + "execute returns a chisel execution result" in { + val args = Array("--compiler", "low") + val result = Driver.execute(Array.empty[String], () => new DummyModule) + result shouldBe a[ChiselExecutionSucccess] + val successResult = result.asInstanceOf[ChiselExecutionSucccess] + successResult.emitted should include ("circuit DummyModule") + } + } +} diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index a9086223..90992c01 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -2,6 +2,7 @@ package chiselTests +import firrtl.ir.Input import org.scalatest._ import chisel3._ import chisel3.core.DataMirror -- cgit v1.2.3 From d683e3de74e54766e8ef6f44a7dcb2e42de2df2f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 19 Oct 2016 12:57:12 -0700 Subject: Deprecate "!=". (#323) --- src/main/scala/chisel3/package.scala | 1 + src/main/scala/chisel3/util/BitPat.scala | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 0a57b7de..d0808980 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -152,6 +152,7 @@ package object chisel3 { // scalastyle:ignore package.object.name implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal { final def === (that: BitPat): Bool = macro SourceInfoTransform.thatArg + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") final def != (that: BitPat): Bool = macro SourceInfoTransform.thatArg final def =/= (that: BitPat): Bool = macro SourceInfoTransform.thatArg diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 972010a6..e58258c7 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -82,6 +82,7 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { def getWidth: Int = width def === (that: UInt): Bool = macro SourceInfoTransform.thatArg def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") def != (that: UInt): Bool = macro SourceInfoTransform.thatArg def do_=== (that: UInt)(implicit sourceInfo: SourceInfo): Bool = value.asUInt === (that & mask.asUInt) // scalastyle:ignore method.name -- cgit v1.2.3 From 5df30b390ae5817c4793c6d4e0c5466d96d241f1 Mon Sep 17 00:00:00 2001 From: jackkoenig Date: Wed, 19 Oct 2016 11:34:25 -0700 Subject: Change verilogToCpp to use O0 This causes Verilator tests to compile faster and use less memory --- src/main/scala/chisel3/Driver.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index dbd9b464..a0713379 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -119,13 +119,13 @@ trait BackendCompilationUtilities { "-Wno-WIDTH", "-Wno-STMTDLY", "--trace", - "-O2", + "-O0", "--top-module", topModule, "+define+TOP_TYPE=V" + dutFile, s"+define+PRINTF_COND=!$topModule.reset", s"+define+STOP_COND=!$topModule.reset", "-CFLAGS", - s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", + s"""-Wno-undefined-bool-conversion -O0 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", "-Mdir", dir.toString, "--exe", cppHarness.toString) System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex -- cgit v1.2.3