diff options
| author | Schuyler Eldridge | 2019-02-19 19:46:07 -0500 |
|---|---|---|
| committer | GitHub | 2019-02-19 19:46:07 -0500 |
| commit | e8b2aa9972b98fd15061bb2af5391e1c05b619fc (patch) | |
| tree | 3c1e23ac9b3f43e287cdfa1f89150250ef5dfac1 /src | |
| parent | 4c512593fb5688f3de502ba1ed70681a0802b6c9 (diff) | |
| parent | ba8311a7c1d8bb43065478638acbaa5999a3fdab (diff) | |
Merge pull request #1017 from freechipsproject/scaladoc-TransitName
- Add Scaladoc for chisel3.util.TransitName
- Add test for TransitName
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/chisel3/util/TransitName.scala | 58 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/TransitNameSpec.scala | 55 |
2 files changed, 102 insertions, 11 deletions
diff --git a/src/main/scala/chisel3/util/TransitName.scala b/src/main/scala/chisel3/util/TransitName.scala index a3220a13..3b9a3869 100644 --- a/src/main/scala/chisel3/util/TransitName.scala +++ b/src/main/scala/chisel3/util/TransitName.scala @@ -2,25 +2,61 @@ package chisel3.util -import chisel3._ -import internal.HasId +import chisel3.internal.HasId -/** - * The purpose of TransitName is to allow a library to 'move' a name - * call to a more appropriate place. - * For example, a library factory function may create a module and return - * the io. The only user-exposed field is that given IO, which can't use - * any name supplied by the user. This can add a hook so that the supplied - * name then names the Module. - * See Queue companion object for working example - */ +/** The purpose of `TransitName` is to improve the naming of some object created in a different scope by "transiting" + * the name from the outer scope to the inner scope. + * + * Consider the example below. This shows three ways of instantiating `MyModule` and returning the IO. Normally, the + * instance will be named `MyModule`. However, it would be better if the instance was named using the name of the `val` + * that user provides for the returned IO. `TransitName` can then be used to "transit" the name ''from'' the IO ''to'' + * the module: + * + * {{{ + * /* Assign the IO of a new MyModule instance to value "foo". The instance will be named "MyModule". */ + * val foo = Module(new MyModule).io + * + * /* Assign the IO of a new MyModule instance to value "bar". The instance will be named "bar". */ + * val bar = { + * val x = Module(new MyModule) + * TransitName(x.io, x) // TransitName returns the first argument + * } + * + * /* Assign the IO of a new MyModule instance to value "baz". The instance will be named "baz_generated". */ + * val baz = { + * val x = Module(new MyModule) + * TransitName.withSuffix("_generated")(x.io, x) // TransitName returns the first argument + * } + * }}} + * + * `TransitName` helps library writers following the [[https://en.wikipedia.org/wiki/Factory_method_pattern Factory + * Method Pattern]] where modules may be instantiated inside an enclosing scope. For an example of this, see how the + * [[Queue$ Queue]] factory uses `TransitName` in + * [[https://github.com/freechipsproject/chisel3/blob/master/src/main/scala/chisel3/util/Decoupled.scala + * Decoupled.scala]] factory. + */ object TransitName { + + /** Transit a name from one type to another + * @param from the thing with a "good" name + * @param to the thing that will receive the "good" name + * @return the `from` parameter + */ def apply[T<:HasId](from: T, to: HasId): T = { from.addPostnameHook((given_name: String) => {to.suggestName(given_name)}) from } + + + /** Transit a name from one type to another ''and add a suffix'' + * @param suffix the suffix to append + * @param from the thing with a "good" name + * @param to the thing that will receive the "good" name + * @return the `from` parameter + */ def withSuffix[T<:HasId](suffix: String)(from: T, to: HasId): T = { from.addPostnameHook((given_name: String) => {to.suggestName(given_name + suffix)}) from } + } diff --git a/src/test/scala/chiselTests/TransitNameSpec.scala b/src/test/scala/chiselTests/TransitNameSpec.scala new file mode 100644 index 00000000..857d6470 --- /dev/null +++ b/src/test/scala/chiselTests/TransitNameSpec.scala @@ -0,0 +1,55 @@ +// See LICENSE for license details. +package chiselTests + +import org.scalatest.{FlatSpec, Matchers} + +import chisel3._ +import chisel3.experimental.RawModule +import chisel3.util.TransitName + +import firrtl.FirrtlExecutionSuccess + +class TransitNameSpec extends FlatSpec with Matchers { + + class MyModule extends RawModule { + val io = IO(new Bundle{}) + override val desiredName: String = "MyModule" + } + + /** A top-level module that instantiates three copies of MyModule */ + class Top extends RawModule { + + /* Assign the IO of a new MyModule instance to value "foo". The instance will be named "MyModule". */ + val foo = Module(new MyModule).io + + /* Assign the IO of a new MyModule instance to value "bar". The instance will be named "bar". */ + val bar = { + val x = Module(new MyModule) + TransitName(x.io, x) // TransitName returns the first argument + } + + /* Assign the IO of a new MyModule instance to value "baz". The instance will be named "baz_generated". */ + val baz = { + val x = Module(new MyModule) + TransitName.withSuffix("_generated")(x.io, x) // TransitName returns the first argument + } + + } + + it should "transit a name" in { + + Driver.execute(Array("-X", "high", "--target-dir", "test_run_dir/TransitNameSpec"), () => new Top) match { + case ChiselExecutionSuccess(_,_,Some(FirrtlExecutionSuccess(_,a))) => + info("""output FIRRTL includes "inst MyModule"""") + a should include ("inst MyModule of MyModule") + + info("""output FIRRTL includes "inst bar"""") + a should include ("inst bar of MyModule") + + info("""output FIRRTL includes "inst baz_generated"""") + a should include ("inst baz_generated of MyModule") + case _ => fail + } + } + +} |
