1"use strict";(globalThis.webpackChunkchisel_lang=globalThis.webpackChunkchisel_lang||[]).push([[3867],{2218(e,n,r){r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>t,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"explanations/probes","title":"Probes","description":"Probes are a way to encode a reference to hardware that will be later","source":"@site/docs/explanations/probes.md","sourceDirName":"explanations","slug":"/explanations/probes","permalink":"/docs/explanations/probes","draft":false,"unlisted":false,"editUrl":"https://github.com/chipsalliance/chisel/tree/main/docs/src/explanations/probes.md","tags":[],"version":"current","frontMatter":{"layout":"docs","title":"Probes","section":"chisel3"},"sidebar":"chiselSidebar","previous":{"title":"Printing","permalink":"/docs/explanations/printing"},"next":{"title":"Properties","permalink":"/docs/explanations/properties"}}');var a=r(4848),i=r(8453);const t={layout:"docs",title:"Probes",section:"chisel3"},s="Probes",l={},d=[{value:"Overview",id:"overview",level:2},{value:"Read Probes",id:"read-probes",level:3},{value:"Read--write Probes",id:"read--write-probes",level:3},{value:"Verilog ABI",id:"verilog-abi",level:2},{value:"Layer-colored Probes",id:"layer-colored-probes",level:2},{value:"Why Input Probes are Not Allowed",id:"why-input-probes-are-not-allowed",level:2},{value:"BoringUtils",id:"boringutils",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"probes",children:"Probes"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.em,{children:"Probes"})," are a way to encode a ",(0,a.jsx)(n.em,{children:"reference"})," to hardware that will be later\nreferred to by-name. Mechanistically, probes are a way to genereate\nSystemVerilog which includes hierarchical names (see: Section 23.6 of the\nSystemVerilog 2023 specification)."]}),"\n",(0,a.jsxs)(n.p,{children:['Probes are typically used to expose a "verification interface" to a unit for\ndebugging, testing, or inspection without adding ports to the final hardware.\nWhen combined with ',(0,a.jsx)(n.a,{href:"layers",children:"layers"}),', they may be "layer-colored" and optionally\nexist in a design based on Verilog compilation-time decisions.']}),"\n",(0,a.jsx)(n.admonition,{type:"warning",children:(0,a.jsxs)(n.p,{children:["Probes are ",(0,a.jsx)(n.em,{children:"not"})," shadow dataflow. They are ",(0,a.jsx)(n.em,{children:"not"}),' a mechanism to connect\narbitrary hardware while avoiding ports. They are closer to "references" in a\ntraditional programming language, except that they have extra restrictions.\nNamely, a probe will eventually be accessed by-name and that name must, at its\naccess site, resolve to the probed value unambiguously.']})}),"\n",(0,a.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,a.jsxs)(n.p,{children:["There are two kinds of probes based on the type of access that a user wants to\nhave to a piece of hardware. A ",(0,a.jsx)(n.em,{children:"read probe"})," allows for read-only access to\nhardware. A ",(0,a.jsx)(n.em,{children:"read--write probe"})," allows for both read and write access."]}),"\n",(0,a.jsx)(n.p,{children:'Read probes are typically used for passive verification (e.g., assertions or\nmonitors) or debugging (e.g., building an architectural debug "view" of a\nmicroarchitecture). Read--write probes are typically used for more active\nverification (e.g., injecting faults to test fault recovery mechanisms or as a\nmeans of closing difficult to reach coverage).'}),"\n",(0,a.jsxs)(n.p,{children:["APIs for working with probes are in the ",(0,a.jsx)(n.code,{children:"chisel3.probe"})," package."]}),"\n",(0,a.jsx)(n.h3,{id:"read-probes",children:"Read Probes"}),"\n",(0,a.jsxs)(n.p,{children:["To create a read probe of a hardware value, use the ",(0,a.jsx)(n.code,{children:"ProbeValue"})," API. To create\na read probe ",(0,a.jsx)(n.em,{children:"type"}),", use the ",(0,a.jsx)(n.code,{children:"Probe"})," API. Probes are legal types for ports and\nwires, but not for stateful elements (e.g., registers or memories)."]}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsx)(n.p,{children:'It may be surprising the a probe is a legal type for a wire. However, wires in\nChisel behave more like variables than they do like "hardware wires" (or Verilog\nnet types). With this view, it is natural that a probe (a reference) may be\npassed through a variable.'})}),"\n",(0,a.jsxs)(n.p,{children:['Probes are different from normal Chisel hardware types. Whereas normal Chisel\nhardware may be connected to multiple times with the last connection "winning"\nvia so-called "last-connect semantics", probe types may only be ',(0,a.jsx)(n.em,{children:"defined"}),"\nexactly once. The API to define a probe is, unsurprisingly, called ",(0,a.jsx)(n.code,{children:"define"}),'.\nThis is used to "forward" a probe up through the hierarchy, e.g., to define a\nprobe port with the probed value of a wire.']}),"\n",(0,a.jsxs)(n.p,{children:["For convenience, you may alternatively use the standard Chisel connection\noperators which will, under-the-hood, use the ",(0,a.jsx)(n.code,{children:"define"})," operator automatically\nfor you."]}),"\n",(0,a.jsxs)(n.p,{children:["To read the value of a probe type, use the ",(0,a.jsx)(n.code,{children:"read"})," API."]}),"\n",(0,a.jsxs)(n.p,{children:["The following example shows a circuit that uses all of the APIs introduced\npreviously. Both ",(0,a.jsx)(n.code,{children:"define"})," and standard Chisel connection operators are shown.\nCareful use of ",(0,a.jsx)(n.code,{children:"dontTouch"})," is used to prevent optimization across probes so that\nthe output is not trivially simple."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scala",children:"import
1chisel3._\nimport chisel3.probe.{Probe, ProbeValue, define, read}\n\nclass Bar extends RawModule {\n val a_port = IO(Probe(Bool()))\n val b_port = IO(Probe(Bool()))\n\n private val a = dontTouch(WireInit(Bool(), true.B))\n private val a_probe = ProbeValue(a)\n define(a_port, a_probe)\n b_port :<= a_probe\n}\n\nclass Foo extends RawModule {\n\n private val bar = Module(new Bar)\n\n private val a_read = dontTouch(WireInit(read(bar.a_port)))\n private val b_read = dontTouch(WireInit(read(bar.b_port)))\n}\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"The SystemVerilog for the above circuit is shown below:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.160.0\nmodule Bar();\n wire a = 1'h1;\nendmodule\n\nmodule Foo();\n wire a_read = Foo.bar.a;\n wire b_read = Foo.bar.a;\n Bar bar ();\nendmodule\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"There are several things that are worth highlighting in the above SystemVerilog:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["The wires ",(0,a.jsx)(n.code,{children:"a_read"})," and ",(0,a.jsx)(n.code,{children:"b_read"})," are driven with ",(0,a.jsx)(n.em,{children:"hierarchical names"})," that\nreach into module ",(0,a.jsx)(n.code,{children:"Bar"}),". There are ",(0,a.jsx)(n.em,{children:"no ports"})," created on module ",(0,a.jsx)(n.code,{children:"Bar"}),". This\nis intended to support design verification use cases where certain signals\nare made available from ",(0,a.jsx)(n.code,{children:"Bar"})," via probe ports that are then used to, e.g.,\nconnect to assertions, monitors, or verification intellectual property (IP).\nIf hardware ports were used this would change the interface of the design\nunfavorably."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Observability, via probes, is not free. While the above circuit is contrived\nin its simplicity, if hardware is probed, that may limit the ability of the\ncompiler to optimize that hardware. Read probes are generally more amenable\nto optimization than read--write probes. However, they still have effects."}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"read--write-probes",children:"Read--write Probes"}),"\n",(0,a.jsxs)(n.p,{children:["To create a read--write probe of a hardware value, use the ",(0,a.jsx)(n.code,{children:"RWProbeValue"})," API.\nTo create a read--write probe ",(0,a.jsx)(n.em,{children:"type"}),", use the ",(0,a.jsx)(n.code,{children:"RWProbe"})," API. As with read\nprobes, read--write probes are legal types for ports and wires, but not for\nstateful elements (e.g., registers or memories)."]}),"\n",(0,a.jsxs)(n.p,{children:["As with read probes, read--write probes forward references using the ",(0,a.jsx)(n.code,{children:"define"}),"\nAPI or the standard Chisel connection operators."]}),"\n",(0,a.jsxs)(n.p,{children:["A read--write probe can be read using the same ",(0,a.jsx)(n.code,{children:"read"})," API that is used for read\nprobes. Multiple different operations are provided for writing to a read--write\nprobe. The ",(0,a.jsx)(n.code,{children:"force"})," and ",(0,a.jsx)(n.code,{children:"forceInitial"})," APIs are used to overwrite the value of\nread--write probed hardware. The ",(0,a.jsx)(n.code,{children:"release"})," and ",(0,a.jsx)(n.code,{children:"releaseInitial"})," APIs are used\nto stop overwriting a read--write probed hardware value."]}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:["All writing of read--write probes is done through APIs which lower to System\nVerilog ",(0,a.jsx)(n.code,{children:"force"}),"/",(0,a.jsx)(n.code,{children:"release"})," statements (see: Section 10.6 of the SystemVerilog\n2023 specification). It is intentionally not possible to use normal Chisel\nconnects to write to read--write probes. Put differently, read--write probes do\n",(0,a.jsx)(n.em,{children:"not"})," participate in last-connect semantics."]})}),"\n",(0,a.jsxs)(n.p,{children:["The following example shows a circuit that uses all of the APIs introduced\npreviously. Both ",(0,a.jsx)(n.code,{children:"define"})," and standard Chisel connection operators are shown.\nCareful use of ",(0,a.jsx)(n.code,{children:"dontTouch"})," is used to prevent optimization across probes so that\nthe output is not trivially simple."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scala",children:"import
1chisel3._\nimport chisel3.probe.{RWProbe, RWProbeValue, force, forceInitial, read, release, releaseInitial}\n\nclass Bar extends RawModule {\n val a_port = IO(RWProbe(Bool()))\n val b_port = IO(RWProbe(UInt(8.W)))\n\n private val a = WireInit(Bool(), true.B)\n a_port :<= RWProbeValue(a)\n\n private val b = WireInit(UInt(8.W), 0.U)\n b_port :<= RWProbeValue(b)\n}\n\nclass Foo extends Module {\n val cond = IO(Input(Bool()))\n\n private val bar = Module(new Bar)\n\n // Example usage of forceInitial/releaseInitial:\n forceInitial(bar.a_port, false.B)\n releaseInitial(bar.a_port)\n\n // Example usage of force/release:\n when (cond) {\n force(bar.b_port, 42.U)\n }.otherwise {\n release(bar.b_port)\n }\n\n // The read API may still be used:\n private val a_read = dontTouch(WireInit(read(bar.a_port)))\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"The SystemVerilog for the above circuit is shown below:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.160.0\nmodule Bar();\n wire a = 1'h1;\n wire [7:0] b = 8'h0;\nendmodule\n\nmodule Foo(\n input clock,\n reset,\n cond\n);\n\n reg hasBeenResetReg;\n reg hasBeenResetReg_0;\n initial begin\n hasBeenResetReg = 1'bx;\n hasBeenResetReg_0 = 1'bx;\n end // initial\n always @(posedge clock) begin\n if (reset) begin\n hasBeenResetReg <= 1'h1;\n hasBeenResetReg_0 <= 1'h1;\n end\n end // always @(posedge)\n `ifndef SYNTHESIS\n initial begin\n force Foo.bar.a = 1'h0;\n release Foo.bar.a;\n end // initial\n always @(posedge clock) begin\n automatic logic _GEN = reset === 1'h0;\n if (cond & hasBeenResetReg === 1'h1 & _GEN)\n force Foo.bar.b = 8'h2A;\n if (~cond & hasBeenResetReg_0 === 1'h1 & _GEN)\n release Foo.bar.b;\n end // always @(posedge)\n `endif // not def SYNTHESIS\n wire a_read = Foo.bar.a;\n Bar bar ();\nendmodule\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"Several things are worth commenting on in the above SystemVerilog:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Writability is very invasive. In order to compile a write probe, all\noptimizations on its target must be blocked and any optimizations ",(0,a.jsx)(n.em,{children:"through"}),"\nthe target are not possible. This is because any writes to a read--write\nprobe must affect downstream users."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["The APIs for writing to read--write probes (e.g., ",(0,a.jsx)(n.code,{children:"force"}),") are extremely\nlow-level and very tightly coupled to SystemVerilog. Take great care when\nusing these APIs and validating that the resulting SystemVerilog does what\nyou want."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.admonition,{type:"warning",children:(0,a.jsx)(n.p,{children:"Not all simulators correctly implement force and release as described in the\nSystemVerilog spec! Be careful when using read--write probes. You may need to\nuse a SystemVerilog-compliant simulator."})}),"\n",(0,a.jsx)(n.h2,{id:"verilog-abi",children:"Verilog ABI"}),"\n",(0,a.jsx)(n.p,{children:"Earlier examples only show probes being used internal to a circuit. However,\nprobes also compile to SystemVerilog in such a way that they are usable external\nto the circuit."}),"\n",(0,a.jsx)(n.p,{children:"Consider the following example circuit. In this, an internal register's value\nis exposed via a read probe."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.probe.{Probe, ProbeValue}\n\nclass Foo extends Module {\n\n val d = IO(Input(UInt(32.W)))\n val q = IO(Output(UInt(32.W)))\n val r_probe = IO(Output(Probe(UInt(32.W))))\n\n private val r = Reg(UInt(32.W))\n\n q :<= r\n\n r_probe :<= ProbeValue(r)\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"The SystemVerilog for the above circuit is shown below:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-verilog",children:'// Generated by CIRCT firtool-1.160.0\nmodule Foo(\n input clock,\n reset,\n input [31:0] d,\n output [31:0] q\n);\n\n wire [31:0] _GEN = 32\'h0;\n assign q = _GEN;\nendmodule\n\n\n// ----- 8< ----- FILE "ref_Foo.sv" ----- 8< -----\n\n// Generated by CIRCT firtool-1.160.0\n`define ref_Foo_r_probe _GEN\n'})}),"\n",(0,a.jsxs)(n.p,{children:["As part of the compilation, this is guaranteed to produce an additional file for\neach public module with a specific filename: ",(0,a.jsx)(n.code,{children:"ref_<module-name>.sv"}),". In this\nfile, there will be one SystemVerilog text macro definition for each probe port\nof that public module. The define will have a text macro name derived from the\nmodule name and the probe port name: ",(0,a.jsx)(n.code,{children:"ref_<module-name>_<probe-name>"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"Using this ABI, the module may be instantiated elsewhere (e.g., by a\nSystemVerilog testbench) and its probed internals accessed."}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:["For the exact definition of the port lowering ABI for probes, see the ",(0,a.jsx)(n.a,{href:"https://github.com/chipsalliance/firrtl-spec/releases/latest/download/abi.pdf",children:"FIRRTL\nABI\nSpecification"}),"."]})}),"\n",(0,a.jsx)(n.h2,{id:"layer-colored-probes",children:"Layer-colored Probes"}),"\n",(0,a.jsxs)(n.p,{children:["Probes are allowed to be layer-colored. I.e., this is a mechanism to declare\nthat a probe's existence is contingent on a specific layer being enabled. To\ndeclare a probe as being layer-colored, the ",(0,a.jsx)(n.code,{children:"Probe"})," or ",(0,a.jsx)(n.code,{children:"RWProbe"})," type takes an\noptional argument indicating what the layer coloring is. The following example\ndecalres two probe ports with different layer colors:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scala",children:"import
1chisel3._\nimport chisel3.layer.{Layer, LayerConfig}\nimport chisel3.probe.{Probe, ProbeValue}\n\nobject A extends Layer(LayerConfig.Extract())\nobject B extends Layer(LayerConfig.Extract())\n\nclass Foo extends Module {\n val a = IO(Output(Probe(Bool(), A)))\n val b = IO(Output(Probe(UInt(8.W), B)))\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["For more information on layer-colored probes see ",(0,a.jsx)(n.a,{href:"layers#layer-colored-probes-and-wires",children:"the appropriate subsection of\nthe layers documentation"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"why-input-probes-are-not-allowed",children:"Why Input Probes are Not Allowed"}),"\n",(0,a.jsx)(n.p,{children:"Input probes (of either read or read--write kind) are disallowed. This is an\nintentional decision that stems from requirements of both what probes are and\nhow probes can be compiled to SystemVerilog."}),"\n",(0,a.jsx)(n.p,{children:'First, probes are references. They refer to hardware which exists somewhere\nelse. They are not hardware wires. They are not "shadow" ports. They do not\nrepresent "shadow" dataflow.'}),"\n",(0,a.jsx)(n.p,{children:"Second, a probe always comes with two pieces: the actual probed hardware and the\noperation which uses the reference to the probed hardware. The operation that\nuses the probe must, at its specific location, be able to refer unambiguously to\nthe probed hardware. As the example below will show, this is problematic with\ninput probes."}),"\n",(0,a.jsx)(n.p,{children:"Consider the following illegal Chisel which uses hypothetical input probes:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.probe.{Probe, ProbeValue, read}\n\nmodule Baz extends RawModule {\n val probe = IO(Input(Probe(Bool())))\n\n val b = WireInit(read(probe))\n}\n\nmodule Bar extends RawModule {\n val probe = IO(Input(Probe(Bool())))\n\n val baz = Module(new Baz)\n baz.probe :<= probe\n\n}\n\nmodule Foo extends RawModule {\n\n val w = Wire(Bool())\n\n val bar = Module(new Bar)\n bar.probe :<= ProbeValue(w)\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"This could be compiled to the following SystemVerilog:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-verilog",children:"module Baz();\n\n wire b = Foo.a;\n\nendmodule\n\nmodule Bar();\n\n Baz baz();\n\nendmodule\n\nmodule Foo();\n\n wire a;\n\n Bar bar();\n\nendmodule\n"})}),"\n",(0,a.jsxs)(n.p,{children:["SystemVerilog provides an algorithm for resolving ",(0,a.jsx)(n.em,{children:"upwards"})," hierarchical names\n(see: Section 23.8 of the SystemVerilog 2023 specification). This works by\nlooking in the current scope for a match for the root of the name (",(0,a.jsx)(n.code,{children:"Foo"}),") and if\nit fails, it moves up one level and tries to look aagin. This then repeats\nuntil a name is found (or errors if the top of the circuit is reached).\nHowever, this algorithm places harsh naming constraints on intermediary modules.\nE.g., in the example above, no name ",(0,a.jsx)(n.code,{children:"Foo"})," can exist in ",(0,a.jsx)(n.code,{children:"Baz"})," or in an\n",(0,a.jsx)(n.em,{children:"intervening"})," modules between ",(0,a.jsx)(n.code,{children:"Baz"})," and ",(0,a.jsx)(n.code,{children:"Foo"}),". This can easily run afoul of\nnames which cannot be changed, e.g., public modules or public module ports."]}),"\n",(0,a.jsxs)(n.p,{children:["Additionally, any use of a hierarchical name that resolves upwards means that\nthe module that uses that upwards reference is limited in its ability to be\nfreely instantiated. In the circuit above, ",(0,a.jsx)(n.code,{children:"Baz"})," is singly instantiated.\nHowever, if ",(0,a.jsx)(n.code,{children:"Baz"})," was multiply instantiated, it could be given two different\ninput probes. This would mean that ",(0,a.jsx)(n.code,{children:"Baz"})," could ",(0,a.jsx)(n.em,{children:"not"})," be compiled to a single\nVerilog module. It must be duplicated for each unique hierarchical name that it\ncontains. This can have cascading duplication effects where parent modules,\ntheir parents, etc. must be duplicated. The unpredictability of this is not\nviewed as tolerable by users."]}),"\n",(0,a.jsx)(n.p,{children:"Both of these constraints (the constraints on names in intevening modules and\nduplication to resolve hierarchical names) make the use of input probes\nproblematic. While they could be compiled, the results will be unpredictable\nand difficult for a user to debug when things go wrong."}),"\n",(0,a.jsx)(n.p,{children:"Due to these problems, input probes were rejected as a design point and are not\nplanned to be implemented."}),"\n",(0,a.jsx)(n.h2,{id:"boringutils",children:"BoringUtils"}),"\n",(0,a.jsx)(n.p,{children:"Probes are an intentionally a low-level API. E.g., if a design needs to expose\na probe port, it may need to add probe ports to all intervening modules between\nit and a probed value."}
1),"\n",(0,a.jsxs)(n.p,{children:["For a more flexible API, consider using ",(0,a.jsx)(n.code,{children:"chisel3.util.experimental.BoringUtils"}),".\nThis provides higher-level APIs that automatically create probe ports for the\nuser:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"rwTap"}),": creates a read--write probe of a signal and routes it to the call\nsite"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"tap"}),": creates a read probe of a signal and routes it to the call site"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"tapAndRead"}),": `creates a read probe of a signal, routes it to the call site,\nand reads it (converts from probe to real hardware)"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["E.g., consider the original example shown for read probes. This can be\nrewritten using ",(0,a.jsx)(n.code,{children:"BoringUtils"})," to be more terse:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scala",children:"import chisel3._\nimport chisel3.util.experimental.BoringUtils\n\nclass Bar extends RawModule {\n val a = dontTouch(WireInit(Bool(), true.B))\n}\n\nclass Foo extends RawModule {\n\n private val bar = Module(new Bar)\n\n private val a_read = dontTouch(WireInit(BoringUtils.tapAndRead(bar.a)))\n}\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"The SystemVerilog for the above circuit is shown below:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-verilog",children:"// Generated by CIRCT firtool-1.160.0\nmodule Bar();\n wire a = 1'h1;\nendmodule\n\nmodule Foo();\n wire a_read = Foo.bar.a;\n Bar bar ();\nendmodule\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"In order to do this, it requires that the tapped target is public from Scala's\nperspective."}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"BoringUtils"})," is only suitable for use ",(0,a.jsx)(n.em,{children:"within"})," a compilation unit.\nAdditionally, excessive use of ",(0,a.jsx)(n.code,{children:"BoringUtils"})," can result in very confusing\nhardware generators where the port-level interfaces are unpredictable."]})}),"\n",(0,a.jsxs)(n.p,{children:["If a ",(0,a.jsx)(n.code,{children:"BoringUtils"})," API is used in a situation which would create an input probe,\nit will instead create a non-probe input port."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453(e,n,r){r.d(n,{R:()=>t,x:()=>s});var o=r(6540);const a={},i=o.createContext(a);function t(e){const n=o.useContext(i);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:t(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.