diff --git a/abi.md b/abi.md index 992bcfe..6aded74 100644 --- a/abi.md +++ b/abi.md @@ -131,24 +131,33 @@ Reference types in ports shall be logically split out from aggregates and named ## On Layers -The lowering convention of a declared layer specifies how a layer and all its associated layer blocks will be lowered. -Currently, the only lowering convention that must be supported is `"bind"`{.firrtl.}. +The lowering convention of a layer specifies how the functionality contained within its associated layer block will both be represented after compilation and the mechanism to enable the functionality. +There are two standard lowering conventions: + +1. The `bind`{.firrtl} convention will "extract" layer blocks from the circuit into modules that are instantiated via SystemVerilog's `bind`{.verilog} feature (Section 23.11 of IEEE 1800-2023). + Functionality is enabled by including a file during compilation. +2. The `inline`{.firrtl} convention lowers the layer blocks to `` `ifdef ``{.verilog}-guarded regions (Section 23.6 of IEEE 1800-2023). + Functionality is enabled by defining a macro during Verilog elaboration. + FIRRTL compilers may implement other non-standard lowering conventions. ### Bind Lowering Convention -The bind lowering convention is indicated by the `"bind"`{.firrtl} string on a declared layer. -When using this convention, layer blocks associated with that layer are lowered to separate modules that are instantiated via SystemVerilog `bind`{.verilog} statements ("bind instantiation"). +The bind lowering convention is indicated by the `bind`{.firrtl} string on a declared layer. +When using this convention, the functionality contained within layer blocks will be converted to FIRRTL modules. +These modules are then instantiated via SystemVerilog `bind`{.verilog} statements ("bind instantiation"). -Each module that contains layer blocks will produce one additional module per layer block that has "internal" module convention. -I.e., the modules are private and have no defined ABI---the name of each module is implementation defined, the instantiation name of a bound instance is implementation defined, and any ports created on the module may have any name and may be optimized away. +The bind lowering convention is intended to be used in situations where layer functionality must be removed from the design. +E.g., bind layers can be used to remove verification code for more succinct Verilog presentation or to prevent it from being included in a release of design Intellectual Property (IP). + +The number, instantiation location, name, ports, and port names of these modules is implementation defined. +(While it is a legal compilation to produce one module for each layerblock in a module, a compiler is free to optimize layer blocks in any way that it sees fit so long as the functionality of the layer blocks is unchanged.) Practically speaking, additional ports of each generated module must be created whenever a value defined outside the layer block is used inside the layer block. The values captured by the layer block will create input ports. Values defined in a layer block and used by a nested layer block will create output ports because SystemVerilog disallows the use of a bind instantiation underneath the scope of another bind instantiation. -The names of additional ports are implementation defined. -For each layer and public module, one binding file will be produced for each layer or nested layer. +For each layer and public module, one binding file must be produced for each layer or nested layer. The public module, layer name, and any nested layer names are used to derive a predictable filename of the binding file. The file format uses the format below where `module` is the name of the public module, `root` is the name of the root-level layer and `nested` is the name of zero or more nested layers: @@ -311,6 +320,47 @@ bind Bar Bar_Layer1_Layer2 layer1_layer2(.notA(Bar.layer1.notA)); The `` `ifdef ``{.verilog} guards enable any combination of the bind files to be included while still producing legal SystemVerilog. I.e., the end user may safely include none, either, or both of the bindings files. +### Inline Lowering Convention + +The inline lowering convention is indicated by the `inline`{.firrtl} string on a declared layer. +When using this convention, the functionality contained within layer blocks will be included *inline* in the final circuit, but will be guarded behind conditional compilation compiler directives, e.g., `` `ifdef ``{.verilog}. + +The number and location of conditional compilation compiler directive code regions is implementation defined. + +To enable the functionality for all layer blocks under a public module, a user should set a preprocessor define during Verilog compilation to enable the conditional compilation compiler directives. +The define uses the format below where `module` is the name of the public module, `root` is the name of the root-level layer and `nested` is the name of zero or more nested layers: + +``` ebnf +define = "layer_" , module , "$" , root , { "$" , nested } ; +``` + +If an inline layer is nested under a bind layer, the name of the bind layer should be included in the define. + +As an example, consider the following circuit with one bind layer and two inline layers: + +``` firrtl +FIRRTL version 4.0.0 +circuit Bar: + layer Layer1, bind: + layer Layer2, inline: + layer Layer3, inline: + public module Bar: + public module Baz: +``` + +When compiled to Verilog, this creates two Verilog modules. +Verilog module `Bar` will be sensitive to the following defines: + + layer_Bar$Layer1$Layer2 + layer_Bar$Layer1$Layer2$Layer3 + +Verilog module `Baz` will be sensitive to the following defines: + + layer_Baz$Layer1$Layer2 + layer_Baz$Layer1$Layer2$Layer3 + +The effect of enabling a child inline layer *does not* enable its parent layers. + ## On Types Types are only guaranteed to follow this lowering when the Verilog type is on an element which is part of the ABI defined public elements. diff --git a/revision-history.yaml b/revision-history.yaml index 2232780..8d187be 100644 --- a/revision-history.yaml +++ b/revision-history.yaml @@ -5,7 +5,9 @@ revisionHistory: # additions to the specification should append entries here. thisVersion: spec: + - Add a second standard layer convention, "inline". abi: + - Add inline layer convention ABI. # Information about the old versions. This should be static. oldVersions: - version: 4.0.0 diff --git a/spec.md b/spec.md index d43d242..edcc88b 100644 --- a/spec.md +++ b/spec.md @@ -241,12 +241,18 @@ A layer may be declared in a circuit or in another layer declaration. A layer's identifier must be unique within the current namespace. I.e., the identifier of a top-level layer declared in a circuit must not conflict with the identifier of a module, external module, or implementation defined module. -Layers may be nested. +Layers may be nested, with the exceptions of convention constraints described below. Nested layers are declared with the `layer`{.firrtl} keyword indented under an existing `layer`{.firrtl} keyword. -Each layer must include a string that sets the lowering convention for that layer. -The FIRRTL ABI specification defines supported lowering conventions. -One such strategy is `bind`{.firrtl} which lowers to modules and instances which are instantiated using the SystemVerilog `bind`{.verilog} feature. +Each layer must include a string that sets the *lowering convention* for that layer. +The conventions defines both how the optional functionality is represented when the circuit is compiled to a backend language and the mechanism by which the layer's optional functionality can be enabled. +For the purposes of FIRRTL execution, all layer conventions are the same---enabling the layer enables the optional functionality. + +There are two standard lowering conventions: `bind`{.firrtl} and `inline`{.firrtl}. +For details of the representation and mechanism of these conventions, see the FIRRTL ABI Specification. +Compilers may define other non-standard lowering conventions. + +A layer with the `bind`{.firrtl} convention may not be nested, or transitively nested, under a layer of `inline`{.firrtl} convention. The example below shows a circuit with layers `A`, `B`, and `B.C`: