# CIRCT

Circuit IR Compilers and Tools

# 'hw' Dialect

Types and operations for the hardware dialect This dialect defines the hw dialect, which is intended to be a generic representation of HW outside of a particular use-case.

## Type constraint definition ¶

### fixed-sized array ¶

Fixed sized HW arrays are roughly similar to C arrays. On the wire (vs. in a memory), arrays are always packed. Memory layout is not defined as it does not need to be since in silicon there is not implicit memory sharing.

### inout type ¶

InOut type is used for model operations and values that have “connection” semantics, instead of typical dataflow behavior. This is used for wires and inout ports in Verilog.

### HW struct type ¶

Represents a structure of name, value pairs. !hw.struct<fieldName1: Type1, fieldName2: Type2>

### An symbolic reference to a type declaration ¶

A TypeAlias is parameterized by a SymbolRefAttr, which points to a TypedeclOp. The root reference should refer to a TypeScope within the same outer ModuleOp, and the leaf reference should refer to a type within that TypeScope. A TypeAlias is further parameterized by the inner type, which is needed to be known at the time the type is parsed.

Upon construction, a TypeAlias stores the symbol reference and type, and canonicalizes the type to resolve any nested type aliases. The canonical type is also cached to avoid recomputing it when needed.

### SystemVerilog ‘unpacked’ fixed-sized array ¶

Unpacked arrays are a more flexible array representation than packed arrays, and are typically used to model memories. See SystemVerilog Spec 7.4.2.

## Operation definition ¶

### hw.array_concat (::circt::hw::ArrayConcatOp) ¶

Concatenate some arrays

Syntax:

operation ::= hw.array_concat $inputs attr-dict : custom<ArrayConcatTypes>(type($inputs), type($result))  Creates an array by concatenating a variable set of arrays. One or more values must be listed. // %a, %b, %c are hw arrays of i4 with sizes 2, 5, and 4 respectively. %array = hw.array_concat %a, %b, %c : (2, 5, 4 x i4) // %array is !hw.array<11 x i4>  See the HW-SV rationale document for details on operand ordering. #### Operands: ¶ OperandDescription inputsan ArrayType #### Results: ¶ ResultDescription resultan ArrayType ### hw.array_create (::circt::hw::ArrayCreateOp) ¶ Create an array from values Creates an array from a variable set of values. One or more values must be listed. // %a, %b, %c are all i4 %array = hw.array_create %a, %b, %c : i4  See the HW-SV rationale document for details on operand ordering. #### Operands: ¶ OperandDescription inputsa type without inout #### Results: ¶ ResultDescription resultan ArrayType ### hw.array_get (::circt::hw::ArrayGetOp) ¶ Get the value in an array at the specified index Syntax: operation ::= hw.array_get$input[$index] attr-dict : type($input)


#### Operands: ¶

OperandDescription
inputan ArrayType
indexan integer bitvector of one or more bits

#### Results: ¶

ResultDescription
resulta type without inout

### hw.array_slice (::circt::hw::ArraySliceOp) ¶

Get a range of values from an array

Syntax:

operation ::= hw.array_slice $input at$lowIndex attr-dict :
( custom<SliceTypes>(type($input), type($lowIndex)) ) -> type($dst)  Extracts a sub-range from an array. The range is from lowIndex to lowIndex + the number of elements in the return type, non-inclusive on the high end. For instance, // Slices 16 elements starting at '%offset'. %subArray = hw.slice %largerArray at %offset : (!hw.array<1024xi8>) -> !hw.array<16xi8>  Would translate to the following SystemVerilog: logic [7:0][15:0] subArray = largerArray[offset +: 16];  Width of ‘idx’ is defined to be the precise number of bits required to index the ‘input’ array. More precisely: for an input array of size M, the width of ‘idx’ is ceil(log2(M)). Lower and upper bound indexes which are larger than the size of the ‘input’ array results in undefined behavior. #### Operands: ¶ OperandDescription inputan ArrayType lowIndexan integer bitvector of one or more bits #### Results: ¶ ResultDescription dstan ArrayType ### hw.bitcast (::circt::hw::BitcastOp) ¶ Reinterpret one value to another value of the same size and potentially different type.  Syntax: operation ::= hw.bitcast$input attr-dict : functional-type($input,$result)


See the HW-SV rationale document for a longer description, including an example.

#### Operands: ¶

OperandDescription
inputType wherein the bitwidth in hardware is known

#### Results: ¶

ResultDescription
resultType wherein the bitwidth in hardware is known

### hw.constant (::circt::hw::ConstantOp) ¶

Produce a constant value

