summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSchuyler Eldridge2019-02-19 19:46:07 -0500
committerGitHub2019-02-19 19:46:07 -0500
commite8b2aa9972b98fd15061bb2af5391e1c05b619fc (patch)
tree3c1e23ac9b3f43e287cdfa1f89150250ef5dfac1 /src
parent4c512593fb5688f3de502ba1ed70681a0802b6c9 (diff)
parentba8311a7c1d8bb43065478638acbaa5999a3fdab (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.scala58
-rw-r--r--src/test/scala/chiselTests/TransitNameSpec.scala55
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
+ }
+ }
+
+}