summaryrefslogtreecommitdiff
path: root/docs/src/explanations/bundles-and-vecs.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/src/explanations/bundles-and-vecs.md')
-rw-r--r--docs/src/explanations/bundles-and-vecs.md215
1 files changed, 215 insertions, 0 deletions
diff --git a/docs/src/explanations/bundles-and-vecs.md b/docs/src/explanations/bundles-and-vecs.md
new file mode 100644
index 00000000..4b1eb196
--- /dev/null
+++ b/docs/src/explanations/bundles-and-vecs.md
@@ -0,0 +1,215 @@
+---
+layout: docs
+title: "Bundles and Vecs"
+section: "chisel3"
+---
+```
+
+```
+
+`Bundle` and `Vec` are classes that allow the user to expand the set of Chisel datatypes with aggregates of other types.
+
+Bundles group together several named fields of potentially different types into a coherent unit, much like a `struct` in
+C. Users define their own bundles by defining a class as a subclass of `Bundle`.
+```scala mdoc:silent
+import chisel3._
+class MyFloat extends Bundle {
+ val sign = Bool()
+ val exponent = UInt(8.W)
+ val significand = UInt(23.W)
+}
+
+class ModuleWithFloatWire extends RawModule {
+ val x = Wire(new MyFloat)
+ val xs = x.sign
+}
+```
+
+> Currently, there is no way to create a bundle literal like ```8.U``` for ```UInt```s. Therefore, in order to create
+>literals for bundles, we must declare a [[wire|Combinational-Circuits#wires]] of that bundle type, and then assign
+>values to it. We are working on a way to declare bundle literals without requiring the creation of a Wire node and
+>assigning to it.
+
+```scala mdoc:silent
+class ModuleWithFloatConstant extends RawModule {
+ // Floating point constant.
+ val floatConst = Wire(new MyFloat)
+ floatConst.sign := true.B
+ floatConst.exponent := 10.U
+ floatConst.significand := 128.U
+}
+```
+
+A Scala convention is to capitalize the name of new classes and we suggest you follow that convention in Chisel too.
+
+Vecs create an indexable vector of elements, and are constructed as follows:
+```scala mdoc:silent
+class ModuleWithVec extends RawModule {
+ // Vector of 5 23-bit signed integers.
+ val myVec = Wire(Vec(5, SInt(23.W)))
+
+ // Connect to one element of vector.
+ val reg3 = myVec(3)
+}
+```
+
+(Note that we specify the number followed by the type of the `Vec` elements. We also specifiy the width of the `SInt`)
+
+The set of primitive classes
+(`SInt`, `UInt`, and `Bool`) plus the aggregate
+classes (`Bundles` and `Vec`s) all inherit from a common
+superclass, `Data`. Every object that ultimately inherits from
+`Data` can be represented as a bit vector in a hardware design.
+
+Bundles and Vecs can be arbitrarily nested to build complex data
+structures:
+```scala mdoc:silent
+class BigBundle extends Bundle {
+ // Vector of 5 23-bit signed integers.
+ val myVec = Vec(5, SInt(23.W))
+ val flag = Bool()
+ // Previously defined bundle.
+ val f = new MyFloat
+}
+```
+
+Note that the builtin Chisel primitive and aggregate classes do not
+require the `new` when creating an instance, whereas new user
+datatypes will. A Scala `apply` constructor can be defined so
+that a user datatype also does not require `new`, as described in
+[Function Constructor](../wiki-deprecated/functional-module-creation.md).
+
+### Flipping Bundles
+
+The `Flipped()` function recursively flips all elements in a Bundle/Record. This is very useful for building bidirectional interfaces that connect to each other (e.g. `Decoupled`). See below for an example.
+
+```scala mdoc:silent
+class ABBundle extends Bundle {
+ val a = Input(Bool())
+ val b = Output(Bool())
+}
+class MyFlippedModule extends RawModule {
+ // Normal instantiation of the bundle
+ // 'a' is an Input and 'b' is an Output
+ val normalBundle = IO(new ABBundle)
+ normalBundle.b := normalBundle.a
+
+ // Flipped recursively flips the direction of all Bundle fields
+ // Now 'a' is an Output and 'b' is an Input
+ val flippedBundle = IO(Flipped(new ABBundle))
+ flippedBundle.a := flippedBundle.b
+}
+```
+
+This generates the following Verilog:
+
+```scala mdoc
+import chisel3.stage.ChiselStage
+
+println(ChiselStage.emitVerilog(new MyFlippedModule()))
+```
+
+### MixedVec
+
+(Chisel 3.2+)
+
+All elements of a `Vec` must be of the same type. If we want to create a Vec where the elements have different types, we
+can use a MixedVec:
+
+```scala mdoc:silent
+import chisel3.util.MixedVec
+class ModuleMixedVec extends Module {
+ val io = IO(new Bundle {
+ val x = Input(UInt(3.W))
+ val y = Input(UInt(10.W))
+ val vec = Output(MixedVec(UInt(3.W), UInt(10.W)))
+ })
+ io.vec(0) := io.x
+ io.vec(1) := io.y
+}
+```
+
+We can also programmatically create the types in a MixedVec:
+
+```scala mdoc:silent
+class ModuleProgrammaticMixedVec(x: Int, y: Int) extends Module {
+ val io = IO(new Bundle {
+ val vec = Input(MixedVec((x to y) map { i => UInt(i.W) }))
+ // ...
+ })
+ // ...rest of the module goes here...
+}
+```
+
+### A note on `cloneType`
+
+Since Chisel is built on top of Scala and the JVM, it needs to know how to construct copies of bundles for various
+purposes (creating wires, IOs, etc). If you have a parametrized bundle and Chisel can't automatically figure out how to
+clone your bundle, you will need to create a custom `cloneType` method in your bundle. Most of the time, this is as
+simple as `override def cloneType = (new YourBundleHere(...)).asInstanceOf[this.type]`.
+
+Note that in the vast majority of cases, **this is not required** as Chisel can figure out how to clone most bundles
+automatically.
+
+Here is an example of a parametrized bundle (`ExampleBundle`) that features a custom `cloneType`.
+```scala mdoc:silent
+class ExampleBundle(a: Int, b: Int) extends Bundle {
+ val foo = UInt(a.W)
+ val bar = UInt(b.W)
+ override def cloneType = (new ExampleBundle(a, b)).asInstanceOf[this.type]
+}
+
+class ExampleBundleModule(btype: ExampleBundle) extends Module {
+ val io = IO(new Bundle {
+ val out = Output(UInt(32.W))
+ val b = Input(chiselTypeOf(btype))
+ })
+ io.out := io.b.foo + io.b.bar
+}
+
+class Top extends Module {
+ val io = IO(new Bundle {
+ val out = Output(UInt(32.W))
+ val in = Input(UInt(17.W))
+ })
+ val x = Wire(new ExampleBundle(31, 17))
+ x := DontCare
+ val m = Module(new ExampleBundleModule(x))
+ m.io.b.foo := io.in
+ m.io.b.bar := io.in
+ io.out := m.io.out
+}
+```
+
+Generally cloneType can be automatically defined if all arguments to the Bundle are vals e.g.
+
+```scala mdoc:silent
+class MyCloneTypeBundle(val bitwidth: Int) extends Bundle {
+ val field = UInt(bitwidth.W)
+ // ...
+}
+```
+
+The only caveat is if you are passing something of type Data as a "generator" parameter, in which case you should make
+it a `private val`.
+
+For example, consider the following Bundle. Because its `gen` variable is not a `private val`, the user has to
+explicitly define the `cloneType` method.
+
+```scala mdoc:silent
+import chisel3.util.{Decoupled, Irrevocable}
+class RegisterWriteIOExplicitCloneType[T <: Data](gen: T) extends Bundle {
+ val request = Flipped(Decoupled(gen))
+ val response = Irrevocable(Bool())
+ override def cloneType = new RegisterWriteIOExplicitCloneType(gen).asInstanceOf[this.type]
+}
+```
+
+We can make this this infer cloneType by making `gen` private since it is a "type parameter":
+
+```scala mdoc:silent
+class RegisterWriteIO[T <: Data](private val gen: T) extends Bundle {
+ val request = Flipped(Decoupled(gen))
+ val response = Irrevocable(Bool())
+}
+```