The constant operation produces a constant value of standard integer type without a sign.

  %result = hw.constant 42 : t1


#### Attributes: ¶

AttributeMLIR TypeDescription
value::mlir::IntegerAttrarbitrary integer attribute

#### Results: ¶

ResultDescription
resultan integer bitvector of one or more bits

### hw.generator.schema (::circt::hw::HWGeneratorSchemaOp) ¶

HW Generator Schema declaration

Syntax:

operation ::= hw.generator.schema $sym_name ,$descriptor , $requiredAttrs attr-dict  The “hw.generator.schema” operation declares a kind of generated module by declaring the schema of meta-data required. A generated module instance of a schema is independent of the external method of producing it. It is assumed that for well known schema instances, multiple external tools might exist which can process it. Generator nodes list attributes required by hw.module.generated instances. For example: generator.schema @MEMORY, “Simple-Memory”, [“ports”, “write_latency”, “read_latency”] module.generated @mymem, @MEMORY(ports) -> (ports) {write_latency=1, read_latency=1, ports=[“read”,“write”]} #### Attributes: ¶ AttributeMLIR TypeDescription sym_name::mlir::StringAttrstring attribute descriptor::mlir::StringAttrstring attribute requiredAttrs::mlir::ArrayAttrstring array attribute ### hw.module.extern (::circt::hw::HWModuleExternOp) ¶ HW external Module The “hw.module.extern” operation represents an external reference to a Verilog module, including a given name and a list of ports. The ‘verilogName’ attribute (when present) specifies the spelling of the module name in Verilog we can use. TODO: This is a hack because we don’t have proper parameterization in the hw.dialect. We need a way to represent parameterized types instead of just concrete types. #### Attributes: ¶ AttributeMLIR TypeDescription argNames::mlir::ArrayAttrstring array attribute resultNames::mlir::ArrayAttrstring array attribute verilogName::mlir::StringAttrstring attribute ### hw.module.generated (::circt::hw::HWModuleGeneratedOp) ¶ HW Generated Module The “hw.module.generated” operation represents a reference to an external module that will be produced by some external process. This represents the name and list of ports to be generated. The ‘verilogName’ attribute (when present) specifies the spelling of the module name in Verilog we can use. See hw.module for an explanation. #### Attributes: ¶ AttributeMLIR TypeDescription generatorKind::mlir::FlatSymbolRefAttrflat symbol reference attribute verilogName::mlir::StringAttrstring attribute argNames::mlir::ArrayAttrstring array attribute resultNames::mlir::ArrayAttrstring array attribute ### hw.module (::circt::hw::HWModuleOp) ¶ HW Module The “hw.module” operation represents a Verilog module, including a given name, a list of ports, and a body that represents the connections within the module. #### Attributes: ¶ AttributeMLIR TypeDescription argNames::mlir::ArrayAttrstring array attribute resultNames::mlir::ArrayAttrstring array attribute ### hw.instance (::circt::hw::InstanceOp) ¶ Create an instance of a module Syntax: operation ::= hw.instance$instanceName (sym $sym_name^)?$moduleName ( $inputs ) attr-dict : functional-type($inputs, results)


This represents an instance of a module. The inputs and results are the referenced module’s inputs and outputs. Any parameters are stored in the “parameters” dictionary.

#### Attributes: ¶

AttributeMLIR TypeDescription
instanceName::mlir::StringAttrstring attribute
moduleName::mlir::FlatSymbolRefAttrflat symbol reference attribute is module like
parameters::mlir::DictionaryAttrdictionary of named attribute values
sym_name::mlir::StringAttrstring attribute

#### Operands: ¶

OperandDescription
inputsany type

#### Results: ¶

ResultDescription
«unnamed»any type

### hw.output (::circt::hw::OutputOp) ¶

HW termination operation

Syntax:

operation ::= hw.output attr-dict ($operands^ : type($operands))?


“hw.output” marks the end of a region in the HW dialect and the values to put on the output ports.

#### Operands: ¶

OperandDescription
operandsany type

### hw.struct_create (::circt::hw::StructCreateOp) ¶

Create a struct from constituent parts.

#### Operands: ¶

OperandDescription
inputa type without inout

#### Results: ¶

ResultDescription
resulta StructType

### hw.struct_explode (::circt::hw::StructExplodeOp) ¶

Expand a struct into its constituent parts.

#### Operands: ¶

OperandDescription
inputa StructType

#### Results: ¶

ResultDescription
resulta type without inout

### hw.struct_extract (::circt::hw::StructExtractOp) ¶

Extract a named field from a struct.

#### Attributes: ¶

