diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/src/cookbooks/naming.md | 62 | ||||
| -rw-r--r-- | docs/src/explanations/naming.md | 229 |
2 files changed, 291 insertions, 0 deletions
diff --git a/docs/src/cookbooks/naming.md b/docs/src/cookbooks/naming.md new file mode 100644 index 00000000..5f57826f --- /dev/null +++ b/docs/src/cookbooks/naming.md @@ -0,0 +1,62 @@ +--- +layout: docs +title: "Naming Cookbook" +section: "chisel3" +--- + +```scala mdoc:invisible +import chisel3.internal.plugin._ +import chisel3._ +import chisel3.experimental.prefix +import chisel3.experimental.noPrefix +import chisel3.stage.ChiselStage +``` + +### I still have _T signals, can this be fixed? + +First check - is the compiler plugin properly enabled? Scalac plugins are enabled via the scalac option +`-Xplugin:<path/to/jar>`. You can check which compiler plugins are enabled by running `show Compile / scalacOptions` in +the sbt prompt. + +If the plugin is enabled, these signals could be intermediate values which are consumed by either assertions or when +predicates. In these cases, the compiler plugin often can't find a good prefix for the generated intermediate signals. +We recommend you manually insert calls to `prefix` to fix these cases. We did this to Rocket Chip and saw huge benefits! + +### I still see _GEN signals, can this be fixed? + +`_GEN` signals are usually generated from the FIRRTL compiler, rather than the Chisel library. We are working on +renaming these signals with more context-dependent names, but it is a work in progress. Thanks for caring! + +### My module names are super unstable - I change one thing and Queue_1 becomes Queue_42. Help! + +This is the infamous `Queue` instability problem. In general, these cases are best solved at the source - the module +itself! If you overwrite `desiredName` to include parameter information (see the +[explanation](../explanations/naming.md#set-a-module-name) for more info), then this can avoid this problem permanantly. +We've done this with some Chisel utilities with great results! + +### I want to add some hardware or assertions, but each time I do all the signal names get bumped! + +This is the classic "ECO" problem, and we provide descriptions in [explanation](../explanations/naming.md). In short, +we recommend wrapping all additional logic in a prefix scope, which enables a unique namespace. This should prevent +name collisions, which are what triggers all those annoying signal name bumps! + +### I want to force a signal (or instance) name to something, how do I do that? + +Use the `.suggestName` method, which is on all classes which subtype 'Data'. + +### All this prefixing is annoying, how do I fix it? + +You can use the `noPrefix { ... }` to strip the prefix from all signals generated in that scope. + +```scala mdoc +class ExampleNoPrefix extends MultiIOModule { + val in = IO(Input(UInt(2.W))) + val out = IO(Output(UInt())) + + val add = noPrefix { in + in + in } + + out := add +} + +println(ChiselStage.emitVerilog(new Example7)) +``` diff --git a/docs/src/explanations/naming.md b/docs/src/explanations/naming.md new file mode 100644 index 00000000..69870813 --- /dev/null +++ b/docs/src/explanations/naming.md @@ -0,0 +1,229 @@ +--- +layout: docs +title: "Naming" +section: "chisel3" +--- + +Historically, Chisel has had trouble reliably capturing the names of signals. The reasons for this are due to (1) +primarily relying on reflection to find names, (2) using `@chiselName` macro which had unreliable behavior. + +Chisel 3.4 introduced a custom Scala compiler plugin which enables reliabe and automatic capturing of signal names, when +they are declared. In addition, this release includes prolific use of a new prefixing API which enables more stable +naming of signals programmatically generated from function calls. + +This document explains how naming now works in Chisel for signal and module names. For cookbook examples on how to fix +systemic name-stability issues, please refer to the naming [cookbook](../cookbooks/naming.md). + +### Compiler Plugin + +```scala mdoc +import chisel3.internal.plugin._ +import chisel3._ +import chisel3.experimental.prefix +import chisel3.experimental.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: + +```scala +addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full) +``` + +This plugin will run after the 'typer' phase of the Scala compiler. It looks for any user code which is of the form +`val x = y`, where `x` is of type `chisel3.Data`, `chisel3.MemBase`, or `chisel3.experimental.BaseModule`. For each +line which fits this criteria, it rewrites that line. In the following examples, the commented line is the what the +line above is rewritten to. + +If the line is within a bundle declaration or is a module instantiation, it is rewritten to replace the right hand +side with a call to `autoNameRecursively`, which names the signal/module. + +```scala mdoc +class MyBundle extends Bundle { + val foo = Input(UInt(3.W)) + // val foo = autoNameRecursively("foo", Input(UInt(3.W))) +} +class Example1 extends MultiIOModule { + val io = IO(new MyBundle()) + // val io = autoNameRecursively("io", IO(new MyBundle())) +} +println(ChiselStage.emitVerilog(new Example1)) +``` + +Otherwise, it is rewritten to also include the name as a prefix to any signals generated while executing the right-hand- +side of the val declaration: + +```scala mdoc +class Example2 extends MultiIOModule { + 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))))) + + def inXin() = in * in + + val add = 3.U + inXin() + // val add = autoNameRecursively("add", prefix("add")(3.U + inXin())) + // Note that the intermediate result of the multiplication is prefixed with `add` + + out := add + 1.U +} + +println(ChiselStage.emitVerilog(new Example2)) +``` + +Note that the naming also works if the hardware type is nested in an `Option` or a subtype of `Iterable`: + +```scala mdoc +class Example3 extends MultiIOModule { + val in = IO(Input(UInt(2.W))) + // val in = autoNameRecursively("in", prefix("in")(IO(Input(UInt(2.W))))) + + val out = IO(Output(UInt())) + // val out = autoNameRecursively("out", prefix("out")(IO(Output(UInt(2.W))))) + + def inXin() = in * in + + val opt = Some(3.U + inXin()) + // Note that the intermediate result of the inXin() is prefixed with `opt`: + // val opt = autoNameRecursively("opt", prefix("opt")(Some(3.U + inXin()))) + + out := opt.get + 1.U +} + +println(ChiselStage.emitVerilog(new Example3)) +``` + +### 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 +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: + +```scala mdoc +class Example4 extends MultiIOModule { + val in = IO(Input(UInt(2.W))) + val out = IO(Output(UInt())) + + val add = in + in + in + + out := add + 1.U +} + +class Example5 extends MultiIOModule { + val in = IO(Input(UInt(2.W))) + val out = IO(Output(UInt())) + + val add = in + in + in + + out := prefix("ECO") { add + 1.U + in } +} + +println(ChiselStage.emitVerilog(new Example4)) +println(ChiselStage.emitVerilog(new Example5)) + +``` + +Also note that the prefixes append to each other (including the prefix generated by the compiler plugin): + +```scala mdoc +class Example6 extends MultiIOModule { + val in = IO(Input(UInt(2.W))) + val out = IO(Output(UInt())) + + val add = prefix("foo") { in + in + in } + + out := add +} + +println(ChiselStage.emitVerilog(new Example6)) +``` + +Sometimes you may want to disable the prefixing. This might occur if you are writing a library function and +don't want the prefixing behavior. In this case, you can use the `noPrefix` object: + +```scala mdoc +class Example7 extends MultiIOModule { + val in = IO(Input(UInt(2.W))) + val out = IO(Output(UInt())) + + val add = noPrefix { in + in + in } + + out := add +} + +println(ChiselStage.emitVerilog(new Example7)) +``` + +### Suggest a Signal's Name (or the instance name of a Module) + +If you want to specify the name of a signal, you can always use the `.suggestName` API. Please note that the suggested +name will still be prefixed (including by the plugin). You can always use the `noPrefix` object to strip this. + +```scala mdoc +class Example8 extends MultiIOModule { + val in = IO(Input(UInt(2.W))) + val out = IO(Output(UInt())) + + val add = (in + (in + in).suggestName("foo")) + + out := add +} + +println(ChiselStage.emitVerilog(new Example8)) +``` + +### 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` +value. Note that you can parameterize the name by the module's parameters. This is an excellent way to make your module +names more stable and is highly recommended to do. + +```scala mdoc +class Example9(width: Int) extends MultiIOModule { + override val desiredName = s"EXAMPLE9WITHWIDTH$width" + val in = IO(Input(UInt(width.W))) + val out = IO(Output(UInt())) + + val add = (in + (in + in).suggestName("foo")) + + out := add +} + +println(ChiselStage.emitVerilog(new Example9(8))) +println(ChiselStage.emitVerilog(new Example9(1))) +``` + +### Reflection Naming + +Regardless of whether the compiler plugin is enabled or not, after Chisel constructs a module, it attempts to name all +members of the Module. This will name all vals which are fields of the module class, but it will not name any +vals in nested functions or scopes. + +If the plugin successfully names a signal, the reflection naming will do nothing. We plan to deprecate all reflection +naming in a future Chisel release, but are leaving it to allow the plugin naming to be optional (but recommended). + +For example, the signals in the following module are in a nested scope; the plugin successfully names them, but +reflection naming cannot: + +```scala mdoc +class Example10 extends MultiIOModule { + { + val in = IO(Input(UInt(width.W))) + val out = IO(Output(UInt())) + + val add = in + in + + out := add + } +} +``` + +### @chiselName + +This macro is no longer recommended as its functionality is entirely replaced by the compiler plugin. Feel free to +delete from your Chisel designs!
\ No newline at end of file |
