From 0a9256130714100c08cd0fbf7d74cbde44716424 Mon Sep 17 00:00:00 2001 From: azidar Date: Tue, 24 Oct 2023 22:12:20 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20=20@=20de74d?= =?UTF-8?q?754f63e713e00207588d1c4daa64258b77a=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chisel3/docs/cookbooks/cookbook.html | 2 +- chisel3/docs/cookbooks/hierarchy.html | 2 +- chisel3/docs/explanations/chisel-type-vs-scala-type.html | 2 +- js/search.js | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/chisel3/docs/cookbooks/cookbook.html b/chisel3/docs/cookbooks/cookbook.html index aeb14785a2d..ff46a5e3355 100644 --- a/chisel3/docs/cookbooks/cookbook.html +++ b/chisel3/docs/cookbooks/cookbook.html @@ -984,7 +984,7 @@

How
ChiselStage.emitSystemVerilog(new BadRegConnect)
-// circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: firtool returned a non-zero exit code. Note that this version of Chisel (0.0.0+1-8b7b7a23-SNAPSHOT) was published against firtool version 1.57.1.
+// circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: firtool returned a non-zero exit code. Note that this version of Chisel (0.0.0+1-de74d754-SNAPSHOT) was published against firtool version 1.57.1.
 // ------------------------------------------------------------------------------
 // ExitCode:
 // 1
diff --git a/chisel3/docs/cookbooks/hierarchy.html b/chisel3/docs/cookbooks/hierarchy.html
index fae77821694..a1c1fc51e35 100644
--- a/chisel3/docs/cookbooks/hierarchy.html
+++ b/chisel3/docs/cookbooks/hierarchy.html
@@ -219,7 +219,7 @@ 

How do I make m }