AttributeMLIR TypeDescription
field::mlir::StringAttrstring attribute

#### Operands: ¶

OperandDescription
inputa StructType

#### Results: ¶

ResultDescription
resulta type without inout

### hw.struct_inject (::circt::hw::StructInjectOp) ¶

Inject a value into a named field of a struct.

#### Attributes: ¶

AttributeMLIR TypeDescription
field::mlir::StringAttrstring attribute

#### Operands: ¶

OperandDescription
inputa StructType
newValuea type without inout

#### Results: ¶

ResultDescription
resulta StructType

### hw.type_scope (::circt::hw::TypeScopeOp) ¶

Type declaration wrapper.

Syntax:

operation ::= hw.type_scope $sym_name$body attr-dict


An operation whose one body block contains type declarations. This op provides a scope for type declarations at the top level of an MLIR module. It is a symbol that may be looked up within the module, as well as a symbol table itself, so type declarations may be looked up.

#### Attributes: ¶

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute

### hw.typedecl (::circt::hw::TypedeclOp) ¶

Type declaration.

Syntax:

operation ::= hw.typedecl $sym_name (,$verilogName^)? : \$type attr-dict


Associate a symbolic name with a type.

#### Attributes: ¶

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
type::mlir::TypeAttrany type attribute
verilogName::mlir::StringAttrstring attribute

### hw.union_create (::circt::hw::UnionCreateOp) ¶

Create a union with the specified value.

Create a union with the value ‘input’, which can then be accessed via the specified field.

  %x = hw.constant 0 : i3
%z = hw.union_create "bar", %x : !hw.union<bar: i3, baz: i8>


#### Attributes: ¶

AttributeMLIR TypeDescription
field::mlir::StringAttrstring attribute

#### Operands: ¶

OperandDescription
inputa type without inout

#### Results: ¶

ResultDescription
resulta UnionType

### hw.union_extract (::circt::hw::UnionExtractOp) ¶

Get a union member.

Get the value of a union, interpreting it as the type of the specified member field. Extracting a value belonging to a different field than the union was initially created will result in undefined behavior.

  %u = ...
%v = hw.union_extract %u["foo"] : !hw.union<foo: i3, bar: i16>
// %v is of type 'i3'


#### Attributes: ¶

AttributeMLIR TypeDescription
field::mlir::StringAttrstring attribute

#### Operands: ¶

OperandDescription
inputa UnionType

#### Results: ¶

ResultDescription
resulta type without inout

## Type definition ¶

### ArrayType ¶

fixed-sized array

Fixed sized HW arrays are roughly similar to C arrays. On the wire (vs. in a memory), arrays are always packed. Memory layout is not defined as it does not need to be since in silicon there is not implicit memory sharing.

#### Parameters: ¶

ParameterC++ typeDescription
elementType::mlir::Type
sizesize_t

### InOutType ¶

inout type

InOut type is used for model operations and values that have “connection” semantics, instead of typical dataflow behavior. This is used for wires and inout ports in Verilog.

#### Parameters: ¶

ParameterC++ typeDescription
elementType::mlir::Type

### StructType ¶

HW struct type

Represents a structure of name, value pairs. !hw.struct<fieldName1: Type1, fieldName2: Type2>

#### Parameters: ¶

ParameterC++ typeDescription
elements::llvm::ArrayRef<::circt::hw::StructType::FieldInfo>struct fields

### TypeAliasType ¶

An symbolic reference to a type declaration

A TypeAlias is parameterized by a SymbolRefAttr, which points to a TypedeclOp. The root reference should refer to a TypeScope within the same outer ModuleOp, and the leaf reference should refer to a type within that TypeScope. A TypeAlias is further parameterized by the inner type, which is needed to be known at the time the type is parsed.

Upon construction, a TypeAlias stores the symbol reference and type, and canonicalizes the type to resolve any nested type aliases. The canonical type is also cached to avoid recomputing it when needed.

#### Parameters: ¶

ParameterC++ typeDescription
refmlir::SymbolRefAttr
innerTypemlir::Type
canonicalTypemlir::Type

### UnionType ¶

An untagged union of types

#### Parameters: ¶

ParameterC++ typeDescription
elements::llvm::ArrayRef<::circt::hw::UnionType::FieldInfo>union fields

### UnpackedArrayType ¶

SystemVerilog ‘unpacked’ fixed-sized array

Unpacked arrays are a more flexible array representation than packed arrays, and are typically used to model memories. See SystemVerilog Spec 7.4.2.

#### Parameters: ¶

ParameterC++ typeDescription
elementType::mlir::Type
sizesize_t