diff --git a/api/chisel3/latest.html b/api/chisel3/latest.html
index b5453befb7..2a4a1b8cb1 100644
--- a/api/chisel3/latest.html
+++ b/api/chisel3/latest.html
@@ -4,7 +4,7 @@
Chisel
-
+
diff --git a/assets/js/1ce89024.232f983b.js b/assets/js/1ce89024.232f983b.js
new file mode 100644
index 0000000000..40edd49b31
--- /dev/null
+++ b/assets/js/1ce89024.232f983b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[741],{3519:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>r});var t=i(4848),o=i(8453),a=i(1871);const s={sidebar_position:2},l="Hierarchy Cookbook",c={id:"cookbooks/hierarchy",title:"Hierarchy Cookbook",description:"How do I instantiate multiple instances with the same module parameterization?",source:"@site/docs/cookbooks/hierarchy.md",sourceDirName:"cookbooks",slug:"/cookbooks/hierarchy",permalink:"/docs/cookbooks/hierarchy",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/cookbooks/hierarchy.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"chiselSidebar",previous:{title:"Naming Cookbook",permalink:"/docs/cookbooks/naming"},next:{title:"DataView Cookbook",permalink:"/docs/cookbooks/dataview"}},d={},r=[{value:"How do I instantiate multiple instances with the same module parameterization?",id:"how-do-i-instantiate-multiple-instances-with-the-same-module-parameterization",level:2},{value:"Using Definition and Instance",id:"using-definition-and-instance",level:3},{value:"Using Instantiate",id:"using-instantiate",level:3},{value:"How do I access internal fields of an instance?",id:"how-do-i-access-internal-fields-of-an-instance",level:2},{value:"How do I make my parameters accessible from an instance?",id:"how-do-i-make-my-parameters-accessible-from-an-instance",level:2},{value:"How do I look up parameters from a Definition, if I don't want to instantiate it?",id:"how-do-i-look-up-parameters-from-a-definition-if-i-dont-want-to-instantiate-it",level:2},{value:"How do I parameterize a module by its children instances?",id:"how-do-i-parameterize-a-module-by-its-children-instances",level:2},{value:"How do I use the new hierarchy-specific Select functions?",id:"how-do-i-use-the-new-hierarchy-specific-select-functions",level:2}];function u(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"hierarchy-cookbook",children:"Hierarchy Cookbook"})}),"\n","\n",(0,t.jsx)(a.A,{toc:r}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-instantiate-multiple-instances-with-the-same-module-parameterization",children:"How do I instantiate multiple instances with the same module parameterization?"}),"\n",(0,t.jsx)(n.p,{children:'Prior to this package, Chisel users relied on deduplication in a FIRRTL compiler to combine\nstructurally equivalent modules into one module (aka "deduplication").\nThis package introduces the following new APIs to enable multiply-instantiated modules directly in Chisel.'}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Definition(...)"})," enables elaborating a module, but does not actually instantiate that module.\nInstead, it returns a ",(0,t.jsx)(n.code,{children:"Definition"})," class which represents that module's definition."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Instance(...)"})," takes a ",(0,t.jsx)(n.code,{children:"Definition"})," and instantiates it, returning an ",(0,t.jsx)(n.code,{children:"Instance"})," object."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Instantiate(...)"})," provides an API similar to ",(0,t.jsx)(n.code,{children:"Module(...)"}),", except it uses\n",(0,t.jsx)(n.code,{children:"Definition"})," and ",(0,t.jsx)(n.code,{children:"Instance"})," to only elaborate modules once for a given set of\nparameters. It returns an ",(0,t.jsx)(n.code,{children:"Instance"})," object."]}),"\n",(0,t.jsxs)(n.p,{children:["Modules (classes or traits) which will be used with the ",(0,t.jsx)(n.code,{children:"Definition"}),"/",(0,t.jsx)(n.code,{children:"Instance"})," api should be marked\nwith the ",(0,t.jsx)(n.code,{children:"@instantiable"})," annotation at the class/trait definition."]}),"\n",(0,t.jsxs)(n.p,{children:["To make a Module's members variables accessible from an ",(0,t.jsx)(n.code,{children:"Instance"})," object, they must be annotated\nwith the ",(0,t.jsx)(n.code,{children:"@public"})," annotation. Note that this is only accessible from a Scala sense\u2014this is not\nin and of itself a mechanism for cross-module references."]}),"\n",(0,t.jsx)(n.h3,{id:"using-definition-and-instance",children:"Using Definition and Instance"}),"\n",(0,t.jsxs)(n.p,{children:["In the following example, use ",(0,t.jsx)(n.code,{children:"Definition"}),", ",(0,t.jsx)(n.code,{children:"Instance"}),", ",(0,t.jsx)(n.code,{children:"@instantiable"})," and ",(0,t.jsx)(n.code,{children:"@public"})," to create\nmultiple instances of one specific parameterization of a module, ",(0,t.jsx)(n.code,{children:"AddOne"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public}\n\n@instantiable\nclass AddOne(width: Int) extends Module {\n @public val in = IO(Input(UInt(width.W)))\n @public val out = IO(Output(UInt(width.W)))\n out := in + 1.U\n}\n\nclass AddTwo(width: Int) extends Module {\n val in = IO(Input(UInt(width.W)))\n val out = IO(Output(UInt(width.W)))\n val addOneDef = Definition(new AddOne(width))\n val i0 = Instance(addOneDef)\n val i1 = Instance(addOneDef)\n i0.in := in\n i1.in := i0.out\n out := i1.out\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule AddOne(\n input [9:0] in,\n output [9:0] out\n);\n\n assign out = in + 10'h1;\nendmodule\n\nmodule AddTwo(\n input clock,\n reset,\n input [9:0] in,\n output [9:0] out\n);\n\n wire [9:0] _i0_out;\n AddOne i0 (\n .in (in),\n .out (_i0_out)\n );\n AddOne i1 (\n .in (_i0_out),\n .out (out)\n );\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"using-instantiate",children:"Using Instantiate"}),"\n",(0,t.jsxs)(n.p,{children:["Similar to the above, the following example uses ",(0,t.jsx)(n.code,{children:"Instantiate"})," to create\nmultiple instances of ",(0,t.jsx)(n.code,{children:"AddOne"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.hierarchy.Instantiate\n\nclass AddTwoInstantiate(width: Int) extends Module {\n val in = IO(Input(UInt(width.W)))\n val out = IO(Output(UInt(width.W)))\n val i0 = Instantiate(new AddOne(width))\n val i1 = Instantiate(new AddOne(width))\n i0.in := in\n i1.in := i0.out\n out := i1.out\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule AddOne(\n input [15:0] in,\n output [15:0] out\n);\n\n assign out = in + 16'h1;\nendmodule\n\nmodule AddTwoInstantiate(\n input clock,\n reset,\n input [15:0] in,\n output [15:0] out\n);\n\n wire [15:0] _i0_out;\n AddOne i0 (\n .in (in),\n .out (_i0_out)\n );\n AddOne i1 (\n .in (_i0_out),\n .out (out)\n );\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-access-internal-fields-of-an-instance",children:"How do I access internal fields of an instance?"}),"\n",(0,t.jsxs)(n.p,{children:["You can mark internal members of a class or trait marked with ",(0,t.jsx)(n.code,{children:"@instantiable"})," with the ",(0,t.jsx)(n.code,{children:"@public"})," annotation.\nThe requirements are that the field is publicly accessible, is a ",(0,t.jsx)(n.code,{children:"val"})," or ",(0,t.jsx)(n.code,{children:"lazy val"}),", and is a valid type.\nThe list of valid types are:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"IsInstantiable"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"IsLookupable"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"Data"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"BaseModule"})}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Iterable"}),"/",(0,t.jsx)(n.code,{children:"Option "}),"containing a type that meets these requirements"]}),"\n",(0,t.jsxs)(n.li,{children:["Basic type like ",(0,t.jsx)(n.code,{children:"String"}),", ",(0,t.jsx)(n.code,{children:"Int"}),", ",(0,t.jsx)(n.code,{children:"BigInt"})," etc."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["To mark a superclass's member as ",(0,t.jsx)(n.code,{children:"@public"}),", use the following pattern (shown with ",(0,t.jsx)(n.code,{children:"val clock"}),")."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.hierarchy.{instantiable, public}\n\n@instantiable\nclass MyModule extends Module {\n @public val clock = clock\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["You'll get the following error message for improperly marking something as ",(0,t.jsx)(n.code,{children:"@public"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.hierarchy.{instantiable, public}\n\nobject NotValidType\n\n@instantiable\nclass MyModule extends Module {\n @public val x = NotValidType\n}\n// 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\n// val x = circt.stage.ChiselStage.emitCHIRRTL(new Top)\n// ^\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-make-my-parameters-accessible-from-an-instance",children:"How do I make my parameters accessible from an instance?"}),"\n",(0,t.jsxs)(n.p,{children:["If an instance's parameters are simple (e.g. ",(0,t.jsx)(n.code,{children:"Int"}),", ",(0,t.jsx)(n.code,{children:"String"})," etc.) they can be marked directly with ",(0,t.jsx)(n.code,{children:"@public"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Often, parameters are more complicated and are contained in case classes.\nIn such cases, mark the case class with the ",(0,t.jsx)(n.code,{children:"IsLookupable"})," trait.\nThis indicates to Chisel that instances of the ",(0,t.jsx)(n.code,{children:"IsLookupable"})," class may be accessed from within instances."]}),"\n",(0,t.jsxs)(n.p,{children:["However, ensure that these parameters are true for ",(0,t.jsx)(n.strong,{children:"all"})," instances of a definition.\nFor example, if our parameters contained an id field which was instance-specific but defaulted to zero,\nthen the definition's id would be returned for all instances.\nThis change in behavior could lead to bugs if other code presumed the id field was correct."]}),"\n",(0,t.jsxs)(n.p,{children:["Thus, it is important that when converting normal modules to use this package,\nyou are careful about what you mark as ",(0,t.jsx)(n.code,{children:"IsLookupable"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["In the following example, we added the trait ",(0,t.jsx)(n.code,{children:"IsLookupable"})," to allow the member to be marked ",(0,t.jsx)(n.code,{children:"@public"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, Instance, instantiable, IsLookupable, public}\n\ncase class MyCaseClass(width: Int) extends IsLookupable\n\n@instantiable\nclass MyModule extends Module {\n @public val x = MyCaseClass(10)\n}\n\nclass Top extends Module {\n val inst = Instance(Definition(new MyModule))\n println(s"Width is ${inst.x.width}")\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Width is 10\nCircuit(Top,List(DefModule(repl.MdocSession$MdocApp5$MyModule@5b93be84,MyModule,false,List(),List(Port(MyModule.clock: IO[Clock],Input,SourceLine(hierarchy.md,105,2)), Port(MyModule.reset: IO[Reset],Input,SourceLine(hierarchy.md,105,2))),Vector()), DefModule(repl.MdocSession$MdocApp5$Top@da69f3f,Top,true,List(),List(Port(Top.clock: IO[Clock],Input,SourceLine(hierarchy.md,111,7)), Port(Top.reset: IO[Bool],Input,SourceLine(hierarchy.md,111,7))),Vector(DefInstance(SourceLine(hierarchy.md,112,22),ModuleClone(repl.MdocSession$MdocApp5$MyModule@5b93be84),List(Port(MyModule.clock: IO[Clock],Input,SourceLine(hierarchy.md,105,2)), Port(MyModule.reset: IO[Reset],Input,SourceLine(hierarchy.md,105,2)))), 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@347d5612,List(),List(),List(Layer(UnlocatableSourceInfo,Verification,Extract(Some(Verification)),List(Layer(UnlocatableSourceInfo,Assert,Extract(Some(Verification/Assert)),List()), Layer(UnlocatableSourceInfo,Assume,Extract(Some(Verification/Assume)),List()), Layer(UnlocatableSourceInfo,Cover,Extract(Some(Verification/Cover)),List())))),List())\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-look-up-parameters-from-a-definition-if-i-dont-want-to-instantiate-it",children:"How do I look up parameters from a Definition, if I don't want to instantiate it?"}),"\n",(0,t.jsxs)(n.p,{children:["Just like ",(0,t.jsx)(n.code,{children:"Instance"}),"s, ",(0,t.jsx)(n.code,{children:"Definition"}),"'s also contain accessors for ",(0,t.jsx)(n.code,{children:"@public"})," members.\nAs such, you can directly access them:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, instantiable, public}\n\n@instantiable\nclass AddOne(val width: Int) extends RawModule {\n @public val width = width\n @public val in = IO(Input(UInt(width.W)))\n @public val out = IO(Output(UInt(width.W)))\n out := in + 1.U\n}\n\nclass Top extends Module {\n val definition = Definition(new AddOne(10))\n println(s"Width is: ${definition.width}")\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule Top(\n input clock,\n reset\n);\n\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-parameterize-a-module-by-its-children-instances",children:"How do I parameterize a module by its children instances?"}),"\n",(0,t.jsx)(n.p,{children:"Prior to the introduction of this package, a parent module would have to pass all necessary parameters\nwhen instantiating a child module.\nThis had the unfortunate consequence of requiring a parent's parameters to always contain the child's\nparameters, which was an unnecessary coupling which lead to some anti-patterns."}),"\n",(0,t.jsxs)(n.p,{children:["Now, a parent can take a child ",(0,t.jsx)(n.code,{children:"Definition"})," as an argument, and instantiate it directly.\nIn addition, it can analyze the parameters used in the definition to parameterize itself.\nIn a sense, now the child can actually parameterize the parent."]}),"\n",(0,t.jsxs)(n.p,{children:["In the following example, we create a definition of ",(0,t.jsx)(n.code,{children:"AddOne"}),", and pass the definition to ",(0,t.jsx)(n.code,{children:"AddTwo"}),".\nThe width of the ",(0,t.jsx)(n.code,{children:"AddTwo"})," ports are now derived from the parameterization of the ",(0,t.jsx)(n.code,{children:"AddOne"})," instance."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public}\n\n@instantiable\nclass AddOne(val width: Int) extends Module {\n @public val width = width\n @public val in = IO(Input(UInt(width.W)))\n @public val out = IO(Output(UInt(width.W)))\n out := in + 1.U\n}\n\nclass AddTwo(addOneDef: Definition[AddOne]) extends Module {\n val i0 = Instance(addOneDef)\n val i1 = Instance(addOneDef)\n val in = IO(Input(UInt(addOneDef.width.W)))\n val out = IO(Output(UInt(addOneDef.width.W)))\n i0.in := in\n i1.in := i0.out\n out := i1.out\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule AddOne(\n input [9:0] in,\n output [9:0] out\n);\n\n assign out = in + 10'h1;\nendmodule\n\nmodule AddTwo(\n input clock,\n reset,\n input [9:0] in,\n output [9:0] out\n);\n\n wire [9:0] _i0_out;\n AddOne i0 (\n .in (in),\n .out (_i0_out)\n );\n AddOne i1 (\n .in (_i0_out),\n .out (out)\n );\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-use-the-new-hierarchy-specific-select-functions",children:"How do I use the new hierarchy-specific Select functions?"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["There are seven hierarchy-specific functions, which (with the exception of ",(0,t.jsx)(n.code,{children:"ios"}),") either return ",(0,t.jsx)(n.code,{children:"Instance"}),"'s or ",(0,t.jsx)(n.code,{children:"Definition"}),"'s:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"instancesIn(parent)"}),": Return all instances directly instantiated locally within ",(0,t.jsx)(n.code,{children:"parent"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"instancesOf[type](parent)"}),": Return all instances of provided ",(0,t.jsx)(n.code,{children:"type"})," directly instantiated locally within ",(0,t.jsx)(n.code,{children:"parent"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"allInstancesOf[type](root)"}),": Return all instances of provided ",(0,t.jsx)(n.code,{children:"type"})," directly and indirectly instantiated, locally and deeply, starting from ",(0,t.jsx)(n.code,{children:"root"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"definitionsIn"}),": Return definitions of all instances directly instantiated locally within ",(0,t.jsx)(n.code,{children:"parent"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"definitionsOf[type]"}),": Return definitions of all instances of provided ",(0,t.jsx)(n.code,{children:"type"})," directly instantiated locally within ",(0,t.jsx)(n.code,{children:"parent"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"allDefinitionsOf[type]"}),": Return all definitions of instances of provided ",(0,t.jsx)(n.code,{children:"type"})," directly and indirectly instantiated, locally and deeply, starting from ",(0,t.jsx)(n.code,{children:"root"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"ios"}),": Returns all the I/Os of the provided definition or instance."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["To demonstrate this, consider the following. We mock up an example where we are using the ",(0,t.jsx)(n.code,{children:"Select.allInstancesOf"})," and ",(0,t.jsx)(n.code,{children:"Select.allDefinitionsOf"})," to annotate instances and the definition of ",(0,t.jsx)(n.code,{children:"EmptyModule"}),". When converting the ",(0,t.jsx)(n.code,{children:"ChiselAnnotation"})," to firrtl's ",(0,t.jsx)(n.code,{children:"Annotation"}),", we print out the resulting ",(0,t.jsx)(n.code,{children:"Target"}),". As shown, despite ",(0,t.jsx)(n.code,{children:"EmptyModule"})," actually only being elaborated once, we still provide different targets depending on how the instance or definition is selected."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, Instance, Hierarchy, instantiable, public}\nimport firrtl.annotations.{IsModule, NoTargetAnnotation}\ncase object EmptyAnnotation extends NoTargetAnnotation\ncase class MyChiselAnnotation(m: Hierarchy[RawModule], tag: String) extends experimental.ChiselAnnotation {\n def toFirrtl = {\n println(tag + ": " + m.toTarget)\n EmptyAnnotation\n }\n}\n\n@instantiable\nclass EmptyModule extends Module {\n println("Elaborating EmptyModule!")\n}\n\n@instantiable\nclass TwoEmptyModules extends Module {\n val definition = Definition(new EmptyModule)\n val i0 = Instance(definition)\n val i1 = Instance(definition)\n}\n\nclass Top extends Module {\n val definition = Definition(new TwoEmptyModules)\n val instance = Instance(definition)\n aop.Select.allInstancesOf[EmptyModule](instance).foreach { i =>\n experimental.annotate(MyChiselAnnotation(i, "instance"))\n }\n aop.Select.allDefinitionsOf[EmptyModule](instance).foreach { d =>\n experimental.annotate(MyChiselAnnotation(d, "definition"))\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Elaborating EmptyModule!\ninstance: ~Top|Top/instance:TwoEmptyModules/i0:EmptyModule\ninstance: ~Top|Top/instance:TwoEmptyModules/i1:EmptyModule\ndefinition: ~Top|EmptyModule\n"})}),"\n",(0,t.jsxs)(n.p,{children:["You can also use ",(0,t.jsx)(n.code,{children:"Select.ios"})," on either a ",(0,t.jsx)(n.code,{children:"Definition"})," or an ",(0,t.jsx)(n.code,{children:"Instance"})," to annotate the I/Os appropriately:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'case class MyIOAnnotation(m: Data, tag: String) extends experimental.ChiselAnnotation {\n def toFirrtl = {\n println(tag + ": " + m.toTarget)\n EmptyAnnotation\n }\n}\n\n@instantiable\nclass InOutModule extends Module {\n @public val in = IO(Input(Bool()))\n @public val out = IO(Output(Bool()))\n out := in\n}\n\n@instantiable\nclass TwoInOutModules extends Module {\n val in = IO(Input(Bool()))\n val out = IO(Output(Bool()))\n val definition = Definition(new InOutModule)\n val i0 = Instance(definition)\n val i1 = Instance(definition)\n i0.in := in\n i1.in := i0.out\n out := i1.out\n}\n\nclass InOutTop extends Module {\n val definition = Definition(new TwoInOutModules)\n val instance = Instance(definition)\n aop.Select.allInstancesOf[InOutModule](instance).foreach { i =>\n aop.Select.ios(i).foreach { io =>\n experimental.annotate(MyIOAnnotation(io, "instance io"))\n }}\n aop.Select.allDefinitionsOf[InOutModule](instance).foreach { d =>\n aop.Select.ios(d).foreach {io =>\n experimental.annotate(MyIOAnnotation(io, "definition io"))\n }}\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>clock\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>reset\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>in\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>out\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>clock\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>reset\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>in\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>out\ndefinition io: ~InOutTop|InOutModule>clock\ndefinition io: ~InOutTop|InOutModule>reset\ndefinition io: ~InOutTop|InOutModule>in\ndefinition io: ~InOutTop|InOutModule>out\n"})})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1871:(e,n,i)=>{i.d(n,{A:()=>s});i(6540);var t=i(5195);const o={tableOfContentsInline:"tableOfContentsInline_prmo"};var a=i(4848);function s(e){let{toc:n,minHeadingLevel:i,maxHeadingLevel:s}=e;return(0,a.jsx)("div",{className:o.tableOfContentsInline,children:(0,a.jsx)(t.A,{toc:n,minHeadingLevel:i,maxHeadingLevel:s,className:"table-of-contents",linkClassName:null})})}},5195:(e,n,i)=>{i.d(n,{A:()=>f});var t=i(6540),o=i(6342);function a(e){const n=e.map((e=>({...e,parentIndex:-1,children:[]}))),i=Array(7).fill(-1);n.forEach(((e,n)=>{const t=i.slice(2,e.level);e.parentIndex=Math.max(...t),i[e.level]=n}));const t=[];return n.forEach((e=>{const{parentIndex:i,...o}=e;i>=0?n[i].children.push(o):t.push(o)})),t}function s(e){let{toc:n,minHeadingLevel:i,maxHeadingLevel:t}=e;return n.flatMap((e=>{const n=s({toc:e.children,minHeadingLevel:i,maxHeadingLevel:t});return function(e){return e.level>=i&&e.level<=t}(e)?[{...e,children:n}]:n}))}function l(e){const n=e.getBoundingClientRect();return n.top===n.bottom?l(e.parentNode):n}function c(e,n){let{anchorTopOffset:i}=n;const t=e.find((e=>l(e).top>=i));if(t){return function(e){return e.top>0&&e.bottom{e.current=n?0:document.querySelector(".navbar").clientHeight}),[n]),e}function r(e){const n=(0,t.useRef)(void 0),i=d();(0,t.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:t,linkActiveClassName:o,minHeadingLevel:a,maxHeadingLevel:s}=e;function l(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(t),l=function(e){let{minHeadingLevel:n,maxHeadingLevel:i}=e;const t=[];for(let o=n;o<=i;o+=1)t.push(`h${o}.anchor`);return Array.from(document.querySelectorAll(t.join()))}({minHeadingLevel:a,maxHeadingLevel:s}),d=c(l,{anchorTopOffset:i.current}),r=e.find((e=>d&&d.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,i){i?(n.current&&n.current!==e&&n.current.classList.remove(o),e.classList.add(o),n.current=e):e.classList.remove(o)}(e,e===r)}))}return document.addEventListener("scroll",l),document.addEventListener("resize",l),l(),()=>{document.removeEventListener("scroll",l),document.removeEventListener("resize",l)}}),[e,i])}var u=i(8774),h=i(4848);function p(e){let{toc:n,className:i,linkClassName:t,isChild:o}=e;return n.length?(0,h.jsx)("ul",{className:o?void 0:i,children:n.map((e=>(0,h.jsxs)("li",{children:[(0,h.jsx)(u.A,{to:`#${e.id}`,className:t??void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,h.jsx)(p,{isChild:!0,toc:e.children,className:i,linkClassName:t})]},e.id)))}):null}const m=t.memo(p);function f(e){let{toc:n,className:i="table-of-contents table-of-contents__left-border",linkClassName:l="table-of-contents__link",linkActiveClassName:c,minHeadingLevel:d,maxHeadingLevel:u,...p}=e;const f=(0,o.p)(),x=d??f.tableOfContents.minHeadingLevel,I=u??f.tableOfContents.maxHeadingLevel,j=function(e){let{toc:n,minHeadingLevel:i,maxHeadingLevel:o}=e;return(0,t.useMemo)((()=>s({toc:a(n),minHeadingLevel:i,maxHeadingLevel:o})),[n,i,o])}({toc:n,minHeadingLevel:x,maxHeadingLevel:I});return r((0,t.useMemo)((()=>{if(l&&c)return{linkClassName:l,linkActiveClassName:c,minHeadingLevel:x,maxHeadingLevel:I}}),[l,c,x,I])),(0,h.jsx)(m,{toc:j,className:i,linkClassName:l,...p})}},8453:(e,n,i)=>{i.d(n,{R:()=>s,x:()=>l});var t=i(6540);const o={},a=t.createContext(o);function s(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/1ce89024.be0df6cd.js b/assets/js/1ce89024.be0df6cd.js
deleted file mode 100644
index b45a2174b2..0000000000
--- a/assets/js/1ce89024.be0df6cd.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[741],{3519:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>r});var t=i(4848),o=i(8453),a=i(1871);const s={sidebar_position:2},l="Hierarchy Cookbook",c={id:"cookbooks/hierarchy",title:"Hierarchy Cookbook",description:"How do I instantiate multiple instances with the same module parameterization?",source:"@site/docs/cookbooks/hierarchy.md",sourceDirName:"cookbooks",slug:"/cookbooks/hierarchy",permalink:"/docs/cookbooks/hierarchy",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/cookbooks/hierarchy.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"chiselSidebar",previous:{title:"Naming Cookbook",permalink:"/docs/cookbooks/naming"},next:{title:"DataView Cookbook",permalink:"/docs/cookbooks/dataview"}},d={},r=[{value:"How do I instantiate multiple instances with the same module parameterization?",id:"how-do-i-instantiate-multiple-instances-with-the-same-module-parameterization",level:2},{value:"Using Definition and Instance",id:"using-definition-and-instance",level:3},{value:"Using Instantiate",id:"using-instantiate",level:3},{value:"How do I access internal fields of an instance?",id:"how-do-i-access-internal-fields-of-an-instance",level:2},{value:"How do I make my parameters accessible from an instance?",id:"how-do-i-make-my-parameters-accessible-from-an-instance",level:2},{value:"How do I look up parameters from a Definition, if I don't want to instantiate it?",id:"how-do-i-look-up-parameters-from-a-definition-if-i-dont-want-to-instantiate-it",level:2},{value:"How do I parameterize a module by its children instances?",id:"how-do-i-parameterize-a-module-by-its-children-instances",level:2},{value:"How do I use the new hierarchy-specific Select functions?",id:"how-do-i-use-the-new-hierarchy-specific-select-functions",level:2}];function u(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"hierarchy-cookbook",children:"Hierarchy Cookbook"})}),"\n","\n",(0,t.jsx)(a.A,{toc:r}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-instantiate-multiple-instances-with-the-same-module-parameterization",children:"How do I instantiate multiple instances with the same module parameterization?"}),"\n",(0,t.jsx)(n.p,{children:'Prior to this package, Chisel users relied on deduplication in a FIRRTL compiler to combine\nstructurally equivalent modules into one module (aka "deduplication").\nThis package introduces the following new APIs to enable multiply-instantiated modules directly in Chisel.'}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Definition(...)"})," enables elaborating a module, but does not actually instantiate that module.\nInstead, it returns a ",(0,t.jsx)(n.code,{children:"Definition"})," class which represents that module's definition."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Instance(...)"})," takes a ",(0,t.jsx)(n.code,{children:"Definition"})," and instantiates it, returning an ",(0,t.jsx)(n.code,{children:"Instance"})," object."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Instantiate(...)"})," provides an API similar to ",(0,t.jsx)(n.code,{children:"Module(...)"}),", except it uses\n",(0,t.jsx)(n.code,{children:"Definition"})," and ",(0,t.jsx)(n.code,{children:"Instance"})," to only elaborate modules once for a given set of\nparameters. It returns an ",(0,t.jsx)(n.code,{children:"Instance"})," object."]}),"\n",(0,t.jsxs)(n.p,{children:["Modules (classes or traits) which will be used with the ",(0,t.jsx)(n.code,{children:"Definition"}),"/",(0,t.jsx)(n.code,{children:"Instance"})," api should be marked\nwith the ",(0,t.jsx)(n.code,{children:"@instantiable"})," annotation at the class/trait definition."]}),"\n",(0,t.jsxs)(n.p,{children:["To make a Module's members variables accessible from an ",(0,t.jsx)(n.code,{children:"Instance"})," object, they must be annotated\nwith the ",(0,t.jsx)(n.code,{children:"@public"})," annotation. Note that this is only accessible from a Scala sense\u2014this is not\nin and of itself a mechanism for cross-module references."]}),"\n",(0,t.jsx)(n.h3,{id:"using-definition-and-instance",children:"Using Definition and Instance"}),"\n",(0,t.jsxs)(n.p,{children:["In the following example, use ",(0,t.jsx)(n.code,{children:"Definition"}),", ",(0,t.jsx)(n.code,{children:"Instance"}),", ",(0,t.jsx)(n.code,{children:"@instantiable"})," and ",(0,t.jsx)(n.code,{children:"@public"})," to create\nmultiple instances of one specific parameterization of a module, ",(0,t.jsx)(n.code,{children:"AddOne"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public}\n\n@instantiable\nclass AddOne(width: Int) extends Module {\n @public val in = IO(Input(UInt(width.W)))\n @public val out = IO(Output(UInt(width.W)))\n out := in + 1.U\n}\n\nclass AddTwo(width: Int) extends Module {\n val in = IO(Input(UInt(width.W)))\n val out = IO(Output(UInt(width.W)))\n val addOneDef = Definition(new AddOne(width))\n val i0 = Instance(addOneDef)\n val i1 = Instance(addOneDef)\n i0.in := in\n i1.in := i0.out\n out := i1.out\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule AddOne(\n input [9:0] in,\n output [9:0] out\n);\n\n assign out = in + 10'h1;\nendmodule\n\nmodule AddTwo(\n input clock,\n reset,\n input [9:0] in,\n output [9:0] out\n);\n\n wire [9:0] _i0_out;\n AddOne i0 (\n .in (in),\n .out (_i0_out)\n );\n AddOne i1 (\n .in (_i0_out),\n .out (out)\n );\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"using-instantiate",children:"Using Instantiate"}),"\n",(0,t.jsxs)(n.p,{children:["Similar to the above, the following example uses ",(0,t.jsx)(n.code,{children:"Instantiate"})," to create\nmultiple instances of ",(0,t.jsx)(n.code,{children:"AddOne"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.hierarchy.Instantiate\n\nclass AddTwoInstantiate(width: Int) extends Module {\n val in = IO(Input(UInt(width.W)))\n val out = IO(Output(UInt(width.W)))\n val i0 = Instantiate(new AddOne(width))\n val i1 = Instantiate(new AddOne(width))\n i0.in := in\n i1.in := i0.out\n out := i1.out\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule AddOne(\n input [15:0] in,\n output [15:0] out\n);\n\n assign out = in + 16'h1;\nendmodule\n\nmodule AddTwoInstantiate(\n input clock,\n reset,\n input [15:0] in,\n output [15:0] out\n);\n\n wire [15:0] _i0_out;\n AddOne i0 (\n .in (in),\n .out (_i0_out)\n );\n AddOne i1 (\n .in (_i0_out),\n .out (out)\n );\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-access-internal-fields-of-an-instance",children:"How do I access internal fields of an instance?"}),"\n",(0,t.jsxs)(n.p,{children:["You can mark internal members of a class or trait marked with ",(0,t.jsx)(n.code,{children:"@instantiable"})," with the ",(0,t.jsx)(n.code,{children:"@public"})," annotation.\nThe requirements are that the field is publicly accessible, is a ",(0,t.jsx)(n.code,{children:"val"})," or ",(0,t.jsx)(n.code,{children:"lazy val"}),", and is a valid type.\nThe list of valid types are:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"IsInstantiable"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"IsLookupable"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"Data"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"BaseModule"})}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Iterable"}),"/",(0,t.jsx)(n.code,{children:"Option "}),"containing a type that meets these requirements"]}),"\n",(0,t.jsxs)(n.li,{children:["Basic type like ",(0,t.jsx)(n.code,{children:"String"}),", ",(0,t.jsx)(n.code,{children:"Int"}),", ",(0,t.jsx)(n.code,{children:"BigInt"})," etc."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["To mark a superclass's member as ",(0,t.jsx)(n.code,{children:"@public"}),", use the following pattern (shown with ",(0,t.jsx)(n.code,{children:"val clock"}),")."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.hierarchy.{instantiable, public}\n\n@instantiable\nclass MyModule extends Module {\n @public val clock = clock\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["You'll get the following error message for improperly marking something as ",(0,t.jsx)(n.code,{children:"@public"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.hierarchy.{instantiable, public}\n\nobject NotValidType\n\n@instantiable\nclass MyModule extends Module {\n @public val x = NotValidType\n}\n// 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\n// val x = circt.stage.ChiselStage.emitCHIRRTL(new Top)\n// ^\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-make-my-parameters-accessible-from-an-instance",children:"How do I make my parameters accessible from an instance?"}),"\n",(0,t.jsxs)(n.p,{children:["If an instance's parameters are simple (e.g. ",(0,t.jsx)(n.code,{children:"Int"}),", ",(0,t.jsx)(n.code,{children:"String"})," etc.) they can be marked directly with ",(0,t.jsx)(n.code,{children:"@public"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Often, parameters are more complicated and are contained in case classes.\nIn such cases, mark the case class with the ",(0,t.jsx)(n.code,{children:"IsLookupable"})," trait.\nThis indicates to Chisel that instances of the ",(0,t.jsx)(n.code,{children:"IsLookupable"})," class may be accessed from within instances."]}),"\n",(0,t.jsxs)(n.p,{children:["However, ensure that these parameters are true for ",(0,t.jsx)(n.strong,{children:"all"})," instances of a definition.\nFor example, if our parameters contained an id field which was instance-specific but defaulted to zero,\nthen the definition's id would be returned for all instances.\nThis change in behavior could lead to bugs if other code presumed the id field was correct."]}),"\n",(0,t.jsxs)(n.p,{children:["Thus, it is important that when converting normal modules to use this package,\nyou are careful about what you mark as ",(0,t.jsx)(n.code,{children:"IsLookupable"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["In the following example, we added the trait ",(0,t.jsx)(n.code,{children:"IsLookupable"})," to allow the member to be marked ",(0,t.jsx)(n.code,{children:"@public"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, Instance, instantiable, IsLookupable, public}\n\ncase class MyCaseClass(width: Int) extends IsLookupable\n\n@instantiable\nclass MyModule extends Module {\n @public val x = MyCaseClass(10)\n}\n\nclass Top extends Module {\n val inst = Instance(Definition(new MyModule))\n println(s"Width is ${inst.x.width}")\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Width is 10\nCircuit(Top,List(DefModule(repl.MdocSession$MdocApp5$MyModule@68a99c10,MyModule,false,List(),List(Port(MyModule.clock: IO[Clock],Input,SourceLine(hierarchy.md,105,2)), Port(MyModule.reset: IO[Reset],Input,SourceLine(hierarchy.md,105,2))),Vector()), DefModule(repl.MdocSession$MdocApp5$Top@775ef9f3,Top,true,List(),List(Port(Top.clock: IO[Clock],Input,SourceLine(hierarchy.md,111,7)), Port(Top.reset: IO[Bool],Input,SourceLine(hierarchy.md,111,7))),Vector(DefInstance(SourceLine(hierarchy.md,112,22),ModuleClone(repl.MdocSession$MdocApp5$MyModule@68a99c10),List(Port(MyModule.clock: IO[Clock],Input,SourceLine(hierarchy.md,105,2)), Port(MyModule.reset: IO[Reset],Input,SourceLine(hierarchy.md,105,2)))), 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@69172960,List(),List(),List(Layer(UnlocatableSourceInfo,Verification,Extract(Some(Verification)),List(Layer(UnlocatableSourceInfo,Assert,Extract(Some(Verification/Assert)),List()), Layer(UnlocatableSourceInfo,Assume,Extract(Some(Verification/Assume)),List()), Layer(UnlocatableSourceInfo,Cover,Extract(Some(Verification/Cover)),List())))),List())\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-look-up-parameters-from-a-definition-if-i-dont-want-to-instantiate-it",children:"How do I look up parameters from a Definition, if I don't want to instantiate it?"}),"\n",(0,t.jsxs)(n.p,{children:["Just like ",(0,t.jsx)(n.code,{children:"Instance"}),"s, ",(0,t.jsx)(n.code,{children:"Definition"}),"'s also contain accessors for ",(0,t.jsx)(n.code,{children:"@public"})," members.\nAs such, you can directly access them:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, instantiable, public}\n\n@instantiable\nclass AddOne(val width: Int) extends RawModule {\n @public val width = width\n @public val in = IO(Input(UInt(width.W)))\n @public val out = IO(Output(UInt(width.W)))\n out := in + 1.U\n}\n\nclass Top extends Module {\n val definition = Definition(new AddOne(10))\n println(s"Width is: ${definition.width}")\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule Top(\n input clock,\n reset\n);\n\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-parameterize-a-module-by-its-children-instances",children:"How do I parameterize a module by its children instances?"}),"\n",(0,t.jsx)(n.p,{children:"Prior to the introduction of this package, a parent module would have to pass all necessary parameters\nwhen instantiating a child module.\nThis had the unfortunate consequence of requiring a parent's parameters to always contain the child's\nparameters, which was an unnecessary coupling which lead to some anti-patterns."}),"\n",(0,t.jsxs)(n.p,{children:["Now, a parent can take a child ",(0,t.jsx)(n.code,{children:"Definition"})," as an argument, and instantiate it directly.\nIn addition, it can analyze the parameters used in the definition to parameterize itself.\nIn a sense, now the child can actually parameterize the parent."]}),"\n",(0,t.jsxs)(n.p,{children:["In the following example, we create a definition of ",(0,t.jsx)(n.code,{children:"AddOne"}),", and pass the definition to ",(0,t.jsx)(n.code,{children:"AddTwo"}),".\nThe width of the ",(0,t.jsx)(n.code,{children:"AddTwo"})," ports are now derived from the parameterization of the ",(0,t.jsx)(n.code,{children:"AddOne"})," instance."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public}\n\n@instantiable\nclass AddOne(val width: Int) extends Module {\n @public val width = width\n @public val in = IO(Input(UInt(width.W)))\n @public val out = IO(Output(UInt(width.W)))\n out := in + 1.U\n}\n\nclass AddTwo(addOneDef: Definition[AddOne]) extends Module {\n val i0 = Instance(addOneDef)\n val i1 = Instance(addOneDef)\n val in = IO(Input(UInt(addOneDef.width.W)))\n val out = IO(Output(UInt(addOneDef.width.W)))\n i0.in := in\n i1.in := i0.out\n out := i1.out\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule AddOne(\n input [9:0] in,\n output [9:0] out\n);\n\n assign out = in + 10'h1;\nendmodule\n\nmodule AddTwo(\n input clock,\n reset,\n input [9:0] in,\n output [9:0] out\n);\n\n wire [9:0] _i0_out;\n AddOne i0 (\n .in (in),\n .out (_i0_out)\n );\n AddOne i1 (\n .in (_i0_out),\n .out (out)\n );\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-use-the-new-hierarchy-specific-select-functions",children:"How do I use the new hierarchy-specific Select functions?"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["There are seven hierarchy-specific functions, which (with the exception of ",(0,t.jsx)(n.code,{children:"ios"}),") either return ",(0,t.jsx)(n.code,{children:"Instance"}),"'s or ",(0,t.jsx)(n.code,{children:"Definition"}),"'s:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"instancesIn(parent)"}),": Return all instances directly instantiated locally within ",(0,t.jsx)(n.code,{children:"parent"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"instancesOf[type](parent)"}),": Return all instances of provided ",(0,t.jsx)(n.code,{children:"type"})," directly instantiated locally within ",(0,t.jsx)(n.code,{children:"parent"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"allInstancesOf[type](root)"}),": Return all instances of provided ",(0,t.jsx)(n.code,{children:"type"})," directly and indirectly instantiated, locally and deeply, starting from ",(0,t.jsx)(n.code,{children:"root"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"definitionsIn"}),": Return definitions of all instances directly instantiated locally within ",(0,t.jsx)(n.code,{children:"parent"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"definitionsOf[type]"}),": Return definitions of all instances of provided ",(0,t.jsx)(n.code,{children:"type"})," directly instantiated locally within ",(0,t.jsx)(n.code,{children:"parent"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"allDefinitionsOf[type]"}),": Return all definitions of instances of provided ",(0,t.jsx)(n.code,{children:"type"})," directly and indirectly instantiated, locally and deeply, starting from ",(0,t.jsx)(n.code,{children:"root"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"ios"}),": Returns all the I/Os of the provided definition or instance."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["To demonstrate this, consider the following. We mock up an example where we are using the ",(0,t.jsx)(n.code,{children:"Select.allInstancesOf"})," and ",(0,t.jsx)(n.code,{children:"Select.allDefinitionsOf"})," to annotate instances and the definition of ",(0,t.jsx)(n.code,{children:"EmptyModule"}),". When converting the ",(0,t.jsx)(n.code,{children:"ChiselAnnotation"})," to firrtl's ",(0,t.jsx)(n.code,{children:"Annotation"}),", we print out the resulting ",(0,t.jsx)(n.code,{children:"Target"}),". As shown, despite ",(0,t.jsx)(n.code,{children:"EmptyModule"})," actually only being elaborated once, we still provide different targets depending on how the instance or definition is selected."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.experimental.hierarchy.{Definition, Instance, Hierarchy, instantiable, public}\nimport firrtl.annotations.{IsModule, NoTargetAnnotation}\ncase object EmptyAnnotation extends NoTargetAnnotation\ncase class MyChiselAnnotation(m: Hierarchy[RawModule], tag: String) extends experimental.ChiselAnnotation {\n def toFirrtl = {\n println(tag + ": " + m.toTarget)\n EmptyAnnotation\n }\n}\n\n@instantiable\nclass EmptyModule extends Module {\n println("Elaborating EmptyModule!")\n}\n\n@instantiable\nclass TwoEmptyModules extends Module {\n val definition = Definition(new EmptyModule)\n val i0 = Instance(definition)\n val i1 = Instance(definition)\n}\n\nclass Top extends Module {\n val definition = Definition(new TwoEmptyModules)\n val instance = Instance(definition)\n aop.Select.allInstancesOf[EmptyModule](instance).foreach { i =>\n experimental.annotate(MyChiselAnnotation(i, "instance"))\n }\n aop.Select.allDefinitionsOf[EmptyModule](instance).foreach { d =>\n experimental.annotate(MyChiselAnnotation(d, "definition"))\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Elaborating EmptyModule!\ninstance: ~Top|Top/instance:TwoEmptyModules/i0:EmptyModule\ninstance: ~Top|Top/instance:TwoEmptyModules/i1:EmptyModule\ndefinition: ~Top|EmptyModule\n"})}),"\n",(0,t.jsxs)(n.p,{children:["You can also use ",(0,t.jsx)(n.code,{children:"Select.ios"})," on either a ",(0,t.jsx)(n.code,{children:"Definition"})," or an ",(0,t.jsx)(n.code,{children:"Instance"})," to annotate the I/Os appropriately:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'case class MyIOAnnotation(m: Data, tag: String) extends experimental.ChiselAnnotation {\n def toFirrtl = {\n println(tag + ": " + m.toTarget)\n EmptyAnnotation\n }\n}\n\n@instantiable\nclass InOutModule extends Module {\n @public val in = IO(Input(Bool()))\n @public val out = IO(Output(Bool()))\n out := in\n}\n\n@instantiable\nclass TwoInOutModules extends Module {\n val in = IO(Input(Bool()))\n val out = IO(Output(Bool()))\n val definition = Definition(new InOutModule)\n val i0 = Instance(definition)\n val i1 = Instance(definition)\n i0.in := in\n i1.in := i0.out\n out := i1.out\n}\n\nclass InOutTop extends Module {\n val definition = Definition(new TwoInOutModules)\n val instance = Instance(definition)\n aop.Select.allInstancesOf[InOutModule](instance).foreach { i =>\n aop.Select.ios(i).foreach { io =>\n experimental.annotate(MyIOAnnotation(io, "instance io"))\n }}\n aop.Select.allDefinitionsOf[InOutModule](instance).foreach { d =>\n aop.Select.ios(d).foreach {io =>\n experimental.annotate(MyIOAnnotation(io, "definition io"))\n }}\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"instance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>clock\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>reset\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>in\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i0:InOutModule>out\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>clock\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>reset\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>in\ninstance io: ~InOutTop|InOutTop/instance:TwoInOutModules/i1:InOutModule>out\ndefinition io: ~InOutTop|InOutModule>clock\ndefinition io: ~InOutTop|InOutModule>reset\ndefinition io: ~InOutTop|InOutModule>in\ndefinition io: ~InOutTop|InOutModule>out\n"})})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1871:(e,n,i)=>{i.d(n,{A:()=>s});i(6540);var t=i(5195);const o={tableOfContentsInline:"tableOfContentsInline_prmo"};var a=i(4848);function s(e){let{toc:n,minHeadingLevel:i,maxHeadingLevel:s}=e;return(0,a.jsx)("div",{className:o.tableOfContentsInline,children:(0,a.jsx)(t.A,{toc:n,minHeadingLevel:i,maxHeadingLevel:s,className:"table-of-contents",linkClassName:null})})}},5195:(e,n,i)=>{i.d(n,{A:()=>f});var t=i(6540),o=i(6342);function a(e){const n=e.map((e=>({...e,parentIndex:-1,children:[]}))),i=Array(7).fill(-1);n.forEach(((e,n)=>{const t=i.slice(2,e.level);e.parentIndex=Math.max(...t),i[e.level]=n}));const t=[];return n.forEach((e=>{const{parentIndex:i,...o}=e;i>=0?n[i].children.push(o):t.push(o)})),t}function s(e){let{toc:n,minHeadingLevel:i,maxHeadingLevel:t}=e;return n.flatMap((e=>{const n=s({toc:e.children,minHeadingLevel:i,maxHeadingLevel:t});return function(e){return e.level>=i&&e.level<=t}(e)?[{...e,children:n}]:n}))}function l(e){const n=e.getBoundingClientRect();return n.top===n.bottom?l(e.parentNode):n}function c(e,n){let{anchorTopOffset:i}=n;const t=e.find((e=>l(e).top>=i));if(t){return function(e){return e.top>0&&e.bottom{e.current=n?0:document.querySelector(".navbar").clientHeight}),[n]),e}function r(e){const n=(0,t.useRef)(void 0),i=d();(0,t.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:t,linkActiveClassName:o,minHeadingLevel:a,maxHeadingLevel:s}=e;function l(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(t),l=function(e){let{minHeadingLevel:n,maxHeadingLevel:i}=e;const t=[];for(let o=n;o<=i;o+=1)t.push(`h${o}.anchor`);return Array.from(document.querySelectorAll(t.join()))}({minHeadingLevel:a,maxHeadingLevel:s}),d=c(l,{anchorTopOffset:i.current}),r=e.find((e=>d&&d.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,i){i?(n.current&&n.current!==e&&n.current.classList.remove(o),e.classList.add(o),n.current=e):e.classList.remove(o)}(e,e===r)}))}return document.addEventListener("scroll",l),document.addEventListener("resize",l),l(),()=>{document.removeEventListener("scroll",l),document.removeEventListener("resize",l)}}),[e,i])}var u=i(8774),h=i(4848);function p(e){let{toc:n,className:i,linkClassName:t,isChild:o}=e;return n.length?(0,h.jsx)("ul",{className:o?void 0:i,children:n.map((e=>(0,h.jsxs)("li",{children:[(0,h.jsx)(u.A,{to:`#${e.id}`,className:t??void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,h.jsx)(p,{isChild:!0,toc:e.children,className:i,linkClassName:t})]},e.id)))}):null}const m=t.memo(p);function f(e){let{toc:n,className:i="table-of-contents table-of-contents__left-border",linkClassName:l="table-of-contents__link",linkActiveClassName:c,minHeadingLevel:d,maxHeadingLevel:u,...p}=e;const f=(0,o.p)(),x=d??f.tableOfContents.minHeadingLevel,I=u??f.tableOfContents.maxHeadingLevel,j=function(e){let{toc:n,minHeadingLevel:i,maxHeadingLevel:o}=e;return(0,t.useMemo)((()=>s({toc:a(n),minHeadingLevel:i,maxHeadingLevel:o})),[n,i,o])}({toc:n,minHeadingLevel:x,maxHeadingLevel:I});return r((0,t.useMemo)((()=>{if(l&&c)return{linkClassName:l,linkActiveClassName:c,minHeadingLevel:x,maxHeadingLevel:I}}),[l,c,x,I])),(0,h.jsx)(m,{toc:j,className:i,linkClassName:l,...p})}},8453:(e,n,i)=>{i.d(n,{R:()=>s,x:()=>l});var t=i(6540);const o={},a=t.createContext(o);function s(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/67ffb541.3deaf02c.js b/assets/js/67ffb541.bee895a3.js
similarity index 99%
rename from assets/js/67ffb541.3deaf02c.js
rename to assets/js/67ffb541.bee895a3.js
index d3d843f8b4..90d8268c83 100644
--- a/assets/js/67ffb541.3deaf02c.js
+++ b/assets/js/67ffb541.bee895a3.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[7132],{2869:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>r});var i=a(4848),t=a(8453);const l={layout:"docs",title:"DataView",section:"chisel3"},s="DataView",o={id:"explanations/dataview",title:"DataView",description:"New in Chisel 3.5",source:"@site/docs/explanations/dataview.md",sourceDirName:"explanations",slug:"/explanations/dataview",permalink:"/docs/explanations/dataview",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/dataview.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"DataView",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Chisel Data Types",permalink:"/docs/explanations/data-types"},next:{title:"Decoders",permalink:"/docs/explanations/decoder"}},d={},r=[{value:"Introduction",id:"introduction",level:2},{value:"A Motivating Example (AXI4)",id:"a-motivating-example-axi4",level:2},{value:"Other Use Cases",id:"other-use-cases",level:2},{value:"Tuples",id:"tuples",level:3},{value:"Totality and PartialDataView",id:"totality-and-partialdataview",level:2},{value:"Advanced Details",id:"advanced-details",level:2},{value:"Type Classes",id:"type-classes",level:3},{value:"Implicit Resolution",id:"implicit-resolution",level:3},{value:"Implicit Resolution Example",id:"implicit-resolution-example",level:4},{value:"DataProduct",id:"dataproduct",level:3}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"dataview",children:"DataView"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.em,{children:"New in Chisel 3.5"})}),"\n",(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(n.p,{children:['DataView is a mechanism for "viewing" Scala objects as a subtype of ',(0,i.jsx)(n.code,{children:"chisel3.Data"}),".\nOften, this is useful for viewing one subtype of ",(0,i.jsx)(n.code,{children:"chisel3.Data"}),", as another.\nOne can think about a ",(0,i.jsx)(n.code,{children:"DataView"})," as a mapping from a ",(0,i.jsx)(n.em,{children:"Target"})," type ",(0,i.jsx)(n.code,{children:"T"})," to a ",(0,i.jsx)(n.em,{children:"View"})," type ",(0,i.jsx)(n.code,{children:"V"}),".\nThis is similar to a cast (eg. ",(0,i.jsx)(n.code,{children:".asTypeOf"}),") with a few differences:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Views are ",(0,i.jsx)(n.em,{children:"connectable"}),"\u2014connections to the view will occur on the target"]}),"\n",(0,i.jsxs)(n.li,{children:["Whereas casts are ",(0,i.jsx)(n.em,{children:"structural"})," (a reinterpretation of the underlying bits), a DataView is a customizable mapping"]}),"\n",(0,i.jsxs)(n.li,{children:["Views can be ",(0,i.jsx)(n.em,{children:"partial"}),"\u2014not every field in the target must be included in the mapping"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"a-motivating-example-axi4",children:"A Motivating Example (AXI4)"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Advanced_eXtensible_Interface",children:"AXI4"})," is a common interface in digital\ndesign.\nA typical Verilog peripheral using AXI4 will define a write channel as something like:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"module my_module(\n // Write Channel\n input AXI_AWVALID,\n output AXI_AWREADY,\n input [3:0] AXI_AWID,\n input [19:0] AXI_AWADDR,\n input [1:0] AXI_AWLEN,\n input [1:0] AXI_AWSIZE,\n // ...\n);\n"})}),"\n",(0,i.jsx)(n.p,{children:"This would correspond to the following Chisel Bundle:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class VerilogAXIBundle(val addrWidth: Int) extends Bundle {\n val AWVALID = Output(Bool())\n val AWREADY = Input(Bool())\n val AWID = Output(UInt(4.W))\n val AWADDR = Output(UInt(addrWidth.W))\n val AWLEN = Output(UInt(2.W))\n val AWSIZE = Output(UInt(2.W))\n // The rest of AW and other AXI channels here\n}\n\n// Instantiated as\nclass my_module extends RawModule {\n val AXI = IO(new VerilogAXIBundle(20))\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Expressing something that matches a standard Verilog interface is important when instantiating Verilog\nmodules in a Chisel design as ",(0,i.jsx)(n.code,{children:"BlackBoxes"}),".\nGenerally though, Chisel developers prefer to use composition via utilities like ",(0,i.jsx)(n.code,{children:"Decoupled"})," rather\nthan a flat handling of ",(0,i.jsx)(n.code,{children:"ready"})," and ",(0,i.jsx)(n.code,{children:"valid"}),' as in the above.\nA more "Chisel-y" implementation of this interface might look like:']}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// Note that both the AW and AR channels look similar and could use the same Bundle definition\nclass AXIAddressChannel(val addrWidth: Int) extends Bundle {\n val id = UInt(4.W)\n val addr = UInt(addrWidth.W)\n val len = UInt(2.W)\n val size = UInt(2.W)\n // ...\n}\nimport chisel3.util.Decoupled\n// We can compose the various AXI channels together\nclass AXIBundle(val addrWidth: Int) extends Bundle {\n val aw = Decoupled(new AXIAddressChannel(addrWidth))\n // val ar = new AXIAddressChannel\n // ... Other channels here ...\n}\n// Instantiated as\nclass MyModule extends RawModule {\n val axi = IO(new AXIBundle(20))\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Of course, this would result in very different looking Verilog:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule MyModule(\n input axi_aw_ready,\n output axi_aw_valid,\n output [3:0] axi_aw_bits_id,\n output [19:0] axi_aw_bits_addr,\n output [1:0] axi_aw_bits_len,\n axi_aw_bits_size\n);\n\n assign axi_aw_valid = 1'h0;\n assign axi_aw_bits_id = 4'h0;\n assign axi_aw_bits_addr = 20'h0;\n assign axi_aw_bits_len = 2'h0;\n assign axi_aw_bits_size = 2'h0;\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.p,{children:"So how can we use our more structured types while maintaining expected Verilog interfaces?\nMeet DataView:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.dataview._\n\n// We recommend putting DataViews in a companion object of one of the involved types\nobject AXIBundle {\n // Don't be afraid of the use of implicits, we will discuss this pattern in more detail later\n implicit val axiView = DataView[VerilogAXIBundle, AXIBundle](\n // The first argument is a function constructing an object of View type (AXIBundle)\n // from an object of the Target type (VerilogAXIBundle)\n vab => new AXIBundle(vab.addrWidth),\n // The remaining arguments are a mapping of the corresponding fields of the two types\n _.AWVALID -> _.aw.valid,\n _.AWREADY -> _.aw.ready,\n _.AWID -> _.aw.bits.id,\n _.AWADDR -> _.aw.bits.addr,\n _.AWLEN -> _.aw.bits.len,\n _.AWSIZE -> _.aw.bits.size,\n // ...\n )\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This ",(0,i.jsx)(n.code,{children:"DataView"})," is a mapping between our flat, Verilog-style AXI Bundle to our more compositional,\nChisel-style AXI Bundle.\nIt allows us to define our ports to match the expected Verilog interface, while manipulating it as if\nit were the more structured type:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class AXIStub extends RawModule {\n val AXI = IO(new VerilogAXIBundle(20))\n val view = AXI.viewAs[AXIBundle]\n\n // We can now manipulate `AXI` via `view`\n view.aw.bits := 0.U.asTypeOf(new AXIAddressChannel(20)) // zero everything out by default\n view.aw.valid := true.B\n when (view.aw.ready) {\n view.aw.bits.id := 5.U\n view.aw.bits.addr := 1234.U\n // We can still manipulate AXI as well\n AXI.AWLEN := 1.U\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"This will generate Verilog that matches the standard naming convention:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule AXIStub(\n output AXI_AWVALID,\n input AXI_AWREADY,\n output [3:0] AXI_AWID,\n output [19:0] AXI_AWADDR,\n output [1:0] AXI_AWLEN,\n AXI_AWSIZE\n);\n\n assign AXI_AWVALID = 1'h1;\n assign AXI_AWID = AXI_AWREADY ? 4'h5 : 4'h0;\n assign AXI_AWADDR = AXI_AWREADY ? 20'h4D2 : 20'h0;\n assign AXI_AWLEN = {1'h0, AXI_AWREADY};\n assign AXI_AWSIZE = 2'h0;\nendmodule\n\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that if both the ",(0,i.jsx)(n.em,{children:"Target"})," and the ",(0,i.jsx)(n.em,{children:"View"})," types are subtypes of ",(0,i.jsx)(n.code,{children:"Data"})," (as they are in this example),\nthe ",(0,i.jsx)(n.code,{children:"DataView"})," is ",(0,i.jsx)(n.em,{children:"invertible"}),".\nThis means that we can easily create a ",(0,i.jsx)(n.code,{children:"DataView[AXIBundle, VerilogAXIBundle]"})," from our existing\n",(0,i.jsx)(n.code,{children:"DataView[VerilogAXIBundle, AXIBundle]"}),", all we need to do is provide a function to construct\na ",(0,i.jsx)(n.code,{children:"VerilogAXIBundle"})," from an instance of an ",(0,i.jsx)(n.code,{children:"AXIBundle"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// Note that typically you should define these together (eg. inside object AXIBundle)\nimplicit val axiView2 = AXIBundle.axiView.invert(ab => new VerilogAXIBundle(ab.addrWidth))\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The following example shows this and illustrates another use case of ",(0,i.jsx)(n.code,{children:"DataView"}),"\u2014connecting unrelated\ntypes:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class ConnectionExample extends RawModule {\n val in = IO(new AXIBundle(20))\n val out = IO(Flipped(new VerilogAXIBundle(20)))\n out.viewAs[AXIBundle] <> in\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"This results in the corresponding fields being connected in the emitted Verilog:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule ConnectionExample(\n input in_aw_ready,\n output in_aw_valid,\n output [3:0] in_aw_bits_id,\n output [19:0] in_aw_bits_addr,\n output [1:0] in_aw_bits_len,\n in_aw_bits_size,\n input out_AWVALID,\n output out_AWREADY,\n input [3:0] out_AWID,\n input [19:0] out_AWADDR,\n input [1:0] out_AWLEN,\n out_AWSIZE\n);\n\n assign in_aw_valid = out_AWVALID;\n assign in_aw_bits_id = out_AWID;\n assign in_aw_bits_addr = out_AWADDR;\n assign in_aw_bits_len = out_AWLEN;\n assign in_aw_bits_size = out_AWSIZE;\n assign out_AWREADY = in_aw_ready;\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.h2,{id:"other-use-cases",children:"Other Use Cases"}),"\n",(0,i.jsxs)(n.p,{children:["While the ability to map between ",(0,i.jsx)(n.code,{children:"Bundle"})," types as in the AXI4 example is pretty compelling,\nDataView has many other applications.\nImportantly, because the ",(0,i.jsx)(n.em,{children:"Target"})," of the ",(0,i.jsx)(n.code,{children:"DataView"})," need not be a ",(0,i.jsx)(n.code,{children:"Data"}),", it provides a way to use\n",(0,i.jsx)(n.code,{children:"non-Data"})," objects with APIs that require ",(0,i.jsx)(n.code,{children:"Data"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"tuples",children:"Tuples"}),"\n",(0,i.jsxs)(n.p,{children:["Perhaps the most helpful use of ",(0,i.jsx)(n.code,{children:"DataView"})," for a non-",(0,i.jsx)(n.code,{children:"Data"})," type is viewing Scala tuples as ",(0,i.jsx)(n.code,{children:"Bundles"}),".\nFor example, in Chisel prior to the introduction of ",(0,i.jsx)(n.code,{children:"DataView"}),", one might try to ",(0,i.jsx)(n.code,{children:"Mux"})," tuples and\nsee an error like the following:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class TupleExample extends RawModule {\n val a, b, c, d = IO(Input(UInt(8.W)))\n val cond = IO(Input(Bool()))\n val x, y = IO(Output(UInt(8.W)))\n (x, y) := Mux(cond, (a, b), (c, d))\n}\n// error: value := is not a member of (chisel3.UInt, chisel3.UInt)\n// Expression does not convert to assignment because receiver is not assignable.\n// (x, y) := Mux(cond, (a, b), (c, d))\n// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n// error: inferred type arguments [(chisel3.UInt, chisel3.UInt)] do not conform to macro method apply's type parameter bounds [T <: chisel3.Data]\n// (x, y) := Mux(cond, (a, b), (c, d))\n// ^^^\n// error: type mismatch;\n// found : (chisel3.UInt, chisel3.UInt)\n// required: T\n// (x, y) := Mux(cond, (a, b), (c, d))\n// ^^^^^^\n// error: type mismatch;\n// found : (chisel3.UInt, chisel3.UInt)\n// required: T\n// (x, y) := Mux(cond, (a, b), (c, d))\n// ^^^^^^\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The issue, is that Chisel primitives like ",(0,i.jsx)(n.code,{children:"Mux"})," and ",(0,i.jsx)(n.code,{children:":="})," only operate on subtypes of ",(0,i.jsx)(n.code,{children:"Data"})," and\nTuples (as members of the Scala standard library), are not subclasses of ",(0,i.jsx)(n.code,{children:"Data"}),".\n",(0,i.jsx)(n.code,{children:"DataView"})," provides a mechanism to ",(0,i.jsx)(n.em,{children:"view"})," a ",(0,i.jsx)(n.code,{children:"Tuple"})," as if it were a ",(0,i.jsx)(n.code,{children:"Data"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// We need a type to represent the Tuple\nclass HWTuple2[A <: Data, B <: Data](val _1: A, val _2: B) extends Bundle\n\n// Provide DataView between Tuple and HWTuple\nimplicit def view[A <: Data, B <: Data]: DataView[(A, B), HWTuple2[A, B]] =\n DataView(tup => new HWTuple2(tup._1.cloneType, tup._2.cloneType),\n _._1 -> _._1, _._2 -> _._2)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Now, we can use ",(0,i.jsx)(n.code,{children:".viewAs"})," to view Tuples as if they were subtypes of ",(0,i.jsx)(n.code,{children:"Data"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class TupleVerboseExample extends RawModule {\n val a, b, c, d = IO(Input(UInt(8.W)))\n val cond = IO(Input(Bool()))\n val x, y = IO(Output(UInt(8.W)))\n (x, y).viewAs[HWTuple2[UInt, UInt]] := Mux(cond, (a, b).viewAs[HWTuple2[UInt, UInt]], (c, d).viewAs[HWTuple2[UInt, UInt]])\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This is much more verbose than the original idea of just using the Tuples directly as if they were ",(0,i.jsx)(n.code,{children:"Data"}),".\nWe can make this better by providing an implicit conversion that views a ",(0,i.jsx)(n.code,{children:"Tuple"})," as a ",(0,i.jsx)(n.code,{children:"HWTuple2"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"implicit def tuple2hwtuple[A <: Data, B <: Data](tup: (A, B)): HWTuple2[A, B] =\n tup.viewAs[HWTuple2[A, B]]\n"})}),"\n",(0,i.jsx)(n.p,{children:"Now, the original code just works!"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class TupleExample extends RawModule {\n val a, b, c, d = IO(Input(UInt(8.W)))\n val cond = IO(Input(Bool()))\n val x, y = IO(Output(UInt(8.W)))\n (x, y) := Mux(cond, (a, b), (c, d))\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that this example ignored ",(0,i.jsx)(n.code,{children:"DataProduct"})," which is another required piece (see ",(0,i.jsx)(n.a,{href:"#dataproduct",children:"the documentation\nabout it below"}),")."]}),"\n",(0,i.jsx)(n.p,{children:"All of this is available to users via a single import:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.conversions._\n"})}),"\n",(0,i.jsx)(n.h2,{id:"totality-and-partialdataview",children:"Totality and PartialDataView"}),"\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.code,{children:"DataView"})," is ",(0,i.jsx)(n.em,{children:"total"})," if all fields of the ",(0,i.jsx)(n.em,{children:"Target"})," type and all fields of the ",(0,i.jsx)(n.em,{children:"View"})," type are\nincluded in the mapping.\nChisel will error if a field is accidentally left out from a ",(0,i.jsx)(n.code,{children:"DataView"}),".\nFor example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class BundleA extends Bundle {\n val foo = UInt(8.W)\n val bar = UInt(8.W)\n}\nclass BundleB extends Bundle {\n val fizz = UInt(8.W)\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// We forgot BundleA.foo in the mapping!\nimplicit val myView = DataView[BundleA, BundleB](_ => new BundleB, _.bar -> _.fizz)\nclass BadMapping extends Module {\n val in = IO(Input(new BundleA))\n val out = IO(Output(new BundleB))\n out := in.viewAs[BundleB]\n}\n// We must run Chisel to see the error\ngetVerilogString(new BadMapping)\n// chisel3.experimental.dataview.package$InvalidViewException: Viewing BadMapping.in: IO[BundleA] as BundleB is non-Total!\n// Target field '_.foo' is missing.\n// DataView used is DataView(defined @[dataview.md:228:49]).\n// If the view *should* be non-total, try a 'PartialDataView'.\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1$$anonfun$60.apply(dataview.md:232)\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1$$anonfun$60.apply(dataview.md:232)\n// \tat chisel3.DataImpl.$anonfun$$colon$eq$1(DataImpl.scala:807)\n// \tat scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:33)\n// \tat chisel3.DataImpl.$colon$eq(DataImpl.scala:807)\n// \tat chisel3.DataImpl.$colon$eq$(DataImpl.scala:805)\n// \tat chisel3.Data.$colon$eq(Data.scala:31)\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1.(dataview.md:232)\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$$anonfun$apply$67.apply(dataview.md:234)\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$$anonfun$apply$67.apply(dataview.md:234)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["As that error suggests, if we ",(0,i.jsx)(n.em,{children:"want"})," the view to be non-total, we can use a ",(0,i.jsx)(n.code,{children:"PartialDataView"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// A PartialDataView does not have to be total for the Target\nimplicit val myView = PartialDataView[BundleA, BundleB](_ => new BundleB, _.bar -> _.fizz)\n// myView: DataView[BundleA, BundleB] = PartialDataView(defined @[dataview.md:243:56])\nclass PartialDataViewModule extends Module {\n val in = IO(Input(new BundleA))\n val out = IO(Output(new BundleB))\n out := in.viewAs[BundleB]\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PartialDataViewModule(\n input clock,\n reset,\n input [7:0] in_foo,\n in_bar,\n output [7:0] out_fizz\n);\n\n assign out_fizz = in_bar;\nendmodule\n\n"})}),"\n",(0,i.jsxs)(n.p,{children:["While ",(0,i.jsx)(n.code,{children:"PartialDataViews"})," need not be total for the ",(0,i.jsx)(n.em,{children:"Target"}),", both ",(0,i.jsx)(n.code,{children:"PartialDataViews"})," and ",(0,i.jsx)(n.code,{children:"DataViews"}),"\nmust always be total for the ",(0,i.jsx)(n.em,{children:"View"}),".\nThis has the consequence that ",(0,i.jsx)(n.code,{children:"PartialDataViews"})," are ",(0,i.jsx)(n.strong,{children:"not"})," invertible in the same way as ",(0,i.jsx)(n.code,{children:"DataViews"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"implicit val myView2 = myView.invert(_ => new BundleA)\nclass PartialDataViewModule2 extends Module {\n val in = IO(Input(new BundleA))\n val out = IO(Output(new BundleB))\n // Using the inverted version of the mapping\n out.viewAs[BundleA] := in\n}\n// We must run Chisel to see the error\ngetVerilogString(new PartialDataViewModule2)\n// chisel3.experimental.dataview.package$InvalidViewException: Cannot invert 'PartialDataView(defined @[dataview.md:243:56])' as it is non-total.\n// Try providing a DataView[MdocApp6.this.BundleB, MdocApp6.this.BundleA].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview.\n// \tat chisel3.experimental.dataview.DataView$InvertibleDataView.invert(DataView.scala:136)\n// \tat repl.MdocSession$MdocApp6$$anonfun$67.apply(dataview.md:263)\n// \tat repl.MdocSession$MdocApp6$$anonfun$67.apply(dataview.md:262)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["As noted, the mapping must ",(0,i.jsx)(n.strong,{children:"always"})," be total for the ",(0,i.jsx)(n.code,{children:"View"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"advanced-details",children:"Advanced Details"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"DataView"})," takes advantage of features of Scala that may be new to many users of Chisel\u2014in particular\n",(0,i.jsx)(n.a,{href:"#type-classes",children:"Type Classes"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"type-classes",children:"Type Classes"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Type_class",children:"Type classes"}),' are powerful language feature for writing\npolymorphic code.\nThey are a common feature in "modern programming languages" like\nScala,\nSwift (see ',(0,i.jsx)(n.a,{href:"https://docs.swift.org/swift-book/LanguageGuide/Protocols.html",children:"protocols"}),"),\nand Rust (see ",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/book/ch10-02-traits.html",children:"traits"}),").\nType classes may appear similar to inheritance in object-oriented programming but there are some\nimportant differences:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"You can provide a type class for a type you don't own (eg. one defined in a 3rd party library,\nthe Scala standard library, or Chisel itself)"}),"\n",(0,i.jsx)(n.li,{children:"You can write a single type class for many types that do not have a sub-typing relationship"}),"\n",(0,i.jsx)(n.li,{children:"You can provide multiple different type classes for the same type"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["For ",(0,i.jsx)(n.code,{children:"DataView"}),", (1) is crucial because we want to be able to implement ",(0,i.jsx)(n.code,{children:"DataViews"})," of built-in Scala\ntypes like tuples and ",(0,i.jsx)(n.code,{children:"Seqs"}),". Furthermore, ",(0,i.jsx)(n.code,{children:"DataView"})," has two type parameters (the ",(0,i.jsx)(n.em,{children:"Target"})," and the\n",(0,i.jsx)(n.em,{children:"View"})," types) so inheritance does not really make sense\u2014which type would ",(0,i.jsx)(n.code,{children:"extend"})," ",(0,i.jsx)(n.code,{children:"DataView"}),"?"]}),"\n",(0,i.jsx)(n.p,{children:"In Scala 2, type classes are not a built-in language feature, but rather are implemented using implicits.\nThere are great resources out there for interested readers:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://scalac.io/blog/typeclasses-in-scala/",children:"Basic Tutorial"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://stackoverflow.com/a/5598107/2483329",children:"Fantastic Explanation on StackOverflow"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Note that Scala 3 has added built-in syntax for type classes that does not apply to Chisel 3 which\ncurrently only supports Scala 2."}),"\n",(0,i.jsx)(n.h3,{id:"implicit-resolution",children:"Implicit Resolution"}),"\n",(0,i.jsxs)(n.p,{children:["Given that ",(0,i.jsx)(n.code,{children:"DataView"})," is implemented using implicits, it is important to understand implicit\nresolution.\nWhenever the compiler sees an implicit argument is required, it first looks in ",(0,i.jsx)(n.em,{children:"current scope"}),"\nbefore looking in the ",(0,i.jsx)(n.em,{children:"implicit scope"}),"."]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Current scope","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Values defined in the current scope"}),"\n",(0,i.jsx)(n.li,{children:"Explicit imports"}),"\n",(0,i.jsx)(n.li,{children:"Wildcard imports"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Implicit scope","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Companion object of a type"}),"\n",(0,i.jsx)(n.li,{children:"Implicit scope of an argument's type"}),"\n",(0,i.jsx)(n.li,{children:"Implicit scope of type parameters"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"If at either stage, multiple implicits are found, then the static overloading rule is used to resolve\nit.\nPut simply, if one implicit applies to a more-specific type than the other, the more-specific one\nwill be selected.\nIf multiple implicits apply within a given stage, then the compiler throws an ambiguous implicit\nresolution error."}),"\n",(0,i.jsxs)(n.p,{children:["This section draws heavily from ",(0,i.jsx)(n.a,{href:"https://stackoverflow.com/a/5598107/2483329",children:"[1]"})," and\n",(0,i.jsx)(n.a,{href:"https://stackoverflow.com/a/8694558/2483329",children:"[2]"}),".\nIn particular, see [1] for examples."]}),"\n",(0,i.jsx)(n.h4,{id:"implicit-resolution-example",children:"Implicit Resolution Example"}),"\n",(0,i.jsxs)(n.p,{children:["To help clarify a bit, let us consider how implicit resolution works for ",(0,i.jsx)(n.code,{children:"DataView"}),".\nConsider the definition of ",(0,i.jsx)(n.code,{children:"viewAs"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"def viewAs[V <: Data](implicit dataView: DataView[T, V]): V\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Armed with the knowledge from the previous section, we know that whenever we call ",(0,i.jsx)(n.code,{children:".viewAs"}),", the\nScala compiler will first look for a ",(0,i.jsx)(n.code,{children:"DataView[T, V]"})," in the current scope (defined in, or imported),\nthen it will look in the companion objects of ",(0,i.jsx)(n.code,{children:"DataView"}),", ",(0,i.jsx)(n.code,{children:"T"}),", and ",(0,i.jsx)(n.code,{children:"V"}),".\nThis enables a fairly powerful pattern, namely that default or typical implementations of a ",(0,i.jsx)(n.code,{children:"DataView"}),"\nshould be defined in the companion object for one of the two types.\nWe can think about ",(0,i.jsx)(n.code,{children:"DataViews"}),' defined in this way as "low priority defaults".\nThey can then be overruled by a specific import if a given user ever wants different behavior.\nFor example:']}),"\n",(0,i.jsx)(n.p,{children:"Given the following types:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class Foo extends Bundle {\n val a = UInt(8.W)\n val b = UInt(8.W)\n}\nclass Bar extends Bundle {\n val c = UInt(8.W)\n val d = UInt(8.W)\n}\nobject Foo {\n implicit val f2b = DataView[Foo, Bar](_ => new Bar, _.a -> _.c, _.b -> _.d)\n implicit val b2f = f2b.invert(_ => new Foo)\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This provides an implementation of ",(0,i.jsx)(n.code,{children:"DataView"})," in the ",(0,i.jsx)(n.em,{children:"implicit scope"}),' as a "default" mapping between\n',(0,i.jsx)(n.code,{children:"Foo"})," and ",(0,i.jsx)(n.code,{children:"Bar"})," (and it doesn't even require an import!):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class FooToBar extends Module {\n val foo = IO(Input(new Foo))\n val bar = IO(Output(new Bar))\n bar := foo.viewAs[Bar]\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule FooToBar(\n input clock,\n reset,\n input [7:0] foo_a,\n foo_b,\n output [7:0] bar_c,\n bar_d\n);\n\n assign bar_c = foo_a;\n assign bar_d = foo_b;\nendmodule\n\n"})}),"\n",(0,i.jsxs)(n.p,{children:["However, it's possible that some user of ",(0,i.jsx)(n.code,{children:"Foo"})," and ",(0,i.jsx)(n.code,{children:"Bar"}),' wants different behavior,\nperhaps they would prefer more of "swizzling" behavior rather than a direct mapping:']}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"object Swizzle {\n implicit val swizzle = DataView[Foo, Bar](_ => new Bar, _.a -> _.d, _.b -> _.c)\n}\n// Current scope always wins over implicit scope\nimport Swizzle._\nclass FooToBarSwizzled extends Module {\n val foo = IO(Input(new Foo))\n val bar = IO(Output(new Bar))\n bar := foo.viewAs[Bar]\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule FooToBarSwizzled(\n input clock,\n reset,\n input [7:0] foo_a,\n foo_b,\n output [7:0] bar_c,\n bar_d\n);\n\n assign bar_c = foo_b;\n assign bar_d = foo_a;\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.h3,{id:"dataproduct",children:"DataProduct"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"DataProduct"})," is a type class used by ",(0,i.jsx)(n.code,{children:"DataView"}),' to validate the correctness of a user-provided mapping.\nIn order for a type to be "viewable" (ie. the ',(0,i.jsx)(n.code,{children:"Target"})," type of a ",(0,i.jsx)(n.code,{children:"DataView"}),"), it must have an\nimplementation of ",(0,i.jsx)(n.code,{children:"DataProduct"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"For example, say we have some non-Bundle type:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// Loosely based on chisel3.util.Counter\nclass MyCounter(val width: Int) {\n /** Indicates if the Counter is incrementing this cycle */\n val active = WireDefault(false.B)\n val value = RegInit(0.U(width.W))\n def inc(): Unit = {\n active := true.B\n value := value + 1.U\n }\n def reset(): Unit = {\n value := 0.U\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Say we want to view ",(0,i.jsx)(n.code,{children:"MyCounter"})," as a ",(0,i.jsx)(n.code,{children:"Valid[UInt]"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.Valid\nimplicit val counterView = DataView[MyCounter, Valid[UInt]](c => Valid(UInt(c.width.W)), _.value -> _.bits, _.active -> _.valid)\n// error: myView is already defined as value myView\n// implicit val myView = PartialDataView[BundleA, BundleB](_ => new BundleB, _.bar -> _.fizz)\n// ^^^^^^\n// error: Could not find implicit value for DataView[MdocApp1.this.BundleA, MdocApp1.this.BundleB].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview\n// out := in.viewAs[BundleB]\n// ^^^^^^^^^^^^^^^^^^\n// error: Could not find implicit value for DataView[MdocApp1.this.BundleA, MdocApp1.this.BundleB].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview\n// out := in.viewAs[BundleB]\n// ^^^^^^^^^^^^^^^^^^\n// error: Could not find implicit value for DataView[MdocApp1.this.BundleB, MdocApp1.this.BundleA].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview\n// out.viewAs[BundleA] := in\n// ^^^^^^^^^^^^^^^^^^^\n// error: Could not find implicit value for DataProduct[MdocApp1.this.MyCounter].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct\n// implicit val counterView = DataView[MyCounter, Valid[UInt]](c => Valid(UInt(c.width.W)), _.value -> _.bits, _.active -> _.valid)\n// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"})}),"\n",(0,i.jsxs)(n.p,{children:["As you can see, this fails Scala compliation.\nWe need to provide an implementation of ",(0,i.jsx)(n.code,{children:"DataProduct[MyCounter]"})," which provides Chisel a way to access\nthe objects of type ",(0,i.jsx)(n.code,{children:"Data"})," within ",(0,i.jsx)(n.code,{children:"MyCounter"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'import chisel3.util.Valid\nimplicit val counterProduct = new DataProduct[MyCounter] {\n // The String part of the tuple is a String path to the object to help in debugging\n def dataIterator(a: MyCounter, path: String): Iterator[(Data, String)] =\n List(a.value -> s"$path.value", a.active -> s"$path.active").iterator\n}\n// Now this works\nimplicit val counterView = DataView[MyCounter, Valid[UInt]](c => Valid(UInt(c.width.W)), _.value -> _.bits, _.active -> _.valid)\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Why is this useful?\nThis is how Chisel is able to check for totality as ",(0,i.jsx)(n.a,{href:"#totality-and-partialdataview",children:"described above"}),".\nIn addition to checking if a user has left a field out of the mapping, it also allows Chisel to check\nif the user has included a ",(0,i.jsx)(n.code,{children:"Data"})," in the mapping that isn't actually a part of the ",(0,i.jsx)(n.em,{children:"target"})," nor the\n",(0,i.jsx)(n.em,{children:"view"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>s,x:()=>o});var i=a(6540);const t={},l=i.createContext(t);function s(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[7132],{2869:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>r});var i=a(4848),t=a(8453);const l={layout:"docs",title:"DataView",section:"chisel3"},s="DataView",o={id:"explanations/dataview",title:"DataView",description:"New in Chisel 3.5",source:"@site/docs/explanations/dataview.md",sourceDirName:"explanations",slug:"/explanations/dataview",permalink:"/docs/explanations/dataview",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/dataview.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"DataView",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Chisel Data Types",permalink:"/docs/explanations/data-types"},next:{title:"Decoders",permalink:"/docs/explanations/decoder"}},d={},r=[{value:"Introduction",id:"introduction",level:2},{value:"A Motivating Example (AXI4)",id:"a-motivating-example-axi4",level:2},{value:"Other Use Cases",id:"other-use-cases",level:2},{value:"Tuples",id:"tuples",level:3},{value:"Totality and PartialDataView",id:"totality-and-partialdataview",level:2},{value:"Advanced Details",id:"advanced-details",level:2},{value:"Type Classes",id:"type-classes",level:3},{value:"Implicit Resolution",id:"implicit-resolution",level:3},{value:"Implicit Resolution Example",id:"implicit-resolution-example",level:4},{value:"DataProduct",id:"dataproduct",level:3}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"dataview",children:"DataView"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.em,{children:"New in Chisel 3.5"})}),"\n",(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(n.p,{children:['DataView is a mechanism for "viewing" Scala objects as a subtype of ',(0,i.jsx)(n.code,{children:"chisel3.Data"}),".\nOften, this is useful for viewing one subtype of ",(0,i.jsx)(n.code,{children:"chisel3.Data"}),", as another.\nOne can think about a ",(0,i.jsx)(n.code,{children:"DataView"})," as a mapping from a ",(0,i.jsx)(n.em,{children:"Target"})," type ",(0,i.jsx)(n.code,{children:"T"})," to a ",(0,i.jsx)(n.em,{children:"View"})," type ",(0,i.jsx)(n.code,{children:"V"}),".\nThis is similar to a cast (eg. ",(0,i.jsx)(n.code,{children:".asTypeOf"}),") with a few differences:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Views are ",(0,i.jsx)(n.em,{children:"connectable"}),"\u2014connections to the view will occur on the target"]}),"\n",(0,i.jsxs)(n.li,{children:["Whereas casts are ",(0,i.jsx)(n.em,{children:"structural"})," (a reinterpretation of the underlying bits), a DataView is a customizable mapping"]}),"\n",(0,i.jsxs)(n.li,{children:["Views can be ",(0,i.jsx)(n.em,{children:"partial"}),"\u2014not every field in the target must be included in the mapping"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"a-motivating-example-axi4",children:"A Motivating Example (AXI4)"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Advanced_eXtensible_Interface",children:"AXI4"})," is a common interface in digital\ndesign.\nA typical Verilog peripheral using AXI4 will define a write channel as something like:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"module my_module(\n // Write Channel\n input AXI_AWVALID,\n output AXI_AWREADY,\n input [3:0] AXI_AWID,\n input [19:0] AXI_AWADDR,\n input [1:0] AXI_AWLEN,\n input [1:0] AXI_AWSIZE,\n // ...\n);\n"})}),"\n",(0,i.jsx)(n.p,{children:"This would correspond to the following Chisel Bundle:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class VerilogAXIBundle(val addrWidth: Int) extends Bundle {\n val AWVALID = Output(Bool())\n val AWREADY = Input(Bool())\n val AWID = Output(UInt(4.W))\n val AWADDR = Output(UInt(addrWidth.W))\n val AWLEN = Output(UInt(2.W))\n val AWSIZE = Output(UInt(2.W))\n // The rest of AW and other AXI channels here\n}\n\n// Instantiated as\nclass my_module extends RawModule {\n val AXI = IO(new VerilogAXIBundle(20))\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Expressing something that matches a standard Verilog interface is important when instantiating Verilog\nmodules in a Chisel design as ",(0,i.jsx)(n.code,{children:"BlackBoxes"}),".\nGenerally though, Chisel developers prefer to use composition via utilities like ",(0,i.jsx)(n.code,{children:"Decoupled"})," rather\nthan a flat handling of ",(0,i.jsx)(n.code,{children:"ready"})," and ",(0,i.jsx)(n.code,{children:"valid"}),' as in the above.\nA more "Chisel-y" implementation of this interface might look like:']}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// Note that both the AW and AR channels look similar and could use the same Bundle definition\nclass AXIAddressChannel(val addrWidth: Int) extends Bundle {\n val id = UInt(4.W)\n val addr = UInt(addrWidth.W)\n val len = UInt(2.W)\n val size = UInt(2.W)\n // ...\n}\nimport chisel3.util.Decoupled\n// We can compose the various AXI channels together\nclass AXIBundle(val addrWidth: Int) extends Bundle {\n val aw = Decoupled(new AXIAddressChannel(addrWidth))\n // val ar = new AXIAddressChannel\n // ... Other channels here ...\n}\n// Instantiated as\nclass MyModule extends RawModule {\n val axi = IO(new AXIBundle(20))\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Of course, this would result in very different looking Verilog:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule MyModule(\n input axi_aw_ready,\n output axi_aw_valid,\n output [3:0] axi_aw_bits_id,\n output [19:0] axi_aw_bits_addr,\n output [1:0] axi_aw_bits_len,\n axi_aw_bits_size\n);\n\n assign axi_aw_valid = 1'h0;\n assign axi_aw_bits_id = 4'h0;\n assign axi_aw_bits_addr = 20'h0;\n assign axi_aw_bits_len = 2'h0;\n assign axi_aw_bits_size = 2'h0;\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.p,{children:"So how can we use our more structured types while maintaining expected Verilog interfaces?\nMeet DataView:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.dataview._\n\n// We recommend putting DataViews in a companion object of one of the involved types\nobject AXIBundle {\n // Don't be afraid of the use of implicits, we will discuss this pattern in more detail later\n implicit val axiView = DataView[VerilogAXIBundle, AXIBundle](\n // The first argument is a function constructing an object of View type (AXIBundle)\n // from an object of the Target type (VerilogAXIBundle)\n vab => new AXIBundle(vab.addrWidth),\n // The remaining arguments are a mapping of the corresponding fields of the two types\n _.AWVALID -> _.aw.valid,\n _.AWREADY -> _.aw.ready,\n _.AWID -> _.aw.bits.id,\n _.AWADDR -> _.aw.bits.addr,\n _.AWLEN -> _.aw.bits.len,\n _.AWSIZE -> _.aw.bits.size,\n // ...\n )\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This ",(0,i.jsx)(n.code,{children:"DataView"})," is a mapping between our flat, Verilog-style AXI Bundle to our more compositional,\nChisel-style AXI Bundle.\nIt allows us to define our ports to match the expected Verilog interface, while manipulating it as if\nit were the more structured type:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class AXIStub extends RawModule {\n val AXI = IO(new VerilogAXIBundle(20))\n val view = AXI.viewAs[AXIBundle]\n\n // We can now manipulate `AXI` via `view`\n view.aw.bits := 0.U.asTypeOf(new AXIAddressChannel(20)) // zero everything out by default\n view.aw.valid := true.B\n when (view.aw.ready) {\n view.aw.bits.id := 5.U\n view.aw.bits.addr := 1234.U\n // We can still manipulate AXI as well\n AXI.AWLEN := 1.U\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"This will generate Verilog that matches the standard naming convention:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule AXIStub(\n output AXI_AWVALID,\n input AXI_AWREADY,\n output [3:0] AXI_AWID,\n output [19:0] AXI_AWADDR,\n output [1:0] AXI_AWLEN,\n AXI_AWSIZE\n);\n\n assign AXI_AWVALID = 1'h1;\n assign AXI_AWID = AXI_AWREADY ? 4'h5 : 4'h0;\n assign AXI_AWADDR = AXI_AWREADY ? 20'h4D2 : 20'h0;\n assign AXI_AWLEN = {1'h0, AXI_AWREADY};\n assign AXI_AWSIZE = 2'h0;\nendmodule\n\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that if both the ",(0,i.jsx)(n.em,{children:"Target"})," and the ",(0,i.jsx)(n.em,{children:"View"})," types are subtypes of ",(0,i.jsx)(n.code,{children:"Data"})," (as they are in this example),\nthe ",(0,i.jsx)(n.code,{children:"DataView"})," is ",(0,i.jsx)(n.em,{children:"invertible"}),".\nThis means that we can easily create a ",(0,i.jsx)(n.code,{children:"DataView[AXIBundle, VerilogAXIBundle]"})," from our existing\n",(0,i.jsx)(n.code,{children:"DataView[VerilogAXIBundle, AXIBundle]"}),", all we need to do is provide a function to construct\na ",(0,i.jsx)(n.code,{children:"VerilogAXIBundle"})," from an instance of an ",(0,i.jsx)(n.code,{children:"AXIBundle"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// Note that typically you should define these together (eg. inside object AXIBundle)\nimplicit val axiView2 = AXIBundle.axiView.invert(ab => new VerilogAXIBundle(ab.addrWidth))\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The following example shows this and illustrates another use case of ",(0,i.jsx)(n.code,{children:"DataView"}),"\u2014connecting unrelated\ntypes:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class ConnectionExample extends RawModule {\n val in = IO(new AXIBundle(20))\n val out = IO(Flipped(new VerilogAXIBundle(20)))\n out.viewAs[AXIBundle] <> in\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"This results in the corresponding fields being connected in the emitted Verilog:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule ConnectionExample(\n input in_aw_ready,\n output in_aw_valid,\n output [3:0] in_aw_bits_id,\n output [19:0] in_aw_bits_addr,\n output [1:0] in_aw_bits_len,\n in_aw_bits_size,\n input out_AWVALID,\n output out_AWREADY,\n input [3:0] out_AWID,\n input [19:0] out_AWADDR,\n input [1:0] out_AWLEN,\n out_AWSIZE\n);\n\n assign in_aw_valid = out_AWVALID;\n assign in_aw_bits_id = out_AWID;\n assign in_aw_bits_addr = out_AWADDR;\n assign in_aw_bits_len = out_AWLEN;\n assign in_aw_bits_size = out_AWSIZE;\n assign out_AWREADY = in_aw_ready;\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.h2,{id:"other-use-cases",children:"Other Use Cases"}),"\n",(0,i.jsxs)(n.p,{children:["While the ability to map between ",(0,i.jsx)(n.code,{children:"Bundle"})," types as in the AXI4 example is pretty compelling,\nDataView has many other applications.\nImportantly, because the ",(0,i.jsx)(n.em,{children:"Target"})," of the ",(0,i.jsx)(n.code,{children:"DataView"})," need not be a ",(0,i.jsx)(n.code,{children:"Data"}),", it provides a way to use\n",(0,i.jsx)(n.code,{children:"non-Data"})," objects with APIs that require ",(0,i.jsx)(n.code,{children:"Data"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"tuples",children:"Tuples"}),"\n",(0,i.jsxs)(n.p,{children:["Perhaps the most helpful use of ",(0,i.jsx)(n.code,{children:"DataView"})," for a non-",(0,i.jsx)(n.code,{children:"Data"})," type is viewing Scala tuples as ",(0,i.jsx)(n.code,{children:"Bundles"}),".\nFor example, in Chisel prior to the introduction of ",(0,i.jsx)(n.code,{children:"DataView"}),", one might try to ",(0,i.jsx)(n.code,{children:"Mux"})," tuples and\nsee an error like the following:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class TupleExample extends RawModule {\n val a, b, c, d = IO(Input(UInt(8.W)))\n val cond = IO(Input(Bool()))\n val x, y = IO(Output(UInt(8.W)))\n (x, y) := Mux(cond, (a, b), (c, d))\n}\n// error: value := is not a member of (chisel3.UInt, chisel3.UInt)\n// Expression does not convert to assignment because receiver is not assignable.\n// (x, y) := Mux(cond, (a, b), (c, d))\n// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n// error: inferred type arguments [(chisel3.UInt, chisel3.UInt)] do not conform to macro method apply's type parameter bounds [T <: chisel3.Data]\n// (x, y) := Mux(cond, (a, b), (c, d))\n// ^^^\n// error: type mismatch;\n// found : (chisel3.UInt, chisel3.UInt)\n// required: T\n// (x, y) := Mux(cond, (a, b), (c, d))\n// ^^^^^^\n// error: type mismatch;\n// found : (chisel3.UInt, chisel3.UInt)\n// required: T\n// (x, y) := Mux(cond, (a, b), (c, d))\n// ^^^^^^\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The issue, is that Chisel primitives like ",(0,i.jsx)(n.code,{children:"Mux"})," and ",(0,i.jsx)(n.code,{children:":="})," only operate on subtypes of ",(0,i.jsx)(n.code,{children:"Data"})," and\nTuples (as members of the Scala standard library), are not subclasses of ",(0,i.jsx)(n.code,{children:"Data"}),".\n",(0,i.jsx)(n.code,{children:"DataView"})," provides a mechanism to ",(0,i.jsx)(n.em,{children:"view"})," a ",(0,i.jsx)(n.code,{children:"Tuple"})," as if it were a ",(0,i.jsx)(n.code,{children:"Data"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// We need a type to represent the Tuple\nclass HWTuple2[A <: Data, B <: Data](val _1: A, val _2: B) extends Bundle\n\n// Provide DataView between Tuple and HWTuple\nimplicit def view[A <: Data, B <: Data]: DataView[(A, B), HWTuple2[A, B]] =\n DataView(tup => new HWTuple2(tup._1.cloneType, tup._2.cloneType),\n _._1 -> _._1, _._2 -> _._2)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Now, we can use ",(0,i.jsx)(n.code,{children:".viewAs"})," to view Tuples as if they were subtypes of ",(0,i.jsx)(n.code,{children:"Data"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class TupleVerboseExample extends RawModule {\n val a, b, c, d = IO(Input(UInt(8.W)))\n val cond = IO(Input(Bool()))\n val x, y = IO(Output(UInt(8.W)))\n (x, y).viewAs[HWTuple2[UInt, UInt]] := Mux(cond, (a, b).viewAs[HWTuple2[UInt, UInt]], (c, d).viewAs[HWTuple2[UInt, UInt]])\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This is much more verbose than the original idea of just using the Tuples directly as if they were ",(0,i.jsx)(n.code,{children:"Data"}),".\nWe can make this better by providing an implicit conversion that views a ",(0,i.jsx)(n.code,{children:"Tuple"})," as a ",(0,i.jsx)(n.code,{children:"HWTuple2"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"implicit def tuple2hwtuple[A <: Data, B <: Data](tup: (A, B)): HWTuple2[A, B] =\n tup.viewAs[HWTuple2[A, B]]\n"})}),"\n",(0,i.jsx)(n.p,{children:"Now, the original code just works!"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class TupleExample extends RawModule {\n val a, b, c, d = IO(Input(UInt(8.W)))\n val cond = IO(Input(Bool()))\n val x, y = IO(Output(UInt(8.W)))\n (x, y) := Mux(cond, (a, b), (c, d))\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that this example ignored ",(0,i.jsx)(n.code,{children:"DataProduct"})," which is another required piece (see ",(0,i.jsx)(n.a,{href:"#dataproduct",children:"the documentation\nabout it below"}),")."]}),"\n",(0,i.jsx)(n.p,{children:"All of this is available to users via a single import:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.conversions._\n"})}),"\n",(0,i.jsx)(n.h2,{id:"totality-and-partialdataview",children:"Totality and PartialDataView"}),"\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.code,{children:"DataView"})," is ",(0,i.jsx)(n.em,{children:"total"})," if all fields of the ",(0,i.jsx)(n.em,{children:"Target"})," type and all fields of the ",(0,i.jsx)(n.em,{children:"View"})," type are\nincluded in the mapping.\nChisel will error if a field is accidentally left out from a ",(0,i.jsx)(n.code,{children:"DataView"}),".\nFor example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class BundleA extends Bundle {\n val foo = UInt(8.W)\n val bar = UInt(8.W)\n}\nclass BundleB extends Bundle {\n val fizz = UInt(8.W)\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// We forgot BundleA.foo in the mapping!\nimplicit val myView = DataView[BundleA, BundleB](_ => new BundleB, _.bar -> _.fizz)\nclass BadMapping extends Module {\n val in = IO(Input(new BundleA))\n val out = IO(Output(new BundleB))\n out := in.viewAs[BundleB]\n}\n// We must run Chisel to see the error\ngetVerilogString(new BadMapping)\n// chisel3.experimental.dataview.package$InvalidViewException: Viewing BadMapping.in: IO[BundleA] as BundleB is non-Total!\n// Target field '_.foo' is missing.\n// DataView used is DataView(defined @[dataview.md:228:49]).\n// If the view *should* be non-total, try a 'PartialDataView'.\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1$$anonfun$60.apply(dataview.md:232)\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1$$anonfun$60.apply(dataview.md:232)\n// \tat chisel3.DataImpl.$anonfun$$colon$eq$1(DataImpl.scala:807)\n// \tat scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:33)\n// \tat chisel3.DataImpl.$colon$eq(DataImpl.scala:807)\n// \tat chisel3.DataImpl.$colon$eq$(DataImpl.scala:805)\n// \tat chisel3.Data.$colon$eq(Data.scala:31)\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1.(dataview.md:232)\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$$anonfun$apply$67.apply(dataview.md:234)\n// \tat repl.MdocSession$MdocApp6$$anonfun$55$$anonfun$apply$67.apply(dataview.md:234)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["As that error suggests, if we ",(0,i.jsx)(n.em,{children:"want"})," the view to be non-total, we can use a ",(0,i.jsx)(n.code,{children:"PartialDataView"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// A PartialDataView does not have to be total for the Target\nimplicit val myView = PartialDataView[BundleA, BundleB](_ => new BundleB, _.bar -> _.fizz)\n// myView: DataView[BundleA, BundleB] = PartialDataView(defined @[dataview.md:243:56])\nclass PartialDataViewModule extends Module {\n val in = IO(Input(new BundleA))\n val out = IO(Output(new BundleB))\n out := in.viewAs[BundleB]\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PartialDataViewModule(\n input clock,\n reset,\n input [7:0] in_foo,\n in_bar,\n output [7:0] out_fizz\n);\n\n assign out_fizz = in_bar;\nendmodule\n\n"})}),"\n",(0,i.jsxs)(n.p,{children:["While ",(0,i.jsx)(n.code,{children:"PartialDataViews"})," need not be total for the ",(0,i.jsx)(n.em,{children:"Target"}),", both ",(0,i.jsx)(n.code,{children:"PartialDataViews"})," and ",(0,i.jsx)(n.code,{children:"DataViews"}),"\nmust always be total for the ",(0,i.jsx)(n.em,{children:"View"}),".\nThis has the consequence that ",(0,i.jsx)(n.code,{children:"PartialDataViews"})," are ",(0,i.jsx)(n.strong,{children:"not"})," invertible in the same way as ",(0,i.jsx)(n.code,{children:"DataViews"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"implicit val myView2 = myView.invert(_ => new BundleA)\nclass PartialDataViewModule2 extends Module {\n val in = IO(Input(new BundleA))\n val out = IO(Output(new BundleB))\n // Using the inverted version of the mapping\n out.viewAs[BundleA] := in\n}\n// We must run Chisel to see the error\ngetVerilogString(new PartialDataViewModule2)\n// chisel3.experimental.dataview.package$InvalidViewException: Cannot invert 'PartialDataView(defined @[dataview.md:243:56])' as it is non-total.\n// Try providing a DataView[MdocApp6.this.BundleB, MdocApp6.this.BundleA].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview.\n// \tat chisel3.experimental.dataview.DataView$InvertibleDataView.invert(DataView.scala:136)\n// \tat repl.MdocSession$MdocApp6$$anonfun$67.apply(dataview.md:263)\n// \tat repl.MdocSession$MdocApp6$$anonfun$67.apply(dataview.md:262)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["As noted, the mapping must ",(0,i.jsx)(n.strong,{children:"always"})," be total for the ",(0,i.jsx)(n.code,{children:"View"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"advanced-details",children:"Advanced Details"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"DataView"})," takes advantage of features of Scala that may be new to many users of Chisel\u2014in particular\n",(0,i.jsx)(n.a,{href:"#type-classes",children:"Type Classes"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"type-classes",children:"Type Classes"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Type_class",children:"Type classes"}),' are powerful language feature for writing\npolymorphic code.\nThey are a common feature in "modern programming languages" like\nScala,\nSwift (see ',(0,i.jsx)(n.a,{href:"https://docs.swift.org/swift-book/LanguageGuide/Protocols.html",children:"protocols"}),"),\nand Rust (see ",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/book/ch10-02-traits.html",children:"traits"}),").\nType classes may appear similar to inheritance in object-oriented programming but there are some\nimportant differences:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"You can provide a type class for a type you don't own (eg. one defined in a 3rd party library,\nthe Scala standard library, or Chisel itself)"}),"\n",(0,i.jsx)(n.li,{children:"You can write a single type class for many types that do not have a sub-typing relationship"}),"\n",(0,i.jsx)(n.li,{children:"You can provide multiple different type classes for the same type"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["For ",(0,i.jsx)(n.code,{children:"DataView"}),", (1) is crucial because we want to be able to implement ",(0,i.jsx)(n.code,{children:"DataViews"})," of built-in Scala\ntypes like tuples and ",(0,i.jsx)(n.code,{children:"Seqs"}),". Furthermore, ",(0,i.jsx)(n.code,{children:"DataView"})," has two type parameters (the ",(0,i.jsx)(n.em,{children:"Target"})," and the\n",(0,i.jsx)(n.em,{children:"View"})," types) so inheritance does not really make sense\u2014which type would ",(0,i.jsx)(n.code,{children:"extend"})," ",(0,i.jsx)(n.code,{children:"DataView"}),"?"]}),"\n",(0,i.jsx)(n.p,{children:"In Scala 2, type classes are not a built-in language feature, but rather are implemented using implicits.\nThere are great resources out there for interested readers:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://scalac.io/blog/typeclasses-in-scala/",children:"Basic Tutorial"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://stackoverflow.com/a/5598107/2483329",children:"Fantastic Explanation on StackOverflow"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Note that Scala 3 has added built-in syntax for type classes that does not apply to Chisel 3 which\ncurrently only supports Scala 2."}),"\n",(0,i.jsx)(n.h3,{id:"implicit-resolution",children:"Implicit Resolution"}),"\n",(0,i.jsxs)(n.p,{children:["Given that ",(0,i.jsx)(n.code,{children:"DataView"})," is implemented using implicits, it is important to understand implicit\nresolution.\nWhenever the compiler sees an implicit argument is required, it first looks in ",(0,i.jsx)(n.em,{children:"current scope"}),"\nbefore looking in the ",(0,i.jsx)(n.em,{children:"implicit scope"}),"."]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Current scope","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Values defined in the current scope"}),"\n",(0,i.jsx)(n.li,{children:"Explicit imports"}),"\n",(0,i.jsx)(n.li,{children:"Wildcard imports"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Implicit scope","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Companion object of a type"}),"\n",(0,i.jsx)(n.li,{children:"Implicit scope of an argument's type"}),"\n",(0,i.jsx)(n.li,{children:"Implicit scope of type parameters"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"If at either stage, multiple implicits are found, then the static overloading rule is used to resolve\nit.\nPut simply, if one implicit applies to a more-specific type than the other, the more-specific one\nwill be selected.\nIf multiple implicits apply within a given stage, then the compiler throws an ambiguous implicit\nresolution error."}),"\n",(0,i.jsxs)(n.p,{children:["This section draws heavily from ",(0,i.jsx)(n.a,{href:"https://stackoverflow.com/a/5598107/2483329",children:"[1]"})," and\n",(0,i.jsx)(n.a,{href:"https://stackoverflow.com/a/8694558/2483329",children:"[2]"}),".\nIn particular, see [1] for examples."]}),"\n",(0,i.jsx)(n.h4,{id:"implicit-resolution-example",children:"Implicit Resolution Example"}),"\n",(0,i.jsxs)(n.p,{children:["To help clarify a bit, let us consider how implicit resolution works for ",(0,i.jsx)(n.code,{children:"DataView"}),".\nConsider the definition of ",(0,i.jsx)(n.code,{children:"viewAs"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"def viewAs[V <: Data](implicit dataView: DataView[T, V]): V\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Armed with the knowledge from the previous section, we know that whenever we call ",(0,i.jsx)(n.code,{children:".viewAs"}),", the\nScala compiler will first look for a ",(0,i.jsx)(n.code,{children:"DataView[T, V]"})," in the current scope (defined in, or imported),\nthen it will look in the companion objects of ",(0,i.jsx)(n.code,{children:"DataView"}),", ",(0,i.jsx)(n.code,{children:"T"}),", and ",(0,i.jsx)(n.code,{children:"V"}),".\nThis enables a fairly powerful pattern, namely that default or typical implementations of a ",(0,i.jsx)(n.code,{children:"DataView"}),"\nshould be defined in the companion object for one of the two types.\nWe can think about ",(0,i.jsx)(n.code,{children:"DataViews"}),' defined in this way as "low priority defaults".\nThey can then be overruled by a specific import if a given user ever wants different behavior.\nFor example:']}),"\n",(0,i.jsx)(n.p,{children:"Given the following types:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class Foo extends Bundle {\n val a = UInt(8.W)\n val b = UInt(8.W)\n}\nclass Bar extends Bundle {\n val c = UInt(8.W)\n val d = UInt(8.W)\n}\nobject Foo {\n implicit val f2b = DataView[Foo, Bar](_ => new Bar, _.a -> _.c, _.b -> _.d)\n implicit val b2f = f2b.invert(_ => new Foo)\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This provides an implementation of ",(0,i.jsx)(n.code,{children:"DataView"})," in the ",(0,i.jsx)(n.em,{children:"implicit scope"}),' as a "default" mapping between\n',(0,i.jsx)(n.code,{children:"Foo"})," and ",(0,i.jsx)(n.code,{children:"Bar"})," (and it doesn't even require an import!):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class FooToBar extends Module {\n val foo = IO(Input(new Foo))\n val bar = IO(Output(new Bar))\n bar := foo.viewAs[Bar]\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule FooToBar(\n input clock,\n reset,\n input [7:0] foo_a,\n foo_b,\n output [7:0] bar_c,\n bar_d\n);\n\n assign bar_c = foo_a;\n assign bar_d = foo_b;\nendmodule\n\n"})}),"\n",(0,i.jsxs)(n.p,{children:["However, it's possible that some user of ",(0,i.jsx)(n.code,{children:"Foo"})," and ",(0,i.jsx)(n.code,{children:"Bar"}),' wants different behavior,\nperhaps they would prefer more of "swizzling" behavior rather than a direct mapping:']}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"object Swizzle {\n implicit val swizzle = DataView[Foo, Bar](_ => new Bar, _.a -> _.d, _.b -> _.c)\n}\n// Current scope always wins over implicit scope\nimport Swizzle._\nclass FooToBarSwizzled extends Module {\n val foo = IO(Input(new Foo))\n val bar = IO(Output(new Bar))\n bar := foo.viewAs[Bar]\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule FooToBarSwizzled(\n input clock,\n reset,\n input [7:0] foo_a,\n foo_b,\n output [7:0] bar_c,\n bar_d\n);\n\n assign bar_c = foo_b;\n assign bar_d = foo_a;\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.h3,{id:"dataproduct",children:"DataProduct"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"DataProduct"})," is a type class used by ",(0,i.jsx)(n.code,{children:"DataView"}),' to validate the correctness of a user-provided mapping.\nIn order for a type to be "viewable" (ie. the ',(0,i.jsx)(n.code,{children:"Target"})," type of a ",(0,i.jsx)(n.code,{children:"DataView"}),"), it must have an\nimplementation of ",(0,i.jsx)(n.code,{children:"DataProduct"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"For example, say we have some non-Bundle type:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"// Loosely based on chisel3.util.Counter\nclass MyCounter(val width: Int) {\n /** Indicates if the Counter is incrementing this cycle */\n val active = WireDefault(false.B)\n val value = RegInit(0.U(width.W))\n def inc(): Unit = {\n active := true.B\n value := value + 1.U\n }\n def reset(): Unit = {\n value := 0.U\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Say we want to view ",(0,i.jsx)(n.code,{children:"MyCounter"})," as a ",(0,i.jsx)(n.code,{children:"Valid[UInt]"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.Valid\nimplicit val counterView = DataView[MyCounter, Valid[UInt]](c => Valid(UInt(c.width.W)), _.value -> _.bits, _.active -> _.valid)\n// error: myView is already defined as value myView\n// implicit val myView = PartialDataView[BundleA, BundleB](_ => new BundleB, _.bar -> _.fizz)\n// ^^^^^^\n// error: Could not find implicit value for DataView[MdocApp1.this.BundleA, MdocApp1.this.BundleB].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview\n// out := in.viewAs[BundleB]\n// ^^^^^^^^^^^^^^^^^^\n// error: Could not find implicit value for DataView[MdocApp1.this.BundleA, MdocApp1.this.BundleB].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview\n// out := in.viewAs[BundleB]\n// ^^^^^^^^^^^^^^^^^^\n// error: Could not find implicit value for DataView[MdocApp1.this.BundleB, MdocApp1.this.BundleA].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview\n// out.viewAs[BundleA] := in\n// ^^^^^^^^^^^^^^^^^^^\n// error: Could not find implicit value for DataProduct[MdocApp1.this.MyCounter].\n// Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct\n// implicit val counterView = DataView[MyCounter, Valid[UInt]](c => Valid(UInt(c.width.W)), _.value -> _.bits, _.active -> _.valid)\n// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"})}),"\n",(0,i.jsxs)(n.p,{children:["As you can see, this fails Scala compliation.\nWe need to provide an implementation of ",(0,i.jsx)(n.code,{children:"DataProduct[MyCounter]"})," which provides Chisel a way to access\nthe objects of type ",(0,i.jsx)(n.code,{children:"Data"})," within ",(0,i.jsx)(n.code,{children:"MyCounter"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'import chisel3.util.Valid\nimplicit val counterProduct = new DataProduct[MyCounter] {\n // The String part of the tuple is a String path to the object to help in debugging\n def dataIterator(a: MyCounter, path: String): Iterator[(Data, String)] =\n List(a.value -> s"$path.value", a.active -> s"$path.active").iterator\n}\n// Now this works\nimplicit val counterView = DataView[MyCounter, Valid[UInt]](c => Valid(UInt(c.width.W)), _.value -> _.bits, _.active -> _.valid)\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Why is this useful?\nThis is how Chisel is able to check for totality as ",(0,i.jsx)(n.a,{href:"#totality-and-partialdataview",children:"described above"}),".\nIn addition to checking if a user has left a field out of the mapping, it also allows Chisel to check\nif the user has included a ",(0,i.jsx)(n.code,{children:"Data"})," in the mapping that isn't actually a part of the ",(0,i.jsx)(n.em,{children:"target"})," nor the\n",(0,i.jsx)(n.em,{children:"view"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>s,x:()=>o});var i=a(6540);const t={},l=i.createContext(t);function s(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/7b5bfa87.d8c045dc.js b/assets/js/7b5bfa87.48536f48.js
similarity index 97%
rename from assets/js/7b5bfa87.d8c045dc.js
rename to assets/js/7b5bfa87.48536f48.js
index 6e66a10ac9..0b6192fed6 100644
--- a/assets/js/7b5bfa87.d8c045dc.js
+++ b/assets/js/7b5bfa87.48536f48.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[2785],{1001:(a,e,n)=>{n.r(e),n.d(e,{assets:()=>i,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>p});var l=n(4848),t=n(8453);const s={layout:"docs",title:"Chisel Type vs Scala Type",section:"chisel3"},c="Chisel Type vs Scala Type",o={id:"explanations/chisel-type-vs-scala-type",title:"Chisel Type vs Scala Type",description:"The Scala compiler cannot distinguish between Chisel's representation of hardware such as false.B, Reg(Bool())",source:"@site/docs/explanations/chisel-type-vs-scala-type.md",sourceDirName:"explanations",slug:"/explanations/chisel-type-vs-scala-type",permalink:"/docs/explanations/chisel-type-vs-scala-type",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/chisel-type-vs-scala-type.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Chisel Type vs Scala Type",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Enumerations",permalink:"/docs/explanations/chisel-enum"},next:{title:"Combinational Circuits",permalink:"/docs/explanations/combinational-circuits"}},i={},p=[{value:"Scala Type vs Chisel Type vs Hardware",id:"scala-type-vs-chisel-type-vs-hardware",level:2},{value:"Chisel Type vs Hardware vs Literals",id:"chisel-type-vs-hardware-vs-literals",level:2},{value:"Chisel Type vs Hardware -- Specific Functions and Errors",id:"chisel-type-vs-hardware----specific-functions-and-errors",level:2},{value:".asInstanceOf vs .asTypeOf vs chiselTypeOf",id:"asinstanceof-vs-astypeof-vs-chiseltypeof",level:2}];function r(a){const e={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,t.R)(),...a.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(e.header,{children:(0,l.jsx)(e.h1,{id:"chisel-type-vs-scala-type",children:"Chisel Type vs Scala Type"})}),"\n",(0,l.jsxs)(e.p,{children:["The Scala compiler cannot distinguish between Chisel's representation of hardware such as ",(0,l.jsx)(e.code,{children:"false.B"}),", ",(0,l.jsx)(e.code,{children:"Reg(Bool())"}),"\nand pure Chisel types (e.g. ",(0,l.jsx)(e.code,{children:"Bool()"}),"). You can get runtime errors passing a Chisel type when hardware is expected, and vice versa."]}),"\n",(0,l.jsx)(e.h2,{id:"scala-type-vs-chisel-type-vs-hardware",children:"Scala Type vs Chisel Type vs Hardware"}),"\n",(0,l.jsxs)(e.p,{children:["The ",(0,l.jsx)(e.em,{children:"Scala"})," type of the Data is recognized by the Scala compiler, such as ",(0,l.jsx)(e.code,{children:"Bool"}),", ",(0,l.jsx)(e.code,{children:"Decoupled[UInt]"})," or ",(0,l.jsx)(e.code,{children:"MyBundle"})," in"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"class MyBundle(w: Int) extends Bundle {\n val foo = UInt(w.W)\n val bar = UInt(w.W)\n}\n"})}),"\n",(0,l.jsxs)(e.p,{children:["The ",(0,l.jsx)(e.em,{children:"Chisel"})," type of a ",(0,l.jsx)(e.code,{children:"Data"})," is a Scala object. It captures all the fields actually present,\nby names, and their types including widths.\nFor example, ",(0,l.jsx)(e.code,{children:"MyBundle(3)"})," creates a Chisel Type with fields ",(0,l.jsx)(e.code,{children:"foo: UInt(3.W), bar: UInt(3.W))"}),"."]}),"\n",(0,l.jsxs)(e.p,{children:["Hardware is ",(0,l.jsx)(e.code,{children:"Data"}),' that is "bound" to synthesizable hardware. For example ',(0,l.jsx)(e.code,{children:"false.B"})," or ",(0,l.jsx)(e.code,{children:"Reg(Bool())"}),".\nThe binding is what determines the actual directionality of each field, it is not a property of the Chisel type."]}),"\n",(0,l.jsxs)(e.p,{children:["A literal is a ",(0,l.jsx)(e.code,{children:"Data"})," that is respresentable as a literal value without being wrapped in Wire, Reg, or IO."]}),"\n",(0,l.jsx)(e.h2,{id:"chisel-type-vs-hardware-vs-literals",children:"Chisel Type vs Hardware vs Literals"}),"\n",(0,l.jsxs)(e.p,{children:["The below code demonstrates how objects with the same Scala type (",(0,l.jsx)(e.code,{children:"MyBundle"}),") can have different properties."]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"import chisel3.experimental.BundleLiterals._\n\nclass MyModule(gen: () => MyBundle) extends Module {\n // Hardware Literal\n val xType: MyBundle = new MyBundle(3) // - -\n val dirXType: MyBundle = Input(new MyBundle(3)) // - -\n val xReg: MyBundle = Reg(new MyBundle(3)) // x -\n val xIO: MyBundle = IO(Input(new MyBundle(3))) // x -\n val xRegInit: MyBundle = RegInit(xIO) // x -\n val xLit: MyBundle = xType.Lit( // x x\n _.foo -> 0.U(3.W),\n _.bar -> 0.U(3.W)\n )\n val y: MyBundle = gen() // ? ?\n\n // Need to initialize all hardware values\n xReg := DontCare\n}\n"})}),"\n",(0,l.jsx)(e.h2,{id:"chisel-type-vs-hardware----specific-functions-and-errors",children:"Chisel Type vs Hardware -- Specific Functions and Errors"}),"\n",(0,l.jsxs)(e.p,{children:[(0,l.jsx)(e.code,{children:".asTypeOf"})," works for both hardware and Chisel type:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"elaborate(new Module {\n val chiselType = new MyBundle(3)\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n val a = 0.U.asTypeOf(chiselType)\n val b = 0.U.asTypeOf(hardware)\n})\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can only ",(0,l.jsx)(e.code,{children:":="})," to hardware:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val chiselType = new MyBundle(3)\n chiselType := DontCare\n})\n// 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(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21$$anon$3.(chisel-type-vs-scala-type.md:90)\n// \tat repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21.apply(chisel-type-vs-scala-type.md:88)\n// \tat repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21.apply(chisel-type-vs-scala-type.md:88)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can only ",(0,l.jsx)(e.code,{children:":="})," from hardware:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = IO(new MyBundle(3))\n val moarHardware = Wire(new MyBundle(3))\n moarHardware := DontCare\n hardware := moarHardware\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val hardware = IO(new MyBundle(3))\n val chiselType = new MyBundle(3)\n hardware := chiselType\n})\n// 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(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27$$anon$5.(chisel-type-vs-scala-type.md:115)\n// \tat repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27.apply(chisel-type-vs-scala-type.md:112)\n// \tat repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27.apply(chisel-type-vs-scala-type.md:112)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Have to pass hardware to ",(0,l.jsx)(e.code,{children:"chiselTypeOf"}),":"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n val chiselType = chiselTypeOf(hardware)\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val chiselType = new MyBundle(3)\n val crash = chiselTypeOf(chiselType)\n})\n// chisel3.package$ExpectedHardwareException: 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39$$anonfun$apply$36.apply(chisel-type-vs-scala-type.md:138)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39$$anonfun$apply$36.apply(chisel-type-vs-scala-type.md:138)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39.apply(chisel-type-vs-scala-type.md:138)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7.(chisel-type-vs-scala-type.md:138)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34.apply(chisel-type-vs-scala-type.md:136)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34.apply(chisel-type-vs-scala-type.md:136)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Have to pass hardware to ",(0,l.jsx)(e.code,{children:"*Init"}),":"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n val moarHardware = WireInit(hardware)\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val crash = WireInit(new MyBundle(3))\n})\n// chisel3.package$ExpectedHardwareException: wire initializer 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45$$anonfun$apply$41.apply(chisel-type-vs-scala-type.md:160)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45$$anonfun$apply$41.apply(chisel-type-vs-scala-type.md:160)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45.apply(chisel-type-vs-scala-type.md:160)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9.(chisel-type-vs-scala-type.md:160)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40.apply(chisel-type-vs-scala-type.md:159)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40.apply(chisel-type-vs-scala-type.md:159)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can't pass hardware to a ",(0,l.jsx)(e.code,{children:"Wire"}),", ",(0,l.jsx)(e.code,{children:"Reg"}),", ",(0,l.jsx)(e.code,{children:"IO"}),":"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n val crash = Wire(hardware)\n})\n// chisel3.package$ExpectedChiselTypeException: wire type '_44_Anon.hardware: Wire[MyBundle]' must be a Chisel type, not hardware\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51$$anonfun$apply$47.apply(chisel-type-vs-scala-type.md:182)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51$$anonfun$apply$47.apply(chisel-type-vs-scala-type.md:182)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51.apply(chisel-type-vs-scala-type.md:182)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11.(chisel-type-vs-scala-type.md:182)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44.apply(chisel-type-vs-scala-type.md:180)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44.apply(chisel-type-vs-scala-type.md:180)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:[(0,l.jsx)(e.code,{children:".Lit"})," can only be called on Chisel type:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardwareLit = (new MyBundle(3)).Lit(\n _.foo -> 0.U,\n _.bar -> 0.U\n )\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"//Not this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n val crash = hardware.Lit(\n _.foo -> 0.U,\n _.bar -> 0.U\n )\n})\n// chisel3.package$ExpectedChiselTypeException: bundle literal constructor model '_52_Anon.hardware: Wire[MyBundle]' must be a Chisel type, not hardware\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56$$anonfun$apply$55.apply(chisel-type-vs-scala-type.md:206)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56$$anonfun$apply$55.apply(chisel-type-vs-scala-type.md:206)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56.apply(chisel-type-vs-scala-type.md:206)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13.(chisel-type-vs-scala-type.md:206)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52.apply(chisel-type-vs-scala-type.md:204)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52.apply(chisel-type-vs-scala-type.md:204)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can only use a Chisel type within a ",(0,l.jsx)(e.code,{children:"Bundle"})," definition:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new Bundle {\n val nested = new MyBundle(3)\n })\n hardware := DontCare\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val crash = Wire(new Bundle {\n val nested = Wire(new MyBundle(3))\n })\n})\n// chisel3.package$ExpectedChiselTypeException: Bundle: AnonymousBundle contains hardware fields: nested: _60_Anon.crash_nested: Wire[MyBundle]\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62$$anonfun$apply$61.apply(chisel-type-vs-scala-type.md:232)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62$$anonfun$apply$61.apply(chisel-type-vs-scala-type.md:232)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62.apply(chisel-type-vs-scala-type.md:232)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16.(chisel-type-vs-scala-type.md:232)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60.apply(chisel-type-vs-scala-type.md:231)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60.apply(chisel-type-vs-scala-type.md:231)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can only call ",(0,l.jsx)(e.code,{children:"directionOf"})," on Hardware:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"import chisel3.reflect.DataMirror\n\nclass Child extends Module{\n val hardware = IO(new MyBundle(3))\n hardware := DontCare\n val chiselType = new MyBundle(3)\n}\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val child = Module(new Child())\n child.hardware := DontCare\n val direction = DataMirror.directionOf(child.hardware)\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\nval child = Module(new Child())\n child.hardware := DontCare\n val direction = DataMirror.directionOf(child.chiselType)\n})\n// 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(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68$$anon$19.(chisel-type-vs-scala-type.md:271)\n// \tat repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68.apply(chisel-type-vs-scala-type.md:268)\n// \tat repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68.apply(chisel-type-vs-scala-type.md:268)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can call ",(0,l.jsx)(e.code,{children:"specifiedDirectionOf"})," on hardware or Chisel type:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"elaborate(new Module {\n val child = Module(new Child())\n child.hardware := DontCare\n val direction0 = DataMirror.specifiedDirectionOf(child.hardware)\n val direction1 = DataMirror.specifiedDirectionOf(child.chiselType)\n})\n"})}),"\n",(0,l.jsxs)(e.h2,{id:"asinstanceof-vs-astypeof-vs-chiseltypeof",children:[(0,l.jsx)(e.code,{children:".asInstanceOf"})," vs ",(0,l.jsx)(e.code,{children:".asTypeOf"})," vs ",(0,l.jsx)(e.code,{children:"chiselTypeOf"})]}),"\n",(0,l.jsxs)(e.p,{children:[(0,l.jsx)(e.code,{children:".asInstanceOf"})," is a Scala runtime cast, usually used for telling the compiler\nthat you have more information than it can infer to convert Scala types:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"class ScalaCastingModule(gen: () => Bundle) extends Module {\n val io = IO(Output(gen().asInstanceOf[MyBundle]))\n io.foo := 0.U\n}\n"})}),"\n",(0,l.jsx)(e.p,{children:"This works if we do indeed have more information than the compiler:"}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"elaborate(new ScalaCastingModule( () => new MyBundle(3)))\n"})}),"\n",(0,l.jsx)(e.p,{children:"But if we are wrong, we can get a Scala runtime exception:"}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"class NotMyBundle extends Bundle {val baz = Bool()}\nelaborate(new ScalaCastingModule(() => new NotMyBundle()))\n// 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 @62f84d3d)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293)\n// \tat chisel3.SpecifiedDirection$.specifiedDirection(DataImpl.scala:73)\n// \tat chisel3.Output$.apply(DataImpl.scala:317)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72.apply(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72.apply(chisel-type-vs-scala-type.md:293)\n// \tat chisel3.IO$.apply(IO.scala:34)\n// \tat chisel3.experimental.BaseModule.IO(ModuleImpl.scala:859)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71.apply(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71.apply(chisel-type-vs-scala-type.md:293)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76.apply(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule.(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$$anonfun$79$$anonfun$apply$75.apply(chisel-type-vs-scala-type.md:309)\n// \tat repl.MdocSession$MdocApp$$anonfun$79$$anonfun$apply$75.apply(chisel-type-vs-scala-type.md:309)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:[(0,l.jsx)(e.code,{children:".asTypeOf"})," is a conversion from one ",(0,l.jsx)(e.code,{children:"Data"})," subclass to another.\nIt is commonly used to assign data to all-zeros, as described in ",(0,l.jsx)(e.a,{href:"https://www.chisel-lang.org/chisel3/docs/cookbooks/cookbook.html#how-can-i-tieoff-a-bundlevec-to-0",children:"this cookbook recipe"}),", but it can\nalso be used (though not really recommended, as there is no checking on\nwidth matches) to convert one Chisel type to another:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:'class SimilarToMyBundle(w: Int) extends Bundle{\n val foobar = UInt((2*w).W)\n}\n\nemitSystemVerilog(new Module {\n val in = IO(Input(new MyBundle(3)))\n val out = IO(Output(new SimilarToMyBundle(3)))\n\n out := in.asTypeOf(out)\n})\n// res12: String = """// Generated by CIRCT firtool-1.86.0\n// module _82_Anon(\n// input clock,\n// reset,\n// input [2:0] in_foo,\n// in_bar,\n// output [5:0] out_foobar\n// );\n// \n// assign out_foobar = {in_foo, in_bar};\n// endmodule\n// \n// """\n'})}),"\n",(0,l.jsxs)(e.p,{children:["In contrast to ",(0,l.jsx)(e.code,{children:"asInstanceOf"})," and ",(0,l.jsx)(e.code,{children:"asTypeOf"}),",\n",(0,l.jsx)(e.code,{children:"chiselTypeOf"})," is not a casting operation. It returns a Scala object which\ncan be used as shown in the examples above to create more Chisel types and\nhardware with the same Chisel type as existing hardware."]})]})}function d(a={}){const{wrapper:e}={...(0,t.R)(),...a.components};return e?(0,l.jsx)(e,{...a,children:(0,l.jsx)(r,{...a})}):r(a)}},8453:(a,e,n)=>{n.d(e,{R:()=>c,x:()=>o});var l=n(6540);const t={},s=l.createContext(t);function c(a){const e=l.useContext(s);return l.useMemo((function(){return"function"==typeof a?a(e):{...e,...a}}),[e,a])}function o(a){let e;return e=a.disableParentContext?"function"==typeof a.components?a.components(t):a.components||t:c(a.components),l.createElement(s.Provider,{value:e},a.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[2785],{1001:(a,e,n)=>{n.r(e),n.d(e,{assets:()=>i,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>p});var l=n(4848),t=n(8453);const s={layout:"docs",title:"Chisel Type vs Scala Type",section:"chisel3"},c="Chisel Type vs Scala Type",o={id:"explanations/chisel-type-vs-scala-type",title:"Chisel Type vs Scala Type",description:"The Scala compiler cannot distinguish between Chisel's representation of hardware such as false.B, Reg(Bool())",source:"@site/docs/explanations/chisel-type-vs-scala-type.md",sourceDirName:"explanations",slug:"/explanations/chisel-type-vs-scala-type",permalink:"/docs/explanations/chisel-type-vs-scala-type",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/chisel-type-vs-scala-type.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Chisel Type vs Scala Type",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Enumerations",permalink:"/docs/explanations/chisel-enum"},next:{title:"Combinational Circuits",permalink:"/docs/explanations/combinational-circuits"}},i={},p=[{value:"Scala Type vs Chisel Type vs Hardware",id:"scala-type-vs-chisel-type-vs-hardware",level:2},{value:"Chisel Type vs Hardware vs Literals",id:"chisel-type-vs-hardware-vs-literals",level:2},{value:"Chisel Type vs Hardware -- Specific Functions and Errors",id:"chisel-type-vs-hardware----specific-functions-and-errors",level:2},{value:".asInstanceOf vs .asTypeOf vs chiselTypeOf",id:"asinstanceof-vs-astypeof-vs-chiseltypeof",level:2}];function r(a){const e={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,t.R)(),...a.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(e.header,{children:(0,l.jsx)(e.h1,{id:"chisel-type-vs-scala-type",children:"Chisel Type vs Scala Type"})}),"\n",(0,l.jsxs)(e.p,{children:["The Scala compiler cannot distinguish between Chisel's representation of hardware such as ",(0,l.jsx)(e.code,{children:"false.B"}),", ",(0,l.jsx)(e.code,{children:"Reg(Bool())"}),"\nand pure Chisel types (e.g. ",(0,l.jsx)(e.code,{children:"Bool()"}),"). You can get runtime errors passing a Chisel type when hardware is expected, and vice versa."]}),"\n",(0,l.jsx)(e.h2,{id:"scala-type-vs-chisel-type-vs-hardware",children:"Scala Type vs Chisel Type vs Hardware"}),"\n",(0,l.jsxs)(e.p,{children:["The ",(0,l.jsx)(e.em,{children:"Scala"})," type of the Data is recognized by the Scala compiler, such as ",(0,l.jsx)(e.code,{children:"Bool"}),", ",(0,l.jsx)(e.code,{children:"Decoupled[UInt]"})," or ",(0,l.jsx)(e.code,{children:"MyBundle"})," in"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"class MyBundle(w: Int) extends Bundle {\n val foo = UInt(w.W)\n val bar = UInt(w.W)\n}\n"})}),"\n",(0,l.jsxs)(e.p,{children:["The ",(0,l.jsx)(e.em,{children:"Chisel"})," type of a ",(0,l.jsx)(e.code,{children:"Data"})," is a Scala object. It captures all the fields actually present,\nby names, and their types including widths.\nFor example, ",(0,l.jsx)(e.code,{children:"MyBundle(3)"})," creates a Chisel Type with fields ",(0,l.jsx)(e.code,{children:"foo: UInt(3.W), bar: UInt(3.W))"}),"."]}),"\n",(0,l.jsxs)(e.p,{children:["Hardware is ",(0,l.jsx)(e.code,{children:"Data"}),' that is "bound" to synthesizable hardware. For example ',(0,l.jsx)(e.code,{children:"false.B"})," or ",(0,l.jsx)(e.code,{children:"Reg(Bool())"}),".\nThe binding is what determines the actual directionality of each field, it is not a property of the Chisel type."]}),"\n",(0,l.jsxs)(e.p,{children:["A literal is a ",(0,l.jsx)(e.code,{children:"Data"})," that is respresentable as a literal value without being wrapped in Wire, Reg, or IO."]}),"\n",(0,l.jsx)(e.h2,{id:"chisel-type-vs-hardware-vs-literals",children:"Chisel Type vs Hardware vs Literals"}),"\n",(0,l.jsxs)(e.p,{children:["The below code demonstrates how objects with the same Scala type (",(0,l.jsx)(e.code,{children:"MyBundle"}),") can have different properties."]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"import chisel3.experimental.BundleLiterals._\n\nclass MyModule(gen: () => MyBundle) extends Module {\n // Hardware Literal\n val xType: MyBundle = new MyBundle(3) // - -\n val dirXType: MyBundle = Input(new MyBundle(3)) // - -\n val xReg: MyBundle = Reg(new MyBundle(3)) // x -\n val xIO: MyBundle = IO(Input(new MyBundle(3))) // x -\n val xRegInit: MyBundle = RegInit(xIO) // x -\n val xLit: MyBundle = xType.Lit( // x x\n _.foo -> 0.U(3.W),\n _.bar -> 0.U(3.W)\n )\n val y: MyBundle = gen() // ? ?\n\n // Need to initialize all hardware values\n xReg := DontCare\n}\n"})}),"\n",(0,l.jsx)(e.h2,{id:"chisel-type-vs-hardware----specific-functions-and-errors",children:"Chisel Type vs Hardware -- Specific Functions and Errors"}),"\n",(0,l.jsxs)(e.p,{children:[(0,l.jsx)(e.code,{children:".asTypeOf"})," works for both hardware and Chisel type:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"elaborate(new Module {\n val chiselType = new MyBundle(3)\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n val a = 0.U.asTypeOf(chiselType)\n val b = 0.U.asTypeOf(hardware)\n})\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can only ",(0,l.jsx)(e.code,{children:":="})," to hardware:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val chiselType = new MyBundle(3)\n chiselType := DontCare\n})\n// 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(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21$$anon$3.(chisel-type-vs-scala-type.md:90)\n// \tat repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21.apply(chisel-type-vs-scala-type.md:88)\n// \tat repl.MdocSession$MdocApp$$anonfun$21$$anonfun$apply$21.apply(chisel-type-vs-scala-type.md:88)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can only ",(0,l.jsx)(e.code,{children:":="})," from hardware:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = IO(new MyBundle(3))\n val moarHardware = Wire(new MyBundle(3))\n moarHardware := DontCare\n hardware := moarHardware\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val hardware = IO(new MyBundle(3))\n val chiselType = new MyBundle(3)\n hardware := chiselType\n})\n// 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(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27$$anon$5.(chisel-type-vs-scala-type.md:115)\n// \tat repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27.apply(chisel-type-vs-scala-type.md:112)\n// \tat repl.MdocSession$MdocApp$$anonfun$29$$anonfun$apply$27.apply(chisel-type-vs-scala-type.md:112)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Have to pass hardware to ",(0,l.jsx)(e.code,{children:"chiselTypeOf"}),":"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n val chiselType = chiselTypeOf(hardware)\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val chiselType = new MyBundle(3)\n val crash = chiselTypeOf(chiselType)\n})\n// chisel3.package$ExpectedHardwareException: 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39$$anonfun$apply$36.apply(chisel-type-vs-scala-type.md:138)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39$$anonfun$apply$36.apply(chisel-type-vs-scala-type.md:138)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39.apply(chisel-type-vs-scala-type.md:138)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7$$anonfun$39.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34$$anon$7.(chisel-type-vs-scala-type.md:138)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34.apply(chisel-type-vs-scala-type.md:136)\n// \tat repl.MdocSession$MdocApp$$anonfun$37$$anonfun$apply$34.apply(chisel-type-vs-scala-type.md:136)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Have to pass hardware to ",(0,l.jsx)(e.code,{children:"*Init"}),":"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n val moarHardware = WireInit(hardware)\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val crash = WireInit(new MyBundle(3))\n})\n// chisel3.package$ExpectedHardwareException: wire initializer 'MyBundle' must be hardware, not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45$$anonfun$apply$41.apply(chisel-type-vs-scala-type.md:160)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45$$anonfun$apply$41.apply(chisel-type-vs-scala-type.md:160)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45.apply(chisel-type-vs-scala-type.md:160)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9$$anonfun$45.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40$$anon$9.(chisel-type-vs-scala-type.md:160)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40.apply(chisel-type-vs-scala-type.md:159)\n// \tat repl.MdocSession$MdocApp$$anonfun$44$$anonfun$apply$40.apply(chisel-type-vs-scala-type.md:159)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can't pass hardware to a ",(0,l.jsx)(e.code,{children:"Wire"}),", ",(0,l.jsx)(e.code,{children:"Reg"}),", ",(0,l.jsx)(e.code,{children:"IO"}),":"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n hardware := DontCare\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n val crash = Wire(hardware)\n})\n// chisel3.package$ExpectedChiselTypeException: wire type '_44_Anon.hardware: Wire[MyBundle]' must be a Chisel type, not hardware\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51$$anonfun$apply$47.apply(chisel-type-vs-scala-type.md:182)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51$$anonfun$apply$47.apply(chisel-type-vs-scala-type.md:182)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51.apply(chisel-type-vs-scala-type.md:182)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11$$anonfun$51.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44$$anon$11.(chisel-type-vs-scala-type.md:182)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44.apply(chisel-type-vs-scala-type.md:180)\n// \tat repl.MdocSession$MdocApp$$anonfun$49$$anonfun$apply$44.apply(chisel-type-vs-scala-type.md:180)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:[(0,l.jsx)(e.code,{children:".Lit"})," can only be called on Chisel type:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardwareLit = (new MyBundle(3)).Lit(\n _.foo -> 0.U,\n _.bar -> 0.U\n )\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"//Not this...\nelaborate(new Module {\n val hardware = Wire(new MyBundle(3))\n val crash = hardware.Lit(\n _.foo -> 0.U,\n _.bar -> 0.U\n )\n})\n// chisel3.package$ExpectedChiselTypeException: bundle literal constructor model '_52_Anon.hardware: Wire[MyBundle]' must be a Chisel type, not hardware\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56$$anonfun$apply$55.apply(chisel-type-vs-scala-type.md:206)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56$$anonfun$apply$55.apply(chisel-type-vs-scala-type.md:206)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56.apply(chisel-type-vs-scala-type.md:206)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13$$anonfun$56.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52$$anon$13.(chisel-type-vs-scala-type.md:206)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52.apply(chisel-type-vs-scala-type.md:204)\n// \tat repl.MdocSession$MdocApp$$anonfun$54$$anonfun$apply$52.apply(chisel-type-vs-scala-type.md:204)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can only use a Chisel type within a ",(0,l.jsx)(e.code,{children:"Bundle"})," definition:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val hardware = Wire(new Bundle {\n val nested = new MyBundle(3)\n })\n hardware := DontCare\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\n val crash = Wire(new Bundle {\n val nested = Wire(new MyBundle(3))\n })\n})\n// chisel3.package$ExpectedChiselTypeException: Bundle: AnonymousBundle contains hardware fields: nested: _60_Anon.crash_nested: Wire[MyBundle]\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62$$anonfun$apply$61.apply(chisel-type-vs-scala-type.md:232)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62$$anonfun$apply$61.apply(chisel-type-vs-scala-type.md:232)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62.apply(chisel-type-vs-scala-type.md:232)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16$$anonfun$62.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60$$anon$16.(chisel-type-vs-scala-type.md:232)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60.apply(chisel-type-vs-scala-type.md:231)\n// \tat repl.MdocSession$MdocApp$$anonfun$61$$anonfun$apply$60.apply(chisel-type-vs-scala-type.md:231)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can only call ",(0,l.jsx)(e.code,{children:"directionOf"})," on Hardware:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"import chisel3.reflect.DataMirror\n\nclass Child extends Module{\n val hardware = IO(new MyBundle(3))\n hardware := DontCare\n val chiselType = new MyBundle(3)\n}\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Do this...\nelaborate(new Module {\n val child = Module(new Child())\n child.hardware := DontCare\n val direction = DataMirror.directionOf(child.hardware)\n})\n"})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"// Not this...\nelaborate(new Module {\nval child = Module(new Child())\n child.hardware := DontCare\n val direction = DataMirror.directionOf(child.chiselType)\n})\n// 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(_)?\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68$$anon$19.(chisel-type-vs-scala-type.md:271)\n// \tat repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68.apply(chisel-type-vs-scala-type.md:268)\n// \tat repl.MdocSession$MdocApp$$anonfun$70$$anonfun$apply$68.apply(chisel-type-vs-scala-type.md:268)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:["Can call ",(0,l.jsx)(e.code,{children:"specifiedDirectionOf"})," on hardware or Chisel type:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"elaborate(new Module {\n val child = Module(new Child())\n child.hardware := DontCare\n val direction0 = DataMirror.specifiedDirectionOf(child.hardware)\n val direction1 = DataMirror.specifiedDirectionOf(child.chiselType)\n})\n"})}),"\n",(0,l.jsxs)(e.h2,{id:"asinstanceof-vs-astypeof-vs-chiseltypeof",children:[(0,l.jsx)(e.code,{children:".asInstanceOf"})," vs ",(0,l.jsx)(e.code,{children:".asTypeOf"})," vs ",(0,l.jsx)(e.code,{children:"chiselTypeOf"})]}),"\n",(0,l.jsxs)(e.p,{children:[(0,l.jsx)(e.code,{children:".asInstanceOf"})," is a Scala runtime cast, usually used for telling the compiler\nthat you have more information than it can infer to convert Scala types:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"class ScalaCastingModule(gen: () => Bundle) extends Module {\n val io = IO(Output(gen().asInstanceOf[MyBundle]))\n io.foo := 0.U\n}\n"})}),"\n",(0,l.jsx)(e.p,{children:"This works if we do indeed have more information than the compiler:"}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"elaborate(new ScalaCastingModule( () => new MyBundle(3)))\n"})}),"\n",(0,l.jsx)(e.p,{children:"But if we are wrong, we can get a Scala runtime exception:"}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:"class NotMyBundle extends Bundle {val baz = Bool()}\nelaborate(new ScalaCastingModule(() => new NotMyBundle()))\n// 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 @5e30c611)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72$$anonfun$apply$73.apply(chisel-type-vs-scala-type.md:293)\n// \tat chisel3.SpecifiedDirection$.specifiedDirection(DataImpl.scala:73)\n// \tat chisel3.Output$.apply(DataImpl.scala:317)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72.apply(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71$$anonfun$apply$72.apply(chisel-type-vs-scala-type.md:293)\n// \tat chisel3.IO$.apply(IO.scala:34)\n// \tat chisel3.experimental.BaseModule.IO(ModuleImpl.scala:863)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71.apply(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76$$anonfun$apply$71.apply(chisel-type-vs-scala-type.md:293)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76.apply(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule$$anonfun$76.apply(chisel-type-vs-scala-type.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp$ScalaCastingModule.(chisel-type-vs-scala-type.md:293)\n// \tat repl.MdocSession$MdocApp$$anonfun$79$$anonfun$apply$75.apply(chisel-type-vs-scala-type.md:309)\n// \tat repl.MdocSession$MdocApp$$anonfun$79$$anonfun$apply$75.apply(chisel-type-vs-scala-type.md:309)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,l.jsxs)(e.p,{children:[(0,l.jsx)(e.code,{children:".asTypeOf"})," is a conversion from one ",(0,l.jsx)(e.code,{children:"Data"})," subclass to another.\nIt is commonly used to assign data to all-zeros, as described in ",(0,l.jsx)(e.a,{href:"https://www.chisel-lang.org/chisel3/docs/cookbooks/cookbook.html#how-can-i-tieoff-a-bundlevec-to-0",children:"this cookbook recipe"}),", but it can\nalso be used (though not really recommended, as there is no checking on\nwidth matches) to convert one Chisel type to another:"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-scala",children:'class SimilarToMyBundle(w: Int) extends Bundle{\n val foobar = UInt((2*w).W)\n}\n\nemitSystemVerilog(new Module {\n val in = IO(Input(new MyBundle(3)))\n val out = IO(Output(new SimilarToMyBundle(3)))\n\n out := in.asTypeOf(out)\n})\n// res12: String = """// Generated by CIRCT firtool-1.86.0\n// module _82_Anon(\n// input clock,\n// reset,\n// input [2:0] in_foo,\n// in_bar,\n// output [5:0] out_foobar\n// );\n// \n// assign out_foobar = {in_foo, in_bar};\n// endmodule\n// \n// """\n'})}),"\n",(0,l.jsxs)(e.p,{children:["In contrast to ",(0,l.jsx)(e.code,{children:"asInstanceOf"})," and ",(0,l.jsx)(e.code,{children:"asTypeOf"}),",\n",(0,l.jsx)(e.code,{children:"chiselTypeOf"})," is not a casting operation. It returns a Scala object which\ncan be used as shown in the examples above to create more Chisel types and\nhardware with the same Chisel type as existing hardware."]})]})}function d(a={}){const{wrapper:e}={...(0,t.R)(),...a.components};return e?(0,l.jsx)(e,{...a,children:(0,l.jsx)(r,{...a})}):r(a)}},8453:(a,e,n)=>{n.d(e,{R:()=>c,x:()=>o});var l=n(6540);const t={},s=l.createContext(t);function c(a){const e=l.useContext(s);return l.useMemo((function(){return"function"==typeof a?a(e):{...e,...a}}),[e,a])}function o(a){let e;return e=a.disableParentContext?"function"==typeof a.components?a.components(t):a.components||t:c(a.components),l.createElement(s.Provider,{value:e},a.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/7e1e4a75.ec8437ac.js b/assets/js/7e1e4a75.12cdae69.js
similarity index 99%
rename from assets/js/7e1e4a75.ec8437ac.js
rename to assets/js/7e1e4a75.12cdae69.js
index eab82dc578..cc03b2bce0 100644
--- a/assets/js/7e1e4a75.ec8437ac.js
+++ b/assets/js/7e1e4a75.12cdae69.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[5432],{7363:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>s,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var t=a(4848),o=a(8453),l=a(1871);const i={sidebar_position:0},s="General Cookbook",c={id:"cookbooks/cookbook",title:"General Cookbook",description:"Please note that these examples make use of Chisel's scala-style printing.",source:"@site/docs/cookbooks/cookbook.md",sourceDirName:"cookbooks",slug:"/cookbooks/cookbook",permalink:"/docs/cookbooks/cookbook",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/cookbooks/cookbook.md",tags:[],version:"current",sidebarPosition:0,frontMatter:{sidebar_position:0},sidebar:"chiselSidebar",previous:{title:"Cookbooks",permalink:"/docs/cookbooks"},next:{title:"Naming Cookbook",permalink:"/docs/cookbooks/naming"}},r={},d=[{value:"Type Conversions",id:"type-conversions",level:2},{value:"How do I create a UInt from an instance of a Bundle?",id:"how-do-i-create-a-uint-from-an-instance-of-a-bundle",level:3},{value:"How do I create a Bundle from a UInt?",id:"how-do-i-create-a-bundle-from-a-uint",level:3},{value:"How can I tieoff a Bundle/Vec to 0?",id:"how-can-i-tieoff-a-bundlevec-to-0",level:3},{value:"How do I create a Vec of Bools from a UInt?",id:"how-do-i-create-a-vec-of-bools-from-a-uint",level:3},{value:"How do I create a UInt from a Vec of Bool?",id:"how-do-i-create-a-uint-from-a-vec-of-bool",level:3},{value:"How do I connect a subset of Bundle fields?",id:"how-do-i-connect-a-subset-of-bundle-fields",level:3},{value:"Vectors and Registers",id:"vectors-and-registers",level:2},{value:"Can I make a 2D or 3D Vector?",id:"can-i-make-a-2d-or-3d-vector",level:3},{value:"How do I create a Vector of Registers?",id:"how-do-i-create-a-vector-of-registers",level:3},{value:"How do I create a Reg of type Vec?",id:"how-do-i-create-a-reg-of-type-vec",level:3},{value:"How do I partially reset an Aggregate Reg?",id:"how-do-i-partially-reset-an-aggregate-reg",level:3},{value:"Bundles",id:"bundles",level:2},{value:"How do I deal with aliased Bundle fields?",id:"how-do-i-deal-with-aliased-bundle-fields",level:3},{value:"1. 0-arity function parameters",id:"1-0-arity-function-parameters",level:4},{value:"Aliased Warning",id:"aliased-warning",level:5},{value:"2. By-name function parameters",id:"2-by-name-function-parameters",level:4},{value:"3. Directioned Bundle fields",id:"3-directioned-bundle-fields",level:4},{value:"4. Call .cloneType directly",id:"4-call-clonetype-directly",level:4},{value:" How do I deal with the "unable to clone" error?",id:"-how-do-i-deal-with-the-unable-to-clone-error",level:3},{value:"How do I create a finite state machine (FSM)?",id:"how-do-i-create-a-finite-state-machine-fsm",level:2},{value:"How do I unpack a value ("reverse concatenation") like in Verilog?",id:"how-do-i-unpack-a-value-reverse-concatenation-like-in-verilog",level:2},{value:"How do I do subword assignment (assign to some bits in a UInt)?",id:"how-do-i-do-subword-assignment-assign-to-some-bits-in-a-uint",level:2},{value:"How do I create an optional I/O?",id:"how-do-i-create-an-optional-io",level:2},{value:"How do I create I/O without a prefix?",id:"how-do-i-create-io-without-a-prefix",level:2},{value:"How do I override the implicit clock or reset within a Module?",id:"how-do-i-override-the-implicit-clock-or-reset-within-a-module",level:2},{value:"How do I minimize the number of bits used in an output vector?",id:"how-do-i-minimize-the-number-of-bits-used-in-an-output-vector",level:2},{value:"How do I resolve "Dynamic index ... is too wide/narrow for extractee ..."?",id:"how-do-i-resolve-dynamic-index--is-too-widenarrow-for-extractee-",level:2},{value:"Use bit extraction when the index is too wide",id:"use-bit-extraction-when-the-index-is-too-wide",level:4},{value:"Predictable Naming",id:"predictable-naming",level:2},{value:"How do I get Chisel to name signals properly in blocks like when/withClockAndReset?",id:"how-do-i-get-chisel-to-name-signals-properly-in-blocks-like-whenwithclockandreset",level:3},{value:"How do I get Chisel to name the results of vector reads properly?",id:"how-do-i-get-chisel-to-name-the-results-of-vector-reads-properly",level:3},{value:"How can I dynamically set/parametrize the name of a module?",id:"how-can-i-dynamically-setparametrize-the-name-of-a-module",level:3},{value:"Directionality",id:"directionality",level:2},{value:"How do I strip directions from a bidirectional Bundle (or other Data)?",id:"how-do-i-strip-directions-from-a-bidirectional-bundle-or-other-data",level:3}];function u(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"general-cookbook",children:"General Cookbook"})}),"\n",(0,t.jsxs)(n.p,{children:["Please note that these examples make use of ",(0,t.jsx)(n.a,{href:"../explanations/printing#scala-style",children:"Chisel's scala-style printing"}),"."]}),"\n","\n",(0,t.jsx)(l.A,{toc:d}),"\n",(0,t.jsx)(n.h2,{id:"type-conversions",children:"Type Conversions"}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-uint-from-an-instance-of-a-bundle",children:"How do I create a UInt from an instance of a Bundle?"}),"\n",(0,t.jsxs)(n.p,{children:["Call ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html#asUInt:chisel3.UInt",children:(0,t.jsx)(n.code,{children:"asUInt"})})," on the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html",children:(0,t.jsx)(n.code,{children:"Bundle"})})," instance."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = UInt(4.W)\n val bar = UInt(4.W)\n}\n\nclass Foo extends Module {\n val bundle = Wire(new MyBundle)\n bundle.foo := 0xc.U\n bundle.bar := 0x3.U\n val uint = bundle.asUInt\n printf(cf"$uint") // 195\n\n // Test\n assert(uint === 0xc3.U)\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-bundle-from-a-uint",children:"How do I create a Bundle from a UInt?"}),"\n",(0,t.jsxs)(n.p,{children:["Use the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html#asTypeOf%5BT%3C:chisel3.Data%5D(that:T):T",children:(0,t.jsx)(n.code,{children:"asTypeOf"})})," method to reinterpret the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html",children:(0,t.jsx)(n.code,{children:"UInt"})})," as the type of the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html",children:(0,t.jsx)(n.code,{children:"Bundle"})}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = UInt(4.W)\n val bar = UInt(4.W)\n}\n\nclass Foo extends Module {\n val uint = 0xb4.U\n val bundle = uint.asTypeOf(new MyBundle)\n\n printf(cf"$bundle") // Bundle(foo -> 11, bar -> 4)\n\n // Test\n assert(bundle.foo === 0xb.U)\n assert(bundle.bar === 0x4.U)\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"how-can-i-tieoff-a-bundlevec-to-0",children:"How can I tieoff a Bundle/Vec to 0?"}),"\n",(0,t.jsxs)(n.p,{children:["You can use ",(0,t.jsx)(n.code,{children:"asTypeOf"})," as above. If you don't want to worry about the type of the thing\nyou are tying off, you can use ",(0,t.jsx)(n.code,{children:"chiselTypeOf"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = UInt(4.W)\n val bar = Vec(4, UInt(1.W))\n}\n\nclass Foo(typ: MyBundle) extends Module {\n val bundleA = IO(Output(typ))\n val bundleB = IO(Output(typ))\n\n // typ is already a Chisel Data Type, so can use it directly here, but you\n // need to know that bundleA is of type typ\n bundleA := 0.U.asTypeOf(typ)\n\n // bundleB is a Hardware data IO(Output(...)) so need to call chiselTypeOf,\n // but this will work no matter the type of bundleB:\n bundleB := 0.U.asTypeOf(chiselTypeOf(bundleB))\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-vec-of-bools-from-a-uint",children:"How do I create a Vec of Bools from a UInt?"}),"\n",(0,t.jsxs)(n.p,{children:["Use ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/VecInit$.html",children:(0,t.jsx)(n.code,{children:"VecInit"})})," given a ",(0,t.jsx)(n.code,{children:"Seq[Bool]"})," generated using the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html#asBools:Seq%5Bchisel3.Bool%5D",children:(0,t.jsx)(n.code,{children:"asBools"})})," method."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass Foo extends Module {\n val uint = 0xc.U\n val vec = VecInit(uint.asBools)\n\n printf(cf"$vec") // Vec(0, 0, 1, 1)\n\n // Test\n assert(vec(0) === false.B)\n assert(vec(1) === false.B)\n assert(vec(2) === true.B)\n assert(vec(3) === true.B)\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-uint-from-a-vec-of-bool",children:"How do I create a UInt from a Vec of Bool?"}),"\n",(0,t.jsxs)(n.p,{children:["Use the builtin function ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Vec.html#asUInt:chisel3.UInt",children:(0,t.jsx)(n.code,{children:"asUInt"})})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass Foo extends Module {\n val vec = VecInit(true.B, false.B, true.B, true.B)\n val uint = vec.asUInt\n\n printf(cf"$uint") // 13\n\n // Test\n // (remember leftmost Bool in Vec is low order bit)\n assert(0xd.U === uint)\n\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-connect-a-subset-of-bundle-fields",children:"How do I connect a subset of Bundle fields?"}),"\n",(0,t.jsxs)(n.p,{children:["See the ",(0,t.jsx)(n.a,{href:"dataview#how-do-i-connect-a-subset-of-bundle-fields",children:"DataView cookbook"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"vectors-and-registers",children:"Vectors and Registers"}),"\n",(0,t.jsx)(n.h3,{id:"can-i-make-a-2d-or-3d-vector",children:"Can I make a 2D or 3D Vector?"}),"\n",(0,t.jsxs)(n.p,{children:["Yes. Using ",(0,t.jsx)(n.code,{children:"VecInit"})," you can make Vectors that hold Vectors of Chisel types. Methods ",(0,t.jsx)(n.code,{children:"fill"})," and ",(0,t.jsx)(n.code,{children:"tabulate"})," make these multi-dimensional Vectors."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = UInt(4.W)\n val bar = UInt(4.W)\n}\n\nclass Foo extends Module {\n //2D Fill\n val twoDVec = VecInit.fill(2, 3)(5.U)\n //3D Fill\n val myBundle = Wire(new MyBundle)\n myBundle.foo := 0xc.U\n myBundle.bar := 0x3.U\n val threeDVec = VecInit.fill(1, 2, 3)(myBundle)\n assert(threeDVec(0)(0)(0).foo === 0xc.U && threeDVec(0)(0)(0).bar === 0x3.U)\n\n //2D Tabulate\n val indexTiedVec = VecInit.tabulate(2, 2){ (x, y) => (x + y).U }\n assert(indexTiedVec(0)(0) === 0.U)\n assert(indexTiedVec(0)(1) === 1.U)\n assert(indexTiedVec(1)(0) === 1.U)\n assert(indexTiedVec(1)(1) === 2.U)\n //3D Tabulate\n val indexTiedVec3D = VecInit.tabulate(2, 3, 4){ (x, y, z) => (x + y * z).U }\n assert(indexTiedVec3D(0)(0)(0) === 0.U)\n assert(indexTiedVec3D(1)(1)(1) === 2.U)\n assert(indexTiedVec3D(1)(1)(2) === 3.U)\n assert(indexTiedVec3D(1)(1)(3) === 4.U)\n assert(indexTiedVec3D(1)(2)(3) === 7.U)\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-vector-of-registers",children:"How do I create a Vector of Registers?"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Rule! Use Reg of Vec not Vec of Reg!"})}),"\n",(0,t.jsxs)(n.p,{children:["You create a ",(0,t.jsx)(n.a,{href:"#how-do-i-create-a-reg-of-type-vec",children:"Reg of type Vec"}),". Because Vecs are a ",(0,t.jsx)(n.em,{children:"type"})," (like ",(0,t.jsx)(n.code,{children:"UInt"}),", ",(0,t.jsx)(n.code,{children:"Bool"}),") rather than a ",(0,t.jsx)(n.em,{children:"value"}),", we must bind the Vec to some concrete ",(0,t.jsx)(n.em,{children:"value"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-reg-of-type-vec",children:"How do I create a Reg of type Vec?"}),"\n",(0,t.jsxs)(n.p,{children:["For more information, the API Documentation for ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Vec.html",children:(0,t.jsx)(n.code,{children:"Vec"})})," provides more information."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass Foo extends Module {\n val regOfVec = Reg(Vec(4, UInt(32.W))) // Register of 32-bit UInts\n regOfVec(0) := 123.U // Assignments to elements of the Vec\n regOfVec(1) := 456.U\n regOfVec(2) := 789.U\n regOfVec(3) := regOfVec(0)\n\n // Reg of Vec of 32-bit UInts initialized to zero\n // Note that Seq.fill constructs 4 32-bit UInt literals with the value 0\n // VecInit(...) then constructs a Wire of these literals\n // The Reg is then initialized to the value of the Wire (which gives it the same type)\n val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W))))\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-partially-reset-an-aggregate-reg",children:"How do I partially reset an Aggregate Reg?"}),"\n",(0,t.jsxs)(n.p,{children:["The easiest way is to use a partially-specified ",(0,t.jsx)(n.a,{href:"../appendix/experimental-features#bundle-literals",children:"Bundle Literal"}),"\nor ",(0,t.jsx)(n.a,{href:"../appendix/experimental-features#vec-literals",children:"Vec Literal"})," to match the type of the Reg."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.BundleLiterals._\n\nclass MyBundle extends Bundle {\n val foo = UInt(8.W)\n val bar = UInt(8.W)\n}\n\nclass MyModule extends Module {\n // Only .foo will be reset, .bar will have no reset value\n val reg = RegInit((new MyBundle).Lit(_.foo -> 123.U))\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If your initial value is not a literal, or if you just prefer, you can use a\nWire as the initial value for the Reg. Simply connect fields to ",(0,t.jsx)(n.code,{children:"DontCare"})," that\nyou do not wish to be reset."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class MyModule2 extends Module {\n val reg = RegInit({\n // The wire could be constructed before the reg rather than in the RegInit scope,\n // but this style has nice lexical scoping behavior, keeping the Wire private\n val init = Wire(new MyBundle)\n init := DontCare // No fields will be reset\n init.foo := 123.U // Last connect override, .foo is reset\n init\n })\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"bundles",children:"Bundles"}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-deal-with-aliased-bundle-fields",children:"How do I deal with aliased Bundle fields?"}),"\n",(0,t.jsxs)(n.p,{children:["Following the ",(0,t.jsx)(n.code,{children:"gen"})," pattern when creating Bundles can result in some opaque error messages:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class AliasedBundle[T <: Data](gen: T) extends Bundle {\n val foo = gen\n val bar = gen\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"getVerilogString(new Top(new AliasedBundle(UInt(8.W))))\n// chisel3.AliasedAggregateFieldException: AliasedBundle contains aliased fields named (foo,bar)\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp17$Top.(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:317)\n// \tat repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:317)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["This error is saying that fields ",(0,t.jsx)(n.code,{children:"foo"})," and ",(0,t.jsx)(n.code,{children:"bar"})," of ",(0,t.jsx)(n.code,{children:"AliasedBundle"})," are the\nexact same object in memory.\nThis is a problem for Chisel because we need to be able to distinguish uses of\n",(0,t.jsx)(n.code,{children:"foo"})," and ",(0,t.jsx)(n.code,{children:"bar"})," but cannot when they are referentially the same."]}),"\n",(0,t.jsx)(n.p,{children:"Note that the following example looks different but will give you exactly the same issue:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class AlsoAliasedBundle[T <: Data](val gen: T) extends Bundle {\n // ^ This val makes `gen` a field, just like `foo`\n val foo = gen\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["By making ",(0,t.jsx)(n.code,{children:"gen"})," a ",(0,t.jsx)(n.code,{children:"val"}),", it becomes a public field of the ",(0,t.jsx)(n.code,{children:"class"}),", just like ",(0,t.jsx)(n.code,{children:"foo"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"getVerilogString(new Top(new AlsoAliasedBundle(UInt(8.W))))\n// chisel3.AliasedAggregateFieldException: AlsoAliasedBundle contains aliased fields named (gen,foo)\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp17$Top.(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:336)\n// \tat repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:336)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsx)(n.p,{children:"There are several ways to solve this issue with their own advantages and disadvantages."}),"\n",(0,t.jsx)(n.h4,{id:"1-0-arity-function-parameters",children:"1. 0-arity function parameters"}),"\n",(0,t.jsx)(n.p,{children:"Instead of passing an object as a parameter, you can pass a 0-arity function (a function with no arguments):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class UsingAFunctionBundle[T <: Data](gen: () => T) extends Bundle {\n val foo = gen()\n val bar = gen()\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that the type of ",(0,t.jsx)(n.code,{children:"gen"})," is now ",(0,t.jsx)(n.code,{children:"() => T"}),".\nBecause it is now a function and not a subtype of ",(0,t.jsx)(n.code,{children:"Data"}),", you can safely make ",(0,t.jsx)(n.code,{children:"gen"})," a ",(0,t.jsx)(n.code,{children:"val"})," without\nit becoming a hardware field of the ",(0,t.jsx)(n.code,{children:"Bundle"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Note that this also means you must pass ",(0,t.jsx)(n.code,{children:"gen"})," as a function, for example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"chisel3.docs.emitSystemVerilog(new Top(new UsingAFunctionBundle(() => UInt(8.W))))\n"})}),"\n",(0,t.jsx)(n.h5,{id:"aliased-warning",children:"Aliased Warning"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Warning"}),": you must ensure that ",(0,t.jsx)(n.code,{children:"gen"})," creates fresh objects rather than capturing an already constructed value:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class MisusedFunctionArguments extends Module {\n // This usage is correct\n val in = IO(Input(new UsingAFunctionBundle(() => UInt(8.W))))\n\n // This usage is incorrect\n val fizz = UInt(8.W)\n val out = IO(Output(new UsingAFunctionBundle(() => fizz)))\n}\ngetVerilogString(new MisusedFunctionArguments)\n// chisel3.AutoClonetypeException: The bundle plugin was unable to clone UsingAFunctionBundle that has field 'bar' 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.\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:367)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:367)\n// \tat chisel3.IO$.apply(IO.scala:34)\n// \tat chisel3.experimental.BaseModule.IO(ModuleImpl.scala:859)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:367)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:367)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md:367)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1.(cookbook.md:367)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:369)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:369)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["In the above example, value ",(0,t.jsx)(n.code,{children:"fizz"})," and fields ",(0,t.jsx)(n.code,{children:"foo"})," and ",(0,t.jsx)(n.code,{children:"bar"})," of ",(0,t.jsx)(n.code,{children:"out"})," are all the same object in memory."]}),"\n",(0,t.jsx)(n.h4,{id:"2-by-name-function-parameters",children:"2. By-name function parameters"}),"\n",(0,t.jsxs)(n.p,{children:["Functionally the same as (1) but with more subtle syntax, you can use ",(0,t.jsx)(n.a,{href:"https://docs.scala-lang.org/tour/by-name-parameters.html",children:"Scala by-name function parameters"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class UsingByNameParameters[T <: Data](gen: => T) extends Bundle {\n val foo = gen\n val bar = gen\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["With this usage, you do not include ",(0,t.jsx)(n.code,{children:"() =>"})," when passing the argument:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"chisel3.docs.emitSystemVerilog(new Top(new UsingByNameParameters(UInt(8.W))))\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that as this is just syntactic sugar over (1), the ",(0,t.jsx)(n.a,{href:"#aliased-warning",children:"same warning applies"}),"."]}),"\n",(0,t.jsx)(n.h4,{id:"3-directioned-bundle-fields",children:"3. Directioned Bundle fields"}),"\n",(0,t.jsxs)(n.p,{children:["You can alternatively wrap the fields with ",(0,t.jsx)(n.code,{children:"Output(...)"}),", which creates fresh instances of the passed argument.\nChisel treats ",(0,t.jsx)(n.code,{children:"Output"}),' as the "default direction" so if all fields are outputs, the ',(0,t.jsx)(n.code,{children:"Bundle"})," is functionally equivalent to a ",(0,t.jsx)(n.code,{children:"Bundle"})," with no directioned fields."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class DirectionedBundle[T <: Data](gen: T) extends Bundle {\n val foo = Output(gen)\n val bar = Output(gen)\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["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 ",(0,t.jsx)(n.code,{children:"Output"}),"."]}),"\n",(0,t.jsxs)(n.h4,{id:"4-call-clonetype-directly",children:["4. Call ",(0,t.jsx)(n.code,{children:".cloneType"})," directly"]}),"\n",(0,t.jsxs)(n.p,{children:["You can also just call ",(0,t.jsx)(n.code,{children:".cloneType"})," on your ",(0,t.jsx)(n.code,{children:"gen"})," argument directly.\nWhile we try to hide this implementation detail from the user, ",(0,t.jsx)(n.code,{children:".cloneType"})," is the mechanism by which Chisel creates fresh instances of ",(0,t.jsx)(n.code,{children:"Data"})," objects:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class UsingCloneTypeBundle[T <: Data](gen: T) extends Bundle {\n val foo = gen.cloneType\n val bar = gen.cloneType\n}\n"})}),"\n",(0,t.jsxs)(n.h3,{id:"-how-do-i-deal-with-the-unable-to-clone-error",children:[(0,t.jsx)("a",{name:"bundle-unable-to-clone"}),' How do I deal with the "unable to clone" error?']}),"\n",(0,t.jsx)(n.p,{children:'Most Chisel objects need to be cloned in order to differentiate between the\nsoftware representation of the bundle field from its "bound" hardware\nrepresentation, where "binding" is the process of generating a hardware\ncomponent. For Bundle fields, this cloning is supposed to happen automatically\nwith a compiler plugin.'}),"\n",(0,t.jsxs)(n.p,{children:["In some cases though, the plugin may not be able to clone the Bundle fields. The\nmost common case for when this happens is when the ",(0,t.jsx)(n.code,{children:"chisel3.Data"})," part of the\nBundle field is nested inside some other data structure and the compiler plugin\nis unable to figure out how to clone the entire structure. It is best to avoid\nsuch nested structures."]}),"\n",(0,t.jsxs)(n.p,{children:["There are a few ways around this issue - you can try wrapping the problematic\nfields in Input(...), Output(...), or Flipped(...) if appropriate. You can also\ntry manually cloning each field in the Bundle using the ",(0,t.jsx)(n.code,{children:"chiselTypeClone"})," method\nin ",(0,t.jsx)(n.code,{children:"chisel3.reflect.DataMirror"}),". Here's an example with the Bundle whose fields\nwon't get cloned:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class CustomBundleBroken(elts: (String, Data)*) extends Record {\n val elements = ListMap(elts: _*)\n\n def apply(elt: String): Data = elements(elt)\n}\n\nclass NewModule extends Module {\n val out = Output(UInt(8.W))\n val recordType = new CustomBundleBroken("fizz" -> UInt(16.W), "buzz" -> UInt(16.W))\n val record = Wire(recordType)\n val uint = record.asUInt\n val record2 = uint.asTypeOf(recordType)\n out := record\n}\ngetVerilogString(new NewModule)\n// 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.\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:441)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:441)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md:441)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1.(cookbook.md:441)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:446)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:446)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You can use ",(0,t.jsx)(n.code,{children:"chiselTypeClone"})," to clone the elements as:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3.reflect.DataMirror\nimport chisel3.experimental.requireIsChiselType\n\nclass CustomBundleFixed(elts: (String, Data)*) extends Record {\n val elements = ListMap(elts.map {\n case (field, elt) =>\n requireIsChiselType(elt)\n field -> DataMirror.internal.chiselTypeClone(elt)\n }: _*)\n\n def apply(elt: String): Data = elements(elt)\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-a-finite-state-machine-fsm",children:"How do I create a finite state machine (FSM)?"}),"\n",(0,t.jsxs)(n.p,{children:["The advised way is to use ",(0,t.jsx)(n.code,{children:"ChiselEnum"})," to construct enumerated types representing the state of the FSM.\nState transitions are then handled with ",(0,t.jsx)(n.code,{children:"switch"}),"/",(0,t.jsx)(n.code,{children:"is"})," and ",(0,t.jsx)(n.code,{children:"when"}),"/",(0,t.jsx)(n.code,{children:".elsewhen"}),"/",(0,t.jsx)(n.code,{children:".otherwise"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.{switch, is}\n\nobject DetectTwoOnes {\n object State extends ChiselEnum {\n val sNone, sOne1, sTwo1s = Value\n }\n}\n\n/* This FSM detects two 1's one after the other */\nclass DetectTwoOnes extends Module {\n import DetectTwoOnes.State\n import DetectTwoOnes.State._\n\n val io = IO(new Bundle {\n val in = Input(Bool())\n val out = Output(Bool())\n val state = Output(State())\n })\n\n val state = RegInit(sNone)\n\n io.out := (state === sTwo1s)\n io.state := state\n\n switch (state) {\n is (sNone) {\n when (io.in) {\n state := sOne1\n }\n }\n is (sOne1) {\n when (io.in) {\n state := sTwo1s\n } .otherwise {\n state := sNone\n }\n }\n is (sTwo1s) {\n when (!io.in) {\n state := sNone\n }\n }\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note: the ",(0,t.jsx)(n.code,{children:"is"})," statement can take multiple conditions e.g. ",(0,t.jsx)(n.code,{children:"is (sTwo1s, sOne1) { ... }"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-unpack-a-value-reverse-concatenation-like-in-verilog",children:'How do I unpack a value ("reverse concatenation") like in Verilog?'}),"\n",(0,t.jsxs)(n.p,{children:["In Verilog, you can do something like the following which will unpack a the value ",(0,t.jsx)(n.code,{children:"z"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"wire [1:0] a;\nwire [3:0] b;\nwire [2:0] c;\nwire [8:0] z = [...];\nassign {a,b,c} = z;\n"})}),"\n",(0,t.jsx)(n.p,{children:"Unpacking often corresponds to reinterpreting an unstructured data type as a structured data type.\nFrequently, this structured type is used prolifically in the design, and has been declared as in the following example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyBundle extends Bundle {\n val a = UInt(2.W)\n val b = UInt(4.W)\n val c = UInt(3.W)\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"The easiest way to accomplish this in Chisel would be:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Foo extends Module {\n val z = Wire(UInt(9.W))\n z := DontCare // This is a dummy connection\n val unpacked = z.asTypeOf(new MyBundle)\n printf("%d", unpacked.a)\n printf("%d", unpacked.b)\n printf("%d", unpacked.c)\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["If you ",(0,t.jsx)(n.strong,{children:"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 ",(0,t.jsx)(n.a,{href:"https://github.com/freechipsproject/rocket-chip/blob/723af5e6b69e07b5f94c46269a208a8d65e9d73b/src/main/scala/util/Misc.scala#L140",children:"Split utility"})," which can accomplish this."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-do-subword-assignment-assign-to-some-bits-in-a-uint",children:"How do I do subword assignment (assign to some bits in a UInt)?"}),"\n",(0,t.jsxs)(n.p,{children:["You may try to do something like the following where you want to assign only some bits of a Chisel type.\nBelow, the left-hand side connection to ",(0,t.jsx)(n.code,{children:"io.out(0)"})," is not allowed."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass Foo extends Module {\n val io = IO(new Bundle {\n val bit = Input(Bool())\n val out = Output(UInt(10.W))\n })\n io.out(0) := io.bit\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"If you try to compile this, you will get an error."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"getVerilogString(new Foo)\n// chisel3.package$ChiselException: Cannot reassign to read-only Foo.?: OpResult[Bool]\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp26$Foo.(cookbook.md:583)\n// \tat repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:591)\n// \tat repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:591)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Chisel3 ",(0,t.jsx)(n.em,{children:"does not support subword assignment"}),".\nThe reason for this is that subword assignment generally hints at a better abstraction with an aggregate/structured types, i.e., a ",(0,t.jsx)(n.code,{children:"Bundle"})," or a ",(0,t.jsx)(n.code,{children:"Vec"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["If you must express it this way, one approach is to blast your ",(0,t.jsx)(n.code,{children:"UInt"})," to a ",(0,t.jsx)(n.code,{children:"Vec"})," of ",(0,t.jsx)(n.code,{children:"Bool"})," and back:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass Foo extends Module {\n val io = IO(new Bundle {\n val in = Input(UInt(10.W))\n val bit = Input(Bool())\n val out = Output(UInt(10.W))\n })\n val bools = VecInit(io.in.asBools)\n bools(0) := io.bit\n io.out := bools.asUInt\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-an-optional-io",children:"How do I create an optional I/O?"}),"\n",(0,t.jsxs)(n.p,{children:["The following example is a module which includes the optional port ",(0,t.jsx)(n.code,{children:"out2"})," only if the given parameter is ",(0,t.jsx)(n.code,{children:"true"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass ModuleWithOptionalIOs(flag: Boolean) extends Module {\n val io = IO(new Bundle {\n val in = Input(UInt(12.W))\n val out = Output(UInt(12.W))\n val out2 = if (flag) Some(Output(UInt(12.W))) else None\n })\n\n io.out := io.in\n if (flag) {\n io.out2.get := io.in\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The following is an example where an entire ",(0,t.jsx)(n.code,{children:"IO"})," is optional:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass ModuleWithOptionalIO(flag: Boolean) extends Module {\n val in = if (flag) Some(IO(Input(Bool()))) else None\n val out = IO(Output(Bool()))\n\n out := in.getOrElse(false.B)\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-io-without-a-prefix",children:"How do I create I/O without a prefix?"}),"\n",(0,t.jsxs)(n.p,{children:["In most cases, you can simply call ",(0,t.jsx)(n.code,{children:"IO"})," multiple times:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyModule extends Module {\n val in = IO(Input(UInt(8.W)))\n val out = IO(Output(UInt(8.W)))\n\n out := in +% 1.U\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule MyModule(\n input clock,\n reset,\n input [7:0] in,\n output [7:0] out\n);\n\n assign out = in + 8'h1;\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you have a ",(0,t.jsx)(n.code,{children:"Bundle"})," from which you would like to create ports without the\nnormal ",(0,t.jsx)(n.code,{children:"val"})," prefix, you can use ",(0,t.jsx)(n.code,{children:"FlatIO"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = Input(UInt(8.W))\n val bar = Output(UInt(8.W))\n}\n\nclass MyModule extends Module {\n val io = FlatIO(new MyBundle)\n\n io.bar := io.foo +% 1.U\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that ",(0,t.jsx)(n.code,{children:"io_"})," is nowhere to be seen!"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule MyModule(\n input clock,\n reset,\n input [7:0] foo,\n output [7:0] bar\n);\n\n assign bar = foo + 8'h1;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-override-the-implicit-clock-or-reset-within-a-module",children:"How do I override the implicit clock or reset within a Module?"}),"\n",(0,t.jsxs)(n.p,{children:["To change the clock or reset for a region of code, use ",(0,t.jsx)(n.code,{children:"withClock"}),", ",(0,t.jsx)(n.code,{children:"withReset"}),", or ",(0,t.jsx)(n.code,{children:"withClockAndReset"}),".\nSee ",(0,t.jsx)(n.a,{href:"../explanations/multi-clock",children:"Multiple Clock Domains"})," for examples and details."]}),"\n",(0,t.jsxs)(n.p,{children:["To override the clock or reset for the entire scope of the ",(0,t.jsx)(n.code,{children:"Module"}),", you can mixin the ",(0,t.jsx)(n.code,{children:"ImplicitClock"})," and ",(0,t.jsx)(n.code,{children:"ImplicitReset"})," traits."]}),"\n",(0,t.jsx)(n.p,{children:'For example, you could "gate" the default implicit clock as follows:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass MyModule extends Module with ImplicitClock {\n val gate = IO(Input(Bool()))\n val in = IO(Input(UInt(8.W)))\n val out = IO(Output(UInt(8.W)))\n // We could just assign this to val implicitClock, but this allows us to give it a custom name\n val gatedClock = (clock.asBool || gate).asClock\n // The trait requires us to implement this method referring to the clock\n // Note that this is a def, but the actual clock value must be assigned to a val\n override protected def implicitClock = gatedClock\n\n val r = Reg(UInt(8.W))\n out := r\n r := in\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"This gives the following Verilog:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule MyModule(\n input clock,\n reset,\n gate,\n input [7:0] in,\n output [7:0] out\n);\n\n wire gatedClock = clock | gate;\n reg [7:0] r;\n always @(posedge gatedClock)\n r <= in;\n assign out = r;\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you do not care about the name of the overriden clock, you can just assign it to ",(0,t.jsx)(n.code,{children:"val implicitClock"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"override protected val implicitClock = (clock.asBool || gate).asClock\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ImplicitReset"})," works analogously to ",(0,t.jsx)(n.code,{children:"ImplicitClock"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-minimize-the-number-of-bits-used-in-an-output-vector",children:"How do I minimize the number of bits used in an output vector?"}),"\n",(0,t.jsxs)(n.p,{children:["Use inferred width and a ",(0,t.jsx)(n.code,{children:"Seq"})," instead of a ",(0,t.jsx)(n.code,{children:"Vec"}),":"]}),"\n",(0,t.jsx)(n.p,{children:"Consider:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\n// Count the number of set bits up to and including each bit position\nclass CountBits(width: Int) extends Module {\n val bits = IO(Input(UInt(width.W)))\n val countVector = IO(Output(Vec(width, UInt())))\n\n private val countSequence = Seq.tabulate(width)(i => Wire(UInt()))\n countSequence.zipWithIndex.foreach { case (port, i) =>\n port := util.PopCount(bits(i, 0))\n }\n countVector := countSequence\n}\n\nclass Top(width: Int) extends Module {\n val countBits = Module(new CountBits(width))\n countBits.bits :<>= DontCare\n dontTouch(countBits.bits)\n dontTouch(countBits.countVector)\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Note that top modules or public modules cannot have unknown widths."}),"\n",(0,t.jsxs)(n.p,{children:["Unlike ",(0,t.jsx)(n.code,{children:"Vecs"})," which represent a singular Chisel type and must have the same width for every element,\n",(0,t.jsx)(n.code,{children:"Seq"})," is a purely Scala construct, so their elements are independent from the perspective of Chisel and can have different widths."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule CountBits(\n input [3:0] bits,\n output [2:0] countVector_0,\n countVector_1,\n countVector_2,\n countVector_3\n);\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-resolve-dynamic-index--is-too-widenarrow-for-extractee-",children:'How do I resolve "Dynamic index ... is too wide/narrow for extractee ..."?'}),"\n",(0,t.jsx)(n.p,{children:'Chisel will warn if a dynamic index is not the correctly-sized width for indexing a Vec or UInt.\n"Correctly-sized" means that the width of the index should be the log2 of the size of the indexee.\nIf the indexee is a non-power-of-2 size, use the ceiling of the log2 result.'}),"\n",(0,t.jsxs)(n.p,{children:["When the index does not have enough bits to address all entries or bits in the extractee, you can ",(0,t.jsx)(n.code,{children:".pad"})," the index to increase the width."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooNarrow extends RawModule {\n val extractee = Wire(UInt(7.W))\n val index = Wire(UInt(2.W))\n extractee(index)\n}\ncompile(new TooNarrow)\n// [warn] cookbook.md 816:12: [W003] Dynamic index with width 2 is too small for extractee of width 7\n// [warn] There were 1 warning(s) during hardware elaboration.\n"})}),"\n",(0,t.jsxs)(n.p,{children:["This can be fixed with ",(0,t.jsx)(n.code,{children:"pad"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooNarrowFixed extends RawModule {\n val extractee = Wire(UInt(7.W))\n val index = Wire(UInt(2.W))\n extractee(index.pad(3))\n}\ncompile(new TooNarrowFixed)\n"})}),"\n",(0,t.jsx)(n.h4,{id:"use-bit-extraction-when-the-index-is-too-wide",children:"Use bit extraction when the index is too wide"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooWide extends RawModule {\n val extractee = Wire(Vec(8, UInt(32.W)))\n val index = Wire(UInt(4.W))\n extractee(index)\n}\ncompile(new TooWide)\n// [warn] cookbook.md 842:12: [W004] Dynamic index with width 4 is too wide for Vec of size 8 (expected index width 3).\n// [warn] There were 1 warning(s) during hardware elaboration.\n"})}),"\n",(0,t.jsx)(n.p,{children:"This can be fixed with bit extraction:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooWideFixed extends RawModule {\n val extractee = Wire(Vec(8, UInt(32.W)))\n val index = Wire(UInt(4.W))\n extractee(index(2, 0))\n}\ncompile(new TooWideFixed)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that size 1 ",(0,t.jsx)(n.code,{children:"Vecs"})," and ",(0,t.jsx)(n.code,{children:"UInts"})," should be indexed by a zero-width ",(0,t.jsx)(n.code,{children:"UInt"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class SizeOneVec extends RawModule {\n val extractee = Wire(Vec(1, UInt(32.W)))\n val index = Wire(UInt(0.W))\n extractee(index)\n}\ncompile(new SizeOneVec)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Because ",(0,t.jsx)(n.code,{children:"pad"})," only pads if the desired width is less than the current width of the argument,\nyou can use ",(0,t.jsx)(n.code,{children:"pad"})," in conjunction with bit extraction when the widths may be too wide or too\nnarrow under different circumstances"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.log2Ceil\nclass TooWideOrNarrow(extracteeSize: Int, indexWidth: Int) extends Module {\n val extractee = Wire(Vec(extracteeSize, UInt(8.W)))\n val index = Wire(UInt(indexWidth.W))\n val correctWidth = log2Ceil(extracteeSize)\n extractee(index.pad(correctWidth)(correctWidth - 1, 0))\n}\ncompile(new TooWideOrNarrow(8, 2))\ncompile(new TooWideOrNarrow(8, 4))\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Another option for dynamic bit selection of ",(0,t.jsx)(n.code,{children:"UInts"})," (but not ",(0,t.jsx)(n.code,{children:"Vec"})," dynamic indexing) is to do a dynamic\nright shift of the extractee by the index and then just bit select a single bit:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooWideOrNarrowUInt(extracteeSize: Int, indexWidth: Int) extends Module {\n val extractee = Wire(UInt(extracteeSize.W))\n val index = Wire(UInt(indexWidth.W))\n (extractee >> index)(0)\n}\ncompile(new TooWideOrNarrowUInt(8, 2))\ncompile(new TooWideOrNarrowUInt(8, 4))\n"})}),"\n",(0,t.jsx)(n.h2,{id:"predictable-naming",children:"Predictable Naming"}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-get-chisel-to-name-signals-properly-in-blocks-like-whenwithclockandreset",children:"How do I get Chisel to name signals properly in blocks like when/withClockAndReset?"}),"\n",(0,t.jsxs)(n.p,{children:["Use the compiler plugin, and check out the ",(0,t.jsx)(n.a,{href:"naming",children:"Naming Cookbook"})," if that still does not do what you want."]}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-get-chisel-to-name-the-results-of-vector-reads-properly",children:"How do I get Chisel to name the results of vector reads properly?"}),"\n",(0,t.jsx)(n.p,{children:"Currently, name information is lost when using dynamic indexing. For example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass Foo extends Module {\n val io = IO(new Bundle {\n val in = Input(Vec(4, Bool()))\n val idx = Input(UInt(2.W))\n val en = Input(Bool())\n val out = Output(Bool())\n })\n\n val x = io.in(io.idx)\n val y = x && io.en\n io.out := y\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The above code loses the ",(0,t.jsx)(n.code,{children:"x"})," name, instead using ",(0,t.jsx)(n.code,{children:"_GEN_3"})," (the other ",(0,t.jsx)(n.code,{children:"_GEN_*"})," signals are expected)."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule Foo(\n input clock,\n reset,\n io_in_0,\n io_in_1,\n io_in_2,\n io_in_3,\n input [1:0] io_idx,\n input io_en,\n output io_out\n);\n\n wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}};\n assign io_out = _GEN[io_idx] & io_en;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"This can be worked around by creating a wire and connecting the dynamic index to the wire:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"val x = WireInit(io.in(io.idx))\n"})}),"\n",(0,t.jsx)(n.p,{children:"Which produces:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule Foo2(\n input clock,\n reset,\n io_in_0,\n io_in_1,\n io_in_2,\n io_in_3,\n input [1:0] io_idx,\n input io_en,\n output io_out\n);\n\n wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}};\n assign io_out = _GEN[io_idx] & io_en;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-can-i-dynamically-setparametrize-the-name-of-a-module",children:"How can I dynamically set/parametrize the name of a module?"}),"\n",(0,t.jsxs)(n.p,{children:["You can override the ",(0,t.jsx)(n.code,{children:"desiredName"})," function. This works with normal Chisel modules and ",(0,t.jsx)(n.code,{children:"BlackBox"}),"es. Example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass Coffee extends BlackBox {\n val io = IO(new Bundle {\n val I = Input(UInt(32.W))\n val O = Output(UInt(32.W))\n })\n override def desiredName = "Tea"\n}\n\nclass Salt extends Module {\n val io = IO(new Bundle {})\n val drink = Module(new Coffee)\n override def desiredName = "SodiumMonochloride"\n\n drink.io.I := 42.U\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Elaborating the Chisel module ",(0,t.jsx)(n.code,{children:"Salt"}),' yields our "desired names" for ',(0,t.jsx)(n.code,{children:"Salt"})," and ",(0,t.jsx)(n.code,{children:"Coffee"})," in the output Verilog:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule SodiumMonochloride(\n input clock,\n reset\n);\n\n Tea drink (\n .I (32'h2A),\n .O (/* unused */)\n );\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"directionality",children:"Directionality"}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-strip-directions-from-a-bidirectional-bundle-or-other-data",children:"How do I strip directions from a bidirectional Bundle (or other Data)?"}),"\n",(0,t.jsxs)(n.p,{children:["Given a bidirectional port like a ",(0,t.jsx)(n.code,{children:"Decoupled"}),", you will get an error if you try to connect it directly\nto a register:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.Decoupled\nclass BadRegConnect extends Module {\n val io = IO(new Bundle {\n val enq = Decoupled(UInt(8.W))\n })\n\n val monitor = Reg(chiselTypeOf(io.enq))\n monitor := io.enq\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"getVerilogString(new BadRegConnect)\n// circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: /home/runner/.cache/llvm-firtool/1.86.0/bin/firtool returned a non-zero exit code. Note that this version of Chisel (7.0.0-M2+115-fc4de1f3-SNAPSHOT) was published against firtool version 1.86.0.\n// ------------------------------------------------------------------------------\n// ExitCode:\n// 1\n// STDOUT:\n// \n// STDERR:\n// cookbook.md:1013:20: error: 'firrtl.reg' op result #0 must be a passive non-'const' base type that does not contain analog, but got '!firrtl.bundle, valid: uint<1>, bits: uint<8>>'\n// cookbook.md:1013:20: note: see current operation: %4 = \"firrtl.reg\"(%arg0) {annotations = [], name = \"monitor\", nameKind = #firrtl} : (!firrtl.clock) -> !firrtl.bundle, valid: uint<1>, bits: uint<8>>\n// \n// ------------------------------------------------------------------------------\n"})}),"\n",(0,t.jsxs)(n.p,{children:['While there is no construct to "strip direction" in Chisel3, wrapping a type in ',(0,t.jsx)(n.code,{children:"Output(...)"}),"\n(the default direction in Chisel3) will\nset all of the individual elements to output direction.\nThis will have the desired result when used to construct a Register:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.Decoupled\nclass CoercedRegConnect extends Module {\n val io = IO(new Bundle {\n val enq = Flipped(Decoupled(UInt(8.W)))\n })\n\n // Make a Reg which contains all of the bundle's signals, regardless of their directionality\n val monitor = Reg(Output(chiselTypeOf(io.enq)))\n // Even though io.enq is bidirectional, := will drive all fields of monitor with the fields of io.enq\n monitor := io.enq\n}\n"})})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1871:(e,n,a)=>{a.d(n,{A:()=>i});a(6540);var t=a(5195);const o={tableOfContentsInline:"tableOfContentsInline_prmo"};var l=a(4848);function i(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:i}=e;return(0,l.jsx)("div",{className:o.tableOfContentsInline,children:(0,l.jsx)(t.A,{toc:n,minHeadingLevel:a,maxHeadingLevel:i,className:"table-of-contents",linkClassName:null})})}},5195:(e,n,a)=>{a.d(n,{A:()=>g});var t=a(6540),o=a(6342);function l(e){const n=e.map((e=>({...e,parentIndex:-1,children:[]}))),a=Array(7).fill(-1);n.forEach(((e,n)=>{const t=a.slice(2,e.level);e.parentIndex=Math.max(...t),a[e.level]=n}));const t=[];return n.forEach((e=>{const{parentIndex:a,...o}=e;a>=0?n[a].children.push(o):t.push(o)})),t}function i(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:t}=e;return n.flatMap((e=>{const n=i({toc:e.children,minHeadingLevel:a,maxHeadingLevel:t});return function(e){return e.level>=a&&e.level<=t}(e)?[{...e,children:n}]:n}))}function s(e){const n=e.getBoundingClientRect();return n.top===n.bottom?s(e.parentNode):n}function c(e,n){let{anchorTopOffset:a}=n;const t=e.find((e=>s(e).top>=a));if(t){return function(e){return e.top>0&&e.bottom{e.current=n?0:document.querySelector(".navbar").clientHeight}),[n]),e}function d(e){const n=(0,t.useRef)(void 0),a=r();(0,t.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:t,linkActiveClassName:o,minHeadingLevel:l,maxHeadingLevel:i}=e;function s(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(t),s=function(e){let{minHeadingLevel:n,maxHeadingLevel:a}=e;const t=[];for(let o=n;o<=a;o+=1)t.push(`h${o}.anchor`);return Array.from(document.querySelectorAll(t.join()))}({minHeadingLevel:l,maxHeadingLevel:i}),r=c(s,{anchorTopOffset:a.current}),d=e.find((e=>r&&r.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,a){a?(n.current&&n.current!==e&&n.current.classList.remove(o),e.classList.add(o),n.current=e):e.classList.remove(o)}(e,e===d)}))}return document.addEventListener("scroll",s),document.addEventListener("resize",s),s(),()=>{document.removeEventListener("scroll",s),document.removeEventListener("resize",s)}}),[e,a])}var u=a(8774),h=a(4848);function p(e){let{toc:n,className:a,linkClassName:t,isChild:o}=e;return n.length?(0,h.jsx)("ul",{className:o?void 0:a,children:n.map((e=>(0,h.jsxs)("li",{children:[(0,h.jsx)(u.A,{to:`#${e.id}`,className:t??void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,h.jsx)(p,{isChild:!0,toc:e.children,className:a,linkClassName:t})]},e.id)))}):null}const m=t.memo(p);function g(e){let{toc:n,className:a="table-of-contents table-of-contents__left-border",linkClassName:s="table-of-contents__link",linkActiveClassName:c,minHeadingLevel:r,maxHeadingLevel:u,...p}=e;const g=(0,o.p)(),x=r??g.tableOfContents.minHeadingLevel,f=u??g.tableOfContents.maxHeadingLevel,w=function(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:o}=e;return(0,t.useMemo)((()=>i({toc:l(n),minHeadingLevel:a,maxHeadingLevel:o})),[n,a,o])}({toc:n,minHeadingLevel:x,maxHeadingLevel:f});return d((0,t.useMemo)((()=>{if(s&&c)return{linkClassName:s,linkActiveClassName:c,minHeadingLevel:x,maxHeadingLevel:f}}),[s,c,x,f])),(0,h.jsx)(m,{toc:w,className:a,linkClassName:s,...p})}},8453:(e,n,a)=>{a.d(n,{R:()=>i,x:()=>s});var t=a(6540);const o={},l=t.createContext(o);function i(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[5432],{7363:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>s,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var t=a(4848),o=a(8453),l=a(1871);const i={sidebar_position:0},s="General Cookbook",c={id:"cookbooks/cookbook",title:"General Cookbook",description:"Please note that these examples make use of Chisel's scala-style printing.",source:"@site/docs/cookbooks/cookbook.md",sourceDirName:"cookbooks",slug:"/cookbooks/cookbook",permalink:"/docs/cookbooks/cookbook",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/cookbooks/cookbook.md",tags:[],version:"current",sidebarPosition:0,frontMatter:{sidebar_position:0},sidebar:"chiselSidebar",previous:{title:"Cookbooks",permalink:"/docs/cookbooks"},next:{title:"Naming Cookbook",permalink:"/docs/cookbooks/naming"}},r={},d=[{value:"Type Conversions",id:"type-conversions",level:2},{value:"How do I create a UInt from an instance of a Bundle?",id:"how-do-i-create-a-uint-from-an-instance-of-a-bundle",level:3},{value:"How do I create a Bundle from a UInt?",id:"how-do-i-create-a-bundle-from-a-uint",level:3},{value:"How can I tieoff a Bundle/Vec to 0?",id:"how-can-i-tieoff-a-bundlevec-to-0",level:3},{value:"How do I create a Vec of Bools from a UInt?",id:"how-do-i-create-a-vec-of-bools-from-a-uint",level:3},{value:"How do I create a UInt from a Vec of Bool?",id:"how-do-i-create-a-uint-from-a-vec-of-bool",level:3},{value:"How do I connect a subset of Bundle fields?",id:"how-do-i-connect-a-subset-of-bundle-fields",level:3},{value:"Vectors and Registers",id:"vectors-and-registers",level:2},{value:"Can I make a 2D or 3D Vector?",id:"can-i-make-a-2d-or-3d-vector",level:3},{value:"How do I create a Vector of Registers?",id:"how-do-i-create-a-vector-of-registers",level:3},{value:"How do I create a Reg of type Vec?",id:"how-do-i-create-a-reg-of-type-vec",level:3},{value:"How do I partially reset an Aggregate Reg?",id:"how-do-i-partially-reset-an-aggregate-reg",level:3},{value:"Bundles",id:"bundles",level:2},{value:"How do I deal with aliased Bundle fields?",id:"how-do-i-deal-with-aliased-bundle-fields",level:3},{value:"1. 0-arity function parameters",id:"1-0-arity-function-parameters",level:4},{value:"Aliased Warning",id:"aliased-warning",level:5},{value:"2. By-name function parameters",id:"2-by-name-function-parameters",level:4},{value:"3. Directioned Bundle fields",id:"3-directioned-bundle-fields",level:4},{value:"4. Call .cloneType directly",id:"4-call-clonetype-directly",level:4},{value:" How do I deal with the "unable to clone" error?",id:"-how-do-i-deal-with-the-unable-to-clone-error",level:3},{value:"How do I create a finite state machine (FSM)?",id:"how-do-i-create-a-finite-state-machine-fsm",level:2},{value:"How do I unpack a value ("reverse concatenation") like in Verilog?",id:"how-do-i-unpack-a-value-reverse-concatenation-like-in-verilog",level:2},{value:"How do I do subword assignment (assign to some bits in a UInt)?",id:"how-do-i-do-subword-assignment-assign-to-some-bits-in-a-uint",level:2},{value:"How do I create an optional I/O?",id:"how-do-i-create-an-optional-io",level:2},{value:"How do I create I/O without a prefix?",id:"how-do-i-create-io-without-a-prefix",level:2},{value:"How do I override the implicit clock or reset within a Module?",id:"how-do-i-override-the-implicit-clock-or-reset-within-a-module",level:2},{value:"How do I minimize the number of bits used in an output vector?",id:"how-do-i-minimize-the-number-of-bits-used-in-an-output-vector",level:2},{value:"How do I resolve "Dynamic index ... is too wide/narrow for extractee ..."?",id:"how-do-i-resolve-dynamic-index--is-too-widenarrow-for-extractee-",level:2},{value:"Use bit extraction when the index is too wide",id:"use-bit-extraction-when-the-index-is-too-wide",level:4},{value:"Predictable Naming",id:"predictable-naming",level:2},{value:"How do I get Chisel to name signals properly in blocks like when/withClockAndReset?",id:"how-do-i-get-chisel-to-name-signals-properly-in-blocks-like-whenwithclockandreset",level:3},{value:"How do I get Chisel to name the results of vector reads properly?",id:"how-do-i-get-chisel-to-name-the-results-of-vector-reads-properly",level:3},{value:"How can I dynamically set/parametrize the name of a module?",id:"how-can-i-dynamically-setparametrize-the-name-of-a-module",level:3},{value:"Directionality",id:"directionality",level:2},{value:"How do I strip directions from a bidirectional Bundle (or other Data)?",id:"how-do-i-strip-directions-from-a-bidirectional-bundle-or-other-data",level:3}];function u(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"general-cookbook",children:"General Cookbook"})}),"\n",(0,t.jsxs)(n.p,{children:["Please note that these examples make use of ",(0,t.jsx)(n.a,{href:"../explanations/printing#scala-style",children:"Chisel's scala-style printing"}),"."]}),"\n","\n",(0,t.jsx)(l.A,{toc:d}),"\n",(0,t.jsx)(n.h2,{id:"type-conversions",children:"Type Conversions"}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-uint-from-an-instance-of-a-bundle",children:"How do I create a UInt from an instance of a Bundle?"}),"\n",(0,t.jsxs)(n.p,{children:["Call ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html#asUInt:chisel3.UInt",children:(0,t.jsx)(n.code,{children:"asUInt"})})," on the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html",children:(0,t.jsx)(n.code,{children:"Bundle"})})," instance."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = UInt(4.W)\n val bar = UInt(4.W)\n}\n\nclass Foo extends Module {\n val bundle = Wire(new MyBundle)\n bundle.foo := 0xc.U\n bundle.bar := 0x3.U\n val uint = bundle.asUInt\n printf(cf"$uint") // 195\n\n // Test\n assert(uint === 0xc3.U)\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-bundle-from-a-uint",children:"How do I create a Bundle from a UInt?"}),"\n",(0,t.jsxs)(n.p,{children:["Use the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html#asTypeOf%5BT%3C:chisel3.Data%5D(that:T):T",children:(0,t.jsx)(n.code,{children:"asTypeOf"})})," method to reinterpret the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html",children:(0,t.jsx)(n.code,{children:"UInt"})})," as the type of the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html",children:(0,t.jsx)(n.code,{children:"Bundle"})}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = UInt(4.W)\n val bar = UInt(4.W)\n}\n\nclass Foo extends Module {\n val uint = 0xb4.U\n val bundle = uint.asTypeOf(new MyBundle)\n\n printf(cf"$bundle") // Bundle(foo -> 11, bar -> 4)\n\n // Test\n assert(bundle.foo === 0xb.U)\n assert(bundle.bar === 0x4.U)\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"how-can-i-tieoff-a-bundlevec-to-0",children:"How can I tieoff a Bundle/Vec to 0?"}),"\n",(0,t.jsxs)(n.p,{children:["You can use ",(0,t.jsx)(n.code,{children:"asTypeOf"})," as above. If you don't want to worry about the type of the thing\nyou are tying off, you can use ",(0,t.jsx)(n.code,{children:"chiselTypeOf"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = UInt(4.W)\n val bar = Vec(4, UInt(1.W))\n}\n\nclass Foo(typ: MyBundle) extends Module {\n val bundleA = IO(Output(typ))\n val bundleB = IO(Output(typ))\n\n // typ is already a Chisel Data Type, so can use it directly here, but you\n // need to know that bundleA is of type typ\n bundleA := 0.U.asTypeOf(typ)\n\n // bundleB is a Hardware data IO(Output(...)) so need to call chiselTypeOf,\n // but this will work no matter the type of bundleB:\n bundleB := 0.U.asTypeOf(chiselTypeOf(bundleB))\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-vec-of-bools-from-a-uint",children:"How do I create a Vec of Bools from a UInt?"}),"\n",(0,t.jsxs)(n.p,{children:["Use ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/VecInit$.html",children:(0,t.jsx)(n.code,{children:"VecInit"})})," given a ",(0,t.jsx)(n.code,{children:"Seq[Bool]"})," generated using the ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html#asBools:Seq%5Bchisel3.Bool%5D",children:(0,t.jsx)(n.code,{children:"asBools"})})," method."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass Foo extends Module {\n val uint = 0xc.U\n val vec = VecInit(uint.asBools)\n\n printf(cf"$vec") // Vec(0, 0, 1, 1)\n\n // Test\n assert(vec(0) === false.B)\n assert(vec(1) === false.B)\n assert(vec(2) === true.B)\n assert(vec(3) === true.B)\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-uint-from-a-vec-of-bool",children:"How do I create a UInt from a Vec of Bool?"}),"\n",(0,t.jsxs)(n.p,{children:["Use the builtin function ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Vec.html#asUInt:chisel3.UInt",children:(0,t.jsx)(n.code,{children:"asUInt"})})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass Foo extends Module {\n val vec = VecInit(true.B, false.B, true.B, true.B)\n val uint = vec.asUInt\n\n printf(cf"$uint") // 13\n\n // Test\n // (remember leftmost Bool in Vec is low order bit)\n assert(0xd.U === uint)\n\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-connect-a-subset-of-bundle-fields",children:"How do I connect a subset of Bundle fields?"}),"\n",(0,t.jsxs)(n.p,{children:["See the ",(0,t.jsx)(n.a,{href:"dataview#how-do-i-connect-a-subset-of-bundle-fields",children:"DataView cookbook"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"vectors-and-registers",children:"Vectors and Registers"}),"\n",(0,t.jsx)(n.h3,{id:"can-i-make-a-2d-or-3d-vector",children:"Can I make a 2D or 3D Vector?"}),"\n",(0,t.jsxs)(n.p,{children:["Yes. Using ",(0,t.jsx)(n.code,{children:"VecInit"})," you can make Vectors that hold Vectors of Chisel types. Methods ",(0,t.jsx)(n.code,{children:"fill"})," and ",(0,t.jsx)(n.code,{children:"tabulate"})," make these multi-dimensional Vectors."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = UInt(4.W)\n val bar = UInt(4.W)\n}\n\nclass Foo extends Module {\n //2D Fill\n val twoDVec = VecInit.fill(2, 3)(5.U)\n //3D Fill\n val myBundle = Wire(new MyBundle)\n myBundle.foo := 0xc.U\n myBundle.bar := 0x3.U\n val threeDVec = VecInit.fill(1, 2, 3)(myBundle)\n assert(threeDVec(0)(0)(0).foo === 0xc.U && threeDVec(0)(0)(0).bar === 0x3.U)\n\n //2D Tabulate\n val indexTiedVec = VecInit.tabulate(2, 2){ (x, y) => (x + y).U }\n assert(indexTiedVec(0)(0) === 0.U)\n assert(indexTiedVec(0)(1) === 1.U)\n assert(indexTiedVec(1)(0) === 1.U)\n assert(indexTiedVec(1)(1) === 2.U)\n //3D Tabulate\n val indexTiedVec3D = VecInit.tabulate(2, 3, 4){ (x, y, z) => (x + y * z).U }\n assert(indexTiedVec3D(0)(0)(0) === 0.U)\n assert(indexTiedVec3D(1)(1)(1) === 2.U)\n assert(indexTiedVec3D(1)(1)(2) === 3.U)\n assert(indexTiedVec3D(1)(1)(3) === 4.U)\n assert(indexTiedVec3D(1)(2)(3) === 7.U)\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-vector-of-registers",children:"How do I create a Vector of Registers?"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Rule! Use Reg of Vec not Vec of Reg!"})}),"\n",(0,t.jsxs)(n.p,{children:["You create a ",(0,t.jsx)(n.a,{href:"#how-do-i-create-a-reg-of-type-vec",children:"Reg of type Vec"}),". Because Vecs are a ",(0,t.jsx)(n.em,{children:"type"})," (like ",(0,t.jsx)(n.code,{children:"UInt"}),", ",(0,t.jsx)(n.code,{children:"Bool"}),") rather than a ",(0,t.jsx)(n.em,{children:"value"}),", we must bind the Vec to some concrete ",(0,t.jsx)(n.em,{children:"value"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-create-a-reg-of-type-vec",children:"How do I create a Reg of type Vec?"}),"\n",(0,t.jsxs)(n.p,{children:["For more information, the API Documentation for ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Vec.html",children:(0,t.jsx)(n.code,{children:"Vec"})})," provides more information."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass Foo extends Module {\n val regOfVec = Reg(Vec(4, UInt(32.W))) // Register of 32-bit UInts\n regOfVec(0) := 123.U // Assignments to elements of the Vec\n regOfVec(1) := 456.U\n regOfVec(2) := 789.U\n regOfVec(3) := regOfVec(0)\n\n // Reg of Vec of 32-bit UInts initialized to zero\n // Note that Seq.fill constructs 4 32-bit UInt literals with the value 0\n // VecInit(...) then constructs a Wire of these literals\n // The Reg is then initialized to the value of the Wire (which gives it the same type)\n val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W))))\n}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-partially-reset-an-aggregate-reg",children:"How do I partially reset an Aggregate Reg?"}),"\n",(0,t.jsxs)(n.p,{children:["The easiest way is to use a partially-specified ",(0,t.jsx)(n.a,{href:"../appendix/experimental-features#bundle-literals",children:"Bundle Literal"}),"\nor ",(0,t.jsx)(n.a,{href:"../appendix/experimental-features#vec-literals",children:"Vec Literal"})," to match the type of the Reg."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.BundleLiterals._\n\nclass MyBundle extends Bundle {\n val foo = UInt(8.W)\n val bar = UInt(8.W)\n}\n\nclass MyModule extends Module {\n // Only .foo will be reset, .bar will have no reset value\n val reg = RegInit((new MyBundle).Lit(_.foo -> 123.U))\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If your initial value is not a literal, or if you just prefer, you can use a\nWire as the initial value for the Reg. Simply connect fields to ",(0,t.jsx)(n.code,{children:"DontCare"})," that\nyou do not wish to be reset."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class MyModule2 extends Module {\n val reg = RegInit({\n // The wire could be constructed before the reg rather than in the RegInit scope,\n // but this style has nice lexical scoping behavior, keeping the Wire private\n val init = Wire(new MyBundle)\n init := DontCare // No fields will be reset\n init.foo := 123.U // Last connect override, .foo is reset\n init\n })\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"bundles",children:"Bundles"}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-deal-with-aliased-bundle-fields",children:"How do I deal with aliased Bundle fields?"}),"\n",(0,t.jsxs)(n.p,{children:["Following the ",(0,t.jsx)(n.code,{children:"gen"})," pattern when creating Bundles can result in some opaque error messages:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class AliasedBundle[T <: Data](gen: T) extends Bundle {\n val foo = gen\n val bar = gen\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"getVerilogString(new Top(new AliasedBundle(UInt(8.W))))\n// chisel3.AliasedAggregateFieldException: AliasedBundle contains aliased fields named (foo,bar)\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp17$Top.(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:317)\n// \tat repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:317)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["This error is saying that fields ",(0,t.jsx)(n.code,{children:"foo"})," and ",(0,t.jsx)(n.code,{children:"bar"})," of ",(0,t.jsx)(n.code,{children:"AliasedBundle"})," are the\nexact same object in memory.\nThis is a problem for Chisel because we need to be able to distinguish uses of\n",(0,t.jsx)(n.code,{children:"foo"})," and ",(0,t.jsx)(n.code,{children:"bar"})," but cannot when they are referentially the same."]}),"\n",(0,t.jsx)(n.p,{children:"Note that the following example looks different but will give you exactly the same issue:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class AlsoAliasedBundle[T <: Data](val gen: T) extends Bundle {\n // ^ This val makes `gen` a field, just like `foo`\n val foo = gen\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["By making ",(0,t.jsx)(n.code,{children:"gen"})," a ",(0,t.jsx)(n.code,{children:"val"}),", it becomes a public field of the ",(0,t.jsx)(n.code,{children:"class"}),", just like ",(0,t.jsx)(n.code,{children:"foo"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"getVerilogString(new Top(new AlsoAliasedBundle(UInt(8.W))))\n// chisel3.AliasedAggregateFieldException: AlsoAliasedBundle contains aliased fields named (gen,foo)\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp17$Top.(cookbook.md:298)\n// \tat repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:336)\n// \tat repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:336)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsx)(n.p,{children:"There are several ways to solve this issue with their own advantages and disadvantages."}),"\n",(0,t.jsx)(n.h4,{id:"1-0-arity-function-parameters",children:"1. 0-arity function parameters"}),"\n",(0,t.jsx)(n.p,{children:"Instead of passing an object as a parameter, you can pass a 0-arity function (a function with no arguments):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class UsingAFunctionBundle[T <: Data](gen: () => T) extends Bundle {\n val foo = gen()\n val bar = gen()\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that the type of ",(0,t.jsx)(n.code,{children:"gen"})," is now ",(0,t.jsx)(n.code,{children:"() => T"}),".\nBecause it is now a function and not a subtype of ",(0,t.jsx)(n.code,{children:"Data"}),", you can safely make ",(0,t.jsx)(n.code,{children:"gen"})," a ",(0,t.jsx)(n.code,{children:"val"})," without\nit becoming a hardware field of the ",(0,t.jsx)(n.code,{children:"Bundle"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Note that this also means you must pass ",(0,t.jsx)(n.code,{children:"gen"})," as a function, for example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"chisel3.docs.emitSystemVerilog(new Top(new UsingAFunctionBundle(() => UInt(8.W))))\n"})}),"\n",(0,t.jsx)(n.h5,{id:"aliased-warning",children:"Aliased Warning"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Warning"}),": you must ensure that ",(0,t.jsx)(n.code,{children:"gen"})," creates fresh objects rather than capturing an already constructed value:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class MisusedFunctionArguments extends Module {\n // This usage is correct\n val in = IO(Input(new UsingAFunctionBundle(() => UInt(8.W))))\n\n // This usage is incorrect\n val fizz = UInt(8.W)\n val out = IO(Output(new UsingAFunctionBundle(() => fizz)))\n}\ngetVerilogString(new MisusedFunctionArguments)\n// chisel3.AutoClonetypeException: The bundle plugin was unable to clone UsingAFunctionBundle that has field 'bar' 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.\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:367)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:367)\n// \tat chisel3.IO$.apply(IO.scala:34)\n// \tat chisel3.experimental.BaseModule.IO(ModuleImpl.scala:863)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:367)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:367)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md:367)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1.(cookbook.md:367)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:369)\n// \tat repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:369)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["In the above example, value ",(0,t.jsx)(n.code,{children:"fizz"})," and fields ",(0,t.jsx)(n.code,{children:"foo"})," and ",(0,t.jsx)(n.code,{children:"bar"})," of ",(0,t.jsx)(n.code,{children:"out"})," are all the same object in memory."]}),"\n",(0,t.jsx)(n.h4,{id:"2-by-name-function-parameters",children:"2. By-name function parameters"}),"\n",(0,t.jsxs)(n.p,{children:["Functionally the same as (1) but with more subtle syntax, you can use ",(0,t.jsx)(n.a,{href:"https://docs.scala-lang.org/tour/by-name-parameters.html",children:"Scala by-name function parameters"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class UsingByNameParameters[T <: Data](gen: => T) extends Bundle {\n val foo = gen\n val bar = gen\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["With this usage, you do not include ",(0,t.jsx)(n.code,{children:"() =>"})," when passing the argument:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"chisel3.docs.emitSystemVerilog(new Top(new UsingByNameParameters(UInt(8.W))))\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that as this is just syntactic sugar over (1), the ",(0,t.jsx)(n.a,{href:"#aliased-warning",children:"same warning applies"}),"."]}),"\n",(0,t.jsx)(n.h4,{id:"3-directioned-bundle-fields",children:"3. Directioned Bundle fields"}),"\n",(0,t.jsxs)(n.p,{children:["You can alternatively wrap the fields with ",(0,t.jsx)(n.code,{children:"Output(...)"}),", which creates fresh instances of the passed argument.\nChisel treats ",(0,t.jsx)(n.code,{children:"Output"}),' as the "default direction" so if all fields are outputs, the ',(0,t.jsx)(n.code,{children:"Bundle"})," is functionally equivalent to a ",(0,t.jsx)(n.code,{children:"Bundle"})," with no directioned fields."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class DirectionedBundle[T <: Data](gen: T) extends Bundle {\n val foo = Output(gen)\n val bar = Output(gen)\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["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 ",(0,t.jsx)(n.code,{children:"Output"}),"."]}),"\n",(0,t.jsxs)(n.h4,{id:"4-call-clonetype-directly",children:["4. Call ",(0,t.jsx)(n.code,{children:".cloneType"})," directly"]}),"\n",(0,t.jsxs)(n.p,{children:["You can also just call ",(0,t.jsx)(n.code,{children:".cloneType"})," on your ",(0,t.jsx)(n.code,{children:"gen"})," argument directly.\nWhile we try to hide this implementation detail from the user, ",(0,t.jsx)(n.code,{children:".cloneType"})," is the mechanism by which Chisel creates fresh instances of ",(0,t.jsx)(n.code,{children:"Data"})," objects:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class UsingCloneTypeBundle[T <: Data](gen: T) extends Bundle {\n val foo = gen.cloneType\n val bar = gen.cloneType\n}\n"})}),"\n",(0,t.jsxs)(n.h3,{id:"-how-do-i-deal-with-the-unable-to-clone-error",children:[(0,t.jsx)("a",{name:"bundle-unable-to-clone"}),' How do I deal with the "unable to clone" error?']}),"\n",(0,t.jsx)(n.p,{children:'Most Chisel objects need to be cloned in order to differentiate between the\nsoftware representation of the bundle field from its "bound" hardware\nrepresentation, where "binding" is the process of generating a hardware\ncomponent. For Bundle fields, this cloning is supposed to happen automatically\nwith a compiler plugin.'}),"\n",(0,t.jsxs)(n.p,{children:["In some cases though, the plugin may not be able to clone the Bundle fields. The\nmost common case for when this happens is when the ",(0,t.jsx)(n.code,{children:"chisel3.Data"})," part of the\nBundle field is nested inside some other data structure and the compiler plugin\nis unable to figure out how to clone the entire structure. It is best to avoid\nsuch nested structures."]}),"\n",(0,t.jsxs)(n.p,{children:["There are a few ways around this issue - you can try wrapping the problematic\nfields in Input(...), Output(...), or Flipped(...) if appropriate. You can also\ntry manually cloning each field in the Bundle using the ",(0,t.jsx)(n.code,{children:"chiselTypeClone"})," method\nin ",(0,t.jsx)(n.code,{children:"chisel3.reflect.DataMirror"}),". Here's an example with the Bundle whose fields\nwon't get cloned:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class CustomBundleBroken(elts: (String, Data)*) extends Record {\n val elements = ListMap(elts: _*)\n\n def apply(elt: String): Data = elements(elt)\n}\n\nclass NewModule extends Module {\n val out = Output(UInt(8.W))\n val recordType = new CustomBundleBroken("fizz" -> UInt(16.W), "buzz" -> UInt(16.W))\n val record = Wire(recordType)\n val uint = record.asUInt\n val record2 = uint.asTypeOf(recordType)\n out := record\n}\ngetVerilogString(new NewModule)\n// 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.\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:441)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:441)\n// \tat chisel3.experimental.prefix$.apply(prefix.scala:50)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md:441)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1.(cookbook.md:441)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:446)\n// \tat repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:446)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You can use ",(0,t.jsx)(n.code,{children:"chiselTypeClone"})," to clone the elements as:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3.reflect.DataMirror\nimport chisel3.experimental.requireIsChiselType\n\nclass CustomBundleFixed(elts: (String, Data)*) extends Record {\n val elements = ListMap(elts.map {\n case (field, elt) =>\n requireIsChiselType(elt)\n field -> DataMirror.internal.chiselTypeClone(elt)\n }: _*)\n\n def apply(elt: String): Data = elements(elt)\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-a-finite-state-machine-fsm",children:"How do I create a finite state machine (FSM)?"}),"\n",(0,t.jsxs)(n.p,{children:["The advised way is to use ",(0,t.jsx)(n.code,{children:"ChiselEnum"})," to construct enumerated types representing the state of the FSM.\nState transitions are then handled with ",(0,t.jsx)(n.code,{children:"switch"}),"/",(0,t.jsx)(n.code,{children:"is"})," and ",(0,t.jsx)(n.code,{children:"when"}),"/",(0,t.jsx)(n.code,{children:".elsewhen"}),"/",(0,t.jsx)(n.code,{children:".otherwise"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.{switch, is}\n\nobject DetectTwoOnes {\n object State extends ChiselEnum {\n val sNone, sOne1, sTwo1s = Value\n }\n}\n\n/* This FSM detects two 1's one after the other */\nclass DetectTwoOnes extends Module {\n import DetectTwoOnes.State\n import DetectTwoOnes.State._\n\n val io = IO(new Bundle {\n val in = Input(Bool())\n val out = Output(Bool())\n val state = Output(State())\n })\n\n val state = RegInit(sNone)\n\n io.out := (state === sTwo1s)\n io.state := state\n\n switch (state) {\n is (sNone) {\n when (io.in) {\n state := sOne1\n }\n }\n is (sOne1) {\n when (io.in) {\n state := sTwo1s\n } .otherwise {\n state := sNone\n }\n }\n is (sTwo1s) {\n when (!io.in) {\n state := sNone\n }\n }\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note: the ",(0,t.jsx)(n.code,{children:"is"})," statement can take multiple conditions e.g. ",(0,t.jsx)(n.code,{children:"is (sTwo1s, sOne1) { ... }"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-unpack-a-value-reverse-concatenation-like-in-verilog",children:'How do I unpack a value ("reverse concatenation") like in Verilog?'}),"\n",(0,t.jsxs)(n.p,{children:["In Verilog, you can do something like the following which will unpack a the value ",(0,t.jsx)(n.code,{children:"z"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"wire [1:0] a;\nwire [3:0] b;\nwire [2:0] c;\nwire [8:0] z = [...];\nassign {a,b,c} = z;\n"})}),"\n",(0,t.jsx)(n.p,{children:"Unpacking often corresponds to reinterpreting an unstructured data type as a structured data type.\nFrequently, this structured type is used prolifically in the design, and has been declared as in the following example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyBundle extends Bundle {\n val a = UInt(2.W)\n val b = UInt(4.W)\n val c = UInt(3.W)\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"The easiest way to accomplish this in Chisel would be:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Foo extends Module {\n val z = Wire(UInt(9.W))\n z := DontCare // This is a dummy connection\n val unpacked = z.asTypeOf(new MyBundle)\n printf("%d", unpacked.a)\n printf("%d", unpacked.b)\n printf("%d", unpacked.c)\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["If you ",(0,t.jsx)(n.strong,{children:"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 ",(0,t.jsx)(n.a,{href:"https://github.com/freechipsproject/rocket-chip/blob/723af5e6b69e07b5f94c46269a208a8d65e9d73b/src/main/scala/util/Misc.scala#L140",children:"Split utility"})," which can accomplish this."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-do-subword-assignment-assign-to-some-bits-in-a-uint",children:"How do I do subword assignment (assign to some bits in a UInt)?"}),"\n",(0,t.jsxs)(n.p,{children:["You may try to do something like the following where you want to assign only some bits of a Chisel type.\nBelow, the left-hand side connection to ",(0,t.jsx)(n.code,{children:"io.out(0)"})," is not allowed."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass Foo extends Module {\n val io = IO(new Bundle {\n val bit = Input(Bool())\n val out = Output(UInt(10.W))\n })\n io.out(0) := io.bit\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"If you try to compile this, you will get an error."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"getVerilogString(new Foo)\n// chisel3.package$ChiselException: Cannot reassign to read-only Foo.?: OpResult[Bool]\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp26$Foo.(cookbook.md:583)\n// \tat repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:591)\n// \tat repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:591)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Chisel3 ",(0,t.jsx)(n.em,{children:"does not support subword assignment"}),".\nThe reason for this is that subword assignment generally hints at a better abstraction with an aggregate/structured types, i.e., a ",(0,t.jsx)(n.code,{children:"Bundle"})," or a ",(0,t.jsx)(n.code,{children:"Vec"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["If you must express it this way, one approach is to blast your ",(0,t.jsx)(n.code,{children:"UInt"})," to a ",(0,t.jsx)(n.code,{children:"Vec"})," of ",(0,t.jsx)(n.code,{children:"Bool"})," and back:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass Foo extends Module {\n val io = IO(new Bundle {\n val in = Input(UInt(10.W))\n val bit = Input(Bool())\n val out = Output(UInt(10.W))\n })\n val bools = VecInit(io.in.asBools)\n bools(0) := io.bit\n io.out := bools.asUInt\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-an-optional-io",children:"How do I create an optional I/O?"}),"\n",(0,t.jsxs)(n.p,{children:["The following example is a module which includes the optional port ",(0,t.jsx)(n.code,{children:"out2"})," only if the given parameter is ",(0,t.jsx)(n.code,{children:"true"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass ModuleWithOptionalIOs(flag: Boolean) extends Module {\n val io = IO(new Bundle {\n val in = Input(UInt(12.W))\n val out = Output(UInt(12.W))\n val out2 = if (flag) Some(Output(UInt(12.W))) else None\n })\n\n io.out := io.in\n if (flag) {\n io.out2.get := io.in\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The following is an example where an entire ",(0,t.jsx)(n.code,{children:"IO"})," is optional:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass ModuleWithOptionalIO(flag: Boolean) extends Module {\n val in = if (flag) Some(IO(Input(Bool()))) else None\n val out = IO(Output(Bool()))\n\n out := in.getOrElse(false.B)\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-io-without-a-prefix",children:"How do I create I/O without a prefix?"}),"\n",(0,t.jsxs)(n.p,{children:["In most cases, you can simply call ",(0,t.jsx)(n.code,{children:"IO"})," multiple times:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyModule extends Module {\n val in = IO(Input(UInt(8.W)))\n val out = IO(Output(UInt(8.W)))\n\n out := in +% 1.U\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule MyModule(\n input clock,\n reset,\n input [7:0] in,\n output [7:0] out\n);\n\n assign out = in + 8'h1;\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you have a ",(0,t.jsx)(n.code,{children:"Bundle"})," from which you would like to create ports without the\nnormal ",(0,t.jsx)(n.code,{children:"val"})," prefix, you can use ",(0,t.jsx)(n.code,{children:"FlatIO"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass MyBundle extends Bundle {\n val foo = Input(UInt(8.W))\n val bar = Output(UInt(8.W))\n}\n\nclass MyModule extends Module {\n val io = FlatIO(new MyBundle)\n\n io.bar := io.foo +% 1.U\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that ",(0,t.jsx)(n.code,{children:"io_"})," is nowhere to be seen!"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule MyModule(\n input clock,\n reset,\n input [7:0] foo,\n output [7:0] bar\n);\n\n assign bar = foo + 8'h1;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-override-the-implicit-clock-or-reset-within-a-module",children:"How do I override the implicit clock or reset within a Module?"}),"\n",(0,t.jsxs)(n.p,{children:["To change the clock or reset for a region of code, use ",(0,t.jsx)(n.code,{children:"withClock"}),", ",(0,t.jsx)(n.code,{children:"withReset"}),", or ",(0,t.jsx)(n.code,{children:"withClockAndReset"}),".\nSee ",(0,t.jsx)(n.a,{href:"../explanations/multi-clock",children:"Multiple Clock Domains"})," for examples and details."]}),"\n",(0,t.jsxs)(n.p,{children:["To override the clock or reset for the entire scope of the ",(0,t.jsx)(n.code,{children:"Module"}),", you can mixin the ",(0,t.jsx)(n.code,{children:"ImplicitClock"})," and ",(0,t.jsx)(n.code,{children:"ImplicitReset"})," traits."]}),"\n",(0,t.jsx)(n.p,{children:'For example, you could "gate" the default implicit clock as follows:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass MyModule extends Module with ImplicitClock {\n val gate = IO(Input(Bool()))\n val in = IO(Input(UInt(8.W)))\n val out = IO(Output(UInt(8.W)))\n // We could just assign this to val implicitClock, but this allows us to give it a custom name\n val gatedClock = (clock.asBool || gate).asClock\n // The trait requires us to implement this method referring to the clock\n // Note that this is a def, but the actual clock value must be assigned to a val\n override protected def implicitClock = gatedClock\n\n val r = Reg(UInt(8.W))\n out := r\n r := in\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"This gives the following Verilog:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule MyModule(\n input clock,\n reset,\n gate,\n input [7:0] in,\n output [7:0] out\n);\n\n wire gatedClock = clock | gate;\n reg [7:0] r;\n always @(posedge gatedClock)\n r <= in;\n assign out = r;\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you do not care about the name of the overriden clock, you can just assign it to ",(0,t.jsx)(n.code,{children:"val implicitClock"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"override protected val implicitClock = (clock.asBool || gate).asClock\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ImplicitReset"})," works analogously to ",(0,t.jsx)(n.code,{children:"ImplicitClock"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-minimize-the-number-of-bits-used-in-an-output-vector",children:"How do I minimize the number of bits used in an output vector?"}),"\n",(0,t.jsxs)(n.p,{children:["Use inferred width and a ",(0,t.jsx)(n.code,{children:"Seq"})," instead of a ",(0,t.jsx)(n.code,{children:"Vec"}),":"]}),"\n",(0,t.jsx)(n.p,{children:"Consider:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\n// Count the number of set bits up to and including each bit position\nclass CountBits(width: Int) extends Module {\n val bits = IO(Input(UInt(width.W)))\n val countVector = IO(Output(Vec(width, UInt())))\n\n private val countSequence = Seq.tabulate(width)(i => Wire(UInt()))\n countSequence.zipWithIndex.foreach { case (port, i) =>\n port := util.PopCount(bits(i, 0))\n }\n countVector := countSequence\n}\n\nclass Top(width: Int) extends Module {\n val countBits = Module(new CountBits(width))\n countBits.bits :<>= DontCare\n dontTouch(countBits.bits)\n dontTouch(countBits.countVector)\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Note that top modules or public modules cannot have unknown widths."}),"\n",(0,t.jsxs)(n.p,{children:["Unlike ",(0,t.jsx)(n.code,{children:"Vecs"})," which represent a singular Chisel type and must have the same width for every element,\n",(0,t.jsx)(n.code,{children:"Seq"})," is a purely Scala construct, so their elements are independent from the perspective of Chisel and can have different widths."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule CountBits(\n input [3:0] bits,\n output [2:0] countVector_0,\n countVector_1,\n countVector_2,\n countVector_3\n);\n"})}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-resolve-dynamic-index--is-too-widenarrow-for-extractee-",children:'How do I resolve "Dynamic index ... is too wide/narrow for extractee ..."?'}),"\n",(0,t.jsx)(n.p,{children:'Chisel will warn if a dynamic index is not the correctly-sized width for indexing a Vec or UInt.\n"Correctly-sized" means that the width of the index should be the log2 of the size of the indexee.\nIf the indexee is a non-power-of-2 size, use the ceiling of the log2 result.'}),"\n",(0,t.jsxs)(n.p,{children:["When the index does not have enough bits to address all entries or bits in the extractee, you can ",(0,t.jsx)(n.code,{children:".pad"})," the index to increase the width."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooNarrow extends RawModule {\n val extractee = Wire(UInt(7.W))\n val index = Wire(UInt(2.W))\n extractee(index)\n}\ncompile(new TooNarrow)\n// [warn] cookbook.md 816:12: [W003] Dynamic index with width 2 is too small for extractee of width 7\n// [warn] There were 1 warning(s) during hardware elaboration.\n"})}),"\n",(0,t.jsxs)(n.p,{children:["This can be fixed with ",(0,t.jsx)(n.code,{children:"pad"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooNarrowFixed extends RawModule {\n val extractee = Wire(UInt(7.W))\n val index = Wire(UInt(2.W))\n extractee(index.pad(3))\n}\ncompile(new TooNarrowFixed)\n"})}),"\n",(0,t.jsx)(n.h4,{id:"use-bit-extraction-when-the-index-is-too-wide",children:"Use bit extraction when the index is too wide"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooWide extends RawModule {\n val extractee = Wire(Vec(8, UInt(32.W)))\n val index = Wire(UInt(4.W))\n extractee(index)\n}\ncompile(new TooWide)\n// [warn] cookbook.md 842:12: [W004] Dynamic index with width 4 is too wide for Vec of size 8 (expected index width 3).\n// [warn] There were 1 warning(s) during hardware elaboration.\n"})}),"\n",(0,t.jsx)(n.p,{children:"This can be fixed with bit extraction:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooWideFixed extends RawModule {\n val extractee = Wire(Vec(8, UInt(32.W)))\n val index = Wire(UInt(4.W))\n extractee(index(2, 0))\n}\ncompile(new TooWideFixed)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that size 1 ",(0,t.jsx)(n.code,{children:"Vecs"})," and ",(0,t.jsx)(n.code,{children:"UInts"})," should be indexed by a zero-width ",(0,t.jsx)(n.code,{children:"UInt"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class SizeOneVec extends RawModule {\n val extractee = Wire(Vec(1, UInt(32.W)))\n val index = Wire(UInt(0.W))\n extractee(index)\n}\ncompile(new SizeOneVec)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Because ",(0,t.jsx)(n.code,{children:"pad"})," only pads if the desired width is less than the current width of the argument,\nyou can use ",(0,t.jsx)(n.code,{children:"pad"})," in conjunction with bit extraction when the widths may be too wide or too\nnarrow under different circumstances"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.log2Ceil\nclass TooWideOrNarrow(extracteeSize: Int, indexWidth: Int) extends Module {\n val extractee = Wire(Vec(extracteeSize, UInt(8.W)))\n val index = Wire(UInt(indexWidth.W))\n val correctWidth = log2Ceil(extracteeSize)\n extractee(index.pad(correctWidth)(correctWidth - 1, 0))\n}\ncompile(new TooWideOrNarrow(8, 2))\ncompile(new TooWideOrNarrow(8, 4))\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Another option for dynamic bit selection of ",(0,t.jsx)(n.code,{children:"UInts"})," (but not ",(0,t.jsx)(n.code,{children:"Vec"})," dynamic indexing) is to do a dynamic\nright shift of the extractee by the index and then just bit select a single bit:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TooWideOrNarrowUInt(extracteeSize: Int, indexWidth: Int) extends Module {\n val extractee = Wire(UInt(extracteeSize.W))\n val index = Wire(UInt(indexWidth.W))\n (extractee >> index)(0)\n}\ncompile(new TooWideOrNarrowUInt(8, 2))\ncompile(new TooWideOrNarrowUInt(8, 4))\n"})}),"\n",(0,t.jsx)(n.h2,{id:"predictable-naming",children:"Predictable Naming"}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-get-chisel-to-name-signals-properly-in-blocks-like-whenwithclockandreset",children:"How do I get Chisel to name signals properly in blocks like when/withClockAndReset?"}),"\n",(0,t.jsxs)(n.p,{children:["Use the compiler plugin, and check out the ",(0,t.jsx)(n.a,{href:"naming",children:"Naming Cookbook"})," if that still does not do what you want."]}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-get-chisel-to-name-the-results-of-vector-reads-properly",children:"How do I get Chisel to name the results of vector reads properly?"}),"\n",(0,t.jsx)(n.p,{children:"Currently, name information is lost when using dynamic indexing. For example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\n\nclass Foo extends Module {\n val io = IO(new Bundle {\n val in = Input(Vec(4, Bool()))\n val idx = Input(UInt(2.W))\n val en = Input(Bool())\n val out = Output(Bool())\n })\n\n val x = io.in(io.idx)\n val y = x && io.en\n io.out := y\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The above code loses the ",(0,t.jsx)(n.code,{children:"x"})," name, instead using ",(0,t.jsx)(n.code,{children:"_GEN_3"})," (the other ",(0,t.jsx)(n.code,{children:"_GEN_*"})," signals are expected)."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule Foo(\n input clock,\n reset,\n io_in_0,\n io_in_1,\n io_in_2,\n io_in_3,\n input [1:0] io_idx,\n input io_en,\n output io_out\n);\n\n wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}};\n assign io_out = _GEN[io_idx] & io_en;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"This can be worked around by creating a wire and connecting the dynamic index to the wire:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"val x = WireInit(io.in(io.idx))\n"})}),"\n",(0,t.jsx)(n.p,{children:"Which produces:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule Foo2(\n input clock,\n reset,\n io_in_0,\n io_in_1,\n io_in_2,\n io_in_3,\n input [1:0] io_idx,\n input io_en,\n output io_out\n);\n\n wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}};\n assign io_out = _GEN[io_idx] & io_en;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-can-i-dynamically-setparametrize-the-name-of-a-module",children:"How can I dynamically set/parametrize the name of a module?"}),"\n",(0,t.jsxs)(n.p,{children:["You can override the ",(0,t.jsx)(n.code,{children:"desiredName"})," function. This works with normal Chisel modules and ",(0,t.jsx)(n.code,{children:"BlackBox"}),"es. Example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'import chisel3._\n\nclass Coffee extends BlackBox {\n val io = IO(new Bundle {\n val I = Input(UInt(32.W))\n val O = Output(UInt(32.W))\n })\n override def desiredName = "Tea"\n}\n\nclass Salt extends Module {\n val io = IO(new Bundle {})\n val drink = Module(new Coffee)\n override def desiredName = "SodiumMonochloride"\n\n drink.io.I := 42.U\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Elaborating the Chisel module ",(0,t.jsx)(n.code,{children:"Salt"}),' yields our "desired names" for ',(0,t.jsx)(n.code,{children:"Salt"})," and ",(0,t.jsx)(n.code,{children:"Coffee"})," in the output Verilog:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule SodiumMonochloride(\n input clock,\n reset\n);\n\n Tea drink (\n .I (32'h2A),\n .O (/* unused */)\n );\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"directionality",children:"Directionality"}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-strip-directions-from-a-bidirectional-bundle-or-other-data",children:"How do I strip directions from a bidirectional Bundle (or other Data)?"}),"\n",(0,t.jsxs)(n.p,{children:["Given a bidirectional port like a ",(0,t.jsx)(n.code,{children:"Decoupled"}),", you will get an error if you try to connect it directly\nto a register:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.Decoupled\nclass BadRegConnect extends Module {\n val io = IO(new Bundle {\n val enq = Decoupled(UInt(8.W))\n })\n\n val monitor = Reg(chiselTypeOf(io.enq))\n monitor := io.enq\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"getVerilogString(new BadRegConnect)\n// circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: /home/runner/.cache/llvm-firtool/1.86.0/bin/firtool returned a non-zero exit code. Note that this version of Chisel (7.0.0-M2+116-15a25fff-SNAPSHOT) was published against firtool version 1.86.0.\n// ------------------------------------------------------------------------------\n// ExitCode:\n// 1\n// STDOUT:\n// \n// STDERR:\n// cookbook.md:1013:20: error: 'firrtl.reg' op result #0 must be a passive non-'const' base type that does not contain analog, but got '!firrtl.bundle, valid: uint<1>, bits: uint<8>>'\n// cookbook.md:1013:20: note: see current operation: %4 = \"firrtl.reg\"(%arg0) {annotations = [], name = \"monitor\", nameKind = #firrtl} : (!firrtl.clock) -> !firrtl.bundle, valid: uint<1>, bits: uint<8>>\n// \n// ------------------------------------------------------------------------------\n"})}),"\n",(0,t.jsxs)(n.p,{children:['While there is no construct to "strip direction" in Chisel3, wrapping a type in ',(0,t.jsx)(n.code,{children:"Output(...)"}),"\n(the default direction in Chisel3) will\nset all of the individual elements to output direction.\nThis will have the desired result when used to construct a Register:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.Decoupled\nclass CoercedRegConnect extends Module {\n val io = IO(new Bundle {\n val enq = Flipped(Decoupled(UInt(8.W)))\n })\n\n // Make a Reg which contains all of the bundle's signals, regardless of their directionality\n val monitor = Reg(Output(chiselTypeOf(io.enq)))\n // Even though io.enq is bidirectional, := will drive all fields of monitor with the fields of io.enq\n monitor := io.enq\n}\n"})})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1871:(e,n,a)=>{a.d(n,{A:()=>i});a(6540);var t=a(5195);const o={tableOfContentsInline:"tableOfContentsInline_prmo"};var l=a(4848);function i(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:i}=e;return(0,l.jsx)("div",{className:o.tableOfContentsInline,children:(0,l.jsx)(t.A,{toc:n,minHeadingLevel:a,maxHeadingLevel:i,className:"table-of-contents",linkClassName:null})})}},5195:(e,n,a)=>{a.d(n,{A:()=>g});var t=a(6540),o=a(6342);function l(e){const n=e.map((e=>({...e,parentIndex:-1,children:[]}))),a=Array(7).fill(-1);n.forEach(((e,n)=>{const t=a.slice(2,e.level);e.parentIndex=Math.max(...t),a[e.level]=n}));const t=[];return n.forEach((e=>{const{parentIndex:a,...o}=e;a>=0?n[a].children.push(o):t.push(o)})),t}function i(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:t}=e;return n.flatMap((e=>{const n=i({toc:e.children,minHeadingLevel:a,maxHeadingLevel:t});return function(e){return e.level>=a&&e.level<=t}(e)?[{...e,children:n}]:n}))}function s(e){const n=e.getBoundingClientRect();return n.top===n.bottom?s(e.parentNode):n}function c(e,n){let{anchorTopOffset:a}=n;const t=e.find((e=>s(e).top>=a));if(t){return function(e){return e.top>0&&e.bottom{e.current=n?0:document.querySelector(".navbar").clientHeight}),[n]),e}function d(e){const n=(0,t.useRef)(void 0),a=r();(0,t.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:t,linkActiveClassName:o,minHeadingLevel:l,maxHeadingLevel:i}=e;function s(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(t),s=function(e){let{minHeadingLevel:n,maxHeadingLevel:a}=e;const t=[];for(let o=n;o<=a;o+=1)t.push(`h${o}.anchor`);return Array.from(document.querySelectorAll(t.join()))}({minHeadingLevel:l,maxHeadingLevel:i}),r=c(s,{anchorTopOffset:a.current}),d=e.find((e=>r&&r.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,a){a?(n.current&&n.current!==e&&n.current.classList.remove(o),e.classList.add(o),n.current=e):e.classList.remove(o)}(e,e===d)}))}return document.addEventListener("scroll",s),document.addEventListener("resize",s),s(),()=>{document.removeEventListener("scroll",s),document.removeEventListener("resize",s)}}),[e,a])}var u=a(8774),h=a(4848);function p(e){let{toc:n,className:a,linkClassName:t,isChild:o}=e;return n.length?(0,h.jsx)("ul",{className:o?void 0:a,children:n.map((e=>(0,h.jsxs)("li",{children:[(0,h.jsx)(u.A,{to:`#${e.id}`,className:t??void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,h.jsx)(p,{isChild:!0,toc:e.children,className:a,linkClassName:t})]},e.id)))}):null}const m=t.memo(p);function g(e){let{toc:n,className:a="table-of-contents table-of-contents__left-border",linkClassName:s="table-of-contents__link",linkActiveClassName:c,minHeadingLevel:r,maxHeadingLevel:u,...p}=e;const g=(0,o.p)(),x=r??g.tableOfContents.minHeadingLevel,f=u??g.tableOfContents.maxHeadingLevel,w=function(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:o}=e;return(0,t.useMemo)((()=>i({toc:l(n),minHeadingLevel:a,maxHeadingLevel:o})),[n,a,o])}({toc:n,minHeadingLevel:x,maxHeadingLevel:f});return d((0,t.useMemo)((()=>{if(s&&c)return{linkClassName:s,linkActiveClassName:c,minHeadingLevel:x,maxHeadingLevel:f}}),[s,c,x,f])),(0,h.jsx)(m,{toc:w,className:a,linkClassName:s,...p})}},8453:(e,n,a)=>{a.d(n,{R:()=>i,x:()=>s});var t=a(6540);const o={},l=t.createContext(o);function i(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/868241d3.7cb166e1.js b/assets/js/868241d3.7cb166e1.js
deleted file mode 100644
index 38ac270e40..0000000000
--- a/assets/js/868241d3.7cb166e1.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[9017],{5268:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>d,frontMatter:()=>i,metadata:()=>a,toc:()=>r});var c=s(4848),t=s(8453);const i={},l=void 0,a={type:"mdx",permalink:"/generated/scaladoc_links",source:"@site/src/pages/generated/scaladoc_links.md",description:"- Latest (6.5.0)",frontMatter:{},unlisted:!1},o={},r=[];function h(e){const n={a:"a",li:"li",ul:"ul",...(0,t.R)(),...e.components};return(0,c.jsxs)(n.ul,{children:["\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.a,{href:"pathname:///api/latest/index.html",children:"Latest (6.5.0)"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.a,{href:"https://s01.oss.sonatype.org/service/local/repositories/snapshots/archive/org/chipsalliance/chisel_2.13/7.0.0-M2+115-fc4de1f3-SNAPSHOT/chisel_2.13-7.0.0-M2+115-fc4de1f3-SNAPSHOT-javadoc.jar/!/index.html",children:"Snapshot"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/7.0.0-M2",children:"7.0.0-M2"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/6.5.0",children:"6.5.0"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/5.3.0",children:"5.3.0"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.a,{href:"https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/3.6.1",children:"3.6.1"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.a,{href:"https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/3.5.6",children:"3.5.6"})}),"\n"]})}function d(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,c.jsx)(n,{...e,children:(0,c.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>a});var c=s(6540);const t={},i=c.createContext(t);function l(e){const n=c.useContext(i);return c.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),c.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/868241d3.95b3fb05.js b/assets/js/868241d3.95b3fb05.js
new file mode 100644
index 0000000000..d688c18106
--- /dev/null
+++ b/assets/js/868241d3.95b3fb05.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[9017],{5268:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>r});var t=s(4848),c=s(8453);const i={},a=void 0,l={type:"mdx",permalink:"/generated/scaladoc_links",source:"@site/src/pages/generated/scaladoc_links.md",description:"- Latest (6.5.0)",frontMatter:{},unlisted:!1},o={},r=[];function h(e){const n={a:"a",li:"li",ul:"ul",...(0,c.R)(),...e.components};return(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"pathname:///api/latest/index.html",children:"Latest (6.5.0)"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://s01.oss.sonatype.org/service/local/repositories/snapshots/archive/org/chipsalliance/chisel_2.13/7.0.0-M2+116-15a25fff-SNAPSHOT/chisel_2.13-7.0.0-M2+116-15a25fff-SNAPSHOT-javadoc.jar/!/index.html",children:"Snapshot"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/7.0.0-M2",children:"7.0.0-M2"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/6.5.0",children:"6.5.0"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/5.3.0",children:"5.3.0"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/3.6.1",children:"3.6.1"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/3.5.6",children:"3.5.6"})}),"\n"]})}function d(e={}){const{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>l});var t=s(6540);const c={},i=t.createContext(c);function a(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:a(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/98ca0ee0.311cb1f1.js b/assets/js/98ca0ee0.f3879cfd.js
similarity index 95%
rename from assets/js/98ca0ee0.311cb1f1.js
rename to assets/js/98ca0ee0.f3879cfd.js
index cf58a385e3..b5bc4cb1fe 100644
--- a/assets/js/98ca0ee0.311cb1f1.js
+++ b/assets/js/98ca0ee0.f3879cfd.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[8946,9017],{6734:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>p,frontMatter:()=>o,metadata:()=>r,toc:()=>d});var s=t(4848),i=t(8453),c=t(5268);const o={title:"API Docs"},a=void 0,r={type:"mdx",permalink:"/api",source:"@site/src/pages/api.md",title:"API Docs",description:"Chisel API Documentation",frontMatter:{title:"API Docs"},unlisted:!1},l={},d=[{value:"Chisel API Documentation",id:"chisel-api-documentation",level:2},...c.toc];function h(e){const n={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"chisel-api-documentation",children:"Chisel API Documentation"}),"\n",(0,s.jsxs)(n.p,{children:["Please see the page about ",(0,s.jsx)(n.a,{href:"docs/appendix/versioning",children:"Versioning"})," for more information about major and minor versioning and binary compatibility."]}),"\n",(0,s.jsx)(c.default,{})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},5268:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var s=t(4848),i=t(8453);const c={},o=void 0,a={type:"mdx",permalink:"/generated/scaladoc_links",source:"@site/src/pages/generated/scaladoc_links.md",description:"- Latest (6.5.0)",frontMatter:{},unlisted:!1},r={},l=[];function d(e){const n={a:"a",li:"li",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"pathname:///api/latest/index.html",children:"Latest (6.5.0)"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://s01.oss.sonatype.org/service/local/repositories/snapshots/archive/org/chipsalliance/chisel_2.13/7.0.0-M2+115-fc4de1f3-SNAPSHOT/chisel_2.13-7.0.0-M2+115-fc4de1f3-SNAPSHOT-javadoc.jar/!/index.html",children:"Snapshot"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/7.0.0-M2",children:"7.0.0-M2"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/6.5.0",children:"6.5.0"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/5.3.0",children:"5.3.0"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/3.6.1",children:"3.6.1"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/3.5.6",children:"3.5.6"})}),"\n"]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>a});var s=t(6540);const i={},c=s.createContext(i);function o(e){const n=s.useContext(c);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(c.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[8946,9017],{6734:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>p,frontMatter:()=>o,metadata:()=>r,toc:()=>d});var s=t(4848),i=t(8453),c=t(5268);const o={title:"API Docs"},a=void 0,r={type:"mdx",permalink:"/api",source:"@site/src/pages/api.md",title:"API Docs",description:"Chisel API Documentation",frontMatter:{title:"API Docs"},unlisted:!1},l={},d=[{value:"Chisel API Documentation",id:"chisel-api-documentation",level:2},...c.toc];function h(e){const n={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"chisel-api-documentation",children:"Chisel API Documentation"}),"\n",(0,s.jsxs)(n.p,{children:["Please see the page about ",(0,s.jsx)(n.a,{href:"docs/appendix/versioning",children:"Versioning"})," for more information about major and minor versioning and binary compatibility."]}),"\n",(0,s.jsx)(c.default,{})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},5268:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var s=t(4848),i=t(8453);const c={},o=void 0,a={type:"mdx",permalink:"/generated/scaladoc_links",source:"@site/src/pages/generated/scaladoc_links.md",description:"- Latest (6.5.0)",frontMatter:{},unlisted:!1},r={},l=[];function d(e){const n={a:"a",li:"li",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"pathname:///api/latest/index.html",children:"Latest (6.5.0)"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://s01.oss.sonatype.org/service/local/repositories/snapshots/archive/org/chipsalliance/chisel_2.13/7.0.0-M2+116-15a25fff-SNAPSHOT/chisel_2.13-7.0.0-M2+116-15a25fff-SNAPSHOT-javadoc.jar/!/index.html",children:"Snapshot"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/7.0.0-M2",children:"7.0.0-M2"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/6.5.0",children:"6.5.0"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/org.chipsalliance/chisel_2.13/5.3.0",children:"5.3.0"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/3.6.1",children:"3.6.1"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/3.5.6",children:"3.5.6"})}),"\n"]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>a});var s=t(6540);const i={},c=s.createContext(i);function o(e){const n=s.useContext(c);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(c.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/a26328e3.b3e82129.js b/assets/js/a26328e3.b89ff0c7.js
similarity index 99%
rename from assets/js/a26328e3.b3e82129.js
rename to assets/js/a26328e3.b89ff0c7.js
index 2d67d067c5..f18517cf56 100644
--- a/assets/js/a26328e3.b3e82129.js
+++ b/assets/js/a26328e3.b89ff0c7.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[3117],{8176:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>r});var t=a(4848),i=a(8453);const l={layout:"docs",title:"Interfaces and Connections",section:"chisel3"},s="Interfaces & Connections",o={id:"explanations/interfaces-and-connections",title:"Interfaces and Connections",description:"For more sophisticated modules it is often useful to define and instantiate interface classes while defining the IO for a module. First and foremost, interface classes promote reuse allowing users to capture once and for all common interfaces in a useful form.",source:"@site/docs/explanations/interfaces-and-connections.md",sourceDirName:"explanations",slug:"/explanations/interfaces-and-connections",permalink:"/docs/explanations/interfaces-and-connections",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/interfaces-and-connections.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Interfaces and Connections",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Instance Choices",permalink:"/docs/explanations/instchoice"},next:{title:"Intrinsics",permalink:"/docs/explanations/intrinsics"}},c={},r=[{value:"Ports: Subclasses & Nesting",id:"ports-subclasses--nesting",level:2},{value:"Bundle Vectors",id:"bundle-vectors",level:2},{value:"Bulk Connections",id:"bulk-connections",level:2},{value:"MonoConnect Algorithm",id:"monoconnect-algorithm",level:3},{value:"BiConnect Algorithm",id:"biconnect-algorithm",level:3},{value:"The standard ready-valid interface (ReadyValidIO / Decoupled)",id:"the-standard-ready-valid-interface-readyvalidio--decoupled",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"interfaces--connections",children:"Interfaces & Connections"})}),"\n",(0,t.jsx)(n.p,{children:"For more sophisticated modules it is often useful to define and instantiate interface classes while defining the IO for a module. First and foremost, interface classes promote reuse allowing users to capture once and for all common interfaces in a useful form."}),"\n",(0,t.jsx)(n.p,{children:"Secondly, interfaces allow users to dramatically reduce wiring by supporting bulk connections between producer and consumer modules. Finally, users can make changes in large interfaces in one place reducing the number of updates required when adding or removing pieces of the interface."}),"\n",(0,t.jsx)(n.p,{children:"Note that Chisel has some built-in standard interface which should be used whenever possible for interoperability (e.g. Decoupled)."}),"\n",(0,t.jsx)(n.h2,{id:"ports-subclasses--nesting",children:"Ports: Subclasses & Nesting"}),"\n",(0,t.jsx)(n.p,{children:"As we saw earlier, users can define their own interfaces by defining a class that subclasses Bundle. For example, a user could define a simple link for hand-shaking data as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class SimpleLink extends Bundle {\n val data = Output(UInt(16.W))\n val valid = Output(Bool())\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"We can then extend SimpleLink by adding parity bits using bundle inheritance:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class PLink extends SimpleLink {\n val parity = Output(UInt(5.W))\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"In general, users can organize their interfaces into hierarchies using inheritance."}),"\n",(0,t.jsx)(n.p,{children:"From there we can define a filter interface by nesting two PLinks into a new FilterIO bundle:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class FilterIO extends Bundle {\n val x = Flipped(new PLink)\n val y = new PLink\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"where flip recursively changes the direction of a bundle, changing input to output and output to input."}),"\n",(0,t.jsx)(n.p,{children:"We can now define a filter by defining a filter class extending module:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class Filter extends Module {\n val io = IO(new FilterIO)\n // ...\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"where the io field contains FilterIO."}),"\n",(0,t.jsx)(n.h2,{id:"bundle-vectors",children:"Bundle Vectors"}),"\n",(0,t.jsx)(n.p,{children:"Beyond single elements, vectors of elements form richer hierarchical interfaces. For example, in order to create a crossbar with a vector of inputs, producing a vector of outputs, and selected by a UInt input, we utilize the Vec constructor:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.log2Ceil\nclass CrossbarIo(n: Int) extends Bundle {\n val in = Vec(n, Flipped(new PLink))\n val sel = Input(UInt(log2Ceil(n).W))\n val out = Vec(n, new PLink)\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"where Vec takes a size as the first argument and a block returning a port as the second argument."}),"\n",(0,t.jsx)(n.h2,{id:"bulk-connections",children:"Bulk Connections"}),"\n",(0,t.jsxs)(n.p,{children:["Once we have a defined Interface, we can connect to it via a ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Data.html#:=",children:(0,t.jsx)(n.code,{children:"MonoConnect"})})," operator (",(0,t.jsx)(n.code,{children:":="}),") or ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Data.html#%3C%3E",children:(0,t.jsx)(n.code,{children:"BiConnect"})})," operator (",(0,t.jsx)(n.code,{children:"<>"}),")."]}),"\n",(0,t.jsxs)(n.h3,{id:"monoconnect-algorithm",children:[(0,t.jsx)(n.code,{children:"MonoConnect"})," Algorithm"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"MonoConnect.connect"}),", or ",(0,t.jsx)(n.code,{children:":="}),", executes a mono-directional connection element-wise."]}),"\n",(0,t.jsx)(n.p,{children:"Note that this isn't commutative. There is an explicit source and sink\nalready determined before this function is called."}),"\n",(0,t.jsx)(n.p,{children:"The connect operation will recurse down the left Data (with the right Data).\nAn exception will be thrown if a movement through the left cannot be matched\nin the right. The right side is allowed to have extra fields.\nVecs must still be exactly the same size."}),"\n",(0,t.jsx)(n.p,{children:"Note that the LHS element must be writable so, one of these must hold:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Is an internal writable node (",(0,t.jsx)(n.code,{children:"Reg"})," or ",(0,t.jsx)(n.code,{children:"Wire"}),")"]}),"\n",(0,t.jsx)(n.li,{children:"Is an output of the current module"}),"\n",(0,t.jsx)(n.li,{children:"Is an input of a submodule of the current module"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Note that the RHS element must be readable so, one of these must hold:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Is an internal readable node (",(0,t.jsx)(n.code,{children:"Reg"}),", ",(0,t.jsx)(n.code,{children:"Wire"}),", ",(0,t.jsx)(n.code,{children:"Op"}),")"]}),"\n",(0,t.jsx)(n.li,{children:"Is a literal"}),"\n",(0,t.jsx)(n.li,{children:"Is a port of the current module or submodule of the current module"}),"\n"]}),"\n",(0,t.jsxs)(n.h3,{id:"biconnect-algorithm",children:[(0,t.jsx)(n.code,{children:"BiConnect"})," Algorithm"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"BiConnect.connect"}),", or ",(0,t.jsx)(n.code,{children:"<>"}),", executes a bidirectional connection element-wise. Note that the arguments are left and right (not source and sink) so the intent is for the operation to be commutative. The connect operation will recurse down the left ",(0,t.jsx)(n.code,{children:"Data"})," (with the right ",(0,t.jsx)(n.code,{children:"Data"}),"). An exception will be thrown if a movement through the left cannot be matched in the right, or if the right side has extra fields."]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["Note: We highly encourage new code to be written with the ",(0,t.jsxs)(n.a,{href:"https://www.chisel-lang.org/chisel3/docs/explanations/connectable.html",children:[(0,t.jsx)(n.code,{children:"Connectable"})," Operators"]})," rather than the ",(0,t.jsx)(n.code,{children:"<>"})," operator."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Using the biconnect ",(0,t.jsx)(n.code,{children:"<>"})," operator, we can now compose two filters into a filter block as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class Block extends Module {\n val io = IO(new FilterIO)\n val f1 = Module(new Filter)\n val f2 = Module(new Filter)\n f1.io.x <> io.x\n f1.io.y <> f2.io.x\n f2.io.y <> io.y\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The bidirectional bulk connection operator ",(0,t.jsx)(n.code,{children:"<>"})," connects leaf ports of the same name to each other. The Scala types of the Bundles are not required to match. If one named signal is missing from either side, Chisel will give an error such as in the following example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"\nclass NotReallyAFilterIO extends Bundle {\n val x = Flipped(new PLink)\n val y = new PLink\n val z = Output(new Bool())\n}\nclass Block2 extends Module {\n val io1 = IO(new FilterIO)\n val io2 = IO(Flipped(new NotReallyAFilterIO))\n\n io1 <> io2\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Below we can see the resulting error for this example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"emitSystemVerilog(new Block2)\n// chisel3.package$ChiselException: Connection between left (Block2.io1: IO[FilterIO]) and source (Block2.io2: IO[NotReallyAFilterIO]) failed @.z: Left Record missing field (z).\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$Block2.(interfaces-and-connections.md:89)\n// \tat repl.MdocSession$MdocApp$$anonfun$22$$anonfun$apply$20.apply(interfaces-and-connections.md:97)\n// \tat repl.MdocSession$MdocApp$$anonfun$22$$anonfun$apply$20.apply(interfaces-and-connections.md:97)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Bidirectional connections should only be used with ",(0,t.jsx)(n.strong,{children:"directioned elements"})," (like IOs), e.g. connecting two wires isn't supported since Chisel can't necessarily figure out the directions automatically.\nFor example, putting two temporary wires and connecting them here will not work, even though the directions could be known from the endpoints:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"\nclass BlockWithTemporaryWires extends Module {\n val io = IO(new FilterIO)\n val f1 = Module(new Filter)\n val f2 = Module(new Filter)\n f1.io.x <> io.x\n val tmp1 = Wire(new FilterIO)\n val tmp2 = Wire(new FilterIO)\n f1.io.y <> tmp1\n tmp1 <> tmp2\n tmp2 <> f2.io.x\n f2.io.y <> io.y\n}\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"Below we can see the resulting error for this example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"emitSystemVerilog(new BlockWithTemporaryWires)\n// chisel3.package$ChiselException: Connection between left (Filter.io.y: IO[PLink]) and source (BlockWithTemporaryWires.tmp1: Wire[FilterIO]) failed @.y: Left Record missing field (y).\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$BlockWithTemporaryWires.(interfaces-and-connections.md:113)\n// \tat repl.MdocSession$MdocApp$$anonfun$33$$anonfun$apply$29.apply(interfaces-and-connections.md:124)\n// \tat repl.MdocSession$MdocApp$$anonfun$33$$anonfun$apply$29.apply(interfaces-and-connections.md:124)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["For more details and information, see ",(0,t.jsx)(n.a,{href:"connection-operators",children:"Deep Dive into Connection Operators"})]}),"\n",(0,t.jsxs)(n.p,{children:["NOTE: When using ",(0,t.jsx)(n.code,{children:"Chisel._"})," (compatibility mode) instead of ",(0,t.jsx)(n.code,{children:"chisel3._"}),", the ",(0,t.jsx)(n.code,{children:":="})," operator works in a bidirectional fashion similar to ",(0,t.jsx)(n.code,{children:"<>"}),", but not exactly the same."]}),"\n",(0,t.jsx)(n.h2,{id:"the-standard-ready-valid-interface-readyvalidio--decoupled",children:"The standard ready-valid interface (ReadyValidIO / Decoupled)"}),"\n",(0,t.jsxs)(n.p,{children:["Chisel provides a standard interface for ",(0,t.jsx)(n.a,{href:"http://inst.eecs.berkeley.edu/~cs150/Documents/Interfaces.pdf",children:"ready-valid interfaces"}),".\nA ready-valid interface consists of a ",(0,t.jsx)(n.code,{children:"ready"})," signal, a ",(0,t.jsx)(n.code,{children:"valid"})," signal, and some data stored in ",(0,t.jsx)(n.code,{children:"bits"}),".\nThe ",(0,t.jsx)(n.code,{children:"ready"})," bit indicates that a consumer is ",(0,t.jsx)(n.em,{children:"ready"})," to consume data.\nThe ",(0,t.jsx)(n.code,{children:"valid"})," bit indicates that a producer has ",(0,t.jsx)(n.em,{children:"valid"})," data on ",(0,t.jsx)(n.code,{children:"bits"}),".\nWhen both ",(0,t.jsx)(n.code,{children:"ready"})," and ",(0,t.jsx)(n.code,{children:"valid"})," are asserted, a data transfer from the producer to the consumer takes place.\nA convenience method ",(0,t.jsx)(n.code,{children:"fire"})," is provided that is asserted if both ",(0,t.jsx)(n.code,{children:"ready"})," and ",(0,t.jsx)(n.code,{children:"valid"})," are asserted."]}),"\n",(0,t.jsxs)(n.p,{children:["Usually, we use the utility function ",(0,t.jsx)(n.a,{href:"https://chisel.eecs.berkeley.edu/api/latest/chisel3/util/Decoupled$.html",children:(0,t.jsx)(n.code,{children:"Decoupled()"})})," to turn any type into a ready-valid interface rather than directly using ",(0,t.jsx)(n.a,{href:"http://chisel.eecs.berkeley.edu/api/latest/chisel3/util/ReadyValidIO.html",children:"ReadyValidIO"}),"."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Decoupled(...)"})," creates a producer / output ready-valid interface (i.e. bits is an output)."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Flipped(Decoupled(...))"})," creates a consumer / input ready-valid interface (i.e. bits is an input)."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Take a look at the following example Chisel code to better understand exactly what is generated:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.Decoupled\n\n/**\n * Using Decoupled(...) creates a producer interface.\n * i.e. it has bits as an output.\n * This produces the following ports:\n * input io_readyValid_ready,\n * output io_readyValid_valid,\n * output [31:0] io_readyValid_bits\n */\nclass ProducingData extends Module {\n val io = IO(new Bundle {\n val readyValid = Decoupled(UInt(32.W))\n })\n // do something with io.readyValid.ready\n io.readyValid.valid := true.B\n io.readyValid.bits := 5.U\n}\n\n/**\n * Using Flipped(Decoupled(...)) creates a consumer interface.\n * i.e. it has bits as an input.\n * This produces the following ports:\n * output io_readyValid_ready,\n * input io_readyValid_valid,\n * input [31:0] io_readyValid_bits\n */\nclass ConsumingData extends Module {\n val io = IO(new Bundle {\n val readyValid = Flipped(Decoupled(UInt(32.W)))\n })\n io.readyValid.ready := false.B\n // do something with io.readyValid.valid\n // do something with io.readyValid.bits\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"DecoupledIO"})," is a ready-valid interface with the ",(0,t.jsx)(n.em,{children:"convention"})," that there are no guarantees placed on deasserting ",(0,t.jsx)(n.code,{children:"ready"})," or ",(0,t.jsx)(n.code,{children:"valid"})," or on the stability of ",(0,t.jsx)(n.code,{children:"bits"}),".\nThat means ",(0,t.jsx)(n.code,{children:"ready"})," and ",(0,t.jsx)(n.code,{children:"valid"})," can also be deasserted without a data transfer."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"IrrevocableIO"})," is a ready-valid interface with the ",(0,t.jsx)(n.em,{children:"convention"})," that the value of ",(0,t.jsx)(n.code,{children:"bits"})," will not change while ",(0,t.jsx)(n.code,{children:"valid"})," is asserted and ",(0,t.jsx)(n.code,{children:"ready"})," is deasserted.\nAlso, the consumer shall keep ",(0,t.jsx)(n.code,{children:"ready"})," asserted after a cycle where ",(0,t.jsx)(n.code,{children:"ready"})," was high and ",(0,t.jsx)(n.code,{children:"valid"})," was low.\nNote that the ",(0,t.jsx)(n.em,{children:"irrevocable"})," constraint ",(0,t.jsx)(n.em,{children:"is only a convention"})," and cannot be enforced by the interface.\nChisel does not automatically generate checkers or assertions to enforce the ",(0,t.jsx)(n.em,{children:"irrevocable"})," convention."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>s,x:()=>o});var t=a(6540);const i={},l=t.createContext(i);function s(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[3117],{8176:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>r});var t=a(4848),i=a(8453);const l={layout:"docs",title:"Interfaces and Connections",section:"chisel3"},s="Interfaces & Connections",o={id:"explanations/interfaces-and-connections",title:"Interfaces and Connections",description:"For more sophisticated modules it is often useful to define and instantiate interface classes while defining the IO for a module. First and foremost, interface classes promote reuse allowing users to capture once and for all common interfaces in a useful form.",source:"@site/docs/explanations/interfaces-and-connections.md",sourceDirName:"explanations",slug:"/explanations/interfaces-and-connections",permalink:"/docs/explanations/interfaces-and-connections",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/interfaces-and-connections.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Interfaces and Connections",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Instance Choices",permalink:"/docs/explanations/instchoice"},next:{title:"Intrinsics",permalink:"/docs/explanations/intrinsics"}},c={},r=[{value:"Ports: Subclasses & Nesting",id:"ports-subclasses--nesting",level:2},{value:"Bundle Vectors",id:"bundle-vectors",level:2},{value:"Bulk Connections",id:"bulk-connections",level:2},{value:"MonoConnect Algorithm",id:"monoconnect-algorithm",level:3},{value:"BiConnect Algorithm",id:"biconnect-algorithm",level:3},{value:"The standard ready-valid interface (ReadyValidIO / Decoupled)",id:"the-standard-ready-valid-interface-readyvalidio--decoupled",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"interfaces--connections",children:"Interfaces & Connections"})}),"\n",(0,t.jsx)(n.p,{children:"For more sophisticated modules it is often useful to define and instantiate interface classes while defining the IO for a module. First and foremost, interface classes promote reuse allowing users to capture once and for all common interfaces in a useful form."}),"\n",(0,t.jsx)(n.p,{children:"Secondly, interfaces allow users to dramatically reduce wiring by supporting bulk connections between producer and consumer modules. Finally, users can make changes in large interfaces in one place reducing the number of updates required when adding or removing pieces of the interface."}),"\n",(0,t.jsx)(n.p,{children:"Note that Chisel has some built-in standard interface which should be used whenever possible for interoperability (e.g. Decoupled)."}),"\n",(0,t.jsx)(n.h2,{id:"ports-subclasses--nesting",children:"Ports: Subclasses & Nesting"}),"\n",(0,t.jsx)(n.p,{children:"As we saw earlier, users can define their own interfaces by defining a class that subclasses Bundle. For example, a user could define a simple link for hand-shaking data as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class SimpleLink extends Bundle {\n val data = Output(UInt(16.W))\n val valid = Output(Bool())\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"We can then extend SimpleLink by adding parity bits using bundle inheritance:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class PLink extends SimpleLink {\n val parity = Output(UInt(5.W))\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"In general, users can organize their interfaces into hierarchies using inheritance."}),"\n",(0,t.jsx)(n.p,{children:"From there we can define a filter interface by nesting two PLinks into a new FilterIO bundle:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class FilterIO extends Bundle {\n val x = Flipped(new PLink)\n val y = new PLink\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"where flip recursively changes the direction of a bundle, changing input to output and output to input."}),"\n",(0,t.jsx)(n.p,{children:"We can now define a filter by defining a filter class extending module:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class Filter extends Module {\n val io = IO(new FilterIO)\n // ...\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"where the io field contains FilterIO."}),"\n",(0,t.jsx)(n.h2,{id:"bundle-vectors",children:"Bundle Vectors"}),"\n",(0,t.jsx)(n.p,{children:"Beyond single elements, vectors of elements form richer hierarchical interfaces. For example, in order to create a crossbar with a vector of inputs, producing a vector of outputs, and selected by a UInt input, we utilize the Vec constructor:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.log2Ceil\nclass CrossbarIo(n: Int) extends Bundle {\n val in = Vec(n, Flipped(new PLink))\n val sel = Input(UInt(log2Ceil(n).W))\n val out = Vec(n, new PLink)\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"where Vec takes a size as the first argument and a block returning a port as the second argument."}),"\n",(0,t.jsx)(n.h2,{id:"bulk-connections",children:"Bulk Connections"}),"\n",(0,t.jsxs)(n.p,{children:["Once we have a defined Interface, we can connect to it via a ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Data.html#:=",children:(0,t.jsx)(n.code,{children:"MonoConnect"})})," operator (",(0,t.jsx)(n.code,{children:":="}),") or ",(0,t.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Data.html#%3C%3E",children:(0,t.jsx)(n.code,{children:"BiConnect"})})," operator (",(0,t.jsx)(n.code,{children:"<>"}),")."]}),"\n",(0,t.jsxs)(n.h3,{id:"monoconnect-algorithm",children:[(0,t.jsx)(n.code,{children:"MonoConnect"})," Algorithm"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"MonoConnect.connect"}),", or ",(0,t.jsx)(n.code,{children:":="}),", executes a mono-directional connection element-wise."]}),"\n",(0,t.jsx)(n.p,{children:"Note that this isn't commutative. There is an explicit source and sink\nalready determined before this function is called."}),"\n",(0,t.jsx)(n.p,{children:"The connect operation will recurse down the left Data (with the right Data).\nAn exception will be thrown if a movement through the left cannot be matched\nin the right. The right side is allowed to have extra fields.\nVecs must still be exactly the same size."}),"\n",(0,t.jsx)(n.p,{children:"Note that the LHS element must be writable so, one of these must hold:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Is an internal writable node (",(0,t.jsx)(n.code,{children:"Reg"})," or ",(0,t.jsx)(n.code,{children:"Wire"}),")"]}),"\n",(0,t.jsx)(n.li,{children:"Is an output of the current module"}),"\n",(0,t.jsx)(n.li,{children:"Is an input of a submodule of the current module"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Note that the RHS element must be readable so, one of these must hold:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Is an internal readable node (",(0,t.jsx)(n.code,{children:"Reg"}),", ",(0,t.jsx)(n.code,{children:"Wire"}),", ",(0,t.jsx)(n.code,{children:"Op"}),")"]}),"\n",(0,t.jsx)(n.li,{children:"Is a literal"}),"\n",(0,t.jsx)(n.li,{children:"Is a port of the current module or submodule of the current module"}),"\n"]}),"\n",(0,t.jsxs)(n.h3,{id:"biconnect-algorithm",children:[(0,t.jsx)(n.code,{children:"BiConnect"})," Algorithm"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"BiConnect.connect"}),", or ",(0,t.jsx)(n.code,{children:"<>"}),", executes a bidirectional connection element-wise. Note that the arguments are left and right (not source and sink) so the intent is for the operation to be commutative. The connect operation will recurse down the left ",(0,t.jsx)(n.code,{children:"Data"})," (with the right ",(0,t.jsx)(n.code,{children:"Data"}),"). An exception will be thrown if a movement through the left cannot be matched in the right, or if the right side has extra fields."]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["Note: We highly encourage new code to be written with the ",(0,t.jsxs)(n.a,{href:"https://www.chisel-lang.org/chisel3/docs/explanations/connectable.html",children:[(0,t.jsx)(n.code,{children:"Connectable"})," Operators"]})," rather than the ",(0,t.jsx)(n.code,{children:"<>"})," operator."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Using the biconnect ",(0,t.jsx)(n.code,{children:"<>"})," operator, we can now compose two filters into a filter block as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class Block extends Module {\n val io = IO(new FilterIO)\n val f1 = Module(new Filter)\n val f2 = Module(new Filter)\n f1.io.x <> io.x\n f1.io.y <> f2.io.x\n f2.io.y <> io.y\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The bidirectional bulk connection operator ",(0,t.jsx)(n.code,{children:"<>"})," connects leaf ports of the same name to each other. The Scala types of the Bundles are not required to match. If one named signal is missing from either side, Chisel will give an error such as in the following example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"\nclass NotReallyAFilterIO extends Bundle {\n val x = Flipped(new PLink)\n val y = new PLink\n val z = Output(new Bool())\n}\nclass Block2 extends Module {\n val io1 = IO(new FilterIO)\n val io2 = IO(Flipped(new NotReallyAFilterIO))\n\n io1 <> io2\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Below we can see the resulting error for this example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"emitSystemVerilog(new Block2)\n// chisel3.package$ChiselException: Connection between left (Block2.io1: IO[FilterIO]) and source (Block2.io2: IO[NotReallyAFilterIO]) failed @.z: Left Record missing field (z).\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$Block2.(interfaces-and-connections.md:89)\n// \tat repl.MdocSession$MdocApp$$anonfun$22$$anonfun$apply$20.apply(interfaces-and-connections.md:97)\n// \tat repl.MdocSession$MdocApp$$anonfun$22$$anonfun$apply$20.apply(interfaces-and-connections.md:97)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Bidirectional connections should only be used with ",(0,t.jsx)(n.strong,{children:"directioned elements"})," (like IOs), e.g. connecting two wires isn't supported since Chisel can't necessarily figure out the directions automatically.\nFor example, putting two temporary wires and connecting them here will not work, even though the directions could be known from the endpoints:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"\nclass BlockWithTemporaryWires extends Module {\n val io = IO(new FilterIO)\n val f1 = Module(new Filter)\n val f2 = Module(new Filter)\n f1.io.x <> io.x\n val tmp1 = Wire(new FilterIO)\n val tmp2 = Wire(new FilterIO)\n f1.io.y <> tmp1\n tmp1 <> tmp2\n tmp2 <> f2.io.x\n f2.io.y <> io.y\n}\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"Below we can see the resulting error for this example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"emitSystemVerilog(new BlockWithTemporaryWires)\n// chisel3.package$ChiselException: Connection between left (Filter.io.y: IO[PLink]) and source (BlockWithTemporaryWires.tmp1: Wire[FilterIO]) failed @.y: Left Record missing field (y).\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp$BlockWithTemporaryWires.(interfaces-and-connections.md:113)\n// \tat repl.MdocSession$MdocApp$$anonfun$33$$anonfun$apply$29.apply(interfaces-and-connections.md:124)\n// \tat repl.MdocSession$MdocApp$$anonfun$33$$anonfun$apply$29.apply(interfaces-and-connections.md:124)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["For more details and information, see ",(0,t.jsx)(n.a,{href:"connection-operators",children:"Deep Dive into Connection Operators"})]}),"\n",(0,t.jsxs)(n.p,{children:["NOTE: When using ",(0,t.jsx)(n.code,{children:"Chisel._"})," (compatibility mode) instead of ",(0,t.jsx)(n.code,{children:"chisel3._"}),", the ",(0,t.jsx)(n.code,{children:":="})," operator works in a bidirectional fashion similar to ",(0,t.jsx)(n.code,{children:"<>"}),", but not exactly the same."]}),"\n",(0,t.jsx)(n.h2,{id:"the-standard-ready-valid-interface-readyvalidio--decoupled",children:"The standard ready-valid interface (ReadyValidIO / Decoupled)"}),"\n",(0,t.jsxs)(n.p,{children:["Chisel provides a standard interface for ",(0,t.jsx)(n.a,{href:"http://inst.eecs.berkeley.edu/~cs150/Documents/Interfaces.pdf",children:"ready-valid interfaces"}),".\nA ready-valid interface consists of a ",(0,t.jsx)(n.code,{children:"ready"})," signal, a ",(0,t.jsx)(n.code,{children:"valid"})," signal, and some data stored in ",(0,t.jsx)(n.code,{children:"bits"}),".\nThe ",(0,t.jsx)(n.code,{children:"ready"})," bit indicates that a consumer is ",(0,t.jsx)(n.em,{children:"ready"})," to consume data.\nThe ",(0,t.jsx)(n.code,{children:"valid"})," bit indicates that a producer has ",(0,t.jsx)(n.em,{children:"valid"})," data on ",(0,t.jsx)(n.code,{children:"bits"}),".\nWhen both ",(0,t.jsx)(n.code,{children:"ready"})," and ",(0,t.jsx)(n.code,{children:"valid"})," are asserted, a data transfer from the producer to the consumer takes place.\nA convenience method ",(0,t.jsx)(n.code,{children:"fire"})," is provided that is asserted if both ",(0,t.jsx)(n.code,{children:"ready"})," and ",(0,t.jsx)(n.code,{children:"valid"})," are asserted."]}),"\n",(0,t.jsxs)(n.p,{children:["Usually, we use the utility function ",(0,t.jsx)(n.a,{href:"https://chisel.eecs.berkeley.edu/api/latest/chisel3/util/Decoupled$.html",children:(0,t.jsx)(n.code,{children:"Decoupled()"})})," to turn any type into a ready-valid interface rather than directly using ",(0,t.jsx)(n.a,{href:"http://chisel.eecs.berkeley.edu/api/latest/chisel3/util/ReadyValidIO.html",children:"ReadyValidIO"}),"."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Decoupled(...)"})," creates a producer / output ready-valid interface (i.e. bits is an output)."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Flipped(Decoupled(...))"})," creates a consumer / input ready-valid interface (i.e. bits is an input)."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Take a look at the following example Chisel code to better understand exactly what is generated:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.Decoupled\n\n/**\n * Using Decoupled(...) creates a producer interface.\n * i.e. it has bits as an output.\n * This produces the following ports:\n * input io_readyValid_ready,\n * output io_readyValid_valid,\n * output [31:0] io_readyValid_bits\n */\nclass ProducingData extends Module {\n val io = IO(new Bundle {\n val readyValid = Decoupled(UInt(32.W))\n })\n // do something with io.readyValid.ready\n io.readyValid.valid := true.B\n io.readyValid.bits := 5.U\n}\n\n/**\n * Using Flipped(Decoupled(...)) creates a consumer interface.\n * i.e. it has bits as an input.\n * This produces the following ports:\n * output io_readyValid_ready,\n * input io_readyValid_valid,\n * input [31:0] io_readyValid_bits\n */\nclass ConsumingData extends Module {\n val io = IO(new Bundle {\n val readyValid = Flipped(Decoupled(UInt(32.W)))\n })\n io.readyValid.ready := false.B\n // do something with io.readyValid.valid\n // do something with io.readyValid.bits\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"DecoupledIO"})," is a ready-valid interface with the ",(0,t.jsx)(n.em,{children:"convention"})," that there are no guarantees placed on deasserting ",(0,t.jsx)(n.code,{children:"ready"})," or ",(0,t.jsx)(n.code,{children:"valid"})," or on the stability of ",(0,t.jsx)(n.code,{children:"bits"}),".\nThat means ",(0,t.jsx)(n.code,{children:"ready"})," and ",(0,t.jsx)(n.code,{children:"valid"})," can also be deasserted without a data transfer."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"IrrevocableIO"})," is a ready-valid interface with the ",(0,t.jsx)(n.em,{children:"convention"})," that the value of ",(0,t.jsx)(n.code,{children:"bits"})," will not change while ",(0,t.jsx)(n.code,{children:"valid"})," is asserted and ",(0,t.jsx)(n.code,{children:"ready"})," is deasserted.\nAlso, the consumer shall keep ",(0,t.jsx)(n.code,{children:"ready"})," asserted after a cycle where ",(0,t.jsx)(n.code,{children:"ready"})," was high and ",(0,t.jsx)(n.code,{children:"valid"})," was low.\nNote that the ",(0,t.jsx)(n.em,{children:"irrevocable"})," constraint ",(0,t.jsx)(n.em,{children:"is only a convention"})," and cannot be enforced by the interface.\nChisel does not automatically generate checkers or assertions to enforce the ",(0,t.jsx)(n.em,{children:"irrevocable"})," convention."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>s,x:()=>o});var t=a(6540);const i={},l=t.createContext(i);function s(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d1e6e3d8.9fd43a9d.js b/assets/js/d1e6e3d8.f86086db.js
similarity index 99%
rename from assets/js/d1e6e3d8.9fd43a9d.js
rename to assets/js/d1e6e3d8.f86086db.js
index f9e23703d0..395f178648 100644
--- a/assets/js/d1e6e3d8.9fd43a9d.js
+++ b/assets/js/d1e6e3d8.f86086db.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[4863],{7396:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>p,frontMatter:()=>t,metadata:()=>s,toc:()=>d});var o=i(4848),a=i(8453);const t={layout:"docs",title:"Deep Dive into <> and := Connection Operators",section:"chisel3"},l="Deep Dive into Connection Operators",s={id:"explanations/connection-operators",title:"Deep Dive into <> and := Connection Operators",description:"Chisel contains two connection operators, := and `. This document provides a deeper explanation of the differences of the two and when to use one or the other. The differences are demonstrated with experiments using Scastie examples which use DecoupledIO`.",source:"@site/docs/explanations/connection-operators.md",sourceDirName:"explanations",slug:"/explanations/connection-operators",permalink:"/docs/explanations/connection-operators",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/connection-operators.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Deep Dive into <> and := Connection Operators",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Connectable Operators",permalink:"/docs/explanations/connectable"},next:{title:"Chisel Data Types",permalink:"/docs/explanations/data-types"}},c={},d=[{value:"Experiment Setup",id:"experiment-setup",level:3},{value:"Concept 1: <> is Commutative",id:"concept-1--is-commutative",level:2},{value:"Conclusion:",id:"conclusion",level:3},{value:"Concept 2: := means assign ALL LHS signals from the RHS, regardless of the direction on the LHS.",id:"concept-2--means-assign-all-lhs-signals-from-the-rhs-regardless-of-the-direction-on-the-lhs",level:2},{value:"Conclusion:",id:"conclusion-1",level:3},{value:"Concept 3: Always Use := to assign DontCare to Wires",id:"concept-3-always-use--to-assign-dontcare-to-wires",level:2},{value:"Conclusion:",id:"conclusion-2",level:3},{value:"Concept 4: You can use <> or := to assign DontCare to directioned things (IOs)",id:"concept-4-you-can-use--or--to-assign-dontcare-to-directioned-things-ios",level:2},{value:"Conclusion:",id:"conclusion-3",level:3},{value:"Concept 5: <> works between things with at least one known flow (An IO or child's IO).",id:"concept-5---works-between-things-with-at-least-one-known-flow-an-io-or-childs-io",level:2},{value:"Conclusion:",id:"conclusion-4",level:3},{value:"Concept 6: <> and := connect signals by field name.",id:"concept-6--and--connect-signals-by-field-name",level:2},{value:"Conclusion:",id:"conclusion-5",level:3}];function r(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"deep-dive-into-connection-operators",children:"Deep Dive into Connection Operators"})}),"\n",(0,o.jsxs)(n.p,{children:["Chisel contains two connection operators, ",(0,o.jsx)(n.code,{children:":="})," and ",(0,o.jsx)(n.code,{children:"<>"}),". This document provides a deeper explanation of the differences of the two and when to use one or the other. The differences are demonstrated with experiments using Scastie examples which use ",(0,o.jsx)(n.code,{children:"DecoupledIO"}),"."]}),"\n",(0,o.jsx)(n.h3,{id:"experiment-setup",children:"Experiment Setup"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"// Imports used by the following examples\nimport chisel3._\nimport chisel3.util.DecoupledIO\n"})}),"\n",(0,o.jsxs)(n.p,{children:["The diagram for the experiment can be viewed ",(0,o.jsx)(n.a,{href:"https://docs.google.com/document/d/14C918Hdahk2xOGSJJBT-ZVqAx99_hg3JQIq-vaaifQU/edit?usp=sharing",children:"here"}),".\n",(0,o.jsx)(n.img,{src:"https://raw.githubusercontent.com/chipsalliance/chisel3/master/docs/src/images/connection-operators-experiment.svg?sanitize=true",alt:"Experiment Image"})]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect Producer to IO\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n // connect consumer to IO\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.b <> io.a\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n output io_in_ready,\n input io_in_valid,\n input [7:0] io_in_bits,\n input io_out_ready,\n output io_out_valid,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.h2,{id:"concept-1--is-commutative",children:["Concept 1: ",(0,o.jsx)(n.code,{children:"<>"})," is Commutative"]}),"\n",(0,o.jsxs)(n.p,{children:["This experiment is set up to test for the function of ",(0,o.jsx)(n.code,{children:"<>"})," using the experiment above."]}),"\n",(0,o.jsxs)(n.p,{children:["Achieving this involves flipping the RHS and LHS of the ",(0,o.jsx)(n.code,{children:"<>"})," operator and seeing how ",(0,o.jsx)(n.code,{children:"<>"})," will react.\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/LVhlbkFQQnq7X3trHfgZZQ",children:"https://scastie.scala-lang.org/Shorla/LVhlbkFQQnq7X3trHfgZZQ"})," )"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect producer to I/O\n io.in <> p.io.a\n // connect producer to consumer\n p.io.b <> c.io.a\n // connect consumer to I/O\n c.io.b <> io.out\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.a <> io.b\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n output io_in_ready,\n input io_in_valid,\n input [7:0] io_in_bits,\n input io_out_ready,\n output io_out_valid,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["The Verilog remained the same without incurring errors, showing that the ",(0,o.jsx)(n.code,{children:"<>"})," operator is commutative."]}),"\n",(0,o.jsxs)(n.h2,{id:"concept-2--means-assign-all-lhs-signals-from-the-rhs-regardless-of-the-direction-on-the-lhs",children:["Concept 2: ",(0,o.jsx)(n.code,{children:":="})," means assign ALL LHS signals from the RHS, regardless of the direction on the LHS."]}),"\n",(0,o.jsxs)(n.p,{children:["Using the same experiment code as above, we set to test for the function of ",(0,o.jsx)(n.code,{children:":="}),"\nWe replace all instances of ",(0,o.jsx)(n.code,{children:"<>"})," with ",(0,o.jsx)(n.code,{children:":="})," in the sample code above.\n(Scastie link to the experiment: ",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/o1ShdaY3RWKf0IIFwwQ1UQ/1",children:"https://scastie.scala-lang.org/Shorla/o1ShdaY3RWKf0IIFwwQ1UQ/1"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect producer to I/O\n p.io.a := io.in\n // connect producer to consumer\n c.io.a := p.io.b\n // connect consumer to I/O\n io.out := c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.a := io.b\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting error message for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"circt.stage.ChiselStage.emitSystemVerilog(new Wrapper)\n// chisel3.package$ChiselException: Connection between sink (PipelineStage.io.a: IO[DecoupledIO]) and source (PipelineStage.io.b: IO[DecoupledIO]) failed @: .bitsio.a.bits in PipelineStage cannot be written from module PipelineStage.\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp3$PipelineStage.(connection-operators.md:124)\n// \tat repl.MdocSession$MdocApp3$Wrapper$$anonfun$30$$anonfun$apply$20.apply(connection-operators.md:108)\n// \tat repl.MdocSession$MdocApp3$Wrapper$$anonfun$30$$anonfun$apply$20.apply(connection-operators.md:108)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat repl.MdocSession$MdocApp3$Wrapper$$anonfun$30.apply(connection-operators.md:108)\n// \tat repl.MdocSession$MdocApp3$Wrapper$$anonfun$30.apply(connection-operators.md:108)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp3$Wrapper.(connection-operators.md:108)\n// \tat repl.MdocSession$MdocApp3$$anonfun$39$$anonfun$apply$25.apply(connection-operators.md:132)\n// \tat repl.MdocSession$MdocApp3$$anonfun$39$$anonfun$apply$25.apply(connection-operators.md:132)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-1",children:"Conclusion:"}),"\n",(0,o.jsx)(n.p,{children:"The := operator goes field-by-field on the LHS and attempts to connect it to the same-named signal from the RHS. If something on the LHS is actually an Input, or the corresponding signal on the RHS is an Output, you will get an error as shown above."}),"\n",(0,o.jsxs)(n.h2,{id:"concept-3-always-use--to-assign-dontcare-to-wires",children:["Concept 3: Always Use ",(0,o.jsx)(n.code,{children:":="})," to assign DontCare to Wires"]}),"\n",(0,o.jsxs)(n.p,{children:["When assigning ",(0,o.jsx)(n.code,{children:"DontCare"})," to something that is not directioned, should you use ",(0,o.jsx)(n.code,{children:":="})," or ",(0,o.jsx)(n.code,{children:"<>"}),"?\nWe will find out using the sample codes below:\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1",children:"https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n //connect Producer to IO\n io.in := DontCare\n p.io.a <> DontCare\n val tmp = Wire(Flipped(DecoupledIO(UInt(8.W))))\n tmp := DontCare\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n //connect consumer to IO\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.b <> io.a\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n output io_in_ready,\n input io_in_valid,\n input [7:0] io_in_bits,\n input io_out_ready,\n output io_out_valid,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-2",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["If ",(0,o.jsx)(n.code,{children:"<>"})," were used to assign the unidrectioned wire ",(0,o.jsx)(n.code,{children:"tmp"})," to DontCare, we would get an error. But in the example above, we used ",(0,o.jsx)(n.code,{children:":="})," and no errors occurred.\nBut when ",(0,o.jsx)(n.code,{children:":="})," was used to assign the wire to DontCare, no errors will occur."]}),"\n",(0,o.jsxs)(n.p,{children:["Thus, when assigning ",(0,o.jsx)(n.code,{children:"DontCare"})," to a ",(0,o.jsx)(n.code,{children:"Wire"}),", always use ",(0,o.jsx)(n.code,{children:":="}),"."]}),"\n",(0,o.jsxs)(n.h2,{id:"concept-4-you-can-use--or--to-assign-dontcare-to-directioned-things-ios",children:["Concept 4: You can use ",(0,o.jsx)(n.code,{children:"<>"})," or ",(0,o.jsx)(n.code,{children:":="})," to assign ",(0,o.jsx)(n.code,{children:"DontCare"})," to directioned things (IOs)"]}),"\n",(0,o.jsxs)(n.p,{children:["When assigning ",(0,o.jsx)(n.code,{children:"DontCare"})," to something that is directioned, should you use ",(0,o.jsx)(n.code,{children:":="})," or ",(0,o.jsx)(n.code,{children:"<>"}),"?\nWe will find out using the sample codes below:\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1",children:"https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n //connect Producer to IO\n io.in := DontCare\n p.io.a <> DontCare\n val tmp = Wire(Flipped(DecoupledIO(UInt(8.W))))\n tmp := DontCare\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n //connect consumer to IO\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.b <> io.a\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n output io_in_ready,\n input io_in_valid,\n input [7:0] io_in_bits,\n input io_out_ready,\n output io_out_valid,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-3",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["Both ",(0,o.jsx)(n.code,{children:"<>"})," and ",(0,o.jsx)(n.code,{children:":="})," can be used to assign directioned things (IOs) to DontCare as shown in ",(0,o.jsx)(n.code,{children:"io.in"})," and ",(0,o.jsx)(n.code,{children:"p.io.a"})," respectively. This is basically equivalent because in this case both ",(0,o.jsx)(n.code,{children:"<>"})," and ",(0,o.jsx)(n.code,{children:":="})," will determine the direction from the LHS."]}),"\n",(0,o.jsxs)(n.h2,{id:"concept-5---works-between-things-with-at-least-one-known-flow-an-io-or-childs-io",children:["Concept 5: ",(0,o.jsx)(n.code,{children:"<>"})," works between things with at least one known flow (An IO or child's IO)."]}),"\n",(0,o.jsxs)(n.p,{children:["If there is at least one known flow what will ",(0,o.jsx)(n.code,{children:"<>"})," do? This will be shown using the experiment code below:\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/gKx9ReLVTTqDTk9vmw5ozg",children:"https://scastie.scala-lang.org/Shorla/gKx9ReLVTTqDTk9vmw5ozg"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n //connect Producer to IO\n // For this experiment, we add a temporary wire and see if it works...\n //p.io.a <> io.in\n val tmp = Wire(DecoupledIO(UInt(8.W)))\n // connect intermediate wire\n tmp <> io.in\n p.io.a <> tmp\n // connect producer to consumer\n c.io.a <> p.io.b\n //connect consumer to IO\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.b <> io.a\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:'chisel3.docs.emitSystemVerilog(new Wrapper)\n// res9: String = """// Generated by CIRCT firtool-1.86.0\n// module PipelineStage(\n// output io_a_ready,\n// input io_a_valid,\n// input [7:0] io_a_bits,\n// input io_b_ready,\n// output io_b_valid,\n// output [7:0] io_b_bits\n// );\n// \n// assign io_a_ready = io_b_ready;\n// assign io_b_valid = io_a_valid;\n// assign io_b_bits = io_a_bits;\n// endmodule\n// \n// module Wrapper(\n// input clock,\n// reset,\n// output io_in_ready,\n// input io_in_valid,\n// input [7:0] io_in_bits,\n// input io_out_ready,\n// output io_out_valid,\n// output [7:0] io_out_bits\n// );\n// \n// wire _c_io_a_ready;\n// wire _p_io_b_valid;\n// wire [7:0] _p_io_b_bits;\n// PipelineStage p (\n// .io_a_ready (io_in_ready),\n// .io_a_valid (io_in_valid),\n// .io_a_bits (io_in_bits),\n// .io_b_ready (_c_io_a_ready),\n// .io_b_valid (_p_io_b_valid),\n// .io_b_bits (_p_io_b_bits)\n// );\n// PipelineStage c (\n// .io_a_ready (_c_io_a_ready),\n// .io_a_valid (_p_io_b_valid),\n// .io_a_bits (_p_io_b_bits),\n// .io_b_ready (io_out_ready),\n// .io_b_valid (io_out_valid),\n// .io_b_bits (io_out_bits)\n// );\n// endmodule\n// \n// """\n'})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-4",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["The connection above went smoothly with no errors, this goes to show ",(0,o.jsx)(n.code,{children:"<>"}),' will work as long as there is at least one directioned thing (IO or submodule\'s IO) to "fix" the direction.']}),"\n",(0,o.jsxs)(n.h2,{id:"concept-6--and--connect-signals-by-field-name",children:["Concept 6: ",(0,o.jsx)(n.code,{children:"<>"})," and ",(0,o.jsx)(n.code,{children:":="})," connect signals by field name."]}),"\n",(0,o.jsxs)(n.p,{children:["This experiment creates a MockDecoupledIO which has the same fields by name as a DecoupledIO. Chisel lets us connect it and produces the same verilog, even though MockDecoupledIO and DecoupledIO are different types.\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Uf4tQquvQYigZAW705NFIQ",children:"https://scastie.scala-lang.org/Uf4tQquvQYigZAW705NFIQ"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass MockDecoupledIO extends Bundle {\n val valid = Output(Bool())\n val ready = Input(Bool())\n val bits = Output(UInt(8.W))\n}\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(new MockDecoupledIO())\n val out = new MockDecoupledIO()\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect producer to I/O\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n // connect consumer to I/O\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.a <> io.b\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n io_in_valid,\n output io_in_ready,\n input [7:0] io_in_bits,\n output io_out_valid,\n input io_out_ready,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.p,{children:["And here is another experiment, where we remove one of the fields of MockDecoupledIO:\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/ChtkhKCpS9CvJkjjqpdeIA",children:"https://scastie.scala-lang.org/ChtkhKCpS9CvJkjjqpdeIA"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass MockDecoupledIO extends Bundle {\n val valid = Output(Bool())\n val ready = Input(Bool())\n //val bits = Output(UInt(8.W))\n}\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(new MockDecoupledIO())\n val out = new MockDecoupledIO()\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect producer to I/O\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n // connect consumer to I/O\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.a <> io.b\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting error for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"circt.stage.ChiselStage.emitSystemVerilog(new Wrapper)\n// chisel3.package$ChiselException: Connection between left (PipelineStage.io.a: IO[DecoupledIO]) and source (Wrapper.io.in: IO[MockDecoupledIO]) failed @.bits: Right Record missing field (bits).\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp12$Wrapper.(connection-operators.md:357)\n// \tat repl.MdocSession$MdocApp12$$anonfun$119$$anonfun$apply$79.apply(connection-operators.md:378)\n// \tat repl.MdocSession$MdocApp12$$anonfun$119$$anonfun$apply$79.apply(connection-operators.md:378)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This one fails because there is a field ",(0,o.jsx)(n.code,{children:"bits"})," missing."]}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-5",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.code,{children:":="}),", the Scala types do not need to match but all the signals on the LHS must be provided by the RHS or you will get a Chisel elaboration error. There may be additional signals on the RHS, these will be ignored. For ",(0,o.jsx)(n.code,{children:"<>"}),", the Scala types do not need to match, but all signals must match exactly between LHS and RHS. In both cases, the order of the fields does not matter."]})]})}function p(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(r,{...e})}):r(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>s});var o=i(6540);const a={},t=o.createContext(a);function l(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:l(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[4863],{7396:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>p,frontMatter:()=>t,metadata:()=>s,toc:()=>d});var o=i(4848),a=i(8453);const t={layout:"docs",title:"Deep Dive into <> and := Connection Operators",section:"chisel3"},l="Deep Dive into Connection Operators",s={id:"explanations/connection-operators",title:"Deep Dive into <> and := Connection Operators",description:"Chisel contains two connection operators, := and `. This document provides a deeper explanation of the differences of the two and when to use one or the other. The differences are demonstrated with experiments using Scastie examples which use DecoupledIO`.",source:"@site/docs/explanations/connection-operators.md",sourceDirName:"explanations",slug:"/explanations/connection-operators",permalink:"/docs/explanations/connection-operators",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/connection-operators.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Deep Dive into <> and := Connection Operators",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Connectable Operators",permalink:"/docs/explanations/connectable"},next:{title:"Chisel Data Types",permalink:"/docs/explanations/data-types"}},c={},d=[{value:"Experiment Setup",id:"experiment-setup",level:3},{value:"Concept 1: <> is Commutative",id:"concept-1--is-commutative",level:2},{value:"Conclusion:",id:"conclusion",level:3},{value:"Concept 2: := means assign ALL LHS signals from the RHS, regardless of the direction on the LHS.",id:"concept-2--means-assign-all-lhs-signals-from-the-rhs-regardless-of-the-direction-on-the-lhs",level:2},{value:"Conclusion:",id:"conclusion-1",level:3},{value:"Concept 3: Always Use := to assign DontCare to Wires",id:"concept-3-always-use--to-assign-dontcare-to-wires",level:2},{value:"Conclusion:",id:"conclusion-2",level:3},{value:"Concept 4: You can use <> or := to assign DontCare to directioned things (IOs)",id:"concept-4-you-can-use--or--to-assign-dontcare-to-directioned-things-ios",level:2},{value:"Conclusion:",id:"conclusion-3",level:3},{value:"Concept 5: <> works between things with at least one known flow (An IO or child's IO).",id:"concept-5---works-between-things-with-at-least-one-known-flow-an-io-or-childs-io",level:2},{value:"Conclusion:",id:"conclusion-4",level:3},{value:"Concept 6: <> and := connect signals by field name.",id:"concept-6--and--connect-signals-by-field-name",level:2},{value:"Conclusion:",id:"conclusion-5",level:3}];function r(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"deep-dive-into-connection-operators",children:"Deep Dive into Connection Operators"})}),"\n",(0,o.jsxs)(n.p,{children:["Chisel contains two connection operators, ",(0,o.jsx)(n.code,{children:":="})," and ",(0,o.jsx)(n.code,{children:"<>"}),". This document provides a deeper explanation of the differences of the two and when to use one or the other. The differences are demonstrated with experiments using Scastie examples which use ",(0,o.jsx)(n.code,{children:"DecoupledIO"}),"."]}),"\n",(0,o.jsx)(n.h3,{id:"experiment-setup",children:"Experiment Setup"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"// Imports used by the following examples\nimport chisel3._\nimport chisel3.util.DecoupledIO\n"})}),"\n",(0,o.jsxs)(n.p,{children:["The diagram for the experiment can be viewed ",(0,o.jsx)(n.a,{href:"https://docs.google.com/document/d/14C918Hdahk2xOGSJJBT-ZVqAx99_hg3JQIq-vaaifQU/edit?usp=sharing",children:"here"}),".\n",(0,o.jsx)(n.img,{src:"https://raw.githubusercontent.com/chipsalliance/chisel3/master/docs/src/images/connection-operators-experiment.svg?sanitize=true",alt:"Experiment Image"})]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect Producer to IO\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n // connect consumer to IO\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.b <> io.a\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n output io_in_ready,\n input io_in_valid,\n input [7:0] io_in_bits,\n input io_out_ready,\n output io_out_valid,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.h2,{id:"concept-1--is-commutative",children:["Concept 1: ",(0,o.jsx)(n.code,{children:"<>"})," is Commutative"]}),"\n",(0,o.jsxs)(n.p,{children:["This experiment is set up to test for the function of ",(0,o.jsx)(n.code,{children:"<>"})," using the experiment above."]}),"\n",(0,o.jsxs)(n.p,{children:["Achieving this involves flipping the RHS and LHS of the ",(0,o.jsx)(n.code,{children:"<>"})," operator and seeing how ",(0,o.jsx)(n.code,{children:"<>"})," will react.\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/LVhlbkFQQnq7X3trHfgZZQ",children:"https://scastie.scala-lang.org/Shorla/LVhlbkFQQnq7X3trHfgZZQ"})," )"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect producer to I/O\n io.in <> p.io.a\n // connect producer to consumer\n p.io.b <> c.io.a\n // connect consumer to I/O\n c.io.b <> io.out\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.a <> io.b\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n output io_in_ready,\n input io_in_valid,\n input [7:0] io_in_bits,\n input io_out_ready,\n output io_out_valid,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["The Verilog remained the same without incurring errors, showing that the ",(0,o.jsx)(n.code,{children:"<>"})," operator is commutative."]}),"\n",(0,o.jsxs)(n.h2,{id:"concept-2--means-assign-all-lhs-signals-from-the-rhs-regardless-of-the-direction-on-the-lhs",children:["Concept 2: ",(0,o.jsx)(n.code,{children:":="})," means assign ALL LHS signals from the RHS, regardless of the direction on the LHS."]}),"\n",(0,o.jsxs)(n.p,{children:["Using the same experiment code as above, we set to test for the function of ",(0,o.jsx)(n.code,{children:":="}),"\nWe replace all instances of ",(0,o.jsx)(n.code,{children:"<>"})," with ",(0,o.jsx)(n.code,{children:":="})," in the sample code above.\n(Scastie link to the experiment: ",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/o1ShdaY3RWKf0IIFwwQ1UQ/1",children:"https://scastie.scala-lang.org/Shorla/o1ShdaY3RWKf0IIFwwQ1UQ/1"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect producer to I/O\n p.io.a := io.in\n // connect producer to consumer\n c.io.a := p.io.b\n // connect consumer to I/O\n io.out := c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.a := io.b\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting error message for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"circt.stage.ChiselStage.emitSystemVerilog(new Wrapper)\n// chisel3.package$ChiselException: Connection between sink (PipelineStage.io.a: IO[DecoupledIO]) and source (PipelineStage.io.b: IO[DecoupledIO]) failed @: .bitsio.a.bits in PipelineStage cannot be written from module PipelineStage.\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp3$PipelineStage.(connection-operators.md:124)\n// \tat repl.MdocSession$MdocApp3$Wrapper$$anonfun$30$$anonfun$apply$20.apply(connection-operators.md:108)\n// \tat repl.MdocSession$MdocApp3$Wrapper$$anonfun$30$$anonfun$apply$20.apply(connection-operators.md:108)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat repl.MdocSession$MdocApp3$Wrapper$$anonfun$30.apply(connection-operators.md:108)\n// \tat repl.MdocSession$MdocApp3$Wrapper$$anonfun$30.apply(connection-operators.md:108)\n// \tat chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)\n// \tat repl.MdocSession$MdocApp3$Wrapper.(connection-operators.md:108)\n// \tat repl.MdocSession$MdocApp3$$anonfun$39$$anonfun$apply$25.apply(connection-operators.md:132)\n// \tat repl.MdocSession$MdocApp3$$anonfun$39$$anonfun$apply$25.apply(connection-operators.md:132)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-1",children:"Conclusion:"}),"\n",(0,o.jsx)(n.p,{children:"The := operator goes field-by-field on the LHS and attempts to connect it to the same-named signal from the RHS. If something on the LHS is actually an Input, or the corresponding signal on the RHS is an Output, you will get an error as shown above."}),"\n",(0,o.jsxs)(n.h2,{id:"concept-3-always-use--to-assign-dontcare-to-wires",children:["Concept 3: Always Use ",(0,o.jsx)(n.code,{children:":="})," to assign DontCare to Wires"]}),"\n",(0,o.jsxs)(n.p,{children:["When assigning ",(0,o.jsx)(n.code,{children:"DontCare"})," to something that is not directioned, should you use ",(0,o.jsx)(n.code,{children:":="})," or ",(0,o.jsx)(n.code,{children:"<>"}),"?\nWe will find out using the sample codes below:\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1",children:"https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n //connect Producer to IO\n io.in := DontCare\n p.io.a <> DontCare\n val tmp = Wire(Flipped(DecoupledIO(UInt(8.W))))\n tmp := DontCare\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n //connect consumer to IO\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.b <> io.a\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n output io_in_ready,\n input io_in_valid,\n input [7:0] io_in_bits,\n input io_out_ready,\n output io_out_valid,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-2",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["If ",(0,o.jsx)(n.code,{children:"<>"})," were used to assign the unidrectioned wire ",(0,o.jsx)(n.code,{children:"tmp"})," to DontCare, we would get an error. But in the example above, we used ",(0,o.jsx)(n.code,{children:":="})," and no errors occurred.\nBut when ",(0,o.jsx)(n.code,{children:":="})," was used to assign the wire to DontCare, no errors will occur."]}),"\n",(0,o.jsxs)(n.p,{children:["Thus, when assigning ",(0,o.jsx)(n.code,{children:"DontCare"})," to a ",(0,o.jsx)(n.code,{children:"Wire"}),", always use ",(0,o.jsx)(n.code,{children:":="}),"."]}),"\n",(0,o.jsxs)(n.h2,{id:"concept-4-you-can-use--or--to-assign-dontcare-to-directioned-things-ios",children:["Concept 4: You can use ",(0,o.jsx)(n.code,{children:"<>"})," or ",(0,o.jsx)(n.code,{children:":="})," to assign ",(0,o.jsx)(n.code,{children:"DontCare"})," to directioned things (IOs)"]}),"\n",(0,o.jsxs)(n.p,{children:["When assigning ",(0,o.jsx)(n.code,{children:"DontCare"})," to something that is directioned, should you use ",(0,o.jsx)(n.code,{children:":="})," or ",(0,o.jsx)(n.code,{children:"<>"}),"?\nWe will find out using the sample codes below:\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1",children:"https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n //connect Producer to IO\n io.in := DontCare\n p.io.a <> DontCare\n val tmp = Wire(Flipped(DecoupledIO(UInt(8.W))))\n tmp := DontCare\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n //connect consumer to IO\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.b <> io.a\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n output io_in_ready,\n input io_in_valid,\n input [7:0] io_in_bits,\n input io_out_ready,\n output io_out_valid,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-3",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["Both ",(0,o.jsx)(n.code,{children:"<>"})," and ",(0,o.jsx)(n.code,{children:":="})," can be used to assign directioned things (IOs) to DontCare as shown in ",(0,o.jsx)(n.code,{children:"io.in"})," and ",(0,o.jsx)(n.code,{children:"p.io.a"})," respectively. This is basically equivalent because in this case both ",(0,o.jsx)(n.code,{children:"<>"})," and ",(0,o.jsx)(n.code,{children:":="})," will determine the direction from the LHS."]}),"\n",(0,o.jsxs)(n.h2,{id:"concept-5---works-between-things-with-at-least-one-known-flow-an-io-or-childs-io",children:["Concept 5: ",(0,o.jsx)(n.code,{children:"<>"})," works between things with at least one known flow (An IO or child's IO)."]}),"\n",(0,o.jsxs)(n.p,{children:["If there is at least one known flow what will ",(0,o.jsx)(n.code,{children:"<>"})," do? This will be shown using the experiment code below:\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Shorla/gKx9ReLVTTqDTk9vmw5ozg",children:"https://scastie.scala-lang.org/Shorla/gKx9ReLVTTqDTk9vmw5ozg"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(DecoupledIO(UInt(8.W)))\n val out = DecoupledIO(UInt(8.W))\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n //connect Producer to IO\n // For this experiment, we add a temporary wire and see if it works...\n //p.io.a <> io.in\n val tmp = Wire(DecoupledIO(UInt(8.W)))\n // connect intermediate wire\n tmp <> io.in\n p.io.a <> tmp\n // connect producer to consumer\n c.io.a <> p.io.b\n //connect consumer to IO\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.b <> io.a\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:'chisel3.docs.emitSystemVerilog(new Wrapper)\n// res9: String = """// Generated by CIRCT firtool-1.86.0\n// module PipelineStage(\n// output io_a_ready,\n// input io_a_valid,\n// input [7:0] io_a_bits,\n// input io_b_ready,\n// output io_b_valid,\n// output [7:0] io_b_bits\n// );\n// \n// assign io_a_ready = io_b_ready;\n// assign io_b_valid = io_a_valid;\n// assign io_b_bits = io_a_bits;\n// endmodule\n// \n// module Wrapper(\n// input clock,\n// reset,\n// output io_in_ready,\n// input io_in_valid,\n// input [7:0] io_in_bits,\n// input io_out_ready,\n// output io_out_valid,\n// output [7:0] io_out_bits\n// );\n// \n// wire _c_io_a_ready;\n// wire _p_io_b_valid;\n// wire [7:0] _p_io_b_bits;\n// PipelineStage p (\n// .io_a_ready (io_in_ready),\n// .io_a_valid (io_in_valid),\n// .io_a_bits (io_in_bits),\n// .io_b_ready (_c_io_a_ready),\n// .io_b_valid (_p_io_b_valid),\n// .io_b_bits (_p_io_b_bits)\n// );\n// PipelineStage c (\n// .io_a_ready (_c_io_a_ready),\n// .io_a_valid (_p_io_b_valid),\n// .io_a_bits (_p_io_b_bits),\n// .io_b_ready (io_out_ready),\n// .io_b_valid (io_out_valid),\n// .io_b_bits (io_out_bits)\n// );\n// endmodule\n// \n// """\n'})}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-4",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["The connection above went smoothly with no errors, this goes to show ",(0,o.jsx)(n.code,{children:"<>"}),' will work as long as there is at least one directioned thing (IO or submodule\'s IO) to "fix" the direction.']}),"\n",(0,o.jsxs)(n.h2,{id:"concept-6--and--connect-signals-by-field-name",children:["Concept 6: ",(0,o.jsx)(n.code,{children:"<>"})," and ",(0,o.jsx)(n.code,{children:":="})," connect signals by field name."]}),"\n",(0,o.jsxs)(n.p,{children:["This experiment creates a MockDecoupledIO which has the same fields by name as a DecoupledIO. Chisel lets us connect it and produces the same verilog, even though MockDecoupledIO and DecoupledIO are different types.\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/Uf4tQquvQYigZAW705NFIQ",children:"https://scastie.scala-lang.org/Uf4tQquvQYigZAW705NFIQ"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass MockDecoupledIO extends Bundle {\n val valid = Output(Bool())\n val ready = Input(Bool())\n val bits = Output(UInt(8.W))\n}\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(new MockDecoupledIO())\n val out = new MockDecoupledIO()\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect producer to I/O\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n // connect consumer to I/O\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.a <> io.b\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting Verilog for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.86.0\nmodule PipelineStage(\n output io_a_ready,\n input io_a_valid,\n input [7:0] io_a_bits,\n input io_b_ready,\n output io_b_valid,\n output [7:0] io_b_bits\n);\n\n assign io_a_ready = io_b_ready;\n assign io_b_valid = io_a_valid;\n assign io_b_bits = io_a_bits;\nendmodule\n\nmodule Wrapper(\n input clock,\n reset,\n io_in_valid,\n output io_in_ready,\n input [7:0] io_in_bits,\n output io_out_valid,\n input io_out_ready,\n output [7:0] io_out_bits\n);\n\n wire _c_io_a_ready;\n wire _p_io_b_valid;\n wire [7:0] _p_io_b_bits;\n PipelineStage p (\n .io_a_ready (io_in_ready),\n .io_a_valid (io_in_valid),\n .io_a_bits (io_in_bits),\n .io_b_ready (_c_io_a_ready),\n .io_b_valid (_p_io_b_valid),\n .io_b_bits (_p_io_b_bits)\n );\n PipelineStage c (\n .io_a_ready (_c_io_a_ready),\n .io_a_valid (_p_io_b_valid),\n .io_a_bits (_p_io_b_bits),\n .io_b_ready (io_out_ready),\n .io_b_valid (io_out_valid),\n .io_b_bits (io_out_bits)\n );\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.p,{children:["And here is another experiment, where we remove one of the fields of MockDecoupledIO:\n( Scastie link for the experiment:",(0,o.jsx)(n.a,{href:"https://scastie.scala-lang.org/ChtkhKCpS9CvJkjjqpdeIA",children:"https://scastie.scala-lang.org/ChtkhKCpS9CvJkjjqpdeIA"}),")"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.DecoupledIO\n\nclass MockDecoupledIO extends Bundle {\n val valid = Output(Bool())\n val ready = Input(Bool())\n //val bits = Output(UInt(8.W))\n}\nclass Wrapper extends Module{\n val io = IO(new Bundle {\n val in = Flipped(new MockDecoupledIO())\n val out = new MockDecoupledIO()\n })\n val p = Module(new PipelineStage)\n val c = Module(new PipelineStage)\n // connect producer to I/O\n p.io.a <> io.in\n // connect producer to consumer\n c.io.a <> p.io.b\n // connect consumer to I/O\n io.out <> c.io.b\n}\nclass PipelineStage extends Module{\n val io = IO(new Bundle{\n val a = Flipped(DecoupledIO(UInt(8.W)))\n val b = DecoupledIO(UInt(8.W))\n })\n io.a <> io.b\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Below we can see the resulting error for this example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"circt.stage.ChiselStage.emitSystemVerilog(new Wrapper)\n// chisel3.package$ChiselException: Connection between left (PipelineStage.io.a: IO[DecoupledIO]) and source (Wrapper.io.in: IO[MockDecoupledIO]) failed @.bits: Right Record missing field (bits).\n// \tat ... ()\n// \tat repl.MdocSession$MdocApp12$Wrapper.(connection-operators.md:357)\n// \tat repl.MdocSession$MdocApp12$$anonfun$119$$anonfun$apply$79.apply(connection-operators.md:378)\n// \tat repl.MdocSession$MdocApp12$$anonfun$119$$anonfun$apply$79.apply(connection-operators.md:378)\n// \tat chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84)\n// \tat chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52)\n// \tat chisel3.Module$.evaluate(Module.scala:10)\n// \tat chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25)\n// \tat chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23)\n// \tat chisel3.Module$._applyImpl(Module.scala:10)\n// \tat chisel3.Module$.do_apply(Module.scala:22)\n// \tat chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54)\n// \tat chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat chisel3.internal.Builder$.buildImpl(Builder.scala:1071)\n// \tat chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063)\n// \tat logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)\n// \tat scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)\n// \tat logger.Logger$.makeScope(Logger.scala:146)\n// \tat logger.Logger$.makeScope(Logger.scala:133)\n// \tat ... ()\n// \tat ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This one fails because there is a field ",(0,o.jsx)(n.code,{children:"bits"})," missing."]}),"\n",(0,o.jsx)(n.h3,{id:"conclusion-5",children:"Conclusion:"}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.code,{children:":="}),", the Scala types do not need to match but all the signals on the LHS must be provided by the RHS or you will get a Chisel elaboration error. There may be additional signals on the RHS, these will be ignored. For ",(0,o.jsx)(n.code,{children:"<>"}),", the Scala types do not need to match, but all signals must match exactly between LHS and RHS. In both cases, the order of the fields does not matter."]})]})}function p(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(r,{...e})}):r(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>s});var o=i(6540);const a={},t=o.createContext(a);function l(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:l(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/runtime~main.9be11a54.js b/assets/js/runtime~main.2bf389d2.js
similarity index 70%
rename from assets/js/runtime~main.9be11a54.js
rename to assets/js/runtime~main.2bf389d2.js
index 0c81f357df..977969aee2 100644
--- a/assets/js/runtime~main.9be11a54.js
+++ b/assets/js/runtime~main.2bf389d2.js
@@ -1 +1 @@
-(()=>{"use strict";var e,a,c,d,b,f={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var c=t[e]={exports:{}};return f[e].call(c.exports,c,c.exports,r),c.exports}r.m=f,e=[],r.O=(a,c,d,b)=>{if(!c){var f=1/0;for(i=0;i=b)&&Object.keys(r.O).every((e=>r.O[e](c[o])))?c.splice(o--,1):(t=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[c,d,b]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var b=Object.create(null);r.r(b);var f={};a=a||[null,c({}),c([]),c(c)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=c(t))Object.getOwnPropertyNames(t).forEach((a=>f[a]=()=>e[a]));return f.default=()=>e,r.d(b,f),b},r.d=(e,a)=>{for(var c in a)r.o(a,c)&&!r.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,c)=>(r.f[c](e,a),a)),[])),r.u=e=>"assets/js/"+({340:"c5561474",635:"c260b502",741:"1ce89024",849:"0058b4c6",957:"c141421f",1108:"bc33eb1f",1188:"e7b22fe0",1235:"a7456010",1281:"d50fb5c7",1384:"8fdf13ba",1596:"f416550b",1921:"2024159c",2012:"f10ce86b",2138:"1a4e3797",2289:"916cecd1",2504:"54ab625b",2579:"9cc76f42",2634:"c4f5d8e4",2785:"7b5bfa87",3117:"a26328e3",3126:"cddf45a4",3130:"3afb3224",3291:"7cc2f0dc",3313:"a8f82c73",3316:"c48de377",3361:"c377a04b",3460:"a98e3d7d",3543:"96d1adfe",3599:"30c88dbf",4020:"44ff0b81",4166:"d4b6d0e6",4286:"11a69d4a",4315:"651e9e03",4825:"44147ff4",4863:"d1e6e3d8",5056:"ae8e96e2",5432:"7e1e4a75",5497:"46a40f56",5522:"cdcdfbab",5540:"d1a7dbc9",5583:"f901c241",5666:"0bba5ab0",5742:"aba21aa0",6061:"1f391b9e",6067:"1f7682ec",6304:"21d75435",6403:"d1a683e4",6474:"c7666d49",6760:"11d458a9",6803:"3b8c55ea",6969:"14eb3368",6991:"37a5b604",7087:"1883c3a9",7098:"a7bd4aaa",7132:"67ffb541",7315:"407ce553",7425:"a47e47c7",7437:"adf02ec5",8118:"6559d260",8227:"19ad7e9f",8316:"17dd133b",8401:"17896441",8485:"806d4637",8507:"b13aa1a2",8864:"d92a3c43",8946:"98ca0ee0",9017:"868241d3",9048:"a94703ab",9128:"7fa9ea57",9387:"c71a47e4",9647:"5e95c892",9670:"87ed036d",9710:"bc089483",9920:"6a9619ba",9942:"12b2b068"}[e]||e)+"."+{340:"8dbece39",416:"d5c32938",635:"9468039b",741:"be0df6cd",849:"287c9173",957:"0fd76349",1108:"c5d79c51",1188:"be1f0183",1235:"e788d507",1281:"d9c2612f",1384:"0af447b8",1596:"d359a0d4",1921:"61527e57",2012:"6ca66e63",2138:"ec805fbc",2237:"c1ab8b5a",2289:"ac9d2c88",2504:"c3eb51cb",2579:"8000e271",2634:"b2d80d44",2785:"d8c045dc",3117:"b3e82129",3126:"ade07b02",3130:"4c52d26f",3291:"ea3e6fff",3313:"53e915bb",3316:"c728b2ab",3361:"304b9e45",3460:"3a0c1e06",3543:"ef9fba8c",3599:"70c8f729",4020:"42b22afe",4166:"359990fd",4286:"0b48b87d",4315:"387bd3d0",4825:"a73dbf93",4863:"9fd43a9d",5056:"50814aef",5432:"ec8437ac",5497:"1a3404c7",5522:"89d15cfa",5540:"cc8714f3",5583:"9339da55",5666:"7d862322",5742:"23cb5882",6061:"7dc4fdd6",6067:"298dd3a2",6304:"747541f6",6403:"148f34e8",6474:"56c153fa",6760:"b9d97434",6803:"e22bea40",6969:"7ffbfc53",6991:"00e7852a",7087:"2844b440",7098:"c65a07f8",7132:"3deaf02c",7315:"6c1220b4",7425:"51d18bcb",7437:"9654a22f",8118:"e80dab3d",8158:"887a29fb",8227:"c6729e12",8316:"bc3397bf",8401:"c8c06b99",8485:"78350f78",8507:"81fc2d29",8608:"e90d5e14",8864:"6b30aa7d",8913:"eae5cfc0",8946:"311cb1f1",9017:"7cb166e1",9048:"d3c53685",9128:"ec532c62",9387:"f1c35766",9647:"539b71e6",9670:"2f651873",9710:"7773c241",9920:"2496f8e2",9942:"e726c7f9"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},b="chisel-lang:",r.l=(e,a,c,f)=>{if(d[e])d[e].push(a);else{var t,o;if(void 0!==c)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(s);var b=d[e];if(delete d[e],t.parentNode&&t.parentNode.removeChild(t),b&&b.forEach((e=>e(c))),a)return a(c)},s=setTimeout(u.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=u.bind(null,t.onerror),t.onload=u.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",c5561474:"340",c260b502:"635","1ce89024":"741","0058b4c6":"849",c141421f:"957",bc33eb1f:"1108",e7b22fe0:"1188",a7456010:"1235",d50fb5c7:"1281","8fdf13ba":"1384",f416550b:"1596","2024159c":"1921",f10ce86b:"2012","1a4e3797":"2138","916cecd1":"2289","54ab625b":"2504","9cc76f42":"2579",c4f5d8e4:"2634","7b5bfa87":"2785",a26328e3:"3117",cddf45a4:"3126","3afb3224":"3130","7cc2f0dc":"3291",a8f82c73:"3313",c48de377:"3316",c377a04b:"3361",a98e3d7d:"3460","96d1adfe":"3543","30c88dbf":"3599","44ff0b81":"4020",d4b6d0e6:"4166","11a69d4a":"4286","651e9e03":"4315","44147ff4":"4825",d1e6e3d8:"4863",ae8e96e2:"5056","7e1e4a75":"5432","46a40f56":"5497",cdcdfbab:"5522",d1a7dbc9:"5540",f901c241:"5583","0bba5ab0":"5666",aba21aa0:"5742","1f391b9e":"6061","1f7682ec":"6067","21d75435":"6304",d1a683e4:"6403",c7666d49:"6474","11d458a9":"6760","3b8c55ea":"6803","14eb3368":"6969","37a5b604":"6991","1883c3a9":"7087",a7bd4aaa:"7098","67ffb541":"7132","407ce553":"7315",a47e47c7:"7425",adf02ec5:"7437","6559d260":"8118","19ad7e9f":"8227","17dd133b":"8316","806d4637":"8485",b13aa1a2:"8507",d92a3c43:"8864","98ca0ee0":"8946","868241d3":"9017",a94703ab:"9048","7fa9ea57":"9128",c71a47e4:"9387","5e95c892":"9647","87ed036d":"9670",bc089483:"9710","6a9619ba":"9920","12b2b068":"9942"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,c)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)c.push(d[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var b=new Promise(((c,b)=>d=e[a]=[c,b]));c.push(d[2]=b);var f=r.p+r.u(a),t=new Error;r.l(f,(c=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var b=c&&("load"===c.type?"missing":c.type),f=c&&c.target&&c.target.src;t.message="Loading chunk "+a+" failed.\n("+b+": "+f+")",t.name="ChunkLoadError",t.type=b,t.request=f,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,c)=>{var d,b,f=c[0],t=c[1],o=c[2],n=0;if(f.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(c);n{"use strict";var e,a,c,d,f,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var c=t[e]={exports:{}};return b[e].call(c.exports,c,c.exports,r),c.exports}r.m=b,e=[],r.O=(a,c,d,f)=>{if(!c){var b=1/0;for(i=0;i=f)&&Object.keys(r.O).every((e=>r.O[e](c[o])))?c.splice(o--,1):(t=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[c,d,f]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var f=Object.create(null);r.r(f);var b={};a=a||[null,c({}),c([]),c(c)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=c(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(f,b),f},r.d=(e,a)=>{for(var c in a)r.o(a,c)&&!r.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,c)=>(r.f[c](e,a),a)),[])),r.u=e=>"assets/js/"+({340:"c5561474",635:"c260b502",741:"1ce89024",849:"0058b4c6",957:"c141421f",1108:"bc33eb1f",1188:"e7b22fe0",1235:"a7456010",1281:"d50fb5c7",1384:"8fdf13ba",1596:"f416550b",1921:"2024159c",2012:"f10ce86b",2138:"1a4e3797",2289:"916cecd1",2504:"54ab625b",2579:"9cc76f42",2634:"c4f5d8e4",2785:"7b5bfa87",3117:"a26328e3",3126:"cddf45a4",3130:"3afb3224",3291:"7cc2f0dc",3313:"a8f82c73",3316:"c48de377",3361:"c377a04b",3460:"a98e3d7d",3543:"96d1adfe",3599:"30c88dbf",4020:"44ff0b81",4166:"d4b6d0e6",4286:"11a69d4a",4315:"651e9e03",4825:"44147ff4",4863:"d1e6e3d8",5056:"ae8e96e2",5432:"7e1e4a75",5497:"46a40f56",5522:"cdcdfbab",5540:"d1a7dbc9",5583:"f901c241",5666:"0bba5ab0",5742:"aba21aa0",6061:"1f391b9e",6067:"1f7682ec",6304:"21d75435",6403:"d1a683e4",6474:"c7666d49",6760:"11d458a9",6803:"3b8c55ea",6969:"14eb3368",6991:"37a5b604",7087:"1883c3a9",7098:"a7bd4aaa",7132:"67ffb541",7315:"407ce553",7425:"a47e47c7",7437:"adf02ec5",8118:"6559d260",8227:"19ad7e9f",8316:"17dd133b",8401:"17896441",8485:"806d4637",8507:"b13aa1a2",8864:"d92a3c43",8946:"98ca0ee0",9017:"868241d3",9048:"a94703ab",9128:"7fa9ea57",9387:"c71a47e4",9647:"5e95c892",9670:"87ed036d",9710:"bc089483",9920:"6a9619ba",9942:"12b2b068"}[e]||e)+"."+{340:"8dbece39",416:"d5c32938",635:"9468039b",741:"232f983b",849:"287c9173",957:"0fd76349",1108:"c5d79c51",1188:"be1f0183",1235:"e788d507",1281:"d9c2612f",1384:"0af447b8",1596:"d359a0d4",1921:"61527e57",2012:"6ca66e63",2138:"ec805fbc",2237:"c1ab8b5a",2289:"ac9d2c88",2504:"c3eb51cb",2579:"8000e271",2634:"b2d80d44",2785:"48536f48",3117:"b89ff0c7",3126:"ade07b02",3130:"4c52d26f",3291:"ea3e6fff",3313:"53e915bb",3316:"c728b2ab",3361:"304b9e45",3460:"3a0c1e06",3543:"ef9fba8c",3599:"70c8f729",4020:"42b22afe",4166:"359990fd",4286:"0b48b87d",4315:"387bd3d0",4825:"a73dbf93",4863:"f86086db",5056:"50814aef",5432:"12cdae69",5497:"1a3404c7",5522:"89d15cfa",5540:"cc8714f3",5583:"9339da55",5666:"7d862322",5742:"23cb5882",6061:"7dc4fdd6",6067:"298dd3a2",6304:"747541f6",6403:"148f34e8",6474:"56c153fa",6760:"b9d97434",6803:"e22bea40",6969:"7ffbfc53",6991:"00e7852a",7087:"2844b440",7098:"c65a07f8",7132:"bee895a3",7315:"6c1220b4",7425:"51d18bcb",7437:"9654a22f",8118:"e80dab3d",8158:"887a29fb",8227:"c6729e12",8316:"bc3397bf",8401:"c8c06b99",8485:"78350f78",8507:"81fc2d29",8608:"e90d5e14",8864:"6b30aa7d",8913:"eae5cfc0",8946:"f3879cfd",9017:"95b3fb05",9048:"d3c53685",9128:"ec532c62",9387:"f1c35766",9647:"539b71e6",9670:"2f651873",9710:"7773c241",9920:"2496f8e2",9942:"e726c7f9"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},f="chisel-lang:",r.l=(e,a,c,b)=>{if(d[e])d[e].push(a);else{var t,o;if(void 0!==c)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(s);var f=d[e];if(delete d[e],t.parentNode&&t.parentNode.removeChild(t),f&&f.forEach((e=>e(c))),a)return a(c)},s=setTimeout(u.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=u.bind(null,t.onerror),t.onload=u.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",c5561474:"340",c260b502:"635","1ce89024":"741","0058b4c6":"849",c141421f:"957",bc33eb1f:"1108",e7b22fe0:"1188",a7456010:"1235",d50fb5c7:"1281","8fdf13ba":"1384",f416550b:"1596","2024159c":"1921",f10ce86b:"2012","1a4e3797":"2138","916cecd1":"2289","54ab625b":"2504","9cc76f42":"2579",c4f5d8e4:"2634","7b5bfa87":"2785",a26328e3:"3117",cddf45a4:"3126","3afb3224":"3130","7cc2f0dc":"3291",a8f82c73:"3313",c48de377:"3316",c377a04b:"3361",a98e3d7d:"3460","96d1adfe":"3543","30c88dbf":"3599","44ff0b81":"4020",d4b6d0e6:"4166","11a69d4a":"4286","651e9e03":"4315","44147ff4":"4825",d1e6e3d8:"4863",ae8e96e2:"5056","7e1e4a75":"5432","46a40f56":"5497",cdcdfbab:"5522",d1a7dbc9:"5540",f901c241:"5583","0bba5ab0":"5666",aba21aa0:"5742","1f391b9e":"6061","1f7682ec":"6067","21d75435":"6304",d1a683e4:"6403",c7666d49:"6474","11d458a9":"6760","3b8c55ea":"6803","14eb3368":"6969","37a5b604":"6991","1883c3a9":"7087",a7bd4aaa:"7098","67ffb541":"7132","407ce553":"7315",a47e47c7:"7425",adf02ec5:"7437","6559d260":"8118","19ad7e9f":"8227","17dd133b":"8316","806d4637":"8485",b13aa1a2:"8507",d92a3c43:"8864","98ca0ee0":"8946","868241d3":"9017",a94703ab:"9048","7fa9ea57":"9128",c71a47e4:"9387","5e95c892":"9647","87ed036d":"9670",bc089483:"9710","6a9619ba":"9920","12b2b068":"9942"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,c)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)c.push(d[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var f=new Promise(((c,f)=>d=e[a]=[c,f]));c.push(d[2]=f);var b=r.p+r.u(a),t=new Error;r.l(b,(c=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var f=c&&("load"===c.type?"missing":c.type),b=c&&c.target&&c.target.src;t.message="Loading chunk "+a+" failed.\n("+f+": "+b+")",t.name="ChunkLoadError",t.type=f,t.request=b,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,c)=>{var d,f,b=c[0],t=c[1],o=c[2],n=0;if(b.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(c);nCommunity | Chisel
-
+
diff --git a/docs.html b/docs.html
index 91ababb473..7613330f0f 100644
--- a/docs.html
+++ b/docs.html
@@ -4,7 +4,7 @@
Introduction | Chisel
-
+
diff --git a/docs/appendix.html b/docs/appendix.html
index 1214db9e91..7e00ba7edc 100644
--- a/docs/appendix.html
+++ b/docs/appendix.html
@@ -4,7 +4,7 @@
Appendix | Chisel
-
+
diff --git a/docs/appendix/experimental-features.html b/docs/appendix/experimental-features.html
index 09003f6d50..a6178c4a5c 100644
--- a/docs/appendix/experimental-features.html
+++ b/docs/appendix/experimental-features.html
@@ -4,7 +4,7 @@
Experimental Features | Chisel
-
+
diff --git a/docs/appendix/migrating-from-chiseltest.html b/docs/appendix/migrating-from-chiseltest.html
index a0a57b9c20..1066c953f4 100644
--- a/docs/appendix/migrating-from-chiseltest.html
+++ b/docs/appendix/migrating-from-chiseltest.html
@@ -4,7 +4,7 @@
Migrating from ChiselTest | Chisel
-
+
diff --git a/docs/appendix/upgrading-from-chisel-3-4.html b/docs/appendix/upgrading-from-chisel-3-4.html
index b610cf1e67..2244ec3fc4 100644
--- a/docs/appendix/upgrading-from-chisel-3-4.html
+++ b/docs/appendix/upgrading-from-chisel-3-4.html
@@ -4,7 +4,7 @@
Upgrading From Chisel 3.4 to 3.5 | Chisel
-
+
diff --git a/docs/appendix/upgrading-from-scala-2-11.html b/docs/appendix/upgrading-from-scala-2-11.html
index 6530e03f55..d96e7bef1a 100644
--- a/docs/appendix/upgrading-from-scala-2-11.html
+++ b/docs/appendix/upgrading-from-scala-2-11.html
@@ -4,7 +4,7 @@
Upgrading From Scala 2.11 | Chisel
-
+
diff --git a/docs/appendix/versioning.html b/docs/appendix/versioning.html
index b0d00049f5..87b316bcac 100644
--- a/docs/appendix/versioning.html
+++ b/docs/appendix/versioning.html
@@ -4,7 +4,7 @@
Versioning | Chisel
-
+
diff --git a/docs/category/getting-started.html b/docs/category/getting-started.html
index 532e0ae01a..b2f3ce0e05 100644
--- a/docs/category/getting-started.html
+++ b/docs/category/getting-started.html
@@ -4,7 +4,7 @@
Getting Started | Chisel
-
+
diff --git a/docs/cookbooks.html b/docs/cookbooks.html
index 18619372fa..7138e57215 100644
--- a/docs/cookbooks.html
+++ b/docs/cookbooks.html
@@ -4,7 +4,7 @@
Cookbooks | Chisel
-
+
diff --git a/docs/cookbooks/cookbook.html b/docs/cookbooks/cookbook.html
index 2326e79b5f..951b5e3ed3 100644
--- a/docs/cookbooks/cookbook.html
+++ b/docs/cookbooks/cookbook.html
@@ -4,7 +4,7 @@
General Cookbook | Chisel
-
+
@@ -53,7 +53,7 @@
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 (foo,bar) // at ... () // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298) // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:298) // 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:298) // at repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:317) // at repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:317) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
getVerilogString(new Top(new AliasedBundle(UInt(8.W)))) // chisel3.AliasedAggregateFieldException: AliasedBundle contains aliased fields named (foo,bar) // at ... () // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298) // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:298) // 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:298) // at repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:317) // at repl.MdocSession$MdocApp17$$anonfun$55$$anonfun$apply$43.apply(cookbook.md:317) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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
@@ -61,7 +61,7 @@
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 (gen,foo) // at ... () // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298) // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:298) // 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:298) // at repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:336) // at repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:336) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
getVerilogString(new Top(new AlsoAliasedBundle(UInt(8.W)))) // chisel3.AliasedAggregateFieldException: AlsoAliasedBundle contains aliased fields named (gen,foo) // at ... () // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298) // at repl.MdocSession$MdocApp17$Top$$anonfun$50$$anonfun$apply$37.apply(cookbook.md:298) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$Top$$anonfun$50.apply(cookbook.md:298) // 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:298) // at repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:336) // at repl.MdocSession$MdocApp17$$anonfun$57$$anonfun$apply$44.apply(cookbook.md:336) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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.
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 'bar' 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:367) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:367) // at chisel3.IO$.apply(IO.scala:34) // at chisel3.experimental.BaseModule.IO(ModuleImpl.scala:859) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:367) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:367) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md:367) // 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:367) // at repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:369) // at repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:369) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
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 'bar' 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:367) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51$$anonfun$apply$52.apply(cookbook.md:367) // at chisel3.IO$.apply(IO.scala:34) // at chisel3.experimental.BaseModule.IO(ModuleImpl.scala:863) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:367) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62$$anonfun$apply$51.apply(cookbook.md:367) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$$anonfun$59$MisusedFunctionArguments$1$$anonfun$62.apply(cookbook.md:367) // 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:367) // at repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:369) // at repl.MdocSession$MdocApp17$$anonfun$59$$anonfun$apply$55.apply(cookbook.md:369) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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.
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:441) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:441) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md:441) // 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:441) // at repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:446) // at repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:446) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
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:441) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74$$anonfun$apply$63.apply(cookbook.md:441) // at chisel3.experimental.prefix$.apply(prefix.scala:50) // at repl.MdocSession$MdocApp17$$anonfun$70$NewModule$1$$anonfun$74.apply(cookbook.md:441) // 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:441) // at repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:446) // at repl.MdocSession$MdocApp17$$anonfun$70$$anonfun$apply$67.apply(cookbook.md:446) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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:
importchisel3.reflect.DataMirror importchisel3.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) }
importchisel3._ 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:583) // at repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:591) // at repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:591) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
getVerilogString(new Foo) // chisel3.package$ChiselException: Cannot reassign to read-only Foo.?: OpResult[Bool] // at ... () // at repl.MdocSession$MdocApp26$Foo.<init>(cookbook.md:583) // at repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:591) // at repl.MdocSession$MdocApp26$$anonfun$104$$anonfun$apply$90.apply(cookbook.md:591) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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:
@@ -209,7 +209,7 @@
importchisel3._ importchisel3.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 }
-
getVerilogString(new BadRegConnect) // circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: /home/runner/.cache/llvm-firtool/1.86.0/bin/firtool returned a non-zero exit code. Note that this version of Chisel (7.0.0-M2+115-fc4de1f3-SNAPSHOT) was published against firtool version 1.86.0. // ------------------------------------------------------------------------------ // ExitCode: // 1 // STDOUT: // // STDERR: // cookbook.md:1013: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:1013: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>> // // ------------------------------------------------------------------------------
+
getVerilogString(new BadRegConnect) // circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: /home/runner/.cache/llvm-firtool/1.86.0/bin/firtool returned a non-zero exit code. Note that this version of Chisel (7.0.0-M2+116-15a25fff-SNAPSHOT) was published against firtool version 1.86.0. // ------------------------------------------------------------------------------ // ExitCode: // 1 // STDOUT: // // STDERR: // cookbook.md:1013: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:1013: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.
diff --git a/docs/cookbooks/dataview.html b/docs/cookbooks/dataview.html
index 743254168a..0921f6722e 100644
--- a/docs/cookbooks/dataview.html
+++ b/docs/cookbooks/dataview.html
@@ -4,7 +4,7 @@
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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
// 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
// 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
// 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
// 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
// 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
//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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
// 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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:
importchisel3.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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
// 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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) })
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 @62f84d3d) // 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(DataImpl.scala:73) // at chisel3.Output$.apply(DataImpl.scala:317) // 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(ModuleImpl.scala:859) // 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
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 @5e30c611) // 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(DataImpl.scala:73) // at chisel3.Output$.apply(DataImpl.scala:317) // 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(ModuleImpl.scala:863) // 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 chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // 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
diff --git a/docs/explanations/combinational-circuits.html b/docs/explanations/combinational-circuits.html
index 4e2eca5edf..8c0e005ee6 100644
--- a/docs/explanations/combinational-circuits.html
+++ b/docs/explanations/combinational-circuits.html
@@ -4,7 +4,7 @@
importchisel3._ importchisel3.util.DecoupledIO class Wrapper extends Module{ val io = IO(new Bundle { val in = Flipped(DecoupledIO(UInt(8.W))) val out = DecoupledIO(UInt(8.W)) }) val p = Module(new PipelineStage) val c = Module(new PipelineStage) // connect producer to I/O p.io.a := io.in // connect producer to consumer c.io.a := p.io.b // connect consumer to I/O io.out := c.io.b } class PipelineStage extends Module{ val io = IO(new Bundle{ val a = Flipped(DecoupledIO(UInt(8.W))) val b = DecoupledIO(UInt(8.W)) }) io.a := io.b }
Below we can see the resulting error message for this example:
-
circt.stage.ChiselStage.emitSystemVerilog(new Wrapper) // chisel3.package$ChiselException: Connection between sink (PipelineStage.io.a: IO[DecoupledIO]) and source (PipelineStage.io.b: IO[DecoupledIO]) failed @: .bitsio.a.bits in PipelineStage cannot be written from module PipelineStage. // at ... () // at repl.MdocSession$MdocApp3$PipelineStage.<init>(connection-operators.md:124) // at repl.MdocSession$MdocApp3$Wrapper$$anonfun$30$$anonfun$apply$20.apply(connection-operators.md:108) // at repl.MdocSession$MdocApp3$Wrapper$$anonfun$30$$anonfun$apply$20.apply(connection-operators.md:108) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at repl.MdocSession$MdocApp3$Wrapper$$anonfun$30.apply(connection-operators.md:108) // at repl.MdocSession$MdocApp3$Wrapper$$anonfun$30.apply(connection-operators.md:108) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp3$Wrapper.<init>(connection-operators.md:108) // at repl.MdocSession$MdocApp3$$anonfun$39$$anonfun$apply$25.apply(connection-operators.md:132) // at repl.MdocSession$MdocApp3$$anonfun$39$$anonfun$apply$25.apply(connection-operators.md:132) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
circt.stage.ChiselStage.emitSystemVerilog(new Wrapper) // chisel3.package$ChiselException: Connection between sink (PipelineStage.io.a: IO[DecoupledIO]) and source (PipelineStage.io.b: IO[DecoupledIO]) failed @: .bitsio.a.bits in PipelineStage cannot be written from module PipelineStage. // at ... () // at repl.MdocSession$MdocApp3$PipelineStage.<init>(connection-operators.md:124) // at repl.MdocSession$MdocApp3$Wrapper$$anonfun$30$$anonfun$apply$20.apply(connection-operators.md:108) // at repl.MdocSession$MdocApp3$Wrapper$$anonfun$30$$anonfun$apply$20.apply(connection-operators.md:108) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at repl.MdocSession$MdocApp3$Wrapper$$anonfun$30.apply(connection-operators.md:108) // at repl.MdocSession$MdocApp3$Wrapper$$anonfun$30.apply(connection-operators.md:108) // at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33) // at repl.MdocSession$MdocApp3$Wrapper.<init>(connection-operators.md:108) // at repl.MdocSession$MdocApp3$$anonfun$39$$anonfun$apply$25.apply(connection-operators.md:132) // at repl.MdocSession$MdocApp3$$anonfun$39$$anonfun$apply$25.apply(connection-operators.md:132) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
The := operator goes field-by-field on the LHS and attempts to connect it to the same-named signal from the RHS. If something on the LHS is actually an Input, or the corresponding signal on the RHS is an Output, you will get an error as shown above.
Concept 3: Always Use := to assign DontCare to Wires​
importchisel3._ importchisel3.util.DecoupledIO class MockDecoupledIO extends Bundle { val valid = Output(Bool()) val ready = Input(Bool()) //val bits = Output(UInt(8.W)) } class Wrapper extends Module{ val io = IO(new Bundle { val in = Flipped(new MockDecoupledIO()) val out =new MockDecoupledIO() }) val p = Module(new PipelineStage) val c = Module(new PipelineStage) // connect producer to I/O p.io.a <> io.in // connect producer to consumer c.io.a <> p.io.b // connect consumer to I/O io.out <> c.io.b } class PipelineStage extends Module{ val io = IO(new Bundle{ val a = Flipped(DecoupledIO(UInt(8.W))) val b = DecoupledIO(UInt(8.W)) }) io.a <> io.b }
Below we can see the resulting error for this example:
-
circt.stage.ChiselStage.emitSystemVerilog(new Wrapper) // chisel3.package$ChiselException: Connection between left (PipelineStage.io.a: IO[DecoupledIO]) and source (Wrapper.io.in: IO[MockDecoupledIO]) failed @.bits: Right Record missing field (bits). // at ... () // at repl.MdocSession$MdocApp12$Wrapper.<init>(connection-operators.md:357) // at repl.MdocSession$MdocApp12$$anonfun$119$$anonfun$apply$79.apply(connection-operators.md:378) // at repl.MdocSession$MdocApp12$$anonfun$119$$anonfun$apply$79.apply(connection-operators.md:378) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
circt.stage.ChiselStage.emitSystemVerilog(new Wrapper) // chisel3.package$ChiselException: Connection between left (PipelineStage.io.a: IO[DecoupledIO]) and source (Wrapper.io.in: IO[MockDecoupledIO]) failed @.bits: Right Record missing field (bits). // at ... () // at repl.MdocSession$MdocApp12$Wrapper.<init>(connection-operators.md:357) // at repl.MdocSession$MdocApp12$$anonfun$119$$anonfun$apply$79.apply(connection-operators.md:378) // at repl.MdocSession$MdocApp12$$anonfun$119$$anonfun$apply$79.apply(connection-operators.md:378) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
This one fails because there is a field bits missing.
For :=, the Scala types do not need to match but all the signals on the LHS must be provided by the RHS or you will get a Chisel elaboration error. There may be additional signals on the RHS, these will be ignored. For <>, the Scala types do not need to match, but all signals must match exactly between LHS and RHS. In both cases, the order of the fields does not matter.
class BundleA extends Bundle { val foo = UInt(8.W) val bar = UInt(8.W) } class BundleB extends Bundle { val fizz = UInt(8.W) }
-
// We forgot BundleA.foo in the mapping! implicitval myView = DataView[BundleA, BundleB](_ =>new BundleB, _.bar -> _.fizz) class BadMapping extends Module { val in = IO(Input(new BundleA)) val out = IO(Output(new BundleB)) out := in.viewAs[BundleB] } // We must run Chisel to see the error getVerilogString(new BadMapping) // chisel3.experimental.dataview.package$InvalidViewException: Viewing BadMapping.in: IO[BundleA] as BundleB is non-Total! // Target field '_.foo' is missing. // DataView used is DataView(defined @[dataview.md:228:49]). // If the view *should* be non-total, try a 'PartialDataView'. // at ... () // at repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1$$anonfun$60.apply(dataview.md:232) // at repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1$$anonfun$60.apply(dataview.md:232) // at chisel3.DataImpl.$anonfun$$colon$eq$1(DataImpl.scala:807) // at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18) // at chisel3.experimental.prefix$.apply(prefix.scala:33) // at chisel3.DataImpl.$colon$eq(DataImpl.scala:807) // at chisel3.DataImpl.$colon$eq$(DataImpl.scala:805) // at chisel3.Data.$colon$eq(Data.scala:31) // at repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1.<init>(dataview.md:232) // at repl.MdocSession$MdocApp6$$anonfun$55$$anonfun$apply$67.apply(dataview.md:234) // at repl.MdocSession$MdocApp6$$anonfun$55$$anonfun$apply$67.apply(dataview.md:234) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
// We forgot BundleA.foo in the mapping! implicitval myView = DataView[BundleA, BundleB](_ =>new BundleB, _.bar -> _.fizz) class BadMapping extends Module { val in = IO(Input(new BundleA)) val out = IO(Output(new BundleB)) out := in.viewAs[BundleB] } // We must run Chisel to see the error getVerilogString(new BadMapping) // chisel3.experimental.dataview.package$InvalidViewException: Viewing BadMapping.in: IO[BundleA] as BundleB is non-Total! // Target field '_.foo' is missing. // DataView used is DataView(defined @[dataview.md:228:49]). // If the view *should* be non-total, try a 'PartialDataView'. // at ... () // at repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1$$anonfun$60.apply(dataview.md:232) // at repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1$$anonfun$60.apply(dataview.md:232) // at chisel3.DataImpl.$anonfun$$colon$eq$1(DataImpl.scala:807) // at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18) // at chisel3.experimental.prefix$.apply(prefix.scala:33) // at chisel3.DataImpl.$colon$eq(DataImpl.scala:807) // at chisel3.DataImpl.$colon$eq$(DataImpl.scala:805) // at chisel3.Data.$colon$eq(Data.scala:31) // at repl.MdocSession$MdocApp6$$anonfun$55$BadMapping$1.<init>(dataview.md:232) // at repl.MdocSession$MdocApp6$$anonfun$55$$anonfun$apply$67.apply(dataview.md:234) // at repl.MdocSession$MdocApp6$$anonfun$55$$anonfun$apply$67.apply(dataview.md:234) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
As that error suggests, if we want the view to be non-total, we can use a PartialDataView:
// A PartialDataView does not have to be total for the Target implicitval myView = PartialDataView[BundleA, BundleB](_ =>new BundleB, _.bar -> _.fizz) // myView: DataView[BundleA, BundleB] = PartialDataView(defined @[dataview.md:243:56]) class PartialDataViewModule extends Module { val in = IO(Input(new BundleA)) val out = IO(Output(new BundleB)) out := in.viewAs[BundleB] }
The bidirectional bulk connection operator <> connects leaf ports of the same name to each other. The Scala types of the Bundles are not required to match. If one named signal is missing from either side, Chisel will give an error such as in the following example:
class NotReallyAFilterIO extends Bundle { val x = Flipped(new PLink) val y =new PLink val z = Output(new Bool()) } class Block2 extends Module { val io1 = IO(new FilterIO) val io2 = IO(Flipped(new NotReallyAFilterIO)) io1 <> io2 }
Below we can see the resulting error for this example:
-
emitSystemVerilog(new Block2) // chisel3.package$ChiselException: Connection between left (Block2.io1: IO[FilterIO]) and source (Block2.io2: IO[NotReallyAFilterIO]) failed @.z: Left Record missing field (z). // at ... () // at repl.MdocSession$MdocApp$Block2.<init>(interfaces-and-connections.md:89) // at repl.MdocSession$MdocApp$$anonfun$22$$anonfun$apply$20.apply(interfaces-and-connections.md:97) // at repl.MdocSession$MdocApp$$anonfun$22$$anonfun$apply$20.apply(interfaces-and-connections.md:97) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
emitSystemVerilog(new Block2) // chisel3.package$ChiselException: Connection between left (Block2.io1: IO[FilterIO]) and source (Block2.io2: IO[NotReallyAFilterIO]) failed @.z: Left Record missing field (z). // at ... () // at repl.MdocSession$MdocApp$Block2.<init>(interfaces-and-connections.md:89) // at repl.MdocSession$MdocApp$$anonfun$22$$anonfun$apply$20.apply(interfaces-and-connections.md:97) // at repl.MdocSession$MdocApp$$anonfun$22$$anonfun$apply$20.apply(interfaces-and-connections.md:97) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
Bidirectional connections should only be used with directioned elements (like IOs), e.g. connecting two wires isn't supported since Chisel can't necessarily figure out the directions automatically.
For example, putting two temporary wires and connecting them here will not work, even though the directions could be known from the endpoints:
class BlockWithTemporaryWires extends Module { val io = IO(new FilterIO) val f1 = Module(new Filter) val f2 = Module(new Filter) f1.io.x <> io.x val tmp1 = Wire(new FilterIO) val tmp2 = Wire(new FilterIO) f1.io.y <> tmp1 tmp1 <> tmp2 tmp2 <> f2.io.x f2.io.y <> io.y }
Below we can see the resulting error for this example:
-
emitSystemVerilog(new BlockWithTemporaryWires) // chisel3.package$ChiselException: Connection between left (Filter.io.y: IO[PLink]) and source (BlockWithTemporaryWires.tmp1: Wire[FilterIO]) failed @.y: Left Record missing field (y). // at ... () // at repl.MdocSession$MdocApp$BlockWithTemporaryWires.<init>(interfaces-and-connections.md:113) // at repl.MdocSession$MdocApp$$anonfun$33$$anonfun$apply$29.apply(interfaces-and-connections.md:124) // at repl.MdocSession$MdocApp$$anonfun$33$$anonfun$apply$29.apply(interfaces-and-connections.md:124) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:82) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
+
emitSystemVerilog(new BlockWithTemporaryWires) // chisel3.package$ChiselException: Connection between left (Filter.io.y: IO[PLink]) and source (BlockWithTemporaryWires.tmp1: Wire[FilterIO]) failed @.y: Left Record missing field (y). // at ... () // at repl.MdocSession$MdocApp$BlockWithTemporaryWires.<init>(interfaces-and-connections.md:113) // at repl.MdocSession$MdocApp$$anonfun$33$$anonfun$apply$29.apply(interfaces-and-connections.md:124) // at repl.MdocSession$MdocApp$$anonfun$33$$anonfun$apply$29.apply(interfaces-and-connections.md:124) // at chisel3.ObjectModuleImpl.evaluate(ModuleImpl.scala:84) // at chisel3.ObjectModuleImpl.evaluate$(ModuleImpl.scala:52) // at chisel3.Module$.evaluate(Module.scala:10) // at chisel3.ObjectModuleImpl._applyImpl(ModuleImpl.scala:25) // at chisel3.ObjectModuleImpl._applyImpl$(ModuleImpl.scala:23) // at chisel3.Module$._applyImpl(Module.scala:10) // at chisel3.Module$.do_apply(Module.scala:22) // at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:54) // at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1081) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at chisel3.internal.Builder$.buildImpl(Builder.scala:1071) // at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1063) // at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148) // at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59) // at logger.Logger$.makeScope(Logger.scala:146) // at logger.Logger$.makeScope(Logger.scala:133) // at ... () // at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
NOTE: When using Chisel._ (compatibility mode) instead of chisel3._, the := operator works in a bidirectional fashion similar to <>, but not exactly the same.
The standard ready-valid interface (ReadyValidIO / Decoupled)​