diff options
| author | Jack | 2022-07-30 22:41:15 +0000 |
|---|---|---|
| committer | Jack | 2022-07-30 22:41:15 +0000 |
| commit | 4cd44fa4dab370fcc5c20bcacc1fa0ee02327252 (patch) | |
| tree | 05730be260feca0d2a870c4bb88325d36631a8fc /docs | |
| parent | fe9635ef21bad233945617a24ab16cfa4055f2d1 (diff) | |
| parent | bced77045c8fc5db37e40b159c49220929e15d46 (diff) | |
Merge branch '3.5.x' into 3.5-release
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/src/appendix/experimental-features.md | 15 | ||||
| -rw-r--r-- | docs/src/cookbooks/cookbook.md | 40 | ||||
| -rw-r--r-- | docs/src/explanations/chisel-type-vs-scala-type.md | 285 | ||||
| -rw-r--r-- | docs/src/explanations/data-types.md | 3 | ||||
| -rw-r--r-- | docs/src/explanations/explanations.md | 1 | ||||
| -rw-r--r-- | docs/src/explanations/interfaces-and-connections.md | 2 | ||||
| -rw-r--r-- | docs/src/explanations/naming.md | 121 |
7 files changed, 456 insertions, 11 deletions
diff --git a/docs/src/appendix/experimental-features.md b/docs/src/appendix/experimental-features.md index 92226f8f..a85704c2 100644 --- a/docs/src/appendix/experimental-features.md +++ b/docs/src/appendix/experimental-features.md @@ -9,7 +9,8 @@ Chisel has a number of new features that are worth checking out. This page is a - [FixedPoint](#fixed-point) - [Module Variants](#module-variants) -- [Module Variants](#bundle-literals) +- [Bundle Literals](#bundle-literals) +- [Vec Literals](#vec-literals) - [Interval Type](#interval-type) - [Loading Memories for simulation or FPGA initialization](#loading-memories) @@ -52,7 +53,10 @@ class Example extends RawModule { chisel3.stage.ChiselStage.emitVerilog(new Example) ``` -Partial specification is allowed, defaulting any unconnected fields to 0 (regardless of type). +Partial specification is allowed, which results in "invalidated fields" as +described in [Unconnected Wires](../explanations/unconnected-wires). +Note that this can be used with `RegInit` to construct partially reset registers as +described in the [Cookbook](../cookbooks/cookbook#how-do-i-partially-reset-an-aggregate-reg). ```scala mdoc class Example2 extends RawModule { @@ -122,9 +126,10 @@ chisel3.stage.ChiselStage.emitVerilog(new VecExample1a) ``` The following examples all use the explicit form. -With the explicit form partial specification is allowed. -When used with as a `Reg` `reset` value, only specified indices of the `Reg`'s `Vec` -will be reset +With the explicit form partial specification is allowed, which results in +"invalidated fields" as described in [Unconnected Wires](../explanations/unconnected-wires). +Note that this can be used with `RegInit` to construct partially reset registers as +described in the [Cookbook](../cookbooks/cookbook#how-do-i-partially-reset-an-aggregate-reg). ```scala mdoc class VecExample2 extends RawModule { diff --git a/docs/src/cookbooks/cookbook.md b/docs/src/cookbooks/cookbook.md index b9e5db38..ab8e76d3 100644 --- a/docs/src/cookbooks/cookbook.md +++ b/docs/src/cookbooks/cookbook.md @@ -20,6 +20,7 @@ Please note that these examples make use of [Chisel's scala-style printing](../e * [Can I make a 2D or 3D Vector?](#can-i-make-a-2D-or-3D-Vector) * [How do I create a Vector of Registers?](#how-do-i-create-a-vector-of-registers) * [How do I create a Reg of type Vec?](#how-do-i-create-a-reg-of-type-vec) + * [How do I partially reset an Aggregate Reg?](#how-do-i-partially-reset-an-aggregate-reg) * Bundles * [How do I deal with aliased Bundle fields?](#aliased-bundle-fields) * [How do I create a finite state machine?](#how-do-i-create-a-finite-state-machine-fsm) @@ -234,6 +235,45 @@ class Foo extends RawModule { } ``` + +### How do I partially reset an Aggregate Reg? + +The easiest way is to use a partially-specified [Bundle Literal](#../appendix/experimental-features#bundle-literals) +or [Vec Literal](#../appendix/experimental-features#vec-literals) to match the type of the Reg. + +```scala mdoc:silent:reset +import chisel3._ +import chisel3.experimental.BundleLiterals._ + +class MyBundle extends Bundle { + val foo = UInt(8.W) + val bar = UInt(8.W) +} + +class MyModule extends Module { + // Only .foo will be reset, .bar will have no reset value + val reg = RegInit((new MyBundle).Lit(_.foo -> 123.U)) +} +``` + +If your initial value is not a literal, or if you just prefer, you can use a +Wire as the initial value for the Reg. Simply connect fields to `DontCare` that +you do not wish to be reset. + +```scala mdoc:silent +class MyModule2 extends Module { + val reg = RegInit({ + // The wire could be constructed before the reg rather than in the RegInit scope, + // but this style has nice lexical scoping behavior, keeping the Wire private + val init = Wire(new MyBundle) + init := DontCare // No fields will be reset + init.foo := 123.U // Last connect override, .foo is reset + init + }) +} +``` + + ## Bundles ### <a name="aliased-bundle-fields"></a> How do I deal with aliased Bundle fields? 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` |
