diff --git a/404.html b/404.html index e6debc7c80e..d3840146755 100644 --- a/404.html +++ b/404.html @@ -9,7 +9,7 @@ - +
diff --git a/api.html b/api.html index 390a92d93e5..fa0edb3cb57 100644 --- a/api.html +++ b/api.html @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@Please see the page about Versioning for more information about major and minor versioning and binary compatibility.
Module(...)
?",id:"why-do-i-have-to-wrap-module-instantiations-in-module",level:3},{value:"Why Chisel?",id:"why-chisel",level:3},{value:"Does Chisel support X and Z logic values",id:"does-chisel-support-x-and-z-logic-values",level:3},{value:"Get me Verilog",id:"get-me-verilog",level:3},{value:"Get me FIRRTL",id:"get-me-firrtl",level:3},{value:"Why doesn't Chisel tell me which wires aren't connected?",id:"why-doesnt-chisel-tell-me-which-wires-arent-connected",level:3},{value:"What does Reference ... is not fully initialized.
mean?",id:"what-does-reference--is-not-fully-initialized-mean",level:3},{value:"Can I specify behavior before and after generated initial blocks?",id:"can-i-specify-behavior-before-and-after-generated-initial-blocks",level:3}];function c(e){const i={a:"a",code:"code",em:"em",h1:"h1",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(i.header,{children:(0,l.jsx)(i.h1,{id:"frequently-asked-questions",children:"Frequently Asked Questions"})}),"\n",(0,l.jsxs)(i.ul,{children:["\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#where-should-i-start-if-i-want-to-learn-chisel",children:"Where should I start if I want to learn Chisel?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#how-do-i-do--eg-like-that-in-verilog-in-chisel",children:"How do I ... in Chisel?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#what-versions-of-the-various-projects-work-together",children:"What versions of the various projects work together?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#how-can-i-contribute-to-chisel",children:"How can I contribute to Chisel?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#why-decoupledio-instead-of-readyvalidio",children:"Why DecoupledIO instead of ReadyValidIO?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsxs)(i.a,{href:"#why-do-i-have-to-wrap-module-instantiations-in-module",children:["Why do I have to wrap module instantiations in ",(0,l.jsx)(i.code,{children:"Module(...)"}),"?"]})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#why-chisel",children:"Why Chisel?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#does-chisel-support-x-and-z-logic-values",children:"Does Chisel support X and Z logic values?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#get-me-verilog",children:"I just want some Verilog; what do I do?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#get-me-firrtl",children:"I just want some FIRRTL; what do I do?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#why-doesnt-chisel-tell-me-which-wires-arent-connected",children:"Why doesn't Chisel tell me which wires aren't connected?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsxs)(i.a,{href:"#what-does-reference--is-not-fully-initialized-mean",children:["What does ",(0,l.jsx)(i.code,{children:"Reference ... is not fully initialized."})," mean?"]})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#can-i-specify-behavior-before-and-after-generated-initial-blocks",children:"Can I specify behavior before and after generated initial blocks?"})}),"\n"]}),"\n",(0,l.jsx)(i.h3,{id:"where-should-i-start-if-i-want-to-learn-chisel",children:"Where should I start if I want to learn Chisel?"}),"\n",(0,l.jsxs)(i.p,{children:["We recommend the ",(0,l.jsx)(i.a,{href:"https://github.com/freechipsproject/chisel-bootcamp",children:"Chisel Bootcamp"})," for getting started with Chisel."]}),"\n",(0,l.jsx)(i.h3,{id:"how-do-i-do--eg-like-that-in-verilog-in-chisel",children:"How do I do ... (e.g. like that in Verilog) in Chisel?"}),"\n",(0,l.jsxs)(i.p,{children:["See the ",(0,l.jsx)(i.a,{href:"../cookbooks/cookbook",children:"cookbooks"}),"."]}),"\n",(0,l.jsx)(i.h3,{id:"what-versions-of-the-various-projects-work-together",children:"What versions of the various projects work together?"}),"\n",(0,l.jsxs)(i.p,{children:["See ",(0,l.jsx)(i.a,{href:"../appendix/versioning",children:"Chisel Project Versioning"}),"."]}),"\n",(0,l.jsx)(i.h3,{id:"how-can-i-contribute-to-chisel",children:"How can I contribute to Chisel?"}),"\n",(0,l.jsxs)(i.p,{children:["Check out the ",(0,l.jsx)(i.a,{href:"https://github.com/chipsalliance/chisel3#contributor-documentation",children:"Contributor Documentation"})," in the chisel3 repository."]}),"\n",(0,l.jsx)(i.h3,{id:"why-decoupledio-instead-of-readyvalidio",children:"Why DecoupledIO instead of ReadyValidIO?"}),"\n",(0,l.jsx)(i.p,{children:"There are multiple kinds of Ready/Valid interfaces that impose varying restrictions on the producers and consumers. Chisel currently provides the following:"}),"\n",(0,l.jsxs)(i.ul,{children:["\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://chisel.eecs.berkeley.edu/api/index.html#chisel3.util.DecoupledIO",children:"DecoupledIO"})," - No guarantees"]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://chisel.eecs.berkeley.edu/api/index.html#chisel3.util.IrrevocableIO",children:"IrrevocableIO"})," - Producer promises to not change the value of 'bits' after a cycle where 'valid' is high and 'ready' is low. Additionally, once 'valid' is raised it will never be lowered until after 'ready' has also been raised."]}),"\n"]}),"\n",(0,l.jsxs)(i.h3,{id:"why-do-i-have-to-wrap-module-instantiations-in-module",children:["Why do I have to wrap module instantiations in ",(0,l.jsx)(i.code,{children:"Module(...)"}),"?"]}),"\n",(0,l.jsx)(i.p,{children:"In short: Limitations of Scala"}),"\n",(0,l.jsxs)(i.p,{children:["Chisel Modules are written by defining a ",(0,l.jsx)(i.a,{href:"http://docs.scala-lang.org/tutorials/tour/classes.html",children:"Scala class"})," and implementing its constructor. As elaboration runs, Chisel constructs a hardware AST from these Modules. The compiler needs hooks to run before and after the actual construction of the Module object. In Scala, superclasses are fully initialized before subclasses, so by extending Module, Chisel has the ability to run some initialization code before the user's Module is constructed. However, there is no such hook to run after the Module object is initialized. By wrapping Module instantiations in the Module object's apply method (ie. ",(0,l.jsx)(i.code,{children:"Module(...)"}),"), Chisel is able to perform post-initialization actions. There is a ",(0,l.jsx)(i.a,{href:"https://issues.scala-lang.org/browse/SI-4330",children:"proposed solution"}),", so eventually this requirement will be lifted, but for now, wrap those Modules!"]}),"\n",(0,l.jsx)(i.h3,{id:"why-chisel",children:"Why Chisel?"}),"\n",(0,l.jsxs)(i.p,{children:["Please see ",(0,l.jsx)(i.a,{href:"../explanations/motivation",children:"Chisel Motivation"})]}),"\n",(0,l.jsx)(i.h3,{id:"does-chisel-support-x-and-z-logic-values",children:"Does Chisel support X and Z logic values"}),"\n",(0,l.jsxs)(i.p,{children:["Chisel does not directly support Verilog logic values ",(0,l.jsx)(i.code,{children:"x"})," ",(0,l.jsx)(i.em,{children:"unknown"})," and ",(0,l.jsx)(i.code,{children:"z"})," ",(0,l.jsx)(i.em,{children:"high-impedance"}),". There are a number of reasons to want to avoid these values. See:",(0,l.jsx)(i.a,{href:"http://infocenter.arm.com/help/topic/com.arm.doc.arp0009a/Verilog_X_Bugs.pdf",children:"The Dangers of Living With An X"})," and ",(0,l.jsx)(i.a,{href:"http://ieeexplore.ieee.org/document/7827620/",children:"Malicious LUT: A stealthy FPGA Trojan injected and triggered by the design flow"}),". Chisel has its own eco-system of unit and functional testers that limit the need for ",(0,l.jsx)(i.code,{children:"x"})," and ",(0,l.jsx)(i.code,{children:"z"})," and their omission simplify language implementation, design, and testing. The circuits created by chisel do not preclude developers from using ",(0,l.jsx)(i.code,{children:"x"})," and ",(0,l.jsx)(i.code,{children:"z"})," in downstream toolchains as they see fit."]}),"\n",(0,l.jsx)(i.h3,{id:"get-me-verilog",children:"Get me Verilog"}),"\n",(0,l.jsx)(i.p,{children:"I wrote a module and I want to see the Verilog; what do I do?"}),"\n",(0,l.jsx)(i.p,{children:"Here's a simple hello world module in a file HelloWorld.scala."}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-scala",children:"package intro\n"})}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-scala",children:'import chisel3._\nclass HelloWorld extends Module {\n val io = IO(new Bundle{})\n printf("hello world\\n")\n}\n'})}),"\n",(0,l.jsx)(i.p,{children:"Add the following"}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-scala",children:"import circt.stage.ChiselStage\nobject VerilogMain extends App {\n ChiselStage.emitSystemVerilog(new HelloWorld)\n}\n"})}),"\n",(0,l.jsx)(i.p,{children:"Now you can get some Verilog. Start sbt:"}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{children:"bash> sbt\n> run-main intro.VerilogMain\n[info] Running intro.VerilogMain\n[info] [0.004] Elaborating design...\n[info] [0.100] Done elaborating.\n[success] Total time: 1 s, completed Jan 12, 2017 6:24:03 PM\n"})}),"\n",(0,l.jsx)(i.p,{children:"or as a one-liner:"}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{children:"bash> sbt 'runMain intro.VerilogMain'\n"})}),"\n",(0,l.jsx)(i.p,{children:"After either of the above there will be a HelloWorld.v file in the current directory:"}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-verilog",children:'// Generated by CIRCT firtool-1.99.2\nmodule HelloWorld(\t// faqs.md:11:7\n input clock,\t// faqs.md:11:7\n reset\t// faqs.md:11:7\n);\n\nendmodule\n\n\n// ----- 8< ----- FILE "verification/cover/layers-HelloWorld-Verification-Cover.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\n`include "verification/layers-HelloWorld-Verification.sv"\n`ifndef layers_HelloWorld_Verification_Cover\n`define layers_HelloWorld_Verification_Cover\t// Module(...)
?",id:"why-do-i-have-to-wrap-module-instantiations-in-module",level:3},{value:"Why Chisel?",id:"why-chisel",level:3},{value:"Does Chisel support X and Z logic values",id:"does-chisel-support-x-and-z-logic-values",level:3},{value:"Get me Verilog",id:"get-me-verilog",level:3},{value:"Get me FIRRTL",id:"get-me-firrtl",level:3},{value:"Why doesn't Chisel tell me which wires aren't connected?",id:"why-doesnt-chisel-tell-me-which-wires-arent-connected",level:3},{value:"What does Reference ... is not fully initialized.
mean?",id:"what-does-reference--is-not-fully-initialized-mean",level:3},{value:"Can I specify behavior before and after generated initial blocks?",id:"can-i-specify-behavior-before-and-after-generated-initial-blocks",level:3}];function c(e){const i={a:"a",code:"code",em:"em",h1:"h1",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(i.header,{children:(0,l.jsx)(i.h1,{id:"frequently-asked-questions",children:"Frequently Asked Questions"})}),"\n",(0,l.jsxs)(i.ul,{children:["\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#where-should-i-start-if-i-want-to-learn-chisel",children:"Where should I start if I want to learn Chisel?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#how-do-i-do--eg-like-that-in-verilog-in-chisel",children:"How do I ... in Chisel?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#what-versions-of-the-various-projects-work-together",children:"What versions of the various projects work together?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#how-can-i-contribute-to-chisel",children:"How can I contribute to Chisel?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#why-decoupledio-instead-of-readyvalidio",children:"Why DecoupledIO instead of ReadyValidIO?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsxs)(i.a,{href:"#why-do-i-have-to-wrap-module-instantiations-in-module",children:["Why do I have to wrap module instantiations in ",(0,l.jsx)(i.code,{children:"Module(...)"}),"?"]})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#why-chisel",children:"Why Chisel?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#does-chisel-support-x-and-z-logic-values",children:"Does Chisel support X and Z logic values?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#get-me-verilog",children:"I just want some Verilog; what do I do?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#get-me-firrtl",children:"I just want some FIRRTL; what do I do?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#why-doesnt-chisel-tell-me-which-wires-arent-connected",children:"Why doesn't Chisel tell me which wires aren't connected?"})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsxs)(i.a,{href:"#what-does-reference--is-not-fully-initialized-mean",children:["What does ",(0,l.jsx)(i.code,{children:"Reference ... is not fully initialized."})," mean?"]})}),"\n",(0,l.jsx)(i.li,{children:(0,l.jsx)(i.a,{href:"#can-i-specify-behavior-before-and-after-generated-initial-blocks",children:"Can I specify behavior before and after generated initial blocks?"})}),"\n"]}),"\n",(0,l.jsx)(i.h3,{id:"where-should-i-start-if-i-want-to-learn-chisel",children:"Where should I start if I want to learn Chisel?"}),"\n",(0,l.jsxs)(i.p,{children:["We recommend the ",(0,l.jsx)(i.a,{href:"https://github.com/freechipsproject/chisel-bootcamp",children:"Chisel Bootcamp"})," for getting started with Chisel."]}),"\n",(0,l.jsx)(i.h3,{id:"how-do-i-do--eg-like-that-in-verilog-in-chisel",children:"How do I do ... (e.g. like that in Verilog) in Chisel?"}),"\n",(0,l.jsxs)(i.p,{children:["See the ",(0,l.jsx)(i.a,{href:"../cookbooks/cookbook",children:"cookbooks"}),"."]}),"\n",(0,l.jsx)(i.h3,{id:"what-versions-of-the-various-projects-work-together",children:"What versions of the various projects work together?"}),"\n",(0,l.jsxs)(i.p,{children:["See ",(0,l.jsx)(i.a,{href:"../appendix/versioning",children:"Chisel Project Versioning"}),"."]}),"\n",(0,l.jsx)(i.h3,{id:"how-can-i-contribute-to-chisel",children:"How can I contribute to Chisel?"}),"\n",(0,l.jsxs)(i.p,{children:["Check out the ",(0,l.jsx)(i.a,{href:"https://github.com/chipsalliance/chisel3#contributor-documentation",children:"Contributor Documentation"})," in the chisel3 repository."]}),"\n",(0,l.jsx)(i.h3,{id:"why-decoupledio-instead-of-readyvalidio",children:"Why DecoupledIO instead of ReadyValidIO?"}),"\n",(0,l.jsx)(i.p,{children:"There are multiple kinds of Ready/Valid interfaces that impose varying restrictions on the producers and consumers. Chisel currently provides the following:"}),"\n",(0,l.jsxs)(i.ul,{children:["\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://chisel.eecs.berkeley.edu/api/index.html#chisel3.util.DecoupledIO",children:"DecoupledIO"})," - No guarantees"]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://chisel.eecs.berkeley.edu/api/index.html#chisel3.util.IrrevocableIO",children:"IrrevocableIO"})," - Producer promises to not change the value of 'bits' after a cycle where 'valid' is high and 'ready' is low. Additionally, once 'valid' is raised it will never be lowered until after 'ready' has also been raised."]}),"\n"]}),"\n",(0,l.jsxs)(i.h3,{id:"why-do-i-have-to-wrap-module-instantiations-in-module",children:["Why do I have to wrap module instantiations in ",(0,l.jsx)(i.code,{children:"Module(...)"}),"?"]}),"\n",(0,l.jsx)(i.p,{children:"In short: Limitations of Scala"}),"\n",(0,l.jsxs)(i.p,{children:["Chisel Modules are written by defining a ",(0,l.jsx)(i.a,{href:"http://docs.scala-lang.org/tutorials/tour/classes.html",children:"Scala class"})," and implementing its constructor. As elaboration runs, Chisel constructs a hardware AST from these Modules. The compiler needs hooks to run before and after the actual construction of the Module object. In Scala, superclasses are fully initialized before subclasses, so by extending Module, Chisel has the ability to run some initialization code before the user's Module is constructed. However, there is no such hook to run after the Module object is initialized. By wrapping Module instantiations in the Module object's apply method (ie. ",(0,l.jsx)(i.code,{children:"Module(...)"}),"), Chisel is able to perform post-initialization actions. There is a ",(0,l.jsx)(i.a,{href:"https://issues.scala-lang.org/browse/SI-4330",children:"proposed solution"}),", so eventually this requirement will be lifted, but for now, wrap those Modules!"]}),"\n",(0,l.jsx)(i.h3,{id:"why-chisel",children:"Why Chisel?"}),"\n",(0,l.jsxs)(i.p,{children:["Please see ",(0,l.jsx)(i.a,{href:"../explanations/motivation",children:"Chisel Motivation"})]}),"\n",(0,l.jsx)(i.h3,{id:"does-chisel-support-x-and-z-logic-values",children:"Does Chisel support X and Z logic values"}),"\n",(0,l.jsxs)(i.p,{children:["Chisel does not directly support Verilog logic values ",(0,l.jsx)(i.code,{children:"x"})," ",(0,l.jsx)(i.em,{children:"unknown"})," and ",(0,l.jsx)(i.code,{children:"z"})," ",(0,l.jsx)(i.em,{children:"high-impedance"}),". There are a number of reasons to want to avoid these values. See:",(0,l.jsx)(i.a,{href:"http://infocenter.arm.com/help/topic/com.arm.doc.arp0009a/Verilog_X_Bugs.pdf",children:"The Dangers of Living With An X"})," and ",(0,l.jsx)(i.a,{href:"http://ieeexplore.ieee.org/document/7827620/",children:"Malicious LUT: A stealthy FPGA Trojan injected and triggered by the design flow"}),". Chisel has its own eco-system of unit and functional testers that limit the need for ",(0,l.jsx)(i.code,{children:"x"})," and ",(0,l.jsx)(i.code,{children:"z"})," and their omission simplify language implementation, design, and testing. The circuits created by chisel do not preclude developers from using ",(0,l.jsx)(i.code,{children:"x"})," and ",(0,l.jsx)(i.code,{children:"z"})," in downstream toolchains as they see fit."]}),"\n",(0,l.jsx)(i.h3,{id:"get-me-verilog",children:"Get me Verilog"}),"\n",(0,l.jsx)(i.p,{children:"I wrote a module and I want to see the Verilog; what do I do?"}),"\n",(0,l.jsx)(i.p,{children:"Here's a simple hello world module in a file HelloWorld.scala."}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-scala",children:"package intro\n"})}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-scala",children:'import chisel3._\nclass HelloWorld extends Module {\n val io = IO(new Bundle{})\n printf("hello world\\n")\n}\n'})}),"\n",(0,l.jsx)(i.p,{children:"Add the following"}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-scala",children:"import circt.stage.ChiselStage\nobject VerilogMain extends App {\n ChiselStage.emitSystemVerilog(new HelloWorld)\n}\n"})}),"\n",(0,l.jsx)(i.p,{children:"Now you can get some Verilog. Start sbt:"}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{children:"bash> sbt\n> run-main intro.VerilogMain\n[info] Running intro.VerilogMain\n[info] [0.004] Elaborating design...\n[info] [0.100] Done elaborating.\n[success] Total time: 1 s, completed Jan 12, 2017 6:24:03 PM\n"})}),"\n",(0,l.jsx)(i.p,{children:"or as a one-liner:"}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{children:"bash> sbt 'runMain intro.VerilogMain'\n"})}),"\n",(0,l.jsx)(i.p,{children:"After either of the above there will be a HelloWorld.v file in the current directory:"}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-verilog",children:'// Generated by CIRCT firtool-1.100.0\nmodule HelloWorld(\t// faqs.md:11:7\n input clock,\t// faqs.md:11:7\n reset\t// faqs.md:11:7\n);\n\nendmodule\n\n\n// ----- 8< ----- FILE "verification/cover/layers-HelloWorld-Verification-Cover.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\n`include "verification/layers-HelloWorld-Verification.sv"\n`ifndef layers_HelloWorld_Verification_Cover\n`define layers_HelloWorld_Verification_Cover\t// .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..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..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:"How can I use Verilog "case equality" operators in Chisel?",id:"how-can-i-use-verilog-case-equality-operators-in-chisel",level:2},{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,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"general-cookbook",children:"General Cookbook"})}),"\n",(0,o.jsxs)(n.p,{children:["Please note that these examples make use of ",(0,o.jsx)(n.a,{href:"../explanations/printing#scala-style",children:"Chisel's scala-style printing"}),"."]}),"\n","\n",(0,o.jsx)(l.A,{toc:d}),"\n",(0,o.jsx)(n.h2,{id:"type-conversions",children:"Type Conversions"}),"\n",(0,o.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,o.jsxs)(n.p,{children:["Call ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html#asUInt:chisel3.UInt",children:(0,o.jsx)(n.code,{children:"asUInt"})})," on the ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html",children:(0,o.jsx)(n.code,{children:"Bundle"})})," instance."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsxs)(n.p,{children:["Use the ",(0,o.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,o.jsx)(n.code,{children:"asTypeOf"})})," method to reinterpret the ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html",children:(0,o.jsx)(n.code,{children:"UInt"})})," as the type of the ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html",children:(0,o.jsx)(n.code,{children:"Bundle"})}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.h3,{id:"how-can-i-tieoff-a-bundlevec-to-0",children:"How can I tieoff a Bundle/Vec to 0?"}),"\n",(0,o.jsxs)(n.p,{children:["You can use ",(0,o.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,o.jsx)(n.code,{children:"chiselTypeOf"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsxs)(n.p,{children:["Use ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/VecInit$.html",children:(0,o.jsx)(n.code,{children:"VecInit"})})," given a ",(0,o.jsx)(n.code,{children:"Seq[Bool]"})," generated using the ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html#asBools:Seq%5Bchisel3.Bool%5D",children:(0,o.jsx)(n.code,{children:"asBools"})})," method."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsxs)(n.p,{children:["Use the builtin function ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Vec.html#asUInt:chisel3.UInt",children:(0,o.jsx)(n.code,{children:"asUInt"})})]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsxs)(n.p,{children:["See the ",(0,o.jsx)(n.a,{href:"dataview#how-do-i-connect-a-subset-of-bundle-fields",children:"DataView cookbook"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"vectors-and-registers",children:"Vectors and Registers"}),"\n",(0,o.jsx)(n.h3,{id:"can-i-make-a-2d-or-3d-vector",children:"Can I make a 2D or 3D Vector?"}),"\n",(0,o.jsxs)(n.p,{children:["Yes. Using ",(0,o.jsx)(n.code,{children:"VecInit"})," you can make Vectors that hold Vectors of Chisel types. Methods ",(0,o.jsx)(n.code,{children:"fill"})," and ",(0,o.jsx)(n.code,{children:"tabulate"})," make these multi-dimensional Vectors."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.h3,{id:"how-do-i-create-a-vector-of-registers",children:"How do I create a Vector of Registers?"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Rule! Use Reg of Vec not Vec of Reg!"})}),"\n",(0,o.jsxs)(n.p,{children:["You create a ",(0,o.jsx)(n.a,{href:"#how-do-i-create-a-reg-of-type-vec",children:"Reg of type Vec"}),". Because Vecs are a ",(0,o.jsx)(n.em,{children:"type"})," (like ",(0,o.jsx)(n.code,{children:"UInt"}),", ",(0,o.jsx)(n.code,{children:"Bool"}),") rather than a ",(0,o.jsx)(n.em,{children:"value"}),", we must bind the Vec to some concrete ",(0,o.jsx)(n.em,{children:"value"}),"."]}),"\n",(0,o.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,o.jsxs)(n.p,{children:["For more information, the API Documentation for ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Vec.html",children:(0,o.jsx)(n.code,{children:"Vec"})})," provides more information."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.h3,{id:"how-do-i-partially-reset-an-aggregate-reg",children:"How do I partially reset an Aggregate Reg?"}),"\n",(0,o.jsxs)(n.p,{children:["The easiest way is to use a partially-specified ",(0,o.jsx)(n.a,{href:"../appendix/experimental-features#bundle-literals",children:"Bundle Literal"}),"\nor ",(0,o.jsx)(n.a,{href:"../appendix/experimental-features#vec-literals",children:"Vec Literal"})," to match the type of the Reg."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsx)(n.code,{children:"DontCare"})," that\nyou do not wish to be reset."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.h2,{id:"bundles",children:"Bundles"}),"\n",(0,o.jsx)(n.h3,{id:"how-do-i-deal-with-aliased-bundle-fields",children:"How do I deal with aliased Bundle fields?"}),"\n",(0,o.jsxs)(n.p,{children:["Following the ",(0,o.jsx)(n.code,{children:"gen"})," pattern when creating Bundles can result in some opaque error messages:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.pre,{children:(0,o.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..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:"How can I use Verilog "case equality" operators in Chisel?",id:"how-can-i-use-verilog-case-equality-operators-in-chisel",level:2},{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,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"general-cookbook",children:"General Cookbook"})}),"\n",(0,o.jsxs)(n.p,{children:["Please note that these examples make use of ",(0,o.jsx)(n.a,{href:"../explanations/printing#scala-style",children:"Chisel's scala-style printing"}),"."]}),"\n","\n",(0,o.jsx)(l.A,{toc:d}),"\n",(0,o.jsx)(n.h2,{id:"type-conversions",children:"Type Conversions"}),"\n",(0,o.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,o.jsxs)(n.p,{children:["Call ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html#asUInt:chisel3.UInt",children:(0,o.jsx)(n.code,{children:"asUInt"})})," on the ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html",children:(0,o.jsx)(n.code,{children:"Bundle"})})," instance."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsxs)(n.p,{children:["Use the ",(0,o.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,o.jsx)(n.code,{children:"asTypeOf"})})," method to reinterpret the ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html",children:(0,o.jsx)(n.code,{children:"UInt"})})," as the type of the ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Bundle.html",children:(0,o.jsx)(n.code,{children:"Bundle"})}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.h3,{id:"how-can-i-tieoff-a-bundlevec-to-0",children:"How can I tieoff a Bundle/Vec to 0?"}),"\n",(0,o.jsxs)(n.p,{children:["You can use ",(0,o.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,o.jsx)(n.code,{children:"chiselTypeOf"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsxs)(n.p,{children:["Use ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/VecInit$.html",children:(0,o.jsx)(n.code,{children:"VecInit"})})," given a ",(0,o.jsx)(n.code,{children:"Seq[Bool]"})," generated using the ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/UInt.html#asBools:Seq%5Bchisel3.Bool%5D",children:(0,o.jsx)(n.code,{children:"asBools"})})," method."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsxs)(n.p,{children:["Use the builtin function ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Vec.html#asUInt:chisel3.UInt",children:(0,o.jsx)(n.code,{children:"asUInt"})})]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsxs)(n.p,{children:["See the ",(0,o.jsx)(n.a,{href:"dataview#how-do-i-connect-a-subset-of-bundle-fields",children:"DataView cookbook"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"vectors-and-registers",children:"Vectors and Registers"}),"\n",(0,o.jsx)(n.h3,{id:"can-i-make-a-2d-or-3d-vector",children:"Can I make a 2D or 3D Vector?"}),"\n",(0,o.jsxs)(n.p,{children:["Yes. Using ",(0,o.jsx)(n.code,{children:"VecInit"})," you can make Vectors that hold Vectors of Chisel types. Methods ",(0,o.jsx)(n.code,{children:"fill"})," and ",(0,o.jsx)(n.code,{children:"tabulate"})," make these multi-dimensional Vectors."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.h3,{id:"how-do-i-create-a-vector-of-registers",children:"How do I create a Vector of Registers?"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Rule! Use Reg of Vec not Vec of Reg!"})}),"\n",(0,o.jsxs)(n.p,{children:["You create a ",(0,o.jsx)(n.a,{href:"#how-do-i-create-a-reg-of-type-vec",children:"Reg of type Vec"}),". Because Vecs are a ",(0,o.jsx)(n.em,{children:"type"})," (like ",(0,o.jsx)(n.code,{children:"UInt"}),", ",(0,o.jsx)(n.code,{children:"Bool"}),") rather than a ",(0,o.jsx)(n.em,{children:"value"}),", we must bind the Vec to some concrete ",(0,o.jsx)(n.em,{children:"value"}),"."]}),"\n",(0,o.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,o.jsxs)(n.p,{children:["For more information, the API Documentation for ",(0,o.jsx)(n.a,{href:"https://www.chisel-lang.org/api/latest/chisel3/Vec.html",children:(0,o.jsx)(n.code,{children:"Vec"})})," provides more information."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.h3,{id:"how-do-i-partially-reset-an-aggregate-reg",children:"How do I partially reset an Aggregate Reg?"}),"\n",(0,o.jsxs)(n.p,{children:["The easiest way is to use a partially-specified ",(0,o.jsx)(n.a,{href:"../appendix/experimental-features#bundle-literals",children:"Bundle Literal"}),"\nor ",(0,o.jsx)(n.a,{href:"../appendix/experimental-features#vec-literals",children:"Vec Literal"})," to match the type of the Reg."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.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,o.jsx)(n.code,{children:"DontCare"})," that\nyou do not wish to be reset."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.h2,{id:"bundles",children:"Bundles"}),"\n",(0,o.jsx)(n.h3,{id:"how-do-i-deal-with-aliased-bundle-fields",children:"How do I deal with aliased Bundle fields?"}),"\n",(0,o.jsxs)(n.p,{children:["Following the ",(0,o.jsx)(n.code,{children:"gen"})," pattern when creating Bundles can result in some opaque error messages:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.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,o.jsx)(n.pre,{children:(0,o.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.x
, x_1
and x_2
. How can I make them easier to understand?",id:"i-have-so-many-wires-with-the-same-name-like-x-x_1-and-x_2-how-can-i-make-them-easier-to-understand",level:3},{value:"How can I get better names for code generated by when
clauses?",id:"how-can-i-get-better-names-for-code-generated-by-when-clauses",level:3},{value:"I still see _GEN signals, can this be fixed?",id:"i-still-see-_gen-signals-can-this-be-fixed",level:3},{value:"How do I make my modules have more stable names instead of 'Module_1' and 'Module_42'?",id:"how-do-i-make-my-modules-have-more-stable-names-instead-of-module_1-and-module_42",level:3},{value:"How would I write my own typeName
for my data types?",id:"how-would-i-write-my-own-typename-for-my-data-types",level:3},{value:"I don't want to override typeName
over and over! Is there any easy way to generate a typeName
?",id:"i-dont-want-to-override-typename-over-and-over-is-there-any-easy-way-to-generate-a-typename",level:3},{value:"Can I name my bundles in FIRRTL, so I don't generate extremely long bundle types?",id:"can-i-name-my-bundles-in-firrtl-so-i-dont-generate-extremely-long-bundle-types",level:3},{value:"Why do I keep seeing _stripped suffixing everywhere in my FIRRTL? I didn't specify that in my aliasName
.",id:"why-do-i-keep-seeing-_stripped-suffixing-everywhere-in-my-firrtl-i-didnt-specify-that-in-my-aliasname",level:3},{value:"I want to add some hardware or assertions, but each time I do all the signal names get bumped!",id:"i-want-to-add-some-hardware-or-assertions-but-each-time-i-do-all-the-signal-names-get-bumped",level:3},{value:"I want to force a signal (or instance) name to something, how do I do that?",id:"i-want-to-force-a-signal-or-instance-name-to-something-how-do-i-do-that",level:3},{value:"How can I omit the prefix in certain parts of the code?",id:"how-can-i-omit-the-prefix-in-certain-parts-of-the-code",level:3},{value:"I am still not getting the name I want. For example, inlining an instance changes my name!",id:"i-am-still-not-getting-the-name-i-want-for-example-inlining-an-instance-changes-my-name",level:3}];function u(e){const n={a:"a",code:"code",em:"em",h1:"h1",h3:"h3",header:"header",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"naming-cookbook",children:"Naming Cookbook"})}),"\n","\n",(0,i.jsx)(t.A,{toc:c}),"\n",(0,i.jsx)(n.h3,{id:"i-still-have-_t-signals-can-this-be-fixed",children:"I still have _T signals, can this be fixed?"}),"\n",(0,i.jsx)(n.p,{children:"See the next answer!"}),"\n",(0,i.jsxs)(n.h3,{id:"i-have-so-many-wires-with-the-same-name-like-x-x_1-and-x_2-how-can-i-make-them-easier-to-understand",children:["I have so many wires with the same name, like ",(0,i.jsx)(n.code,{children:"x"}),", ",(0,i.jsx)(n.code,{children:"x_1"})," and ",(0,i.jsx)(n.code,{children:"x_2"}),". How can I make them easier to understand?"]}),"\n",(0,i.jsxs)(n.p,{children:["Signals with ",(0,i.jsx)(n.code,{children:"_T"})," names or names that Chisel has to uniquify\noften are intermediate values generated within loops, function calls, or ",(0,i.jsx)(n.code,{children:"when"})," predicates.\nThey can also be consumed by verification statements like ",(0,i.jsx)(n.code,{children:"assert"})," or ",(0,i.jsx)(n.code,{children:"prints"}),".\nIn these cases, the compiler plugin often can't find a good prefix for the generated\nintermediate signals and can't name them at all or has to make up a unique name for them."]}),"\n",(0,i.jsxs)(n.p,{children:["We recommend you manually insert calls to ",(0,i.jsx)(n.code,{children:"prefix"})," to clarify these cases:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'import chisel3.experimental.prefix\nclass ExamplePrefix extends Module {\n\n Seq.tabulate(2) { i =>\n Seq.tabulate(2) { j =>\n prefix(s"loop_${i}_${j}"){\n val x = WireInit((i*0x10+j).U(8.W))\n dontTouch(x)\n }\n }\n }\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule ExamplePrefix(\n input clock,\n reset\n);\n\n wire [7:0] loop_0_0_x = 8'h0;\n wire [7:0] loop_0_1_x = 8'h1;\n wire [7:0] loop_1_0_x = 8'h10;\n wire [7:0] loop_1_1_x = 8'h11;\nendmodule\n\n"})}),"\n",(0,i.jsxs)(n.h3,{id:"how-can-i-get-better-names-for-code-generated-by-when-clauses",children:["How can I get better names for code generated by ",(0,i.jsx)(n.code,{children:"when"})," clauses?"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"prefix"})," API can help with code inside ",(0,i.jsx)(n.code,{children:"when"})," clauses:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class ExampleWhenPrefix extends Module {\n\n val in = IO(Input(UInt(4.W)))\n val out = IO(Output(UInt(4.W)))\n\n out := DontCare\n\n Seq.tabulate(2) { i =>\n val j = i + 1\n prefix(s"clause_${j}") {\n when (in === j.U) {\n val foo = Reg(UInt(4.W))\n foo := in + j.U(4.W)\n out := foo\n }\n }\n }\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule ExampleWhenPrefix(\n input clock,\n reset,\n input [3:0] in,\n output [3:0] out\n);\n\n reg [3:0] clause_1_foo;\n reg [3:0] clause_2_foo;\n always @(posedge clock) begin\n clause_1_foo <= in + 4'h1;\n clause_2_foo <= in + 4'h2;\n end // always @(posedge)\n assign out = in == 4'h2 ? clause_2_foo : clause_1_foo;\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.h3,{id:"i-still-see-_gen-signals-can-this-be-fixed",children:"I still see _GEN signals, can this be fixed?"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"_GEN"})," signals are usually generated from the FIRRTL compiler, rather than the Chisel library. We are working on\nrenaming these signals with more context-dependent names, but it is a work in progress. Thanks for caring!"]}),"\n",(0,i.jsx)(n.h3,{id:"how-do-i-make-my-modules-have-more-stable-names-instead-of-module_1-and-module_42",children:"How do I make my modules have more stable names instead of 'Module_1' and 'Module_42'?"}),"\n",(0,i.jsxs)(n.p,{children:["This is an example of the module instability problem, which results from several modules all sharing the exact same name. To fix this, you must add more specificity to your ",(0,i.jsx)(n.code,{children:"Module"}),"'s name to avoid these name collisions."]}),"\n",(0,i.jsxs)(n.p,{children:["This can be done by leveraging the ",(0,i.jsx)(n.code,{children:"desiredName"})," and ",(0,i.jsx)(n.code,{children:"typeName"})," APIs.\n",(0,i.jsx)(n.code,{children:"desiredName"})," is for indicating the names of ",(0,i.jsx)(n.code,{children:"Modules"})," (e.g. influenced by the parameters passed in), and ",(0,i.jsx)(n.code,{children:"typeName"})," is useful for modules which are type-parameterized by subclasses of ",(0,i.jsx)(n.code,{children:"Data"}),". Overriding ",(0,i.jsx)(n.code,{children:"desiredName"})," can reduce or even eliminate name collisions. For instance, suppose your module looks like the following:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class MyModule[T <: Data](gen: T) extends Module {\n // ...\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["We can override ",(0,i.jsx)(n.code,{children:"desiredName"})," of the module to include the type name of the ",(0,i.jsx)(n.code,{children:"gen"})," parameter like so:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class MyModule[T <: Data](gen: T) extends Module {\n override def desiredName = s"MyModule_${gen.typeName}"\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Any instances of your ",(0,i.jsx)(n.code,{children:"MyModule"})," will now have Verilog module names containing the type parameter."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"val foo = Module(new MyModule(UInt(4.W))) // MyModule_UInt4 // MyModule_UInt4\nval bar = Module(new MyModule(Vec(3, UInt(4.W)))) // MyModule_Vec3_UInt4\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that all base Chisel util modules, like ",(0,i.jsx)(n.code,{children:"Queue"}),", already implement ",(0,i.jsx)(n.code,{children:"desiredName"})," like this:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"val fooQueue = Module(new Queue(UInt(8.W), 4)) // Verilog module would be named 'Queue4_UInt8' // Verilog module would be named 'Queue4_UInt8'\nval barQueue = Module(new Queue(SInt(12.W), 3)) // ... and 'Queue3_SInt12' // ... and 'Queue3_SInt12'\nval bazQueue = Module(new Queue(Bool(), 16)) // ... and 'Queue16_Bool'\n"})}),"\n",(0,i.jsxs)(n.h3,{id:"how-would-i-write-my-own-typename-for-my-data-types",children:["How would I write my own ",(0,i.jsx)(n.code,{children:"typeName"})," for my data types?"]}),"\n",(0,i.jsxs)(n.p,{children:["If you're using your own user-defined ",(0,i.jsx)(n.code,{children:"Bundle"}),", you can increase the specificity of its own ",(0,i.jsx)(n.code,{children:"typeName"})," by overriding it. All ",(0,i.jsx)(n.code,{children:"Data"})," types have a simple default implementation of ",(0,i.jsx)(n.code,{children:"typeName"})," (which is simply its class name), but you can override this yourself:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class MyBundle[T <: Data](gen: T, intParam: Int) extends Bundle {\n // Generate a stable typeName for this Bundle. Two 'words' are present\n // in this implementation: the bundle's name plus its integer parameter\n // (something like 'MyBundle9')\n // and the generator's typeName, which itself can be composed of 'words'\n // (something like 'Vec3_UInt4')\n override def typeName = s\"MyBundle${intParam}_${gen.typeName}\"\n\n // ...\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Now if you use your ",(0,i.jsx)(n.code,{children:"MyBundle"})," in a module like a ",(0,i.jsx)(n.code,{children:"Queue"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"val fooQueue = Module(new Queue(new MyBundle(UInt(4.W), 3), 16)) // Queue16_MyBundle3_UInt4\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The suggested pattern for ",(0,i.jsx)(n.code,{children:"typeName"}),", and subsequently ",(0,i.jsx)(n.code,{children:"desiredName"}),", is to fold single integer-like parameters with the name itself (for example, ",(0,i.jsx)(n.code,{children:"Queue4"}),", ",(0,i.jsx)(n.code,{children:"UInt3"}),", ",(0,i.jsx)(n.code,{children:"MyBundle9"}),") to form 'words' and separate these 'words' with underscores (",(0,i.jsx)(n.code,{children:"Queue4_UInt3"}),", ",(0,i.jsx)(n.code,{children:"FooBundle_BarType4"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Bundles"})," that have multiple integer arguments aren't presently addressed by any of the built-in modules, and so implementing a descriptive and sufficiently differentiable ",(0,i.jsx)(n.code,{children:"typeName"})," for such ",(0,i.jsx)(n.code,{children:"Bundles"})," is left as an exercise to the reader. However, integers should not occur with an underscore before them at the very end of the ",(0,i.jsx)(n.code,{children:"typeName"})," (e.g. ",(0,i.jsx)(n.code,{children:"MyBundle_1"}),") because this is the ",(0,i.jsx)(n.em,{children:"same"})," syntax used for duplicates, and so would cause confusion. Having to disambiguate modules all named ",(0,i.jsx)(n.code,{children:"Queue32_MyBundle_4_1"}),", ",(0,i.jsx)(n.code,{children:"Queue32_MyBundle_4_2"}),", ",(0,i.jsx)(n.code,{children:"Queue32_MyBundle_4_3"}),", and so on would be undesirable, indeed!"]}),"\n",(0,i.jsxs)(n.h3,{id:"i-dont-want-to-override-typename-over-and-over-is-there-any-easy-way-to-generate-a-typename",children:["I don't want to override ",(0,i.jsx)(n.code,{children:"typeName"})," over and over! Is there any easy way to generate a ",(0,i.jsx)(n.code,{children:"typeName"}),"?"]}),"\n",(0,i.jsxs)(n.p,{children:["Yes, with the experimental ",(0,i.jsx)(n.code,{children:"HasAutoTypename"})," trait. This trait can be mixed into your ",(0,i.jsx)(n.code,{children:"Bundle"}),"s to automatically generate a tuple-like ",(0,i.jsx)(n.code,{children:"typeName"})," for them, based on the constructor parameters of that ",(0,i.jsx)(n.code,{children:"Bundle"}),". Let's look at the previous examples:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class MyBundle[T <: Data](gen: T, intParam: Int) extends Bundle {\n override def typeName = s"MyBundle_${gen.typeName}_${intParam}"\n // ...\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'new MyBundle(UInt(8.W), 3).typeName\n// res7: String = "MyBundle_UInt<8>_3"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Auto-generated ",(0,i.jsx)(n.code,{children:"typeName"}),"s take the form of ",(0,i.jsx)(n.code,{children:"{Bundle Name}_{Parameter Value 1}_{Parameter Value 2}_{...}"}),", and so our ",(0,i.jsx)(n.code,{children:"MyBundle"})," can be equivalently expressed with:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.HasAutoTypename\nclass MyBundle[T <: Data](gen: T, intParam: Int) extends Bundle with HasAutoTypename {\n // ...\n // Note: No `override def typeName` statement here\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'new MyBundle(UInt(8.W), 3).typeName\n// res9: String = "MyBundle_UInt<8>_3"\n'})}),"\n",(0,i.jsx)(n.h3,{id:"can-i-name-my-bundles-in-firrtl-so-i-dont-generate-extremely-long-bundle-types",children:"Can I name my bundles in FIRRTL, so I don't generate extremely long bundle types?"}),"\n",(0,i.jsxs)(n.p,{children:["Yes, using the ",(0,i.jsx)(n.code,{children:"HasTypeAlias"})," trait. FIRRTL has a construct to alias a bundle type with a type alias like so:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"circuit Top :\n type MyBundle = { foo : UInt<8>, bar : UInt<1>}\n\n module Top :\n //...\n"})}),"\n",(0,i.jsxs)(n.p,{children:["These can be automatically emitted from Chisel by mixing ",(0,i.jsx)(n.code,{children:"HasTypeAlias"})," into a user-defined ",(0,i.jsx)(n.code,{children:"Record"}),", and implementing a field named ",(0,i.jsx)(n.code,{children:"aliasName"})," with a ",(0,i.jsx)(n.code,{children:"RecordAlias(...)"})," instance."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'import chisel3.experimental.{HasTypeAlias, RecordAlias}\n\nclass AliasedBundle extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("MyAliasedBundle")\n val foo = UInt(8.W)\n val bar = Bool()\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Let's see what happens when we generate FIRRTL using this ",(0,i.jsx)(n.code,{children:"Bundle"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'emitFIRRTL(new Module {\n val wire = Wire(new AliasedBundle)\n})\n// res10: String = """FIRRTL version 4.2.0\n// circuit _18_Anon :\n// type MyAliasedBundle = { foo : UInt<8>, bar : UInt<1>}\n// \n// layer Verification, bind, "verification" :\n// layer Assert, bind, "verification/assert" :\n// layer Assume, bind, "verification/assume" :\n// layer Cover, bind, "verification/cover" :\n// public module _18_Anon : @[naming.md 232:28]\n// input clock : Clock @[naming.md 232:28]\n// input reset : UInt<1> @[naming.md 232:28]\n// \n// wire wire : MyAliasedBundle @[naming.md 233:18]\n// \n// """\n'})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"HasTypeAlias"})," also supports nested bundles, too:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class Child extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("ChildBundle")\n val x = UInt(8.W)\n}\n\nclass Parent extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("ParentBundle")\n val child = new Child\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'emitFIRRTL(new Module {\n val wire = Wire(new Parent)\n})\n// res11: String = """FIRRTL version 4.2.0\n// circuit _22_Anon :\n// type ChildBundle = { x : UInt<8>}\n// type ParentBundle = { child : ChildBundle}\n// \n// layer Verification, bind, "verification" :\n// layer Assert, bind, "verification/assert" :\n// layer Assume, bind, "verification/assume" :\n// layer Cover, bind, "verification/cover" :\n// public module _22_Anon : @[naming.md 255:28]\n// input clock : Clock @[naming.md 255:28]\n// input reset : UInt<1> @[naming.md 255:28]\n// \n// wire wire : ParentBundle @[naming.md 256:18]\n// \n// """\n'})}),"\n",(0,i.jsxs)(n.h3,{id:"why-do-i-keep-seeing-_stripped-suffixing-everywhere-in-my-firrtl-i-didnt-specify-that-in-my-aliasname",children:["Why do I keep seeing _stripped suffixing everywhere in my FIRRTL? I didn't specify that in my ",(0,i.jsx)(n.code,{children:"aliasName"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["You're using an ",(0,i.jsx)(n.code,{children:"Input(...)"})," or ",(0,i.jsx)(n.code,{children:"Output(...)"})," in conjunction with an aliased ",(0,i.jsx)(n.code,{children:"Record"})," that contains a ",(0,i.jsx)(n.code,{children:"Flipped(...)"}),". These flipped values are stripped by ",(0,i.jsx)(n.code,{children:"Input"})," and ",(0,i.jsx)(n.code,{children:"Output"})," which fundamentally changes the type of the parent ",(0,i.jsx)(n.code,{children:"Record"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class StrippedBundle extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("StrippedBundle")\n val flipped = Flipped(UInt(8.W))\n val normal = UInt(8.W)\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'emitFIRRTL(new Module {\n val in = IO(Input(new StrippedBundle))\n})\n// res12: String = """FIRRTL version 4.2.0\n// circuit _26_Anon :\n// type StrippedBundle_stripped = { flipped : UInt<8>, normal : UInt<8>}\n// \n// layer Verification, bind, "verification" :\n// layer Assert, bind, "verification/assert" :\n// layer Assume, bind, "verification/assume" :\n// layer Cover, bind, "verification/cover" :\n// public module _26_Anon : @[naming.md 273:28]\n// input clock : Clock @[naming.md 273:28]\n// input reset : UInt<1> @[naming.md 273:28]\n// input in : StrippedBundle_stripped @[naming.md 274:14]\n// \n// skip\n// \n// """\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Note how the bundle type doesn't contain a ",(0,i.jsx)(n.code,{children:"flip flipped : UInt<8>"})," field, and the alias gains a ",(0,i.jsx)(n.code,{children:'"_stripped"'})," suffix! This ",(0,i.jsx)(n.code,{children:"Bundle"})," type is no longer the same as the one we wrote in Chisel, so we have to distinguish it as such."]}),"\n",(0,i.jsxs)(n.p,{children:["By default, the suffix appended to ",(0,i.jsx)(n.code,{children:"Record"})," names is ",(0,i.jsx)(n.code,{children:'"_stripped"'}),". This can be defined by users with an additional string argument passed to ",(0,i.jsx)(n.code,{children:"RecordAlias(alias, strippedSuffix)"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class CustomStrippedBundle extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("StrippedBundle", "Foo")\n val flipped = Flipped(UInt(8.W))\n val normal = UInt(8.W)\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'emitFIRRTL(new Module {\n val in = IO(Input(new CustomStrippedBundle))\n})\n// res13: String = """FIRRTL version 4.2.0\n// circuit _30_Anon :\n// type StrippedBundleFoo = { flipped : UInt<8>, normal : UInt<8>}\n// \n// layer Verification, bind, "verification" :\n// layer Assert, bind, "verification/assert" :\n// layer Assume, bind, "verification/assume" :\n// layer Cover, bind, "verification/cover" :\n// public module _30_Anon : @[naming.md 291:28]\n// input clock : Clock @[naming.md 291:28]\n// input reset : UInt<1> @[naming.md 291:28]\n// input in : StrippedBundleFoo @[naming.md 292:14]\n// \n// skip\n// \n// """\n'})}),"\n",(0,i.jsx)(n.h3,{id:"i-want-to-add-some-hardware-or-assertions-but-each-time-i-do-all-the-signal-names-get-bumped",children:"I want to add some hardware or assertions, but each time I do all the signal names get bumped!"}),"\n",(0,i.jsxs)(n.p,{children:['This is the classic "ECO" problem, and we provide descriptions in ',(0,i.jsx)(n.a,{href:"../explanations/naming",children:"explanation"}),". In short,\nwe recommend wrapping all additional logic in a prefix scope, which enables a unique namespace. This should prevent\nname collisions, which are what triggers all those annoying signal name bumps!"]}),"\n",(0,i.jsx)(n.h3,{id:"i-want-to-force-a-signal-or-instance-name-to-something-how-do-i-do-that",children:"I want to force a signal (or instance) name to something, how do I do that?"}),"\n",(0,i.jsxs)(n.p,{children:["Use the ",(0,i.jsx)(n.code,{children:".suggestName"})," method, which is on all classes which subtype ",(0,i.jsx)(n.code,{children:"Data"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"how-can-i-omit-the-prefix-in-certain-parts-of-the-code",children:"How can I omit the prefix in certain parts of the code?"}),"\n",(0,i.jsxs)(n.p,{children:["You can use the ",(0,i.jsx)(n.code,{children:"noPrefix { ... }"})," to strip the prefix from all signals generated in that scope."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.noPrefix\n\nclass ExampleNoPrefix extends Module {\n val in = IO(Input(UInt(2.W)))\n val out = IO(Output(UInt(5.W)))\n\n val add = noPrefix {\n // foo will not get a prefix\n val foo = RegNext(in + 1.U)\n foo + in\n }\n\n out := add\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule ExampleNoPrefix(\n input clock,\n reset,\n input [1:0] in,\n output [4:0] out\n);\n\n reg [1:0] foo;\n always @(posedge clock)\n foo <= in + 2'h1;\n assign out = {3'h0, foo + in};\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.h3,{id:"i-am-still-not-getting-the-name-i-want-for-example-inlining-an-instance-changes-my-name",children:"I am still not getting the name I want. For example, inlining an instance changes my name!"}),"\n",(0,i.jsxs)(n.p,{children:["In cases where a FIRRTL transform renames a signal/instance, you can use the ",(0,i.jsx)(n.code,{children:"forcename"})," API:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'import chisel3.util.experimental.{forceName, InlineInstance}\n\nclass WrapperExample extends Module {\n val in = IO(Input(UInt(3.W)))\n val out = IO(Output(UInt(3.W)))\n val inst = Module(new Wrapper)\n inst.in := in\n out := inst.out\n}\nclass Wrapper extends Module with InlineInstance {\n val in = IO(Input(UInt(3.W)))\n val out = IO(Output(UInt(3.W)))\n val inst = Module(new MyLeaf)\n forceName(inst, "inst")\n inst.in := in\n out := inst.out\n}\nclass MyLeaf extends Module {\n val in = IO(Input(UInt(3.W)))\n val out = IO(Output(UInt(3.W)))\n out := in\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule MyLeaf(\n input [2:0] in,\n output [2:0] out\n);\n\n assign out = in;\nendmodule\n\nmodule WrapperExample(\n input clock,\n reset,\n input [2:0] in,\n output [2:0] out\n);\n\n MyLeaf inst (\n .in (in),\n .out (out)\n );\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.p,{children:"This can be used to rename instances and non-aggregate typed signals."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1871:(e,n,a)=>{a.d(n,{A:()=>l});a(6540);var i=a(5195);const s={tableOfContentsInline:"tableOfContentsInline_prmo"};var t=a(4848);function l(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:l}=e;return(0,t.jsx)("div",{className:s.tableOfContentsInline,children:(0,t.jsx)(i.A,{toc:n,minHeadingLevel:a,maxHeadingLevel:l,className:"table-of-contents",linkClassName:null})})}},5195:(e,n,a)=>{a.d(n,{A:()=>x});var i=a(6540),s=a(6342);function t(e){const n=e.map((e=>({...e,parentIndex:-1,children:[]}))),a=Array(7).fill(-1);n.forEach(((e,n)=>{const i=a.slice(2,e.level);e.parentIndex=Math.max(...i),a[e.level]=n}));const i=[];return n.forEach((e=>{const{parentIndex:a,...s}=e;a>=0?n[a].children.push(s):i.push(s)})),i}function l(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:i}=e;return n.flatMap((e=>{const n=l({toc:e.children,minHeadingLevel:a,maxHeadingLevel:i});return function(e){return e.level>=a&&e.level<=i}(e)?[{...e,children:n}]:n}))}function o(e){const n=e.getBoundingClientRect();return n.top===n.bottom?o(e.parentNode):n}function d(e,n){let{anchorTopOffset:a}=n;const i=e.find((e=>o(e).top>=a));if(i){return function(e){return e.top>0&&e.bottomx
, x_1
and x_2
. How can I make them easier to understand?",id:"i-have-so-many-wires-with-the-same-name-like-x-x_1-and-x_2-how-can-i-make-them-easier-to-understand",level:3},{value:"How can I get better names for code generated by when
clauses?",id:"how-can-i-get-better-names-for-code-generated-by-when-clauses",level:3},{value:"I still see _GEN signals, can this be fixed?",id:"i-still-see-_gen-signals-can-this-be-fixed",level:3},{value:"How do I make my modules have more stable names instead of 'Module_1' and 'Module_42'?",id:"how-do-i-make-my-modules-have-more-stable-names-instead-of-module_1-and-module_42",level:3},{value:"How would I write my own typeName
for my data types?",id:"how-would-i-write-my-own-typename-for-my-data-types",level:3},{value:"I don't want to override typeName
over and over! Is there any easy way to generate a typeName
?",id:"i-dont-want-to-override-typename-over-and-over-is-there-any-easy-way-to-generate-a-typename",level:3},{value:"Can I name my bundles in FIRRTL, so I don't generate extremely long bundle types?",id:"can-i-name-my-bundles-in-firrtl-so-i-dont-generate-extremely-long-bundle-types",level:3},{value:"Why do I keep seeing _stripped suffixing everywhere in my FIRRTL? I didn't specify that in my aliasName
.",id:"why-do-i-keep-seeing-_stripped-suffixing-everywhere-in-my-firrtl-i-didnt-specify-that-in-my-aliasname",level:3},{value:"I want to add some hardware or assertions, but each time I do all the signal names get bumped!",id:"i-want-to-add-some-hardware-or-assertions-but-each-time-i-do-all-the-signal-names-get-bumped",level:3},{value:"I want to force a signal (or instance) name to something, how do I do that?",id:"i-want-to-force-a-signal-or-instance-name-to-something-how-do-i-do-that",level:3},{value:"How can I omit the prefix in certain parts of the code?",id:"how-can-i-omit-the-prefix-in-certain-parts-of-the-code",level:3},{value:"I am still not getting the name I want. For example, inlining an instance changes my name!",id:"i-am-still-not-getting-the-name-i-want-for-example-inlining-an-instance-changes-my-name",level:3}];function u(e){const n={a:"a",code:"code",em:"em",h1:"h1",h3:"h3",header:"header",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"naming-cookbook",children:"Naming Cookbook"})}),"\n","\n",(0,i.jsx)(t.A,{toc:c}),"\n",(0,i.jsx)(n.h3,{id:"i-still-have-_t-signals-can-this-be-fixed",children:"I still have _T signals, can this be fixed?"}),"\n",(0,i.jsx)(n.p,{children:"See the next answer!"}),"\n",(0,i.jsxs)(n.h3,{id:"i-have-so-many-wires-with-the-same-name-like-x-x_1-and-x_2-how-can-i-make-them-easier-to-understand",children:["I have so many wires with the same name, like ",(0,i.jsx)(n.code,{children:"x"}),", ",(0,i.jsx)(n.code,{children:"x_1"})," and ",(0,i.jsx)(n.code,{children:"x_2"}),". How can I make them easier to understand?"]}),"\n",(0,i.jsxs)(n.p,{children:["Signals with ",(0,i.jsx)(n.code,{children:"_T"})," names or names that Chisel has to uniquify\noften are intermediate values generated within loops, function calls, or ",(0,i.jsx)(n.code,{children:"when"})," predicates.\nThey can also be consumed by verification statements like ",(0,i.jsx)(n.code,{children:"assert"})," or ",(0,i.jsx)(n.code,{children:"prints"}),".\nIn these cases, the compiler plugin often can't find a good prefix for the generated\nintermediate signals and can't name them at all or has to make up a unique name for them."]}),"\n",(0,i.jsxs)(n.p,{children:["We recommend you manually insert calls to ",(0,i.jsx)(n.code,{children:"prefix"})," to clarify these cases:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'import chisel3.experimental.prefix\nclass ExamplePrefix extends Module {\n\n Seq.tabulate(2) { i =>\n Seq.tabulate(2) { j =>\n prefix(s"loop_${i}_${j}"){\n val x = WireInit((i*0x10+j).U(8.W))\n dontTouch(x)\n }\n }\n }\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule ExamplePrefix(\n input clock,\n reset\n);\n\n wire [7:0] loop_0_0_x = 8'h0;\n wire [7:0] loop_0_1_x = 8'h1;\n wire [7:0] loop_1_0_x = 8'h10;\n wire [7:0] loop_1_1_x = 8'h11;\nendmodule\n\n"})}),"\n",(0,i.jsxs)(n.h3,{id:"how-can-i-get-better-names-for-code-generated-by-when-clauses",children:["How can I get better names for code generated by ",(0,i.jsx)(n.code,{children:"when"})," clauses?"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"prefix"})," API can help with code inside ",(0,i.jsx)(n.code,{children:"when"})," clauses:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class ExampleWhenPrefix extends Module {\n\n val in = IO(Input(UInt(4.W)))\n val out = IO(Output(UInt(4.W)))\n\n out := DontCare\n\n Seq.tabulate(2) { i =>\n val j = i + 1\n prefix(s"clause_${j}") {\n when (in === j.U) {\n val foo = Reg(UInt(4.W))\n foo := in + j.U(4.W)\n out := foo\n }\n }\n }\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule ExampleWhenPrefix(\n input clock,\n reset,\n input [3:0] in,\n output [3:0] out\n);\n\n reg [3:0] clause_1_foo;\n reg [3:0] clause_2_foo;\n always @(posedge clock) begin\n clause_1_foo <= in + 4'h1;\n clause_2_foo <= in + 4'h2;\n end // always @(posedge)\n assign out = in == 4'h2 ? clause_2_foo : clause_1_foo;\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.h3,{id:"i-still-see-_gen-signals-can-this-be-fixed",children:"I still see _GEN signals, can this be fixed?"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"_GEN"})," signals are usually generated from the FIRRTL compiler, rather than the Chisel library. We are working on\nrenaming these signals with more context-dependent names, but it is a work in progress. Thanks for caring!"]}),"\n",(0,i.jsx)(n.h3,{id:"how-do-i-make-my-modules-have-more-stable-names-instead-of-module_1-and-module_42",children:"How do I make my modules have more stable names instead of 'Module_1' and 'Module_42'?"}),"\n",(0,i.jsxs)(n.p,{children:["This is an example of the module instability problem, which results from several modules all sharing the exact same name. To fix this, you must add more specificity to your ",(0,i.jsx)(n.code,{children:"Module"}),"'s name to avoid these name collisions."]}),"\n",(0,i.jsxs)(n.p,{children:["This can be done by leveraging the ",(0,i.jsx)(n.code,{children:"desiredName"})," and ",(0,i.jsx)(n.code,{children:"typeName"})," APIs.\n",(0,i.jsx)(n.code,{children:"desiredName"})," is for indicating the names of ",(0,i.jsx)(n.code,{children:"Modules"})," (e.g. influenced by the parameters passed in), and ",(0,i.jsx)(n.code,{children:"typeName"})," is useful for modules which are type-parameterized by subclasses of ",(0,i.jsx)(n.code,{children:"Data"}),". Overriding ",(0,i.jsx)(n.code,{children:"desiredName"})," can reduce or even eliminate name collisions. For instance, suppose your module looks like the following:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class MyModule[T <: Data](gen: T) extends Module {\n // ...\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["We can override ",(0,i.jsx)(n.code,{children:"desiredName"})," of the module to include the type name of the ",(0,i.jsx)(n.code,{children:"gen"})," parameter like so:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class MyModule[T <: Data](gen: T) extends Module {\n override def desiredName = s"MyModule_${gen.typeName}"\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Any instances of your ",(0,i.jsx)(n.code,{children:"MyModule"})," will now have Verilog module names containing the type parameter."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"val foo = Module(new MyModule(UInt(4.W))) // MyModule_UInt4 // MyModule_UInt4\nval bar = Module(new MyModule(Vec(3, UInt(4.W)))) // MyModule_Vec3_UInt4\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that all base Chisel util modules, like ",(0,i.jsx)(n.code,{children:"Queue"}),", already implement ",(0,i.jsx)(n.code,{children:"desiredName"})," like this:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"val fooQueue = Module(new Queue(UInt(8.W), 4)) // Verilog module would be named 'Queue4_UInt8' // Verilog module would be named 'Queue4_UInt8'\nval barQueue = Module(new Queue(SInt(12.W), 3)) // ... and 'Queue3_SInt12' // ... and 'Queue3_SInt12'\nval bazQueue = Module(new Queue(Bool(), 16)) // ... and 'Queue16_Bool'\n"})}),"\n",(0,i.jsxs)(n.h3,{id:"how-would-i-write-my-own-typename-for-my-data-types",children:["How would I write my own ",(0,i.jsx)(n.code,{children:"typeName"})," for my data types?"]}),"\n",(0,i.jsxs)(n.p,{children:["If you're using your own user-defined ",(0,i.jsx)(n.code,{children:"Bundle"}),", you can increase the specificity of its own ",(0,i.jsx)(n.code,{children:"typeName"})," by overriding it. All ",(0,i.jsx)(n.code,{children:"Data"})," types have a simple default implementation of ",(0,i.jsx)(n.code,{children:"typeName"})," (which is simply its class name), but you can override this yourself:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"class MyBundle[T <: Data](gen: T, intParam: Int) extends Bundle {\n // Generate a stable typeName for this Bundle. Two 'words' are present\n // in this implementation: the bundle's name plus its integer parameter\n // (something like 'MyBundle9')\n // and the generator's typeName, which itself can be composed of 'words'\n // (something like 'Vec3_UInt4')\n override def typeName = s\"MyBundle${intParam}_${gen.typeName}\"\n\n // ...\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Now if you use your ",(0,i.jsx)(n.code,{children:"MyBundle"})," in a module like a ",(0,i.jsx)(n.code,{children:"Queue"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"val fooQueue = Module(new Queue(new MyBundle(UInt(4.W), 3), 16)) // Queue16_MyBundle3_UInt4\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The suggested pattern for ",(0,i.jsx)(n.code,{children:"typeName"}),", and subsequently ",(0,i.jsx)(n.code,{children:"desiredName"}),", is to fold single integer-like parameters with the name itself (for example, ",(0,i.jsx)(n.code,{children:"Queue4"}),", ",(0,i.jsx)(n.code,{children:"UInt3"}),", ",(0,i.jsx)(n.code,{children:"MyBundle9"}),") to form 'words' and separate these 'words' with underscores (",(0,i.jsx)(n.code,{children:"Queue4_UInt3"}),", ",(0,i.jsx)(n.code,{children:"FooBundle_BarType4"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Bundles"})," that have multiple integer arguments aren't presently addressed by any of the built-in modules, and so implementing a descriptive and sufficiently differentiable ",(0,i.jsx)(n.code,{children:"typeName"})," for such ",(0,i.jsx)(n.code,{children:"Bundles"})," is left as an exercise to the reader. However, integers should not occur with an underscore before them at the very end of the ",(0,i.jsx)(n.code,{children:"typeName"})," (e.g. ",(0,i.jsx)(n.code,{children:"MyBundle_1"}),") because this is the ",(0,i.jsx)(n.em,{children:"same"})," syntax used for duplicates, and so would cause confusion. Having to disambiguate modules all named ",(0,i.jsx)(n.code,{children:"Queue32_MyBundle_4_1"}),", ",(0,i.jsx)(n.code,{children:"Queue32_MyBundle_4_2"}),", ",(0,i.jsx)(n.code,{children:"Queue32_MyBundle_4_3"}),", and so on would be undesirable, indeed!"]}),"\n",(0,i.jsxs)(n.h3,{id:"i-dont-want-to-override-typename-over-and-over-is-there-any-easy-way-to-generate-a-typename",children:["I don't want to override ",(0,i.jsx)(n.code,{children:"typeName"})," over and over! Is there any easy way to generate a ",(0,i.jsx)(n.code,{children:"typeName"}),"?"]}),"\n",(0,i.jsxs)(n.p,{children:["Yes, with the experimental ",(0,i.jsx)(n.code,{children:"HasAutoTypename"})," trait. This trait can be mixed into your ",(0,i.jsx)(n.code,{children:"Bundle"}),"s to automatically generate a tuple-like ",(0,i.jsx)(n.code,{children:"typeName"})," for them, based on the constructor parameters of that ",(0,i.jsx)(n.code,{children:"Bundle"}),". Let's look at the previous examples:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class MyBundle[T <: Data](gen: T, intParam: Int) extends Bundle {\n override def typeName = s"MyBundle_${gen.typeName}_${intParam}"\n // ...\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'new MyBundle(UInt(8.W), 3).typeName\n// res7: String = "MyBundle_UInt<8>_3"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Auto-generated ",(0,i.jsx)(n.code,{children:"typeName"}),"s take the form of ",(0,i.jsx)(n.code,{children:"{Bundle Name}_{Parameter Value 1}_{Parameter Value 2}_{...}"}),", and so our ",(0,i.jsx)(n.code,{children:"MyBundle"})," can be equivalently expressed with:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.HasAutoTypename\nclass MyBundle[T <: Data](gen: T, intParam: Int) extends Bundle with HasAutoTypename {\n // ...\n // Note: No `override def typeName` statement here\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'new MyBundle(UInt(8.W), 3).typeName\n// res9: String = "MyBundle_UInt<8>_3"\n'})}),"\n",(0,i.jsx)(n.h3,{id:"can-i-name-my-bundles-in-firrtl-so-i-dont-generate-extremely-long-bundle-types",children:"Can I name my bundles in FIRRTL, so I don't generate extremely long bundle types?"}),"\n",(0,i.jsxs)(n.p,{children:["Yes, using the ",(0,i.jsx)(n.code,{children:"HasTypeAlias"})," trait. FIRRTL has a construct to alias a bundle type with a type alias like so:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"circuit Top :\n type MyBundle = { foo : UInt<8>, bar : UInt<1>}\n\n module Top :\n //...\n"})}),"\n",(0,i.jsxs)(n.p,{children:["These can be automatically emitted from Chisel by mixing ",(0,i.jsx)(n.code,{children:"HasTypeAlias"})," into a user-defined ",(0,i.jsx)(n.code,{children:"Record"}),", and implementing a field named ",(0,i.jsx)(n.code,{children:"aliasName"})," with a ",(0,i.jsx)(n.code,{children:"RecordAlias(...)"})," instance."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'import chisel3.experimental.{HasTypeAlias, RecordAlias}\n\nclass AliasedBundle extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("MyAliasedBundle")\n val foo = UInt(8.W)\n val bar = Bool()\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Let's see what happens when we generate FIRRTL using this ",(0,i.jsx)(n.code,{children:"Bundle"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'emitFIRRTL(new Module {\n val wire = Wire(new AliasedBundle)\n})\n// res10: String = """FIRRTL version 4.2.0\n// circuit _18_Anon :\n// type MyAliasedBundle = { foo : UInt<8>, bar : UInt<1>}\n// \n// layer Verification, bind, "verification" :\n// layer Assert, bind, "verification/assert" :\n// layer Assume, bind, "verification/assume" :\n// layer Cover, bind, "verification/cover" :\n// public module _18_Anon : @[naming.md 232:28]\n// input clock : Clock @[naming.md 232:28]\n// input reset : UInt<1> @[naming.md 232:28]\n// \n// wire wire : MyAliasedBundle @[naming.md 233:18]\n// \n// """\n'})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"HasTypeAlias"})," also supports nested bundles, too:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class Child extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("ChildBundle")\n val x = UInt(8.W)\n}\n\nclass Parent extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("ParentBundle")\n val child = new Child\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'emitFIRRTL(new Module {\n val wire = Wire(new Parent)\n})\n// res11: String = """FIRRTL version 4.2.0\n// circuit _22_Anon :\n// type ChildBundle = { x : UInt<8>}\n// type ParentBundle = { child : ChildBundle}\n// \n// layer Verification, bind, "verification" :\n// layer Assert, bind, "verification/assert" :\n// layer Assume, bind, "verification/assume" :\n// layer Cover, bind, "verification/cover" :\n// public module _22_Anon : @[naming.md 255:28]\n// input clock : Clock @[naming.md 255:28]\n// input reset : UInt<1> @[naming.md 255:28]\n// \n// wire wire : ParentBundle @[naming.md 256:18]\n// \n// """\n'})}),"\n",(0,i.jsxs)(n.h3,{id:"why-do-i-keep-seeing-_stripped-suffixing-everywhere-in-my-firrtl-i-didnt-specify-that-in-my-aliasname",children:["Why do I keep seeing _stripped suffixing everywhere in my FIRRTL? I didn't specify that in my ",(0,i.jsx)(n.code,{children:"aliasName"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["You're using an ",(0,i.jsx)(n.code,{children:"Input(...)"})," or ",(0,i.jsx)(n.code,{children:"Output(...)"})," in conjunction with an aliased ",(0,i.jsx)(n.code,{children:"Record"})," that contains a ",(0,i.jsx)(n.code,{children:"Flipped(...)"}),". These flipped values are stripped by ",(0,i.jsx)(n.code,{children:"Input"})," and ",(0,i.jsx)(n.code,{children:"Output"})," which fundamentally changes the type of the parent ",(0,i.jsx)(n.code,{children:"Record"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class StrippedBundle extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("StrippedBundle")\n val flipped = Flipped(UInt(8.W))\n val normal = UInt(8.W)\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'emitFIRRTL(new Module {\n val in = IO(Input(new StrippedBundle))\n})\n// res12: String = """FIRRTL version 4.2.0\n// circuit _26_Anon :\n// type StrippedBundle_stripped = { flipped : UInt<8>, normal : UInt<8>}\n// \n// layer Verification, bind, "verification" :\n// layer Assert, bind, "verification/assert" :\n// layer Assume, bind, "verification/assume" :\n// layer Cover, bind, "verification/cover" :\n// public module _26_Anon : @[naming.md 273:28]\n// input clock : Clock @[naming.md 273:28]\n// input reset : UInt<1> @[naming.md 273:28]\n// input in : StrippedBundle_stripped @[naming.md 274:14]\n// \n// skip\n// \n// """\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Note how the bundle type doesn't contain a ",(0,i.jsx)(n.code,{children:"flip flipped : UInt<8>"})," field, and the alias gains a ",(0,i.jsx)(n.code,{children:'"_stripped"'})," suffix! This ",(0,i.jsx)(n.code,{children:"Bundle"})," type is no longer the same as the one we wrote in Chisel, so we have to distinguish it as such."]}),"\n",(0,i.jsxs)(n.p,{children:["By default, the suffix appended to ",(0,i.jsx)(n.code,{children:"Record"})," names is ",(0,i.jsx)(n.code,{children:'"_stripped"'}),". This can be defined by users with an additional string argument passed to ",(0,i.jsx)(n.code,{children:"RecordAlias(alias, strippedSuffix)"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'class CustomStrippedBundle extends Bundle with HasTypeAlias {\n override def aliasName = RecordAlias("StrippedBundle", "Foo")\n val flipped = Flipped(UInt(8.W))\n val normal = UInt(8.W)\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'emitFIRRTL(new Module {\n val in = IO(Input(new CustomStrippedBundle))\n})\n// res13: String = """FIRRTL version 4.2.0\n// circuit _30_Anon :\n// type StrippedBundleFoo = { flipped : UInt<8>, normal : UInt<8>}\n// \n// layer Verification, bind, "verification" :\n// layer Assert, bind, "verification/assert" :\n// layer Assume, bind, "verification/assume" :\n// layer Cover, bind, "verification/cover" :\n// public module _30_Anon : @[naming.md 291:28]\n// input clock : Clock @[naming.md 291:28]\n// input reset : UInt<1> @[naming.md 291:28]\n// input in : StrippedBundleFoo @[naming.md 292:14]\n// \n// skip\n// \n// """\n'})}),"\n",(0,i.jsx)(n.h3,{id:"i-want-to-add-some-hardware-or-assertions-but-each-time-i-do-all-the-signal-names-get-bumped",children:"I want to add some hardware or assertions, but each time I do all the signal names get bumped!"}),"\n",(0,i.jsxs)(n.p,{children:['This is the classic "ECO" problem, and we provide descriptions in ',(0,i.jsx)(n.a,{href:"../explanations/naming",children:"explanation"}),". In short,\nwe recommend wrapping all additional logic in a prefix scope, which enables a unique namespace. This should prevent\nname collisions, which are what triggers all those annoying signal name bumps!"]}),"\n",(0,i.jsx)(n.h3,{id:"i-want-to-force-a-signal-or-instance-name-to-something-how-do-i-do-that",children:"I want to force a signal (or instance) name to something, how do I do that?"}),"\n",(0,i.jsxs)(n.p,{children:["Use the ",(0,i.jsx)(n.code,{children:".suggestName"})," method, which is on all classes which subtype ",(0,i.jsx)(n.code,{children:"Data"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"how-can-i-omit-the-prefix-in-certain-parts-of-the-code",children:"How can I omit the prefix in certain parts of the code?"}),"\n",(0,i.jsxs)(n.p,{children:["You can use the ",(0,i.jsx)(n.code,{children:"noPrefix { ... }"})," to strip the prefix from all signals generated in that scope."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.noPrefix\n\nclass ExampleNoPrefix extends Module {\n val in = IO(Input(UInt(2.W)))\n val out = IO(Output(UInt(5.W)))\n\n val add = noPrefix {\n // foo will not get a prefix\n val foo = RegNext(in + 1.U)\n foo + in\n }\n\n out := add\n}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule ExampleNoPrefix(\n input clock,\n reset,\n input [1:0] in,\n output [4:0] out\n);\n\n reg [1:0] foo;\n always @(posedge clock)\n foo <= in + 2'h1;\n assign out = {3'h0, foo + in};\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.h3,{id:"i-am-still-not-getting-the-name-i-want-for-example-inlining-an-instance-changes-my-name",children:"I am still not getting the name I want. For example, inlining an instance changes my name!"}),"\n",(0,i.jsxs)(n.p,{children:["In cases where a FIRRTL transform renames a signal/instance, you can use the ",(0,i.jsx)(n.code,{children:"forcename"})," API:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-scala",children:'import chisel3.util.experimental.{forceName, InlineInstance}\n\nclass WrapperExample extends Module {\n val in = IO(Input(UInt(3.W)))\n val out = IO(Output(UInt(3.W)))\n val inst = Module(new Wrapper)\n inst.in := in\n out := inst.out\n}\nclass Wrapper extends Module with InlineInstance {\n val in = IO(Input(UInt(3.W)))\n val out = IO(Output(UInt(3.W)))\n val inst = Module(new MyLeaf)\n forceName(inst, "inst")\n inst.in := in\n out := inst.out\n}\nclass MyLeaf extends Module {\n val in = IO(Input(UInt(3.W)))\n val out = IO(Output(UInt(3.W)))\n out := in\n}\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule MyLeaf(\n input [2:0] in,\n output [2:0] out\n);\n\n assign out = in;\nendmodule\n\nmodule WrapperExample(\n input clock,\n reset,\n input [2:0] in,\n output [2:0] out\n);\n\n MyLeaf inst (\n .in (in),\n .out (out)\n );\nendmodule\n\n"})}),"\n",(0,i.jsx)(n.p,{children:"This can be used to rename instances and non-aggregate typed signals."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1871:(e,n,a)=>{a.d(n,{A:()=>l});a(6540);var i=a(5195);const s={tableOfContentsInline:"tableOfContentsInline_prmo"};var t=a(4848);function l(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:l}=e;return(0,t.jsx)("div",{className:s.tableOfContentsInline,children:(0,t.jsx)(i.A,{toc:n,minHeadingLevel:a,maxHeadingLevel:l,className:"table-of-contents",linkClassName:null})})}},5195:(e,n,a)=>{a.d(n,{A:()=>x});var i=a(6540),s=a(6342);function t(e){const n=e.map((e=>({...e,parentIndex:-1,children:[]}))),a=Array(7).fill(-1);n.forEach(((e,n)=>{const i=a.slice(2,e.level);e.parentIndex=Math.max(...i),a[e.level]=n}));const i=[];return n.forEach((e=>{const{parentIndex:a,...s}=e;a>=0?n[a].children.push(s):i.push(s)})),i}function l(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:i}=e;return n.flatMap((e=>{const n=l({toc:e.children,minHeadingLevel:a,maxHeadingLevel:i});return function(e){return e.level>=a&&e.level<=i}(e)?[{...e,children:n}]:n}))}function o(e){const n=e.getBoundingClientRect();return n.top===n.bottom?o(e.parentNode):n}function d(e,n){let{anchorTopOffset:a}=n;const i=e.find((e=>o(e).top>=a));if(i){return function(e){return e.top>0&&e.bottomcloneType
(For Chisel < 3.5)",id:"a-note-on-clonetype-for-chisel--35",level:3}];function r(e){const n={a:"a",code:"code",h1:"h1",h3:"h3",header:"header",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"bundles-and-vecs",children:"Bundles and Vecs"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"Bundle"})," and ",(0,s.jsx)(n.code,{children:"Vec"})," are classes that allow the user to expand the set of Chisel datatypes with aggregates of other types."]}),"\n",(0,s.jsxs)(n.p,{children:["Bundles group together several named fields of potentially different types into a coherent unit, much like a ",(0,s.jsx)(n.code,{children:"struct"})," in\nC. Users define their own bundles by defining a class as a subclass of ",(0,s.jsx)(n.code,{children:"Bundle"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass MyFloat extends Bundle {\n val sign = Bool()\n val exponent = UInt(8.W)\n val significand = UInt(23.W)\n}\n\nclass ModuleWithFloatWire extends RawModule {\n val x = Wire(new MyFloat)\n val xs = x.sign\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can create literal Bundles using the experimental ",(0,s.jsx)(n.a,{href:"../appendix/experimental-features#bundle-literals",children:"Bundle Literals"})," feature."]}),"\n",(0,s.jsx)(n.p,{children:"Scala convention is to name classes using UpperCamelCase, and we suggest you follow that convention in your Chisel code."}),"\n",(0,s.jsx)(n.p,{children:"Vecs create an indexable vector of elements, and are constructed as follows:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class ModuleWithVec extends RawModule {\n // Vector of 5 23-bit signed integers.\n val myVec = Wire(Vec(5, SInt(23.W)))\n\n // Connect to one element of vector.\n val reg3 = myVec(3)\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["(Note that we specify the number followed by the type of the ",(0,s.jsx)(n.code,{children:"Vec"})," elements. We also specifiy the width of the ",(0,s.jsx)(n.code,{children:"SInt"}),")"]}),"\n",(0,s.jsxs)(n.p,{children:["The set of primitive classes\n(",(0,s.jsx)(n.code,{children:"SInt"}),", ",(0,s.jsx)(n.code,{children:"UInt"}),", and ",(0,s.jsx)(n.code,{children:"Bool"}),") plus the aggregate\nclasses (",(0,s.jsx)(n.code,{children:"Bundles"})," and ",(0,s.jsx)(n.code,{children:"Vec"}),"s) all inherit from a common\nsuperclass, ",(0,s.jsx)(n.code,{children:"Data"}),". Every object that ultimately inherits from\n",(0,s.jsx)(n.code,{children:"Data"})," can be represented as a bit vector in a hardware design."]}),"\n",(0,s.jsx)(n.p,{children:"Bundles and Vecs can be arbitrarily nested to build complex data\nstructures:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class BigBundle extends Bundle {\n // Vector of 5 23-bit signed integers.\n val myVec = Vec(5, SInt(23.W))\n val flag = Bool()\n // Previously defined bundle.\n val f = new MyFloat\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Note that the builtin Chisel primitive and aggregate classes do not\nrequire the ",(0,s.jsx)(n.code,{children:"new"})," when creating an instance, whereas new user\ndatatypes will. A Scala ",(0,s.jsx)(n.code,{children:"apply"})," constructor can be defined so\nthat a user datatype also does not require ",(0,s.jsx)(n.code,{children:"new"}),", as described in\n",(0,s.jsx)(n.a,{href:"../explanations/functional-module-creation",children:"Function Constructor"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"flipping-bundles",children:"Flipping Bundles"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"Flipped()"})," function recursively flips all elements in a Bundle/Record. This is very useful for building bidirectional interfaces that connect to each other (e.g. ",(0,s.jsx)(n.code,{children:"Decoupled"}),"). See below for an example."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class ABBundle extends Bundle {\n val a = Input(Bool())\n val b = Output(Bool())\n}\nclass MyFlippedModule extends RawModule {\n // Normal instantiation of the bundle\n // 'a' is an Input and 'b' is an Output\n val normalBundle = IO(new ABBundle)\n normalBundle.b := normalBundle.a\n\n // Flipped recursively flips the direction of all Bundle fields\n // Now 'a' is an Output and 'b' is an Input\n val flippedBundle = IO(Flipped(new ABBundle))\n flippedBundle.a := flippedBundle.b\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"This generates the following Verilog:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule MyFlippedModule(\n input normalBundle_a,\n output normalBundle_b,\n flippedBundle_a,\n input flippedBundle_b\n);\n\n assign normalBundle_b = normalBundle_a;\n assign flippedBundle_a = flippedBundle_b;\nendmodule\n\n"})}),"\n",(0,s.jsx)(n.h3,{id:"mixedvec",children:"MixedVec"}),"\n",(0,s.jsx)(n.p,{children:"(Chisel 3.2+)"}),"\n",(0,s.jsxs)(n.p,{children:["All elements of a ",(0,s.jsx)(n.code,{children:"Vec"})," must have the same parameterization. If we want to create a Vec where the elements have the same type but different parameterizations, we can use a MixedVec:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.MixedVec\nclass ModuleMixedVec extends Module {\n val io = IO(new Bundle {\n val x = Input(UInt(3.W))\n val y = Input(UInt(10.W))\n val vec = Output(MixedVec(UInt(3.W), UInt(10.W)))\n })\n io.vec(0) := io.x\n io.vec(1) := io.y\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"We can also programmatically create the types in a MixedVec:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class ModuleProgrammaticMixedVec(x: Int, y: Int) extends Module {\n val io = IO(new Bundle {\n val vec = Input(MixedVec((x to y) map { i => UInt(i.W) }))\n // ...\n })\n // ...rest of the module goes here...\n}\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"a-note-on-clonetype-for-chisel--35",children:["A note on ",(0,s.jsx)(n.code,{children:"cloneType"})," (For Chisel < 3.5)"]}),"\n",(0,s.jsxs)(n.p,{children:["NOTE: This section ",(0,s.jsx)(n.strong,{children:"only applies to Chisel before Chisel 3.5"}),".\nAs of Chisel 3.5, ",(0,s.jsx)(n.code,{children:"Bundle"}),"s should ",(0,s.jsx)(n.strong,{children:"not"})," ",(0,s.jsx)(n.code,{children:"override def cloneType"}),",\nas this is a compiler error when using the chisel3 compiler plugin for inferring ",(0,s.jsx)(n.code,{children:"cloneType"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Since Chisel is built on top of Scala and the JVM,\nit needs to know how to construct copies of ",(0,s.jsx)(n.code,{children:"Bundle"}),"s for various\npurposes (creating wires, IOs, etc).\nIf you have a parametrized ",(0,s.jsx)(n.code,{children:"Bundle"})," and Chisel can't automatically figure out how to\nclone it, you will need to create a custom ",(0,s.jsx)(n.code,{children:"cloneType"})," method in your bundle.\nIn the vast majority of cases, ",(0,s.jsx)(n.strong,{children:"this is not required"}),"\nas Chisel can figure out how to clone most ",(0,s.jsx)(n.code,{children:"Bundle"}),"s automatically:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class MyCloneTypeBundle(val bitwidth: Int) extends Bundle {\n val field = UInt(bitwidth.W)\n // ...\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The only caveat is if you are passing something of type ",(0,s.jsx)(n.code,{children:"Data"}),' as a "generator" parameter,\nin which case you should make it a ',(0,s.jsx)(n.code,{children:"private val"}),", and define a ",(0,s.jsx)(n.code,{children:"cloneType"})," method with\n",(0,s.jsx)(n.code,{children:"override def cloneType = (new YourBundleHere(...)).asInstanceOf[this.type]"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["For example, consider the following ",(0,s.jsx)(n.code,{children:"Bundle"}),". Because its ",(0,s.jsx)(n.code,{children:"gen"})," variable is not a ",(0,s.jsx)(n.code,{children:"private val"}),", the user has to\nexplicitly define the ",(0,s.jsx)(n.code,{children:"cloneType"})," method:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.{Decoupled, Irrevocable}\nclass RegisterWriteIOExplicitCloneType[T <: Data](gen: T) extends Bundle {\n val request = Flipped(Decoupled(gen))\n val response = Irrevocable(Bool())\n override def cloneType = new RegisterWriteIOExplicitCloneType(gen).asInstanceOf[this.type]\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["We can make this this infer cloneType by making ",(0,s.jsx)(n.code,{children:"gen"}),' private since it is a "type parameter":']}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.{Decoupled, Irrevocable}\nclass RegisterWriteIO[T <: Data](private val gen: T) extends Bundle {\n val request = Flipped(Decoupled(gen))\n val response = Irrevocable(Bool())\n}\n"})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(r,{...e})}):r(e)}},8453:(e,n,l)=>{l.d(n,{R:()=>t,x:()=>c});var s=l(6540);const a={},i=s.createContext(a);function t(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:t(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[3313],{5527:(e,n,l)=>{l.r(n),l.d(n,{assets:()=>d,contentTitle:()=>t,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var s=l(4848),a=l(8453);const i={layout:"docs",title:"Bundles and Vecs",section:"chisel3"},t="Bundles and Vecs",c={id:"explanations/bundles-and-vecs",title:"Bundles and Vecs",description:"Bundle and Vec are classes that allow the user to expand the set of Chisel datatypes with aggregates of other types.",source:"@site/docs/explanations/bundles-and-vecs.md",sourceDirName:"explanations",slug:"/explanations/bundles-and-vecs",permalink:"/docs/explanations/bundles-and-vecs",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/bundles-and-vecs.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Bundles and Vecs",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Blackboxes",permalink:"/docs/explanations/blackboxes"},next:{title:"Enumerations",permalink:"/docs/explanations/chisel-enum"}},d={},o=[{value:"Flipping Bundles",id:"flipping-bundles",level:3},{value:"MixedVec",id:"mixedvec",level:3},{value:"A note on cloneType
(For Chisel < 3.5)",id:"a-note-on-clonetype-for-chisel--35",level:3}];function r(e){const n={a:"a",code:"code",h1:"h1",h3:"h3",header:"header",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"bundles-and-vecs",children:"Bundles and Vecs"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"Bundle"})," and ",(0,s.jsx)(n.code,{children:"Vec"})," are classes that allow the user to expand the set of Chisel datatypes with aggregates of other types."]}),"\n",(0,s.jsxs)(n.p,{children:["Bundles group together several named fields of potentially different types into a coherent unit, much like a ",(0,s.jsx)(n.code,{children:"struct"})," in\nC. Users define their own bundles by defining a class as a subclass of ",(0,s.jsx)(n.code,{children:"Bundle"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass MyFloat extends Bundle {\n val sign = Bool()\n val exponent = UInt(8.W)\n val significand = UInt(23.W)\n}\n\nclass ModuleWithFloatWire extends RawModule {\n val x = Wire(new MyFloat)\n val xs = x.sign\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can create literal Bundles using the experimental ",(0,s.jsx)(n.a,{href:"../appendix/experimental-features#bundle-literals",children:"Bundle Literals"})," feature."]}),"\n",(0,s.jsx)(n.p,{children:"Scala convention is to name classes using UpperCamelCase, and we suggest you follow that convention in your Chisel code."}),"\n",(0,s.jsx)(n.p,{children:"Vecs create an indexable vector of elements, and are constructed as follows:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class ModuleWithVec extends RawModule {\n // Vector of 5 23-bit signed integers.\n val myVec = Wire(Vec(5, SInt(23.W)))\n\n // Connect to one element of vector.\n val reg3 = myVec(3)\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["(Note that we specify the number followed by the type of the ",(0,s.jsx)(n.code,{children:"Vec"})," elements. We also specifiy the width of the ",(0,s.jsx)(n.code,{children:"SInt"}),")"]}),"\n",(0,s.jsxs)(n.p,{children:["The set of primitive classes\n(",(0,s.jsx)(n.code,{children:"SInt"}),", ",(0,s.jsx)(n.code,{children:"UInt"}),", and ",(0,s.jsx)(n.code,{children:"Bool"}),") plus the aggregate\nclasses (",(0,s.jsx)(n.code,{children:"Bundles"})," and ",(0,s.jsx)(n.code,{children:"Vec"}),"s) all inherit from a common\nsuperclass, ",(0,s.jsx)(n.code,{children:"Data"}),". Every object that ultimately inherits from\n",(0,s.jsx)(n.code,{children:"Data"})," can be represented as a bit vector in a hardware design."]}),"\n",(0,s.jsx)(n.p,{children:"Bundles and Vecs can be arbitrarily nested to build complex data\nstructures:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class BigBundle extends Bundle {\n // Vector of 5 23-bit signed integers.\n val myVec = Vec(5, SInt(23.W))\n val flag = Bool()\n // Previously defined bundle.\n val f = new MyFloat\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Note that the builtin Chisel primitive and aggregate classes do not\nrequire the ",(0,s.jsx)(n.code,{children:"new"})," when creating an instance, whereas new user\ndatatypes will. A Scala ",(0,s.jsx)(n.code,{children:"apply"})," constructor can be defined so\nthat a user datatype also does not require ",(0,s.jsx)(n.code,{children:"new"}),", as described in\n",(0,s.jsx)(n.a,{href:"../explanations/functional-module-creation",children:"Function Constructor"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"flipping-bundles",children:"Flipping Bundles"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"Flipped()"})," function recursively flips all elements in a Bundle/Record. This is very useful for building bidirectional interfaces that connect to each other (e.g. ",(0,s.jsx)(n.code,{children:"Decoupled"}),"). See below for an example."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class ABBundle extends Bundle {\n val a = Input(Bool())\n val b = Output(Bool())\n}\nclass MyFlippedModule extends RawModule {\n // Normal instantiation of the bundle\n // 'a' is an Input and 'b' is an Output\n val normalBundle = IO(new ABBundle)\n normalBundle.b := normalBundle.a\n\n // Flipped recursively flips the direction of all Bundle fields\n // Now 'a' is an Output and 'b' is an Input\n val flippedBundle = IO(Flipped(new ABBundle))\n flippedBundle.a := flippedBundle.b\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"This generates the following Verilog:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule MyFlippedModule(\n input normalBundle_a,\n output normalBundle_b,\n flippedBundle_a,\n input flippedBundle_b\n);\n\n assign normalBundle_b = normalBundle_a;\n assign flippedBundle_a = flippedBundle_b;\nendmodule\n\n"})}),"\n",(0,s.jsx)(n.h3,{id:"mixedvec",children:"MixedVec"}),"\n",(0,s.jsx)(n.p,{children:"(Chisel 3.2+)"}),"\n",(0,s.jsxs)(n.p,{children:["All elements of a ",(0,s.jsx)(n.code,{children:"Vec"})," must have the same parameterization. If we want to create a Vec where the elements have the same type but different parameterizations, we can use a MixedVec:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.MixedVec\nclass ModuleMixedVec extends Module {\n val io = IO(new Bundle {\n val x = Input(UInt(3.W))\n val y = Input(UInt(10.W))\n val vec = Output(MixedVec(UInt(3.W), UInt(10.W)))\n })\n io.vec(0) := io.x\n io.vec(1) := io.y\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"We can also programmatically create the types in a MixedVec:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class ModuleProgrammaticMixedVec(x: Int, y: Int) extends Module {\n val io = IO(new Bundle {\n val vec = Input(MixedVec((x to y) map { i => UInt(i.W) }))\n // ...\n })\n // ...rest of the module goes here...\n}\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"a-note-on-clonetype-for-chisel--35",children:["A note on ",(0,s.jsx)(n.code,{children:"cloneType"})," (For Chisel < 3.5)"]}),"\n",(0,s.jsxs)(n.p,{children:["NOTE: This section ",(0,s.jsx)(n.strong,{children:"only applies to Chisel before Chisel 3.5"}),".\nAs of Chisel 3.5, ",(0,s.jsx)(n.code,{children:"Bundle"}),"s should ",(0,s.jsx)(n.strong,{children:"not"})," ",(0,s.jsx)(n.code,{children:"override def cloneType"}),",\nas this is a compiler error when using the chisel3 compiler plugin for inferring ",(0,s.jsx)(n.code,{children:"cloneType"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Since Chisel is built on top of Scala and the JVM,\nit needs to know how to construct copies of ",(0,s.jsx)(n.code,{children:"Bundle"}),"s for various\npurposes (creating wires, IOs, etc).\nIf you have a parametrized ",(0,s.jsx)(n.code,{children:"Bundle"})," and Chisel can't automatically figure out how to\nclone it, you will need to create a custom ",(0,s.jsx)(n.code,{children:"cloneType"})," method in your bundle.\nIn the vast majority of cases, ",(0,s.jsx)(n.strong,{children:"this is not required"}),"\nas Chisel can figure out how to clone most ",(0,s.jsx)(n.code,{children:"Bundle"}),"s automatically:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"class MyCloneTypeBundle(val bitwidth: Int) extends Bundle {\n val field = UInt(bitwidth.W)\n // ...\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The only caveat is if you are passing something of type ",(0,s.jsx)(n.code,{children:"Data"}),' as a "generator" parameter,\nin which case you should make it a ',(0,s.jsx)(n.code,{children:"private val"}),", and define a ",(0,s.jsx)(n.code,{children:"cloneType"})," method with\n",(0,s.jsx)(n.code,{children:"override def cloneType = (new YourBundleHere(...)).asInstanceOf[this.type]"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["For example, consider the following ",(0,s.jsx)(n.code,{children:"Bundle"}),". Because its ",(0,s.jsx)(n.code,{children:"gen"})," variable is not a ",(0,s.jsx)(n.code,{children:"private val"}),", the user has to\nexplicitly define the ",(0,s.jsx)(n.code,{children:"cloneType"})," method:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.{Decoupled, Irrevocable}\nclass RegisterWriteIOExplicitCloneType[T <: Data](gen: T) extends Bundle {\n val request = Flipped(Decoupled(gen))\n val response = Irrevocable(Bool())\n override def cloneType = new RegisterWriteIOExplicitCloneType(gen).asInstanceOf[this.type]\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["We can make this this infer cloneType by making ",(0,s.jsx)(n.code,{children:"gen"}),' private since it is a "type parameter":']}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-scala",children:"import chisel3.util.{Decoupled, Irrevocable}\nclass RegisterWriteIO[T <: Data](private val gen: T) extends Bundle {\n val request = Flipped(Decoupled(gen))\n val response = Irrevocable(Bool())\n}\n"})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(r,{...e})}):r(e)}},8453:(e,n,l)=>{l.d(n,{R:()=>t,x:()=>c});var s=l(6540);const a={},i=s.createContext(a);function t(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:t(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c48de377.33b512d1.js b/assets/js/c48de377.33b512d1.js
new file mode 100644
index 00000000000..7dabbae281f
--- /dev/null
+++ b/assets/js/c48de377.33b512d1.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[3316],{1429:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var l=i(4848),t=i(8453);const a={layout:"docs",title:"Experimental Features",section:"chisel3"},o="Experimental Features",s={id:"appendix/experimental-features",title:"Experimental Features",description:"Chisel has a number of new features that are worth checking out. This page is an informal list of these features and projects.",source:"@site/docs/appendix/experimental-features.md",sourceDirName:"appendix",slug:"/appendix/experimental-features",permalink:"/docs/appendix/experimental-features",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/appendix/experimental-features.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Experimental Features",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Migrating from ChiselTest",permalink:"/docs/appendix/migrating-from-chiseltest"},next:{title:"Upgrading From Chisel 3.4 to 3.5",permalink:"/docs/appendix/upgrading-from-chisel-3-4"}},r={},d=[{value:"Module Variants",id:"module-variants",level:2},{value:"Bundle Literals",id:"bundle-literals",level:2},{value:"Vec Literals",id:"vec-literals",level:2},{value:"Loading Memories for simulation or FPGA initialization",id:"loading-memories-for-simulation-or-fpga-initialization",level:2},{value:"Inline initialization with external file",id:"inline-initialization-with-external-file",level:3},{value:"SystemVerilog Bind Initialization",id:"systemverilog-bind-initialization",level:3},{value:"Notes on files",id:"notes-on-files",level:3},{value:"Aggregate memories",id:"aggregate-memories",level:3}];function c(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",ul:"ul",...(0,t.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.header,{children:(0,l.jsx)(n.h1,{id:"experimental-features",children:"Experimental Features"})}),"\n",(0,l.jsx)(n.p,{children:"Chisel has a number of new features that are worth checking out. This page is an informal list of these features and projects."}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"#module-variants",children:"Module Variants"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"#bundle-literals",children:"Bundle Literals"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"#vec-literals",children:"Vec Literals"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"#loading-memories-for-simulation-or-fpga-initialization",children:"Loading-Memories-for-simulation-or-FPGA-initialization"})}),"\n"]}),"\n",(0,l.jsx)(n.h2,{id:"module-variants",children:"Module Variants"}),"\n",(0,l.jsxs)(n.p,{children:["The standard Chisel ",(0,l.jsx)(n.em,{children:"Module"})," requires a ",(0,l.jsx)(n.code,{children:"val io = IO(...)"}),", the experimental package introduces several\nnew ways of defining Modules"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:"BaseModule: no contents, instantiable"}),"\n",(0,l.jsx)(n.li,{children:"BlackBox extends BaseModule"}),"\n",(0,l.jsx)(n.li,{children:"UserDefinedModule extends BaseModule: this module can contain Chisel RTL. No default clock or reset lines. No default IO. - User should be able to specify non-io ports, ideally multiple of them."}),"\n",(0,l.jsx)(n.li,{children:"ImplicitModule extends UserModule: has clock, reset, and io, essentially current Chisel Module."}),"\n",(0,l.jsx)(n.li,{children:"RawModule: will be the user-facing version of UserDefinedModule"}),"\n",(0,l.jsx)(n.li,{children:"Module: type-aliases to ImplicitModule, the user-facing version of ImplicitModule."}),"\n"]}),"\n",(0,l.jsx)(n.h2,{id:"bundle-literals",children:"Bundle Literals"}),"\n",(0,l.jsx)(n.p,{children:"Bundle literals can be constructed via an experimental import:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.BundleLiterals._\n\nclass MyBundle extends Bundle {\n val a = UInt(8.W)\n val b = Bool()\n}\n\nclass Example extends RawModule {\n val out = IO(Output(new MyBundle))\n out := (new MyBundle).Lit(_.a -> 8.U, _.b -> true.B)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example(\n output [7:0] out_a,\n output out_b\n);\n\n assign out_a = 8'h8;\n assign out_b = 1'h1;\nendmodule\n\n"})}),"\n",(0,l.jsxs)(n.p,{children:['Partial specification is allowed, which results in "invalidated fields" as\ndescribed in ',(0,l.jsx)(n.a,{href:"../explanations/unconnected-wires",children:"Unconnected Wires"}),".\nNote that this can be used with ",(0,l.jsx)(n.code,{children:"RegInit"})," to construct partially reset registers as\ndescribed in the ",(0,l.jsx)(n.a,{href:"../cookbooks/cookbook#how-do-i-partially-reset-an-aggregate-reg",children:"Cookbook"}),"."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class Example2 extends RawModule {\n val out = IO(Output(new MyBundle))\n out := (new MyBundle).Lit(_.b -> true.B)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example2(\n output [7:0] out_a,\n output out_b\n);\n\n assign out_a = 8'h0;\n assign out_b = 1'h1;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.p,{children:"Bundle literals can also be nested arbitrarily."}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class ChildBundle extends Bundle {\n val foo = UInt(8.W)\n}\n\nclass ParentBundle extends Bundle {\n val a = UInt(8.W)\n val b = new ChildBundle\n}\n\nclass Example3 extends RawModule {\n val out = IO(Output(new ParentBundle))\n out := (new ParentBundle).Lit(_.a -> 123.U, _.b -> (new ChildBundle).Lit(_.foo -> 42.U))\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example3(\n output [7:0] out_a,\n out_b_foo\n);\n\n assign out_a = 8'h7B;\n assign out_b_foo = 8'h2A;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.h2,{id:"vec-literals",children:"Vec Literals"}),"\n",(0,l.jsx)(n.p,{children:"Vec literals are very similar to Bundle literals and can be constructed via an experimental import.\nThey can be constructed in two forms, with type and length inferred as in:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.VecLiterals._\n\nclass VecExample1 extends Module {\n val out = IO(Output(Vec(2, UInt(4.W))))\n out := Vec.Lit(0xa.U, 0xbb.U)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule VecExample1(\n input clock,\n reset,\n output [3:0] out_0,\n out_1\n);\n\n assign out_0 = 4'hA;\n assign out_1 = 4'hB;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.p,{children:"or explicitly as in:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.VecLiterals._\n\nclass VecExample1a extends Module {\n val out = IO(Output(Vec(2, UInt(4.W))))\n out := Vec(2, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule VecExample1a(\n input clock,\n reset,\n output [3:0] out_0,\n out_1\n);\n\n assign out_0 = 4'h1;\n assign out_1 = 4'h2;\nendmodule\n\n"})}),"\n",(0,l.jsxs)(n.p,{children:['The following examples all use the explicit form.\nWith the explicit form partial specification is allowed, which results in\n"invalidated fields" as described in ',(0,l.jsx)(n.a,{href:"../explanations/unconnected-wires",children:"Unconnected Wires"}),".\nNote that this can be used with ",(0,l.jsx)(n.code,{children:"RegInit"})," to construct partially reset registers as\ndescribed in the ",(0,l.jsx)(n.a,{href:"../cookbooks/cookbook#how-do-i-partially-reset-an-aggregate-reg",children:"Cookbook"}),"."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class VecExample2 extends RawModule {\n val out = IO(Output(Vec(4, UInt(4.W))))\n out := Vec(4, UInt(4.W)).Lit(0 -> 1.U, 3 -> 7.U)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule VecExample2(\n output [3:0] out_0,\n out_1,\n out_2,\n out_3\n);\n\n assign out_0 = 4'h1;\n assign out_1 = 4'h0;\n assign out_2 = 4'h0;\n assign out_3 = 4'h7;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.p,{children:"Registers can be initialized from Vec literals"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class VecExample3 extends Module {\n val out = IO(Output(Vec(4, UInt(8.W))))\n val y = RegInit(\n Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 1 -> 0xCD.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W))\n )\n out := y\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule VecExample3(\n input clock,\n reset,\n output [7:0] out_0,\n out_1,\n out_2,\n out_3\n);\n\n assign out_0 = 8'hAB;\n assign out_1 = 8'hCD;\n assign out_2 = 8'hEF;\n assign out_3 = 8'hFF;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.p,{children:"Vec literals can also be nested arbitrarily."}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class VecExample5 extends RawModule {\n val out = IO(Output(Vec(2, new ChildBundle)))\n out := Vec(2, new ChildBundle).Lit(\n 0 -> (new ChildBundle).Lit(_.foo -> 42.U),\n 1 -> (new ChildBundle).Lit(_.foo -> 7.U)\n )\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule VecExample5(\n output [7:0] out_0_foo,\n out_1_foo\n);\n\n assign out_0_foo = 8'h2A;\n assign out_1_foo = 8'h7;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.h2,{id:"loading-memories-for-simulation-or-fpga-initialization",children:"Loading Memories for simulation or FPGA initialization"}),"\n",(0,l.jsx)(n.h3,{id:"inline-initialization-with-external-file",children:"Inline initialization with external file"}),"\n",(0,l.jsxs)(n.p,{children:["Memories can be initialized by generating inline ",(0,l.jsx)(n.code,{children:"readmemh"})," or ",(0,l.jsx)(n.code,{children:"readmemb"})," statements in the output Verilog."]}),"\n",(0,l.jsxs)(n.p,{children:["The function ",(0,l.jsx)(n.code,{children:"loadMemoryFromFileInline"})," from ",(0,l.jsx)(n.code,{children:"chisel3.util.experimental"})," allows the memory to be initialized by the synthesis software from the specified file. Chisel does not validate the file contents nor its location. Both the memory initialization file and the Verilog source should be accessible for the toolchain."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.util.experimental.loadMemoryFromFileInline\n\nclass InitMemInline(memoryFile: String = "") extends Module {\n val width: Int = 32\n val io = IO(new Bundle {\n val enable = Input(Bool())\n val write = Input(Bool())\n val addr = Input(UInt(10.W))\n val dataIn = Input(UInt(width.W))\n val dataOut = Output(UInt(width.W))\n })\n\n val mem = SyncReadMem(1024, UInt(width.W))\n // Initialize memory\n if (memoryFile.trim().nonEmpty) {\n loadMemoryFromFileInline(mem, memoryFile)\n }\n io.dataOut := DontCare\n when(io.enable) {\n val rdwrPort = mem(io.addr)\n when (io.write) { rdwrPort := io.dataIn }\n .otherwise { io.dataOut := rdwrPort }\n }\n}\n'})}),"\n",(0,l.jsxs)(n.p,{children:["The default is to use ",(0,l.jsx)(n.code,{children:"$readmemh"})," (which assumes all numbers in the file are in ascii hex),\nbut to use ascii binary there is an optional ",(0,l.jsx)(n.code,{children:"hexOrBinary"})," argument which can be set to ",(0,l.jsx)(n.code,{children:"MemoryLoadFileType.Hex"})," or ",(0,l.jsx)(n.code,{children:"MemoryLoadFileType.Binary"}),". You will need to add an additional import."]}),"\n",(0,l.jsx)(n.h3,{id:"systemverilog-bind-initialization",children:"SystemVerilog Bind Initialization"}),"\n",(0,l.jsxs)(n.p,{children:["Chisel can also initialize memories by generating a SV bind module with ",(0,l.jsx)(n.code,{children:"readmemh"})," or ",(0,l.jsx)(n.code,{children:"readmemb"})," statements by using the function ",(0,l.jsx)(n.code,{children:"loadMemoryFromFile"})," from ",(0,l.jsx)(n.code,{children:"chisel3.util.experimental"}),"."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.experimental.loadMemoryFromFile\n\nclass InitMemBind(val bits: Int, val size: Int, filename: String) extends Module {\n val io = IO(new Bundle {\n val nia = Input(UInt(bits.W))\n val insn = Output(UInt(32.W))\n })\n\n val memory = Mem(size, UInt(32.W))\n io.insn := memory(io.nia >> 2);\n loadMemoryFromFile(memory, filename)\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"Which generates the bind module:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:'module BindsTo_0_Foo(\n input clock,\n input reset,\n input [31:0] io_nia,\n output [31:0] io_insn\n);\n\ninitial begin\n $readmemh("test.hex", Foo.memory);\nend\nendmodule\n\nbind Foo BindsTo_0_Foo BindsTo_0_Foo_Inst(.*);\n'})}),"\n",(0,l.jsx)(n.h3,{id:"notes-on-files",children:"Notes on files"}),"\n",(0,l.jsxs)(n.p,{children:["There is no simple answer to where to put the ",(0,l.jsx)(n.code,{children:"hex"})," or ",(0,l.jsx)(n.code,{children:"bin"})," file with the initial contents. It's probably best to create a resource directory somewhere and reference that through a full path or place the file beside the generated Verilog. Another option is adding the path to the memory file in the synthesis tool path. Because these files may be large, Chisel does not copy them."]}),"\n",(0,l.jsxs)(n.blockquote,{children:["\n",(0,l.jsx)(n.p,{children:"Don't forget there is no decimal option, so a 10 in an input file will be 16 decimal"}),"\n"]}),"\n",(0,l.jsxs)(n.p,{children:["See: ",(0,l.jsx)(n.a,{href:"https://github.com/freechipsproject/chisel-testers/blob/master/src/test/scala/examples/ComplexMemoryLoadingSpec.scala",children:"ComplexMemoryLoadingSpec.scala"})," and\n",(0,l.jsx)(n.a,{href:"https://github.com/freechipsproject/chisel-testers/blob/master/src/test/scala/examples/LoadMemoryFromFileSpec.scala",children:"LoadMemoryFromFileSpec.scala"}),"\nfor working examples."]}),"\n",(0,l.jsx)(n.h3,{id:"aggregate-memories",children:"Aggregate memories"}),"\n",(0,l.jsxs)(n.p,{children:["Aggregate memories are supported and will be lowered to a single wide ",(0,l.jsx)(n.code,{children:"UInt"}),". The memory loading file should be constructed to align with the final structure of the memory."]})]})}function u(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,l.jsx)(n,{...e,children:(0,l.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>s});var l=i(6540);const t={},a=l.createContext(t);function o(e){const n=l.useContext(a);return l.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(t):e.components||t:o(e.components),l.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c48de377.f67a205e.js b/assets/js/c48de377.f67a205e.js
deleted file mode 100644
index 7fefd0950db..00000000000
--- a/assets/js/c48de377.f67a205e.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[3316],{1429:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var l=i(4848),t=i(8453);const a={layout:"docs",title:"Experimental Features",section:"chisel3"},o="Experimental Features",s={id:"appendix/experimental-features",title:"Experimental Features",description:"Chisel has a number of new features that are worth checking out. This page is an informal list of these features and projects.",source:"@site/docs/appendix/experimental-features.md",sourceDirName:"appendix",slug:"/appendix/experimental-features",permalink:"/docs/appendix/experimental-features",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/appendix/experimental-features.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Experimental Features",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Migrating from ChiselTest",permalink:"/docs/appendix/migrating-from-chiseltest"},next:{title:"Upgrading From Chisel 3.4 to 3.5",permalink:"/docs/appendix/upgrading-from-chisel-3-4"}},r={},d=[{value:"Module Variants",id:"module-variants",level:2},{value:"Bundle Literals",id:"bundle-literals",level:2},{value:"Vec Literals",id:"vec-literals",level:2},{value:"Loading Memories for simulation or FPGA initialization",id:"loading-memories-for-simulation-or-fpga-initialization",level:2},{value:"Inline initialization with external file",id:"inline-initialization-with-external-file",level:3},{value:"SystemVerilog Bind Initialization",id:"systemverilog-bind-initialization",level:3},{value:"Notes on files",id:"notes-on-files",level:3},{value:"Aggregate memories",id:"aggregate-memories",level:3}];function c(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",ul:"ul",...(0,t.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.header,{children:(0,l.jsx)(n.h1,{id:"experimental-features",children:"Experimental Features"})}),"\n",(0,l.jsx)(n.p,{children:"Chisel has a number of new features that are worth checking out. This page is an informal list of these features and projects."}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"#module-variants",children:"Module Variants"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"#bundle-literals",children:"Bundle Literals"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"#vec-literals",children:"Vec Literals"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"#loading-memories-for-simulation-or-fpga-initialization",children:"Loading-Memories-for-simulation-or-FPGA-initialization"})}),"\n"]}),"\n",(0,l.jsx)(n.h2,{id:"module-variants",children:"Module Variants"}),"\n",(0,l.jsxs)(n.p,{children:["The standard Chisel ",(0,l.jsx)(n.em,{children:"Module"})," requires a ",(0,l.jsx)(n.code,{children:"val io = IO(...)"}),", the experimental package introduces several\nnew ways of defining Modules"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:"BaseModule: no contents, instantiable"}),"\n",(0,l.jsx)(n.li,{children:"BlackBox extends BaseModule"}),"\n",(0,l.jsx)(n.li,{children:"UserDefinedModule extends BaseModule: this module can contain Chisel RTL. No default clock or reset lines. No default IO. - User should be able to specify non-io ports, ideally multiple of them."}),"\n",(0,l.jsx)(n.li,{children:"ImplicitModule extends UserModule: has clock, reset, and io, essentially current Chisel Module."}),"\n",(0,l.jsx)(n.li,{children:"RawModule: will be the user-facing version of UserDefinedModule"}),"\n",(0,l.jsx)(n.li,{children:"Module: type-aliases to ImplicitModule, the user-facing version of ImplicitModule."}),"\n"]}),"\n",(0,l.jsx)(n.h2,{id:"bundle-literals",children:"Bundle Literals"}),"\n",(0,l.jsx)(n.p,{children:"Bundle literals can be constructed via an experimental import:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.BundleLiterals._\n\nclass MyBundle extends Bundle {\n val a = UInt(8.W)\n val b = Bool()\n}\n\nclass Example extends RawModule {\n val out = IO(Output(new MyBundle))\n out := (new MyBundle).Lit(_.a -> 8.U, _.b -> true.B)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example(\n output [7:0] out_a,\n output out_b\n);\n\n assign out_a = 8'h8;\n assign out_b = 1'h1;\nendmodule\n\n"})}),"\n",(0,l.jsxs)(n.p,{children:['Partial specification is allowed, which results in "invalidated fields" as\ndescribed in ',(0,l.jsx)(n.a,{href:"../explanations/unconnected-wires",children:"Unconnected Wires"}),".\nNote that this can be used with ",(0,l.jsx)(n.code,{children:"RegInit"})," to construct partially reset registers as\ndescribed in the ",(0,l.jsx)(n.a,{href:"../cookbooks/cookbook#how-do-i-partially-reset-an-aggregate-reg",children:"Cookbook"}),"."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class Example2 extends RawModule {\n val out = IO(Output(new MyBundle))\n out := (new MyBundle).Lit(_.b -> true.B)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example2(\n output [7:0] out_a,\n output out_b\n);\n\n assign out_a = 8'h0;\n assign out_b = 1'h1;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.p,{children:"Bundle literals can also be nested arbitrarily."}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class ChildBundle extends Bundle {\n val foo = UInt(8.W)\n}\n\nclass ParentBundle extends Bundle {\n val a = UInt(8.W)\n val b = new ChildBundle\n}\n\nclass Example3 extends RawModule {\n val out = IO(Output(new ParentBundle))\n out := (new ParentBundle).Lit(_.a -> 123.U, _.b -> (new ChildBundle).Lit(_.foo -> 42.U))\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example3(\n output [7:0] out_a,\n out_b_foo\n);\n\n assign out_a = 8'h7B;\n assign out_b_foo = 8'h2A;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.h2,{id:"vec-literals",children:"Vec Literals"}),"\n",(0,l.jsx)(n.p,{children:"Vec literals are very similar to Bundle literals and can be constructed via an experimental import.\nThey can be constructed in two forms, with type and length inferred as in:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.VecLiterals._\n\nclass VecExample1 extends Module {\n val out = IO(Output(Vec(2, UInt(4.W))))\n out := Vec.Lit(0xa.U, 0xbb.U)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule VecExample1(\n input clock,\n reset,\n output [3:0] out_0,\n out_1\n);\n\n assign out_0 = 4'hA;\n assign out_1 = 4'hB;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.p,{children:"or explicitly as in:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.VecLiterals._\n\nclass VecExample1a extends Module {\n val out = IO(Output(Vec(2, UInt(4.W))))\n out := Vec(2, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule VecExample1a(\n input clock,\n reset,\n output [3:0] out_0,\n out_1\n);\n\n assign out_0 = 4'h1;\n assign out_1 = 4'h2;\nendmodule\n\n"})}),"\n",(0,l.jsxs)(n.p,{children:['The following examples all use the explicit form.\nWith the explicit form partial specification is allowed, which results in\n"invalidated fields" as described in ',(0,l.jsx)(n.a,{href:"../explanations/unconnected-wires",children:"Unconnected Wires"}),".\nNote that this can be used with ",(0,l.jsx)(n.code,{children:"RegInit"})," to construct partially reset registers as\ndescribed in the ",(0,l.jsx)(n.a,{href:"../cookbooks/cookbook#how-do-i-partially-reset-an-aggregate-reg",children:"Cookbook"}),"."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class VecExample2 extends RawModule {\n val out = IO(Output(Vec(4, UInt(4.W))))\n out := Vec(4, UInt(4.W)).Lit(0 -> 1.U, 3 -> 7.U)\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule VecExample2(\n output [3:0] out_0,\n out_1,\n out_2,\n out_3\n);\n\n assign out_0 = 4'h1;\n assign out_1 = 4'h0;\n assign out_2 = 4'h0;\n assign out_3 = 4'h7;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.p,{children:"Registers can be initialized from Vec literals"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class VecExample3 extends Module {\n val out = IO(Output(Vec(4, UInt(8.W))))\n val y = RegInit(\n Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 1 -> 0xCD.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W))\n )\n out := y\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule VecExample3(\n input clock,\n reset,\n output [7:0] out_0,\n out_1,\n out_2,\n out_3\n);\n\n assign out_0 = 8'hAB;\n assign out_1 = 8'hCD;\n assign out_2 = 8'hEF;\n assign out_3 = 8'hFF;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.p,{children:"Vec literals can also be nested arbitrarily."}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class VecExample5 extends RawModule {\n val out = IO(Output(Vec(2, new ChildBundle)))\n out := Vec(2, new ChildBundle).Lit(\n 0 -> (new ChildBundle).Lit(_.foo -> 42.U),\n 1 -> (new ChildBundle).Lit(_.foo -> 7.U)\n )\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule VecExample5(\n output [7:0] out_0_foo,\n out_1_foo\n);\n\n assign out_0_foo = 8'h2A;\n assign out_1_foo = 8'h7;\nendmodule\n\n"})}),"\n",(0,l.jsx)(n.h2,{id:"loading-memories-for-simulation-or-fpga-initialization",children:"Loading Memories for simulation or FPGA initialization"}),"\n",(0,l.jsx)(n.h3,{id:"inline-initialization-with-external-file",children:"Inline initialization with external file"}),"\n",(0,l.jsxs)(n.p,{children:["Memories can be initialized by generating inline ",(0,l.jsx)(n.code,{children:"readmemh"})," or ",(0,l.jsx)(n.code,{children:"readmemb"})," statements in the output Verilog."]}),"\n",(0,l.jsxs)(n.p,{children:["The function ",(0,l.jsx)(n.code,{children:"loadMemoryFromFileInline"})," from ",(0,l.jsx)(n.code,{children:"chisel3.util.experimental"})," allows the memory to be initialized by the synthesis software from the specified file. Chisel does not validate the file contents nor its location. Both the memory initialization file and the Verilog source should be accessible for the toolchain."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.util.experimental.loadMemoryFromFileInline\n\nclass InitMemInline(memoryFile: String = "") extends Module {\n val width: Int = 32\n val io = IO(new Bundle {\n val enable = Input(Bool())\n val write = Input(Bool())\n val addr = Input(UInt(10.W))\n val dataIn = Input(UInt(width.W))\n val dataOut = Output(UInt(width.W))\n })\n\n val mem = SyncReadMem(1024, UInt(width.W))\n // Initialize memory\n if (memoryFile.trim().nonEmpty) {\n loadMemoryFromFileInline(mem, memoryFile)\n }\n io.dataOut := DontCare\n when(io.enable) {\n val rdwrPort = mem(io.addr)\n when (io.write) { rdwrPort := io.dataIn }\n .otherwise { io.dataOut := rdwrPort }\n }\n}\n'})}),"\n",(0,l.jsxs)(n.p,{children:["The default is to use ",(0,l.jsx)(n.code,{children:"$readmemh"})," (which assumes all numbers in the file are in ascii hex),\nbut to use ascii binary there is an optional ",(0,l.jsx)(n.code,{children:"hexOrBinary"})," argument which can be set to ",(0,l.jsx)(n.code,{children:"MemoryLoadFileType.Hex"})," or ",(0,l.jsx)(n.code,{children:"MemoryLoadFileType.Binary"}),". You will need to add an additional import."]}),"\n",(0,l.jsx)(n.h3,{id:"systemverilog-bind-initialization",children:"SystemVerilog Bind Initialization"}),"\n",(0,l.jsxs)(n.p,{children:["Chisel can also initialize memories by generating a SV bind module with ",(0,l.jsx)(n.code,{children:"readmemh"})," or ",(0,l.jsx)(n.code,{children:"readmemb"})," statements by using the function ",(0,l.jsx)(n.code,{children:"loadMemoryFromFile"})," from ",(0,l.jsx)(n.code,{children:"chisel3.util.experimental"}),"."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.experimental.loadMemoryFromFile\n\nclass InitMemBind(val bits: Int, val size: Int, filename: String) extends Module {\n val io = IO(new Bundle {\n val nia = Input(UInt(bits.W))\n val insn = Output(UInt(32.W))\n })\n\n val memory = Mem(size, UInt(32.W))\n io.insn := memory(io.nia >> 2);\n loadMemoryFromFile(memory, filename)\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"Which generates the bind module:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:'module BindsTo_0_Foo(\n input clock,\n input reset,\n input [31:0] io_nia,\n output [31:0] io_insn\n);\n\ninitial begin\n $readmemh("test.hex", Foo.memory);\nend\nendmodule\n\nbind Foo BindsTo_0_Foo BindsTo_0_Foo_Inst(.*);\n'})}),"\n",(0,l.jsx)(n.h3,{id:"notes-on-files",children:"Notes on files"}),"\n",(0,l.jsxs)(n.p,{children:["There is no simple answer to where to put the ",(0,l.jsx)(n.code,{children:"hex"})," or ",(0,l.jsx)(n.code,{children:"bin"})," file with the initial contents. It's probably best to create a resource directory somewhere and reference that through a full path or place the file beside the generated Verilog. Another option is adding the path to the memory file in the synthesis tool path. Because these files may be large, Chisel does not copy them."]}),"\n",(0,l.jsxs)(n.blockquote,{children:["\n",(0,l.jsx)(n.p,{children:"Don't forget there is no decimal option, so a 10 in an input file will be 16 decimal"}),"\n"]}),"\n",(0,l.jsxs)(n.p,{children:["See: ",(0,l.jsx)(n.a,{href:"https://github.com/freechipsproject/chisel-testers/blob/master/src/test/scala/examples/ComplexMemoryLoadingSpec.scala",children:"ComplexMemoryLoadingSpec.scala"})," and\n",(0,l.jsx)(n.a,{href:"https://github.com/freechipsproject/chisel-testers/blob/master/src/test/scala/examples/LoadMemoryFromFileSpec.scala",children:"LoadMemoryFromFileSpec.scala"}),"\nfor working examples."]}),"\n",(0,l.jsx)(n.h3,{id:"aggregate-memories",children:"Aggregate memories"}),"\n",(0,l.jsxs)(n.p,{children:["Aggregate memories are supported and will be lowered to a single wide ",(0,l.jsx)(n.code,{children:"UInt"}),". The memory loading file should be constructed to align with the final structure of the memory."]})]})}function u(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,l.jsx)(n,{...e,children:(0,l.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>s});var l=i(6540);const t={},a=l.createContext(t);function o(e){const n=l.useContext(a);return l.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(t):e.components||t:o(e.components),l.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c7666d49.4bc58ceb.js b/assets/js/c7666d49.edd1fd74.js
similarity index 60%
rename from assets/js/c7666d49.4bc58ceb.js
rename to assets/js/c7666d49.edd1fd74.js
index 213342d362f..0ec3d606cd6 100644
--- a/assets/js/c7666d49.4bc58ceb.js
+++ b/assets/js/c7666d49.edd1fd74.js
@@ -1 +1 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[6474],{6458:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>t,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var r=i(4848),a=i(8453);const o={layout:"docs",title:"Layers",section:"chisel3"},l="Layers",s={id:"explanations/layers",title:"Layers",description:"Layers describe functionality of a Chisel generator that a user would like to",source:"@site/docs/explanations/layers.md",sourceDirName:"explanations",slug:"/explanations/layers",permalink:"/docs/explanations/layers",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/layers.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Layers",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Intrinsics",permalink:"/docs/explanations/intrinsics"},next:{title:"Memories",permalink:"/docs/explanations/memories"}},t={},c=[{value:"Overview",id:"overview",level:2},{value:"Verilog ABI",id:"verilog-abi",level:2},{value:"Extract Layers",id:"extract-layers",level:3},{value:"Inline Layers",id:"inline-layers",level:3},{value:"User-defined Layers",id:"user-defined-layers",level:2},{value:"Built-in Layers",id:"built-in-layers",level:2},{value:"Layer-coloring",id:"layer-coloring",level:2},{value:"Layer-colored Probes and Wires",id:"layer-colored-probes-and-wires",level:3},{value:"Enabling Layers",id:"enabling-layers",level:3},{value:"Examples",id:"examples",level:2},{value:"Simple Extract Layer",id:"simple-extract-layer",level:3},{value:"Simple Inline Layer",id:"simple-inline-layer",level:3},{value:"Design Verification Example",id:"design-verification-example",level:3},{value:"Implementation Notes",id:"implementation-notes",level:4},{value:"Verilog Output",id:"verilog-output",level:4}];function d(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"layers",children:"Layers"})}),"\n",(0,r.jsxs)(n.p,{children:["Layers describe functionality of a Chisel generator that a user would like to\n",(0,r.jsx)(n.em,{children:"optionally"})," include at Verilog elaboration time. Pragmatically, they are a\nfeature to access SystemVerilog's ",(0,r.jsx)(n.code,{children:"bind"})," construct and ",(0,r.jsx)(n.code,{children:"`ifdef"})," preprocessor\nmacros. The optional functionality of layers, by construction, is not allowed\nto affect logic outside the layer."]}),"\n",(0,r.jsx)(n.p,{children:"Layers are typically used to describe design verification code or\ndebugging logic that a user would like to be able to later disable (for\nperformance, verbosity, or cleanliness reasons) or use internally, but exclude\nfrom delivery to a customer."}),"\n",(0,r.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,r.jsx)(n.p,{children:"A layer consists of two pieces:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["A layer ",(0,r.jsx)(n.em,{children:"declaration"}),", and"]}),"\n",(0,r.jsxs)(n.li,{children:["One or more ",(0,r.jsx)(n.em,{children:"layer blocks"})," inside Chisel modules."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"The declaration indicates that optional functionality can exist. The layer\nblock contains the optional functionality."}),"\n",(0,r.jsxs)(n.p,{children:["There are two kinds of layers. The layer kind determines the ",(0,r.jsx)(n.em,{children:"convention"}),",\ni.e., how the layer blocks of a layer are represented in Verilog and the\nmechanism to enable a layer. Available layer kinds are:"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:['"Extract" Layers: layers whose blocks are lowered to modules that are\ninstantiated using ',(0,r.jsx)(n.code,{children:"bind"})," and can be enabled by including a file during\nVerilog elaboration, and"]}),"\n",(0,r.jsxs)(n.li,{children:['"Inline" Layers: layers whose blocks will be guarded with ',(0,r.jsx)(n.code,{children:"`ifdef"})," macros\nand can be enabled by setting a Verilog preprocessor define."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Extract layers may also specify a directory into which their collateral are\nwritten."}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["For more information about these SystemVerilog concepts, the IEEE 1800-2023\nstandard discusses ",(0,r.jsx)(n.code,{children:"bind"})," in Section 23.11 and ",(0,r.jsx)(n.code,{children:"`ifdef"})," in Section 23.6."]})}),"\n",(0,r.jsxs)(n.p,{children:["To declare a layer, create a singleton ",(0,r.jsx)(n.code,{children:"object"})," in scala that extends the\nabstract class ",(0,r.jsx)(n.code,{children:"chisel3.layer.Layer"}),", passing into the layer constructor either\nan object of class ",(0,r.jsx)(n.code,{children:"chisel3.layer.LayerConfig.Extract"})," for an extract layer, or\nthe object ",(0,r.jsx)(n.code,{children:"chisel3.layer.LayerConfig.Inline"})," for an inline layer."]}),"\n",(0,r.jsx)(n.p,{children:"Below, an extract layer and an inline layer are declared:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"import chisel3.layer.{Layer, LayerConfig}\n\nobject A extends Layer(LayerConfig.Extract())\n\nobject B extends Layer(LayerConfig.Inline)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Layers may be nested. Nesting a child layer under a parent layer means that the\nchild layer may access constructs in the parent layer. Put differently, the\nchild layer will only be enabled if the parent layer is already enabled. To\ndeclare a nested layer, extend the ",(0,r.jsx)(n.code,{children:"chisel3.layer.Layer"})," abstract class inside\nanother declaration."]}),"\n",(0,r.jsx)(n.p,{children:"The following example defines an extract layer with two nested layers inside it:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"object C extends Layer(LayerConfig.Extract()) {\n object D extends Layer(LayerConfig.Extract())\n object E extends Layer(LayerConfig.Inline) {\n object F extends Layer(LayerConfig.Inline)\n }\n}\n"})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["SystemVerilog prohibits a ",(0,r.jsx)(n.code,{children:"bind"})," instantiation under another ",(0,r.jsx)(n.code,{children:"bind"}),"\ninstantiation. However, Chisel allows nesting of extract layers. This is\nresolved by the FIRRTL compiler to restructure nested extract layers to be\nsibling modules that communicate via ports."]})}),"\n",(0,r.jsxs)(n.admonition,{type:"warning",children:[(0,r.jsx)(n.p,{children:"Extract layers may not be nested under inline layers. However, inline layers\nmay be nested under extract layers."}),(0,r.jsx)(n.p,{children:"Any module which contains layer blocks or transitively contains layer blocks in\nits submodules may not be instantiated under a layer block."})]}),"\n",(0,r.jsxs)(n.p,{children:["A ",(0,r.jsx)(n.em,{children:"layer block"}),", associated with a layer, adds optional functionality to a\nmodule that is enabled if that layer is enabled. To define a layer block, use\nthe ",(0,r.jsx)(n.code,{children:"chisel3.layer.block"})," inside a Chisel module and pass the layer that it\nshould be associated with."]}),"\n",(0,r.jsx)(n.p,{children:"Inside the layer block, any Chisel or Scala value visible in lexical scope may\nbe used. Layer blocks may not return values. Any values created inside a layer\nblock are not accessible outside the layer block, unless using layer-colored\nprobes."}),"\n",(0,r.jsxs)(n.p,{children:["The following example defines layer blocks inside module ",(0,r.jsx)(n.code,{children:"Foo"}),". Each layer\nblock contains a wire that captures a value from its visible lexical scope.\n(For nested layer blocks, this scope includes their parent layer blocks.):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.layer.block\n\nclass Foo extends RawModule {\n val port = IO(Input(Bool()))\n\n block(A) {\n val a = WireInit(port)\n }\n\n block(B) {\n val b = WireInit(port)\n }\n\n block(C) {\n val c = WireInit(port)\n block(C.D) {\n val d = WireInit(port | c)\n }\n block(C.E) {\n val e = WireInit(port ^ c)\n block (C.E.F) {\n val f = WireInit(port & e)\n }\n }\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The layer block API will automatically create parent layer blocks for you if\npossible. In the following example, it is legal to directly create a layer\nblock of ",(0,r.jsx)(n.code,{children:"C.D"})," directly in a module:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"class Bar extends RawModule {\n block (C.D) {}\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Formally, it is legal to create a layer block associated with a layer as long as\nthe current scope is an ",(0,r.jsx)(n.em,{children:"ancestor"})," of the request layer."]}),"\n",(0,r.jsxs)(n.admonition,{type:"info",children:[(0,r.jsxs)(n.p,{children:["The requirement is an ",(0,r.jsx)(n.em,{children:"ancestor"})," relationship, not a ",(0,r.jsx)(n.em,{children:"proper ancestor"}),"\nrelationship. This means that it is legal to nest a layer block under a layer\nblock of the same layer like:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"class Baz extends RawModule {\n block(A) {\n block(A) {}\n }\n}\n"})})]}),"\n",(0,r.jsx)(n.h2,{id:"verilog-abi",children:"Verilog ABI"}),"\n",(0,r.jsx)(n.p,{children:"Layers are compiled to SystemVerilog using the FIRRTL ABI. This ABI defines\nwhat happens to layer blocks in a Chisel design and how a layer can be enabled\nafter a design is compiled to SystemVerilog."}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["For the exact definition of the FIRRTL ABI for layers, see the ",(0,r.jsx)(n.a,{href:"https://github.com/chipsalliance/firrtl-spec/releases/latest/download/abi.pdf",children:"FIRRTL ABI\nSpecification"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"extract-layers",children:"Extract Layers"}),"\n",(0,r.jsxs)(n.p,{children:["Extract layers have their layer blocks removed from the design. To enable a\nlayer, a file with a specific name should be included in the design. This file\nbegins with ",(0,r.jsx)(n.code,{children:"layers-"})," and then includes the circuit name and all layer names\ndelimited with dashes (",(0,r.jsx)(n.code,{children:"-"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, for module ",(0,r.jsx)(n.code,{children:"Foo"})," declared above, this will produce three files, one\nfor each extract layer:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"layers-Foo-A.sv\nlayers-Foo-C.sv\nlayers-Foo-C-D.sv\n"})}),"\n",(0,r.jsx)(n.p,{children:"To enable any of these layers at compilation time, the appropriate file should\nbe included in the build. Any combination of files may be included. Including\nonly a child layer's file will automatically include its parent layer's file."}),"\n",(0,r.jsx)(n.h3,{id:"inline-layers",children:"Inline Layers"}),"\n",(0,r.jsxs)(n.p,{children:["Inline layers have their layer blocks guarded with conditional compilation\ndirectives. To enable an inline layer, set a preprocessor define when compiling\nyour design. The preprocessor define begins with ",(0,r.jsx)(n.code,{children:"layer_"})," and then includes the\ncircuit name and all layer names delimited with dollar signs (",(0,r.jsx)(n.code,{children:"$"}),"). Parent\nextract layer names appear in the macro."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, for module ",(0,r.jsx)(n.code,{children:"Foo"})," declared above, this will be sensitive to three\nmacros, one for each inline layer:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"layer_Foo$B\nlayer_Foo$C$E\nlayer_Foo$C$E$F\n"})}),"\n",(0,r.jsx)(n.h2,{id:"user-defined-layers",children:"User-defined Layers"}),"\n",(0,r.jsxs)(n.p,{children:["A user is free to define as many layers as they want. All layers shown\npreviously are user-defined, e.g., ",(0,r.jsx)(n.code,{children:"A"})," and ",(0,r.jsx)(n.code,{children:"C.E"})," are user-defined layers.\nUser-defined layers are only emitted into FIRRTL if they have layer block users.\nTo change this behavior and unconditionally emit a user-defined layer, use the\n",(0,r.jsx)(n.code,{children:"chisel3.layer.addLayer"})," API."]}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsx)(n.p,{children:"Before creating new user-defined layers, consider using the built-in layers\ndefined below. Additionally, if working in a larger project, the project may\nhave it's own user-defined layers that you are expected to use. This is because\nthe ABIs affect the build system. Please consult with a technical lead of the\nproject to see if this is the case."})}),"\n",(0,r.jsx)(n.h2,{id:"built-in-layers",children:"Built-in Layers"}),"\n",(0,r.jsx)(n.p,{children:"Chisel provides several built-in layers. These are shown below with their full\nScala paths. All built-in layers are extract layers:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"chisel3.layers.Verification\n\u251c\u2500\u2500 chisel3.layers.Verification.Assert\n\u251c\u2500\u2500 chisel3.layers.Verification.Assume\n\u2514\u2500\u2500 chisel3.layers.Verification.Cover\n"})}),"\n",(0,r.jsxs)(n.p,{children:["These built-in layers are dual purpose. First, these layers match the common\nuse case of sequestering verification code. The ",(0,r.jsx)(n.code,{children:"Verification"})," layer is for\ncommon verification collateral. The ",(0,r.jsx)(n.code,{children:"Assert"}),", ",(0,r.jsx)(n.code,{children:"Assume"}),", and ",(0,r.jsx)(n.code,{children:"Cover"})," layers are\nfor, respectively, assertions, assumptions, and cover statements. Second, the\nChisel standard library uses them for a number of its APIs. ",(0,r.jsx)(n.em,{children:"Unless otherwise\nwrapped in a different layer block, the following operations are automatically\nplaced in layers"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Prints are placed in the ",(0,r.jsx)(n.code,{children:"Verification"})," layer"]}),"\n",(0,r.jsxs)(n.li,{children:["Assertions are placed in the ",(0,r.jsx)(n.code,{children:"Verification.Assert"})," layer"]}),"\n",(0,r.jsxs)(n.li,{children:["Assumptions are placed in the ",(0,r.jsx)(n.code,{children:"Verification.Assume"})," layer"]}),"\n",(0,r.jsxs)(n.li,{children:["Covers are placed in the ",(0,r.jsx)(n.code,{children:"Verification.Cover"})," layer"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["For predictability of output, these layers will always be show up in the FIRRTL\nthat Chisel emits. To change this behavior, use ",(0,r.jsx)(n.code,{children:"firtool"})," command line options\nto ",(0,r.jsx)(n.em,{children:"specialize"})," these layers (remove their optionality by making them always\nenabled or disabled). Use ",(0,r.jsx)(n.code,{children:"-enable-layers"})," to enable a layer, ",(0,r.jsx)(n.code,{children:"-disable-layers"}),"\nto disable a layer, or ",(0,r.jsx)(n.code,{children:"-default-layer-specialization"})," to set a default\nspecialization."]}),"\n",(0,r.jsxs)(n.admonition,{type:"tip",children:[(0,r.jsx)(n.p,{children:"Users may extend built-in layers with user-defined layers using an advanced API.\nTo do this, the layer parent must be specified as an implicit value."}),(0,r.jsxs)(n.p,{children:["The following example nests the layer ",(0,r.jsx)(n.code,{children:"Debug"})," to the ",(0,r.jsx)(n.code,{children:"Verification"})," layer:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"object UserDefined {\n // Define an implicit val `root` of type `Layer` to cause layers which can see\n // this to use `root` as their parent layer. This allows us to nest the\n // user-defined `Debug` layer under the built-in `Verification` layer.\n implicit val root: Layer = chisel3.layers.Verification\n object Debug extends Layer(LayerConfig.Inline)\n}\n"})})]}),"\n",(0,r.jsx)(n.h2,{id:"layer-coloring",children:"Layer-coloring"}),"\n",(0,r.jsxs)(n.p,{children:["While layers are not allowed to influence the design or their parent layers, it\nis often useful and necessary to allow layer blocks to send information out of\ntheir containing modules to be read by layer blocks of the same layer or\nchildren layers. Hardware which has this optional property is said to be\n",(0,r.jsx)(n.em,{children:"layer-colored"}),". Both probes and wires can be layer-colored."]}),"\n",(0,r.jsx)(n.h3,{id:"layer-colored-probes-and-wires",children:"Layer-colored Probes and Wires"}),"\n",(0,r.jsx)(n.p,{children:"A layer-colored probe is a probe that exists if a user enables its corresponding\nlayer during Verilog elaboration. Layer-colored probes are used to describe\noptional verification, debugging, or logging interfaces."}),"\n",(0,r.jsx)(n.p,{children:"Layer-colored wires are used as temporary storage of defined probe values. They\nare used for communication between layer blocks of the same layer in the same\nmodule or as temporary storage when forwarding a probe to a port."}),"\n",(0,r.jsxs)(n.p,{children:["A layer-colored probe or wire may be the target of a ",(0,r.jsx)(n.code,{children:"define"})," if the ",(0,r.jsx)(n.code,{children:"define"})," is\nenabled when the color of the probe or wire is enabled. A layer-colored probe\nor wire may be ",(0,r.jsx)(n.code,{children:"read"})," from if the color of the probe or wire is enabled when the\n",(0,r.jsx)(n.code,{children:"read"})," is enabled. Put differently, you may write to your layer or a child\nlayer and you may read from your layer or a parent layer."]}),"\n",(0,r.jsx)(n.p,{children:"The example below shows two layer-colored probe ports and one layer-colored\nprobe wire driven in legal ways:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.layer.{Layer, LayerConfig}\nimport chisel3.probe.{Probe, ProbeValue, define}\n\nobject A extends Layer(LayerConfig.Extract())\nobject B extends Layer(LayerConfig.Extract())\n\nclass Foo extends RawModule {\n val a = IO(Output(Probe(Bool(), A)))\n val b = IO(Output(Probe(Bool(), B)))\n\n layer.block(A) {\n val a_wire = WireInit(false.B)\n define(a, ProbeValue(a_wire))\n }\n\n val b_wire_probe = Wire(Probe(Bool(), B))\n define(b, b_wire_probe)\n\n layer.block(B) {\n val b_wire = WireInit(false.B)\n define(b_wire_probe, ProbeValue(b_wire))\n }\n\n}\n"})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["For more information, see the layer coloring section of the ",(0,r.jsx)(n.a,{href:"https://github.com/chipsalliance/firrtl-spec/releases/latest/download/spec.pdf",children:"FIRRTL\nSpecification"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"enabling-layers",children:"Enabling Layers"}),"\n",(0,r.jsxs)(n.p,{children:["When working with layer-colored probes, it is often convenient to grant access\nto probes of one or more colors. E.g., testbenches often want to ",(0,r.jsx)(n.em,{children:"enable"})," all\nlayers in a design-under-test so that they gain access to layer-colored probe\nports necessary for advanced design verification. Without an additional\nfeature, this use case is poorly supported with just layer coloring. First, it\nis tedious to enclose all code inside a testbench in a layer block. Second, a\ntestbench may need to read probes with colors that do not have a parent--child\nrelationship. No layer block is capable of both legally reading from different\nprobes and combining the results."]}),"\n",(0,r.jsxs)(n.p,{children:["To support this use case, Chisel provides the ",(0,r.jsx)(n.code,{children:"layer.enable"})," API. This API\ngrants access to any layer-colored probes of instantiated modules for the\nenabled layer. The API may be used more than once to enable more than one\nlayer."]}),"\n",(0,r.jsxs)(n.p,{children:["The example below instantiates module ",(0,r.jsx)(n.code,{children:"Foo"})," from the previous section. After\nenabling layers ",(0,r.jsx)(n.code,{children:"A"})," and ",(0,r.jsx)(n.code,{children:"B"}),", the module can read from probes with colors ",(0,r.jsx)(n.code,{children:"A"})," and\n",(0,r.jsx)(n.code,{children:"B"})," and use their results in a single operation:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"import chisel3.layer.enable\nimport chisel3.probe.read\n\nclass Bar extends RawModule {\n\n enable(A)\n enable(B)\n\n val foo = Module(new Foo)\n\n val c = read(foo.a) ^ read(foo.b)\n\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,r.jsx)(n.h3,{id:"simple-extract-layer",children:"Simple Extract Layer"}),"\n",(0,r.jsxs)(n.p,{children:["The design below has a single extract layer that, when enabled, will add an\nassert that checks for overflow. Based on the FIRRTL ABI, we can expect that a\nfile called ",(0,r.jsx)(n.code,{children:"layers-Foo-A.sv"})," will be produced when we compile it."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.layer.{Layer, LayerConfig, block}\nimport chisel3.ltl.AssertProperty\n\nobject A extends Layer(LayerConfig.Extract())\n\nclass Foo extends Module {\n val a, b = IO(Input(UInt(4.W)))\n val sum = IO(Output(UInt(4.W)))\n\n sum :<= a +% b\n\n block(A) {\n withDisable(Disable.Never) {\n AssertProperty(!(a +& b)(4), "overflow occurred")\n }\n }\n\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["After compilation, we get the following SystemVerilog. Comments that include\n",(0,r.jsx)(n.code,{children:"FILE"})," indicate the beginning of a new file:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-verilog",children:'// Generated by CIRCT firtool-1.99.2\nmodule Foo(\n input clock,\n reset,\n input [3:0] a,\n b,\n output [3:0] sum\n);\n\n wire [4:0] _sum_T = {1\'h0, a} + {1\'h0, b};\n assign sum = _sum_T[3:0];\nendmodule\n\n\n// ----- 8< ----- FILE "A/layers-Foo-A.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\n`ifndef layers_Foo_A\n`define layers_Foo_A\nbind Foo Foo_A a_0 (\n ._GEN (_sum_T),\n .clock (clock)\n);\n`endif // layers_Foo_A\n\n// ----- 8< ----- FILE "A/Foo_A.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\nmodule Foo_A(\n input [4:0] _GEN,\n input clock\n);\n\n overflow_occurred: assert property (@(posedge clock) ~(_GEN[4]));\nendmodule\n\n'})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["The above example was compiled with the firtool options\n",(0,r.jsx)(n.code,{children:"-enable-layers=Verification"}),", ",(0,r.jsx)(n.code,{children:"-enable-layers=Verification.Assert"}),",\n",(0,r.jsx)(n.code,{children:"-enable-layers=Verification.Assume"}),", and ",(0,r.jsx)(n.code,{children:"-enable-layers=Verification.Cover"})," to\nmake the output terser. Normally, bind files would show up for these built-in\nlayers."]})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["Note: the generated module, ",(0,r.jsx)(n.code,{children:"Foo_A"}),", and its file, ",(0,r.jsx)(n.code,{children:"Foo_A.sv"}),", are ",(0,r.jsx)(n.em,{children:"not part of\nthe ABI"}),". You should not rely on any generated module names or files other than\nthe bind file, ",(0,r.jsx)(n.code,{children:"layers-Foo-A.sv"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"simple-inline-layer",children:"Simple Inline Layer"}),"\n",(0,r.jsxs)(n.p,{children:["The design below is the same as the previous example, but uses an inline layer.\nBased on the FIRRTL ABI, we can expect that the body of the layer block will be\nguarded by an ",(0,r.jsx)(n.code,{children:"`ifdef"})," sensitive to the preprocessor macro ",(0,r.jsx)(n.code,{children:"layer_Foo$A"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.layer.{Layer, LayerConfig, block}\nimport chisel3.ltl.AssertProperty\n\nobject A extends Layer(LayerConfig.Inline)\n\nclass Foo extends Module {\n val a, b = IO(Input(UInt(4.W)))\n val sum = IO(Output(UInt(4.W)))\n\n sum :<= a +% b\n\n block(A) {\n withDisable(Disable.Never) {\n AssertProperty(!(a +& b)(4), "overflow occurred")\n }\n }\n\n}\n'})}),"\n",(0,r.jsx)(n.p,{children:"After compilation, we get the following SystemVerilog."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Foo(\n input clock,\n reset,\n input [3:0] a,\n b,\n output [3:0] sum\n);\n\n wire [4:0] _sum_T = {1'h0, a} + {1'h0, b};\n `ifdef layer_Foo$A\n overflow_occurred: assert property (@(posedge clock) ~(_sum_T[4]));\n `endif // layer_Foo$A\n assign sum = _sum_T[3:0];\nendmodule\n\n"})}),"\n",(0,r.jsx)(n.h3,{id:"design-verification-example",children:"Design Verification Example"}),"\n",(0,r.jsx)(n.p,{children:"Consider a use case where a design or design verification engineer would like to\nadd some asserts and debug prints to a module. The logic necessary for the\nasserts and debug prints requires additional computation. All of this code\nshould selectively included at Verilog elaboration time (not at Chisel\nelaboration time). The engineer can use three layers to do this."}),"\n",(0,r.jsx)(n.p,{children:"There are three layers used in this example:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["The built-in ",(0,r.jsx)(n.code,{children:"Verification"})," layer"]}),"\n",(0,r.jsxs)(n.li,{children:["The built-in ",(0,r.jsx)(n.code,{children:"Assert"})," layer which is nested under the built-in ",(0,r.jsx)(n.code,{children:"Verification"}),"\nlayer"]}),"\n",(0,r.jsxs)(n.li,{children:["A user-defined ",(0,r.jsx)(n.code,{children:"Debug"})," layer which is also nested under the built-in\n",(0,r.jsx)(n.code,{children:"Verification"})," layer"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"Verification"})," layer can be used to store common logic used by both the\n",(0,r.jsx)(n.code,{children:"Assert"})," and ",(0,r.jsx)(n.code,{children:"Debug"})," layers. The latter two layers allow for separation of,\nrespectively, assertions from prints."]}),"\n",(0,r.jsx)(n.p,{children:"One way to write this in Scala is the following:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.layer.{Layer, LayerConfig, block}\nimport chisel3.layers.Verification\n\n// User-defined layers are declared here. Built-in layers do not need to be declared.\nobject UserDefined {\n implicit val root: Layer = Verification\n object Debug extends Layer(LayerConfig.Inline)\n}\n\nclass Foo extends Module {\n val a = IO(Input(UInt(32.W)))\n val b = IO(Output(UInt(32.W)))\n\n b := a +% 1.U\n\n // This adds a `Verification` layer block inside Foo.\n block(Verification) {\n\n // Some common logic added here. The input port `a` is "captured" and\n // used here.\n val a_d0 = RegNext(a)\n\n // This adds an `Assert` layer block.\n block(Verification.Assert) {\n chisel3.assert(a >= a_d0, "a must always increment")\n }\n\n // This adds a `Debug` layer block.\n block(UserDefined.Debug) {\n printf("a: %x, a_d0: %x", a, a_d0)\n }\n\n }\n\n}\n\n'})}),"\n",(0,r.jsx)(n.p,{children:"After compilation, this will produce two layer include files with the\nfollowing filenames. One file is created for each extract layer:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"layers_Foo_Verification.sv"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"layers_Foo_Verification_Assert.sv"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Additionally, the resulting SystemVerilog will be sensitive to the preprocessor\ndefine ",(0,r.jsx)(n.code,{children:"layer_Foo$Verification$Debug"})," due to the one inline layer we added."]}),"\n",(0,r.jsxs)(n.p,{children:["A user can then include any combination of these files in their design to\ninclude the optional functionality described by the ",(0,r.jsx)(n.code,{children:"Verification"})," or\n",(0,r.jsx)(n.code,{children:"Verification.Assert"})," layers and enable debugging by setting the preprocessor\nmacro. The ",(0,r.jsx)(n.code,{children:"Verification.Assert"})," bind file automatically includes the\n",(0,r.jsx)(n.code,{children:"Verification"})," bind file for the user."]}),"\n",(0,r.jsx)(n.h4,{id:"implementation-notes",children:"Implementation Notes"}),"\n",(0,r.jsxs)(n.admonition,{type:"warning",children:[(0,r.jsxs)(n.p,{children:["This section describes the implementation of how layers are compiled. Anything\nthat is ",(0,r.jsx)(n.em,{children:"not"})," a bind file name or a preprocessor macro should not be relied\nupon! A FIRRTL compiler may implement this differently or may optimize layer\nblocks in any legal way it chooses. E.g., layer blocks associated with the same\nlayer may be merged, layer blocks may be moved up or down the hierarchy, code\nthat only fans out to a layer block may be sunk into it, and unused layer blocks\nmay be deleted."]}),(0,r.jsx)(n.p,{children:"The information below is for user understanding and interest only."})]}),"\n",(0,r.jsxs)(n.p,{children:["In implementation, a FIRRTL compiler creates three Verilog modules for the\ncircuit above (one for ",(0,r.jsx)(n.code,{children:"Foo"})," and one for each layer block associated with an\nextract layer in module ",(0,r.jsx)(n.code,{children:"Foo"}),"):"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"Foo"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"Foo_Verification"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"Foo_Verification_Assert"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["These will typically be created in separate files with names that match the\nmodules, i.e., ",(0,r.jsx)(n.code,{children:"Foo.sv"}),", ",(0,r.jsx)(n.code,{children:"Foo_Verification.sv"}),", and\n",(0,r.jsx)(n.code,{children:"Foo_Verification_Assert.sv"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["The ports of each module created from a layer block will be automatically\ndetermined based on what that layer block captured from outside the layer block.\nIn the example above, the ",(0,r.jsx)(n.code,{children:"Verification"})," layer block captured port ",(0,r.jsx)(n.code,{children:"a"}),". The\n",(0,r.jsx)(n.code,{children:"Assert"})," layer block captured captured ",(0,r.jsx)(n.code,{children:"a"})," and ",(0,r.jsx)(n.code,{children:"a_d0"}),"."]}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["Even though there are no layer blocks that use the ",(0,r.jsx)(n.code,{children:"Verification.Assume"})," or\n",(0,r.jsx)(n.code,{children:"Verification.Cover"})," layers, bind files which have no effect are produced in the\noutput. This is due to the ABI which requires that layers that are defined in\nFIRRTL must produce these files."]})}),"\n",(0,r.jsx)(n.h4,{id:"verilog-output",children:"Verilog Output"}),"\n",(0,r.jsx)(n.p,{children:"The complete Verilog output for this example is reproduced below:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-verilog",children:'// Generated by CIRCT firtool-1.99.2\nmodule Foo(\n input clock,\n reset,\n input [31:0] a,\n output [31:0] b\n);\n\n assign b = a + 32\'h1;\nendmodule\n\n\n// ----- 8< ----- FILE "verification/cover/layers-Foo-Verification-Cover.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\n`include "verification/layers-Foo-Verification.sv"\n`ifndef layers_Foo_Verification_Cover\n`define layers_Foo_Verification_Cover\n`endif // layers_Foo_Verification_Cover\n\n// ----- 8< ----- FILE "verification/assume/layers-Foo-Verification-Assume.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\n`include "verification/layers-Foo-Verification.sv"\n`ifndef layers_Foo_Verification_Assume\n`define layers_Foo_Verification_Assume\n`endif // layers_Foo_Verification_Assume\n\n// ----- 8< ----- FILE "verification/assert/layers-Foo-Verification-Assert.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\n`include "verification/layers-Foo-Verification.sv"\n`ifndef layers_Foo_Verification_Assert\n`define layers_Foo_Verification_Assert\nbind Foo Foo_Verification_Assert verification_assert (\n .a (Foo.verification.a_probe),\n .a_d0 (Foo.verification.a_d0_probe),\n .reset (reset),\n .clock (Foo.verification.clock_probe)\n);\n`endif // layers_Foo_Verification_Assert\n\n// ----- 8< ----- FILE "verification/layers-Foo-Verification.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\n`ifndef layers_Foo_Verification\n`define layers_Foo_Verification\nbind Foo Foo_Verification verification (\n .clock (clock),\n .a (a),\n .reset (reset)\n);\n`endif // layers_Foo_Verification\n\n// ----- 8< ----- FILE "verification/assert/Foo_Verification_Assert.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\n\n// Users can define \'STOP_COND\' to add an extra gate to stop conditions.\n`ifndef STOP_COND_\n `ifdef STOP_COND\n `define STOP_COND_ (`STOP_COND)\n `else // STOP_COND\n `define STOP_COND_ 1\n `endif // STOP_COND\n`endif // not def STOP_COND_\n\n// Users can define \'ASSERT_VERBOSE_COND\' to add an extra gate to assert error printing.\n`ifndef ASSERT_VERBOSE_COND_\n `ifdef ASSERT_VERBOSE_COND\n `define ASSERT_VERBOSE_COND_ (`ASSERT_VERBOSE_COND)\n `else // ASSERT_VERBOSE_COND\n `define ASSERT_VERBOSE_COND_ 1\n `endif // ASSERT_VERBOSE_COND\n`endif // not def ASSERT_VERBOSE_COND_\nmodule Foo_Verification_Assert(\n input [31:0] a,\n a_d0,\n input reset,\n clock\n);\n\n `ifndef SYNTHESIS\n always @(posedge clock) begin\n if (~reset & a < a_d0) begin\n if (`ASSERT_VERBOSE_COND_)\n $error("Assertion failed: a must always increment\\n");\n if (`STOP_COND_)\n $fatal;\n end\n end // always @(posedge)\n `endif // not def SYNTHESIS\nendmodule\n\n\n// ----- 8< ----- FILE "verification/Foo_Verification.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.99.2\n\n// Users can define \'PRINTF_COND\' to add an extra gate to prints.\n`ifndef PRINTF_COND_\n `ifdef PRINTF_COND\n `define PRINTF_COND_ (`PRINTF_COND)\n `else // PRINTF_COND\n `define PRINTF_COND_ 1\n `endif // PRINTF_COND\n`endif // not def PRINTF_COND_\nmodule Foo_Verification(\n input clock,\n input [31:0] a,\n input reset\n);\n\n wire clock_probe = clock;\n wire [31:0] a_probe = a;\n reg [31:0] a_d0;\n wire [31:0] a_d0_probe = a_d0;\n `ifdef layer_Foo$Verification$Debug\n `ifndef SYNTHESIS\n always @(posedge clock) begin\n if ((`PRINTF_COND_) & ~reset)\n $fwrite(32\'h80000002, "a: %x, a_d0: %x", a, a_d0);\n end // always @(posedge)\n `endif // not def SYNTHESIS\n `endif // layer_Foo$Verification$Debug\n always @(posedge clock)\n a_d0 <= a;\nendmodule\n\n'})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>s});var r=i(6540);const a={},o=r.createContext(a);function l(e){const n=r.useContext(o);return r.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),r.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[6474],{6458:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>t,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var r=i(4848),a=i(8453);const o={layout:"docs",title:"Layers",section:"chisel3"},l="Layers",s={id:"explanations/layers",title:"Layers",description:"Layers describe functionality of a Chisel generator that a user would like to",source:"@site/docs/explanations/layers.md",sourceDirName:"explanations",slug:"/explanations/layers",permalink:"/docs/explanations/layers",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/layers.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Layers",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Intrinsics",permalink:"/docs/explanations/intrinsics"},next:{title:"Memories",permalink:"/docs/explanations/memories"}},t={},c=[{value:"Overview",id:"overview",level:2},{value:"Verilog ABI",id:"verilog-abi",level:2},{value:"Extract Layers",id:"extract-layers",level:3},{value:"Inline Layers",id:"inline-layers",level:3},{value:"User-defined Layers",id:"user-defined-layers",level:2},{value:"Built-in Layers",id:"built-in-layers",level:2},{value:"Layer-coloring",id:"layer-coloring",level:2},{value:"Layer-colored Probes and Wires",id:"layer-colored-probes-and-wires",level:3},{value:"Enabling Layers",id:"enabling-layers",level:3},{value:"Examples",id:"examples",level:2},{value:"Simple Extract Layer",id:"simple-extract-layer",level:3},{value:"Simple Inline Layer",id:"simple-inline-layer",level:3},{value:"Design Verification Example",id:"design-verification-example",level:3},{value:"Implementation Notes",id:"implementation-notes",level:4},{value:"Verilog Output",id:"verilog-output",level:4}];function d(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"layers",children:"Layers"})}),"\n",(0,r.jsxs)(n.p,{children:["Layers describe functionality of a Chisel generator that a user would like to\n",(0,r.jsx)(n.em,{children:"optionally"})," include at Verilog elaboration time. Pragmatically, they are a\nfeature to access SystemVerilog's ",(0,r.jsx)(n.code,{children:"bind"})," construct and ",(0,r.jsx)(n.code,{children:"`ifdef"})," preprocessor\nmacros. The optional functionality of layers, by construction, is not allowed\nto affect logic outside the layer."]}),"\n",(0,r.jsx)(n.p,{children:"Layers are typically used to describe design verification code or\ndebugging logic that a user would like to be able to later disable (for\nperformance, verbosity, or cleanliness reasons) or use internally, but exclude\nfrom delivery to a customer."}),"\n",(0,r.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,r.jsx)(n.p,{children:"A layer consists of two pieces:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["A layer ",(0,r.jsx)(n.em,{children:"declaration"}),", and"]}),"\n",(0,r.jsxs)(n.li,{children:["One or more ",(0,r.jsx)(n.em,{children:"layer blocks"})," inside Chisel modules."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"The declaration indicates that optional functionality can exist. The layer\nblock contains the optional functionality."}),"\n",(0,r.jsxs)(n.p,{children:["There are two kinds of layers. The layer kind determines the ",(0,r.jsx)(n.em,{children:"convention"}),",\ni.e., how the layer blocks of a layer are represented in Verilog and the\nmechanism to enable a layer. Available layer kinds are:"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:['"Extract" Layers: layers whose blocks are lowered to modules that are\ninstantiated using ',(0,r.jsx)(n.code,{children:"bind"})," and can be enabled by including a file during\nVerilog elaboration, and"]}),"\n",(0,r.jsxs)(n.li,{children:['"Inline" Layers: layers whose blocks will be guarded with ',(0,r.jsx)(n.code,{children:"`ifdef"})," macros\nand can be enabled by setting a Verilog preprocessor define."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Extract layers may also specify a directory into which their collateral are\nwritten."}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["For more information about these SystemVerilog concepts, the IEEE 1800-2023\nstandard discusses ",(0,r.jsx)(n.code,{children:"bind"})," in Section 23.11 and ",(0,r.jsx)(n.code,{children:"`ifdef"})," in Section 23.6."]})}),"\n",(0,r.jsxs)(n.p,{children:["To declare a layer, create a singleton ",(0,r.jsx)(n.code,{children:"object"})," in scala that extends the\nabstract class ",(0,r.jsx)(n.code,{children:"chisel3.layer.Layer"}),", passing into the layer constructor either\nan object of class ",(0,r.jsx)(n.code,{children:"chisel3.layer.LayerConfig.Extract"})," for an extract layer, or\nthe object ",(0,r.jsx)(n.code,{children:"chisel3.layer.LayerConfig.Inline"})," for an inline layer."]}),"\n",(0,r.jsx)(n.p,{children:"Below, an extract layer and an inline layer are declared:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"import chisel3.layer.{Layer, LayerConfig}\n\nobject A extends Layer(LayerConfig.Extract())\n\nobject B extends Layer(LayerConfig.Inline)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Layers may be nested. Nesting a child layer under a parent layer means that the\nchild layer may access constructs in the parent layer. Put differently, the\nchild layer will only be enabled if the parent layer is already enabled. To\ndeclare a nested layer, extend the ",(0,r.jsx)(n.code,{children:"chisel3.layer.Layer"})," abstract class inside\nanother declaration."]}),"\n",(0,r.jsx)(n.p,{children:"The following example defines an extract layer with two nested layers inside it:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"object C extends Layer(LayerConfig.Extract()) {\n object D extends Layer(LayerConfig.Extract())\n object E extends Layer(LayerConfig.Inline) {\n object F extends Layer(LayerConfig.Inline)\n }\n}\n"})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["SystemVerilog prohibits a ",(0,r.jsx)(n.code,{children:"bind"})," instantiation under another ",(0,r.jsx)(n.code,{children:"bind"}),"\ninstantiation. However, Chisel allows nesting of extract layers. This is\nresolved by the FIRRTL compiler to restructure nested extract layers to be\nsibling modules that communicate via ports."]})}),"\n",(0,r.jsxs)(n.admonition,{type:"warning",children:[(0,r.jsx)(n.p,{children:"Extract layers may not be nested under inline layers. However, inline layers\nmay be nested under extract layers."}),(0,r.jsx)(n.p,{children:"Any module which contains layer blocks or transitively contains layer blocks in\nits submodules may not be instantiated under a layer block."})]}),"\n",(0,r.jsxs)(n.p,{children:["A ",(0,r.jsx)(n.em,{children:"layer block"}),", associated with a layer, adds optional functionality to a\nmodule that is enabled if that layer is enabled. To define a layer block, use\nthe ",(0,r.jsx)(n.code,{children:"chisel3.layer.block"})," inside a Chisel module and pass the layer that it\nshould be associated with."]}),"\n",(0,r.jsx)(n.p,{children:"Inside the layer block, any Chisel or Scala value visible in lexical scope may\nbe used. Layer blocks may not return values. Any values created inside a layer\nblock are not accessible outside the layer block, unless using layer-colored\nprobes."}),"\n",(0,r.jsxs)(n.p,{children:["The following example defines layer blocks inside module ",(0,r.jsx)(n.code,{children:"Foo"}),". Each layer\nblock contains a wire that captures a value from its visible lexical scope.\n(For nested layer blocks, this scope includes their parent layer blocks.):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.layer.block\n\nclass Foo extends RawModule {\n val port = IO(Input(Bool()))\n\n block(A) {\n val a = WireInit(port)\n }\n\n block(B) {\n val b = WireInit(port)\n }\n\n block(C) {\n val c = WireInit(port)\n block(C.D) {\n val d = WireInit(port | c)\n }\n block(C.E) {\n val e = WireInit(port ^ c)\n block (C.E.F) {\n val f = WireInit(port & e)\n }\n }\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The layer block API will automatically create parent layer blocks for you if\npossible. In the following example, it is legal to directly create a layer\nblock of ",(0,r.jsx)(n.code,{children:"C.D"})," directly in a module:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"class Bar extends RawModule {\n block (C.D) {}\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Formally, it is legal to create a layer block associated with a layer as long as\nthe current scope is an ",(0,r.jsx)(n.em,{children:"ancestor"})," of the request layer."]}),"\n",(0,r.jsxs)(n.admonition,{type:"info",children:[(0,r.jsxs)(n.p,{children:["The requirement is an ",(0,r.jsx)(n.em,{children:"ancestor"})," relationship, not a ",(0,r.jsx)(n.em,{children:"proper ancestor"}),"\nrelationship. This means that it is legal to nest a layer block under a layer\nblock of the same layer like:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"class Baz extends RawModule {\n block(A) {\n block(A) {}\n }\n}\n"})})]}),"\n",(0,r.jsx)(n.h2,{id:"verilog-abi",children:"Verilog ABI"}),"\n",(0,r.jsx)(n.p,{children:"Layers are compiled to SystemVerilog using the FIRRTL ABI. This ABI defines\nwhat happens to layer blocks in a Chisel design and how a layer can be enabled\nafter a design is compiled to SystemVerilog."}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["For the exact definition of the FIRRTL ABI for layers, see the ",(0,r.jsx)(n.a,{href:"https://github.com/chipsalliance/firrtl-spec/releases/latest/download/abi.pdf",children:"FIRRTL ABI\nSpecification"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"extract-layers",children:"Extract Layers"}),"\n",(0,r.jsxs)(n.p,{children:["Extract layers have their layer blocks removed from the design. To enable a\nlayer, a file with a specific name should be included in the design. This file\nbegins with ",(0,r.jsx)(n.code,{children:"layers-"})," and then includes the circuit name and all layer names\ndelimited with dashes (",(0,r.jsx)(n.code,{children:"-"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, for module ",(0,r.jsx)(n.code,{children:"Foo"})," declared above, this will produce three files, one\nfor each extract layer:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"layers-Foo-A.sv\nlayers-Foo-C.sv\nlayers-Foo-C-D.sv\n"})}),"\n",(0,r.jsx)(n.p,{children:"To enable any of these layers at compilation time, the appropriate file should\nbe included in the build. Any combination of files may be included. Including\nonly a child layer's file will automatically include its parent layer's file."}),"\n",(0,r.jsx)(n.h3,{id:"inline-layers",children:"Inline Layers"}),"\n",(0,r.jsxs)(n.p,{children:["Inline layers have their layer blocks guarded with conditional compilation\ndirectives. To enable an inline layer, set a preprocessor define when compiling\nyour design. The preprocessor define begins with ",(0,r.jsx)(n.code,{children:"layer_"})," and then includes the\ncircuit name and all layer names delimited with dollar signs (",(0,r.jsx)(n.code,{children:"$"}),"). Parent\nextract layer names appear in the macro."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, for module ",(0,r.jsx)(n.code,{children:"Foo"})," declared above, this will be sensitive to three\nmacros, one for each inline layer:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"layer_Foo$B\nlayer_Foo$C$E\nlayer_Foo$C$E$F\n"})}),"\n",(0,r.jsx)(n.h2,{id:"user-defined-layers",children:"User-defined Layers"}),"\n",(0,r.jsxs)(n.p,{children:["A user is free to define as many layers as they want. All layers shown\npreviously are user-defined, e.g., ",(0,r.jsx)(n.code,{children:"A"})," and ",(0,r.jsx)(n.code,{children:"C.E"})," are user-defined layers.\nUser-defined layers are only emitted into FIRRTL if they have layer block users.\nTo change this behavior and unconditionally emit a user-defined layer, use the\n",(0,r.jsx)(n.code,{children:"chisel3.layer.addLayer"})," API."]}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsx)(n.p,{children:"Before creating new user-defined layers, consider using the built-in layers\ndefined below. Additionally, if working in a larger project, the project may\nhave it's own user-defined layers that you are expected to use. This is because\nthe ABIs affect the build system. Please consult with a technical lead of the\nproject to see if this is the case."})}),"\n",(0,r.jsx)(n.h2,{id:"built-in-layers",children:"Built-in Layers"}),"\n",(0,r.jsx)(n.p,{children:"Chisel provides several built-in layers. These are shown below with their full\nScala paths. All built-in layers are extract layers:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"chisel3.layers.Verification\n\u251c\u2500\u2500 chisel3.layers.Verification.Assert\n\u251c\u2500\u2500 chisel3.layers.Verification.Assume\n\u2514\u2500\u2500 chisel3.layers.Verification.Cover\n"})}),"\n",(0,r.jsxs)(n.p,{children:["These built-in layers are dual purpose. First, these layers match the common\nuse case of sequestering verification code. The ",(0,r.jsx)(n.code,{children:"Verification"})," layer is for\ncommon verification collateral. The ",(0,r.jsx)(n.code,{children:"Assert"}),", ",(0,r.jsx)(n.code,{children:"Assume"}),", and ",(0,r.jsx)(n.code,{children:"Cover"})," layers are\nfor, respectively, assertions, assumptions, and cover statements. Second, the\nChisel standard library uses them for a number of its APIs. ",(0,r.jsx)(n.em,{children:"Unless otherwise\nwrapped in a different layer block, the following operations are automatically\nplaced in layers"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Prints are placed in the ",(0,r.jsx)(n.code,{children:"Verification"})," layer"]}),"\n",(0,r.jsxs)(n.li,{children:["Assertions are placed in the ",(0,r.jsx)(n.code,{children:"Verification.Assert"})," layer"]}),"\n",(0,r.jsxs)(n.li,{children:["Assumptions are placed in the ",(0,r.jsx)(n.code,{children:"Verification.Assume"})," layer"]}),"\n",(0,r.jsxs)(n.li,{children:["Covers are placed in the ",(0,r.jsx)(n.code,{children:"Verification.Cover"})," layer"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["For predictability of output, these layers will always be show up in the FIRRTL\nthat Chisel emits. To change this behavior, use ",(0,r.jsx)(n.code,{children:"firtool"})," command line options\nto ",(0,r.jsx)(n.em,{children:"specialize"})," these layers (remove their optionality by making them always\nenabled or disabled). Use ",(0,r.jsx)(n.code,{children:"-enable-layers"})," to enable a layer, ",(0,r.jsx)(n.code,{children:"-disable-layers"}),"\nto disable a layer, or ",(0,r.jsx)(n.code,{children:"-default-layer-specialization"})," to set a default\nspecialization."]}),"\n",(0,r.jsxs)(n.admonition,{type:"tip",children:[(0,r.jsx)(n.p,{children:"Users may extend built-in layers with user-defined layers using an advanced API.\nTo do this, the layer parent must be specified as an implicit value."}),(0,r.jsxs)(n.p,{children:["The following example nests the layer ",(0,r.jsx)(n.code,{children:"Debug"})," to the ",(0,r.jsx)(n.code,{children:"Verification"})," layer:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"object UserDefined {\n // Define an implicit val `root` of type `Layer` to cause layers which can see\n // this to use `root` as their parent layer. This allows us to nest the\n // user-defined `Debug` layer under the built-in `Verification` layer.\n implicit val root: Layer = chisel3.layers.Verification\n object Debug extends Layer(LayerConfig.Inline)\n}\n"})})]}),"\n",(0,r.jsx)(n.h2,{id:"layer-coloring",children:"Layer-coloring"}),"\n",(0,r.jsxs)(n.p,{children:["While layers are not allowed to influence the design or their parent layers, it\nis often useful and necessary to allow layer blocks to send information out of\ntheir containing modules to be read by layer blocks of the same layer or\nchildren layers. Hardware which has this optional property is said to be\n",(0,r.jsx)(n.em,{children:"layer-colored"}),". Both probes and wires can be layer-colored."]}),"\n",(0,r.jsx)(n.h3,{id:"layer-colored-probes-and-wires",children:"Layer-colored Probes and Wires"}),"\n",(0,r.jsx)(n.p,{children:"A layer-colored probe is a probe that exists if a user enables its corresponding\nlayer during Verilog elaboration. Layer-colored probes are used to describe\noptional verification, debugging, or logging interfaces."}),"\n",(0,r.jsx)(n.p,{children:"Layer-colored wires are used as temporary storage of defined probe values. They\nare used for communication between layer blocks of the same layer in the same\nmodule or as temporary storage when forwarding a probe to a port."}),"\n",(0,r.jsxs)(n.p,{children:["A layer-colored probe or wire may be the target of a ",(0,r.jsx)(n.code,{children:"define"})," if the ",(0,r.jsx)(n.code,{children:"define"})," is\nenabled when the color of the probe or wire is enabled. A layer-colored probe\nor wire may be ",(0,r.jsx)(n.code,{children:"read"})," from if the color of the probe or wire is enabled when the\n",(0,r.jsx)(n.code,{children:"read"})," is enabled. Put differently, you may write to your layer or a child\nlayer and you may read from your layer or a parent layer."]}),"\n",(0,r.jsx)(n.p,{children:"The example below shows two layer-colored probe ports and one layer-colored\nprobe wire driven in legal ways:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.layer.{Layer, LayerConfig}\nimport chisel3.probe.{Probe, ProbeValue, define}\n\nobject A extends Layer(LayerConfig.Extract())\nobject B extends Layer(LayerConfig.Extract())\n\nclass Foo extends RawModule {\n val a = IO(Output(Probe(Bool(), A)))\n val b = IO(Output(Probe(Bool(), B)))\n\n layer.block(A) {\n val a_wire = WireInit(false.B)\n define(a, ProbeValue(a_wire))\n }\n\n val b_wire_probe = Wire(Probe(Bool(), B))\n define(b, b_wire_probe)\n\n layer.block(B) {\n val b_wire = WireInit(false.B)\n define(b_wire_probe, ProbeValue(b_wire))\n }\n\n}\n"})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["For more information, see the layer coloring section of the ",(0,r.jsx)(n.a,{href:"https://github.com/chipsalliance/firrtl-spec/releases/latest/download/spec.pdf",children:"FIRRTL\nSpecification"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"enabling-layers",children:"Enabling Layers"}),"\n",(0,r.jsxs)(n.p,{children:["When working with layer-colored probes, it is often convenient to grant access\nto probes of one or more colors. E.g., testbenches often want to ",(0,r.jsx)(n.em,{children:"enable"})," all\nlayers in a design-under-test so that they gain access to layer-colored probe\nports necessary for advanced design verification. Without an additional\nfeature, this use case is poorly supported with just layer coloring. First, it\nis tedious to enclose all code inside a testbench in a layer block. Second, a\ntestbench may need to read probes with colors that do not have a parent--child\nrelationship. No layer block is capable of both legally reading from different\nprobes and combining the results."]}),"\n",(0,r.jsxs)(n.p,{children:["To support this use case, Chisel provides the ",(0,r.jsx)(n.code,{children:"layer.enable"})," API. This API\ngrants access to any layer-colored probes of instantiated modules for the\nenabled layer. The API may be used more than once to enable more than one\nlayer."]}),"\n",(0,r.jsxs)(n.p,{children:["The example below instantiates module ",(0,r.jsx)(n.code,{children:"Foo"})," from the previous section. After\nenabling layers ",(0,r.jsx)(n.code,{children:"A"})," and ",(0,r.jsx)(n.code,{children:"B"}),", the module can read from probes with colors ",(0,r.jsx)(n.code,{children:"A"})," and\n",(0,r.jsx)(n.code,{children:"B"})," and use their results in a single operation:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:"import chisel3.layer.enable\nimport chisel3.probe.read\n\nclass Bar extends RawModule {\n\n enable(A)\n enable(B)\n\n val foo = Module(new Foo)\n\n val c = read(foo.a) ^ read(foo.b)\n\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,r.jsx)(n.h3,{id:"simple-extract-layer",children:"Simple Extract Layer"}),"\n",(0,r.jsxs)(n.p,{children:["The design below has a single extract layer that, when enabled, will add an\nassert that checks for overflow. Based on the FIRRTL ABI, we can expect that a\nfile called ",(0,r.jsx)(n.code,{children:"layers-Foo-A.sv"})," will be produced when we compile it."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.layer.{Layer, LayerConfig, block}\nimport chisel3.ltl.AssertProperty\n\nobject A extends Layer(LayerConfig.Extract())\n\nclass Foo extends Module {\n val a, b = IO(Input(UInt(4.W)))\n val sum = IO(Output(UInt(4.W)))\n\n sum :<= a +% b\n\n block(A) {\n withDisable(Disable.Never) {\n AssertProperty(!(a +& b)(4), "overflow occurred")\n }\n }\n\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["After compilation, we get the following SystemVerilog. Comments that include\n",(0,r.jsx)(n.code,{children:"FILE"})," indicate the beginning of a new file:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-verilog",children:'// Generated by CIRCT firtool-1.100.0\nmodule Foo(\n input clock,\n reset,\n input [3:0] a,\n b,\n output [3:0] sum\n);\n\n wire [4:0] _sum_T = {1\'h0, a} + {1\'h0, b};\n assign sum = _sum_T[3:0];\nendmodule\n\n\n// ----- 8< ----- FILE "A/layers-Foo-A.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\n`ifndef layers_Foo_A\n`define layers_Foo_A\nbind Foo Foo_A a_0 (\n ._GEN (_sum_T),\n .clock (clock)\n);\n`endif // layers_Foo_A\n\n// ----- 8< ----- FILE "A/Foo_A.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\nmodule Foo_A(\n input [4:0] _GEN,\n input clock\n);\n\n overflow_occurred: assert property (@(posedge clock) ~(_GEN[4]));\nendmodule\n\n'})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["The above example was compiled with the firtool options\n",(0,r.jsx)(n.code,{children:"-enable-layers=Verification"}),", ",(0,r.jsx)(n.code,{children:"-enable-layers=Verification.Assert"}),",\n",(0,r.jsx)(n.code,{children:"-enable-layers=Verification.Assume"}),", and ",(0,r.jsx)(n.code,{children:"-enable-layers=Verification.Cover"})," to\nmake the output terser. Normally, bind files would show up for these built-in\nlayers."]})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["Note: the generated module, ",(0,r.jsx)(n.code,{children:"Foo_A"}),", and its file, ",(0,r.jsx)(n.code,{children:"Foo_A.sv"}),", are ",(0,r.jsx)(n.em,{children:"not part of\nthe ABI"}),". You should not rely on any generated module names or files other than\nthe bind file, ",(0,r.jsx)(n.code,{children:"layers-Foo-A.sv"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"simple-inline-layer",children:"Simple Inline Layer"}),"\n",(0,r.jsxs)(n.p,{children:["The design below is the same as the previous example, but uses an inline layer.\nBased on the FIRRTL ABI, we can expect that the body of the layer block will be\nguarded by an ",(0,r.jsx)(n.code,{children:"`ifdef"})," sensitive to the preprocessor macro ",(0,r.jsx)(n.code,{children:"layer_Foo$A"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.layer.{Layer, LayerConfig, block}\nimport chisel3.ltl.AssertProperty\n\nobject A extends Layer(LayerConfig.Inline)\n\nclass Foo extends Module {\n val a, b = IO(Input(UInt(4.W)))\n val sum = IO(Output(UInt(4.W)))\n\n sum :<= a +% b\n\n block(A) {\n withDisable(Disable.Never) {\n AssertProperty(!(a +& b)(4), "overflow occurred")\n }\n }\n\n}\n'})}),"\n",(0,r.jsx)(n.p,{children:"After compilation, we get the following SystemVerilog."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Foo(\n input clock,\n reset,\n input [3:0] a,\n b,\n output [3:0] sum\n);\n\n wire [4:0] _sum_T = {1'h0, a} + {1'h0, b};\n `ifdef layer_Foo$A\n overflow_occurred: assert property (@(posedge clock) ~(_sum_T[4]));\n `endif // layer_Foo$A\n assign sum = _sum_T[3:0];\nendmodule\n\n"})}),"\n",(0,r.jsx)(n.h3,{id:"design-verification-example",children:"Design Verification Example"}),"\n",(0,r.jsx)(n.p,{children:"Consider a use case where a design or design verification engineer would like to\nadd some asserts and debug prints to a module. The logic necessary for the\nasserts and debug prints requires additional computation. All of this code\nshould selectively included at Verilog elaboration time (not at Chisel\nelaboration time). The engineer can use three layers to do this."}),"\n",(0,r.jsx)(n.p,{children:"There are three layers used in this example:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["The built-in ",(0,r.jsx)(n.code,{children:"Verification"})," layer"]}),"\n",(0,r.jsxs)(n.li,{children:["The built-in ",(0,r.jsx)(n.code,{children:"Assert"})," layer which is nested under the built-in ",(0,r.jsx)(n.code,{children:"Verification"}),"\nlayer"]}),"\n",(0,r.jsxs)(n.li,{children:["A user-defined ",(0,r.jsx)(n.code,{children:"Debug"})," layer which is also nested under the built-in\n",(0,r.jsx)(n.code,{children:"Verification"})," layer"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"Verification"})," layer can be used to store common logic used by both the\n",(0,r.jsx)(n.code,{children:"Assert"})," and ",(0,r.jsx)(n.code,{children:"Debug"})," layers. The latter two layers allow for separation of,\nrespectively, assertions from prints."]}),"\n",(0,r.jsx)(n.p,{children:"One way to write this in Scala is the following:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scala",children:'import chisel3._\nimport chisel3.layer.{Layer, LayerConfig, block}\nimport chisel3.layers.Verification\n\n// User-defined layers are declared here. Built-in layers do not need to be declared.\nobject UserDefined {\n implicit val root: Layer = Verification\n object Debug extends Layer(LayerConfig.Inline)\n}\n\nclass Foo extends Module {\n val a = IO(Input(UInt(32.W)))\n val b = IO(Output(UInt(32.W)))\n\n b := a +% 1.U\n\n // This adds a `Verification` layer block inside Foo.\n block(Verification) {\n\n // Some common logic added here. The input port `a` is "captured" and\n // used here.\n val a_d0 = RegNext(a)\n\n // This adds an `Assert` layer block.\n block(Verification.Assert) {\n chisel3.assert(a >= a_d0, "a must always increment")\n }\n\n // This adds a `Debug` layer block.\n block(UserDefined.Debug) {\n printf("a: %x, a_d0: %x", a, a_d0)\n }\n\n }\n\n}\n\n'})}),"\n",(0,r.jsx)(n.p,{children:"After compilation, this will produce two layer include files with the\nfollowing filenames. One file is created for each extract layer:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"layers_Foo_Verification.sv"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"layers_Foo_Verification_Assert.sv"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Additionally, the resulting SystemVerilog will be sensitive to the preprocessor\ndefine ",(0,r.jsx)(n.code,{children:"layer_Foo$Verification$Debug"})," due to the one inline layer we added."]}),"\n",(0,r.jsxs)(n.p,{children:["A user can then include any combination of these files in their design to\ninclude the optional functionality described by the ",(0,r.jsx)(n.code,{children:"Verification"})," or\n",(0,r.jsx)(n.code,{children:"Verification.Assert"})," layers and enable debugging by setting the preprocessor\nmacro. The ",(0,r.jsx)(n.code,{children:"Verification.Assert"})," bind file automatically includes the\n",(0,r.jsx)(n.code,{children:"Verification"})," bind file for the user."]}),"\n",(0,r.jsx)(n.h4,{id:"implementation-notes",children:"Implementation Notes"}),"\n",(0,r.jsxs)(n.admonition,{type:"warning",children:[(0,r.jsxs)(n.p,{children:["This section describes the implementation of how layers are compiled. Anything\nthat is ",(0,r.jsx)(n.em,{children:"not"})," a bind file name or a preprocessor macro should not be relied\nupon! A FIRRTL compiler may implement this differently or may optimize layer\nblocks in any legal way it chooses. E.g., layer blocks associated with the same\nlayer may be merged, layer blocks may be moved up or down the hierarchy, code\nthat only fans out to a layer block may be sunk into it, and unused layer blocks\nmay be deleted."]}),(0,r.jsx)(n.p,{children:"The information below is for user understanding and interest only."})]}),"\n",(0,r.jsxs)(n.p,{children:["In implementation, a FIRRTL compiler creates three Verilog modules for the\ncircuit above (one for ",(0,r.jsx)(n.code,{children:"Foo"})," and one for each layer block associated with an\nextract layer in module ",(0,r.jsx)(n.code,{children:"Foo"}),"):"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"Foo"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"Foo_Verification"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"Foo_Verification_Assert"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["These will typically be created in separate files with names that match the\nmodules, i.e., ",(0,r.jsx)(n.code,{children:"Foo.sv"}),", ",(0,r.jsx)(n.code,{children:"Foo_Verification.sv"}),", and\n",(0,r.jsx)(n.code,{children:"Foo_Verification_Assert.sv"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["The ports of each module created from a layer block will be automatically\ndetermined based on what that layer block captured from outside the layer block.\nIn the example above, the ",(0,r.jsx)(n.code,{children:"Verification"})," layer block captured port ",(0,r.jsx)(n.code,{children:"a"}),". The\n",(0,r.jsx)(n.code,{children:"Assert"})," layer block captured captured ",(0,r.jsx)(n.code,{children:"a"})," and ",(0,r.jsx)(n.code,{children:"a_d0"}),"."]}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["Even though there are no layer blocks that use the ",(0,r.jsx)(n.code,{children:"Verification.Assume"})," or\n",(0,r.jsx)(n.code,{children:"Verification.Cover"})," layers, bind files which have no effect are produced in the\noutput. This is due to the ABI which requires that layers that are defined in\nFIRRTL must produce these files."]})}),"\n",(0,r.jsx)(n.h4,{id:"verilog-output",children:"Verilog Output"}),"\n",(0,r.jsx)(n.p,{children:"The complete Verilog output for this example is reproduced below:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-verilog",children:'// Generated by CIRCT firtool-1.100.0\nmodule Foo(\n input clock,\n reset,\n input [31:0] a,\n output [31:0] b\n);\n\n assign b = a + 32\'h1;\nendmodule\n\n\n// ----- 8< ----- FILE "verification/cover/layers-Foo-Verification-Cover.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\n`include "verification/layers-Foo-Verification.sv"\n`ifndef layers_Foo_Verification_Cover\n`define layers_Foo_Verification_Cover\n`endif // layers_Foo_Verification_Cover\n\n// ----- 8< ----- FILE "verification/assume/layers-Foo-Verification-Assume.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\n`include "verification/layers-Foo-Verification.sv"\n`ifndef layers_Foo_Verification_Assume\n`define layers_Foo_Verification_Assume\n`endif // layers_Foo_Verification_Assume\n\n// ----- 8< ----- FILE "verification/assert/layers-Foo-Verification-Assert.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\n`include "verification/layers-Foo-Verification.sv"\n`ifndef layers_Foo_Verification_Assert\n`define layers_Foo_Verification_Assert\nbind Foo Foo_Verification_Assert verification_assert (\n .a (Foo.verification.a_probe),\n .a_d0 (Foo.verification.a_d0_probe),\n .reset (reset),\n .clock (Foo.verification.clock_probe)\n);\n`endif // layers_Foo_Verification_Assert\n\n// ----- 8< ----- FILE "verification/layers-Foo-Verification.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\n`ifndef layers_Foo_Verification\n`define layers_Foo_Verification\nbind Foo Foo_Verification verification (\n .clock (clock),\n .a (a),\n .reset (reset)\n);\n`endif // layers_Foo_Verification\n\n// ----- 8< ----- FILE "verification/assert/Foo_Verification_Assert.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\n\n// Users can define \'STOP_COND\' to add an extra gate to stop conditions.\n`ifndef STOP_COND_\n `ifdef STOP_COND\n `define STOP_COND_ (`STOP_COND)\n `else // STOP_COND\n `define STOP_COND_ 1\n `endif // STOP_COND\n`endif // not def STOP_COND_\n\n// Users can define \'ASSERT_VERBOSE_COND\' to add an extra gate to assert error printing.\n`ifndef ASSERT_VERBOSE_COND_\n `ifdef ASSERT_VERBOSE_COND\n `define ASSERT_VERBOSE_COND_ (`ASSERT_VERBOSE_COND)\n `else // ASSERT_VERBOSE_COND\n `define ASSERT_VERBOSE_COND_ 1\n `endif // ASSERT_VERBOSE_COND\n`endif // not def ASSERT_VERBOSE_COND_\nmodule Foo_Verification_Assert(\n input [31:0] a,\n a_d0,\n input reset,\n clock\n);\n\n `ifndef SYNTHESIS\n always @(posedge clock) begin\n if (~reset & a < a_d0) begin\n if (`ASSERT_VERBOSE_COND_)\n $error("Assertion failed: a must always increment\\n");\n if (`STOP_COND_)\n $fatal;\n end\n end // always @(posedge)\n `endif // not def SYNTHESIS\nendmodule\n\n\n// ----- 8< ----- FILE "verification/Foo_Verification.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.100.0\n\n// Users can define \'PRINTF_FD\' to add a specified fd to prints.\n`ifndef PRINTF_FD_\n `ifdef PRINTF_FD\n `define PRINTF_FD_ (`PRINTF_FD)\n `else // PRINTF_FD\n `define PRINTF_FD_ 32\'h80000002\n `endif // PRINTF_FD\n`endif // not def PRINTF_FD_\n\n// Users can define \'PRINTF_COND\' to add an extra gate to prints.\n`ifndef PRINTF_COND_\n `ifdef PRINTF_COND\n `define PRINTF_COND_ (`PRINTF_COND)\n `else // PRINTF_COND\n `define PRINTF_COND_ 1\n `endif // PRINTF_COND\n`endif // not def PRINTF_COND_\nmodule Foo_Verification(\n input clock,\n input [31:0] a,\n input reset\n);\n\n wire clock_probe = clock;\n wire [31:0] a_probe = a;\n reg [31:0] a_d0;\n wire [31:0] a_d0_probe = a_d0;\n `ifdef layer_Foo$Verification$Debug\n `ifndef SYNTHESIS\n always @(posedge clock) begin\n if ((`PRINTF_COND_) & ~reset)\n $fwrite(`PRINTF_FD_, "a: %x, a_d0: %x", a, a_d0);\n end // always @(posedge)\n `endif // not def SYNTHESIS\n `endif // layer_Foo$Verification$Debug\n always @(posedge clock)\n a_d0 <= a;\nendmodule\n\n'})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>s});var r=i(6540);const a={},o=r.createContext(a);function l(e){const n=r.useContext(o);return r.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),r.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/cdcdfbab.6031edb9.js b/assets/js/cdcdfbab.6031edb9.js
deleted file mode 100644
index dbd9548250b..00000000000
--- a/assets/js/cdcdfbab.6031edb9.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[5522],{6102:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>d,frontMatter:()=>t,metadata:()=>c,toc:()=>u});var l=s(4848),a=s(8453);const t={layout:"docs",title:"Enumerations",section:"chisel3"},i="ChiselEnum",c={id:"explanations/chisel-enum",title:"Enumerations",description:"The ChiselEnum type can be used to reduce the chance of error when encoding mux selectors, opcodes, and functional unit operations.",source:"@site/docs/explanations/chisel-enum.md",sourceDirName:"explanations",slug:"/explanations/chisel-enum",permalink:"/docs/explanations/chisel-enum",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/chisel-enum.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Enumerations",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Bundles and Vecs",permalink:"/docs/explanations/bundles-and-vecs"},next:{title:"Chisel Type vs Scala Type",permalink:"/docs/explanations/chisel-type-vs-scala-type"}},o={},u=[{value:"Functionality and Examples",id:"functionality-and-examples",level:2},{value:"Casting",id:"casting",level:2},{value:"Testing",id:"testing",level:2},{value:"Workarounds",id:"workarounds",level:2},{value:"Additional Resources",id:"additional-resources",level:2}];function r(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.header,{children:(0,l.jsx)(n.h1,{id:"chiselenum",children:"ChiselEnum"})}),"\n",(0,l.jsxs)(n.p,{children:["The ChiselEnum type can be used to reduce the chance of error when encoding mux selectors, opcodes, and functional unit operations.\nIn contrast with ",(0,l.jsx)(n.code,{children:"Chisel.util.Enum"}),", ",(0,l.jsx)(n.code,{children:"ChiselEnum"})," are subclasses of ",(0,l.jsx)(n.code,{children:"Data"}),", which means that they can be used to define fields in ",(0,l.jsx)(n.code,{children:"Bundle"}),"s, including in ",(0,l.jsx)(n.code,{children:"IO"}),"s."]}),"\n",(0,l.jsx)(n.h2,{id:"functionality-and-examples",children:"Functionality and Examples"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"// Imports used in the following examples\nimport chisel3._\nimport chisel3.util._\n"})}),"\n",(0,l.jsx)(n.p,{children:"Below we see ChiselEnum being used as mux select for a RISC-V core. While wrapping the object in a package is not required, it is highly recommended as it allows for the type to be used in multiple files more easily."}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"// package CPUTypes {\nobject AluMux1Sel extends ChiselEnum {\n val selectRS1, selectPC = Value\n}\n// We can see the mapping by printing each Value\nAluMux1Sel.all.foreach(println)\n// AluMux1Sel(0=selectRS1)\n// AluMux1Sel(1=selectPC)\n"})}),"\n",(0,l.jsx)(n.p,{children:"Here we see a mux using the AluMux1Sel to select between different inputs."}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"import AluMux1Sel._\n\nclass AluMux1Bundle extends Bundle {\n val aluMux1Sel = Input(AluMux1Sel())\n val rs1Out = Input(Bits(32.W))\n val pcOut = Input(Bits(32.W))\n val aluMux1Out = Output(Bits(32.W))\n}\n\nclass AluMux1File extends Module {\n val io = IO(new AluMux1Bundle)\n\n // Default value for aluMux1Out\n io.aluMux1Out := 0.U\n\n switch (io.aluMux1Sel) {\n is (selectRS1) {\n io.aluMux1Out := io.rs1Out\n }\n is (selectPC) {\n io.aluMux1Out := io.pcOut\n }\n }\n}\n"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule AluMux1File(\n input clock,\n reset,\n io_aluMux1Sel,\n input [31:0] io_rs1Out,\n io_pcOut,\n output [31:0] io_aluMux1Out\n);\n\n assign io_aluMux1Out = io_aluMux1Sel ? io_pcOut : io_rs1Out;\nendmodule\n\n"})}),"\n",(0,l.jsxs)(n.p,{children:["ChiselEnum also allows for the user to directly set the Values by passing an ",(0,l.jsx)(n.code,{children:"UInt"})," to ",(0,l.jsx)(n.code,{children:"Value(...)"}),"\nas shown below. Note that the magnitude of each ",(0,l.jsx)(n.code,{children:"Value"})," must be strictly greater than the one before\nit."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:'object Opcode extends ChiselEnum {\n val load = Value(0x03.U) // i "load" -> 000_0011\n val imm = Value(0x13.U) // i "imm" -> 001_0011\n val auipc = Value(0x17.U) // u "auipc" -> 001_0111\n val store = Value(0x23.U) // s "store" -> 010_0011\n val reg = Value(0x33.U) // r "reg" -> 011_0011\n val lui = Value(0x37.U) // u "lui" -> 011_0111\n val br = Value(0x63.U) // b "br" -> 110_0011\n val jalr = Value(0x67.U) // i "jalr" -> 110_0111\n val jal = Value(0x6F.U) // j "jal" -> 110_1111\n}\n'})}),"\n",(0,l.jsx)(n.p,{children:"The user can 'jump' to a value and continue incrementing by passing a start point then using a regular Value definition."}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"object BranchFunct3 extends ChiselEnum {\n val beq, bne = Value\n val blt = Value(4.U)\n val bge, bltu, bgeu = Value\n}\n// We can see the mapping by printing each Value\nBranchFunct3.all.foreach(println)\n// BranchFunct3(0=beq)\n// BranchFunct3(1=bne)\n// BranchFunct3(4=blt)\n// BranchFunct3(5=bge)\n// BranchFunct3(6=bltu)\n// BranchFunct3(7=bgeu)\n"})}),"\n",(0,l.jsx)(n.h2,{id:"casting",children:"Casting"}),"\n",(0,l.jsxs)(n.p,{children:["You can cast an enum to a ",(0,l.jsx)(n.code,{children:"UInt"})," using ",(0,l.jsx)(n.code,{children:".asUInt"}),":"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class ToUInt extends RawModule {\n val in = IO(Input(Opcode()))\n val out = IO(Output(UInt(in.getWidth.W)))\n out := in.asUInt\n}\n"})}),"\n",(0,l.jsxs)(n.p,{children:["You can cast from a ",(0,l.jsx)(n.code,{children:"UInt"})," to an enum by passing the ",(0,l.jsx)(n.code,{children:"UInt"})," to the apply method of the ",(0,l.jsx)(n.code,{children:"ChiselEnum"})," object:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class FromUInt extends Module {\n val in = IO(Input(UInt(7.W)))\n val out = IO(Output(Opcode()))\n out := Opcode(in)\n}\n"})}),"\n",(0,l.jsxs)(n.p,{children:["However, if you cast from a ",(0,l.jsx)(n.code,{children:"UInt"})," to an Enum type when there are undefined states in the Enum values\nthat the ",(0,l.jsx)(n.code,{children:"UInt"})," could hit, you will see a warning like the following:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:"[warn] chisel-enum.md 133:16: [W001] Casting non-literal UInt to repl.MdocSession$MdocApp$Opcode. You can use repl.MdocSession$MdocApp$Opcode.safe to cast without this warning.\n[warn] There were 1 warning(s) during hardware elaboration.\n"})}),"\n",(0,l.jsx)(n.p,{children:"(Note that the name of the Enum is ugly as an artifact of our documentation generation flow, it will\nbe cleaner in normal use)."}),"\n",(0,l.jsxs)(n.p,{children:["You can avoid this warning by using the ",(0,l.jsx)(n.code,{children:".safe"})," factory method which returns the cast Enum in addition\nto a ",(0,l.jsx)(n.code,{children:"Bool"})," indicating if the Enum is in a valid state:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:'class SafeFromUInt extends Module {\n val in = IO(Input(UInt(7.W)))\n val out = IO(Output(Opcode()))\n val (value, valid) = Opcode.safe(in)\n assert(valid, "Enum state must be valid, got %d!", in)\n out := value\n}\n'})}),"\n",(0,l.jsx)(n.p,{children:"Now there will be no warning:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{})}),"\n",(0,l.jsxs)(n.p,{children:["You can also suppress the warning by using ",(0,l.jsx)(n.code,{children:"suppressEnumCastWarning"}),". This is\nprimarily used for casting from [[UInt]] to a Bundle type that contains an\nEnum, where the [[UInt]] is known to be valid for the Bundle type."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-scala",children:"class MyBundle extends Bundle {\n val addr = UInt(8.W)\n val op = Opcode()\n}\n\nclass SuppressedFromUInt extends Module {\n val in = IO(Input(UInt(15.W)))\n val out = IO(Output(new MyBundle()))\n suppressEnumCastWarning {\n out := in.asTypeOf(new MyBundle)\n }\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"testing",children:"Testing"}),"\n",(0,l.jsxs)(n.p,{children:["The ",(0,l.jsx)(n.em,{children:"Type"})," of the enums values is ",(0,l.jsx)(n.code,{children:"<>
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.99.2\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.99.2\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.<>
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.100.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.100.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.:<>=
)",id:"bi-direction-connection-operator-",level:3},{value:"Port-Direction Computation versus Connection-Direction Computation",id:"port-direction-computation-versus-connection-direction-computation",level:3},{value:"Aligned connection operator (:<=
)",id:"aligned-connection-operator-",level:3},{value:"Flipped connection operator (:>=
)",id:"flipped-connection-operator-",level:3},{value:"Coercing mono-direction connection operator (:#=
)",id:"coercing-mono-direction-connection-operator-",level:3},{value:"Connectable",id:"connectable",level:2},{value:"Connecting Records",id:"connecting-records",level:3},{value:"Defaults with waived connections",id:"defaults-with-waived-connections",level:3},{value:"Connecting types with optional members",id:"connecting-types-with-optional-members",level:3},{value:"Always ignore errors caused by extra members (partial connection operator)",id:"always-ignore-errors-caused-by-extra-members-partial-connection-operator",level:3},{value:"Connecting components with different widths",id:"connecting-components-with-different-widths",level:3},{value:"Excluding members from any operator on a Connectable",id:"excluding-members-from-any-operator-on-a-connectable",level:3},{value:"Techniques for connecting structurally inequivalent Chisel types",id:"techniques-for-connecting-structurally-inequivalent-chisel-types",level:2},{value:"Connecting different sub-types of the same super-type, with colliding names",id:"connecting-different-sub-types-of-the-same-super-type-with-colliding-names",level:3},{value:"Connecting sub-types to super-types by waiving extra members",id:"connecting-sub-types-to-super-types-by-waiving-extra-members",level:3},{value:"Connecting different sub-types",id:"connecting-different-sub-types",level:3},{value:"FAQ",id:"faq",level:2},{value:"How do I connect two items as flexibly as possible (try your best but never error)",id:"how-do-i-connect-two-items-as-flexibly-as-possible-try-your-best-but-never-error",level:3},{value:"How do I connect two items but don't care about the Scala types being equivalent?",id:"how-do-i-connect-two-items-but-dont-care-about-the-scala-types-being-equivalent",level:3}];function a(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h2,{id:"table-of-contents",children:"Table of Contents"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#terminology",children:"Terminology"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#overview",children:"Overview"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#alignment-flipped-vs-aligned",children:"Alignment: Flipped vs Aligned"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#inputoutput",children:"Input/Output"})}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.a,{href:"#connecting-components-with-fully-aligned-members",children:"Connecting components with fully aligned members"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#mono-direction-connection-operator-",children:["Mono-direction connection operator (",(0,o.jsx)(n.code,{children:":="}),")"]})}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.a,{href:"#connecting-components-with-mixed-alignment-members",children:"Connecting components with mixed alignment members"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#bi-direction-connection-operator-",children:["Bi-direction connection operator (",(0,o.jsx)(n.code,{children:":<>="}),")"]})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#port-direction-computation-versus-connection-direction-computation",children:"Port-Direction Computation versus Connection-Direction Computation"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#aligned-connection-operator-",children:["Aligned connection operator (",(0,o.jsx)(n.code,{children:":<="}),")"]})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#flipped-connection-operator-",children:["Flipped connection operator (",(0,o.jsx)(n.code,{children:":>="}),")"]})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#coercing-mono-direction-connection-operator-",children:["Coercing mono-direction connection operator (",(0,o.jsx)(n.code,{children:":#="}),")"]})}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.a,{href:"#connectable",children:"Connectable"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-records",children:"Connecting Records"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#defaults-with-waived-connections",children:"Defaults with waived connections"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-types-with-optional-members",children:"Connecting types with optional members"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#always-ignore-errors-caused-by-extra-members-partial-connection-operator",children:"Always ignore extra members (partial connection operator)"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-components-with-different-widths",children:"Connecting components with different widths"})}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.a,{href:"#techniques-for-connecting-structurally-inequivalent-chisel-types",children:"Techniques for connecting structurally inequivalent Chisel types"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-different-sub-types-of-the-same-super-type-with-colliding-names",children:"Connecting different sub-types of the same super-type, with colliding names"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-sub-types-to-super-types-by-waiving-extra-members",children:"Connecting sub-types to super-types by waiving extra members"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-different-sub-types",children:"Connecting different sub-types"})}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#faq",children:"FAQ"})}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"terminology",children:"Terminology"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:['"Chisel type" - a ',(0,o.jsx)(n.code,{children:"Data"})," that is not bound to hardware, i.e. not a component. (more details ",(0,o.jsx)(n.a,{href:"chisel-type-vs-scala-type",children:"here"}),").","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"UInt(3.W)"}),", ",(0,o.jsx)(n.code,{children:"new Bundle {..}"}),", ",(0,o.jsx)(n.code,{children:"Vec(3, SInt(2.W))"})," are all Chisel types"]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:['"component" - a ',(0,o.jsx)(n.code,{children:"Data"})," that is bound to hardware (",(0,o.jsx)(n.code,{children:"IO"}),", ",(0,o.jsx)(n.code,{children:"Reg"}),", ",(0,o.jsx)(n.code,{children:"Wire"}),", etc.)","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"Wire(UInt(3.W))"})," is a component, whose Chisel type is ",(0,o.jsx)(n.code,{children:"UInt(3.W)"})]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"Aggregate"})," - a Chisel type or component that contains other Chisel types or components (i.e. ",(0,o.jsx)(n.code,{children:"Vec"}),", ",(0,o.jsx)(n.code,{children:"Record"}),", or ",(0,o.jsx)(n.code,{children:"Bundle"}),")"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"Element"})," - a Chisel type or component that does not contain other Chisel types or components (e.g. ",(0,o.jsx)(n.code,{children:"UInt"}),", ",(0,o.jsx)(n.code,{children:"SInt"}),", ",(0,o.jsx)(n.code,{children:"Clock"}),", ",(0,o.jsx)(n.code,{children:"Bool"})," etc.)"]}),"\n",(0,o.jsxs)(n.li,{children:['"member" - a Chisel type or component, or any of its children (could be an ',(0,o.jsx)(n.code,{children:"Aggregate"})," or an ",(0,o.jsx)(n.code,{children:"Element"}),")","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"Vec(3, UInt(2.W))(0)"})," is a member of the parent ",(0,o.jsx)(n.code,{children:"Vec"})," Chisel type"]}),"\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"Wire(Vec(3, UInt(2.W)))(0)"})," is a member of the parent ",(0,o.jsx)(n.code,{children:"Wire"})," component"]}),"\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"IO(Decoupled(Bool)).ready"})," is a member of the parent ",(0,o.jsx)(n.code,{children:"IO"})," component"]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:['"relative alignment" - whether two members of the same component or Chisel type are aligned/flipped, relative to one another',"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["see section ",(0,o.jsx)(n.a,{href:"#alignment-flipped-vs-aligned",children:"below"})," for a detailed definition"]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:['"structural type check" - Chisel type ',(0,o.jsx)(n.code,{children:"A"})," is structurally equivalent to Chisel type ",(0,o.jsx)(n.code,{children:"B"})," if ",(0,o.jsx)(n.code,{children:"A"})," and ",(0,o.jsx)(n.code,{children:"B"})," have matching bundle field names and types (",(0,o.jsx)(n.code,{children:"Record"})," vs ",(0,o.jsx)(n.code,{children:"Vector"})," vs ",(0,o.jsx)(n.code,{children:"Element"}),"), probe modifiers (probe vs nonprobe), vector sizes, ",(0,o.jsx)(n.code,{children:"Element"})," types (UInt/SInt/Bool/Clock)","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"ignores relative alignment (flippedness)"}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:['"alignment type check" - a Chisel type ',(0,o.jsx)(n.code,{children:"A"})," matches alignment with another Chisel type ",(0,o.jsx)(n.code,{children:"B"})," if every member of ",(0,o.jsx)(n.code,{children:"A"}),"'s relative alignment to ",(0,o.jsx)(n.code,{children:"A"})," is the same as the structurally corresponding member of ",(0,o.jsx)(n.code,{children:"B"}),"'s relative alignment to ",(0,o.jsx)(n.code,{children:"B"}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"Connectable"})," operators are the standard way to connect Chisel hardware components to one another."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note: For descriptions of the semantics for the previous operators, see ",(0,o.jsx)(n.a,{href:"connection-operators",children:(0,o.jsx)(n.code,{children:"Connection Operators"})}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"All connection operators require the two hardware components (consumer and producer) to be structurally type equivalent."}),"\n",(0,o.jsxs)(n.p,{children:["The one exception to the structural type-equivalence rule is using the ",(0,o.jsx)(n.code,{children:"Connectable"})," mechanism, detailed at this ",(0,o.jsx)(n.a,{href:"#techniques-for-connecting-structurally-inequivalent-chisel-types",children:"section"})," towards the end of this document."]}),"\n",(0,o.jsxs)(n.p,{children:["Aggregate (",(0,o.jsx)(n.code,{children:"Record"}),", ",(0,o.jsx)(n.code,{children:"Vec"}),", ",(0,o.jsx)(n.code,{children:"Bundle"}),") Chisel types can include data members which are flipped relative to one another.\nDue to this, there are many desired connection behaviors between two Chisel components.\nThe following are the Chisel connection operators between a consumer ",(0,o.jsx)(n.code,{children:"c"})," and producer ",(0,o.jsx)(n.code,{children:"p"}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c := p"})," (mono-direction): connects all ",(0,o.jsx)(n.code,{children:"p"})," members to ",(0,o.jsx)(n.code,{children:"c"}),"; requires ",(0,o.jsx)(n.code,{children:"c"})," and ",(0,o.jsx)(n.code,{children:"p"})," to not have any flipped members"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c :#= p"})," (coercing mono-direction): connects all ",(0,o.jsx)(n.code,{children:"p"})," members to ",(0,o.jsx)(n.code,{children:"c"}),"; regardless of alignment"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c :<= p"})," (aligned-direction): connects all aligned (non-flipped) ",(0,o.jsx)(n.code,{children:"c"})," members from ",(0,o.jsx)(n.code,{children:"p"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c :>= p"})," (flipped-direction): connects all flipped ",(0,o.jsx)(n.code,{children:"p"})," members from ",(0,o.jsx)(n.code,{children:"c"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c :<>= p"})," (bi-direction operator): connects all aligned ",(0,o.jsx)(n.code,{children:"c"})," members from ",(0,o.jsx)(n.code,{children:"p"}),"; all flipped ",(0,o.jsx)(n.code,{children:"p"})," members from ",(0,o.jsx)(n.code,{children:"c"})]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"These operators may appear to be a random collection of symbols; however, the characters are consistent between operators and self-describe the semantics of each operator:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:":"})," always indicates the consumer, or left-hand-side, of the operator."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"="})," always indicates the producer, or right-hand-side, of the operator.","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c := p"})," connects a consumer (",(0,o.jsx)(n.code,{children:"c"}),") and a producer (",(0,o.jsx)(n.code,{children:"p"}),")."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"<"})," always indicates that some members will be driven producer-to-consumer, or right-to-left.","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c :<= p"})," drives members in producer (",(0,o.jsx)(n.code,{children:"p"}),") to members in consumer (",(0,o.jsx)(n.code,{children:"c"}),")."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:">"})," always indicates that some signals will be driven consumer-to-producer, or left-to-right.","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c :>= p"})," drives members in consumer (",(0,o.jsx)(n.code,{children:"c"}),") to members producer (",(0,o.jsx)(n.code,{children:"p"}),")."]}),"\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c :<>= p"})," both drives members from ",(0,o.jsx)(n.code,{children:"p"})," to ",(0,o.jsx)(n.code,{children:"c"})," and from ",(0,o.jsx)(n.code,{children:"c"})," to ",(0,o.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"#"})," always indicates to ignore member alignment and to drive producer-to-consumer, or right-to-left.","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c :#= p"})," always drives members from ",(0,o.jsx)(n.code,{children:"p"})," to ",(0,o.jsx)(n.code,{children:"c"})," ignoring direction."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note: in addition, an operator that ends in ",(0,o.jsx)(n.code,{children:"="})," has assignment-precedence, which means that ",(0,o.jsx)(n.code,{children:"x :<>= y + z"})," will translate to ",(0,o.jsx)(n.code,{children:"x :<>= (y + z)"}),", rather than ",(0,o.jsx)(n.code,{children:"(x :<>= y) + z"}),".\nThis was not true of the ",(0,o.jsx)(n.code,{children:"<>"})," operator and was a minor painpoint for users."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"alignment-flipped-vs-aligned",children:"Alignment: Flipped vs Aligned"}),"\n",(0,o.jsxs)(n.p,{children:["A member's alignment is a relative property: a member is aligned/flipped relative to another member of the same component or Chisel type.\nHence, one must always say whether a member is flipped/aligned ",(0,o.jsx)(n.em,{children:"with respect to (w.r.t)"})," another member of that type (parent, sibling, child etc.)."]}),"\n",(0,o.jsxs)(n.p,{children:["We use the following example of a non-nested bundle ",(0,o.jsx)(n.code,{children:"Parent"})," to let us state all of the alignment relationships between members of ",(0,o.jsx)(n.code,{children:"p"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass Parent extends Bundle {\n val alignedChild = UInt(32.W)\n val flippedChild = Flipped(UInt(32.W))\n}\nclass MyModule0 extends Module {\n val p = Wire(new Parent)\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"First, every member is always aligned with themselves:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.alignedChild"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.flippedChild"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedChild"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Next, we list all parent/child relationships.\nBecause the ",(0,o.jsx)(n.code,{children:"flippedChild"})," field is ",(0,o.jsx)(n.code,{children:"Flipped"}),", it changes its alignment relative to its parent."]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedChild"})]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Finally, we can list all sibling relationships:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.alignedChild"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedChild"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["The next example has a nested bundle ",(0,o.jsx)(n.code,{children:"GrandParent"})," who instantiates an aligned ",(0,o.jsx)(n.code,{children:"Parent"})," field and flipped ",(0,o.jsx)(n.code,{children:"Parent"})," field."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass GrandParent extends Bundle {\n val alignedParent = new Parent\n val flippedParent = Flipped(new Parent)\n}\nclass MyModule1 extends Module {\n val g = Wire(new GrandParent)\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Consider the following alignments between grandparent and grandchildren.\nAn odd number of flips indicate a flipped relationship; even numbers of flips indicate an aligned relationship."}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"g.flippedParent.flippedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"g.alignedParent.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"g.flippedParent.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"g.alignedParent.flippedChild"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Consider the following alignment relationships starting from ",(0,o.jsx)(n.code,{children:"g.alignedParent"})," and ",(0,o.jsx)(n.code,{children:"g.flippedParent"}),".\n",(0,o.jsxs)(n.em,{children:["Note that whether ",(0,o.jsx)(n.code,{children:"g.alignedParent"})," is aligned/flipped relative to ",(0,o.jsx)(n.code,{children:"g"})," has no effect on the aligned/flipped relationship between ",(0,o.jsx)(n.code,{children:"g.alignedParent"})," and ",(0,o.jsx)(n.code,{children:"g.alignedParent.alignedChild"})," because alignment is only relative to the two members in question!"]}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.alignedParent"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.alignedParent.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.flippedParent"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.flippedParent.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.alignedParent"})," is flipped w.r.t. ",(0,o.jsx)(n.code,{children:"g.alignedParent.flippedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.flippedParent"})," is flipped w.r.t. ",(0,o.jsx)(n.code,{children:"g.flippedParent.flippedChild"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["In summary, a member is aligned or flipped w.r.t. another member of the hardware component.\nThis means that the type of the consumer/producer is the only information needed to determine the behavior of any operator.\n",(0,o.jsx)(n.em,{children:"Whether the consumer/producer is a member of a larger bundle is irrelevant; you ONLY need to know the type of the consumer/producer"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"inputoutput",children:"Input/Output"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"Input(gen)"}),"/",(0,o.jsx)(n.code,{children:"Output(gen)"})," are coercing operators.\nThey perform two functions: (1) create a new Chisel type that has all flips removed from all recursive children members (still structurally equivalent to ",(0,o.jsx)(n.code,{children:"gen"})," but no longer alignment type equivalent), and (2) apply ",(0,o.jsx)(n.code,{children:"Flipped"})," if ",(0,o.jsx)(n.code,{children:"Input"}),", keep aligned (do nothing) if ",(0,o.jsx)(n.code,{children:"Output"}),".\nE.g. if we imagine a function called ",(0,o.jsx)(n.code,{children:"cloneChiselTypeButStripAllFlips"}),", then ",(0,o.jsx)(n.code,{children:"Input(gen)"})," is structurally and alignment type equivalent to ",(0,o.jsx)(n.code,{children:"Flipped(cloneChiselTypeButStripAllFlips(gen))"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Note that if ",(0,o.jsx)(n.code,{children:"gen"})," is a non-aggregate, then ",(0,o.jsx)(n.code,{children:"Input(nonAggregateGen)"})," is equivalent to ",(0,o.jsx)(n.code,{children:"Flipped(nonAggregateGen)"}),"."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Future work will refactor how these primitives are exposed to the user to make Chisel's type system more intuitive.\nSee [",(0,o.jsx)(n.a,{href:"https://github.com/chipsalliance/chisel3/issues/2643",children:"https://github.com/chipsalliance/chisel3/issues/2643"}),"]."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"With this in mind, we can consider the following examples and detail relative alignments of members."}),"\n",(0,o.jsxs)(n.p,{children:["First, we can use a similar example to ",(0,o.jsx)(n.code,{children:"Parent"})," but use ",(0,o.jsx)(n.code,{children:"Input/Output"})," instead of ",(0,o.jsx)(n.code,{children:"Flipped"}),".\nBecause ",(0,o.jsx)(n.code,{children:"alignedChild"})," and ",(0,o.jsx)(n.code,{children:"flippedChild"})," are non-aggregates, ",(0,o.jsx)(n.code,{children:"Input"})," is basically just a ",(0,o.jsx)(n.code,{children:"Flipped"})," and thus the alignments are unchanged compared to the previous ",(0,o.jsx)(n.code,{children:"Parent"})," example."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass ParentWithOutputInput extends Bundle {\n val alignedCoerced = Output(UInt(32.W)) // Equivalent to just UInt(32.W)\n val flippedCoerced = Input(UInt(32.W)) // Equivalent to Flipped(UInt(32.W))\n}\nclass MyModule2 extends Module {\n val p = Wire(new ParentWithOutputInput)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["The alignments are the same as the previous ",(0,o.jsx)(n.code,{children:"Parent"})," example:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.alignedCoerced"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.flippedCoerced"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.alignedCoerced"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedCoerced"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["The next example has a nested bundle ",(0,o.jsx)(n.code,{children:"GrandParent"})," who instantiates an ",(0,o.jsx)(n.code,{children:"Output"})," ",(0,o.jsx)(n.code,{children:"ParentWithOutputInput"})," field and an ",(0,o.jsx)(n.code,{children:"Input"})," ",(0,o.jsx)(n.code,{children:"ParentWithOutputInput"})," field."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass GrandParentWithOutputInput extends Bundle {\n val alignedCoerced = Output(new ParentWithOutputInput)\n val flippedCoerced = Input(new ParentWithOutputInput)\n}\nclass MyModule3 extends Module {\n val g = Wire(new GrandParentWithOutputInput)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["Remember that ",(0,o.jsx)(n.code,{children:"Output(gen)/Input(gen)"})," recursively strips the ",(0,o.jsx)(n.code,{children:"Flipped"})," of any recursive children.\nThis makes every member of ",(0,o.jsx)(n.code,{children:"gen"})," aligned with every other member of ",(0,o.jsx)(n.code,{children:"gen"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Consider the following alignments between grandparent and grandchildren.\nBecause ",(0,o.jsx)(n.code,{children:"alignedCoerced"})," and ",(0,o.jsx)(n.code,{children:"flippedCoerced"})," are aligned with all their recursive members, they are fully aligned.\nThus, only their alignment to ",(0,o.jsx)(n.code,{children:"g"})," influences grandchildren alignment:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.flippedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"g.flippedCoerced.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"g.flippedCoerced.flippedCoerced"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Consider the following alignment relationships starting from ",(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," and ",(0,o.jsx)(n.code,{children:"g.flippedCoerced"}),".\n",(0,o.jsxs)(n.em,{children:["Note that whether ",(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," is aligned/flipped relative to ",(0,o.jsx)(n.code,{children:"g"})," has no effect on the aligned/flipped relationship between ",(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," and ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.alignedCoerced"})," or ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.flippedCoerced"})," because alignment is only relative to the two members in question! However, because alignment is coerced, everything is aligned between ",(0,o.jsx)(n.code,{children:"g.alignedCoerced"}),"/",(0,o.jsx)(n.code,{children:"g.flippedAligned"})," and their children"]}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.flippedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.flippedCoerced"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.flippedCoerced.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.flippedCoerced"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.flippedCoerced.flippedCoerced"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["In summary, ",(0,o.jsx)(n.code,{children:"Input(gen)"})," and ",(0,o.jsx)(n.code,{children:"Output(gen)"})," recursively coerce children alignment, as well as dictate ",(0,o.jsx)(n.code,{children:"gen"}),"'s alignment to its parent bundle (if it exists)."]}),"\n",(0,o.jsx)(n.h2,{id:"connecting-components-with-fully-aligned-members",children:"Connecting components with fully aligned members"}),"\n",(0,o.jsx)(n.h3,{id:"mono-direction-connection-operator-",children:"Mono-direction connection operator (:=)"}),"\n",(0,o.jsxs)(n.p,{children:["For simple connections where all members are aligned (non-flipped) w.r.t. one another, use ",(0,o.jsx)(n.code,{children:":="}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass FullyAlignedBundle extends Bundle {\n val a = Bool()\n val b = Bool()\n}\nclass Example0 extends RawModule {\n val incoming = IO(Flipped(new FullyAlignedBundle))\n val outgoing = IO(new FullyAlignedBundle)\n outgoing := incoming\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where each member of ",(0,o.jsx)(n.code,{children:"incoming"})," drives every member of ",(0,o.jsx)(n.code,{children:"outgoing"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example0(\n input incoming_a,\n incoming_b,\n output outgoing_a,\n outgoing_b\n);\n\n assign outgoing_a = incoming_a;\n assign outgoing_b = incoming_b;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["You may be thinking \"Wait, I'm confused! Isn't ",(0,o.jsx)(n.code,{children:"incoming"})," flipped and ",(0,o.jsx)(n.code,{children:"outgoing"}),' aligned?" -- Noo! Whether ',(0,o.jsx)(n.code,{children:"incoming"})," is aligned with ",(0,o.jsx)(n.code,{children:"outgoing"})," makes no sense; remember, you only evaluate alignment between members of the same component or Chisel type.\nBecause components are always aligned to themselves, ",(0,o.jsx)(n.code,{children:"outgoing"})," is aligned to ",(0,o.jsx)(n.code,{children:"outgoing"}),", and ",(0,o.jsx)(n.code,{children:"incoming"})," is aligned to ",(0,o.jsx)(n.code,{children:"incoming"}),", there is no problem.\nTheir relative flippedness to anything else is irrelevant."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"connecting-components-with-mixed-alignment-members",children:"Connecting components with mixed alignment members"}),"\n",(0,o.jsxs)(n.p,{children:["Aggregate Chisel types can include data members which are flipped relative to one another; in the example below, ",(0,o.jsx)(n.code,{children:"alignedChild"})," and ",(0,o.jsx)(n.code,{children:"flippedChild"})," are aligned/flipped relative to ",(0,o.jsx)(n.code,{children:"MixedAlignmentBundle"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass MixedAlignmentBundle extends Bundle {\n val alignedChild = Bool()\n val flippedChild = Flipped(Bool())\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["Due to this, there are many desired connection behaviors between two Chisel components.\nFirst we will introduce the most common Chisel connection operator, ",(0,o.jsx)(n.code,{children:":<>="}),", useful for connecting components with members of mixed-alignments, then take a moment to investigate a common source of confusion between port-direction and connection-direction.\nThen, we will explore the remainder of the Chisel connection operators."]}),"\n",(0,o.jsxs)(n.h3,{id:"bi-direction-connection-operator-",children:["Bi-direction connection operator (",(0,o.jsx)(n.code,{children:":<>="}),")"]}),"\n",(0,o.jsxs)(n.p,{children:["For connections where you want 'bulk-connect-like-semantics' where the aligned members are driven producer-to-consumer and flipped members are driven consumer-to-producer, use ",(0,o.jsx)(n.code,{children:":<>="}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Example1 extends RawModule {\n val incoming = IO(Flipped(new MixedAlignmentBundle))\n val outgoing = IO(new MixedAlignmentBundle)\n outgoing :<>= incoming\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where the aligned members are driven ",(0,o.jsx)(n.code,{children:"incoming"})," to ",(0,o.jsx)(n.code,{children:"outgoing"})," and flipped members are driven ",(0,o.jsx)(n.code,{children:"outgoing"})," to ",(0,o.jsx)(n.code,{children:"incoming"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example1(\n input incoming_alignedChild,\n output incoming_flippedChild,\n outgoing_alignedChild,\n input outgoing_flippedChild\n);\n\n assign incoming_flippedChild = outgoing_flippedChild;\n assign outgoing_alignedChild = incoming_alignedChild;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"port-direction-computation-versus-connection-direction-computation",children:"Port-Direction Computation versus Connection-Direction Computation"}),"\n",(0,o.jsxs)(n.p,{children:["A common question is if you use a mixed-alignment connection (such as ",(0,o.jsx)(n.code,{children:":<>="}),") to connect submembers of parent components, does the alignment of the submember to their parent affect anything? The answer is no, because ",(0,o.jsx)(n.em,{children:"alignment is always computed relative to what is being connected to, and members are always aligned with themselves."})]}),"\n",(0,o.jsxs)(n.p,{children:["In the following example connecting from ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," to ",(0,o.jsx)(n.code,{children:"outgoing.alignedChild"}),", whether ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," is aligned with ",(0,o.jsx)(n.code,{children:"incoming"})," is irrelevant because the ",(0,o.jsx)(n.code,{children:":<>="})," only computes alignment relative to the thing being connected to, and ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," is aligned with ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Example1a extends RawModule {\n val incoming = IO(Flipped(new MixedAlignmentBundle))\n val outgoing = IO(new MixedAlignmentBundle)\n outgoing.alignedChild :<>= incoming.alignedChild // whether incoming.alignedChild is aligned/flipped to incoming is IRRELEVANT to what gets connected with :<>=\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["While ",(0,o.jsx)(n.code,{children:"incoming.flippedChild"}),"'s alignment with ",(0,o.jsx)(n.code,{children:"incoming"})," does not affect our operators, it does influence whether ",(0,o.jsx)(n.code,{children:"incoming.flippedChild"})," is an output or input port of my module.\nA common source of confusion is to mistake the process for determining whether ",(0,o.jsx)(n.code,{children:"incoming.flippedChild"})," will resolve to a Verilog ",(0,o.jsx)(n.code,{children:"output"}),"/",(0,o.jsx)(n.code,{children:"input"})," (the port-direction computation) with the process for determining how ",(0,o.jsx)(n.code,{children:":<>="})," drives what with what (the connection-direction computation).\nWhile both processes consider relative alignment, they are distinct."]}),"\n",(0,o.jsxs)(n.p,{children:["The port-direction computation always computes alignment relative to the component marked with ",(0,o.jsx)(n.code,{children:"IO"}),".\nAn ",(0,o.jsx)(n.code,{children:"IO(Flipped(gen))"})," is an incoming port, and any member of ",(0,o.jsx)(n.code,{children:"gen"})," that is aligned/flipped with ",(0,o.jsx)(n.code,{children:"gen"})," is an incoming/outgoing port.\nAn ",(0,o.jsx)(n.code,{children:"IO(gen)"})," is an outgoing port, and any member of ",(0,o.jsx)(n.code,{children:"gen"})," that is aligned/flipped with ",(0,o.jsx)(n.code,{children:"gen"})," is an outgoing/incoming port."]}),"\n",(0,o.jsxs)(n.p,{children:["The connection-direction computation always computes alignment based on the explicit consumer/producer referenced for the connection.\nIf one connects ",(0,o.jsx)(n.code,{children:"incoming :<>= outgoing"}),", alignments are computed based on ",(0,o.jsx)(n.code,{children:"incoming"})," and ",(0,o.jsx)(n.code,{children:"outgoing"}),".\nIf one connects ",(0,o.jsx)(n.code,{children:"incoming.alignedChild :<>= outgoing.alignedChild"}),", then alignments are computed based on ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," and ",(0,o.jsx)(n.code,{children:"outgoing.alignedChild"})," (and the alignment of ",(0,o.jsx)(n.code,{children:"incoming"})," to ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," is irrelevant)."]}),"\n",(0,o.jsxs)(n.p,{children:["This means that users can try to connect to input ports of their module! If I write ",(0,o.jsx)(n.code,{children:"x :<>= y"}),", and ",(0,o.jsx)(n.code,{children:"x"})," is an input to the current module, then that is what the connection is trying to do.\nHowever, because input ports are not drivable from within the current module, Chisel will throw an error.\nThis is the same error a user would get using a mono-directioned operator: ",(0,o.jsx)(n.code,{children:"x := y"})," will throw the same error if ",(0,o.jsx)(n.code,{children:"x"})," is an input to the current module.\n",(0,o.jsx)(n.em,{children:"Whether a component is drivable is irrelevant to the semantics of any connection operator attempting to drive to it."})]}),"\n",(0,o.jsxs)(n.p,{children:["In summary, the port-direction computation is relative to the root marked ",(0,o.jsx)(n.code,{children:"IO"}),", but connection-direction computation is relative to the consumer/producer that the connection is doing.\nThis has the positive property that connection semantics are solely based on the Chisel structural type and its relative alignments of the consumer/producer (nothing more, nothing less)."]}),"\n",(0,o.jsxs)(n.h3,{id:"aligned-connection-operator-",children:["Aligned connection operator (",(0,o.jsx)(n.code,{children:":<="}),")"]}),"\n",(0,o.jsxs)(n.p,{children:["For connections where you want the aligned-half of 'bulk-connect-like-semantics' where the aligned members are driven producer-to-consumer and flipped members are ignored, use ",(0,o.jsx)(n.code,{children:":<="}),' (the "aligned connection").']}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Example2 extends RawModule {\n val incoming = IO(Flipped(new MixedAlignmentBundle))\n val outgoing = IO(new MixedAlignmentBundle)\n incoming.flippedChild := DontCare // Otherwise FIRRTL throws an uninitialization error\n outgoing :<= incoming\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where the aligned members are driven ",(0,o.jsx)(n.code,{children:"incoming"})," to ",(0,o.jsx)(n.code,{children:"outgoing"})," and flipped members are ignored:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example2(\n input incoming_alignedChild,\n output incoming_flippedChild,\n outgoing_alignedChild,\n input outgoing_flippedChild\n);\n\n assign incoming_flippedChild = 1'h0;\n assign outgoing_alignedChild = incoming_alignedChild;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.h3,{id:"flipped-connection-operator-",children:["Flipped connection operator (",(0,o.jsx)(n.code,{children:":>="}),")"]}),"\n",(0,o.jsxs)(n.p,{children:["For connections where you want the flipped-half of 'bulk-connect-like-semantics' where the aligned members are ignored and flipped members are connected consumer-to-producer, use ",(0,o.jsx)(n.code,{children:":>="}),' (the "flipped connection", or "backpressure connection").']}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Example3 extends RawModule {\n val incoming = IO(Flipped(new MixedAlignmentBundle))\n val outgoing = IO(new MixedAlignmentBundle)\n outgoing.alignedChild := DontCare // Otherwise FIRRTL throws an uninitialization error\n outgoing :>= incoming\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where the aligned members are ignored and the flipped members are driven ",(0,o.jsx)(n.code,{children:"outgoing"})," to ",(0,o.jsx)(n.code,{children:"incoming"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example3(\n input incoming_alignedChild,\n output incoming_flippedChild,\n outgoing_alignedChild,\n input outgoing_flippedChild\n);\n\n assign incoming_flippedChild = outgoing_flippedChild;\n assign outgoing_alignedChild = 1'h0;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note: Astute observers will realize that ",(0,o.jsx)(n.code,{children:"c :<>= p"})," is semantically equivalent to ",(0,o.jsx)(n.code,{children:"c :<= p"})," followed by ",(0,o.jsx)(n.code,{children:"c :>= p"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.h3,{id:"coercing-mono-direction-connection-operator-",children:["Coercing mono-direction connection operator (",(0,o.jsx)(n.code,{children:":#="}),")"]}),"\n",(0,o.jsxs)(n.p,{children:["For connections where you want to every producer member to always drive every consumer member, regardless of alignment, use ",(0,o.jsx)(n.code,{children:":#="}),' (the "coercion connection").\nThis operator is useful for initializing wires whose types contain members of mixed alignment.']}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.BundleLiterals._\nclass Example4 extends RawModule {\n val w = Wire(new MixedAlignmentBundle)\n dontTouch(w) // So we see it in the output Verilog\n w :#= (new MixedAlignmentBundle).Lit(_.alignedChild -> true.B, _.flippedChild -> true.B)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where all members are driven from the literal to ",(0,o.jsx)(n.code,{children:"w"}),", regardless of alignment:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example4();\n wire w_alignedChild = 1'h1;\n wire w_flippedChild = 1'h1;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note: Astute observers will realize that ",(0,o.jsx)(n.code,{children:"c :#= p"})," is semantically equivalent to ",(0,o.jsx)(n.code,{children:"c :<= p"})," followed by ",(0,o.jsx)(n.code,{children:"p :>= c"})," (note ",(0,o.jsx)(n.code,{children:"p"})," and ",(0,o.jsx)(n.code,{children:"c"})," switched places in the second connection)."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Another use case for ",(0,o.jsx)(n.code,{children:":#="})," is for connecting a mixed-directional bundle to a fully-aligned monitor."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.BundleLiterals._\nclass Example4b extends RawModule {\n val monitor = IO(Output(new MixedAlignmentBundle))\n val w = Wire(new MixedAlignmentBundle)\n dontTouch(w) // So we see it in the output Verilog\n w :#= DontCare\n monitor :#= w\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where all members are driven from the literal to ",(0,o.jsx)(n.code,{children:"w"}),", regardless of alignment:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example4b(\n output monitor_alignedChild,\n monitor_flippedChild\n);\n\n wire w_alignedChild = 1'h0;\n wire w_flippedChild = 1'h0;\n assign monitor_alignedChild = w_alignedChild;\n assign monitor_flippedChild = w_flippedChild;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h2,{id:"connectable",children:"Connectable"}),"\n",(0,o.jsxs)(n.p,{children:["Sometimes a user wants to connect Chisel components which are not type equivalent.\nFor example, a user may want to hook up anonymous ",(0,o.jsx)(n.code,{children:"Record"})," components who may have an intersection of their fields being equivalent, but cannot because they are not structurally equivalent.\nAlternatively, one may want to connect two types that have different widths."]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"Connectable"})," is the mechanism to specialize connection operator behavior in these scenarios.\nFor additional members which are not present in the other component being connected to, or for mismatched widths, or for always excluding a member from being connected to, they can be explicitly called out from the ",(0,o.jsx)(n.code,{children:"Connectable"})," object, rather than trigger an error."]}),"\n",(0,o.jsxs)(n.p,{children:["In addition, there are other techniques that can be used to address similar use cases including ",(0,o.jsx)(n.code,{children:".viewAsSuperType"}),", a static cast to a supertype (e.g. ",(0,o.jsx)(n.code,{children:"(x: T)"}),"), or creating a custom ",(0,o.jsx)(n.code,{children:"DataView"}),".\nFor a discussion about when to use each technique, please continue ",(0,o.jsx)(n.a,{href:"#techniques-for-connecting-structurally-inequivalent-chisel-types",children:"here"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["This section demonstrates how ",(0,o.jsx)(n.code,{children:"Connectable"})," specifically can be used in a multitude of scenarios."]}),"\n",(0,o.jsx)(n.h3,{id:"connecting-records",children:"Connecting Records"}),"\n",(0,o.jsxs)(n.p,{children:["One use case is to try to connect two ",(0,o.jsx)(n.code,{children:"Record"}),"s; for matching members, they should be connected, but for unmatched members, the errors caused due to them being unmatched should be ignored.\nTo accomplish this, use the other operators to initialize all ",(0,o.jsx)(n.code,{children:"Record"})," members, then use ",(0,o.jsx)(n.code,{children:":<>="})," with ",(0,o.jsx)(n.code,{children:".waive"})," to connect only the matching members."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note that none of ",(0,o.jsx)(n.code,{children:".viewAsSuperType"}),", static casts, nor a custom ",(0,o.jsx)(n.code,{children:"DataView"})," helps this case because the Scala types are still ",(0,o.jsx)(n.code,{children:"Record"}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:'import scala.collection.immutable.SeqMap\n\nclass Example9 extends RawModule {\n val abType = new Record { val elements = SeqMap("a" -> Bool(), "b" -> Flipped(Bool())) }\n val bcType = new Record { val elements = SeqMap("b" -> Flipped(Bool()), "c" -> Bool()) }\n\n val p = IO(Flipped(abType))\n val c = IO(bcType)\n\n DontCare :>= p\n c :<= DontCare\n\n c.waive(_.elements("c")):<>= p.waive(_.elements("a"))\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"p.b"})," is driven from ",(0,o.jsx)(n.code,{children:"c.b"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example9(\n output p_b,\n input p_a,\n output c_c,\n input c_b\n);\n\n assign p_b = c_b;\n assign c_c = 1'h0;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"defaults-with-waived-connections",children:"Defaults with waived connections"}),"\n",(0,o.jsxs)(n.p,{children:["Another use case is to try to connect two ",(0,o.jsx)(n.code,{children:"Record"}),"s; for matching members, they should be connected, but for unmatched members, ",(0,o.jsx)(n.em,{children:"they should be connected to a default value"}),".\nTo accomplish this, use the other operators to initialize all ",(0,o.jsx)(n.code,{children:"Record"})," members, then use ",(0,o.jsx)(n.code,{children:":<>="})," with ",(0,o.jsx)(n.code,{children:".waive"})," to connect only the matching members."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:'import scala.collection.immutable.SeqMap\n\nclass Example10 extends RawModule {\n val abType = new Record { val elements = SeqMap("a" -> Bool(), "b" -> Flipped(Bool())) }\n val bcType = new Record { val elements = SeqMap("b" -> Flipped(Bool()), "c" -> Bool()) }\n\n val p = Wire(abType)\n val c = Wire(bcType)\n\n dontTouch(p) // So it doesn\'t get constant-propped away for the example\n dontTouch(c) // So it doesn\'t get constant-propped away for the example\n\n p :#= abType.Lit(_.elements("a") -> true.B, _.elements("b") -> true.B)\n c :#= bcType.Lit(_.elements("b") -> true.B, _.elements("c") -> true.B)\n\n c.waive(_.elements("c")) :<>= p.waive(_.elements("a"))\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"p.b"})," is driven from ",(0,o.jsx)(n.code,{children:"c.b"}),", and ",(0,o.jsx)(n.code,{children:"p.a"}),", ",(0,o.jsx)(n.code,{children:"c.b"}),", and ",(0,o.jsx)(n.code,{children:"c.c"})," are initialized to default values:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example10();\n wire p_a = 1'h1;\n wire c_c = 1'h1;\n wire c_b = 1'h1;\n wire p_b = c_b;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"connecting-types-with-optional-members",children:"Connecting types with optional members"}),"\n",(0,o.jsxs)(n.p,{children:["In the following example, we can use ",(0,o.jsx)(n.code,{children:":<>="})," and ",(0,o.jsx)(n.code,{children:".waive"})," to connect two ",(0,o.jsx)(n.code,{children:"MyDecoupledOpts"}),"'s, where only one has a ",(0,o.jsx)(n.code,{children:"bits"})," member."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class MyDecoupledOpt(hasBits: Boolean) extends Bundle {\n val valid = Bool()\n val ready = Flipped(Bool())\n val bits = if (hasBits) Some(UInt(32.W)) else None\n}\nclass Example6 extends RawModule {\n val in = IO(Flipped(new MyDecoupledOpt(true)))\n val out = IO(new MyDecoupledOpt(false))\n out :<>= in.waive(_.bits.get) // We can know to call .get because we can inspect in.bits.isEmpty\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"ready"})," and ",(0,o.jsx)(n.code,{children:"valid"})," are connected, and ",(0,o.jsx)(n.code,{children:"bits"})," is ignored:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example6(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"always-ignore-errors-caused-by-extra-members-partial-connection-operator",children:"Always ignore errors caused by extra members (partial connection operator)"}),"\n",(0,o.jsx)(n.p,{children:"The most unsafe connection is to connect only members that are present in both consumer and producer, and ignore all other members.\nThis is unsafe because this connection will never error on any Chisel types."}),"\n",(0,o.jsxs)(n.p,{children:["To do this, you can use ",(0,o.jsx)(n.code,{children:".waiveAll"})," and static cast to ",(0,o.jsx)(n.code,{children:"Data"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class OnlyA extends Bundle {\n val a = UInt(32.W)\n}\nclass OnlyB extends Bundle {\n val b = UInt(32.W)\n}\nclass Example11 extends RawModule {\n val in = IO(Flipped(new OnlyA))\n val out = IO(new OnlyB)\n\n out := DontCare\n\n (out: Data).waiveAll :<>= (in: Data).waiveAll\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"This generates the following Verilog, where nothing is connected:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example11(\n input [31:0] in_a,\n output [31:0] out_b\n);\n\n assign out_b = 32'h0;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"connecting-components-with-different-widths",children:"Connecting components with different widths"}),"\n",(0,o.jsxs)(n.p,{children:["Non-",(0,o.jsx)(n.code,{children:"Connectable"})," operators implicitly truncate if a component with a larger width is connected to a component with a smaller width.\n",(0,o.jsx)(n.code,{children:"Connectable"})," operators disallow this implicit truncation behavior and require the driven component to be equal or larger in width that the sourcing component."]}),"\n",(0,o.jsxs)(n.p,{children:["If implicit truncation behavior is desired, then ",(0,o.jsx)(n.code,{children:"Connectable"})," provides a ",(0,o.jsx)(n.code,{children:"squeeze"})," mechanism which will allow the connection to continue with implicit truncation."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import scala.collection.immutable.SeqMap\n\nclass Example14 extends RawModule {\n val p = IO(Flipped(UInt(4.W)))\n val c = IO(UInt(3.W))\n\n c :<>= p.squeeze\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"p"})," is truncated prior to driving ",(0,o.jsx)(n.code,{children:"c"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example14(\n input [3:0] p,\n output [2:0] c\n);\n\n assign c = p[2:0];\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"excluding-members-from-any-operator-on-a-connectable",children:"Excluding members from any operator on a Connectable"}),"\n",(0,o.jsxs)(n.p,{children:["If a user wants to always exclude a field from a connect, use the ",(0,o.jsx)(n.code,{children:".exclude"})," mechanism which will never connect the field (as if it didn't exist to the connection)."]}),"\n",(0,o.jsxs)(n.p,{children:["Note that if a field matches in both producer and consumer, but only one is excluded, the other non-excluded field will still trigger an error; to fix this, use either ",(0,o.jsx)(n.code,{children:".waive"})," or ",(0,o.jsx)(n.code,{children:".exclude"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import scala.collection.immutable.SeqMap\n\nclass BundleWithSpecialField extends Bundle {\n val foo = UInt(3.W)\n val special = Bool()\n}\nclass Example15 extends RawModule {\n val p = IO(Flipped(new BundleWithSpecialField()))\n val c = IO(new BundleWithSpecialField())\n\n c.special := true.B // must initialize it\n\n c.exclude(_.special) :<>= p.exclude(_.special)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where the ",(0,o.jsx)(n.code,{children:"special"})," field is not connected:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example15(\n input [2:0] p_foo,\n input p_special,\n output [2:0] c_foo,\n output c_special\n);\n\n assign c_foo = p_foo;\n assign c_special = 1'h1;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h2,{id:"techniques-for-connecting-structurally-inequivalent-chisel-types",children:"Techniques for connecting structurally inequivalent Chisel types"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"DataView"})," and ",(0,o.jsx)(n.code,{children:".viewAsSupertype"})," create a view of the component that has a different Chisel type.\nThis means that a user can first create a ",(0,o.jsx)(n.code,{children:"DataView"})," of the consumer or producer (or both) so that the Chisel types are structurally equivalent.\nThis is useful when the difference between the consumer and producer aren't super nested, and also if they have rich Scala types which encode their structure.\nIn general, ",(0,o.jsx)(n.code,{children:"DataView"})," is the preferred mechanism to use (if you can) because it maintains the most amount of Chisel information in the Scala type, but there are many instances where it doesn't work and thus one must fall back on ",(0,o.jsx)(n.code,{children:"Connectable"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"Connectable"})," does not change the Chisel type, but instead changes the semantics of the operator to not error on the waived members if they are dangling or unconnected.\nThis is useful for when differences between the consumer and producer do not show up in the Scala type system (e.g. present/missing fields of type ",(0,o.jsx)(n.code,{children:"Option[Data]"}),", or anonymous ",(0,o.jsx)(n.code,{children:"Record"}),"s) or are deeply nested in a bundle that is especially onerous to create a ",(0,o.jsx)(n.code,{children:"DataView"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Static casts (e.g. ",(0,o.jsx)(n.code,{children:"(x: T)"}),") allows connecting components that have different Scala types, but leaves the Chisel type unchanged.\nUse this to force a connection to occur, even if the Scala types are different."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsx)(n.p,{children:'One may wonder why the operators require identical Scala types in the first place, if they can easily be bypassed.\nThe reason is to encourage users to use the Scala type system to encode Chisel information as it can make their code more robust; however, we don\'t want to be draconian about it because there are times when we want to enable the user to "just connect the darn thing".'}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"When all else fails one can always manually expand the connection to do what they want to happen, member by member.\nThe down-side to this approach is its verbosity and that adding new members to a component will require updating the manual connections."}),"\n",(0,o.jsxs)(n.p,{children:["Things to remember about ",(0,o.jsx)(n.code,{children:"Connectable"})," vs ",(0,o.jsx)(n.code,{children:".viewAsSupertype"}),"/",(0,o.jsx)(n.code,{children:"DataView"})," vs static cast (e.g. ",(0,o.jsx)(n.code,{children:"(x: T)"}),"):"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"DataView"})," and ",(0,o.jsx)(n.code,{children:".viewAsSupertype"})," will preemptively remove members that are not present in the new view which has a different Chisel type, thus ",(0,o.jsx)(n.code,{children:"DataView"})," ",(0,o.jsx)(n.em,{children:"does"})," affect what is connected"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"Connectable"})," can be used to waive the error on members who end up being dangling or unconnected.\nImportantly, ",(0,o.jsx)(n.code,{children:"Connectable"})," waives ",(0,o.jsx)(n.em,{children:"do not"})," affect what is connected"]}),"\n",(0,o.jsxs)(n.li,{children:["Static cast does not remove extra members, thus a static cast ",(0,o.jsx)(n.em,{children:"does not"})," affect what is connected"]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"connecting-different-sub-types-of-the-same-super-type-with-colliding-names",children:"Connecting different sub-types of the same super-type, with colliding names"}),"\n",(0,o.jsxs)(n.p,{children:["In these examples, we are connecting ",(0,o.jsx)(n.code,{children:"MyDecoupled"})," with ",(0,o.jsx)(n.code,{children:"MyDecoupledOtherBits"}),".\nBoth are subtypes of ",(0,o.jsx)(n.code,{children:"MyReadyValid"}),", and both have a ",(0,o.jsx)(n.code,{children:"bits"})," field of type ",(0,o.jsx)(n.code,{children:"UInt(32.W)"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["The first example will use ",(0,o.jsx)(n.code,{children:".viewAsSupertype"})," to connect them as ",(0,o.jsx)(n.code,{children:"MyReadyValid"}),".\nBecause it changes the Chisel type to omit both ",(0,o.jsx)(n.code,{children:"bits"})," fields, the ",(0,o.jsx)(n.code,{children:"bits"})," fields are unconnected."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import experimental.dataview._\nclass MyDecoupledOtherBits extends MyReadyValid {\n val bits = UInt(32.W)\n}\nclass Example12 extends RawModule {\n val in = IO(Flipped(new MyDecoupled))\n val out = IO(new MyDecoupledOtherBits)\n\n out := DontCare\n\n out.viewAsSupertype(new MyReadyValid) :<>= in.viewAsSupertype(new MyReadyValid)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["Note that the ",(0,o.jsx)(n.code,{children:"bits"})," fields are unconnected."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example12(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready,\n output [31:0] out_bits\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\n assign out_bits = 32'h0;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.p,{children:["The second example will use a static cast and ",(0,o.jsx)(n.code,{children:".waive(_.bits)"})," to connect them as ",(0,o.jsx)(n.code,{children:"MyReadyValid"}),".\nNote that because the static cast does not change the Chisel type, the connection finds that both consumer and producer have a ",(0,o.jsx)(n.code,{children:"bits"})," field.\nThis means that since they are structurally equivalent, they match and are connected.\nThe ",(0,o.jsx)(n.code,{children:"waive(_.bits)"})," does nothing, because the ",(0,o.jsx)(n.code,{children:"bits"})," are neither dangling nor unconnected."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import experimental.dataview._\nclass Example13 extends RawModule {\n val in = IO(Flipped(new MyDecoupled))\n val out = IO(new MyDecoupledOtherBits)\n\n out := DontCare\n\n out.waiveAs[MyReadyValid](_.bits) :<>= in.waiveAs[MyReadyValid](_.bits)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["Note that the ",(0,o.jsx)(n.code,{children:"bits"})," fields ARE connected, even though they are waived, as ",(0,o.jsx)(n.code,{children:".waive"})," just changes whether an error should be thrown if they are missing, NOT to not connect them if they are structurally equivalent.\nTo always omit the connection, use ",(0,o.jsx)(n.code,{children:".exclude"})," on one side and either ",(0,o.jsx)(n.code,{children:".exclude"})," or ",(0,o.jsx)(n.code,{children:".waive"})," on the other side."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example13(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready,\n output [31:0] out_bits\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\n assign out_bits = in_bits;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"connecting-sub-types-to-super-types-by-waiving-extra-members",children:"Connecting sub-types to super-types by waiving extra members"}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note that in this example, it would be better to use ",(0,o.jsx)(n.code,{children:".viewAsSupertype"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["In the following example, we can use ",(0,o.jsx)(n.code,{children:":<>="})," to connect a ",(0,o.jsx)(n.code,{children:"MyReadyValid"})," to a ",(0,o.jsx)(n.code,{children:"MyDecoupled"})," by waiving the ",(0,o.jsx)(n.code,{children:"bits"})," member."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class MyReadyValid extends Bundle {\n val valid = Bool()\n val ready = Flipped(Bool())\n}\nclass MyDecoupled extends MyReadyValid {\n val bits = UInt(32.W)\n}\nclass Example5 extends RawModule {\n val in = IO(Flipped(new MyDecoupled))\n val out = IO(new MyReadyValid)\n out :<>= in.waiveAs[MyReadyValid](_.bits)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"ready"})," and ",(0,o.jsx)(n.code,{children:"valid"})," are connected, and ",(0,o.jsx)(n.code,{children:"bits"})," is ignored:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example5(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"connecting-different-sub-types",children:"Connecting different sub-types"}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note that in this example, it would be better to use ",(0,o.jsx)(n.code,{children:".viewAsSupertype"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Note that the connection operator requires the ",(0,o.jsx)(n.code,{children:"consumer"})," and ",(0,o.jsx)(n.code,{children:"producer"})," to be the same Scala type to encourage capturing more information statically, but they can always be cast to ",(0,o.jsx)(n.code,{children:"Data"})," or another common supertype prior to connecting."]}),"\n",(0,o.jsxs)(n.p,{children:["In the following example, we can use ",(0,o.jsx)(n.code,{children:":<>="})," and ",(0,o.jsx)(n.code,{children:".waiveAs"})," to connect two different sub-types of ",(0,o.jsx)(n.code,{children:"MyReadyValid"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class HasBits extends MyReadyValid {\n val bits = UInt(32.W)\n}\nclass HasEcho extends MyReadyValid {\n val echo = Flipped(UInt(32.W))\n}\nclass Example7 extends RawModule {\n val in = IO(Flipped(new HasBits))\n val out = IO(new HasEcho)\n out.waiveAs[MyReadyValid](_.echo) :<>= in.waiveAs[MyReadyValid](_.bits)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"ready"})," and ",(0,o.jsx)(n.code,{children:"valid"})," are connected, and ",(0,o.jsx)(n.code,{children:"bits"})," and ",(0,o.jsx)(n.code,{children:"echo"})," are ignored:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example7(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready,\n input [31:0] out_echo\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h2,{id:"faq",children:"FAQ"}),"\n",(0,o.jsx)(n.h3,{id:"how-do-i-connect-two-items-as-flexibly-as-possible-try-your-best-but-never-error",children:"How do I connect two items as flexibly as possible (try your best but never error)"}),"\n",(0,o.jsxs)(n.p,{children:["Use ",(0,o.jsx)(n.code,{children:".unsafe"})," (both waives and allows squeezing of all fields)."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class ExampleUnsafe extends RawModule {\n val in = IO(Flipped(new Bundle { val foo = Bool(); val bar = Bool() }))\n val out = IO(new Bundle { val baz = Bool(); val bar = Bool() })\n out.unsafe :<>= in.unsafe // bar is connected, and nothing errors\n}\n"})}),"\n",(0,o.jsx)(n.h3,{id:"how-do-i-connect-two-items-but-dont-care-about-the-scala-types-being-equivalent",children:"How do I connect two items but don't care about the Scala types being equivalent?"}),"\n",(0,o.jsxs)(n.p,{children:["Use ",(0,o.jsx)(n.code,{children:".as"})," (upcasts the Scala type)."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class ExampleAs extends RawModule {\n val in = IO(Flipped(new Bundle { val foo = Bool(); val bar = Bool() }))\n val out = IO(new Bundle { val foo = Bool(); val bar = Bool() })\n // foo and bar are connected, although Scala types aren't the same\n out.as[Data] :<>= in.as[Data]\n}\n"})})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(a,{...e})}):a(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>c,x:()=>s});var o=i(6540);const l={},t=o.createContext(l);function c(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(l):e.components||l:c(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d4b6d0e6.f68aedf5.js b/assets/js/d4b6d0e6.f68aedf5.js
deleted file mode 100644
index dc059f7444c..00000000000
--- a/assets/js/d4b6d0e6.f68aedf5.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[4166],{7240:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>t,metadata:()=>s,toc:()=>r});var o=i(4848),l=i(8453);const t={layout:"docs",title:"Connectable Operators",section:"chisel3"},c=void 0,s={id:"explanations/connectable",title:"Connectable Operators",description:"Table of Contents",source:"@site/docs/explanations/connectable.md",sourceDirName:"explanations",slug:"/explanations/connectable",permalink:"/docs/explanations/connectable",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/connectable.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Connectable Operators",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Combinational Circuits",permalink:"/docs/explanations/combinational-circuits"},next:{title:"Deep Dive into <> and := Connection Operators",permalink:"/docs/explanations/connection-operators"}},d={},r=[{value:"Table of Contents",id:"table-of-contents",level:2},{value:"Terminology",id:"terminology",level:2},{value:"Overview",id:"overview",level:2},{value:"Alignment: Flipped vs Aligned",id:"alignment-flipped-vs-aligned",level:2},{value:"Input/Output",id:"inputoutput",level:2},{value:"Connecting components with fully aligned members",id:"connecting-components-with-fully-aligned-members",level:2},{value:"Mono-direction connection operator (:=)",id:"mono-direction-connection-operator-",level:3},{value:"Connecting components with mixed alignment members",id:"connecting-components-with-mixed-alignment-members",level:2},{value:"Bi-direction connection operator (:<>=
)",id:"bi-direction-connection-operator-",level:3},{value:"Port-Direction Computation versus Connection-Direction Computation",id:"port-direction-computation-versus-connection-direction-computation",level:3},{value:"Aligned connection operator (:<=
)",id:"aligned-connection-operator-",level:3},{value:"Flipped connection operator (:>=
)",id:"flipped-connection-operator-",level:3},{value:"Coercing mono-direction connection operator (:#=
)",id:"coercing-mono-direction-connection-operator-",level:3},{value:"Connectable",id:"connectable",level:2},{value:"Connecting Records",id:"connecting-records",level:3},{value:"Defaults with waived connections",id:"defaults-with-waived-connections",level:3},{value:"Connecting types with optional members",id:"connecting-types-with-optional-members",level:3},{value:"Always ignore errors caused by extra members (partial connection operator)",id:"always-ignore-errors-caused-by-extra-members-partial-connection-operator",level:3},{value:"Connecting components with different widths",id:"connecting-components-with-different-widths",level:3},{value:"Excluding members from any operator on a Connectable",id:"excluding-members-from-any-operator-on-a-connectable",level:3},{value:"Techniques for connecting structurally inequivalent Chisel types",id:"techniques-for-connecting-structurally-inequivalent-chisel-types",level:2},{value:"Connecting different sub-types of the same super-type, with colliding names",id:"connecting-different-sub-types-of-the-same-super-type-with-colliding-names",level:3},{value:"Connecting sub-types to super-types by waiving extra members",id:"connecting-sub-types-to-super-types-by-waiving-extra-members",level:3},{value:"Connecting different sub-types",id:"connecting-different-sub-types",level:3},{value:"FAQ",id:"faq",level:2},{value:"How do I connect two items as flexibly as possible (try your best but never error)",id:"how-do-i-connect-two-items-as-flexibly-as-possible-try-your-best-but-never-error",level:3},{value:"How do I connect two items but don't care about the Scala types being equivalent?",id:"how-do-i-connect-two-items-but-dont-care-about-the-scala-types-being-equivalent",level:3}];function a(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h2,{id:"table-of-contents",children:"Table of Contents"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#terminology",children:"Terminology"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#overview",children:"Overview"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#alignment-flipped-vs-aligned",children:"Alignment: Flipped vs Aligned"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#inputoutput",children:"Input/Output"})}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.a,{href:"#connecting-components-with-fully-aligned-members",children:"Connecting components with fully aligned members"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#mono-direction-connection-operator-",children:["Mono-direction connection operator (",(0,o.jsx)(n.code,{children:":="}),")"]})}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.a,{href:"#connecting-components-with-mixed-alignment-members",children:"Connecting components with mixed alignment members"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#bi-direction-connection-operator-",children:["Bi-direction connection operator (",(0,o.jsx)(n.code,{children:":<>="}),")"]})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#port-direction-computation-versus-connection-direction-computation",children:"Port-Direction Computation versus Connection-Direction Computation"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#aligned-connection-operator-",children:["Aligned connection operator (",(0,o.jsx)(n.code,{children:":<="}),")"]})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#flipped-connection-operator-",children:["Flipped connection operator (",(0,o.jsx)(n.code,{children:":>="}),")"]})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsxs)(n.a,{href:"#coercing-mono-direction-connection-operator-",children:["Coercing mono-direction connection operator (",(0,o.jsx)(n.code,{children:":#="}),")"]})}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.a,{href:"#connectable",children:"Connectable"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-records",children:"Connecting Records"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#defaults-with-waived-connections",children:"Defaults with waived connections"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-types-with-optional-members",children:"Connecting types with optional members"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#always-ignore-errors-caused-by-extra-members-partial-connection-operator",children:"Always ignore extra members (partial connection operator)"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-components-with-different-widths",children:"Connecting components with different widths"})}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.a,{href:"#techniques-for-connecting-structurally-inequivalent-chisel-types",children:"Techniques for connecting structurally inequivalent Chisel types"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-different-sub-types-of-the-same-super-type-with-colliding-names",children:"Connecting different sub-types of the same super-type, with colliding names"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-sub-types-to-super-types-by-waiving-extra-members",children:"Connecting sub-types to super-types by waiving extra members"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#connecting-different-sub-types",children:"Connecting different sub-types"})}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#faq",children:"FAQ"})}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"terminology",children:"Terminology"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:['"Chisel type" - a ',(0,o.jsx)(n.code,{children:"Data"})," that is not bound to hardware, i.e. not a component. (more details ",(0,o.jsx)(n.a,{href:"chisel-type-vs-scala-type",children:"here"}),").","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"UInt(3.W)"}),", ",(0,o.jsx)(n.code,{children:"new Bundle {..}"}),", ",(0,o.jsx)(n.code,{children:"Vec(3, SInt(2.W))"})," are all Chisel types"]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:['"component" - a ',(0,o.jsx)(n.code,{children:"Data"})," that is bound to hardware (",(0,o.jsx)(n.code,{children:"IO"}),", ",(0,o.jsx)(n.code,{children:"Reg"}),", ",(0,o.jsx)(n.code,{children:"Wire"}),", etc.)","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"Wire(UInt(3.W))"})," is a component, whose Chisel type is ",(0,o.jsx)(n.code,{children:"UInt(3.W)"})]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"Aggregate"})," - a Chisel type or component that contains other Chisel types or components (i.e. ",(0,o.jsx)(n.code,{children:"Vec"}),", ",(0,o.jsx)(n.code,{children:"Record"}),", or ",(0,o.jsx)(n.code,{children:"Bundle"}),")"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"Element"})," - a Chisel type or component that does not contain other Chisel types or components (e.g. ",(0,o.jsx)(n.code,{children:"UInt"}),", ",(0,o.jsx)(n.code,{children:"SInt"}),", ",(0,o.jsx)(n.code,{children:"Clock"}),", ",(0,o.jsx)(n.code,{children:"Bool"})," etc.)"]}),"\n",(0,o.jsxs)(n.li,{children:['"member" - a Chisel type or component, or any of its children (could be an ',(0,o.jsx)(n.code,{children:"Aggregate"})," or an ",(0,o.jsx)(n.code,{children:"Element"}),")","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"Vec(3, UInt(2.W))(0)"})," is a member of the parent ",(0,o.jsx)(n.code,{children:"Vec"})," Chisel type"]}),"\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"Wire(Vec(3, UInt(2.W)))(0)"})," is a member of the parent ",(0,o.jsx)(n.code,{children:"Wire"})," component"]}),"\n",(0,o.jsxs)(n.li,{children:["E.g. ",(0,o.jsx)(n.code,{children:"IO(Decoupled(Bool)).ready"})," is a member of the parent ",(0,o.jsx)(n.code,{children:"IO"})," component"]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:['"relative alignment" - whether two members of the same component or Chisel type are aligned/flipped, relative to one another',"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["see section ",(0,o.jsx)(n.a,{href:"#alignment-flipped-vs-aligned",children:"below"})," for a detailed definition"]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:['"structural type check" - Chisel type ',(0,o.jsx)(n.code,{children:"A"})," is structurally equivalent to Chisel type ",(0,o.jsx)(n.code,{children:"B"})," if ",(0,o.jsx)(n.code,{children:"A"})," and ",(0,o.jsx)(n.code,{children:"B"})," have matching bundle field names and types (",(0,o.jsx)(n.code,{children:"Record"})," vs ",(0,o.jsx)(n.code,{children:"Vector"})," vs ",(0,o.jsx)(n.code,{children:"Element"}),"), probe modifiers (probe vs nonprobe), vector sizes, ",(0,o.jsx)(n.code,{children:"Element"})," types (UInt/SInt/Bool/Clock)","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"ignores relative alignment (flippedness)"}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:['"alignment type check" - a Chisel type ',(0,o.jsx)(n.code,{children:"A"})," matches alignment with another Chisel type ",(0,o.jsx)(n.code,{children:"B"})," if every member of ",(0,o.jsx)(n.code,{children:"A"}),"'s relative alignment to ",(0,o.jsx)(n.code,{children:"A"})," is the same as the structurally corresponding member of ",(0,o.jsx)(n.code,{children:"B"}),"'s relative alignment to ",(0,o.jsx)(n.code,{children:"B"}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"Connectable"})," operators are the standard way to connect Chisel hardware components to one another."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note: For descriptions of the semantics for the previous operators, see ",(0,o.jsx)(n.a,{href:"connection-operators",children:(0,o.jsx)(n.code,{children:"Connection Operators"})}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"All connection operators require the two hardware components (consumer and producer) to be structurally type equivalent."}),"\n",(0,o.jsxs)(n.p,{children:["The one exception to the structural type-equivalence rule is using the ",(0,o.jsx)(n.code,{children:"Connectable"})," mechanism, detailed at this ",(0,o.jsx)(n.a,{href:"#techniques-for-connecting-structurally-inequivalent-chisel-types",children:"section"})," towards the end of this document."]}),"\n",(0,o.jsxs)(n.p,{children:["Aggregate (",(0,o.jsx)(n.code,{children:"Record"}),", ",(0,o.jsx)(n.code,{children:"Vec"}),", ",(0,o.jsx)(n.code,{children:"Bundle"}),") Chisel types can include data members which are flipped relative to one another.\nDue to this, there are many desired connection behaviors between two Chisel components.\nThe following are the Chisel connection operators between a consumer ",(0,o.jsx)(n.code,{children:"c"})," and producer ",(0,o.jsx)(n.code,{children:"p"}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c := p"})," (mono-direction): connects all ",(0,o.jsx)(n.code,{children:"p"})," members to ",(0,o.jsx)(n.code,{children:"c"}),"; requires ",(0,o.jsx)(n.code,{children:"c"})," and ",(0,o.jsx)(n.code,{children:"p"})," to not have any flipped members"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c :#= p"})," (coercing mono-direction): connects all ",(0,o.jsx)(n.code,{children:"p"})," members to ",(0,o.jsx)(n.code,{children:"c"}),"; regardless of alignment"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c :<= p"})," (aligned-direction): connects all aligned (non-flipped) ",(0,o.jsx)(n.code,{children:"c"})," members from ",(0,o.jsx)(n.code,{children:"p"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c :>= p"})," (flipped-direction): connects all flipped ",(0,o.jsx)(n.code,{children:"p"})," members from ",(0,o.jsx)(n.code,{children:"c"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"c :<>= p"})," (bi-direction operator): connects all aligned ",(0,o.jsx)(n.code,{children:"c"})," members from ",(0,o.jsx)(n.code,{children:"p"}),"; all flipped ",(0,o.jsx)(n.code,{children:"p"})," members from ",(0,o.jsx)(n.code,{children:"c"})]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"These operators may appear to be a random collection of symbols; however, the characters are consistent between operators and self-describe the semantics of each operator:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:":"})," always indicates the consumer, or left-hand-side, of the operator."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"="})," always indicates the producer, or right-hand-side, of the operator.","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c := p"})," connects a consumer (",(0,o.jsx)(n.code,{children:"c"}),") and a producer (",(0,o.jsx)(n.code,{children:"p"}),")."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"<"})," always indicates that some members will be driven producer-to-consumer, or right-to-left.","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c :<= p"})," drives members in producer (",(0,o.jsx)(n.code,{children:"p"}),") to members in consumer (",(0,o.jsx)(n.code,{children:"c"}),")."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:">"})," always indicates that some signals will be driven consumer-to-producer, or left-to-right.","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c :>= p"})," drives members in consumer (",(0,o.jsx)(n.code,{children:"c"}),") to members producer (",(0,o.jsx)(n.code,{children:"p"}),")."]}),"\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c :<>= p"})," both drives members from ",(0,o.jsx)(n.code,{children:"p"})," to ",(0,o.jsx)(n.code,{children:"c"})," and from ",(0,o.jsx)(n.code,{children:"c"})," to ",(0,o.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"#"})," always indicates to ignore member alignment and to drive producer-to-consumer, or right-to-left.","\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Hence, ",(0,o.jsx)(n.code,{children:"c :#= p"})," always drives members from ",(0,o.jsx)(n.code,{children:"p"})," to ",(0,o.jsx)(n.code,{children:"c"})," ignoring direction."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note: in addition, an operator that ends in ",(0,o.jsx)(n.code,{children:"="})," has assignment-precedence, which means that ",(0,o.jsx)(n.code,{children:"x :<>= y + z"})," will translate to ",(0,o.jsx)(n.code,{children:"x :<>= (y + z)"}),", rather than ",(0,o.jsx)(n.code,{children:"(x :<>= y) + z"}),".\nThis was not true of the ",(0,o.jsx)(n.code,{children:"<>"})," operator and was a minor painpoint for users."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"alignment-flipped-vs-aligned",children:"Alignment: Flipped vs Aligned"}),"\n",(0,o.jsxs)(n.p,{children:["A member's alignment is a relative property: a member is aligned/flipped relative to another member of the same component or Chisel type.\nHence, one must always say whether a member is flipped/aligned ",(0,o.jsx)(n.em,{children:"with respect to (w.r.t)"})," another member of that type (parent, sibling, child etc.)."]}),"\n",(0,o.jsxs)(n.p,{children:["We use the following example of a non-nested bundle ",(0,o.jsx)(n.code,{children:"Parent"})," to let us state all of the alignment relationships between members of ",(0,o.jsx)(n.code,{children:"p"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass Parent extends Bundle {\n val alignedChild = UInt(32.W)\n val flippedChild = Flipped(UInt(32.W))\n}\nclass MyModule0 extends Module {\n val p = Wire(new Parent)\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"First, every member is always aligned with themselves:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.alignedChild"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.flippedChild"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedChild"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Next, we list all parent/child relationships.\nBecause the ",(0,o.jsx)(n.code,{children:"flippedChild"})," field is ",(0,o.jsx)(n.code,{children:"Flipped"}),", it changes its alignment relative to its parent."]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedChild"})]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Finally, we can list all sibling relationships:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.alignedChild"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedChild"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["The next example has a nested bundle ",(0,o.jsx)(n.code,{children:"GrandParent"})," who instantiates an aligned ",(0,o.jsx)(n.code,{children:"Parent"})," field and flipped ",(0,o.jsx)(n.code,{children:"Parent"})," field."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass GrandParent extends Bundle {\n val alignedParent = new Parent\n val flippedParent = Flipped(new Parent)\n}\nclass MyModule1 extends Module {\n val g = Wire(new GrandParent)\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Consider the following alignments between grandparent and grandchildren.\nAn odd number of flips indicate a flipped relationship; even numbers of flips indicate an aligned relationship."}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"g.flippedParent.flippedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"g.alignedParent.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"g.flippedParent.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"g.alignedParent.flippedChild"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Consider the following alignment relationships starting from ",(0,o.jsx)(n.code,{children:"g.alignedParent"})," and ",(0,o.jsx)(n.code,{children:"g.flippedParent"}),".\n",(0,o.jsxs)(n.em,{children:["Note that whether ",(0,o.jsx)(n.code,{children:"g.alignedParent"})," is aligned/flipped relative to ",(0,o.jsx)(n.code,{children:"g"})," has no effect on the aligned/flipped relationship between ",(0,o.jsx)(n.code,{children:"g.alignedParent"})," and ",(0,o.jsx)(n.code,{children:"g.alignedParent.alignedChild"})," because alignment is only relative to the two members in question!"]}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.alignedParent"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.alignedParent.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.flippedParent"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.flippedParent.alignedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.alignedParent"})," is flipped w.r.t. ",(0,o.jsx)(n.code,{children:"g.alignedParent.flippedChild"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.flippedParent"})," is flipped w.r.t. ",(0,o.jsx)(n.code,{children:"g.flippedParent.flippedChild"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["In summary, a member is aligned or flipped w.r.t. another member of the hardware component.\nThis means that the type of the consumer/producer is the only information needed to determine the behavior of any operator.\n",(0,o.jsx)(n.em,{children:"Whether the consumer/producer is a member of a larger bundle is irrelevant; you ONLY need to know the type of the consumer/producer"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"inputoutput",children:"Input/Output"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"Input(gen)"}),"/",(0,o.jsx)(n.code,{children:"Output(gen)"})," are coercing operators.\nThey perform two functions: (1) create a new Chisel type that has all flips removed from all recursive children members (still structurally equivalent to ",(0,o.jsx)(n.code,{children:"gen"})," but no longer alignment type equivalent), and (2) apply ",(0,o.jsx)(n.code,{children:"Flipped"})," if ",(0,o.jsx)(n.code,{children:"Input"}),", keep aligned (do nothing) if ",(0,o.jsx)(n.code,{children:"Output"}),".\nE.g. if we imagine a function called ",(0,o.jsx)(n.code,{children:"cloneChiselTypeButStripAllFlips"}),", then ",(0,o.jsx)(n.code,{children:"Input(gen)"})," is structurally and alignment type equivalent to ",(0,o.jsx)(n.code,{children:"Flipped(cloneChiselTypeButStripAllFlips(gen))"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Note that if ",(0,o.jsx)(n.code,{children:"gen"})," is a non-aggregate, then ",(0,o.jsx)(n.code,{children:"Input(nonAggregateGen)"})," is equivalent to ",(0,o.jsx)(n.code,{children:"Flipped(nonAggregateGen)"}),"."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Future work will refactor how these primitives are exposed to the user to make Chisel's type system more intuitive.\nSee [",(0,o.jsx)(n.a,{href:"https://github.com/chipsalliance/chisel3/issues/2643",children:"https://github.com/chipsalliance/chisel3/issues/2643"}),"]."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"With this in mind, we can consider the following examples and detail relative alignments of members."}),"\n",(0,o.jsxs)(n.p,{children:["First, we can use a similar example to ",(0,o.jsx)(n.code,{children:"Parent"})," but use ",(0,o.jsx)(n.code,{children:"Input/Output"})," instead of ",(0,o.jsx)(n.code,{children:"Flipped"}),".\nBecause ",(0,o.jsx)(n.code,{children:"alignedChild"})," and ",(0,o.jsx)(n.code,{children:"flippedChild"})," are non-aggregates, ",(0,o.jsx)(n.code,{children:"Input"})," is basically just a ",(0,o.jsx)(n.code,{children:"Flipped"})," and thus the alignments are unchanged compared to the previous ",(0,o.jsx)(n.code,{children:"Parent"})," example."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass ParentWithOutputInput extends Bundle {\n val alignedCoerced = Output(UInt(32.W)) // Equivalent to just UInt(32.W)\n val flippedCoerced = Input(UInt(32.W)) // Equivalent to Flipped(UInt(32.W))\n}\nclass MyModule2 extends Module {\n val p = Wire(new ParentWithOutputInput)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["The alignments are the same as the previous ",(0,o.jsx)(n.code,{children:"Parent"})," example:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.alignedCoerced"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.flippedCoerced"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"p.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"p.alignedCoerced"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"p.flippedCoerced"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["The next example has a nested bundle ",(0,o.jsx)(n.code,{children:"GrandParent"})," who instantiates an ",(0,o.jsx)(n.code,{children:"Output"})," ",(0,o.jsx)(n.code,{children:"ParentWithOutputInput"})," field and an ",(0,o.jsx)(n.code,{children:"Input"})," ",(0,o.jsx)(n.code,{children:"ParentWithOutputInput"})," field."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass GrandParentWithOutputInput extends Bundle {\n val alignedCoerced = Output(new ParentWithOutputInput)\n val flippedCoerced = Input(new ParentWithOutputInput)\n}\nclass MyModule3 extends Module {\n val g = Wire(new GrandParentWithOutputInput)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["Remember that ",(0,o.jsx)(n.code,{children:"Output(gen)/Input(gen)"})," recursively strips the ",(0,o.jsx)(n.code,{children:"Flipped"})," of any recursive children.\nThis makes every member of ",(0,o.jsx)(n.code,{children:"gen"})," aligned with every other member of ",(0,o.jsx)(n.code,{children:"gen"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Consider the following alignments between grandparent and grandchildren.\nBecause ",(0,o.jsx)(n.code,{children:"alignedCoerced"})," and ",(0,o.jsx)(n.code,{children:"flippedCoerced"})," are aligned with all their recursive members, they are fully aligned.\nThus, only their alignment to ",(0,o.jsx)(n.code,{children:"g"})," influences grandchildren alignment:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is aligned w.r.t ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.flippedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"g.flippedCoerced.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g"})," is flipped w.r.t ",(0,o.jsx)(n.code,{children:"g.flippedCoerced.flippedCoerced"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Consider the following alignment relationships starting from ",(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," and ",(0,o.jsx)(n.code,{children:"g.flippedCoerced"}),".\n",(0,o.jsxs)(n.em,{children:["Note that whether ",(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," is aligned/flipped relative to ",(0,o.jsx)(n.code,{children:"g"})," has no effect on the aligned/flipped relationship between ",(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," and ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.alignedCoerced"})," or ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.flippedCoerced"})," because alignment is only relative to the two members in question! However, because alignment is coerced, everything is aligned between ",(0,o.jsx)(n.code,{children:"g.alignedCoerced"}),"/",(0,o.jsx)(n.code,{children:"g.flippedAligned"})," and their children"]}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.alignedCoerced"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.alignedCoerced.flippedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.flippedCoerced"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.flippedCoerced.alignedCoerced"})]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"g.flippedCoerced"})," is aligned w.r.t. ",(0,o.jsx)(n.code,{children:"g.flippedCoerced.flippedCoerced"})]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["In summary, ",(0,o.jsx)(n.code,{children:"Input(gen)"})," and ",(0,o.jsx)(n.code,{children:"Output(gen)"})," recursively coerce children alignment, as well as dictate ",(0,o.jsx)(n.code,{children:"gen"}),"'s alignment to its parent bundle (if it exists)."]}),"\n",(0,o.jsx)(n.h2,{id:"connecting-components-with-fully-aligned-members",children:"Connecting components with fully aligned members"}),"\n",(0,o.jsx)(n.h3,{id:"mono-direction-connection-operator-",children:"Mono-direction connection operator (:=)"}),"\n",(0,o.jsxs)(n.p,{children:["For simple connections where all members are aligned (non-flipped) w.r.t. one another, use ",(0,o.jsx)(n.code,{children:":="}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass FullyAlignedBundle extends Bundle {\n val a = Bool()\n val b = Bool()\n}\nclass Example0 extends RawModule {\n val incoming = IO(Flipped(new FullyAlignedBundle))\n val outgoing = IO(new FullyAlignedBundle)\n outgoing := incoming\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where each member of ",(0,o.jsx)(n.code,{children:"incoming"})," drives every member of ",(0,o.jsx)(n.code,{children:"outgoing"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example0(\n input incoming_a,\n incoming_b,\n output outgoing_a,\n outgoing_b\n);\n\n assign outgoing_a = incoming_a;\n assign outgoing_b = incoming_b;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["You may be thinking \"Wait, I'm confused! Isn't ",(0,o.jsx)(n.code,{children:"incoming"})," flipped and ",(0,o.jsx)(n.code,{children:"outgoing"}),' aligned?" -- Noo! Whether ',(0,o.jsx)(n.code,{children:"incoming"})," is aligned with ",(0,o.jsx)(n.code,{children:"outgoing"})," makes no sense; remember, you only evaluate alignment between members of the same component or Chisel type.\nBecause components are always aligned to themselves, ",(0,o.jsx)(n.code,{children:"outgoing"})," is aligned to ",(0,o.jsx)(n.code,{children:"outgoing"}),", and ",(0,o.jsx)(n.code,{children:"incoming"})," is aligned to ",(0,o.jsx)(n.code,{children:"incoming"}),", there is no problem.\nTheir relative flippedness to anything else is irrelevant."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"connecting-components-with-mixed-alignment-members",children:"Connecting components with mixed alignment members"}),"\n",(0,o.jsxs)(n.p,{children:["Aggregate Chisel types can include data members which are flipped relative to one another; in the example below, ",(0,o.jsx)(n.code,{children:"alignedChild"})," and ",(0,o.jsx)(n.code,{children:"flippedChild"})," are aligned/flipped relative to ",(0,o.jsx)(n.code,{children:"MixedAlignmentBundle"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nclass MixedAlignmentBundle extends Bundle {\n val alignedChild = Bool()\n val flippedChild = Flipped(Bool())\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["Due to this, there are many desired connection behaviors between two Chisel components.\nFirst we will introduce the most common Chisel connection operator, ",(0,o.jsx)(n.code,{children:":<>="}),", useful for connecting components with members of mixed-alignments, then take a moment to investigate a common source of confusion between port-direction and connection-direction.\nThen, we will explore the remainder of the Chisel connection operators."]}),"\n",(0,o.jsxs)(n.h3,{id:"bi-direction-connection-operator-",children:["Bi-direction connection operator (",(0,o.jsx)(n.code,{children:":<>="}),")"]}),"\n",(0,o.jsxs)(n.p,{children:["For connections where you want 'bulk-connect-like-semantics' where the aligned members are driven producer-to-consumer and flipped members are driven consumer-to-producer, use ",(0,o.jsx)(n.code,{children:":<>="}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Example1 extends RawModule {\n val incoming = IO(Flipped(new MixedAlignmentBundle))\n val outgoing = IO(new MixedAlignmentBundle)\n outgoing :<>= incoming\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where the aligned members are driven ",(0,o.jsx)(n.code,{children:"incoming"})," to ",(0,o.jsx)(n.code,{children:"outgoing"})," and flipped members are driven ",(0,o.jsx)(n.code,{children:"outgoing"})," to ",(0,o.jsx)(n.code,{children:"incoming"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example1(\n input incoming_alignedChild,\n output incoming_flippedChild,\n outgoing_alignedChild,\n input outgoing_flippedChild\n);\n\n assign incoming_flippedChild = outgoing_flippedChild;\n assign outgoing_alignedChild = incoming_alignedChild;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"port-direction-computation-versus-connection-direction-computation",children:"Port-Direction Computation versus Connection-Direction Computation"}),"\n",(0,o.jsxs)(n.p,{children:["A common question is if you use a mixed-alignment connection (such as ",(0,o.jsx)(n.code,{children:":<>="}),") to connect submembers of parent components, does the alignment of the submember to their parent affect anything? The answer is no, because ",(0,o.jsx)(n.em,{children:"alignment is always computed relative to what is being connected to, and members are always aligned with themselves."})]}),"\n",(0,o.jsxs)(n.p,{children:["In the following example connecting from ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," to ",(0,o.jsx)(n.code,{children:"outgoing.alignedChild"}),", whether ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," is aligned with ",(0,o.jsx)(n.code,{children:"incoming"})," is irrelevant because the ",(0,o.jsx)(n.code,{children:":<>="})," only computes alignment relative to the thing being connected to, and ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," is aligned with ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Example1a extends RawModule {\n val incoming = IO(Flipped(new MixedAlignmentBundle))\n val outgoing = IO(new MixedAlignmentBundle)\n outgoing.alignedChild :<>= incoming.alignedChild // whether incoming.alignedChild is aligned/flipped to incoming is IRRELEVANT to what gets connected with :<>=\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["While ",(0,o.jsx)(n.code,{children:"incoming.flippedChild"}),"'s alignment with ",(0,o.jsx)(n.code,{children:"incoming"})," does not affect our operators, it does influence whether ",(0,o.jsx)(n.code,{children:"incoming.flippedChild"})," is an output or input port of my module.\nA common source of confusion is to mistake the process for determining whether ",(0,o.jsx)(n.code,{children:"incoming.flippedChild"})," will resolve to a Verilog ",(0,o.jsx)(n.code,{children:"output"}),"/",(0,o.jsx)(n.code,{children:"input"})," (the port-direction computation) with the process for determining how ",(0,o.jsx)(n.code,{children:":<>="})," drives what with what (the connection-direction computation).\nWhile both processes consider relative alignment, they are distinct."]}),"\n",(0,o.jsxs)(n.p,{children:["The port-direction computation always computes alignment relative to the component marked with ",(0,o.jsx)(n.code,{children:"IO"}),".\nAn ",(0,o.jsx)(n.code,{children:"IO(Flipped(gen))"})," is an incoming port, and any member of ",(0,o.jsx)(n.code,{children:"gen"})," that is aligned/flipped with ",(0,o.jsx)(n.code,{children:"gen"})," is an incoming/outgoing port.\nAn ",(0,o.jsx)(n.code,{children:"IO(gen)"})," is an outgoing port, and any member of ",(0,o.jsx)(n.code,{children:"gen"})," that is aligned/flipped with ",(0,o.jsx)(n.code,{children:"gen"})," is an outgoing/incoming port."]}),"\n",(0,o.jsxs)(n.p,{children:["The connection-direction computation always computes alignment based on the explicit consumer/producer referenced for the connection.\nIf one connects ",(0,o.jsx)(n.code,{children:"incoming :<>= outgoing"}),", alignments are computed based on ",(0,o.jsx)(n.code,{children:"incoming"})," and ",(0,o.jsx)(n.code,{children:"outgoing"}),".\nIf one connects ",(0,o.jsx)(n.code,{children:"incoming.alignedChild :<>= outgoing.alignedChild"}),", then alignments are computed based on ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," and ",(0,o.jsx)(n.code,{children:"outgoing.alignedChild"})," (and the alignment of ",(0,o.jsx)(n.code,{children:"incoming"})," to ",(0,o.jsx)(n.code,{children:"incoming.alignedChild"})," is irrelevant)."]}),"\n",(0,o.jsxs)(n.p,{children:["This means that users can try to connect to input ports of their module! If I write ",(0,o.jsx)(n.code,{children:"x :<>= y"}),", and ",(0,o.jsx)(n.code,{children:"x"})," is an input to the current module, then that is what the connection is trying to do.\nHowever, because input ports are not drivable from within the current module, Chisel will throw an error.\nThis is the same error a user would get using a mono-directioned operator: ",(0,o.jsx)(n.code,{children:"x := y"})," will throw the same error if ",(0,o.jsx)(n.code,{children:"x"})," is an input to the current module.\n",(0,o.jsx)(n.em,{children:"Whether a component is drivable is irrelevant to the semantics of any connection operator attempting to drive to it."})]}),"\n",(0,o.jsxs)(n.p,{children:["In summary, the port-direction computation is relative to the root marked ",(0,o.jsx)(n.code,{children:"IO"}),", but connection-direction computation is relative to the consumer/producer that the connection is doing.\nThis has the positive property that connection semantics are solely based on the Chisel structural type and its relative alignments of the consumer/producer (nothing more, nothing less)."]}),"\n",(0,o.jsxs)(n.h3,{id:"aligned-connection-operator-",children:["Aligned connection operator (",(0,o.jsx)(n.code,{children:":<="}),")"]}),"\n",(0,o.jsxs)(n.p,{children:["For connections where you want the aligned-half of 'bulk-connect-like-semantics' where the aligned members are driven producer-to-consumer and flipped members are ignored, use ",(0,o.jsx)(n.code,{children:":<="}),' (the "aligned connection").']}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Example2 extends RawModule {\n val incoming = IO(Flipped(new MixedAlignmentBundle))\n val outgoing = IO(new MixedAlignmentBundle)\n incoming.flippedChild := DontCare // Otherwise FIRRTL throws an uninitialization error\n outgoing :<= incoming\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where the aligned members are driven ",(0,o.jsx)(n.code,{children:"incoming"})," to ",(0,o.jsx)(n.code,{children:"outgoing"})," and flipped members are ignored:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example2(\n input incoming_alignedChild,\n output incoming_flippedChild,\n outgoing_alignedChild,\n input outgoing_flippedChild\n);\n\n assign incoming_flippedChild = 1'h0;\n assign outgoing_alignedChild = incoming_alignedChild;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.h3,{id:"flipped-connection-operator-",children:["Flipped connection operator (",(0,o.jsx)(n.code,{children:":>="}),")"]}),"\n",(0,o.jsxs)(n.p,{children:["For connections where you want the flipped-half of 'bulk-connect-like-semantics' where the aligned members are ignored and flipped members are connected consumer-to-producer, use ",(0,o.jsx)(n.code,{children:":>="}),' (the "flipped connection", or "backpressure connection").']}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class Example3 extends RawModule {\n val incoming = IO(Flipped(new MixedAlignmentBundle))\n val outgoing = IO(new MixedAlignmentBundle)\n outgoing.alignedChild := DontCare // Otherwise FIRRTL throws an uninitialization error\n outgoing :>= incoming\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where the aligned members are ignored and the flipped members are driven ",(0,o.jsx)(n.code,{children:"outgoing"})," to ",(0,o.jsx)(n.code,{children:"incoming"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example3(\n input incoming_alignedChild,\n output incoming_flippedChild,\n outgoing_alignedChild,\n input outgoing_flippedChild\n);\n\n assign incoming_flippedChild = outgoing_flippedChild;\n assign outgoing_alignedChild = 1'h0;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note: Astute observers will realize that ",(0,o.jsx)(n.code,{children:"c :<>= p"})," is semantically equivalent to ",(0,o.jsx)(n.code,{children:"c :<= p"})," followed by ",(0,o.jsx)(n.code,{children:"c :>= p"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.h3,{id:"coercing-mono-direction-connection-operator-",children:["Coercing mono-direction connection operator (",(0,o.jsx)(n.code,{children:":#="}),")"]}),"\n",(0,o.jsxs)(n.p,{children:["For connections where you want to every producer member to always drive every consumer member, regardless of alignment, use ",(0,o.jsx)(n.code,{children:":#="}),' (the "coercion connection").\nThis operator is useful for initializing wires whose types contain members of mixed alignment.']}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.BundleLiterals._\nclass Example4 extends RawModule {\n val w = Wire(new MixedAlignmentBundle)\n dontTouch(w) // So we see it in the output Verilog\n w :#= (new MixedAlignmentBundle).Lit(_.alignedChild -> true.B, _.flippedChild -> true.B)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where all members are driven from the literal to ",(0,o.jsx)(n.code,{children:"w"}),", regardless of alignment:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example4();\n wire w_alignedChild = 1'h1;\n wire w_flippedChild = 1'h1;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note: Astute observers will realize that ",(0,o.jsx)(n.code,{children:"c :#= p"})," is semantically equivalent to ",(0,o.jsx)(n.code,{children:"c :<= p"})," followed by ",(0,o.jsx)(n.code,{children:"p :>= c"})," (note ",(0,o.jsx)(n.code,{children:"p"})," and ",(0,o.jsx)(n.code,{children:"c"})," switched places in the second connection)."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Another use case for ",(0,o.jsx)(n.code,{children:":#="})," is for connecting a mixed-directional bundle to a fully-aligned monitor."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import chisel3.experimental.BundleLiterals._\nclass Example4b extends RawModule {\n val monitor = IO(Output(new MixedAlignmentBundle))\n val w = Wire(new MixedAlignmentBundle)\n dontTouch(w) // So we see it in the output Verilog\n w :#= DontCare\n monitor :#= w\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where all members are driven from the literal to ",(0,o.jsx)(n.code,{children:"w"}),", regardless of alignment:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example4b(\n output monitor_alignedChild,\n monitor_flippedChild\n);\n\n wire w_alignedChild = 1'h0;\n wire w_flippedChild = 1'h0;\n assign monitor_alignedChild = w_alignedChild;\n assign monitor_flippedChild = w_flippedChild;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h2,{id:"connectable",children:"Connectable"}),"\n",(0,o.jsxs)(n.p,{children:["Sometimes a user wants to connect Chisel components which are not type equivalent.\nFor example, a user may want to hook up anonymous ",(0,o.jsx)(n.code,{children:"Record"})," components who may have an intersection of their fields being equivalent, but cannot because they are not structurally equivalent.\nAlternatively, one may want to connect two types that have different widths."]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"Connectable"})," is the mechanism to specialize connection operator behavior in these scenarios.\nFor additional members which are not present in the other component being connected to, or for mismatched widths, or for always excluding a member from being connected to, they can be explicitly called out from the ",(0,o.jsx)(n.code,{children:"Connectable"})," object, rather than trigger an error."]}),"\n",(0,o.jsxs)(n.p,{children:["In addition, there are other techniques that can be used to address similar use cases including ",(0,o.jsx)(n.code,{children:".viewAsSuperType"}),", a static cast to a supertype (e.g. ",(0,o.jsx)(n.code,{children:"(x: T)"}),"), or creating a custom ",(0,o.jsx)(n.code,{children:"DataView"}),".\nFor a discussion about when to use each technique, please continue ",(0,o.jsx)(n.a,{href:"#techniques-for-connecting-structurally-inequivalent-chisel-types",children:"here"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["This section demonstrates how ",(0,o.jsx)(n.code,{children:"Connectable"})," specifically can be used in a multitude of scenarios."]}),"\n",(0,o.jsx)(n.h3,{id:"connecting-records",children:"Connecting Records"}),"\n",(0,o.jsxs)(n.p,{children:["One use case is to try to connect two ",(0,o.jsx)(n.code,{children:"Record"}),"s; for matching members, they should be connected, but for unmatched members, the errors caused due to them being unmatched should be ignored.\nTo accomplish this, use the other operators to initialize all ",(0,o.jsx)(n.code,{children:"Record"})," members, then use ",(0,o.jsx)(n.code,{children:":<>="})," with ",(0,o.jsx)(n.code,{children:".waive"})," to connect only the matching members."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note that none of ",(0,o.jsx)(n.code,{children:".viewAsSuperType"}),", static casts, nor a custom ",(0,o.jsx)(n.code,{children:"DataView"})," helps this case because the Scala types are still ",(0,o.jsx)(n.code,{children:"Record"}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:'import scala.collection.immutable.SeqMap\n\nclass Example9 extends RawModule {\n val abType = new Record { val elements = SeqMap("a" -> Bool(), "b" -> Flipped(Bool())) }\n val bcType = new Record { val elements = SeqMap("b" -> Flipped(Bool()), "c" -> Bool()) }\n\n val p = IO(Flipped(abType))\n val c = IO(bcType)\n\n DontCare :>= p\n c :<= DontCare\n\n c.waive(_.elements("c")):<>= p.waive(_.elements("a"))\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"p.b"})," is driven from ",(0,o.jsx)(n.code,{children:"c.b"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example9(\n output p_b,\n input p_a,\n output c_c,\n input c_b\n);\n\n assign p_b = c_b;\n assign c_c = 1'h0;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"defaults-with-waived-connections",children:"Defaults with waived connections"}),"\n",(0,o.jsxs)(n.p,{children:["Another use case is to try to connect two ",(0,o.jsx)(n.code,{children:"Record"}),"s; for matching members, they should be connected, but for unmatched members, ",(0,o.jsx)(n.em,{children:"they should be connected to a default value"}),".\nTo accomplish this, use the other operators to initialize all ",(0,o.jsx)(n.code,{children:"Record"})," members, then use ",(0,o.jsx)(n.code,{children:":<>="})," with ",(0,o.jsx)(n.code,{children:".waive"})," to connect only the matching members."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:'import scala.collection.immutable.SeqMap\n\nclass Example10 extends RawModule {\n val abType = new Record { val elements = SeqMap("a" -> Bool(), "b" -> Flipped(Bool())) }\n val bcType = new Record { val elements = SeqMap("b" -> Flipped(Bool()), "c" -> Bool()) }\n\n val p = Wire(abType)\n val c = Wire(bcType)\n\n dontTouch(p) // So it doesn\'t get constant-propped away for the example\n dontTouch(c) // So it doesn\'t get constant-propped away for the example\n\n p :#= abType.Lit(_.elements("a") -> true.B, _.elements("b") -> true.B)\n c :#= bcType.Lit(_.elements("b") -> true.B, _.elements("c") -> true.B)\n\n c.waive(_.elements("c")) :<>= p.waive(_.elements("a"))\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"p.b"})," is driven from ",(0,o.jsx)(n.code,{children:"c.b"}),", and ",(0,o.jsx)(n.code,{children:"p.a"}),", ",(0,o.jsx)(n.code,{children:"c.b"}),", and ",(0,o.jsx)(n.code,{children:"c.c"})," are initialized to default values:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example10();\n wire p_a = 1'h1;\n wire c_c = 1'h1;\n wire c_b = 1'h1;\n wire p_b = c_b;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"connecting-types-with-optional-members",children:"Connecting types with optional members"}),"\n",(0,o.jsxs)(n.p,{children:["In the following example, we can use ",(0,o.jsx)(n.code,{children:":<>="})," and ",(0,o.jsx)(n.code,{children:".waive"})," to connect two ",(0,o.jsx)(n.code,{children:"MyDecoupledOpts"}),"'s, where only one has a ",(0,o.jsx)(n.code,{children:"bits"})," member."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class MyDecoupledOpt(hasBits: Boolean) extends Bundle {\n val valid = Bool()\n val ready = Flipped(Bool())\n val bits = if (hasBits) Some(UInt(32.W)) else None\n}\nclass Example6 extends RawModule {\n val in = IO(Flipped(new MyDecoupledOpt(true)))\n val out = IO(new MyDecoupledOpt(false))\n out :<>= in.waive(_.bits.get) // We can know to call .get because we can inspect in.bits.isEmpty\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"ready"})," and ",(0,o.jsx)(n.code,{children:"valid"})," are connected, and ",(0,o.jsx)(n.code,{children:"bits"})," is ignored:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example6(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"always-ignore-errors-caused-by-extra-members-partial-connection-operator",children:"Always ignore errors caused by extra members (partial connection operator)"}),"\n",(0,o.jsx)(n.p,{children:"The most unsafe connection is to connect only members that are present in both consumer and producer, and ignore all other members.\nThis is unsafe because this connection will never error on any Chisel types."}),"\n",(0,o.jsxs)(n.p,{children:["To do this, you can use ",(0,o.jsx)(n.code,{children:".waiveAll"})," and static cast to ",(0,o.jsx)(n.code,{children:"Data"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class OnlyA extends Bundle {\n val a = UInt(32.W)\n}\nclass OnlyB extends Bundle {\n val b = UInt(32.W)\n}\nclass Example11 extends RawModule {\n val in = IO(Flipped(new OnlyA))\n val out = IO(new OnlyB)\n\n out := DontCare\n\n (out: Data).waiveAll :<>= (in: Data).waiveAll\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"This generates the following Verilog, where nothing is connected:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example11(\n input [31:0] in_a,\n output [31:0] out_b\n);\n\n assign out_b = 32'h0;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"connecting-components-with-different-widths",children:"Connecting components with different widths"}),"\n",(0,o.jsxs)(n.p,{children:["Non-",(0,o.jsx)(n.code,{children:"Connectable"})," operators implicitly truncate if a component with a larger width is connected to a component with a smaller width.\n",(0,o.jsx)(n.code,{children:"Connectable"})," operators disallow this implicit truncation behavior and require the driven component to be equal or larger in width that the sourcing component."]}),"\n",(0,o.jsxs)(n.p,{children:["If implicit truncation behavior is desired, then ",(0,o.jsx)(n.code,{children:"Connectable"})," provides a ",(0,o.jsx)(n.code,{children:"squeeze"})," mechanism which will allow the connection to continue with implicit truncation."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import scala.collection.immutable.SeqMap\n\nclass Example14 extends RawModule {\n val p = IO(Flipped(UInt(4.W)))\n val c = IO(UInt(3.W))\n\n c :<>= p.squeeze\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"p"})," is truncated prior to driving ",(0,o.jsx)(n.code,{children:"c"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example14(\n input [3:0] p,\n output [2:0] c\n);\n\n assign c = p[2:0];\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"excluding-members-from-any-operator-on-a-connectable",children:"Excluding members from any operator on a Connectable"}),"\n",(0,o.jsxs)(n.p,{children:["If a user wants to always exclude a field from a connect, use the ",(0,o.jsx)(n.code,{children:".exclude"})," mechanism which will never connect the field (as if it didn't exist to the connection)."]}),"\n",(0,o.jsxs)(n.p,{children:["Note that if a field matches in both producer and consumer, but only one is excluded, the other non-excluded field will still trigger an error; to fix this, use either ",(0,o.jsx)(n.code,{children:".waive"})," or ",(0,o.jsx)(n.code,{children:".exclude"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import scala.collection.immutable.SeqMap\n\nclass BundleWithSpecialField extends Bundle {\n val foo = UInt(3.W)\n val special = Bool()\n}\nclass Example15 extends RawModule {\n val p = IO(Flipped(new BundleWithSpecialField()))\n val c = IO(new BundleWithSpecialField())\n\n c.special := true.B // must initialize it\n\n c.exclude(_.special) :<>= p.exclude(_.special)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where the ",(0,o.jsx)(n.code,{children:"special"})," field is not connected:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example15(\n input [2:0] p_foo,\n input p_special,\n output [2:0] c_foo,\n output c_special\n);\n\n assign c_foo = p_foo;\n assign c_special = 1'h1;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h2,{id:"techniques-for-connecting-structurally-inequivalent-chisel-types",children:"Techniques for connecting structurally inequivalent Chisel types"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"DataView"})," and ",(0,o.jsx)(n.code,{children:".viewAsSupertype"})," create a view of the component that has a different Chisel type.\nThis means that a user can first create a ",(0,o.jsx)(n.code,{children:"DataView"})," of the consumer or producer (or both) so that the Chisel types are structurally equivalent.\nThis is useful when the difference between the consumer and producer aren't super nested, and also if they have rich Scala types which encode their structure.\nIn general, ",(0,o.jsx)(n.code,{children:"DataView"})," is the preferred mechanism to use (if you can) because it maintains the most amount of Chisel information in the Scala type, but there are many instances where it doesn't work and thus one must fall back on ",(0,o.jsx)(n.code,{children:"Connectable"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"Connectable"})," does not change the Chisel type, but instead changes the semantics of the operator to not error on the waived members if they are dangling or unconnected.\nThis is useful for when differences between the consumer and producer do not show up in the Scala type system (e.g. present/missing fields of type ",(0,o.jsx)(n.code,{children:"Option[Data]"}),", or anonymous ",(0,o.jsx)(n.code,{children:"Record"}),"s) or are deeply nested in a bundle that is especially onerous to create a ",(0,o.jsx)(n.code,{children:"DataView"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Static casts (e.g. ",(0,o.jsx)(n.code,{children:"(x: T)"}),") allows connecting components that have different Scala types, but leaves the Chisel type unchanged.\nUse this to force a connection to occur, even if the Scala types are different."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsx)(n.p,{children:'One may wonder why the operators require identical Scala types in the first place, if they can easily be bypassed.\nThe reason is to encourage users to use the Scala type system to encode Chisel information as it can make their code more robust; however, we don\'t want to be draconian about it because there are times when we want to enable the user to "just connect the darn thing".'}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"When all else fails one can always manually expand the connection to do what they want to happen, member by member.\nThe down-side to this approach is its verbosity and that adding new members to a component will require updating the manual connections."}),"\n",(0,o.jsxs)(n.p,{children:["Things to remember about ",(0,o.jsx)(n.code,{children:"Connectable"})," vs ",(0,o.jsx)(n.code,{children:".viewAsSupertype"}),"/",(0,o.jsx)(n.code,{children:"DataView"})," vs static cast (e.g. ",(0,o.jsx)(n.code,{children:"(x: T)"}),"):"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"DataView"})," and ",(0,o.jsx)(n.code,{children:".viewAsSupertype"})," will preemptively remove members that are not present in the new view which has a different Chisel type, thus ",(0,o.jsx)(n.code,{children:"DataView"})," ",(0,o.jsx)(n.em,{children:"does"})," affect what is connected"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"Connectable"})," can be used to waive the error on members who end up being dangling or unconnected.\nImportantly, ",(0,o.jsx)(n.code,{children:"Connectable"})," waives ",(0,o.jsx)(n.em,{children:"do not"})," affect what is connected"]}),"\n",(0,o.jsxs)(n.li,{children:["Static cast does not remove extra members, thus a static cast ",(0,o.jsx)(n.em,{children:"does not"})," affect what is connected"]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"connecting-different-sub-types-of-the-same-super-type-with-colliding-names",children:"Connecting different sub-types of the same super-type, with colliding names"}),"\n",(0,o.jsxs)(n.p,{children:["In these examples, we are connecting ",(0,o.jsx)(n.code,{children:"MyDecoupled"})," with ",(0,o.jsx)(n.code,{children:"MyDecoupledOtherBits"}),".\nBoth are subtypes of ",(0,o.jsx)(n.code,{children:"MyReadyValid"}),", and both have a ",(0,o.jsx)(n.code,{children:"bits"})," field of type ",(0,o.jsx)(n.code,{children:"UInt(32.W)"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["The first example will use ",(0,o.jsx)(n.code,{children:".viewAsSupertype"})," to connect them as ",(0,o.jsx)(n.code,{children:"MyReadyValid"}),".\nBecause it changes the Chisel type to omit both ",(0,o.jsx)(n.code,{children:"bits"})," fields, the ",(0,o.jsx)(n.code,{children:"bits"})," fields are unconnected."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import experimental.dataview._\nclass MyDecoupledOtherBits extends MyReadyValid {\n val bits = UInt(32.W)\n}\nclass Example12 extends RawModule {\n val in = IO(Flipped(new MyDecoupled))\n val out = IO(new MyDecoupledOtherBits)\n\n out := DontCare\n\n out.viewAsSupertype(new MyReadyValid) :<>= in.viewAsSupertype(new MyReadyValid)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["Note that the ",(0,o.jsx)(n.code,{children:"bits"})," fields are unconnected."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example12(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready,\n output [31:0] out_bits\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\n assign out_bits = 32'h0;\nendmodule\n\n"})}),"\n",(0,o.jsxs)(n.p,{children:["The second example will use a static cast and ",(0,o.jsx)(n.code,{children:".waive(_.bits)"})," to connect them as ",(0,o.jsx)(n.code,{children:"MyReadyValid"}),".\nNote that because the static cast does not change the Chisel type, the connection finds that both consumer and producer have a ",(0,o.jsx)(n.code,{children:"bits"})," field.\nThis means that since they are structurally equivalent, they match and are connected.\nThe ",(0,o.jsx)(n.code,{children:"waive(_.bits)"})," does nothing, because the ",(0,o.jsx)(n.code,{children:"bits"})," are neither dangling nor unconnected."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"import experimental.dataview._\nclass Example13 extends RawModule {\n val in = IO(Flipped(new MyDecoupled))\n val out = IO(new MyDecoupledOtherBits)\n\n out := DontCare\n\n out.waiveAs[MyReadyValid](_.bits) :<>= in.waiveAs[MyReadyValid](_.bits)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["Note that the ",(0,o.jsx)(n.code,{children:"bits"})," fields ARE connected, even though they are waived, as ",(0,o.jsx)(n.code,{children:".waive"})," just changes whether an error should be thrown if they are missing, NOT to not connect them if they are structurally equivalent.\nTo always omit the connection, use ",(0,o.jsx)(n.code,{children:".exclude"})," on one side and either ",(0,o.jsx)(n.code,{children:".exclude"})," or ",(0,o.jsx)(n.code,{children:".waive"})," on the other side."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example13(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready,\n output [31:0] out_bits\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\n assign out_bits = in_bits;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"connecting-sub-types-to-super-types-by-waiving-extra-members",children:"Connecting sub-types to super-types by waiving extra members"}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note that in this example, it would be better to use ",(0,o.jsx)(n.code,{children:".viewAsSupertype"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["In the following example, we can use ",(0,o.jsx)(n.code,{children:":<>="})," to connect a ",(0,o.jsx)(n.code,{children:"MyReadyValid"})," to a ",(0,o.jsx)(n.code,{children:"MyDecoupled"})," by waiving the ",(0,o.jsx)(n.code,{children:"bits"})," member."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class MyReadyValid extends Bundle {\n val valid = Bool()\n val ready = Flipped(Bool())\n}\nclass MyDecoupled extends MyReadyValid {\n val bits = UInt(32.W)\n}\nclass Example5 extends RawModule {\n val in = IO(Flipped(new MyDecoupled))\n val out = IO(new MyReadyValid)\n out :<>= in.waiveAs[MyReadyValid](_.bits)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"ready"})," and ",(0,o.jsx)(n.code,{children:"valid"})," are connected, and ",(0,o.jsx)(n.code,{children:"bits"})," is ignored:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example5(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h3,{id:"connecting-different-sub-types",children:"Connecting different sub-types"}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["Note that in this example, it would be better to use ",(0,o.jsx)(n.code,{children:".viewAsSupertype"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Note that the connection operator requires the ",(0,o.jsx)(n.code,{children:"consumer"})," and ",(0,o.jsx)(n.code,{children:"producer"})," to be the same Scala type to encourage capturing more information statically, but they can always be cast to ",(0,o.jsx)(n.code,{children:"Data"})," or another common supertype prior to connecting."]}),"\n",(0,o.jsxs)(n.p,{children:["In the following example, we can use ",(0,o.jsx)(n.code,{children:":<>="})," and ",(0,o.jsx)(n.code,{children:".waiveAs"})," to connect two different sub-types of ",(0,o.jsx)(n.code,{children:"MyReadyValid"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class HasBits extends MyReadyValid {\n val bits = UInt(32.W)\n}\nclass HasEcho extends MyReadyValid {\n val echo = Flipped(UInt(32.W))\n}\nclass Example7 extends RawModule {\n val in = IO(Flipped(new HasBits))\n val out = IO(new HasEcho)\n out.waiveAs[MyReadyValid](_.echo) :<>= in.waiveAs[MyReadyValid](_.bits)\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This generates the following Verilog, where ",(0,o.jsx)(n.code,{children:"ready"})," and ",(0,o.jsx)(n.code,{children:"valid"})," are connected, and ",(0,o.jsx)(n.code,{children:"bits"})," and ",(0,o.jsx)(n.code,{children:"echo"})," are ignored:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example7(\n input in_valid,\n output in_ready,\n input [31:0] in_bits,\n output out_valid,\n input out_ready,\n input [31:0] out_echo\n);\n\n assign in_ready = out_ready;\n assign out_valid = in_valid;\nendmodule\n\n"})}),"\n",(0,o.jsx)(n.h2,{id:"faq",children:"FAQ"}),"\n",(0,o.jsx)(n.h3,{id:"how-do-i-connect-two-items-as-flexibly-as-possible-try-your-best-but-never-error",children:"How do I connect two items as flexibly as possible (try your best but never error)"}),"\n",(0,o.jsxs)(n.p,{children:["Use ",(0,o.jsx)(n.code,{children:".unsafe"})," (both waives and allows squeezing of all fields)."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class ExampleUnsafe extends RawModule {\n val in = IO(Flipped(new Bundle { val foo = Bool(); val bar = Bool() }))\n val out = IO(new Bundle { val baz = Bool(); val bar = Bool() })\n out.unsafe :<>= in.unsafe // bar is connected, and nothing errors\n}\n"})}),"\n",(0,o.jsx)(n.h3,{id:"how-do-i-connect-two-items-but-dont-care-about-the-scala-types-being-equivalent",children:"How do I connect two items but don't care about the Scala types being equivalent?"}),"\n",(0,o.jsxs)(n.p,{children:["Use ",(0,o.jsx)(n.code,{children:".as"})," (upcasts the Scala type)."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-scala",children:"class ExampleAs extends RawModule {\n val in = IO(Flipped(new Bundle { val foo = Bool(); val bar = Bool() }))\n val out = IO(new Bundle { val foo = Bool(); val bar = Bool() })\n // foo and bar are connected, although Scala types aren't the same\n out.as[Data] :<>= in.as[Data]\n}\n"})})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(a,{...e})}):a(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>c,x:()=>s});var o=i(6540);const l={},t=o.createContext(l);function c(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(l):e.components||l:c(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d50fb5c7.3da5f25c.js b/assets/js/d50fb5c7.3da5f25c.js
deleted file mode 100644
index 9039e43f482..00000000000
--- a/assets/js/d50fb5c7.3da5f25c.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[1281],{9536:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>c,frontMatter:()=>s,metadata:()=>l,toc:()=>u});var t=a(4848),i=a(8453);const s={layout:"docs",title:"Naming",section:"chisel3"},o="Naming",l={id:"explanations/naming",title:"Naming",description:"Historically, Chisel has had trouble reliably capturing the names of signals. The reasons for this are due to (1)",source:"@site/docs/explanations/naming.md",sourceDirName:"explanations",slug:"/explanations/naming",permalink:"/docs/explanations/naming",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/naming.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Naming",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Muxes and Input Selection",permalink:"/docs/explanations/muxes-and-input-selection"},next:{title:"Operators",permalink:"/docs/explanations/operators"}},r={},u=[{value:"Compiler Plugin",id:"compiler-plugin",level:3},{value:"Prefixing",id:"prefixing",level:3},{value:"Suggest a Signal's Name (or the instance name of a Module)",id:"suggest-a-signals-name-or-the-instance-name-of-a-module",level:3},{value:"Behavior for "Unnamed signals" (aka "Temporaries")",id:"behavior-for-unnamed-signals-aka-temporaries",level:3},{value:"Set a Module Name",id:"set-a-module-name",level:3}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h3:"h3",header:"header",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"naming",children:"Naming"})}),"\n",(0,t.jsxs)(n.p,{children:["Historically, Chisel has had trouble reliably capturing the names of signals. The reasons for this are due to (1)\nprimarily relying on reflection to find names, (2) using ",(0,t.jsx)(n.code,{children:"@chiselName"})," macro which had unreliable behavior."]}),"\n",(0,t.jsx)(n.p,{children:"Chisel 3.4 introduced a custom Scala compiler plugin which enables reliabe and automatic capturing of signal names, when\nthey are declared. In addition, this release includes prolific use of a new prefixing API which enables more stable\nnaming of signals programmatically generated from function calls."}),"\n",(0,t.jsxs)(n.p,{children:["This document explains how naming now works in Chisel for signal and module names. For cookbook examples on how to fix\nsystemic name-stability issues, please refer to the naming ",(0,t.jsx)(n.a,{href:"../cookbooks/naming",children:"cookbook"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"compiler-plugin",children:"Compiler Plugin"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"// Imports used by the following examples\nimport chisel3._\nimport chisel3.experimental.{prefix, noPrefix}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Chisel users must also include the compiler plugin in their build settings.\nIn SBT this is something like:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'// For chisel versions 5.0.0+\naddCompilerPlugin("org.chipsalliance" % "chisel-plugin" % "5.0.0" cross CrossVersion.full)\n// For older chisel3 versions, eg. 3.6.0\naddCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % "3.6.0" cross CrossVersion.full)\n'})}),"\n",(0,t.jsxs)(n.p,{children:["This plugin will run after the 'typer' phase of the Scala compiler. It looks for any user code which is of the form\n",(0,t.jsx)(n.code,{children:"val x = y"}),", where ",(0,t.jsx)(n.code,{children:"x"})," is of type ",(0,t.jsx)(n.code,{children:"chisel3.Data"}),", ",(0,t.jsx)(n.code,{children:"chisel3.MemBase"}),", or ",(0,t.jsx)(n.code,{children:"chisel3.experimental.BaseModule"}),". For each\nline which fits this criteria, it rewrites that line. In the following examples, the commented line is the what the\nline above is rewritten to."]}),"\n",(0,t.jsxs)(n.p,{children:["If the line is within a bundle declaration or is a module instantiation, it is rewritten to replace the right hand\nside with a call to ",(0,t.jsx)(n.code,{children:"autoNameRecursively"}),", which names the signal/module."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class MyBundle extends Bundle {\n val foo = Input(UInt(3.W))\n // val foo = autoNameRecursively("foo")(Input(UInt(3.W)))\n}\nclass Example1 extends Module {\n val io = IO(new MyBundle())\n // val io = autoNameRecursively("io")(IO(new MyBundle()))\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example1(\n input clock,\n reset,\n input [2:0] io_foo\n);\n\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"Otherwise, it is rewritten to also include the name as a prefix to any signals generated while executing the right-hand-\nside of the val declaration:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example2 extends Module {\n val in = IO(Input(UInt(2.W)))\n // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W)))))\n\n val out1 = IO(Output(UInt(4.W)))\n // val out1 = autoNameRecursively("out1")(prefix("out1")(IO(Output(UInt(4.W)))))\n val out2 = IO(Output(UInt(4.W)))\n // val out2 = autoNameRecursively("out2")(prefix("out2")(IO(Output(UInt(4.W)))))\n val out3 = IO(Output(UInt(4.W)))\n // val out3 = autoNameRecursively("out3")(prefix("out3")(IO(Output(UInt(4.W)))))\n\n def func() = {\n val squared = in * in\n // val squared = autoNameRecursively("squared")(prefix("squared")(in * in))\n out1 := squared\n val delay = RegNext(squared)\n // val delay = autoNameRecursively("delay")(prefix("delay")(RegNext(squared)))\n delay\n }\n\n val masked = 0xa.U & func()\n // val masked = autoNameRecursively("masked")(prefix("masked")(0xa.U & func()))\n // Note that values created inside of `func()`` are prefixed with `masked`\n\n out2 := masked + 1.U\n out3 := masked - 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.99.2\nmodule Example2(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out1,\n out2,\n out3\n);\n\n wire [3:0] _GEN = {2'h0, in};\n wire [3:0] masked_squared = _GEN * _GEN;\n reg [3:0] masked_delay;\n wire [3:0] masked = masked_delay & 4'hA;\n always @(posedge clock)\n masked_delay <= masked_squared;\n assign out1 = masked_squared;\n assign out2 = masked + 4'h1;\n assign out3 = masked - 4'h1;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"Prefixing can also be derived from the name of signals on the left-hand side of a connection.\nWhile this is not implemented via the compiler plugin, the behavior should feel similar:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class ConnectPrefixing extends Module {\n val in = IO(Input(UInt(2.W)))\n // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W)))))\n\n val out1 = IO(Output(UInt(4.W)))\n // val out1 = autoNameRecursively("out1")(prefix("out1")(IO(Output(UInt(4.W)))))\n val out2 = IO(Output(UInt(4.W)))\n // val out2 = autoNameRecursively("out2")(prefix("out2")(IO(Output(UInt(4.W)))))\n\n out1 := { // technically this is not wrapped in autoNameRecursively nor prefix\n // But the Chisel runtime will still use the name of `out1` as a prefix\n val squared = in * in\n out2 := squared\n val delayed = RegNext(squared)\n // val delayed = autoNameRecursively("delayed")(prefix("delayed")(RegNext(squared)))\n delayed + 1.U\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule ConnectPrefixing(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out1,\n out2\n);\n\n wire [3:0] _GEN = {2'h0, in};\n wire [3:0] out1_squared = _GEN * _GEN;\n reg [3:0] out1_delayed;\n always @(posedge clock)\n out1_delayed <= out1_squared;\n assign out1 = out1_delayed + 4'h1;\n assign out2 = out1_squared;\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that the naming also works if the hardware type is nested in an ",(0,t.jsx)(n.code,{children:"Option"})," or a subtype of ",(0,t.jsx)(n.code,{children:"Iterable"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example3 extends Module {\n val in = IO(Input(UInt(2.W)))\n // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W)))))\n\n val out = IO(Output(UInt(4.W)))\n // val out = autoNameRecursively("out")(prefix("out")(IO(Output(UInt(4.W)))))\n\n def func() = {\n val delay = RegNext(in)\n delay + 1.U\n }\n\n val opt = Some(func())\n // Note that the register in func() is prefixed with `opt`:\n // val opt = autoNameRecursively("opt")(prefix("opt")(Some(func()))\n\n out := opt.get + 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.99.2\nmodule Example3(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out\n);\n\n reg [1:0] opt_delay;\n always @(posedge clock)\n opt_delay <= in;\n assign out = {2'h0, opt_delay - 2'h2};\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["There is also a slight variant (",(0,t.jsx)(n.code,{children:"autoNameRecursivelyProduct"}),") for naming hardware with names provided by an unapply:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class UnapplyExample extends Module {\n def mkIO() = (IO(Input(UInt(2.W))), IO(Output(UInt(2.W))))\n val (in, out) = mkIO()\n // val (in, out) = autoNameRecursivelyProduct(List(Some("in"), Some("out")))(mkIO())\n\n out := in\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule UnapplyExample(\n input clock,\n reset,\n input [1:0] in,\n output [1:0] out\n);\n\n assign out = in;\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that the compiler plugin will not insert a prefix in these cases because it is ambiguous what the prefix should be.\nUsers who desire a prefix are encouraged to provide one as ",(0,t.jsx)(n.a,{href:"#prefixing",children:"described below"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"prefixing",children:"Prefixing"}),"\n",(0,t.jsxs)(n.p,{children:["As shown above, the compiler plugin automatically attempts to prefix some of your signals for you.\nHowever, you as a user can also add your own prefixes by calling ",(0,t.jsx)(n.code,{children:"prefix(...)"}),":"]}),"\n",(0,t.jsx)(n.p,{children:"Also note that the prefixes append to each other (including the prefix generated by the compiler plugin):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example6 extends Module {\n val in = IO(Input(UInt(2.W)))\n val out = IO(Output(UInt(4.W)))\n\n val add = prefix("foo") {\n val sum = RegNext(in + 1.U)\n sum + 1.U\n }\n\n out := add\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example6(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out\n);\n\n reg [1:0] add_foo_sum;\n always @(posedge clock)\n add_foo_sum <= in + 2'h1;\n assign out = {2'h0, add_foo_sum + 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Sometimes you may want to disable the prefixing. This might occur if you are writing a library function and\ndon't want the prefixing behavior. In this case, you can call ",(0,t.jsx)(n.code,{children:"noPrefix"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class Example7 extends Module {\n val in = IO(Input(UInt(2.W)))\n val out = IO(Output(UInt(4.W)))\n\n val add = noPrefix {\n val sum = RegNext(in + 1.U)\n sum + 1.U\n }\n\n out := add\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example7(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out\n);\n\n reg [1:0] sum;\n always @(posedge clock)\n sum <= in + 2'h1;\n assign out = {2'h0, sum + 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"suggest-a-signals-name-or-the-instance-name-of-a-module",children:"Suggest a Signal's Name (or the instance name of a Module)"}),"\n",(0,t.jsxs)(n.p,{children:["If you want to specify the name of a signal, you can always use the ",(0,t.jsx)(n.code,{children:".suggestName"})," API. Please note that the suggested\nname will still be prefixed (including by the plugin). You can always use the ",(0,t.jsx)(n.code,{children:"noPrefix"})," object to strip this."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example8 extends Module {\n val in = IO(Input(UInt(2.W)))\n val out = IO(Output(UInt(4.W)))\n\n val add = {\n val sum = RegNext(in + 1.U).suggestName("foo")\n sum + 1.U\n }\n\n out := add\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule Example8(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out\n);\n\n reg [1:0] add_foo;\n always @(posedge clock)\n add_foo <= in + 2'h1;\n assign out = {2'h0, add_foo + 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that using ",(0,t.jsx)(n.code,{children:".suggestName"})," does ",(0,t.jsx)(n.strong,{children:"not"})," affect prefixes derived from val names;\nhowever, it ",(0,t.jsx)(n.em,{children:"can"})," affect prefixes derived from connections (eg. ",(0,t.jsx)(n.code,{children:":="}),"):"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class ConnectionPrefixExample extends Module {\n val in0 = IO(Input(UInt(2.W)))\n val in1 = IO(Input(UInt(2.W)))\n\n val out0 = {\n val port = IO(Output(UInt(5.W)))\n // Even though this suggestName is before mul, the prefix used in this scope\n // is derived from `val out0`, so this does not affect the name of mul\n port.suggestName("foo")\n // out0_mul\n val mul = RegNext(in0 * in1)\n port := mul + 1.U\n port\n }\n\n val out1 = IO(Output(UInt(4.W)))\n val out2 = IO(Output(UInt(4.W)))\n\n out1 := {\n // out1_sum\n val sum = RegNext(in0 + in1)\n sum + 1.U\n }\n // Comes after so does *not* affect prefix above\n out1.suggestName("bar")\n\n // Comes before so *does* affect prefix below\n out2.suggestName("fizz")\n out2 := {\n // fizz_diff\n val diff = RegNext(in0 - in1)\n diff + 1.U\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule ConnectionPrefixExample(\n input clock,\n reset,\n input [1:0] in0,\n in1,\n output [4:0] foo,\n output [3:0] bar,\n fizz\n);\n\n reg [3:0] out0_mul;\n reg [1:0] out1_sum;\n reg [1:0] fizz_diff;\n always @(posedge clock) begin\n out0_mul <= {2'h0, in0} * {2'h0, in1};\n out1_sum <= in0 + in1;\n fizz_diff <= in0 - in1;\n end // always @(posedge)\n assign foo = {1'h0, out0_mul + 4'h1};\n assign bar = {2'h0, out1_sum + 2'h1};\n assign fizz = {2'h0, fizz_diff + 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"As this example illustrates, this behavior is slightly inconsistent so is subject to change in a future version of Chisel."}),"\n",(0,t.jsx)(n.h3,{id:"behavior-for-unnamed-signals-aka-temporaries",children:'Behavior for "Unnamed signals" (aka "Temporaries")'}),"\n",(0,t.jsxs)(n.p,{children:["If you want to signify that the name of a signal does not matter, you can prefix the name of your val with ",(0,t.jsx)(n.code,{children:"_"}),".\nChisel will preserve the convention of leading ",(0,t.jsx)(n.code,{children:"_"})," signifying an unnamed signal across prefixes.\nFor example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class TemporaryExample extends Module {\n val in0 = IO(Input(UInt(2.W)))\n val in1 = IO(Input(UInt(2.W)))\n\n val out = {\n // We need 2 ports so firtool will maintain the common subexpression\n val port0 = IO(Output(UInt(4.W)))\n // out_port1\n val port1 = IO(Output(UInt(4.W)))\n val _sum = in0 + in1\n port0 := _sum + 1.U\n port1 := _sum - 1.U\n // port0 is returned so will get the name "out"\n port0\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule TemporaryExample(\n input clock,\n reset,\n input [1:0] in0,\n in1,\n output [3:0] out,\n out_port1\n);\n\n wire [1:0] _out_sum_T = in0 + in1;\n assign out = {2'h0, _out_sum_T + 2'h1};\n assign out_port1 = {2'h0, _out_sum_T - 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If an unnamed signal is itself used to generate a prefix, the leading ",(0,t.jsx)(n.code,{children:"_"})," will be ignored to avoid double ",(0,t.jsx)(n.code,{children:"__"})," in the names of further nested signals."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TemporaryPrefixExample extends Module {\n val in0 = IO(Input(UInt(2.W)))\n val in1 = IO(Input(UInt(2.W)))\n val out0 = IO(Output(UInt(3.W)))\n val out1 = IO(Output(UInt(4.W)))\n\n val _sum = {\n val x = in0 + in1\n out0 := x\n x + 1.U\n }\n out1 := _sum & 0x2.U\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule TemporaryPrefixExample(\n input clock,\n reset,\n input [1:0] in0,\n in1,\n output [2:0] out0,\n output [3:0] out1\n);\n\n wire [1:0] _sum_x_T = in0 + in1;\n assign out0 = {1'h0, _sum_x_T};\n assign out1 = {2'h0, _sum_x_T + 2'h1 & 2'h2};\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"set-a-module-name",children:"Set a Module Name"}),"\n",(0,t.jsxs)(n.p,{children:["If you want to specify the module's name (not the instance name of a module), you can always override the ",(0,t.jsx)(n.code,{children:"desiredName"}),"\nvalue. Note that you can parameterize the name by the module's parameters. This is an excellent way to make your module\nnames more stable and is highly recommended to do."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example9(width: Int) extends Module {\n override val desiredName = s"EXAMPLE9WITHWIDTH$width"\n val in = IO(Input(UInt(width.W)))\n val out = IO(Output(UInt((width + 2).W)))\n\n val add = (in + (in + in).suggestName("foo"))\n\n out := add\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule EXAMPLE9WITHWIDTH8(\n input clock,\n reset,\n input [7:0] in,\n output [9:0] out\n);\n\n assign out = {2'h0, in + {in[6:0], 1'h0}};\nendmodule\n\n// Generated by CIRCT firtool-1.99.2\nmodule EXAMPLE9WITHWIDTH1(\n input clock,\n reset,\n in,\n output [2:0] out\n);\n\n assign out = {2'h0, in};\nendmodule\n\n"})})]})}function c(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:()=>o,x:()=>l});var t=a(6540);const i={},s=t.createContext(i);function o(e){const n=t.useContext(s);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(i):e.components||i:o(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d50fb5c7.99b64109.js b/assets/js/d50fb5c7.99b64109.js
new file mode 100644
index 00000000000..ce81c109fac
--- /dev/null
+++ b/assets/js/d50fb5c7.99b64109.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[1281],{9536:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>c,frontMatter:()=>s,metadata:()=>l,toc:()=>u});var t=a(4848),i=a(8453);const s={layout:"docs",title:"Naming",section:"chisel3"},o="Naming",l={id:"explanations/naming",title:"Naming",description:"Historically, Chisel has had trouble reliably capturing the names of signals. The reasons for this are due to (1)",source:"@site/docs/explanations/naming.md",sourceDirName:"explanations",slug:"/explanations/naming",permalink:"/docs/explanations/naming",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/naming.md",tags:[],version:"current",frontMatter:{layout:"docs",title:"Naming",section:"chisel3"},sidebar:"chiselSidebar",previous:{title:"Muxes and Input Selection",permalink:"/docs/explanations/muxes-and-input-selection"},next:{title:"Operators",permalink:"/docs/explanations/operators"}},r={},u=[{value:"Compiler Plugin",id:"compiler-plugin",level:3},{value:"Prefixing",id:"prefixing",level:3},{value:"Suggest a Signal's Name (or the instance name of a Module)",id:"suggest-a-signals-name-or-the-instance-name-of-a-module",level:3},{value:"Behavior for "Unnamed signals" (aka "Temporaries")",id:"behavior-for-unnamed-signals-aka-temporaries",level:3},{value:"Set a Module Name",id:"set-a-module-name",level:3}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h3:"h3",header:"header",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"naming",children:"Naming"})}),"\n",(0,t.jsxs)(n.p,{children:["Historically, Chisel has had trouble reliably capturing the names of signals. The reasons for this are due to (1)\nprimarily relying on reflection to find names, (2) using ",(0,t.jsx)(n.code,{children:"@chiselName"})," macro which had unreliable behavior."]}),"\n",(0,t.jsx)(n.p,{children:"Chisel 3.4 introduced a custom Scala compiler plugin which enables reliabe and automatic capturing of signal names, when\nthey are declared. In addition, this release includes prolific use of a new prefixing API which enables more stable\nnaming of signals programmatically generated from function calls."}),"\n",(0,t.jsxs)(n.p,{children:["This document explains how naming now works in Chisel for signal and module names. For cookbook examples on how to fix\nsystemic name-stability issues, please refer to the naming ",(0,t.jsx)(n.a,{href:"../cookbooks/naming",children:"cookbook"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"compiler-plugin",children:"Compiler Plugin"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"// Imports used by the following examples\nimport chisel3._\nimport chisel3.experimental.{prefix, noPrefix}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Chisel users must also include the compiler plugin in their build settings.\nIn SBT this is something like:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'// For chisel versions 5.0.0+\naddCompilerPlugin("org.chipsalliance" % "chisel-plugin" % "5.0.0" cross CrossVersion.full)\n// For older chisel3 versions, eg. 3.6.0\naddCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % "3.6.0" cross CrossVersion.full)\n'})}),"\n",(0,t.jsxs)(n.p,{children:["This plugin will run after the 'typer' phase of the Scala compiler. It looks for any user code which is of the form\n",(0,t.jsx)(n.code,{children:"val x = y"}),", where ",(0,t.jsx)(n.code,{children:"x"})," is of type ",(0,t.jsx)(n.code,{children:"chisel3.Data"}),", ",(0,t.jsx)(n.code,{children:"chisel3.MemBase"}),", or ",(0,t.jsx)(n.code,{children:"chisel3.experimental.BaseModule"}),". For each\nline which fits this criteria, it rewrites that line. In the following examples, the commented line is the what the\nline above is rewritten to."]}),"\n",(0,t.jsxs)(n.p,{children:["If the line is within a bundle declaration or is a module instantiation, it is rewritten to replace the right hand\nside with a call to ",(0,t.jsx)(n.code,{children:"autoNameRecursively"}),", which names the signal/module."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class MyBundle extends Bundle {\n val foo = Input(UInt(3.W))\n // val foo = autoNameRecursively("foo")(Input(UInt(3.W)))\n}\nclass Example1 extends Module {\n val io = IO(new MyBundle())\n // val io = autoNameRecursively("io")(IO(new MyBundle()))\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example1(\n input clock,\n reset,\n input [2:0] io_foo\n);\n\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"Otherwise, it is rewritten to also include the name as a prefix to any signals generated while executing the right-hand-\nside of the val declaration:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example2 extends Module {\n val in = IO(Input(UInt(2.W)))\n // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W)))))\n\n val out1 = IO(Output(UInt(4.W)))\n // val out1 = autoNameRecursively("out1")(prefix("out1")(IO(Output(UInt(4.W)))))\n val out2 = IO(Output(UInt(4.W)))\n // val out2 = autoNameRecursively("out2")(prefix("out2")(IO(Output(UInt(4.W)))))\n val out3 = IO(Output(UInt(4.W)))\n // val out3 = autoNameRecursively("out3")(prefix("out3")(IO(Output(UInt(4.W)))))\n\n def func() = {\n val squared = in * in\n // val squared = autoNameRecursively("squared")(prefix("squared")(in * in))\n out1 := squared\n val delay = RegNext(squared)\n // val delay = autoNameRecursively("delay")(prefix("delay")(RegNext(squared)))\n delay\n }\n\n val masked = 0xa.U & func()\n // val masked = autoNameRecursively("masked")(prefix("masked")(0xa.U & func()))\n // Note that values created inside of `func()`` are prefixed with `masked`\n\n out2 := masked + 1.U\n out3 := masked - 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.100.0\nmodule Example2(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out1,\n out2,\n out3\n);\n\n wire [3:0] _GEN = {2'h0, in};\n wire [3:0] masked_squared = _GEN * _GEN;\n reg [3:0] masked_delay;\n wire [3:0] masked = masked_delay & 4'hA;\n always @(posedge clock)\n masked_delay <= masked_squared;\n assign out1 = masked_squared;\n assign out2 = masked + 4'h1;\n assign out3 = masked - 4'h1;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"Prefixing can also be derived from the name of signals on the left-hand side of a connection.\nWhile this is not implemented via the compiler plugin, the behavior should feel similar:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class ConnectPrefixing extends Module {\n val in = IO(Input(UInt(2.W)))\n // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W)))))\n\n val out1 = IO(Output(UInt(4.W)))\n // val out1 = autoNameRecursively("out1")(prefix("out1")(IO(Output(UInt(4.W)))))\n val out2 = IO(Output(UInt(4.W)))\n // val out2 = autoNameRecursively("out2")(prefix("out2")(IO(Output(UInt(4.W)))))\n\n out1 := { // technically this is not wrapped in autoNameRecursively nor prefix\n // But the Chisel runtime will still use the name of `out1` as a prefix\n val squared = in * in\n out2 := squared\n val delayed = RegNext(squared)\n // val delayed = autoNameRecursively("delayed")(prefix("delayed")(RegNext(squared)))\n delayed + 1.U\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule ConnectPrefixing(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out1,\n out2\n);\n\n wire [3:0] _GEN = {2'h0, in};\n wire [3:0] out1_squared = _GEN * _GEN;\n reg [3:0] out1_delayed;\n always @(posedge clock)\n out1_delayed <= out1_squared;\n assign out1 = out1_delayed + 4'h1;\n assign out2 = out1_squared;\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that the naming also works if the hardware type is nested in an ",(0,t.jsx)(n.code,{children:"Option"})," or a subtype of ",(0,t.jsx)(n.code,{children:"Iterable"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example3 extends Module {\n val in = IO(Input(UInt(2.W)))\n // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W)))))\n\n val out = IO(Output(UInt(4.W)))\n // val out = autoNameRecursively("out")(prefix("out")(IO(Output(UInt(4.W)))))\n\n def func() = {\n val delay = RegNext(in)\n delay + 1.U\n }\n\n val opt = Some(func())\n // Note that the register in func() is prefixed with `opt`:\n // val opt = autoNameRecursively("opt")(prefix("opt")(Some(func()))\n\n out := opt.get + 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.100.0\nmodule Example3(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out\n);\n\n reg [1:0] opt_delay;\n always @(posedge clock)\n opt_delay <= in;\n assign out = {2'h0, opt_delay - 2'h2};\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["There is also a slight variant (",(0,t.jsx)(n.code,{children:"autoNameRecursivelyProduct"}),") for naming hardware with names provided by an unapply:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class UnapplyExample extends Module {\n def mkIO() = (IO(Input(UInt(2.W))), IO(Output(UInt(2.W))))\n val (in, out) = mkIO()\n // val (in, out) = autoNameRecursivelyProduct(List(Some("in"), Some("out")))(mkIO())\n\n out := in\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule UnapplyExample(\n input clock,\n reset,\n input [1:0] in,\n output [1:0] out\n);\n\n assign out = in;\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that the compiler plugin will not insert a prefix in these cases because it is ambiguous what the prefix should be.\nUsers who desire a prefix are encouraged to provide one as ",(0,t.jsx)(n.a,{href:"#prefixing",children:"described below"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"prefixing",children:"Prefixing"}),"\n",(0,t.jsxs)(n.p,{children:["As shown above, the compiler plugin automatically attempts to prefix some of your signals for you.\nHowever, you as a user can also add your own prefixes by calling ",(0,t.jsx)(n.code,{children:"prefix(...)"}),":"]}),"\n",(0,t.jsx)(n.p,{children:"Also note that the prefixes append to each other (including the prefix generated by the compiler plugin):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example6 extends Module {\n val in = IO(Input(UInt(2.W)))\n val out = IO(Output(UInt(4.W)))\n\n val add = prefix("foo") {\n val sum = RegNext(in + 1.U)\n sum + 1.U\n }\n\n out := add\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example6(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out\n);\n\n reg [1:0] add_foo_sum;\n always @(posedge clock)\n add_foo_sum <= in + 2'h1;\n assign out = {2'h0, add_foo_sum + 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Sometimes you may want to disable the prefixing. This might occur if you are writing a library function and\ndon't want the prefixing behavior. In this case, you can call ",(0,t.jsx)(n.code,{children:"noPrefix"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class Example7 extends Module {\n val in = IO(Input(UInt(2.W)))\n val out = IO(Output(UInt(4.W)))\n\n val add = noPrefix {\n val sum = RegNext(in + 1.U)\n sum + 1.U\n }\n\n out := add\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example7(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out\n);\n\n reg [1:0] sum;\n always @(posedge clock)\n sum <= in + 2'h1;\n assign out = {2'h0, sum + 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"suggest-a-signals-name-or-the-instance-name-of-a-module",children:"Suggest a Signal's Name (or the instance name of a Module)"}),"\n",(0,t.jsxs)(n.p,{children:["If you want to specify the name of a signal, you can always use the ",(0,t.jsx)(n.code,{children:".suggestName"})," API. Please note that the suggested\nname will still be prefixed (including by the plugin). You can always use the ",(0,t.jsx)(n.code,{children:"noPrefix"})," object to strip this."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example8 extends Module {\n val in = IO(Input(UInt(2.W)))\n val out = IO(Output(UInt(4.W)))\n\n val add = {\n val sum = RegNext(in + 1.U).suggestName("foo")\n sum + 1.U\n }\n\n out := add\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule Example8(\n input clock,\n reset,\n input [1:0] in,\n output [3:0] out\n);\n\n reg [1:0] add_foo;\n always @(posedge clock)\n add_foo <= in + 2'h1;\n assign out = {2'h0, add_foo + 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that using ",(0,t.jsx)(n.code,{children:".suggestName"})," does ",(0,t.jsx)(n.strong,{children:"not"})," affect prefixes derived from val names;\nhowever, it ",(0,t.jsx)(n.em,{children:"can"})," affect prefixes derived from connections (eg. ",(0,t.jsx)(n.code,{children:":="}),"):"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class ConnectionPrefixExample extends Module {\n val in0 = IO(Input(UInt(2.W)))\n val in1 = IO(Input(UInt(2.W)))\n\n val out0 = {\n val port = IO(Output(UInt(5.W)))\n // Even though this suggestName is before mul, the prefix used in this scope\n // is derived from `val out0`, so this does not affect the name of mul\n port.suggestName("foo")\n // out0_mul\n val mul = RegNext(in0 * in1)\n port := mul + 1.U\n port\n }\n\n val out1 = IO(Output(UInt(4.W)))\n val out2 = IO(Output(UInt(4.W)))\n\n out1 := {\n // out1_sum\n val sum = RegNext(in0 + in1)\n sum + 1.U\n }\n // Comes after so does *not* affect prefix above\n out1.suggestName("bar")\n\n // Comes before so *does* affect prefix below\n out2.suggestName("fizz")\n out2 := {\n // fizz_diff\n val diff = RegNext(in0 - in1)\n diff + 1.U\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule ConnectionPrefixExample(\n input clock,\n reset,\n input [1:0] in0,\n in1,\n output [4:0] foo,\n output [3:0] bar,\n fizz\n);\n\n reg [3:0] out0_mul;\n reg [1:0] out1_sum;\n reg [1:0] fizz_diff;\n always @(posedge clock) begin\n out0_mul <= {2'h0, in0} * {2'h0, in1};\n out1_sum <= in0 + in1;\n fizz_diff <= in0 - in1;\n end // always @(posedge)\n assign foo = {1'h0, out0_mul + 4'h1};\n assign bar = {2'h0, out1_sum + 2'h1};\n assign fizz = {2'h0, fizz_diff + 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.p,{children:"As this example illustrates, this behavior is slightly inconsistent so is subject to change in a future version of Chisel."}),"\n",(0,t.jsx)(n.h3,{id:"behavior-for-unnamed-signals-aka-temporaries",children:'Behavior for "Unnamed signals" (aka "Temporaries")'}),"\n",(0,t.jsxs)(n.p,{children:["If you want to signify that the name of a signal does not matter, you can prefix the name of your val with ",(0,t.jsx)(n.code,{children:"_"}),".\nChisel will preserve the convention of leading ",(0,t.jsx)(n.code,{children:"_"})," signifying an unnamed signal across prefixes.\nFor example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class TemporaryExample extends Module {\n val in0 = IO(Input(UInt(2.W)))\n val in1 = IO(Input(UInt(2.W)))\n\n val out = {\n // We need 2 ports so firtool will maintain the common subexpression\n val port0 = IO(Output(UInt(4.W)))\n // out_port1\n val port1 = IO(Output(UInt(4.W)))\n val _sum = in0 + in1\n port0 := _sum + 1.U\n port1 := _sum - 1.U\n // port0 is returned so will get the name "out"\n port0\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule TemporaryExample(\n input clock,\n reset,\n input [1:0] in0,\n in1,\n output [3:0] out,\n out_port1\n);\n\n wire [1:0] _out_sum_T = in0 + in1;\n assign out = {2'h0, _out_sum_T + 2'h1};\n assign out_port1 = {2'h0, _out_sum_T - 2'h1};\nendmodule\n\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If an unnamed signal is itself used to generate a prefix, the leading ",(0,t.jsx)(n.code,{children:"_"})," will be ignored to avoid double ",(0,t.jsx)(n.code,{children:"__"})," in the names of further nested signals."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class TemporaryPrefixExample extends Module {\n val in0 = IO(Input(UInt(2.W)))\n val in1 = IO(Input(UInt(2.W)))\n val out0 = IO(Output(UInt(3.W)))\n val out1 = IO(Output(UInt(4.W)))\n\n val _sum = {\n val x = in0 + in1\n out0 := x\n x + 1.U\n }\n out1 := _sum & 0x2.U\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule TemporaryPrefixExample(\n input clock,\n reset,\n input [1:0] in0,\n in1,\n output [2:0] out0,\n output [3:0] out1\n);\n\n wire [1:0] _sum_x_T = in0 + in1;\n assign out0 = {1'h0, _sum_x_T};\n assign out1 = {2'h0, _sum_x_T + 2'h1 & 2'h2};\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"set-a-module-name",children:"Set a Module Name"}),"\n",(0,t.jsxs)(n.p,{children:["If you want to specify the module's name (not the instance name of a module), you can always override the ",(0,t.jsx)(n.code,{children:"desiredName"}),"\nvalue. Note that you can parameterize the name by the module's parameters. This is an excellent way to make your module\nnames more stable and is highly recommended to do."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:'class Example9(width: Int) extends Module {\n override val desiredName = s"EXAMPLE9WITHWIDTH$width"\n val in = IO(Input(UInt(width.W)))\n val out = IO(Output(UInt((width + 2).W)))\n\n val add = (in + (in + in).suggestName("foo"))\n\n out := add\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule EXAMPLE9WITHWIDTH8(\n input clock,\n reset,\n input [7:0] in,\n output [9:0] out\n);\n\n assign out = {2'h0, in + {in[6:0], 1'h0}};\nendmodule\n\n// Generated by CIRCT firtool-1.100.0\nmodule EXAMPLE9WITHWIDTH1(\n input clock,\n reset,\n in,\n output [2:0] out\n);\n\n assign out = {2'h0, in};\nendmodule\n\n"})})]})}function c(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:()=>o,x:()=>l});var t=a(6540);const i={},s=t.createContext(i);function o(e){const n=t.useContext(s);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(i):e.components||i:o(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/f10ce86b.4ffec15d.js b/assets/js/f10ce86b.4ffec15d.js
new file mode 100644
index 00000000000..49b261a9a71
--- /dev/null
+++ b/assets/js/f10ce86b.4ffec15d.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkchisel_lang=self.webpackChunkchisel_lang||[]).push([[2012],{8415:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>p,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var t=a(4848),o=a(8453),i=a(1871);const s={sidebar_position:3},r="DataView Cookbook",l={id:"cookbooks/dataview",title:"DataView Cookbook",description:"How do I view a Data as a UInt or vice versa?",source:"@site/docs/cookbooks/dataview.md",sourceDirName:"cookbooks",slug:"/cookbooks/dataview",permalink:"/docs/cookbooks/dataview",draft:!1,unlisted:!1,editUrl:"https://github.com/chipsalliance/chisel/tree/main/docs/src/cookbooks/dataview.md",tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"chiselSidebar",previous:{title:"Hierarchy Cookbook",permalink:"/docs/cookbooks/hierarchy"},next:{title:"Serialization Cookbook",permalink:"/docs/cookbooks/serialization"}},c={},d=[{value:"How do I view a Data as a UInt or vice versa?",id:"how-do-i-view-a-data-as-a-uint-or-vice-versa",level:2},{value:"How do I create a DataView for a Bundle has a type parameter?",id:"how-do-i-create-a-dataview-for-a-bundle-has-a-type-parameter",level:2},{value:"How do I create a DataView for a Bundle with optional fields?",id:"how-do-i-create-a-dataview-for-a-bundle-with-optional-fields",level:2},{value:"How do I connect a subset of Bundle fields?",id:"how-do-i-connect-a-subset-of-bundle-fields",level:2},{value:"How do I view a Bundle as a parent type (superclass)?",id:"how-do-i-view-a-bundle-as-a-parent-type-superclass",level:3},{value:"How do I view a Bundle as a parent type when the parent type is abstract (like a trait)?",id:"how-do-i-view-a-bundle-as-a-parent-type-when-the-parent-type-is-abstract-like-a-trait",level:3},{value:"How can I use .viewAs
instead of .viewAsSupertype(type)
?",id:"how-can-i-use-viewas-instead-of-viewassupertypetype",level:3}];function u(e){const n={code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"dataview-cookbook",children:"DataView Cookbook"})}),"\n","\n",(0,t.jsx)(i.A,{toc:d}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-view-a-data-as-a-uint-or-vice-versa",children:"How do I view a Data as a UInt or vice versa?"}),"\n",(0,t.jsxs)(n.p,{children:["Subword viewing (using concatenations or bit extractions in ",(0,t.jsx)(n.code,{children:"DataViews"}),") is not yet supported.\nWe intend to implement this in the future, but for the time being, use regular casts\n(",(0,t.jsx)(n.code,{children:".asUInt"})," and ",(0,t.jsx)(n.code,{children:".asTypeOf"}),")."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-a-dataview-for-a-bundle-has-a-type-parameter",children:"How do I create a DataView for a Bundle has a type parameter?"}),"\n",(0,t.jsxs)(n.p,{children:["Instead of using a ",(0,t.jsx)(n.code,{children:"val"}),", use a ",(0,t.jsx)(n.code,{children:"def"})," which can have type parameters:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\nclass Foo[T <: Data](val foo: T) extends Bundle\nclass Bar[T <: Data](val bar: T) extends Bundle\n\nobject Foo {\n implicit def view[T <: Data]: DataView[Foo[T], Bar[T]] = {\n DataView(f => new Bar(f.foo.cloneType), _.foo -> _.bar)\n // .cloneType is necessary because the f passed to this function will be bound hardware\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you think about type parameterized classes as really being a family of different classes\n(one for each type parameter), you can think about the ",(0,t.jsx)(n.code,{children:"implicit def"})," as a generator of ",(0,t.jsx)(n.code,{children:"DataViews"}),"\nfor each type parameter."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-a-dataview-for-a-bundle-with-optional-fields",children:"How do I create a DataView for a Bundle with optional fields?"}),"\n",(0,t.jsxs)(n.p,{children:["Instead of using the default ",(0,t.jsx)(n.code,{children:"DataView"})," apply method, use ",(0,t.jsx)(n.code,{children:"DataView.mapping"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\nclass Foo(val w: Option[Int]) extends Bundle {\n val foo = UInt(8.W)\n val opt = w.map(x => UInt(x.W))\n}\nclass Bar(val w: Option[Int]) extends Bundle {\n val bar = UInt(8.W)\n val opt = w.map(x => UInt(x.W))\n}\n\nobject Foo {\n implicit val view: DataView[Foo, Bar] =\n DataView.mapping(\n // First argument is always the function to make the view from the target\n f => new Bar(f.w),\n // Now instead of a varargs of tuples of individual mappings, we have a single function that\n // takes a target and a view and returns an Iterable of tuple\n (f, b) => List(f.foo -> b.bar) ++ f.opt.map(_ -> b.opt.get)\n // ^ Note that we can append options since they are Iterable!\n\n )\n}\n"})}),"\n",(0,t.jsx)(n.h2,{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:['Chisel 3 requires types to match exactly for connections.\nDataView provides a mechanism for "viewing" one ',(0,t.jsx)(n.code,{children:"Bundle"})," object as if it were the type of another,\nwhich allows them to be connected."]}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-view-a-bundle-as-a-parent-type-superclass",children:"How do I view a Bundle as a parent type (superclass)?"}),"\n",(0,t.jsxs)(n.p,{children:["For viewing ",(0,t.jsx)(n.code,{children:"Bundles"})," as the type of the parent, it is as simple as using ",(0,t.jsx)(n.code,{children:"viewAsSupertype"})," and providing a\ntemplate object of the parent type:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\nclass Foo extends Bundle {\n val foo = UInt(8.W)\n}\nclass Bar extends Foo {\n val bar = UInt(8.W)\n}\nclass MyModule extends Module {\n val foo = IO(Input(new Foo))\n val bar = IO(Output(new Bar))\n bar.viewAsSupertype(new Foo) := foo // bar.foo := foo.foo\n bar.bar := 123.U // all fields need to be connected\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule MyModule(\n input clock,\n reset,\n input [7:0] foo_foo,\n output [7:0] bar_foo,\n bar_bar\n);\n\n assign bar_foo = foo_foo;\n assign bar_bar = 8'h7B;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-view-a-bundle-as-a-parent-type-when-the-parent-type-is-abstract-like-a-trait",children:"How do I view a Bundle as a parent type when the parent type is abstract (like a trait)?"}),"\n",(0,t.jsxs)(n.p,{children:["Given the following ",(0,t.jsx)(n.code,{children:"Bundles"})," that share a common ",(0,t.jsx)(n.code,{children:"trait"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\ntrait Super extends Bundle {\n def bitwidth: Int\n val a = UInt(bitwidth.W)\n}\nclass Foo(val bitwidth: Int) extends Super {\n val foo = UInt(8.W)\n}\nclass Bar(val bitwidth: Int) extends Super {\n val bar = UInt(8.W)\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Foo"})," and ",(0,t.jsx)(n.code,{children:"Bar"})," cannot be connected directly, but they could be connected by viewing them both as if\nthey were instances of their common supertype, ",(0,t.jsx)(n.code,{children:"Super"}),".\nA straightforward approach might run into an issue like the following:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class MyModule extends Module {\n val foo = IO(Input(new Foo(8)))\n val bar = IO(Output(new Bar(8)))\n bar.viewAsSupertype(new Super) := foo.viewAsSupertype(new Super)\n}\n// error: trait Super is abstract; cannot be instantiated\n// bar.viewAsSupertype(new Super) := foo.viewAsSupertype(new Super)\n// ^^^^^^^^^\n// error: trait Super is abstract; cannot be instantiated\n// bar.viewAsSupertype(new Super) := foo.viewAsSupertype(new Super)\n// ^^^^^^^^^\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The problem is that ",(0,t.jsx)(n.code,{children:"viewAs"})," requires an object to use as a type template (so that it can be cloned),\nbut ",(0,t.jsx)(n.code,{children:"traits"})," are abstract and cannot be instantiated.\nThe solution is to create an instance of an ",(0,t.jsx)(n.em,{children:"anonymous class"})," and use that object as the argument to ",(0,t.jsx)(n.code,{children:"viewAs"}),".\nWe can do this like so:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class MyModule extends Module {\n val foo = IO(Input(new Foo(8)))\n val bar = IO(Output(new Bar(8)))\n val tpe = new Super { // Adding curly braces creates an anonymous class\n def bitwidth = 8 // We must implement any abstract methods\n }\n bar.viewAsSupertype(tpe) := foo.viewAsSupertype(tpe)\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["By adding curly braces after the name of the trait, we're telling Scala to create a new concrete\nsubclass of the trait, and create an instance of it.\nAs indicated in the comment, abstract methods must still be implemented.\nThis is the same that happens when one writes ",(0,t.jsx)(n.code,{children:"new Bundle {}"}),",\nthe curly braces create a new concrete subclass; however, because ",(0,t.jsx)(n.code,{children:"Bundle"})," has no abstract methods,\nthe contents of the body can be empty."]}),"\n",(0,t.jsxs)(n.h3,{id:"how-can-i-use-viewas-instead-of-viewassupertypetype",children:["How can I use ",(0,t.jsx)(n.code,{children:".viewAs"})," instead of ",(0,t.jsx)(n.code,{children:".viewAsSupertype(type)"}),"?"]}),"\n",(0,t.jsxs)(n.p,{children:["While ",(0,t.jsx)(n.code,{children:"viewAsSupertype"})," is helpful for one-off casts, the need to provide a type template object\neach time can be onerous.\nBecause of the subtyping relationship, you can use ",(0,t.jsx)(n.code,{children:"PartialDataView.supertype"})," to create a\n",(0,t.jsx)(n.code,{children:"DataView"})," from a Bundle type to a parent type by just providing the function to construct an\ninstance of the parent type from an instance of the child type.\nThe mapping of corresponding fields is automatically determined by Chisel to be the fields defined\nin the supertype."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\nclass Foo(x: Int) extends Bundle {\n val foo = UInt(x.W)\n}\nclass Bar(val x: Int) extends Foo(x) {\n val bar = UInt(x.W)\n}\n// Define a DataView without having to specify the mapping!\nimplicit val view: DataView[Bar, Foo] = PartialDataView.supertype[Bar, Foo](b => new Foo(b.x))\n\nclass MyModule extends Module {\n val foo = IO(Input(new Foo(8)))\n val bar = IO(Output(new Bar(8)))\n bar.viewAs[Foo] := foo // bar.foo := foo.foo\n bar.bar := 123.U // all fields need to be connected\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.100.0\nmodule MyModule(\n input clock,\n reset,\n input [7:0] foo_foo,\n output [7:0] bar_foo,\n bar_bar\n);\n\n assign bar_foo = foo_foo;\n assign bar_bar = 8'h7B;\nendmodule\n\n"})})]})}function p(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:()=>s});a(6540);var t=a(5195);const o={tableOfContentsInline:"tableOfContentsInline_prmo"};var i=a(4848);function s(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:s}=e;return(0,i.jsx)("div",{className:o.tableOfContentsInline,children:(0,i.jsx)(t.A,{toc:n,minHeadingLevel:a,maxHeadingLevel:s,className:"table-of-contents",linkClassName:null})})}},5195:(e,n,a)=>{a.d(n,{A:()=>m});var t=a(6540),o=a(6342);function i(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 s(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:t}=e;return n.flatMap((e=>{const n=s({toc:e.children,minHeadingLevel:a,maxHeadingLevel:t});return function(e){return e.level>=a&&e.level<=t}(e)?[{...e,children:n}]:n}))}function r(e){const n=e.getBoundingClientRect();return n.top===n.bottom?r(e.parentNode):n}function l(e,n){let{anchorTopOffset:a}=n;const t=e.find((e=>r(e).top>=a));if(t){return function(e){return e.top>0&&e.bottom.viewAs
instead of .viewAsSupertype(type)
?",id:"how-can-i-use-viewas-instead-of-viewassupertypetype",level:3}];function u(e){const n={code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"dataview-cookbook",children:"DataView Cookbook"})}),"\n","\n",(0,t.jsx)(i.A,{toc:d}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-view-a-data-as-a-uint-or-vice-versa",children:"How do I view a Data as a UInt or vice versa?"}),"\n",(0,t.jsxs)(n.p,{children:["Subword viewing (using concatenations or bit extractions in ",(0,t.jsx)(n.code,{children:"DataViews"}),") is not yet supported.\nWe intend to implement this in the future, but for the time being, use regular casts\n(",(0,t.jsx)(n.code,{children:".asUInt"})," and ",(0,t.jsx)(n.code,{children:".asTypeOf"}),")."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-a-dataview-for-a-bundle-has-a-type-parameter",children:"How do I create a DataView for a Bundle has a type parameter?"}),"\n",(0,t.jsxs)(n.p,{children:["Instead of using a ",(0,t.jsx)(n.code,{children:"val"}),", use a ",(0,t.jsx)(n.code,{children:"def"})," which can have type parameters:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\nclass Foo[T <: Data](val foo: T) extends Bundle\nclass Bar[T <: Data](val bar: T) extends Bundle\n\nobject Foo {\n implicit def view[T <: Data]: DataView[Foo[T], Bar[T]] = {\n DataView(f => new Bar(f.foo.cloneType), _.foo -> _.bar)\n // .cloneType is necessary because the f passed to this function will be bound hardware\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you think about type parameterized classes as really being a family of different classes\n(one for each type parameter), you can think about the ",(0,t.jsx)(n.code,{children:"implicit def"})," as a generator of ",(0,t.jsx)(n.code,{children:"DataViews"}),"\nfor each type parameter."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-create-a-dataview-for-a-bundle-with-optional-fields",children:"How do I create a DataView for a Bundle with optional fields?"}),"\n",(0,t.jsxs)(n.p,{children:["Instead of using the default ",(0,t.jsx)(n.code,{children:"DataView"})," apply method, use ",(0,t.jsx)(n.code,{children:"DataView.mapping"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\nclass Foo(val w: Option[Int]) extends Bundle {\n val foo = UInt(8.W)\n val opt = w.map(x => UInt(x.W))\n}\nclass Bar(val w: Option[Int]) extends Bundle {\n val bar = UInt(8.W)\n val opt = w.map(x => UInt(x.W))\n}\n\nobject Foo {\n implicit val view: DataView[Foo, Bar] =\n DataView.mapping(\n // First argument is always the function to make the view from the target\n f => new Bar(f.w),\n // Now instead of a varargs of tuples of individual mappings, we have a single function that\n // takes a target and a view and returns an Iterable of tuple\n (f, b) => List(f.foo -> b.bar) ++ f.opt.map(_ -> b.opt.get)\n // ^ Note that we can append options since they are Iterable!\n\n )\n}\n"})}),"\n",(0,t.jsx)(n.h2,{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:['Chisel 3 requires types to match exactly for connections.\nDataView provides a mechanism for "viewing" one ',(0,t.jsx)(n.code,{children:"Bundle"})," object as if it were the type of another,\nwhich allows them to be connected."]}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-view-a-bundle-as-a-parent-type-superclass",children:"How do I view a Bundle as a parent type (superclass)?"}),"\n",(0,t.jsxs)(n.p,{children:["For viewing ",(0,t.jsx)(n.code,{children:"Bundles"})," as the type of the parent, it is as simple as using ",(0,t.jsx)(n.code,{children:"viewAsSupertype"})," and providing a\ntemplate object of the parent type:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\nclass Foo extends Bundle {\n val foo = UInt(8.W)\n}\nclass Bar extends Foo {\n val bar = UInt(8.W)\n}\nclass MyModule extends Module {\n val foo = IO(Input(new Foo))\n val bar = IO(Output(new Bar))\n bar.viewAsSupertype(new Foo) := foo // bar.foo := foo.foo\n bar.bar := 123.U // all fields need to be connected\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule MyModule(\n input clock,\n reset,\n input [7:0] foo_foo,\n output [7:0] bar_foo,\n bar_bar\n);\n\n assign bar_foo = foo_foo;\n assign bar_bar = 8'h7B;\nendmodule\n\n"})}),"\n",(0,t.jsx)(n.h3,{id:"how-do-i-view-a-bundle-as-a-parent-type-when-the-parent-type-is-abstract-like-a-trait",children:"How do I view a Bundle as a parent type when the parent type is abstract (like a trait)?"}),"\n",(0,t.jsxs)(n.p,{children:["Given the following ",(0,t.jsx)(n.code,{children:"Bundles"})," that share a common ",(0,t.jsx)(n.code,{children:"trait"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\ntrait Super extends Bundle {\n def bitwidth: Int\n val a = UInt(bitwidth.W)\n}\nclass Foo(val bitwidth: Int) extends Super {\n val foo = UInt(8.W)\n}\nclass Bar(val bitwidth: Int) extends Super {\n val bar = UInt(8.W)\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Foo"})," and ",(0,t.jsx)(n.code,{children:"Bar"})," cannot be connected directly, but they could be connected by viewing them both as if\nthey were instances of their common supertype, ",(0,t.jsx)(n.code,{children:"Super"}),".\nA straightforward approach might run into an issue like the following:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class MyModule extends Module {\n val foo = IO(Input(new Foo(8)))\n val bar = IO(Output(new Bar(8)))\n bar.viewAsSupertype(new Super) := foo.viewAsSupertype(new Super)\n}\n// error: trait Super is abstract; cannot be instantiated\n// bar.viewAsSupertype(new Super) := foo.viewAsSupertype(new Super)\n// ^^^^^^^^^\n// error: trait Super is abstract; cannot be instantiated\n// bar.viewAsSupertype(new Super) := foo.viewAsSupertype(new Super)\n// ^^^^^^^^^\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The problem is that ",(0,t.jsx)(n.code,{children:"viewAs"})," requires an object to use as a type template (so that it can be cloned),\nbut ",(0,t.jsx)(n.code,{children:"traits"})," are abstract and cannot be instantiated.\nThe solution is to create an instance of an ",(0,t.jsx)(n.em,{children:"anonymous class"})," and use that object as the argument to ",(0,t.jsx)(n.code,{children:"viewAs"}),".\nWe can do this like so:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"class MyModule extends Module {\n val foo = IO(Input(new Foo(8)))\n val bar = IO(Output(new Bar(8)))\n val tpe = new Super { // Adding curly braces creates an anonymous class\n def bitwidth = 8 // We must implement any abstract methods\n }\n bar.viewAsSupertype(tpe) := foo.viewAsSupertype(tpe)\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["By adding curly braces after the name of the trait, we're telling Scala to create a new concrete\nsubclass of the trait, and create an instance of it.\nAs indicated in the comment, abstract methods must still be implemented.\nThis is the same that happens when one writes ",(0,t.jsx)(n.code,{children:"new Bundle {}"}),",\nthe curly braces create a new concrete subclass; however, because ",(0,t.jsx)(n.code,{children:"Bundle"})," has no abstract methods,\nthe contents of the body can be empty."]}),"\n",(0,t.jsxs)(n.h3,{id:"how-can-i-use-viewas-instead-of-viewassupertypetype",children:["How can I use ",(0,t.jsx)(n.code,{children:".viewAs"})," instead of ",(0,t.jsx)(n.code,{children:".viewAsSupertype(type)"}),"?"]}),"\n",(0,t.jsxs)(n.p,{children:["While ",(0,t.jsx)(n.code,{children:"viewAsSupertype"})," is helpful for one-off casts, the need to provide a type template object\neach time can be onerous.\nBecause of the subtyping relationship, you can use ",(0,t.jsx)(n.code,{children:"PartialDataView.supertype"})," to create a\n",(0,t.jsx)(n.code,{children:"DataView"})," from a Bundle type to a parent type by just providing the function to construct an\ninstance of the parent type from an instance of the child type.\nThe mapping of corresponding fields is automatically determined by Chisel to be the fields defined\nin the supertype."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.experimental.dataview._\n\nclass Foo(x: Int) extends Bundle {\n val foo = UInt(x.W)\n}\nclass Bar(val x: Int) extends Foo(x) {\n val bar = UInt(x.W)\n}\n// Define a DataView without having to specify the mapping!\nimplicit val view: DataView[Bar, Foo] = PartialDataView.supertype[Bar, Foo](b => new Foo(b.x))\n\nclass MyModule extends Module {\n val foo = IO(Input(new Foo(8)))\n val bar = IO(Output(new Bar(8)))\n bar.viewAs[Foo] := foo // bar.foo := foo.foo\n bar.bar := 123.U // all fields need to be connected\n}\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.99.2\nmodule MyModule(\n input clock,\n reset,\n input [7:0] foo_foo,\n output [7:0] bar_foo,\n bar_bar\n);\n\n assign bar_foo = foo_foo;\n assign bar_bar = 8'h7B;\nendmodule\n\n"})})]})}function p(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:()=>s});a(6540);var t=a(5195);const o={tableOfContentsInline:"tableOfContentsInline_prmo"};var i=a(4848);function s(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:s}=e;return(0,i.jsx)("div",{className:o.tableOfContentsInline,children:(0,i.jsx)(t.A,{toc:n,minHeadingLevel:a,maxHeadingLevel:s,className:"table-of-contents",linkClassName:null})})}},5195:(e,n,a)=>{a.d(n,{A:()=>m});var t=a(6540),o=a(6342);function i(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 s(e){let{toc:n,minHeadingLevel:a,maxHeadingLevel:t}=e;return n.flatMap((e=>{const n=s({toc:e.children,minHeadingLevel:a,maxHeadingLevel:t});return function(e){return e.level>=a&&e.level<=t}(e)?[{...e,children:n}]:n}))}function r(e){const n=e.getBoundingClientRect();return n.top===n.bottom?r(e.parentNode):n}function l(e,n){let{anchorTopOffset:a}=n;const t=e.find((e=>r(e).top>=a));if(t){return function(e){return e.top>0&&e.bottomBundle literals can be constructed via an experimental import:
import chisel3._
import chisel3.experimental.BundleLiterals._
class MyBundle extends Bundle {
val a = UInt(8.W)
val b = Bool()
}
class Example extends RawModule {
val out = IO(Output(new MyBundle))
out := (new MyBundle).Lit(_.a -> 8.U, _.b -> true.B)
}
// Generated by CIRCT firtool-1.99.2
module Example(
output [7:0] out_a,
output out_b
);
assign out_a = 8'h8;
assign out_b = 1'h1;
endmodule
// Generated by CIRCT firtool-1.100.0
module Example(
output [7:0] out_a,
output out_b
);
assign out_a = 8'h8;
assign out_b = 1'h1;
endmodule
Partial specification is allowed, which results in "invalidated fields" as
described in Unconnected Wires.
Note that this can be used with RegInit
to construct partially reset registers as
described in the Cookbook.
class Example2 extends RawModule {
val out = IO(Output(new MyBundle))
out := (new MyBundle).Lit(_.b -> true.B)
}
// Generated by CIRCT firtool-1.99.2
module Example2(
output [7:0] out_a,
output out_b
);
assign out_a = 8'h0;
assign out_b = 1'h1;
endmodule
// Generated by CIRCT firtool-1.100.0
module Example2(
output [7:0] out_a,
output out_b
);
assign out_a = 8'h0;
assign out_b = 1'h1;
endmodule
Bundle literals can also be nested arbitrarily.
class ChildBundle extends Bundle {
val foo = UInt(8.W)
}
class ParentBundle extends Bundle {
val a = UInt(8.W)
val b = new ChildBundle
}
class Example3 extends RawModule {
val out = IO(Output(new ParentBundle))
out := (new ParentBundle).Lit(_.a -> 123.U, _.b -> (new ChildBundle).Lit(_.foo -> 42.U))
}
// Generated by CIRCT firtool-1.99.2
module Example3(
output [7:0] out_a,
out_b_foo
);
assign out_a = 8'h7B;
assign out_b_foo = 8'h2A;
endmodule
// Generated by CIRCT firtool-1.100.0
module Example3(
output [7:0] out_a,
out_b_foo
);
assign out_a = 8'h7B;
assign out_b_foo = 8'h2A;
endmodule
Vec literals are very similar to Bundle literals and can be constructed via an experimental import. They can be constructed in two forms, with type and length inferred as in:
import chisel3._
import chisel3.experimental.VecLiterals._
class VecExample1 extends Module {
val out = IO(Output(Vec(2, UInt(4.W))))
out := Vec.Lit(0xa.U, 0xbb.U)
}
// Generated by CIRCT firtool-1.99.2
module VecExample1(
input clock,
reset,
output [3:0] out_0,
out_1
);
assign out_0 = 4'hA;
assign out_1 = 4'hB;
endmodule
// Generated by CIRCT firtool-1.100.0
module VecExample1(
input clock,
reset,
output [3:0] out_0,
out_1
);
assign out_0 = 4'hA;
assign out_1 = 4'hB;
endmodule
or explicitly as in:
import chisel3._
import chisel3.experimental.VecLiterals._
class VecExample1a extends Module {
val out = IO(Output(Vec(2, UInt(4.W))))
out := Vec(2, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U)
}
// Generated by CIRCT firtool-1.99.2
module VecExample1a(
input clock,
reset,
output [3:0] out_0,
out_1
);
assign out_0 = 4'h1;
assign out_1 = 4'h2;
endmodule
// Generated by CIRCT firtool-1.100.0
module VecExample1a(
input clock,
reset,
output [3:0] out_0,
out_1
);
assign out_0 = 4'h1;
assign out_1 = 4'h2;
endmodule
The following examples all use the explicit form.
With the explicit form partial specification is allowed, which results in
"invalidated fields" as described in Unconnected Wires.
Note that this can be used with RegInit
to construct partially reset registers as
described in the Cookbook.
class VecExample2 extends RawModule {
val out = IO(Output(Vec(4, UInt(4.W))))
out := Vec(4, UInt(4.W)).Lit(0 -> 1.U, 3 -> 7.U)
}
// Generated by CIRCT firtool-1.99.2
module VecExample2(
output [3:0] out_0,
out_1,
out_2,
out_3
);
assign out_0 = 4'h1;
assign out_1 = 4'h0;
assign out_2 = 4'h0;
assign out_3 = 4'h7;
endmodule
// Generated by CIRCT firtool-1.100.0
module VecExample2(
output [3:0] out_0,
out_1,
out_2,
out_3
);
assign out_0 = 4'h1;
assign out_1 = 4'h0;
assign out_2 = 4'h0;
assign out_3 = 4'h7;
endmodule
Registers can be initialized from Vec literals
class VecExample3 extends Module {
val out = IO(Output(Vec(4, UInt(8.W))))
val y = RegInit(
Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 1 -> 0xCD.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W))
)
out := y
}
// Generated by CIRCT firtool-1.99.2
module VecExample3(
input clock,
reset,
output [7:0] out_0,
out_1,
out_2,
out_3
);
assign out_0 = 8'hAB;
assign out_1 = 8'hCD;
assign out_2 = 8'hEF;
assign out_3 = 8'hFF;
endmodule
// Generated by CIRCT firtool-1.100.0
module VecExample3(
input clock,
reset,
output [7:0] out_0,
out_1,
out_2,
out_3
);
assign out_0 = 8'hAB;
assign out_1 = 8'hCD;
assign out_2 = 8'hEF;
assign out_3 = 8'hFF;
endmodule
Vec literals can also be nested arbitrarily.
class VecExample5 extends RawModule {
val out = IO(Output(Vec(2, new ChildBundle)))
out := Vec(2, new ChildBundle).Lit(
0 -> (new ChildBundle).Lit(_.foo -> 42.U),
1 -> (new ChildBundle).Lit(_.foo -> 7.U)
)
}
// Generated by CIRCT firtool-1.99.2
module VecExample5(
output [7:0] out_0_foo,
out_1_foo
);
assign out_0_foo = 8'h2A;
assign out_1_foo = 8'h7;
endmodule
// Generated by CIRCT firtool-1.100.0
module VecExample5(
output [7:0] out_0_foo,
out_1_foo
);
assign out_0_foo = 8'h2A;
assign out_1_foo = 8'h7;
endmodule
Memories can be initialized by generating inline readmemh
or readmemb
statements in the output Verilog.
In most cases, you can simply call IO
multiple times:
import chisel3._
class MyModule extends Module {
val in = IO(Input(UInt(8.W)))
val out = IO(Output(UInt(8.W)))
out := in +% 1.U
}
// Generated by CIRCT firtool-1.99.2
module MyModule(
input clock,
reset,
input [7:0] in,
output [7:0] out
);
assign out = in + 8'h1;
endmodule
// Generated by CIRCT firtool-1.100.0
module MyModule(
input clock,
reset,
input [7:0] in,
output [7:0] out
);
assign out = in + 8'h1;
endmodule
If you have a Bundle
from which you would like to create ports without the
normal val
prefix, you can use FlatIO
:
import chisel3._
class MyBundle extends Bundle {
val foo = Input(UInt(8.W))
val bar = Output(UInt(8.W))
}
class MyModule extends Module {
val io = FlatIO(new MyBundle)
io.bar := io.foo +% 1.U
}
Note that io_
is nowhere to be seen!
// Generated by CIRCT firtool-1.99.2
module MyModule(
input clock,
reset,
input [7:0] foo,
output [7:0] bar
);
assign bar = foo + 8'h1;
endmodule
// Generated by CIRCT firtool-1.100.0
module MyModule(
input clock,
reset,
input [7:0] foo,
output [7:0] bar
);
assign bar = foo + 8'h1;
endmodule
To change the clock or reset for a region of code, use withClock
, withReset
, or withClockAndReset
.
See Multiple Clock Domains for examples and details.
import chisel3._
class MyModule extends Module with ImplicitClock {
val gate = IO(Input(Bool()))
val in = IO(Input(UInt(8.W)))
val out = IO(Output(UInt(8.W)))
// We could just assign this to val implicitClock, but this allows us to give it a custom name
val gatedClock = (clock.asBool || gate).asClock
// The trait requires us to implement this method referring to the clock
// Note that this is a def, but the actual clock value must be assigned to a val
override protected def implicitClock = gatedClock
val r = Reg(UInt(8.W))
out := r
r := in
}
This gives the following Verilog:
-// Generated by CIRCT firtool-1.99.2
module MyModule(
input clock,
reset,
gate,
input [7:0] in,
output [7:0] out
);
wire gatedClock = clock | gate;
reg [7:0] r;
always @(posedge gatedClock)
r <= in;
assign out = r;
endmodule
// Generated by CIRCT firtool-1.100.0
module MyModule(
input clock,
reset,
gate,
input [7:0] in,
output [7:0] out
);
wire gatedClock = clock | gate;
reg [7:0] r;
always @(posedge gatedClock)
r <= in;
assign out = r;
endmodule
If you do not care about the name of the overriden clock, you can just assign it to val implicitClock
:
override protected val implicitClock = (clock.asBool || gate).asClock
ImplicitReset
works analogously to ImplicitClock
.
// Generated by CIRCT firtool-1.99.2
module CountBits(
input [3:0] bits,
output [2:0] countVector_0,
countVector_1,
countVector_2,
countVector_3
);
// Generated by CIRCT firtool-1.100.0
module CountBits(
input [3:0] bits,
output [2:0] countVector_0,
countVector_1,
countVector_2,
countVector_3
);
Chisel will warn if a dynamic index is not the correctly-sized width for indexing a Vec or UInt. "Correctly-sized" means that the width of the index should be the log2 of the size of the indexee. @@ -205,22 +205,22 @@
import chisel3._
class Foo extends Module {
val io = IO(new Bundle {
val in = Input(Vec(4, Bool()))
val idx = Input(UInt(2.W))
val en = Input(Bool())
val out = Output(Bool())
})
val x = io.in(io.idx)
val y = x && io.en
io.out := y
}
The above code loses the x
name, instead using _GEN_3
(the other _GEN_*
signals are expected).
// Generated by CIRCT firtool-1.99.2
module Foo(
input clock,
reset,
io_in_0,
io_in_1,
io_in_2,
io_in_3,
input [1:0] io_idx,
input io_en,
output io_out
);
wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}};
assign io_out = _GEN[io_idx] & io_en;
endmodule
// Generated by CIRCT firtool-1.100.0
module Foo(
input clock,
reset,
io_in_0,
io_in_1,
io_in_2,
io_in_3,
input [1:0] io_idx,
input io_en,
output io_out
);
wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}};
assign io_out = _GEN[io_idx] & io_en;
endmodule
This can be worked around by creating a wire and connecting the dynamic index to the wire:
val x = WireInit(io.in(io.idx))
Which produces:
-// Generated by CIRCT firtool-1.99.2
module Foo2(
input clock,
reset,
io_in_0,
io_in_1,
io_in_2,
io_in_3,
input [1:0] io_idx,
input io_en,
output io_out
);
wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}};
assign io_out = _GEN[io_idx] & io_en;
endmodule
// Generated by CIRCT firtool-1.100.0
module Foo2(
input clock,
reset,
io_in_0,
io_in_1,
io_in_2,
io_in_3,
input [1:0] io_idx,
input io_en,
output io_out
);
wire [3:0] _GEN = {{io_in_3}, {io_in_2}, {io_in_1}, {io_in_0}};
assign io_out = _GEN[io_idx] & io_en;
endmodule
You can override the desiredName
function. This works with normal Chisel modules and BlackBox
es. Example:
import chisel3._
class Coffee extends BlackBox {
val io = IO(new Bundle {
val I = Input(UInt(32.W))
val O = Output(UInt(32.W))
})
override def desiredName = "Tea"
}
class Salt extends Module {
val io = IO(new Bundle {})
val drink = Module(new Coffee)
override def desiredName = "SodiumMonochloride"
drink.io.I := 42.U
}
Elaborating the Chisel module Salt
yields our "desired names" for Salt
and Coffee
in the output Verilog:
// Generated by CIRCT firtool-1.99.2
module SodiumMonochloride(
input clock,
reset
);
Tea drink (
.I (32'h2A),
.O (/* unused */)
);
endmodule
// Generated by CIRCT firtool-1.100.0
module SodiumMonochloride(
input clock,
reset
);
Tea drink (
.I (32'h2A),
.O (/* unused */)
);
endmodule
Given a bidirectional port like a Decoupled
, you will get an error if you try to connect it directly
to a register:
import chisel3._
import chisel3.util.Decoupled
class BadRegConnect extends Module {
val io = IO(new Bundle {
val enq = Decoupled(UInt(8.W))
})
val monitor = Reg(chiselTypeOf(io.enq))
monitor := io.enq
}
getVerilogString(new BadRegConnect)
// circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: /home/runner/.cache/llvm-firtool/1.99.2/bin/firtool returned a non-zero exit code. Note that this version of Chisel (7.0.0-M2+285-e12935ed-SNAPSHOT) was published against firtool version 1.99.2.
// ------------------------------------------------------------------------------
// ExitCode:
// 1
// STDOUT:
//
// STDERR:
// cookbook.md:1039: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:1039: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.100.0/bin/firtool returned a non-zero exit code. Note that this version of Chisel (7.0.0-M2+286-ba4e01c3-SNAPSHOT) was published against firtool version 1.100.0.
// ------------------------------------------------------------------------------
// ExitCode:
// 1
// STDOUT:
//
// STDERR:
// cookbook.md:1039: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:1039: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 0128c7e12a1..8306db71e08 100644
--- a/docs/cookbooks/dataview.html
+++ b/docs/cookbooks/dataview.html
@@ -9,7 +9,7 @@
-
+
import chisel3._
import chisel3.experimental.dataview._
class Foo extends Bundle {
val foo = UInt(8.W)
}
class Bar extends Foo {
val bar = UInt(8.W)
}
class MyModule extends Module {
val foo = IO(Input(new Foo))
val bar = IO(Output(new Bar))
bar.viewAsSupertype(new Foo) := foo // bar.foo := foo.foo
bar.bar := 123.U // all fields need to be connected
}
// Generated by CIRCT firtool-1.99.2
module MyModule(
input clock,
reset,
input [7:0] foo_foo,
output [7:0] bar_foo,
bar_bar
);
assign bar_foo = foo_foo;
assign bar_bar = 8'h7B;
endmodule
// Generated by CIRCT firtool-1.100.0
module MyModule(
input clock,
reset,
input [7:0] foo_foo,
output [7:0] bar_foo,
bar_bar
);
assign bar_foo = foo_foo;
assign bar_bar = 8'h7B;
endmodule
Given the following Bundles
that share a common trait
:
import chisel3._
import chisel3.experimental.dataview._
trait Super extends Bundle {
def bitwidth: Int
val a = UInt(bitwidth.W)
}
class Foo(val bitwidth: Int) extends Super {
val foo = UInt(8.W)
}
class Bar(val bitwidth: Int) extends Super {
val bar = UInt(8.W)
}
import chisel3._
import chisel3.experimental.dataview._
class Foo(x: Int) extends Bundle {
val foo = UInt(x.W)
}
class Bar(val x: Int) extends Foo(x) {
val bar = UInt(x.W)
}
// Define a DataView without having to specify the mapping!
implicit val view: DataView[Bar, Foo] = PartialDataView.supertype[Bar, Foo](b => new Foo(b.x))
class MyModule extends Module {
val foo = IO(Input(new Foo(8)))
val bar = IO(Output(new Bar(8)))
bar.viewAs[Foo] := foo // bar.foo := foo.foo
bar.bar := 123.U // all fields need to be connected
}
// Generated by CIRCT firtool-1.99.2
module MyModule(
input clock,
reset,
input [7:0] foo_foo,
output [7:0] bar_foo,
bar_bar
);
assign bar_foo = foo_foo;
assign bar_bar = 8'h7B;
endmodule
// Generated by CIRCT firtool-1.100.0
module MyModule(
input clock,
reset,
input [7:0] foo_foo,
output [7:0] bar_foo,
bar_bar
);
assign bar_foo = foo_foo;
assign bar_bar = 8'h7B;
endmodule