Width is 10
-Circuit(Top,List(DefModule(repl.MdocSession$MdocApp5$MyModule@12261bf,MyModule,List(Port(MyModule.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(MyModule.reset: IO[Reset],Input,UnlocatableSourceInfo)),Vector()), DefModule(repl.MdocSession$MdocApp5$Top@181c5fa1,Top,List(Port(Top.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(Top.reset: IO[Bool],Input,UnlocatableSourceInfo)),Vector(DefInstance(SourceLine(hierarchy.md,112,22),ModuleClone(repl.MdocSession$MdocApp5$MyModule@12261bf),List(Port(MyModule.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(MyModule.reset: IO[Reset],Input,UnlocatableSourceInfo))), Connect(SourceLine(hierarchy.md,112,22),Node(MyModule.inst.clock: IO[Clock]),Node(Top.clock: IO[Clock])), Connect(SourceLine(hierarchy.md,112,22),Node(MyModule.inst.reset: IO[Reset]),Node(Top.reset: IO[Bool]))))),List(),firrtl.renamemap.package$MutableRenameMap@6ac5c699,List(),List(),List())
+Circuit(Top,List(DefModule(repl.MdocSession$MdocApp5$MyModule@21c3264,MyModule,List(Port(MyModule.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(MyModule.reset: IO[Reset],Input,UnlocatableSourceInfo)),Vector()), DefModule(repl.MdocSession$MdocApp5$Top@79562b81,Top,List(Port(Top.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(Top.reset: IO[Bool],Input,UnlocatableSourceInfo)),Vector(DefInstance(SourceLine(hierarchy.md,112,22),ModuleClone(repl.MdocSession$MdocApp5$MyModule@21c3264),List(Port(MyModule.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(MyModule.reset: IO[Reset],Input,UnlocatableSourceInfo))), Connect(SourceLine(hierarchy.md,112,22),Node(MyModule.inst.clock: IO[Clock]),Node(Top.clock: IO[Clock])), Connect(SourceLine(hierarchy.md,112,22),Node(MyModule.inst.reset: IO[Reset]),Node(Top.reset: IO[Bool]))))),List(),firrtl.renamemap.package$MutableRenameMap@3ff9aa93,List(),List(),List())
 

How do I look up parameters from a Definition, if I don’t want to instantiate it?

diff --git a/chisel3/docs/explanations/chisel-type-vs-scala-type.html b/chisel3/docs/explanations/chisel-type-vs-scala-type.html index e36a300eba9..cd906b47169 100644 --- a/chisel3/docs/explanations/chisel-type-vs-scala-type.html +++ b/chisel3/docs/explanations/chisel-type-vs-scala-type.html @@ -316,7 +316,7 @@

class NotMyBundle extends Bundle {val baz = Bool()}
 elaborate(new ScalaCastingModule(() => new NotMyBundle()))
-// java.lang.ClassCastException: class repl.MdocSession$MdocApp$$anonfun$79$NotMyBundle$1 cannot be cast to class repl.MdocSession$MdocApp$MyBundle (repl.MdocSession$MdocApp$$anonfun$79$NotMyBundle$1 and repl.MdocSession$MdocApp$MyBundle are in unnamed module of loader scala.reflect.internal.util.AbstractFileClassLoader @2e3317de)
+// java.lang.ClassCastException: class repl.MdocSession$MdocApp$$anonfun$79$NotMyBundle$1 cannot be cast to class repl.MdocSession$MdocApp$MyBundle (repl.MdocSession$MdocApp$$anonfun$79$NotMyBundle$1 and repl.MdocSession$MdocApp$MyBundle are in unnamed module of loader scala.reflect.internal.util.AbstractFileClassLoader @40eefb7b)
 // 	at ... ()
 // 	at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293)
 // 	at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293)
diff --git a/js/search.js b/js/search.js
index 35370e1a31f..3537e18bf79 100644
--- a/js/search.js
+++ b/js/search.js
@@ -55,7 +55,7 @@ function prepareIdxAndDocMap() {
     {
       "title": "Chisel Type vs Scala Type",
       "url": "/chisel3/docs/explanations/chisel-type-vs-scala-type.html",
-      "content": "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 The Scala type of the Data is recognized by the Scala compiler, such as Bool, Decoupled[UInt] or MyBundle in 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. 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 } Chisel Type vs Hardware – Specific Functions and Errors .asTypeOf works for both hardware and Chisel type: 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: // Do this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) hardware := DontCare }) // Not this... elaborate(new Module { val chiselType = new MyBundle(3) chiselType := DontCare }) // chisel3.package$ExpectedHardwareException: data to be connected 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21$$anon$3.<init>(chisel-type-vs-scala-type.md:90) // at repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21.apply(chisel-type-vs-scala-type.md:88) // at repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21.apply(chisel-type-vs-scala-type.md:88) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can only := from hardware: // Do this... elaborate(new Module { val hardware = IO(new MyBundle(3)) val moarHardware = Wire(new MyBundle(3)) moarHardware := DontCare hardware := moarHardware }) // Not this... elaborate(new Module { val hardware = IO(new MyBundle(3)) val chiselType = new MyBundle(3) hardware := chiselType }) // chisel3.package$ExpectedHardwareException: data to be connected 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27$$anon$5.<init>(chisel-type-vs-scala-type.md:115) // at repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27.apply(chisel-type-vs-scala-type.md:112) // at repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27.apply(chisel-type-vs-scala-type.md:112) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Have to pass hardware to chiselTypeOf: // Do this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) hardware := DontCare val chiselType = chiselTypeOf(hardware) }) // Not this... elaborate(new Module { val chiselType = new MyBundle(3) val crash = chiselTypeOf(chiselType) }) // chisel3.package$ExpectedHardwareException: 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39$$anonfun$apply$36.apply(chisel-type-vs-scala-type.md:138) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39$$anonfun$apply$36.apply(chisel-type-vs-scala-type.md:138) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39.apply(chisel-type-vs-scala-type.md:138) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7.<init>(chisel-type-vs-scala-type.md:138) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34.apply(chisel-type-vs-scala-type.md:136) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34.apply(chisel-type-vs-scala-type.md:136) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Have to pass hardware to *Init: // Do this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) hardware := DontCare val moarHardware = WireInit(hardware) }) // Not this... elaborate(new Module { val crash = WireInit(new MyBundle(3)) }) // chisel3.package$ExpectedHardwareException: wire initializer 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45$$anonfun$apply$41.apply(chisel-type-vs-scala-type.md:160) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45$$anonfun$apply$41.apply(chisel-type-vs-scala-type.md:160) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45.apply(chisel-type-vs-scala-type.md:160) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9.<init>(chisel-type-vs-scala-type.md:160) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40.apply(chisel-type-vs-scala-type.md:159) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40.apply(chisel-type-vs-scala-type.md:159) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can’t pass hardware to a Wire, Reg, IO: // Do this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) hardware := DontCare }) // Not this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) val crash = Wire(hardware) }) // chisel3.package$ExpectedChiselTypeException: wire type '_44_Anon.hardware: Wire[MyBundle]' must be a Chisel type, not hardware // at ... () // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51$$anonfun$apply$47.apply(chisel-type-vs-scala-type.md:182) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51$$anonfun$apply$47.apply(chisel-type-vs-scala-type.md:182) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51.apply(chisel-type-vs-scala-type.md:182) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11.<init>(chisel-type-vs-scala-type.md:182) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44.apply(chisel-type-vs-scala-type.md:180) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44.apply(chisel-type-vs-scala-type.md:180) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) .Lit can only be called on Chisel type: // Do this... elaborate(new Module { val hardwareLit = (new MyBundle(3)).Lit( _.foo -> 0.U, _.bar -> 0.U ) }) //Not this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) val crash = hardware.Lit( _.foo -> 0.U, _.bar -> 0.U ) }) // chisel3.package$ExpectedChiselTypeException: bundle literal constructor model '_52_Anon.hardware: Wire[MyBundle]' must be a Chisel type, not hardware // at ... () // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56$$anonfun$apply$55.apply(chisel-type-vs-scala-type.md:206) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56$$anonfun$apply$55.apply(chisel-type-vs-scala-type.md:206) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56.apply(chisel-type-vs-scala-type.md:206) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13.<init>(chisel-type-vs-scala-type.md:206) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52.apply(chisel-type-vs-scala-type.md:204) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52.apply(chisel-type-vs-scala-type.md:204) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can only use a Chisel type within a Bundle definition: // Do this... elaborate(new Module { val hardware = Wire(new Bundle { val nested = new MyBundle(3) }) hardware := DontCare }) // Not this... elaborate(new Module { val crash = Wire(new Bundle { val nested = Wire(new MyBundle(3)) }) }) // chisel3.package$ExpectedChiselTypeException: Bundle: AnonymousBundle contains hardware fields: nested: _60_Anon.crash_nested: Wire[MyBundle] // at ... () // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62$$anonfun$apply$61.apply(chisel-type-vs-scala-type.md:232) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62$$anonfun$apply$61.apply(chisel-type-vs-scala-type.md:232) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62.apply(chisel-type-vs-scala-type.md:232) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16.<init>(chisel-type-vs-scala-type.md:232) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60.apply(chisel-type-vs-scala-type.md:231) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60.apply(chisel-type-vs-scala-type.md:231) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can only call directionOf on Hardware: import chisel3.reflect.DataMirror class Child extends Module{ val hardware = IO(new MyBundle(3)) hardware := DontCare val chiselType = new MyBundle(3) } // Do this... elaborate(new Module { val child = Module(new Child()) child.hardware := DontCare val direction = DataMirror.directionOf(child.hardware) }) // Not this... elaborate(new Module { val child = Module(new Child()) child.hardware := DontCare val direction = DataMirror.directionOf(child.chiselType) }) // chisel3.package$ExpectedHardwareException: node requested directionality on 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68$$anon$19.<init>(chisel-type-vs-scala-type.md:271) // at repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68.apply(chisel-type-vs-scala-type.md:268) // at repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68.apply(chisel-type-vs-scala-type.md:268) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can call specifiedDirectionOf on hardware or Chisel type: 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: class ScalaCastingModule(gen: () => Bundle) extends Module { val io = IO(Output(gen().asInstanceOf[MyBundle])) io.foo := 0.U } This works if we do indeed have more information than the compiler: elaborate(new ScalaCastingModule( () => new MyBundle(3))) But if we are wrong, we can get a Scala runtime exception: class NotMyBundle extends Bundle {val baz = Bool()} elaborate(new ScalaCastingModule(() => new NotMyBundle())) // java.lang.ClassCastException: class repl.MdocSession$MdocApp$$anonfun$79$NotMyBundle$1 cannot be cast to class repl.MdocSession$MdocApp$MyBundle (repl.MdocSession$MdocApp$$anonfun$79$NotMyBundle$1 and repl.MdocSession$MdocApp$MyBundle are in unnamed module of loader scala.reflect.internal.util.AbstractFileClassLoader @2e3317de) // at ... () // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293) // at chisel3.SpecifiedDirection$.specifiedDirection(Data.scala:65) // at chisel3.Output$.apply(Data.scala:268) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72.apply(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72.apply(chisel-type-vs-scala-type.md:293) // at chisel3.IO$.apply(IO.scala:34) // at chisel3.experimental.BaseModule.IO(Module.scala:736) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71.apply(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71.apply(chisel-type-vs-scala-type.md:293) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76.apply(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$ScalaCastingModule.<init>(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$$anonfun$79$$anonfun$apply$75.apply(chisel-type-vs-scala-type.md:309) // at repl.MdocSession$MdocApp$$anonfun$79$$anonfun$apply$75.apply(chisel-type-vs-scala-type.md:309) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) .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, 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: class SimilarToMyBundle(w: Int) extends Bundle{ val foobar = UInt((2*w).W) } ChiselStage.emitSystemVerilog(new Module { val in = IO(Input(new MyBundle(3))) val out = IO(Output(new SimilarToMyBundle(3))) out := in.asTypeOf(out) }) // res12: String = \"\"\"// Generated by CIRCT firtool-1.57.1 // module _82_Anon( // <stdin>:3:3 // input clock, // <stdin>:4:11 // reset, // <stdin>:5:11 // input [2:0] in_foo, // chisel-type-vs-scala-type.md:324:14 // in_bar, // chisel-type-vs-scala-type.md:324:14 // output [5:0] out_foobar // chisel-type-vs-scala-type.md:325:15 // ); // // assign out_foobar = {in_foo, in_bar}; // <stdin>:3:3, chisel-type-vs-scala-type.md:327:21 // endmodule // // \"\"\" 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."
+      "content": "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 The Scala type of the Data is recognized by the Scala compiler, such as Bool, Decoupled[UInt] or MyBundle in 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. 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 } Chisel Type vs Hardware – Specific Functions and Errors .asTypeOf works for both hardware and Chisel type: 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: // Do this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) hardware := DontCare }) // Not this... elaborate(new Module { val chiselType = new MyBundle(3) chiselType := DontCare }) // chisel3.package$ExpectedHardwareException: data to be connected 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21$$anon$3.<init>(chisel-type-vs-scala-type.md:90) // at repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21.apply(chisel-type-vs-scala-type.md:88) // at repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21.apply(chisel-type-vs-scala-type.md:88) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can only := from hardware: // Do this... elaborate(new Module { val hardware = IO(new MyBundle(3)) val moarHardware = Wire(new MyBundle(3)) moarHardware := DontCare hardware := moarHardware }) // Not this... elaborate(new Module { val hardware = IO(new MyBundle(3)) val chiselType = new MyBundle(3) hardware := chiselType }) // chisel3.package$ExpectedHardwareException: data to be connected 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27$$anon$5.<init>(chisel-type-vs-scala-type.md:115) // at repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27.apply(chisel-type-vs-scala-type.md:112) // at repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27.apply(chisel-type-vs-scala-type.md:112) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Have to pass hardware to chiselTypeOf: // Do this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) hardware := DontCare val chiselType = chiselTypeOf(hardware) }) // Not this... elaborate(new Module { val chiselType = new MyBundle(3) val crash = chiselTypeOf(chiselType) }) // chisel3.package$ExpectedHardwareException: 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39$$anonfun$apply$36.apply(chisel-type-vs-scala-type.md:138) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39$$anonfun$apply$36.apply(chisel-type-vs-scala-type.md:138) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39.apply(chisel-type-vs-scala-type.md:138) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7.<init>(chisel-type-vs-scala-type.md:138) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34.apply(chisel-type-vs-scala-type.md:136) // at repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34.apply(chisel-type-vs-scala-type.md:136) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Have to pass hardware to *Init: // Do this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) hardware := DontCare val moarHardware = WireInit(hardware) }) // Not this... elaborate(new Module { val crash = WireInit(new MyBundle(3)) }) // chisel3.package$ExpectedHardwareException: wire initializer 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45$$anonfun$apply$41.apply(chisel-type-vs-scala-type.md:160) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45$$anonfun$apply$41.apply(chisel-type-vs-scala-type.md:160) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45.apply(chisel-type-vs-scala-type.md:160) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9.<init>(chisel-type-vs-scala-type.md:160) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40.apply(chisel-type-vs-scala-type.md:159) // at repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40.apply(chisel-type-vs-scala-type.md:159) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can’t pass hardware to a Wire, Reg, IO: // Do this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) hardware := DontCare }) // Not this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) val crash = Wire(hardware) }) // chisel3.package$ExpectedChiselTypeException: wire type '_44_Anon.hardware: Wire[MyBundle]' must be a Chisel type, not hardware // at ... () // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51$$anonfun$apply$47.apply(chisel-type-vs-scala-type.md:182) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51$$anonfun$apply$47.apply(chisel-type-vs-scala-type.md:182) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51.apply(chisel-type-vs-scala-type.md:182) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11.<init>(chisel-type-vs-scala-type.md:182) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44.apply(chisel-type-vs-scala-type.md:180) // at repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44.apply(chisel-type-vs-scala-type.md:180) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) .Lit can only be called on Chisel type: // Do this... elaborate(new Module { val hardwareLit = (new MyBundle(3)).Lit( _.foo -> 0.U, _.bar -> 0.U ) }) //Not this... elaborate(new Module { val hardware = Wire(new MyBundle(3)) val crash = hardware.Lit( _.foo -> 0.U, _.bar -> 0.U ) }) // chisel3.package$ExpectedChiselTypeException: bundle literal constructor model '_52_Anon.hardware: Wire[MyBundle]' must be a Chisel type, not hardware // at ... () // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56$$anonfun$apply$55.apply(chisel-type-vs-scala-type.md:206) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56$$anonfun$apply$55.apply(chisel-type-vs-scala-type.md:206) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56.apply(chisel-type-vs-scala-type.md:206) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13.<init>(chisel-type-vs-scala-type.md:206) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52.apply(chisel-type-vs-scala-type.md:204) // at repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52.apply(chisel-type-vs-scala-type.md:204) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can only use a Chisel type within a Bundle definition: // Do this... elaborate(new Module { val hardware = Wire(new Bundle { val nested = new MyBundle(3) }) hardware := DontCare }) // Not this... elaborate(new Module { val crash = Wire(new Bundle { val nested = Wire(new MyBundle(3)) }) }) // chisel3.package$ExpectedChiselTypeException: Bundle: AnonymousBundle contains hardware fields: nested: _60_Anon.crash_nested: Wire[MyBundle] // at ... () // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62$$anonfun$apply$61.apply(chisel-type-vs-scala-type.md:232) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62$$anonfun$apply$61.apply(chisel-type-vs-scala-type.md:232) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62.apply(chisel-type-vs-scala-type.md:232) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16.<init>(chisel-type-vs-scala-type.md:232) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60.apply(chisel-type-vs-scala-type.md:231) // at repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60.apply(chisel-type-vs-scala-type.md:231) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can only call directionOf on Hardware: import chisel3.reflect.DataMirror class Child extends Module{ val hardware = IO(new MyBundle(3)) hardware := DontCare val chiselType = new MyBundle(3) } // Do this... elaborate(new Module { val child = Module(new Child()) child.hardware := DontCare val direction = DataMirror.directionOf(child.hardware) }) // Not this... elaborate(new Module { val child = Module(new Child()) child.hardware := DontCare val direction = DataMirror.directionOf(child.chiselType) }) // chisel3.package$ExpectedHardwareException: node requested directionality on 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)? // at ... () // at repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68$$anon$19.<init>(chisel-type-vs-scala-type.md:271) // at repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68.apply(chisel-type-vs-scala-type.md:268) // at repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68.apply(chisel-type-vs-scala-type.md:268) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Can call specifiedDirectionOf on hardware or Chisel type: 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: class ScalaCastingModule(gen: () => Bundle) extends Module { val io = IO(Output(gen().asInstanceOf[MyBundle])) io.foo := 0.U } This works if we do indeed have more information than the compiler: elaborate(new ScalaCastingModule( () => new MyBundle(3))) But if we are wrong, we can get a Scala runtime exception: class NotMyBundle extends Bundle {val baz = Bool()} elaborate(new ScalaCastingModule(() => new NotMyBundle())) // java.lang.ClassCastException: class repl.MdocSession$MdocApp$$anonfun$79$NotMyBundle$1 cannot be cast to class repl.MdocSession$MdocApp$MyBundle (repl.MdocSession$MdocApp$$anonfun$79$NotMyBundle$1 and repl.MdocSession$MdocApp$MyBundle are in unnamed module of loader scala.reflect.internal.util.AbstractFileClassLoader @40eefb7b) // at ... () // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293) // at chisel3.SpecifiedDirection$.specifiedDirection(Data.scala:65) // at chisel3.Output$.apply(Data.scala:268) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72.apply(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72.apply(chisel-type-vs-scala-type.md:293) // at chisel3.IO$.apply(IO.scala:34) // at chisel3.experimental.BaseModule.IO(Module.scala:736) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71.apply(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71.apply(chisel-type-vs-scala-type.md:293) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76.apply(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76.apply(chisel-type-vs-scala-type.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp$ScalaCastingModule.<init>(chisel-type-vs-scala-type.md:293) // at repl.MdocSession$MdocApp$$anonfun$79$$anonfun$apply$75.apply(chisel-type-vs-scala-type.md:309) // at repl.MdocSession$MdocApp$$anonfun$79$$anonfun$apply$75.apply(chisel-type-vs-scala-type.md:309) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) .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, 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: class SimilarToMyBundle(w: Int) extends Bundle{ val foobar = UInt((2*w).W) } ChiselStage.emitSystemVerilog(new Module { val in = IO(Input(new MyBundle(3))) val out = IO(Output(new SimilarToMyBundle(3))) out := in.asTypeOf(out) }) // res12: String = \"\"\"// Generated by CIRCT firtool-1.57.1 // module _82_Anon( // <stdin>:3:3 // input clock, // <stdin>:4:11 // reset, // <stdin>:5:11 // input [2:0] in_foo, // chisel-type-vs-scala-type.md:324:14 // in_bar, // chisel-type-vs-scala-type.md:324:14 // output [5:0] out_foobar // chisel-type-vs-scala-type.md:325:15 // ); // // assign out_foobar = {in_foo, in_bar}; // <stdin>:3:3, chisel-type-vs-scala-type.md:327:21 // endmodule // // \"\"\" 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."
     } ,    
     {
       "title": "Combinational Circuits",
@@ -80,7 +80,7 @@ function prepareIdxAndDocMap() {
     {
       "title": "General Cookbook",
       "url": "/chisel3/docs/cookbooks/cookbook.html",
-      "content": "General Cookbook Please note that these examples make use of Chisel’s scala-style printing. Type Conversions How do I create a UInt from an instance of a Bundle? How do I create a Bundle from a UInt? How can I tieoff a Bundle/Vec to 0? How do I create a Vec of Bools from a UInt? How do I create a UInt from a Vec of Bool? How do I connect a subset of Bundle fields? Vectors and Registers Can I make a 2D or 3D Vector? How do I create a Vector of Registers? How do I create a Reg of type Vec? How do I partially reset an Aggregate Reg? Bundles How do I deal with aliased Bundle fields? How do I deal with the “unable to clone” error? How do I create a finite state machine? How do I unpack a value (“reverse concatenation”) like in Verilog? How do I do subword assignment (assign to some bits in a UInt)? How do I create an optional I/O? How do I create I/O without a prefix? How do I minimize the number of bits used in an output vector How do I resolve “Dynamic index … is too wide/narrow for extractee …”? Predictable Naming How do I get Chisel to name signals properly in blocks like when/withClockAndReset? How do I get Chisel to name the results of vector reads properly? How can I dynamically set/parametrize the name of a module? Directionality How do I strip directions from a bidirectional Bundle (or other Data)? Type Conversions How do I create a UInt from an instance of a Bundle? Call asUInt on the Bundle instance. import chisel3._ class MyBundle extends Bundle { val foo = UInt(4.W) val bar = UInt(4.W) } class Foo extends Module { val bundle = Wire(new MyBundle) bundle.foo := 0xc.U bundle.bar := 0x3.U val uint = bundle.asUInt printf(cf\"$uint\") // 195 // Test assert(uint === 0xc3.U) } How do I create a Bundle from a UInt? Use the asTypeOf method to reinterpret the UInt as the type of the Bundle. import chisel3._ class MyBundle extends Bundle { val foo = UInt(4.W) val bar = UInt(4.W) } class Foo extends Module { val uint = 0xb4.U val bundle = uint.asTypeOf(new MyBundle) printf(cf\"$bundle\") // Bundle(foo -> 11, bar -> 4) // Test assert(bundle.foo === 0xb.U) assert(bundle.bar === 0x4.U) } How can I tieoff a Bundle/Vec to 0? You can use asTypeOf as above. If you don’t want to worry about the type of the thing you are tying off, you can use chiselTypeOf: import chisel3._ import circt.stage.ChiselStage class MyBundle extends Bundle { val foo = UInt(4.W) val bar = Vec(4, UInt(1.W)) } class Foo(typ: MyBundle) extends Module { val bundleA = IO(Output(typ)) val bundleB = IO(Output(typ)) // typ is already a Chisel Data Type, so can use it directly here, but you // need to know that bundleA is of type typ bundleA := 0.U.asTypeOf(typ) // bundleB is a Hardware data IO(Output(...)) so need to call chiselTypeOf, // but this will work no matter the type of bundleB: bundleB := 0.U.asTypeOf(chiselTypeOf(bundleB)) } ChiselStage.emitSystemVerilog(new Foo(new MyBundle)) How do I create a Vec of Bools from a UInt? Use VecInit given a Seq[Bool] generated using the asBools method. import chisel3._ class Foo extends Module { val uint = 0xc.U val vec = VecInit(uint.asBools) printf(cf\"$vec\") // Vec(0, 0, 1, 1) // Test assert(vec(0) === false.B) assert(vec(1) === false.B) assert(vec(2) === true.B) assert(vec(3) === true.B) } How do I create a UInt from a Vec of Bool? Use the builtin function asUInt import chisel3._ class Foo extends Module { val vec = VecInit(true.B, false.B, true.B, true.B) val uint = vec.asUInt printf(cf\"$uint\") // 13 // Test // (remember leftmost Bool in Vec is low order bit) assert(0xd.U === uint) } How do I connect a subset of Bundle fields? See the DataView cookbook. Vectors and Registers Can I make a 2D or 3D Vector? Yes. Using VecInit you can make Vectors that hold Vectors of Chisel types. Methods fill and tabulate make these multi-dimensional Vectors. import chisel3._ class MyBundle extends Bundle { val foo = UInt(4.W) val bar = UInt(4.W) } class Foo extends Module { //2D Fill val twoDVec = VecInit.fill(2, 3)(5.U) //3D Fill val myBundle = Wire(new MyBundle) myBundle.foo := 0xc.U myBundle.bar := 0x3.U val threeDVec = VecInit.fill(1, 2, 3)(myBundle) assert(threeDVec(0)(0)(0).foo === 0xc.U && threeDVec(0)(0)(0).bar === 0x3.U) //2D Tabulate val indexTiedVec = VecInit.tabulate(2, 2){ (x, y) => (x + y).U } assert(indexTiedVec(0)(0) === 0.U) assert(indexTiedVec(0)(1) === 1.U) assert(indexTiedVec(1)(0) === 1.U) assert(indexTiedVec(1)(1) === 2.U) //3D Tabulate val indexTiedVec3D = VecInit.tabulate(2, 3, 4){ (x, y, z) => (x + y * z).U } assert(indexTiedVec3D(0)(0)(0) === 0.U) assert(indexTiedVec3D(1)(1)(1) === 2.U) assert(indexTiedVec3D(1)(1)(2) === 3.U) assert(indexTiedVec3D(1)(1)(3) === 4.U) assert(indexTiedVec3D(1)(2)(3) === 7.U) } How do I create a Vector of Registers? Rule! Use Reg of Vec not Vec of Reg! You create a Reg of type Vec. Because Vecs are a type (like UInt, Bool) rather than a value, we must bind the Vec to some concrete value. How do I create a Reg of type Vec? For more information, the API Documentation for Vec provides more information. import chisel3._ class Foo extends Module { val regOfVec = Reg(Vec(4, UInt(32.W))) // Register of 32-bit UInts regOfVec(0) := 123.U // Assignments to elements of the Vec regOfVec(1) := 456.U regOfVec(2) := 789.U regOfVec(3) := regOfVec(0) // Reg of Vec of 32-bit UInts initialized to zero // Note that Seq.fill constructs 4 32-bit UInt literals with the value 0 // VecInit(...) then constructs a Wire of these literals // The Reg is then initialized to the value of the Wire (which gives it the same type) val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W)))) } How do I partially reset an Aggregate Reg? The easiest way is to use a partially-specified Bundle Literal or Vec Literal to match the type of the Reg. 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. 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 How do I deal with aliased Bundle fields? Following the gen pattern when creating Bundles can result in some opaque error messages: class AliasedBundle[T <: Data](gen: T) extends Bundle { val foo = gen val bar = gen } getVerilogString(new Top(new AliasedBundle(UInt(8.W)))) // chisel3.AliasedAggregateFieldException: AliasedBundle contains aliased fields named (bar,foo) // at ... () // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:301) // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:301) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:301) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp17$Top.<init>(cookbook.md:301) // at repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:320) // at repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:320) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) This error is saying that fields foo and bar of AliasedBundle are the exact same object in memory. This is a problem for Chisel because we need to be able to distinguish uses of foo and bar but cannot when they are referentially the same. Note that the following example looks different but will give you exactly the same issue: class AlsoAliasedBundle[T <: Data](val gen: T) extends Bundle { // ^ This val makes `gen` a field, just like `foo` val foo = gen } By making gen a val, it becomes a public field of the class, just like foo. getVerilogString(new Top(new AlsoAliasedBundle(UInt(8.W)))) // chisel3.AliasedAggregateFieldException: AlsoAliasedBundle contains aliased fields named (foo,gen) // at ... () // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:301) // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:301) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:301) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp17$Top.<init>(cookbook.md:301) // at repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:339) // at repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:339) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) There are several ways to solve this issue with their own advantages and disadvantages. 1. 0-arity function parameters Instead of passing an object as a parameter, you can pass a 0-arity function (a function with no arguments): class UsingAFunctionBundle[T <: Data](gen: () => T) extends Bundle { val foo = gen() val bar = gen() } Note that the type of gen is now () => T. Because it is now a function and not a subtype of Data, you can safely make gen a val without it becoming a hardware field of the Bundle. Note that this also means you must pass gen as a function, for example: getVerilogString(new Top(new UsingAFunctionBundle(() => UInt(8.W)))) Warning: you must ensure that gen creates fresh objects rather than capturing an already constructed value: class MisusedFunctionArguments extends Module { // This usage is correct val in = IO(Input(new UsingAFunctionBundle(() => UInt(8.W)))) // This usage is incorrect val fizz = UInt(8.W) val out = IO(Output(new UsingAFunctionBundle(() => fizz))) } getVerilogString(new MisusedFunctionArguments) // chisel3.AutoClonetypeException: The bundle plugin was unable to clone UsingAFunctionBundle that has field 'foo' aliased with base UsingAFunctionBundle.This likely happened because you tried nesting Data arguments inside of other data structures. Try wrapping the field(s) in Input(...), Output(...), or Flipped(...) if appropriate. As a last resort, you can call chisel3.reflect.DataMirror.internal.chiselTypeClone on any nested Data arguments. See the cookbook entry 'How do I deal with the \"unable to clone\" error?' for more details. // at ... () // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:370) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:370) // at chisel3.IO$.apply(IO.scala:34) // at chisel3.experimental.BaseModule.IO(Module.scala:736) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:370) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:370) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md:370) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1.<init>(cookbook.md:370) // at repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:372) // at repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:372) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) In the above example, value fizz and fields foo and bar of out are all the same object in memory. 2. By-name function parameters Functionally the same as (1) but with more subtle syntax, you can use Scala by-name function parameters: class UsingByNameParameters[T <: Data](gen: => T) extends Bundle { val foo = gen val bar = gen } With this usage, you do not include () => when passing the argument: getVerilogString(new Top(new UsingByNameParameters(UInt(8.W)))) Note that as this is just syntactic sugar over (1), the same warning applies. 3. Directioned Bundle fields You can alternatively wrap the fields with Output(...), which creates fresh instances of the passed argument. Chisel treats Output as the “default direction” so if all fields are outputs, the Bundle is functionally equivalent to a Bundle with no directioned fields. class DirectionedBundle[T <: Data](gen: T) extends Bundle { val foo = Output(gen) val bar = Output(gen) } This approach is admittedly a little ugly and may mislead others reading the code because it implies that this Bundle is intended to be used as an Output. 4. Call .cloneType directly You can also just call .cloneType on your gen argument directly. While we try to hide this implementation detail from the user, .cloneType is the mechanism by which Chisel creates fresh instances of Data objects: class UsingCloneTypeBundle[T <: Data](gen: T) extends Bundle { val foo = gen.cloneType val bar = gen.cloneType } How do I deal with the “unable to clone” error? Most Chisel objects need to be cloned in order to differentiate between the software representation of the bundle field from its “bound” hardware representation, where “binding” is the process of generating a hardware component. For Bundle fields, this cloning is supposed to happen automatically with a compiler plugin. In some cases though, the plugin may not be able to clone the Bundle fields. The most common case for when this happens is when the chisel3.Data part of the Bundle field is nested inside some other data structure and the compiler plugin is unable to figure out how to clone the entire structure. It is best to avoid such nested structures. There are a few ways around this issue - you can try wrapping the problematic fields in Input(…), Output(…), or Flipped(…) if appropriate. You can also try manually cloning each field in the Bundle using the chiselTypeClone method in chisel3.reflect.DataMirror. Here’s an example with the Bundle whose fields won’t get cloned: class CustomBundleBroken(elts: (String, Data)*) extends Record { val elements = ListMap(elts: _*) def apply(elt: String): Data = elements(elt) } class NewModule extends Module { val out = Output(UInt(8.W)) val recordType = new CustomBundleBroken(\"fizz\" -> UInt(16.W), \"buzz\" -> UInt(16.W)) val record = Wire(recordType) val uint = record.asUInt val record2 = uint.asTypeOf(recordType) out := record } getVerilogString(new NewModule) // chisel3.AutoClonetypeException: The bundle plugin was unable to clone CustomBundleBroken$1 that has field 'fizz' aliased with base CustomBundleBroken$1.This likely happened because you tried nesting Data arguments inside of other data structures. Try wrapping the field(s) in Input(...), Output(...), or Flipped(...) if appropriate. As a last resort, you can call chisel3.reflect.DataMirror.internal.chiselTypeClone on any nested Data arguments. See the cookbook entry 'How do I deal with the \"unable to clone\" error?' for more details. // at ... () // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:444) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:444) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md:444) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1.<init>(cookbook.md:444) // at repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:449) // at repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:449) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) You can use chiselTypeClone to clone the elements as: import chisel3.reflect.DataMirror import chisel3.experimental.requireIsChiselType class CustomBundleFixed(elts: (String, Data)*) extends Record { val elements = ListMap(elts.map { case (field, elt) => requireIsChiselType(elt) field -> DataMirror.internal.chiselTypeClone(elt) }: _*) def apply(elt: String): Data = elements(elt) } How do I create a finite state machine (FSM)? The advised way is to use ChiselEnum to construct enumerated types representing the state of the FSM. State transitions are then handled with switch/is and when/.elsewhen/.otherwise. import chisel3._ import chisel3.util.{switch, is} object DetectTwoOnes { object State extends ChiselEnum { val sNone, sOne1, sTwo1s = Value } } /* This FSM detects two 1's one after the other */ class DetectTwoOnes extends Module { import DetectTwoOnes.State import DetectTwoOnes.State._ val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) val state = Output(State()) }) val state = RegInit(sNone) io.out := (state === sTwo1s) io.state := state switch (state) { is (sNone) { when (io.in) { state := sOne1 } } is (sOne1) { when (io.in) { state := sTwo1s } .otherwise { state := sNone } } is (sTwo1s) { when (!io.in) { state := sNone } } } } Note: the is statement can take multiple conditions e.g. is (sTwo1s, sOne1) { ... }. How do I unpack a value (“reverse concatenation”) like in Verilog? In Verilog, you can do something like the following which will unpack a the value z: wire [1:0] a; wire [3:0] b; wire [2:0] c; wire [8:0] z = [...]; assign {a,b,c} = z; Unpacking often corresponds to reinterpreting an unstructured data type as a structured data type. Frequently, this structured type is used prolifically in the design, and has been declared as in the following example: import chisel3._ class MyBundle extends Bundle { val a = UInt(2.W) val b = UInt(4.W) val c = UInt(3.W) } The easiest way to accomplish this in Chisel would be: class Foo extends Module { val z = Wire(UInt(9.W)) z := DontCare // This is a dummy connection val unpacked = z.asTypeOf(new MyBundle) printf(\"%d\", unpacked.a) printf(\"%d\", unpacked.b) printf(\"%d\", unpacked.c) } If you really need to do this for a one-off case (Think thrice! It is likely you can better structure the code using bundles), then rocket-chip has a Split utility which can accomplish this. How do I do subword assignment (assign to some bits in a UInt)? You may try to do something like the following where you want to assign only some bits of a Chisel type. Below, the left-hand side connection to io.out(0) is not allowed. import chisel3._ import circt.stage.ChiselStage class Foo extends Module { val io = IO(new Bundle { val bit = Input(Bool()) val out = Output(UInt(10.W)) }) io.out(0) := io.bit } If you try to compile this, you will get an error. getVerilogString(new Foo) // chisel3.package$ChiselException: Cannot reassign to read-only Foo.?: OpResult[Bool] // at ... () // at repl.MdocSession$MdocApp26$Foo.<init>(cookbook.md:589) // at repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:597) // at repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:597) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Chisel3 does not support subword assignment. The reason for this is that subword assignment generally hints at a better abstraction with an aggregate/structured types, i.e., a Bundle or a Vec. If you must express it this way, one approach is to blast your UInt to a Vec of Bool and back: import chisel3._ class Foo extends Module { val io = IO(new Bundle { val in = Input(UInt(10.W)) val bit = Input(Bool()) val out = Output(UInt(10.W)) }) val bools = VecInit(io.in.asBools) bools(0) := io.bit io.out := bools.asUInt } How do I create an optional I/O? The following example is a module which includes the optional port out2 only if the given parameter is true. import chisel3._ class ModuleWithOptionalIOs(flag: Boolean) extends Module { val io = IO(new Bundle { val in = Input(UInt(12.W)) val out = Output(UInt(12.W)) val out2 = if (flag) Some(Output(UInt(12.W))) else None }) io.out := io.in if (flag) { io.out2.get := io.in } } The following is an example where an entire IO is optional: import chisel3._ class ModuleWithOptionalIO(flag: Boolean) extends Module { val in = if (flag) Some(IO(Input(Bool()))) else None val out = IO(Output(Bool())) out := in.getOrElse(false.B) } How do I create I/O without a prefix? In most cases, you can simply call IO multiple times: import chisel3._ class MyModule extends Module { val in = IO(Input(UInt(8.W))) val out = IO(Output(UInt(8.W))) out := in +% 1.U } // Generated by CIRCT firtool-1.57.1 module MyModule( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 input [7:0] in, // cookbook.md:692:14 output [7:0] out // cookbook.md:693:15 ); assign out = in + 8'h1; // <stdin>:3:3, cookbook.md:695:13 endmodule If you have a Bundle from which you would like to create ports without the normal val prefix, you can use FlatIO: import chisel3._ import chisel3.experimental.FlatIO class MyBundle extends Bundle { val foo = Input(UInt(8.W)) val bar = Output(UInt(8.W)) } class MyModule extends Module { val io = FlatIO(new MyBundle) io.bar := io.foo +% 1.U } Note that io_ is nowhere to be seen! // Generated by CIRCT firtool-1.57.1 module MyModule( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 input [7:0] foo, // cookbook.md:724:18 output [7:0] bar // cookbook.md:724:18 ); assign bar = foo + 8'h1; // <stdin>:3:3, cookbook.md:726:20 endmodule How do I minimize the number of bits used in an output vector? Use inferred width and a Seq instead of a Vec: Consider: import chisel3._ // Count the number of set bits up to and including each bit position class CountBits(width: Int) extends Module { val bits = IO(Input(UInt(width.W))) val countSequence = Seq.tabulate(width)(i => IO(Output(UInt()))) val countVector = IO(Output(Vec(width, UInt()))) countSequence.zipWithIndex.foreach { case (port, i) => port := util.PopCount(bits(i, 0)) } countVector := countSequence } Unlike Vecs which represent a singular Chisel type and must have the same width for every element, Seq is a purely Scala construct, so their elements are independent from the perspective of Chisel and can have different widths. // Generated by CIRCT firtool-1.57.1 module CountBits( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 input [3:0] bits, // cookbook.md:746:16 output countSequence_0, // cookbook.md:747:50 output [1:0] countSequence_1, // cookbook.md:747:50 countSequence_2, // cookbook.md:747:50 output [2:0] countSequence_3, // cookbook.md:747:50 countVector_0, // cookbook.md:748:23 countVector_1, // cookbook.md:748:23 countVector_2, // cookbook.md:748:23 countVector_3 // cookbook.md:748:23 ); How do I resolve “Dynamic index … is too wide/narrow for extractee …”? Chisel will warn if a dynamic index is not the correctly-sized width for indexing a Vec or UInt. “Correctly-sized” means that the width of the index should be the log2 of the size of the indexee. If the indexee is a non-power-of-2 size, use the ceiling of the log2 result. When the index does not have enough bits to address all entries or bits in the extractee, you can .pad the index to increase the width. class TooNarrow extends RawModule { val extractee = Wire(UInt(7.W)) val index = Wire(UInt(2.W)) extractee(index) } compile(new TooNarrow) // [warn] cookbook.md 788:12: [W003] Dynamic index with width 2 is too small for extractee of width 7 // [warn] There were 1 warning(s) during hardware elaboration. This can be fixed with pad: class TooNarrowFixed extends RawModule { val extractee = Wire(UInt(7.W)) val index = Wire(UInt(2.W)) extractee(index.pad(3)) } compile(new TooNarrowFixed) Use bit extraction when the index is too wide class TooWide extends RawModule { val extractee = Wire(Vec(8, UInt(32.W))) val index = Wire(UInt(4.W)) extractee(index) } compile(new TooWide) // [warn] cookbook.md 814:12: [W004] Dynamic index with width 4 is too wide for Vec of size 8 (expected index width 3). // [warn] There were 1 warning(s) during hardware elaboration. This can be fixed with bit extraction: class TooWideFixed extends RawModule { val extractee = Wire(Vec(8, UInt(32.W))) val index = Wire(UInt(4.W)) extractee(index(2, 0)) } compile(new TooWideFixed) Note that size 1 Vecs and UInts should be indexed by a zero-width UInt: class SizeOneVec extends RawModule { val extractee = Wire(Vec(1, UInt(32.W))) val index = Wire(UInt(0.W)) extractee(index) } compile(new SizeOneVec) Because pad only pads if the desired width is less than the current width of the argument, you can use pad in conjunction with bit extraction when the widths may be too wide or too narrow under different circumstances import chisel3.util.log2Ceil class TooWideOrNarrow(extracteeSize: Int, indexWidth: Int) extends Module { val extractee = Wire(Vec(extracteeSize, UInt(8.W))) val index = Wire(UInt(indexWidth.W)) val correctWidth = log2Ceil(extracteeSize) extractee(index.pad(correctWidth)(correctWidth - 1, 0)) } compile(new TooWideOrNarrow(8, 2)) compile(new TooWideOrNarrow(8, 4)) Another option for dynamic bit selection of UInts (but not Vec dynamic indexing) is to do a dynamic right shift of the extractee by the index and then just bit select a single bit: class TooWideOrNarrowUInt(extracteeSize: Int, indexWidth: Int) extends Module { val extractee = Wire(UInt(extracteeSize.W)) val index = Wire(UInt(indexWidth.W)) (extractee >> index)(0) } compile(new TooWideOrNarrowUInt(8, 2)) compile(new TooWideOrNarrowUInt(8, 4)) Predictable Naming How do I get Chisel to name signals properly in blocks like when/withClockAndReset? Use the compiler plugin, and check out the Naming Cookbook if that still does not do what you want. How do I get Chisel to name the results of vector reads properly? Currently, name information is lost when using dynamic indexing. For example: import chisel3._ class Foo extends Module { val io = IO(new Bundle { val in = Input(Vec(4, Bool())) val idx = Input(UInt(2.W)) val en = Input(Bool()) val out = Output(Bool()) }) val x = io.in(io.idx) val y = x && io.en io.out := y } The above code loses the x name, instead using _GEN_3 (the other _GEN_* signals are expected). {% raw %} // Generated by CIRCT firtool-1.57.1 module Foo( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 io_in_0, // cookbook.md:893:14 io_in_1, // cookbook.md:893:14 io_in_2, // cookbook.md:893:14 io_in_3, // cookbook.md:893:14 input [1:0] io_idx, // cookbook.md:893:14 input io_en, // cookbook.md:893:14 output io_out // cookbook.md:893:14 ); wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}}; // cookbook.md:901:13 assign io_out = _GEN[io_idx] & io_en; // <stdin>:3:3, cookbook.md:901:13 endmodule {% endraw %} This can be worked around by creating a wire and connecting the dynamic index to the wire: val x = WireInit(io.in(io.idx)) Which produces: {% raw %} // Generated by CIRCT firtool-1.57.1 module Foo2( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 io_in_0, // cookbook.md:916:14 io_in_1, // cookbook.md:916:14 io_in_2, // cookbook.md:916:14 io_in_3, // cookbook.md:916:14 input [1:0] io_idx, // cookbook.md:916:14 input io_en, // cookbook.md:916:14 output io_out // cookbook.md:916:14 ); wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}}; // cookbook.md:923:19 assign io_out = _GEN[io_idx] & io_en; // <stdin>:3:3, cookbook.md:923:19, :924:13 endmodule {% endraw %} How can I dynamically set/parametrize the name of a module? You can override the desiredName function. This works with normal Chisel modules and BlackBoxes. Example: import chisel3._ class Coffee extends BlackBox { val io = IO(new Bundle { val I = Input(UInt(32.W)) val O = Output(UInt(32.W)) }) override def desiredName = \"Tea\" } class Salt extends Module { val io = IO(new Bundle {}) val drink = Module(new Coffee) override def desiredName = \"SodiumMonochloride\" drink.io.I := 42.U } Elaborating the Chisel module Salt yields our “desired names” for Salt and Coffee in the output Verilog: // Generated by CIRCT firtool-1.57.1 // external module Tea module SodiumMonochloride( // <stdin>:8:3 input clock, // <stdin>:9:11 reset // <stdin>:10:11 ); Tea drink ( // cookbook.md:955:23 .I (32'h2A), // cookbook.md:958:16 .O (/* unused */) ); endmodule Directionality How do I strip directions from a bidirectional Bundle (or other Data)? Given a bidirectional port like a Decoupled, you will get an error if you try to connect it directly to a register: import chisel3._ import circt.stage.ChiselStage import chisel3.util.Decoupled class BadRegConnect extends Module { val io = IO(new Bundle { val enq = Decoupled(UInt(8.W)) }) val monitor = Reg(chiselTypeOf(io.enq)) monitor := io.enq } ChiselStage.emitSystemVerilog(new BadRegConnect) // circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: firtool returned a non-zero exit code. Note that this version of Chisel (0.0.0+1-8b7b7a23-SNAPSHOT) was published against firtool version 1.57.1. // ------------------------------------------------------------------------------ // ExitCode: // 1 // STDOUT: // // STDERR: // cookbook.md:988:20: error: 'firrtl.reg' op result #0 must be a passive non-'const' base type that does not contain analog, but got '!firrtl.bundle<ready flip: uint<1>, valid: uint<1>, bits: uint<8>>' // cookbook.md:988:20: note: see current operation: %4 = \"firrtl.reg\"(%arg0) {annotations = [], name = \"monitor\", nameKind = #firrtl<name_kind interesting_name>} : (!firrtl.clock) -> !firrtl.bundle<ready flip: uint<1>, valid: uint<1>, bits: uint<8>> // // ------------------------------------------------------------------------------ While there is no construct to “strip direction” in Chisel3, wrapping a type in Output(...) (the default direction in Chisel3) will set all of the individual elements to output direction. This will have the desired result when used to construct a Register: import chisel3._ import circt.stage.ChiselStage import chisel3.util.Decoupled class CoercedRegConnect extends Module { val io = IO(new Bundle { val enq = Flipped(Decoupled(UInt(8.W))) }) // Make a Reg which contains all of the bundle's signals, regardless of their directionality val monitor = Reg(Output(chiselTypeOf(io.enq))) // Even though io.enq is bidirectional, := will drive all fields of monitor with the fields of io.enq monitor := io.enq }"
+      "content": "General Cookbook Please note that these examples make use of Chisel’s scala-style printing. Type Conversions How do I create a UInt from an instance of a Bundle? How do I create a Bundle from a UInt? How can I tieoff a Bundle/Vec to 0? How do I create a Vec of Bools from a UInt? How do I create a UInt from a Vec of Bool? How do I connect a subset of Bundle fields? Vectors and Registers Can I make a 2D or 3D Vector? How do I create a Vector of Registers? How do I create a Reg of type Vec? How do I partially reset an Aggregate Reg? Bundles How do I deal with aliased Bundle fields? How do I deal with the “unable to clone” error? How do I create a finite state machine? How do I unpack a value (“reverse concatenation”) like in Verilog? How do I do subword assignment (assign to some bits in a UInt)? How do I create an optional I/O? How do I create I/O without a prefix? How do I minimize the number of bits used in an output vector How do I resolve “Dynamic index … is too wide/narrow for extractee …”? Predictable Naming How do I get Chisel to name signals properly in blocks like when/withClockAndReset? How do I get Chisel to name the results of vector reads properly? How can I dynamically set/parametrize the name of a module? Directionality How do I strip directions from a bidirectional Bundle (or other Data)? Type Conversions How do I create a UInt from an instance of a Bundle? Call asUInt on the Bundle instance. import chisel3._ class MyBundle extends Bundle { val foo = UInt(4.W) val bar = UInt(4.W) } class Foo extends Module { val bundle = Wire(new MyBundle) bundle.foo := 0xc.U bundle.bar := 0x3.U val uint = bundle.asUInt printf(cf\"$uint\") // 195 // Test assert(uint === 0xc3.U) } How do I create a Bundle from a UInt? Use the asTypeOf method to reinterpret the UInt as the type of the Bundle. import chisel3._ class MyBundle extends Bundle { val foo = UInt(4.W) val bar = UInt(4.W) } class Foo extends Module { val uint = 0xb4.U val bundle = uint.asTypeOf(new MyBundle) printf(cf\"$bundle\") // Bundle(foo -> 11, bar -> 4) // Test assert(bundle.foo === 0xb.U) assert(bundle.bar === 0x4.U) } How can I tieoff a Bundle/Vec to 0? You can use asTypeOf as above. If you don’t want to worry about the type of the thing you are tying off, you can use chiselTypeOf: import chisel3._ import circt.stage.ChiselStage class MyBundle extends Bundle { val foo = UInt(4.W) val bar = Vec(4, UInt(1.W)) } class Foo(typ: MyBundle) extends Module { val bundleA = IO(Output(typ)) val bundleB = IO(Output(typ)) // typ is already a Chisel Data Type, so can use it directly here, but you // need to know that bundleA is of type typ bundleA := 0.U.asTypeOf(typ) // bundleB is a Hardware data IO(Output(...)) so need to call chiselTypeOf, // but this will work no matter the type of bundleB: bundleB := 0.U.asTypeOf(chiselTypeOf(bundleB)) } ChiselStage.emitSystemVerilog(new Foo(new MyBundle)) How do I create a Vec of Bools from a UInt? Use VecInit given a Seq[Bool] generated using the asBools method. import chisel3._ class Foo extends Module { val uint = 0xc.U val vec = VecInit(uint.asBools) printf(cf\"$vec\") // Vec(0, 0, 1, 1) // Test assert(vec(0) === false.B) assert(vec(1) === false.B) assert(vec(2) === true.B) assert(vec(3) === true.B) } How do I create a UInt from a Vec of Bool? Use the builtin function asUInt import chisel3._ class Foo extends Module { val vec = VecInit(true.B, false.B, true.B, true.B) val uint = vec.asUInt printf(cf\"$uint\") // 13 // Test // (remember leftmost Bool in Vec is low order bit) assert(0xd.U === uint) } How do I connect a subset of Bundle fields? See the DataView cookbook. Vectors and Registers Can I make a 2D or 3D Vector? Yes. Using VecInit you can make Vectors that hold Vectors of Chisel types. Methods fill and tabulate make these multi-dimensional Vectors. import chisel3._ class MyBundle extends Bundle { val foo = UInt(4.W) val bar = UInt(4.W) } class Foo extends Module { //2D Fill val twoDVec = VecInit.fill(2, 3)(5.U) //3D Fill val myBundle = Wire(new MyBundle) myBundle.foo := 0xc.U myBundle.bar := 0x3.U val threeDVec = VecInit.fill(1, 2, 3)(myBundle) assert(threeDVec(0)(0)(0).foo === 0xc.U && threeDVec(0)(0)(0).bar === 0x3.U) //2D Tabulate val indexTiedVec = VecInit.tabulate(2, 2){ (x, y) => (x + y).U } assert(indexTiedVec(0)(0) === 0.U) assert(indexTiedVec(0)(1) === 1.U) assert(indexTiedVec(1)(0) === 1.U) assert(indexTiedVec(1)(1) === 2.U) //3D Tabulate val indexTiedVec3D = VecInit.tabulate(2, 3, 4){ (x, y, z) => (x + y * z).U } assert(indexTiedVec3D(0)(0)(0) === 0.U) assert(indexTiedVec3D(1)(1)(1) === 2.U) assert(indexTiedVec3D(1)(1)(2) === 3.U) assert(indexTiedVec3D(1)(1)(3) === 4.U) assert(indexTiedVec3D(1)(2)(3) === 7.U) } How do I create a Vector of Registers? Rule! Use Reg of Vec not Vec of Reg! You create a Reg of type Vec. Because Vecs are a type (like UInt, Bool) rather than a value, we must bind the Vec to some concrete value. How do I create a Reg of type Vec? For more information, the API Documentation for Vec provides more information. import chisel3._ class Foo extends Module { val regOfVec = Reg(Vec(4, UInt(32.W))) // Register of 32-bit UInts regOfVec(0) := 123.U // Assignments to elements of the Vec regOfVec(1) := 456.U regOfVec(2) := 789.U regOfVec(3) := regOfVec(0) // Reg of Vec of 32-bit UInts initialized to zero // Note that Seq.fill constructs 4 32-bit UInt literals with the value 0 // VecInit(...) then constructs a Wire of these literals // The Reg is then initialized to the value of the Wire (which gives it the same type) val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W)))) } How do I partially reset an Aggregate Reg? The easiest way is to use a partially-specified Bundle Literal or Vec Literal to match the type of the Reg. 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. 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 How do I deal with aliased Bundle fields? Following the gen pattern when creating Bundles can result in some opaque error messages: class AliasedBundle[T <: Data](gen: T) extends Bundle { val foo = gen val bar = gen } getVerilogString(new Top(new AliasedBundle(UInt(8.W)))) // chisel3.AliasedAggregateFieldException: AliasedBundle contains aliased fields named (bar,foo) // at ... () // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:301) // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:301) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:301) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp17$Top.<init>(cookbook.md:301) // at repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:320) // at repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:320) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) This error is saying that fields foo and bar of AliasedBundle are the exact same object in memory. This is a problem for Chisel because we need to be able to distinguish uses of foo and bar but cannot when they are referentially the same. Note that the following example looks different but will give you exactly the same issue: class AlsoAliasedBundle[T <: Data](val gen: T) extends Bundle { // ^ This val makes `gen` a field, just like `foo` val foo = gen } By making gen a val, it becomes a public field of the class, just like foo. getVerilogString(new Top(new AlsoAliasedBundle(UInt(8.W)))) // chisel3.AliasedAggregateFieldException: AlsoAliasedBundle contains aliased fields named (foo,gen) // at ... () // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:301) // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:301) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:301) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp17$Top.<init>(cookbook.md:301) // at repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:339) // at repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:339) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) There are several ways to solve this issue with their own advantages and disadvantages. 1. 0-arity function parameters Instead of passing an object as a parameter, you can pass a 0-arity function (a function with no arguments): class UsingAFunctionBundle[T <: Data](gen: () => T) extends Bundle { val foo = gen() val bar = gen() } Note that the type of gen is now () => T. Because it is now a function and not a subtype of Data, you can safely make gen a val without it becoming a hardware field of the Bundle. Note that this also means you must pass gen as a function, for example: getVerilogString(new Top(new UsingAFunctionBundle(() => UInt(8.W)))) Warning: you must ensure that gen creates fresh objects rather than capturing an already constructed value: class MisusedFunctionArguments extends Module { // This usage is correct val in = IO(Input(new UsingAFunctionBundle(() => UInt(8.W)))) // This usage is incorrect val fizz = UInt(8.W) val out = IO(Output(new UsingAFunctionBundle(() => fizz))) } getVerilogString(new MisusedFunctionArguments) // chisel3.AutoClonetypeException: The bundle plugin was unable to clone UsingAFunctionBundle that has field 'foo' aliased with base UsingAFunctionBundle.This likely happened because you tried nesting Data arguments inside of other data structures. Try wrapping the field(s) in Input(...), Output(...), or Flipped(...) if appropriate. As a last resort, you can call chisel3.reflect.DataMirror.internal.chiselTypeClone on any nested Data arguments. See the cookbook entry 'How do I deal with the \"unable to clone\" error?' for more details. // at ... () // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:370) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:370) // at chisel3.IO$.apply(IO.scala:34) // at chisel3.experimental.BaseModule.IO(Module.scala:736) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:370) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:370) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md:370) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1.<init>(cookbook.md:370) // at repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:372) // at repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:372) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) In the above example, value fizz and fields foo and bar of out are all the same object in memory. 2. By-name function parameters Functionally the same as (1) but with more subtle syntax, you can use Scala by-name function parameters: class UsingByNameParameters[T <: Data](gen: => T) extends Bundle { val foo = gen val bar = gen } With this usage, you do not include () => when passing the argument: getVerilogString(new Top(new UsingByNameParameters(UInt(8.W)))) Note that as this is just syntactic sugar over (1), the same warning applies. 3. Directioned Bundle fields You can alternatively wrap the fields with Output(...), which creates fresh instances of the passed argument. Chisel treats Output as the “default direction” so if all fields are outputs, the Bundle is functionally equivalent to a Bundle with no directioned fields. class DirectionedBundle[T <: Data](gen: T) extends Bundle { val foo = Output(gen) val bar = Output(gen) } This approach is admittedly a little ugly and may mislead others reading the code because it implies that this Bundle is intended to be used as an Output. 4. Call .cloneType directly You can also just call .cloneType on your gen argument directly. While we try to hide this implementation detail from the user, .cloneType is the mechanism by which Chisel creates fresh instances of Data objects: class UsingCloneTypeBundle[T <: Data](gen: T) extends Bundle { val foo = gen.cloneType val bar = gen.cloneType } How do I deal with the “unable to clone” error? Most Chisel objects need to be cloned in order to differentiate between the software representation of the bundle field from its “bound” hardware representation, where “binding” is the process of generating a hardware component. For Bundle fields, this cloning is supposed to happen automatically with a compiler plugin. In some cases though, the plugin may not be able to clone the Bundle fields. The most common case for when this happens is when the chisel3.Data part of the Bundle field is nested inside some other data structure and the compiler plugin is unable to figure out how to clone the entire structure. It is best to avoid such nested structures. There are a few ways around this issue - you can try wrapping the problematic fields in Input(…), Output(…), or Flipped(…) if appropriate. You can also try manually cloning each field in the Bundle using the chiselTypeClone method in chisel3.reflect.DataMirror. Here’s an example with the Bundle whose fields won’t get cloned: class CustomBundleBroken(elts: (String, Data)*) extends Record { val elements = ListMap(elts: _*) def apply(elt: String): Data = elements(elt) } class NewModule extends Module { val out = Output(UInt(8.W)) val recordType = new CustomBundleBroken(\"fizz\" -> UInt(16.W), \"buzz\" -> UInt(16.W)) val record = Wire(recordType) val uint = record.asUInt val record2 = uint.asTypeOf(recordType) out := record } getVerilogString(new NewModule) // chisel3.AutoClonetypeException: The bundle plugin was unable to clone CustomBundleBroken$1 that has field 'fizz' aliased with base CustomBundleBroken$1.This likely happened because you tried nesting Data arguments inside of other data structures. Try wrapping the field(s) in Input(...), Output(...), or Flipped(...) if appropriate. As a last resort, you can call chisel3.reflect.DataMirror.internal.chiselTypeClone on any nested Data arguments. See the cookbook entry 'How do I deal with the \"unable to clone\" error?' for more details. // at ... () // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:444) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:444) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md:444) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1.<init>(cookbook.md:444) // at repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:449) // at repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:449) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) You can use chiselTypeClone to clone the elements as: import chisel3.reflect.DataMirror import chisel3.experimental.requireIsChiselType class CustomBundleFixed(elts: (String, Data)*) extends Record { val elements = ListMap(elts.map { case (field, elt) => requireIsChiselType(elt) field -> DataMirror.internal.chiselTypeClone(elt) }: _*) def apply(elt: String): Data = elements(elt) } How do I create a finite state machine (FSM)? The advised way is to use ChiselEnum to construct enumerated types representing the state of the FSM. State transitions are then handled with switch/is and when/.elsewhen/.otherwise. import chisel3._ import chisel3.util.{switch, is} object DetectTwoOnes { object State extends ChiselEnum { val sNone, sOne1, sTwo1s = Value } } /* This FSM detects two 1's one after the other */ class DetectTwoOnes extends Module { import DetectTwoOnes.State import DetectTwoOnes.State._ val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) val state = Output(State()) }) val state = RegInit(sNone) io.out := (state === sTwo1s) io.state := state switch (state) { is (sNone) { when (io.in) { state := sOne1 } } is (sOne1) { when (io.in) { state := sTwo1s } .otherwise { state := sNone } } is (sTwo1s) { when (!io.in) { state := sNone } } } } Note: the is statement can take multiple conditions e.g. is (sTwo1s, sOne1) { ... }. How do I unpack a value (“reverse concatenation”) like in Verilog? In Verilog, you can do something like the following which will unpack a the value z: wire [1:0] a; wire [3:0] b; wire [2:0] c; wire [8:0] z = [...]; assign {a,b,c} = z; Unpacking often corresponds to reinterpreting an unstructured data type as a structured data type. Frequently, this structured type is used prolifically in the design, and has been declared as in the following example: import chisel3._ class MyBundle extends Bundle { val a = UInt(2.W) val b = UInt(4.W) val c = UInt(3.W) } The easiest way to accomplish this in Chisel would be: class Foo extends Module { val z = Wire(UInt(9.W)) z := DontCare // This is a dummy connection val unpacked = z.asTypeOf(new MyBundle) printf(\"%d\", unpacked.a) printf(\"%d\", unpacked.b) printf(\"%d\", unpacked.c) } If you really need to do this for a one-off case (Think thrice! It is likely you can better structure the code using bundles), then rocket-chip has a Split utility which can accomplish this. How do I do subword assignment (assign to some bits in a UInt)? You may try to do something like the following where you want to assign only some bits of a Chisel type. Below, the left-hand side connection to io.out(0) is not allowed. import chisel3._ import circt.stage.ChiselStage class Foo extends Module { val io = IO(new Bundle { val bit = Input(Bool()) val out = Output(UInt(10.W)) }) io.out(0) := io.bit } If you try to compile this, you will get an error. getVerilogString(new Foo) // chisel3.package$ChiselException: Cannot reassign to read-only Foo.?: OpResult[Bool] // at ... () // at repl.MdocSession$MdocApp26$Foo.<init>(cookbook.md:589) // at repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:597) // at repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:597) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace) Chisel3 does not support subword assignment. The reason for this is that subword assignment generally hints at a better abstraction with an aggregate/structured types, i.e., a Bundle or a Vec. If you must express it this way, one approach is to blast your UInt to a Vec of Bool and back: import chisel3._ class Foo extends Module { val io = IO(new Bundle { val in = Input(UInt(10.W)) val bit = Input(Bool()) val out = Output(UInt(10.W)) }) val bools = VecInit(io.in.asBools) bools(0) := io.bit io.out := bools.asUInt } How do I create an optional I/O? The following example is a module which includes the optional port out2 only if the given parameter is true. import chisel3._ class ModuleWithOptionalIOs(flag: Boolean) extends Module { val io = IO(new Bundle { val in = Input(UInt(12.W)) val out = Output(UInt(12.W)) val out2 = if (flag) Some(Output(UInt(12.W))) else None }) io.out := io.in if (flag) { io.out2.get := io.in } } The following is an example where an entire IO is optional: import chisel3._ class ModuleWithOptionalIO(flag: Boolean) extends Module { val in = if (flag) Some(IO(Input(Bool()))) else None val out = IO(Output(Bool())) out := in.getOrElse(false.B) } How do I create I/O without a prefix? In most cases, you can simply call IO multiple times: import chisel3._ class MyModule extends Module { val in = IO(Input(UInt(8.W))) val out = IO(Output(UInt(8.W))) out := in +% 1.U } // Generated by CIRCT firtool-1.57.1 module MyModule( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 input [7:0] in, // cookbook.md:692:14 output [7:0] out // cookbook.md:693:15 ); assign out = in + 8'h1; // <stdin>:3:3, cookbook.md:695:13 endmodule If you have a Bundle from which you would like to create ports without the normal val prefix, you can use FlatIO: import chisel3._ import chisel3.experimental.FlatIO class MyBundle extends Bundle { val foo = Input(UInt(8.W)) val bar = Output(UInt(8.W)) } class MyModule extends Module { val io = FlatIO(new MyBundle) io.bar := io.foo +% 1.U } Note that io_ is nowhere to be seen! // Generated by CIRCT firtool-1.57.1 module MyModule( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 input [7:0] foo, // cookbook.md:724:18 output [7:0] bar // cookbook.md:724:18 ); assign bar = foo + 8'h1; // <stdin>:3:3, cookbook.md:726:20 endmodule How do I minimize the number of bits used in an output vector? Use inferred width and a Seq instead of a Vec: Consider: import chisel3._ // Count the number of set bits up to and including each bit position class CountBits(width: Int) extends Module { val bits = IO(Input(UInt(width.W))) val countSequence = Seq.tabulate(width)(i => IO(Output(UInt()))) val countVector = IO(Output(Vec(width, UInt()))) countSequence.zipWithIndex.foreach { case (port, i) => port := util.PopCount(bits(i, 0)) } countVector := countSequence } Unlike Vecs which represent a singular Chisel type and must have the same width for every element, Seq is a purely Scala construct, so their elements are independent from the perspective of Chisel and can have different widths. // Generated by CIRCT firtool-1.57.1 module CountBits( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 input [3:0] bits, // cookbook.md:746:16 output countSequence_0, // cookbook.md:747:50 output [1:0] countSequence_1, // cookbook.md:747:50 countSequence_2, // cookbook.md:747:50 output [2:0] countSequence_3, // cookbook.md:747:50 countVector_0, // cookbook.md:748:23 countVector_1, // cookbook.md:748:23 countVector_2, // cookbook.md:748:23 countVector_3 // cookbook.md:748:23 ); How do I resolve “Dynamic index … is too wide/narrow for extractee …”? Chisel will warn if a dynamic index is not the correctly-sized width for indexing a Vec or UInt. “Correctly-sized” means that the width of the index should be the log2 of the size of the indexee. If the indexee is a non-power-of-2 size, use the ceiling of the log2 result. When the index does not have enough bits to address all entries or bits in the extractee, you can .pad the index to increase the width. class TooNarrow extends RawModule { val extractee = Wire(UInt(7.W)) val index = Wire(UInt(2.W)) extractee(index) } compile(new TooNarrow) // [warn] cookbook.md 788:12: [W003] Dynamic index with width 2 is too small for extractee of width 7 // [warn] There were 1 warning(s) during hardware elaboration. This can be fixed with pad: class TooNarrowFixed extends RawModule { val extractee = Wire(UInt(7.W)) val index = Wire(UInt(2.W)) extractee(index.pad(3)) } compile(new TooNarrowFixed) Use bit extraction when the index is too wide class TooWide extends RawModule { val extractee = Wire(Vec(8, UInt(32.W))) val index = Wire(UInt(4.W)) extractee(index) } compile(new TooWide) // [warn] cookbook.md 814:12: [W004] Dynamic index with width 4 is too wide for Vec of size 8 (expected index width 3). // [warn] There were 1 warning(s) during hardware elaboration. This can be fixed with bit extraction: class TooWideFixed extends RawModule { val extractee = Wire(Vec(8, UInt(32.W))) val index = Wire(UInt(4.W)) extractee(index(2, 0)) } compile(new TooWideFixed) Note that size 1 Vecs and UInts should be indexed by a zero-width UInt: class SizeOneVec extends RawModule { val extractee = Wire(Vec(1, UInt(32.W))) val index = Wire(UInt(0.W)) extractee(index) } compile(new SizeOneVec) Because pad only pads if the desired width is less than the current width of the argument, you can use pad in conjunction with bit extraction when the widths may be too wide or too narrow under different circumstances import chisel3.util.log2Ceil class TooWideOrNarrow(extracteeSize: Int, indexWidth: Int) extends Module { val extractee = Wire(Vec(extracteeSize, UInt(8.W))) val index = Wire(UInt(indexWidth.W)) val correctWidth = log2Ceil(extracteeSize) extractee(index.pad(correctWidth)(correctWidth - 1, 0)) } compile(new TooWideOrNarrow(8, 2)) compile(new TooWideOrNarrow(8, 4)) Another option for dynamic bit selection of UInts (but not Vec dynamic indexing) is to do a dynamic right shift of the extractee by the index and then just bit select a single bit: class TooWideOrNarrowUInt(extracteeSize: Int, indexWidth: Int) extends Module { val extractee = Wire(UInt(extracteeSize.W)) val index = Wire(UInt(indexWidth.W)) (extractee >> index)(0) } compile(new TooWideOrNarrowUInt(8, 2)) compile(new TooWideOrNarrowUInt(8, 4)) Predictable Naming How do I get Chisel to name signals properly in blocks like when/withClockAndReset? Use the compiler plugin, and check out the Naming Cookbook if that still does not do what you want. How do I get Chisel to name the results of vector reads properly? Currently, name information is lost when using dynamic indexing. For example: import chisel3._ class Foo extends Module { val io = IO(new Bundle { val in = Input(Vec(4, Bool())) val idx = Input(UInt(2.W)) val en = Input(Bool()) val out = Output(Bool()) }) val x = io.in(io.idx) val y = x && io.en io.out := y } The above code loses the x name, instead using _GEN_3 (the other _GEN_* signals are expected). {% raw %} // Generated by CIRCT firtool-1.57.1 module Foo( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 io_in_0, // cookbook.md:893:14 io_in_1, // cookbook.md:893:14 io_in_2, // cookbook.md:893:14 io_in_3, // cookbook.md:893:14 input [1:0] io_idx, // cookbook.md:893:14 input io_en, // cookbook.md:893:14 output io_out // cookbook.md:893:14 ); wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}}; // cookbook.md:901:13 assign io_out = _GEN[io_idx] & io_en; // <stdin>:3:3, cookbook.md:901:13 endmodule {% endraw %} This can be worked around by creating a wire and connecting the dynamic index to the wire: val x = WireInit(io.in(io.idx)) Which produces: {% raw %} // Generated by CIRCT firtool-1.57.1 module Foo2( // <stdin>:3:3 input clock, // <stdin>:4:11 reset, // <stdin>:5:11 io_in_0, // cookbook.md:916:14 io_in_1, // cookbook.md:916:14 io_in_2, // cookbook.md:916:14 io_in_3, // cookbook.md:916:14 input [1:0] io_idx, // cookbook.md:916:14 input io_en, // cookbook.md:916:14 output io_out // cookbook.md:916:14 ); wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}}; // cookbook.md:923:19 assign io_out = _GEN[io_idx] & io_en; // <stdin>:3:3, cookbook.md:923:19, :924:13 endmodule {% endraw %} How can I dynamically set/parametrize the name of a module? You can override the desiredName function. This works with normal Chisel modules and BlackBoxes. Example: import chisel3._ class Coffee extends BlackBox { val io = IO(new Bundle { val I = Input(UInt(32.W)) val O = Output(UInt(32.W)) }) override def desiredName = \"Tea\" } class Salt extends Module { val io = IO(new Bundle {}) val drink = Module(new Coffee) override def desiredName = \"SodiumMonochloride\" drink.io.I := 42.U } Elaborating the Chisel module Salt yields our “desired names” for Salt and Coffee in the output Verilog: // Generated by CIRCT firtool-1.57.1 // external module Tea module SodiumMonochloride( // <stdin>:8:3 input clock, // <stdin>:9:11 reset // <stdin>:10:11 ); Tea drink ( // cookbook.md:955:23 .I (32'h2A), // cookbook.md:958:16 .O (/* unused */) ); endmodule Directionality How do I strip directions from a bidirectional Bundle (or other Data)? Given a bidirectional port like a Decoupled, you will get an error if you try to connect it directly to a register: import chisel3._ import circt.stage.ChiselStage import chisel3.util.Decoupled class BadRegConnect extends Module { val io = IO(new Bundle { val enq = Decoupled(UInt(8.W)) }) val monitor = Reg(chiselTypeOf(io.enq)) monitor := io.enq } ChiselStage.emitSystemVerilog(new BadRegConnect) // circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: firtool returned a non-zero exit code. Note that this version of Chisel (0.0.0+1-de74d754-SNAPSHOT) was published against firtool version 1.57.1. // ------------------------------------------------------------------------------ // ExitCode: // 1 // STDOUT: // // STDERR: // cookbook.md:988:20: error: 'firrtl.reg' op result #0 must be a passive non-'const' base type that does not contain analog, but got '!firrtl.bundle<ready flip: uint<1>, valid: uint<1>, bits: uint<8>>' // cookbook.md:988:20: note: see current operation: %4 = \"firrtl.reg\"(%arg0) {annotations = [], name = \"monitor\", nameKind = #firrtl<name_kind interesting_name>} : (!firrtl.clock) -> !firrtl.bundle<ready flip: uint<1>, valid: uint<1>, bits: uint<8>> // // ------------------------------------------------------------------------------ While there is no construct to “strip direction” in Chisel3, wrapping a type in Output(...) (the default direction in Chisel3) will set all of the individual elements to output direction. This will have the desired result when used to construct a Register: import chisel3._ import circt.stage.ChiselStage import chisel3.util.Decoupled class CoercedRegConnect extends Module { val io = IO(new Bundle { val enq = Flipped(Decoupled(UInt(8.W))) }) // Make a Reg which contains all of the bundle's signals, regardless of their directionality val monitor = Reg(Output(chiselTypeOf(io.enq))) // Even though io.enq is bidirectional, := will drive all fields of monitor with the fields of io.enq monitor := io.enq }"
     } ,    
     {
       "title": "Cookbooks",
@@ -140,7 +140,7 @@ function prepareIdxAndDocMap() {
     {
       "title": "Hierarchy Cookbook",
       "url": "/chisel3/docs/cookbooks/hierarchy.html",
-      "content": "Hierarchy Cookbook How do I instantiate multiple instances with the same module parameterization, but avoid re-elaboration? How do I access internal fields of an instance? How do I make my parameters accessable from an instance? How do I reuse a previously elaborated module, if my new module has the same parameterization? How do I parameterize a module by its children instances? How do I use the new hierarchy-specific Select functions? How do I instantiate multiple instances with the same module parameterization? Prior to this package, Chisel users relied on deduplication in a FIRRTL compiler to combine structurally equivalent modules into one module (aka “deduplication”). This package introduces the following new APIs to enable multiply-instantiated modules directly in Chisel. Definition(...) enables elaborating a module, but does not actually instantiate that module. Instead, it returns a Definition class which represents that module’s definition. Instance(...) takes a Definition and instantiates it, returning an Instance object. Instantiate(...) provides an API similar to Module(...), except it uses Definition and Instance to only elaborate modules once for a given set of parameters. It returns an Instance object. Modules (classes or traits) which will be used with the Definition/Instance api should be marked with the @instantiable annotation at the class/trait definition. To make a Module’s members variables accessible from an Instance object, they must be annotated with the @public annotation. Note that this is only accessible from a Scala sense—this is not in and of itself a mechanism for cross-module references. Using Definition and Instance In the following example, use Definition, Instance, @instantiable and @public to create multiple instances of one specific parameterization of a module, AddOne. import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public} @instantiable class AddOne(width: Int) extends Module { @public val in = IO(Input(UInt(width.W))) @public val out = IO(Output(UInt(width.W))) out := in + 1.U } class AddTwo(width: Int) extends Module { val in = IO(Input(UInt(width.W))) val out = IO(Output(UInt(width.W))) val addOneDef = Definition(new AddOne(width)) val i0 = Instance(addOneDef) val i1 = Instance(addOneDef) i0.in := in i1.in := i0.out out := i1.out } // Generated by CIRCT firtool-1.57.1 module AddOne( // <stdin>:3:3 input [9:0] in, // hierarchy.md:16:23 output [9:0] out // hierarchy.md:17:23 ); assign out = in + 10'h1; // <stdin>:3:3, hierarchy.md:18:13 endmodule module AddTwo( // <stdin>:13:3 input clock, // <stdin>:14:11 reset, // <stdin>:15:11 input [9:0] in, // hierarchy.md:23:15 output [9:0] out // hierarchy.md:24:15 ); wire [9:0] _i0_out; // hierarchy.md:26:20 AddOne i0 ( // hierarchy.md:26:20 .in (in), .out (_i0_out) ); AddOne i1 ( // hierarchy.md:27:20 .in (_i0_out), // hierarchy.md:26:20 .out (out) ); endmodule Using Instantiate Similar to the above, the following example uses Instantiate to create multiple instances of AddOne. import chisel3.experimental.hierarchy.Instantiate class AddTwoInstantiate(width: Int) extends Module { val in = IO(Input(UInt(width.W))) val out = IO(Output(UInt(width.W))) val i0 = Instantiate(new AddOne(width)) val i1 = Instantiate(new AddOne(width)) i0.in := in i1.in := i0.out out := i1.out } // Generated by CIRCT firtool-1.57.1 module AddOne( // <stdin>:3:3 input [15:0] in, // hierarchy.md:16:23 output [15:0] out // hierarchy.md:17:23 ); assign out = in + 16'h1; // <stdin>:3:3, hierarchy.md:18:13 endmodule module AddTwoInstantiate( // <stdin>:13:3 input clock, // <stdin>:14:11 reset, // <stdin>:15:11 input [15:0] in, // hierarchy.md:47:15 output [15:0] out // hierarchy.md:48:15 ); wire [15:0] _i0_out; // hierarchy.md:49:23 AddOne i0 ( // hierarchy.md:49:23 .in (in), .out (_i0_out) ); AddOne i1 ( // hierarchy.md:50:23 .in (_i0_out), // hierarchy.md:49:23 .out (out) ); endmodule How do I access internal fields of an instance? You can mark internal members of a class or trait marked with @instantiable with the @public annotation. The requirements are that the field is publicly accessible, is a val or lazy val, and is a valid type. The list of valid types are: IsInstantiable IsLookupable Data BaseModule Iterable/Option containing a type that meets these requirements Basic type like String, Int, BigInt etc. To mark a superclass’s member as @public, use the following pattern (shown with val clock). import chisel3._ import chisel3.experimental.hierarchy.{instantiable, public} @instantiable class MyModule extends Module { @public val clock = clock } You’ll get the following error message for improperly marking something as @public: import chisel3._ import chisel3.experimental.hierarchy.{instantiable, public} object NotValidType @instantiable class MyModule extends Module { @public val x = NotValidType } // error: @public is only legal within a class or trait marked @instantiable, and only on vals of type Data, BaseModule, MemBase, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable, Option, Either, or Tuple2 // val x = circt.stage.ChiselStage.emitCHIRRTL(new Top) // ^ How do I make my parameters accessible from an instance? If an instance’s parameters are simple (e.g. Int, String etc.) they can be marked directly with @public. Often, parameters are more complicated and are contained in case classes. In such cases, mark the case class with the IsLookupable trait. This indicates to Chisel that instances of the IsLookupable class may be accessed from within instances. However, ensure that these parameters are true for all instances of a definition. For example, if our parameters contained an id field which was instance-specific but defaulted to zero, then the definition’s id would be returned for all instances. This change in behavior could lead to bugs if other code presumed the id field was correct. Thus, it is important that when converting normal modules to use this package, you are careful about what you mark as IsLookupable. In the following example, we added the trait IsLookupable to allow the member to be marked @public. import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, IsLookupable, public} case class MyCaseClass(width: Int) extends IsLookupable @instantiable class MyModule extends Module { @public val x = MyCaseClass(10) } class Top extends Module { val inst = Instance(Definition(new MyModule)) println(s\"Width is ${inst.x.width}\") } Width is 10 Circuit(Top,List(DefModule(repl.MdocSession$MdocApp5$MyModule@12261bf,MyModule,List(Port(MyModule.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(MyModule.reset: IO[Reset],Input,UnlocatableSourceInfo)),Vector()), DefModule(repl.MdocSession$MdocApp5$Top@181c5fa1,Top,List(Port(Top.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(Top.reset: IO[Bool],Input,UnlocatableSourceInfo)),Vector(DefInstance(SourceLine(hierarchy.md,112,22),ModuleClone(repl.MdocSession$MdocApp5$MyModule@12261bf),List(Port(MyModule.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(MyModule.reset: IO[Reset],Input,UnlocatableSourceInfo))), Connect(SourceLine(hierarchy.md,112,22),Node(MyModule.inst.clock: IO[Clock]),Node(Top.clock: IO[Clock])), Connect(SourceLine(hierarchy.md,112,22),Node(MyModule.inst.reset: IO[Reset]),Node(Top.reset: IO[Bool]))))),List(),firrtl.renamemap.package$MutableRenameMap@6ac5c699,List(),List(),List()) How do I look up parameters from a Definition, if I don’t want to instantiate it? Just like Instances, Definition’s also contain accessors for @public members. As such, you can directly access them: import chisel3._ import chisel3.experimental.hierarchy.{Definition, instantiable, public} @instantiable class AddOne(val width: Int) extends RawModule { @public val width = width @public val in = IO(Input(UInt(width.W))) @public val out = IO(Output(UInt(width.W))) out := in + 1.U } class Top extends Module { val definition = Definition(new AddOne(10)) println(s\"Width is: ${definition.width}\") } // Generated by CIRCT firtool-1.57.1 module Top( // <stdin>:11:3 input clock, // <stdin>:12:11 reset // <stdin>:13:11 ); endmodule How do I parameterize a module by its children instances? Prior to the introduction of this package, a parent module would have to pass all necessary parameters when instantiating a child module. This had the unfortunate consequence of requiring a parent’s parameters to always contain the child’s parameters, which was an unnecessary coupling which lead to some anti-patterns. Now, a parent can take a child Definition as an argument, and instantiate it directly. In addition, it can analyze the parameters used in the definition to parameterize itself. In a sense, now the child can actually parameterize the parent. In the following example, we create a definition of AddOne, and pass the definition to AddTwo. The width of the AddTwo ports are now derived from the parameterization of the AddOne instance. import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public} @instantiable class AddOne(val width: Int) extends Module { @public val width = width @public val in = IO(Input(UInt(width.W))) @public val out = IO(Output(UInt(width.W))) out := in + 1.U } class AddTwo(addOneDef: Definition[AddOne]) extends Module { val i0 = Instance(addOneDef) val i1 = Instance(addOneDef) val in = IO(Input(UInt(addOneDef.width.W))) val out = IO(Output(UInt(addOneDef.width.W))) i0.in := in i1.in := i0.out out := i1.out } // Generated by CIRCT firtool-1.57.1 module AddOne( // <stdin>:3:3 input [9:0] in, // hierarchy.md:184:23 output [9:0] out // hierarchy.md:185:23 ); assign out = in + 10'h1; // <stdin>:3:3, hierarchy.md:186:13 endmodule module AddTwo( // <stdin>:13:3 input clock, // <stdin>:14:11 reset, // <stdin>:15:11 input [9:0] in, // hierarchy.md:193:15 output [9:0] out // hierarchy.md:194:15 ); wire [9:0] _i0_out; // hierarchy.md:191:20 AddOne i0 ( // hierarchy.md:191:20 .in (in), .out (_i0_out) ); AddOne i1 ( // hierarchy.md:192:20 .in (_i0_out), // hierarchy.md:191:20 .out (out) ); endmodule How do I use the new hierarchy-specific Select functions? Select functions can be applied after a module has been elaborated, either in a Chisel Aspect or in a parent module applied to a child module. There are seven hierarchy-specific functions, which (with the exception of ios) either return Instance’s or Definition’s: instancesIn(parent): Return all instances directly instantiated locally within parent instancesOf[type](parent): Return all instances of provided type directly instantiated locally within parent allInstancesOf[type](root): Return all instances of provided type directly and indirectly instantiated, locally and deeply, starting from root definitionsIn: Return definitions of all instances directly instantiated locally within parent definitionsOf[type]: Return definitions of all instances of provided type directly instantiated locally within parent allDefinitionsOf[type]: Return all definitions of instances of provided type directly and indirectly instantiated, locally and deeply, starting from root ios: Returns all the I/Os of the provided definition or instance. To demonstrate this, consider the following. We mock up an example where we are using the Select.allInstancesOf and Select.allDefinitionsOf to annotate instances and the definition of EmptyModule. When converting the ChiselAnnotation to firrtl’s Annotation, we print out the resulting Target. As shown, despite EmptyModule actually only being elaborated once, we still provide different targets depending on how the instance or definition is selected. import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, Hierarchy, instantiable, public} import firrtl.annotations.{IsModule, NoTargetAnnotation} case object EmptyAnnotation extends NoTargetAnnotation case class MyChiselAnnotation(m: Hierarchy[RawModule], tag: String) extends experimental.ChiselAnnotation { def toFirrtl = { println(tag + \": \" + m.toTarget) EmptyAnnotation } } @instantiable class EmptyModule extends Module { println(\"Elaborating EmptyModule!\") } @instantiable class TwoEmptyModules extends Module { val definition = Definition(new EmptyModule) val i0 = Instance(definition) val i1 = Instance(definition) } class Top extends Module { val definition = Definition(new TwoEmptyModules) val instance = Instance(definition) aop.Select.allInstancesOf[EmptyModule](instance).foreach { i => experimental.annotate(MyChiselAnnotation(i, \"instance\")) } aop.Select.allDefinitionsOf[EmptyModule](instance).foreach { d => experimental.annotate(MyChiselAnnotation(d, \"definition\")) } } Elaborating EmptyModule! instance: ~Top|Top/instance:TwoEmptyModules/i0:EmptyModule instance: ~Top|Top/instance:TwoEmptyModules/i1:EmptyModule definition: ~Top|EmptyModule You can also use Select.ios on either a Definition or an Instance to annotate the I/Os appropriately: case class MyIOAnnotation(m: Data, tag: String) extends experimental.ChiselAnnotation { def toFirrtl = { println(tag + \": \" + m.toTarget) EmptyAnnotation } } @instantiable class InOutModule extends Module { @public val in = IO(Input(Bool())) @public val out = IO(Output(Bool())) out := in } @instantiable class TwoInOutModules extends Module { val in = IO(Input(Bool())) val out = IO(Output(Bool())) val definition = Definition(new InOutModule) val i0 = Instance(definition) val i1 = Instance(definition) i0.in := in i1.in := i0.out out := i1.out } class InOutTop extends Module { val definition = Definition(new TwoInOutModules) val instance = Instance(definition) aop.Select.allInstancesOf[InOutModule](instance).foreach { i => aop.Select.ios(i).foreach { io => experimental.annotate(MyIOAnnotation(io, \"instance io\")) }} aop.Select.allDefinitionsOf[InOutModule](instance).foreach { d => aop.Select.ios(d).foreach {io => experimental.annotate(MyIOAnnotation(io, \"definition io\")) }} } instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>clock instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>reset instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>in instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>out instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>clock instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>reset instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>in instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>out definition io: ~InOutTop|InOutModule>clock definition io: ~InOutTop|InOutModule>reset definition io: ~InOutTop|InOutModule>in definition io: ~InOutTop|InOutModule>out"
+      "content": "Hierarchy Cookbook How do I instantiate multiple instances with the same module parameterization, but avoid re-elaboration? How do I access internal fields of an instance? How do I make my parameters accessable from an instance? How do I reuse a previously elaborated module, if my new module has the same parameterization? How do I parameterize a module by its children instances? How do I use the new hierarchy-specific Select functions? How do I instantiate multiple instances with the same module parameterization? Prior to this package, Chisel users relied on deduplication in a FIRRTL compiler to combine structurally equivalent modules into one module (aka “deduplication”). This package introduces the following new APIs to enable multiply-instantiated modules directly in Chisel. Definition(...) enables elaborating a module, but does not actually instantiate that module. Instead, it returns a Definition class which represents that module’s definition. Instance(...) takes a Definition and instantiates it, returning an Instance object. Instantiate(...) provides an API similar to Module(...), except it uses Definition and Instance to only elaborate modules once for a given set of parameters. It returns an Instance object. Modules (classes or traits) which will be used with the Definition/Instance api should be marked with the @instantiable annotation at the class/trait definition. To make a Module’s members variables accessible from an Instance object, they must be annotated with the @public annotation. Note that this is only accessible from a Scala sense—this is not in and of itself a mechanism for cross-module references. Using Definition and Instance In the following example, use Definition, Instance, @instantiable and @public to create multiple instances of one specific parameterization of a module, AddOne. import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public} @instantiable class AddOne(width: Int) extends Module { @public val in = IO(Input(UInt(width.W))) @public val out = IO(Output(UInt(width.W))) out := in + 1.U } class AddTwo(width: Int) extends Module { val in = IO(Input(UInt(width.W))) val out = IO(Output(UInt(width.W))) val addOneDef = Definition(new AddOne(width)) val i0 = Instance(addOneDef) val i1 = Instance(addOneDef) i0.in := in i1.in := i0.out out := i1.out } // Generated by CIRCT firtool-1.57.1 module AddOne( // <stdin>:3:3 input [9:0] in, // hierarchy.md:16:23 output [9:0] out // hierarchy.md:17:23 ); assign out = in + 10'h1; // <stdin>:3:3, hierarchy.md:18:13 endmodule module AddTwo( // <stdin>:13:3 input clock, // <stdin>:14:11 reset, // <stdin>:15:11 input [9:0] in, // hierarchy.md:23:15 output [9:0] out // hierarchy.md:24:15 ); wire [9:0] _i0_out; // hierarchy.md:26:20 AddOne i0 ( // hierarchy.md:26:20 .in (in), .out (_i0_out) ); AddOne i1 ( // hierarchy.md:27:20 .in (_i0_out), // hierarchy.md:26:20 .out (out) ); endmodule Using Instantiate Similar to the above, the following example uses Instantiate to create multiple instances of AddOne. import chisel3.experimental.hierarchy.Instantiate class AddTwoInstantiate(width: Int) extends Module { val in = IO(Input(UInt(width.W))) val out = IO(Output(UInt(width.W))) val i0 = Instantiate(new AddOne(width)) val i1 = Instantiate(new AddOne(width)) i0.in := in i1.in := i0.out out := i1.out } // Generated by CIRCT firtool-1.57.1 module AddOne( // <stdin>:3:3 input [15:0] in, // hierarchy.md:16:23 output [15:0] out // hierarchy.md:17:23 ); assign out = in + 16'h1; // <stdin>:3:3, hierarchy.md:18:13 endmodule module AddTwoInstantiate( // <stdin>:13:3 input clock, // <stdin>:14:11 reset, // <stdin>:15:11 input [15:0] in, // hierarchy.md:47:15 output [15:0] out // hierarchy.md:48:15 ); wire [15:0] _i0_out; // hierarchy.md:49:23 AddOne i0 ( // hierarchy.md:49:23 .in (in), .out (_i0_out) ); AddOne i1 ( // hierarchy.md:50:23 .in (_i0_out), // hierarchy.md:49:23 .out (out) ); endmodule How do I access internal fields of an instance? You can mark internal members of a class or trait marked with @instantiable with the @public annotation. The requirements are that the field is publicly accessible, is a val or lazy val, and is a valid type. The list of valid types are: IsInstantiable IsLookupable Data BaseModule Iterable/Option containing a type that meets these requirements Basic type like String, Int, BigInt etc. To mark a superclass’s member as @public, use the following pattern (shown with val clock). import chisel3._ import chisel3.experimental.hierarchy.{instantiable, public} @instantiable class MyModule extends Module { @public val clock = clock } You’ll get the following error message for improperly marking something as @public: import chisel3._ import chisel3.experimental.hierarchy.{instantiable, public} object NotValidType @instantiable class MyModule extends Module { @public val x = NotValidType } // error: @public is only legal within a class or trait marked @instantiable, and only on vals of type Data, BaseModule, MemBase, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable, Option, Either, or Tuple2 // val x = circt.stage.ChiselStage.emitCHIRRTL(new Top) // ^ How do I make my parameters accessible from an instance? If an instance’s parameters are simple (e.g. Int, String etc.) they can be marked directly with @public. Often, parameters are more complicated and are contained in case classes. In such cases, mark the case class with the IsLookupable trait. This indicates to Chisel that instances of the IsLookupable class may be accessed from within instances. However, ensure that these parameters are true for all instances of a definition. For example, if our parameters contained an id field which was instance-specific but defaulted to zero, then the definition’s id would be returned for all instances. This change in behavior could lead to bugs if other code presumed the id field was correct. Thus, it is important that when converting normal modules to use this package, you are careful about what you mark as IsLookupable. In the following example, we added the trait IsLookupable to allow the member to be marked @public. import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, IsLookupable, public} case class MyCaseClass(width: Int) extends IsLookupable @instantiable class MyModule extends Module { @public val x = MyCaseClass(10) } class Top extends Module { val inst = Instance(Definition(new MyModule)) println(s\"Width is ${inst.x.width}\") } Width is 10 Circuit(Top,List(DefModule(repl.MdocSession$MdocApp5$MyModule@21c3264,MyModule,List(Port(MyModule.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(MyModule.reset: IO[Reset],Input,UnlocatableSourceInfo)),Vector()), DefModule(repl.MdocSession$MdocApp5$Top@79562b81,Top,List(Port(Top.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(Top.reset: IO[Bool],Input,UnlocatableSourceInfo)),Vector(DefInstance(SourceLine(hierarchy.md,112,22),ModuleClone(repl.MdocSession$MdocApp5$MyModule@21c3264),List(Port(MyModule.clock: IO[Clock],Input,UnlocatableSourceInfo), Port(MyModule.reset: IO[Reset],Input,UnlocatableSourceInfo))), Connect(SourceLine(hierarchy.md,112,22),Node(MyModule.inst.clock: IO[Clock]),Node(Top.clock: IO[Clock])), Connect(SourceLine(hierarchy.md,112,22),Node(MyModule.inst.reset: IO[Reset]),Node(Top.reset: IO[Bool]))))),List(),firrtl.renamemap.package$MutableRenameMap@3ff9aa93,List(),List(),List()) How do I look up parameters from a Definition, if I don’t want to instantiate it? Just like Instances, Definition’s also contain accessors for @public members. As such, you can directly access them: import chisel3._ import chisel3.experimental.hierarchy.{Definition, instantiable, public} @instantiable class AddOne(val width: Int) extends RawModule { @public val width = width @public val in = IO(Input(UInt(width.W))) @public val out = IO(Output(UInt(width.W))) out := in + 1.U } class Top extends Module { val definition = Definition(new AddOne(10)) println(s\"Width is: ${definition.width}\") } // Generated by CIRCT firtool-1.57.1 module Top( // <stdin>:11:3 input clock, // <stdin>:12:11 reset // <stdin>:13:11 ); endmodule How do I parameterize a module by its children instances? Prior to the introduction of this package, a parent module would have to pass all necessary parameters when instantiating a child module. This had the unfortunate consequence of requiring a parent’s parameters to always contain the child’s parameters, which was an unnecessary coupling which lead to some anti-patterns. Now, a parent can take a child Definition as an argument, and instantiate it directly. In addition, it can analyze the parameters used in the definition to parameterize itself. In a sense, now the child can actually parameterize the parent. In the following example, we create a definition of AddOne, and pass the definition to AddTwo. The width of the AddTwo ports are now derived from the parameterization of the AddOne instance. import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public} @instantiable class AddOne(val width: Int) extends Module { @public val width = width @public val in = IO(Input(UInt(width.W))) @public val out = IO(Output(UInt(width.W))) out := in + 1.U } class AddTwo(addOneDef: Definition[AddOne]) extends Module { val i0 = Instance(addOneDef) val i1 = Instance(addOneDef) val in = IO(Input(UInt(addOneDef.width.W))) val out = IO(Output(UInt(addOneDef.width.W))) i0.in := in i1.in := i0.out out := i1.out } // Generated by CIRCT firtool-1.57.1 module AddOne( // <stdin>:3:3 input [9:0] in, // hierarchy.md:184:23 output [9:0] out // hierarchy.md:185:23 ); assign out = in + 10'h1; // <stdin>:3:3, hierarchy.md:186:13 endmodule module AddTwo( // <stdin>:13:3 input clock, // <stdin>:14:11 reset, // <stdin>:15:11 input [9:0] in, // hierarchy.md:193:15 output [9:0] out // hierarchy.md:194:15 ); wire [9:0] _i0_out; // hierarchy.md:191:20 AddOne i0 ( // hierarchy.md:191:20 .in (in), .out (_i0_out) ); AddOne i1 ( // hierarchy.md:192:20 .in (_i0_out), // hierarchy.md:191:20 .out (out) ); endmodule How do I use the new hierarchy-specific Select functions? Select functions can be applied after a module has been elaborated, either in a Chisel Aspect or in a parent module applied to a child module. There are seven hierarchy-specific functions, which (with the exception of ios) either return Instance’s or Definition’s: instancesIn(parent): Return all instances directly instantiated locally within parent instancesOf[type](parent): Return all instances of provided type directly instantiated locally within parent allInstancesOf[type](root): Return all instances of provided type directly and indirectly instantiated, locally and deeply, starting from root definitionsIn: Return definitions of all instances directly instantiated locally within parent definitionsOf[type]: Return definitions of all instances of provided type directly instantiated locally within parent allDefinitionsOf[type]: Return all definitions of instances of provided type directly and indirectly instantiated, locally and deeply, starting from root ios: Returns all the I/Os of the provided definition or instance. To demonstrate this, consider the following. We mock up an example where we are using the Select.allInstancesOf and Select.allDefinitionsOf to annotate instances and the definition of EmptyModule. When converting the ChiselAnnotation to firrtl’s Annotation, we print out the resulting Target. As shown, despite EmptyModule actually only being elaborated once, we still provide different targets depending on how the instance or definition is selected. import chisel3._ import chisel3.experimental.hierarchy.{Definition, Instance, Hierarchy, instantiable, public} import firrtl.annotations.{IsModule, NoTargetAnnotation} case object EmptyAnnotation extends NoTargetAnnotation case class MyChiselAnnotation(m: Hierarchy[RawModule], tag: String) extends experimental.ChiselAnnotation { def toFirrtl = { println(tag + \": \" + m.toTarget) EmptyAnnotation } } @instantiable class EmptyModule extends Module { println(\"Elaborating EmptyModule!\") } @instantiable class TwoEmptyModules extends Module { val definition = Definition(new EmptyModule) val i0 = Instance(definition) val i1 = Instance(definition) } class Top extends Module { val definition = Definition(new TwoEmptyModules) val instance = Instance(definition) aop.Select.allInstancesOf[EmptyModule](instance).foreach { i => experimental.annotate(MyChiselAnnotation(i, \"instance\")) } aop.Select.allDefinitionsOf[EmptyModule](instance).foreach { d => experimental.annotate(MyChiselAnnotation(d, \"definition\")) } } Elaborating EmptyModule! instance: ~Top|Top/instance:TwoEmptyModules/i0:EmptyModule instance: ~Top|Top/instance:TwoEmptyModules/i1:EmptyModule definition: ~Top|EmptyModule You can also use Select.ios on either a Definition or an Instance to annotate the I/Os appropriately: case class MyIOAnnotation(m: Data, tag: String) extends experimental.ChiselAnnotation { def toFirrtl = { println(tag + \": \" + m.toTarget) EmptyAnnotation } } @instantiable class InOutModule extends Module { @public val in = IO(Input(Bool())) @public val out = IO(Output(Bool())) out := in } @instantiable class TwoInOutModules extends Module { val in = IO(Input(Bool())) val out = IO(Output(Bool())) val definition = Definition(new InOutModule) val i0 = Instance(definition) val i1 = Instance(definition) i0.in := in i1.in := i0.out out := i1.out } class InOutTop extends Module { val definition = Definition(new TwoInOutModules) val instance = Instance(definition) aop.Select.allInstancesOf[InOutModule](instance).foreach { i => aop.Select.ios(i).foreach { io => experimental.annotate(MyIOAnnotation(io, \"instance io\")) }} aop.Select.allDefinitionsOf[InOutModule](instance).foreach { d => aop.Select.ios(d).foreach {io => experimental.annotate(MyIOAnnotation(io, \"definition io\")) }} } instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>clock instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>reset instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>in instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>out instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>clock instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>reset instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>in instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>out definition io: ~InOutTop|InOutModule>clock definition io: ~InOutTop|InOutModule>reset definition io: ~InOutTop|InOutModule>in definition io: ~InOutTop|InOutModule>out"
     } ,                
     {
       "title": "Chisel API Documentation",