diff --git a/include/firrtl.xml b/include/firrtl.xml
index 2b0248d3..a4c574f1 100644
--- a/include/firrtl.xml
+++ b/include/firrtl.xml
@@ -7,6 +7,7 @@
- extmodule
- intmodule
- layer
+ - option
- input
@@ -27,6 +28,8 @@
- intrinsic
- propassign
- public
+ - instchoice
+ - case
- UInt
diff --git a/revision-history.yaml b/revision-history.yaml
index 053aded3..7c7bc39c 100644
--- a/revision-history.yaml
+++ b/revision-history.yaml
@@ -12,6 +12,7 @@ revisionHistory:
- Add section "Circuit Components".
- Reorganized statements section.
- Rewrite of the Types section.
+ - Add options and instance choices.
abi:
- Add ABI for public modules and filelist output.
- Changed ABI for group and ref generated files.
diff --git a/spec.md b/spec.md
index d5b439da..d59b9552 100644
--- a/spec.md
+++ b/spec.md
@@ -297,6 +297,34 @@ circuit:
Layer blocks will be compiled to modules whose ports are derived from what they capture from their visible scope.
For full details of the way layers are compiled, see the FIRRTL ABI specification.
+## Option Groups
+
+The option group mechanism declares configurable parameters with a pre-defined set of values to enable the specialization of designs during or after lowering.
+Options groups address the need for configurability.
+For example, designs may need to behave differently on ASIC and FPGA platforms, but at the time of FIRRTL elaboration it is not known which platform the design will be used on.
+This feature allows such choices to be expressed and embedded into the design.
+
+
+The `option`{.firrtl} keyword declares an option group, which contains `case`{.firrtl} declarations naming the settings allotted to that option.
+The circuit can be specialized for a single case of a given option at any time.
+Multiple option groups can be declared to capture orthogonal dimensions of configuration.
+
+Specialization can occur either in the compiler or it can be materialized in the lowering.
+For details, consult the FIRRTL ABI specification.
+Specialization is not mandatory: options can be left unspecified, resorting to explicitly-defined default behaviour.
+
+
+``` firrtl
+circuit:
+ option Platform:
+ case FPGA:
+ case ASIC:
+
+ option Performance:
+ case Slow:
+ case Fast
+```
+
## Externally Defined Modules
Externally defined modules are modules whose implementation is not provided in the current circuit.
@@ -516,6 +544,36 @@ The type of the submodule instance `passthrough`{.firrtl} above is thus:
{ flip in : UInt<8>, out : UInt<8> }
```
+#### Instance Choices
+
+FIRRTL supports the specialization of designs through the `instchoice`{.firrtl} declaration, which selects the instantiated module based on an `option`{.firrtl}.
+
+Example:
+
+``` firrtl
+circuit:
+ option Platform:
+ case FPGA:
+ case ASIC:
+
+ module InstanceChoice:
+ instchoice clock_gate of DefaultTarget, Platform:
+ FPGA => FPGATarget
+
+ module DefaultTarget:
+
+ module FPGATarget:
+```
+
+The instance choice declaration specifies the instance name and names the option group based on which the choices are selected.
+A default module is provided, to be instantiated when the design is not specialized or it is not specialised for a known case.
+Subsequently, modules can be specified for the known choices of the selected option group.
+The operation does not need to specify modules for all cases.
+The references must be either modules or extmodules.
+
+The type of the instance bundle is determined identically to regular instances.
+The port lists of all modules must match and the ports are limited to ground and aggregate types.
+
### Memories
Memories are stateful elements of a design.
@@ -3462,6 +3520,7 @@ decl =
| decl_extmodule
| decl_intmodule
| decl_layer
+ | decl_option
| decl_type_alias ;
decl_module =
@@ -3491,6 +3550,11 @@ decl_layer =
{ decl_layer , newline } ,
dedent ;
+decl_option =
+ "option" , id , ":" , [info] , newline, indent ,
+ { "case" , id , ":" , [ info ] , newline } ,
+ dedent ;
+
decl_type_alias = "type", id, "=", type ;
port = ( "input" | "output" ) , id , ":" , (type | type_property) , [ info ] ;
@@ -3512,11 +3576,17 @@ circuit_component =
| circuit_component_wire
| circuit_component_reg
| circuit_component_inst
+ | circuit_component_instchoice
| circuit_component_mem ;
circuit_component_node = "node" , id , "=" , expr , [ info ] ;
circuit_component_wire = "wire" , id , ":" , type , [ info ] ;
circuit_component_inst = "inst" , id , "of" , id , [ info ] ;
+circuit_component_instchoice =
+ "instchoice" , id , "of" , id , "," , id , ":" , newline ,
+ indent ,
+ { id , "=>" , id , newline } ,
+ dedent;
conditional_reg =
"reg" , id , ":" , type , expr , [ info ]