summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Lawson2016-10-24 10:31:26 -0700
committerJim Lawson2016-10-24 10:31:26 -0700
commitb0b5fd3140186651eb558bd6f4ca51c618deacc9 (patch)
tree1393bbb14303af86aeb5e5ed0375f302864b8307 /src
parent82625071405672eb4a19363d6f73f359ac28a7f5 (diff)
parent5df30b390ae5817c4793c6d4e0c5466d96d241f1 (diff)
Merge branch 'master' into tobits-deprecation
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/chisel3/ChiselExecutionOptions.scala34
-rw-r--r--src/main/scala/chisel3/Driver.scala161
-rw-r--r--src/main/scala/chisel3/compatibility.scala19
-rw-r--r--src/main/scala/chisel3/internal/firrtl/Emitter.scala6
-rw-r--r--src/main/scala/chisel3/package.scala23
-rw-r--r--src/main/scala/chisel3/testers/TesterDriver.scala35
-rw-r--r--src/main/scala/chisel3/util/BitPat.scala1
-rw-r--r--src/test/scala/chiselTests/ComplexAssign.scala2
-rw-r--r--src/test/scala/chiselTests/DriverSpec.scala33
-rw-r--r--src/test/scala/chiselTests/IOCompatibility.scala16
-rw-r--r--src/test/scala/chiselTests/MultiAssign.scala5
-rw-r--r--src/test/scala/chiselTests/Reg.scala1
-rw-r--r--src/test/scala/cookbook/Bundle2UInt.scala31
-rw-r--r--src/test/scala/cookbook/CookbookSpec.scala25
-rw-r--r--src/test/scala/cookbook/UInt2Bundle.scala30
-rw-r--r--src/test/scala/cookbook/UInt2VecOfBool.scala29
-rw-r--r--src/test/scala/cookbook/VecOfBool2UInt.scala28
17 files changed, 415 insertions, 64 deletions
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 5e0a3a0f..a0713379 100644
--- a/src/main/scala/chisel3/Driver.scala
+++ b/src/main/scala/chisel3/Driver.scala
@@ -2,11 +2,37 @@
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 {
/** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6.
@@ -31,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",
@@ -67,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
@@ -86,14 +138,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 = {
@@ -101,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
@@ -108,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))
@@ -132,4 +211,72 @@ 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/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/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
index f1908089..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
}
}
@@ -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"circuit ${circuit.name} : ")
+ private val res = new StringBuilder()
+ res ++= s";${Driver.chiselVersionString}\n"
+ res ++= s"circuit ${circuit.name} : "
withIndent { circuit.components.foreach(c => res ++= emit(c)) }
res ++= newline
}
diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala
index 17ddd55a..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
@@ -166,28 +167,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
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/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
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 {
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/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)
+ }
+ }
}
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()
}
}
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
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 }
+ }
+}