summaryrefslogtreecommitdiff
path: root/docs/src/explanations
diff options
context:
space:
mode:
authorJack2022-07-30 22:41:15 +0000
committerJack2022-07-30 22:41:15 +0000
commit4cd44fa4dab370fcc5c20bcacc1fa0ee02327252 (patch)
tree05730be260feca0d2a870c4bb88325d36631a8fc /docs/src/explanations
parentfe9635ef21bad233945617a24ab16cfa4055f2d1 (diff)
parentbced77045c8fc5db37e40b159c49220929e15d46 (diff)
Merge branch '3.5.x' into 3.5-release
Diffstat (limited to 'docs/src/explanations')
-rw-r--r--docs/src/explanations/chisel-type-vs-scala-type.md285
-rw-r--r--docs/src/explanations/data-types.md3
-rw-r--r--docs/src/explanations/explanations.md1
-rw-r--r--docs/src/explanations/interfaces-and-connections.md2
-rw-r--r--docs/src/explanations/naming.md121
5 files changed, 406 insertions, 6 deletions
diff --git a/docs/src/explanations/chisel-type-vs-scala-type.md b/docs/src/explanations/chisel-type-vs-scala-type.md
new file mode 100644
index 00000000..6c311a21
--- /dev/null
+++ b/docs/src/explanations/chisel-type-vs-scala-type.md
@@ -0,0 +1,285 @@
+---
+layout: docs
+title: "Chisel Type vs Scala Type"
+section: "chisel3"
+---
+
+# Chisel Type vs Scala Type
+
+The Scala compiler cannot distinguish between Chisel's representation of hardware such as `false.B`, `Reg(Bool())`
+and pure Chisel types (e.g. `Bool()`). You can get runtime errors passing a Chisel type when hardware is expected, and vice versa.
+
+## Scala Type vs Chisel Type vs Hardware
+
+```scala mdoc:invisible
+import chisel3._
+import chisel3.stage.ChiselStage
+```
+
+The *Scala* type of the Data is recognized by the Scala compiler, such as `Bool`, `Decoupled[UInt]` or `MyBundle` in
+```scala mdoc:silent
+class MyBundle(w: Int) extends Bundle {
+ val foo = UInt(w.W)
+ val bar = UInt(w.W)
+}
+```
+
+The *Chisel* type of a `Data` is a Scala object. It captures all the fields actually present,
+by names, and their types including widths.
+For example, `MyBundle(3)` creates a Chisel Type with fields `foo: UInt(3.W), bar: UInt(3.W))`.
+
+Hardware is `Data` that is "bound" to synthesizable hardware. For example `false.B` or `Reg(Bool())`.
+The binding is what determines the actual directionality of each field, it is not a property of the Chisel type.
+
+A literal is a `Data` that is respresentable as a literal value without being wrapped in Wire, Reg, or IO.
+
+## Chisel Type vs Hardware vs Literals
+
+The below code demonstrates how objects with the same Scala type (`MyBundle`) can have different properties.
+
+```scala mdoc:silent
+import chisel3.experimental.BundleLiterals._
+
+class MyModule(gen: () => MyBundle) extends Module {
+ // Hardware Literal
+ val xType: MyBundle = new MyBundle(3) // - -
+ val dirXType: MyBundle = Input(new MyBundle(3)) // - -
+ val xReg: MyBundle = Reg(new MyBundle(3)) // x -
+ val xIO: MyBundle = IO(Input(new MyBundle(3))) // x -
+ val xRegInit: MyBundle = RegInit(xIO) // x -
+ val xLit: MyBundle = xType.Lit( // x x
+ _.foo -> 0.U(3.W),
+ _.bar -> 0.U(3.W)
+ )
+ val y: MyBundle = gen() // ? ?
+
+ // Need to initialize all hardware values
+ xReg := DontCare
+}
+```
+
+```scala mdoc:invisible
+// Just here to compile check the above
+ChiselStage.elaborate(new MyModule(() => new MyBundle(3)))
+```
+
+## Chisel Type vs Hardware -- Specific Functions and Errors
+
+`.asTypeOf` works for both hardware and Chisel type:
+
+```scala mdoc:silent
+ChiselStage.elaborate(new Module {
+ val chiselType = new MyBundle(3)
+ val hardware = Wire(new MyBundle(3))
+ hardware := DontCare
+ val a = 0.U.asTypeOf(chiselType)
+ val b = 0.U.asTypeOf(hardware)
+})
+```
+
+Can only `:=` to hardware:
+```scala mdoc:silent
+// Do this...
+ChiselStage.elaborate(new Module {
+ val hardware = Wire(new MyBundle(3))
+ hardware := DontCare
+})
+```
+```scala mdoc:crash
+// Not this...
+ChiselStage.elaborate(new Module {
+ val chiselType = new MyBundle(3)
+ chiselType := DontCare
+})
+```
+
+Can only `:=` from hardware:
+```scala mdoc:silent
+// Do this...
+ChiselStage.elaborate(new Module {
+ val hardware = IO(new MyBundle(3))
+ val moarHardware = Wire(new MyBundle(3))
+ moarHardware := DontCare
+ hardware := moarHardware
+})
+```
+```scala mdoc:crash
+// Not this...
+ChiselStage.elaborate(new Module {
+ val hardware = IO(new MyBundle(3))
+ val chiselType = new MyBundle(3)
+ hardware := chiselType
+})
+```
+
+Have to pass hardware to `chiselTypeOf`:
+```scala mdoc:silent
+// Do this...
+ChiselStage.elaborate(new Module {
+ val hardware = Wire(new MyBundle(3))
+ hardware := DontCare
+ val chiselType = chiselTypeOf(hardware)
+})
+```
+```scala mdoc:crash
+// Not this...
+ChiselStage.elaborate(new Module {
+ val chiselType = new MyBundle(3)
+ val crash = chiselTypeOf(chiselType)
+})
+```
+
+Have to pass hardware to `*Init`:
+```scala mdoc:silent
+// Do this...
+ChiselStage.elaborate(new Module {
+ val hardware = Wire(new MyBundle(3))
+ hardware := DontCare
+ val moarHardware = WireInit(hardware)
+})
+```
+```scala mdoc:crash
+// Not this...
+ChiselStage.elaborate(new Module {
+ val crash = WireInit(new MyBundle(3))
+})
+```
+
+Can't pass hardware to a `Wire`, `Reg`, `IO`:
+```scala mdoc:silent
+// Do this...
+ChiselStage.elaborate(new Module {
+ val hardware = Wire(new MyBundle(3))
+ hardware := DontCare
+})
+```
+```scala mdoc:crash
+// Not this...
+ChiselStage.elaborate(new Module {
+ val hardware = Wire(new MyBundle(3))
+ val crash = Wire(hardware)
+})
+```
+
+`.Lit` can only be called on Chisel type:
+```scala mdoc:silent
+// Do this...
+ChiselStage.elaborate(new Module {
+ val hardwareLit = (new MyBundle(3)).Lit(
+ _.foo -> 0.U,
+ _.bar -> 0.U
+ )
+})
+```
+```scala mdoc:crash
+//Not this...
+ChiselStage.elaborate(new Module {
+ val hardware = Wire(new MyBundle(3))
+ val crash = hardware.Lit(
+ _.foo -> 0.U,
+ _.bar -> 0.U
+ )
+})
+```
+
+Can only use a Chisel type within a `Bundle` definition:
+```scala mdoc:silent
+// Do this...
+ChiselStage.elaborate(new Module {
+ val hardware = Wire(new Bundle {
+ val nested = new MyBundle(3)
+ })
+ hardware := DontCare
+})
+```
+```scala mdoc:crash
+// Not this...
+ChiselStage.elaborate(new Module {
+ val crash = Wire(new Bundle {
+ val nested = Wire(new MyBundle(3))
+ })
+})
+```
+
+Can only call `directionOf` on Hardware:
+```scala mdoc:silent
+import chisel3.experimental.DataMirror
+
+class Child extends Module{
+ val hardware = IO(new MyBundle(3))
+ hardware := DontCare
+ val chiselType = new MyBundle(3)
+}
+```
+```scala mdoc:silent
+// Do this...
+ChiselStage.elaborate(new Module {
+ val child = Module(new Child())
+ child.hardware := DontCare
+ val direction = DataMirror.directionOf(child.hardware)
+})
+```
+```scala mdoc:crash
+// Not this...
+ChiselStage.elaborate(new Module {
+val child = Module(new Child())
+ child.hardware := DontCare
+ val direction = DataMirror.directionOf(child.chiselType)
+})
+```
+
+Can call `specifiedDirectionOf` on hardware or Chisel type:
+```scala mdoc:silent
+ChiselStage.elaborate(new Module {
+ val child = Module(new Child())
+ child.hardware := DontCare
+ val direction0 = DataMirror.specifiedDirectionOf(child.hardware)
+ val direction1 = DataMirror.specifiedDirectionOf(child.chiselType)
+})
+```
+
+## `.asInstanceOf` vs `.asTypeOf` vs `chiselTypeOf`
+
+`.asInstanceOf` is a Scala runtime cast, usually used for telling the compiler
+that you have more information than it can infer to convert Scala types:
+
+```scala mdoc:silent
+class ScalaCastingModule(gen: () => Bundle) extends Module {
+ val io = gen().asInstanceOf[MyBundle]
+ io.foo := 0.U
+}
+```
+
+This works if we do indeed have more information than the compiler:
+``` scala mdoc:silent
+ChiselStage.elaborate(new ScalaCastingModule( () => new MyBundle(3)))
+```
+
+But if we are wrong, we can get a Scala runtime exception:
+```scala mdoc:crash
+class NotMyBundle extends Bundle {val baz = Bool()}
+ChiselStage.elaborate(new ScalaCastingModule(() => new NotMyBundle()))
+```
+
+`.asTypeOf` is a conversion from one `Data` subclass to another.
+It is commonly used to assign data to all-zeros, as described in [this cookbook recipe](https://www.chisel-lang.org/chisel3/docs/cookbooks/cookbook.html#how-can-i-tieoff-a-bundlevec-to-0), but it can
+also be used (though not really recommended, as there is no checking on
+width matches) to convert one Chisel type to another:
+
+```scala mdoc
+class SimilarToMyBundle(w: Int) extends Bundle{
+ val foobar = UInt((2*w).W)
+}
+
+ChiselStage.emitVerilog(new Module {
+ val in = IO(Input(new MyBundle(3)))
+ val out = IO(Output(new SimilarToMyBundle(3)))
+
+ out := in.asTypeOf(out)
+})
+```
+
+In contrast to `asInstanceOf` and `asTypeOf`,
+`chiselTypeOf` is not a casting operation. It returns a Scala object which
+can be used as shown in the examples above to create more Chisel types and
+hardware with the same Chisel type as existing hardware.
diff --git a/docs/src/explanations/data-types.md b/docs/src/explanations/data-types.md
index 6ac6077b..67b8e0b9 100644
--- a/docs/src/explanations/data-types.md
+++ b/docs/src/explanations/data-types.md
@@ -1,6 +1,6 @@
---
layout: docs
-title: "Data Types"
+title: "Chisel Data Types"
section: "chisel3"
---
@@ -134,3 +134,4 @@ a <> b
a <> b
a <> c
```
+
diff --git a/docs/src/explanations/explanations.md b/docs/src/explanations/explanations.md
index 9e0227d5..762648d0 100644
--- a/docs/src/explanations/explanations.md
+++ b/docs/src/explanations/explanations.md
@@ -39,3 +39,4 @@ read these documents in the following order:
* [Unconnected Wires](unconnected-wires)
* [Annotations](annotations)
* [Deep Dive into Connection Operators](connection-operators)
+* [Chisel Type vs Scala Type](chisel-type-vs-scala-type)
diff --git a/docs/src/explanations/interfaces-and-connections.md b/docs/src/explanations/interfaces-and-connections.md
index 0fb8bae8..5d9cfd3c 100644
--- a/docs/src/explanations/interfaces-and-connections.md
+++ b/docs/src/explanations/interfaces-and-connections.md
@@ -150,7 +150,7 @@ Below we can see the resulting error for this example:
```scala mdoc:crash
ChiselStage.emitVerilog(new BlockWithTemporaryWires)
```
-For more details and information, see [Deep Dive into Connection Operators](connection-operators.md)
+For more details and information, see [Deep Dive into Connection Operators](connection-operators)
NOTE: When using `Chisel._` (compatibility mode) instead of `chisel3._`, the `:=` operator works in a bidirectional fashion similar to `<>`, but not exactly the same.
diff --git a/docs/src/explanations/naming.md b/docs/src/explanations/naming.md
index a9f21936..99797cb2 100644
--- a/docs/src/explanations/naming.md
+++ b/docs/src/explanations/naming.md
@@ -24,11 +24,11 @@ import chisel3.experimental.{prefix, noPrefix}
import chisel3.stage.ChiselStage
```
-With the release of Chisel 3.4, users should add the following line to their build.sbt settings to get the improved
-naming:
+With the release of Chisel 3.5, users are required to add the following line to
+their build.sbt settings:
```scala
-// chiselVersion is the String version (eg. "3.4.0")
+// chiselVersion is the String version (eg. "3.5.3")
addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full)
```
@@ -78,6 +78,29 @@ class Example2 extends Module {
ChiselStage.emitVerilog(new Example2)
```
+Prefixing can also be derived from the name of signals on the left-hand side of a connection.
+While this is not implemented via the compiler plugin, the behavior should feel similar:
+
+```scala mdoc
+class ConnectPrefixing extends Module {
+ val in = IO(Input(UInt(2.W)))
+ // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W)))))
+
+ val out = IO(Output(UInt(2.W)))
+ // val out = autoNameRecursively("out")(prefix("out")(IO(Output(UInt(2.W)))))
+
+ out := { // technically this is not wrapped in autoNameRecursively nor prefix
+ // But the Chisel runtime will still use the name of `out` as a prefix
+ val double = in * in
+ // val double = autoNameRecursively("double")(prefix("double")(in * in))
+ double + 1.U
+ }
+}
+```
+```scala mdoc:verilog
+ChiselStage.emitVerilog(new ConnectPrefixing)
+```
+
Note that the naming also works if the hardware type is nested in an `Option` or a subtype of `Iterable`:
```scala mdoc
@@ -121,7 +144,7 @@ Users who desire a prefix are encouraged to provide one as [described below](#pr
### Prefixing
As shown above, the compiler plugin automatically attempts to prefix some of your signals for you. However, you as a
-user can also add your own prefixes. This is especially for ECO-type fixes where you need to add some logic to a module
+user can also add your own prefixes. This is especially useful for ECO-type fixes where you need to add some logic to a module
but don't want to influence other names in the module.
In the following example, we prefix additional logic with "ECO", where `Example4` is pre-ECO and `Example5` is post-ECO:
@@ -202,6 +225,96 @@ class Example8 extends Module {
ChiselStage.emitVerilog(new Example8)
```
+Note that using `.suggestName` does **not** affect prefixes derived from val names;
+however, it _can_ affect prefixes derived from connections (eg. `:=`):
+
+```scala mdoc
+class ConnectionPrefixExample extends Module {
+ val in0 = IO(Input(UInt(2.W)))
+ val in1 = IO(Input(UInt(2.W)))
+
+ val out0 = {
+ val port = IO(Output(UInt()))
+ // Even though this suggestName is before mul, the prefix used in this scope
+ // is derived from `val out0`, so this does not affect the name of mul
+ port.suggestName("foo")
+ // out0_mul
+ val mul = in0 * in1
+ port := mul + 1.U
+ port
+ }
+
+ val out1 = IO(Output(UInt()))
+ val out2 = IO(Output(UInt()))
+
+ out1 := {
+ // out1_sum
+ val sum = in0 + in1
+ sum + 1.U
+ }
+ // Comes after so does *not* affect prefix above
+ out1.suggestName("bar")
+
+ // Comes before so *does* affect prefix below
+ out2.suggestName("fizz")
+ out2 := {
+ // fizz_diff
+ val diff = in0 - in1
+ diff + 1.U
+ }
+}
+```
+```scala mdoc:verilog
+ChiselStage.emitVerilog(new ConnectionPrefixExample)
+```
+
+As this example illustrates, this behavior is slightly inconsistent so is subject to change in a future version of Chisel.
+
+
+### Behavior for "Unnamed signals" (aka "Temporaries")
+
+If you want to signify that the name of a signal does not matter, you can prefix the name of your val with `_`.
+Chisel will preserve the convention of leading `_` signifying an unnamed signal across prefixes.
+For example:
+
+```scala mdoc
+class TemporaryExample extends Module {
+ val in0 = IO(Input(UInt(2.W)))
+ val in1 = IO(Input(UInt(2.W)))
+
+ val out = {
+ val port = IO(Output(UInt()))
+ val _sum = in0 + in1
+ port := _sum + 1.U
+ port
+ }
+}
+```
+```scala mdoc:verilog
+ChiselStage.emitVerilog(new TemporaryExample)
+```
+
+If an unnamed signal is itself used to generate a prefix, the leading `_` will be ignored to avoid double `__` in the names of further nested signals.
+
+
+```scala mdoc
+class TemporaryPrefixExample extends Module {
+ val in0 = IO(Input(UInt(2.W)))
+ val in1 = IO(Input(UInt(2.W)))
+ val out = IO(Output(UInt()))
+
+ val _sum = {
+ val x = in0 + in1
+ x + 1.U
+ }
+ out := _sum & 0x2.U
+}
+```
+```scala mdoc:verilog
+ChiselStage.emitVerilog(new TemporaryPrefixExample)
+```
+
+
### Set a Module Name
If you want to specify the module's name (not the instance name of a module), you can always override the `desiredName`