diff options
| author | Adam Izraelevitz | 2020-09-14 10:17:49 -0700 |
|---|---|---|
| committer | GitHub | 2020-09-14 17:17:49 +0000 |
| commit | 69e27b2fd9e02d4e3a024eec0cafce5b4b46c10a (patch) | |
| tree | da496ac9fcc2ae6d02560edf9cf10d10e9b3964b /docs/src/explanations/naming.md | |
| parent | 3b5fda0c604b393833769250ade9f7d13ca4e5e7 (diff) | |
Documentation and minor plugin changes. (#1573)
* Added documentation. Bugfix in plugin. Moved plugin APIs to separate package
* Revert reg naming behavior (omit underscore)
* Added documentation and a test
* Addressed reviewer feedback.
Diffstat (limited to 'docs/src/explanations/naming.md')
| -rw-r--r-- | docs/src/explanations/naming.md | 229 |
1 files changed, 229 insertions, 0 deletions
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 |
