CIRCT

Circuit IR Compilers and Tools

'llhd' Dialect

A low-level hardware description dialect in MLIR.

Type constraint definition 

LLHD array type 

LLHD time type 

Operation definition 

llhd.and (::circt::llhd::AndOp) 

Bitwise AND

Takes two integers of the same width or two nine-valued-logic (IEEE 1164) values of the same width as input. Calculates the bitwise AND. The result is always of the exact same type as the two inputs.

Syntax:

and-op ::= ssa-id `=` `llhd.and` ssa-lhs `,` ssa-rhs attr-dict `:` type

Examples:

%0 = llhd.const 0 : i32
%1 = llhd.and %0, %0 : i32

Truth Table for integers:

and01
000
101

Truth Table for nine-valued logic:

andUX01ZWLH-
UUU0UUU0UU
XUX0XXX0XX
0000000000
1UX01XX01X
ZUX0XXX0XX
WUX0XXX0XX
L000000000
HUX01XX01X
-UX0XXX0XX

Operands: 

OperandDescription
lhssignless integer
rhssignless integer

Results: 

ResultDescription
«unnamed»signless integer

llhd.array (::circt::llhd::ArrayOp) 

Create an array from a list of values.

Syntax:

operation ::= `llhd.array` $values attr-dict `:` type($result)

The llhd.array operation allows to create an array from a list of SSA-values.

Example:

%c1 = llhd.const 1 : i32
%c2 = llhd.const 2 : i32
%c3 = llhd.const 3 : i32
%array = llhd.array %c1, %c2, %c3 : !llhd.array<3xi32>
%elem = llhd.extract_element %array, 0 : !llhd.array<3xi32> -> i32

Operands: 

OperandDescription
valuesany type

Results: 

ResultDescription
resultLLHD array type

llhd.array_uniform (::circt::llhd::ArrayUniformOp) 

Create a uniform array from an initialization value.

Syntax:

operation ::= `llhd.array_uniform` $init attr-dict `:` type($result)

The llhd.array_uniform operation allows to create an LLHD array from a single SSA-value used as initialization for all elements.

Example:

%init = llhd.const 1 : i32
%array = llhd.array_uniform %init : !llhd.array<3xi32>

Operands: 

OperandDescription
initany type

Results: 

ResultDescription
resultLLHD array type

llhd.con (::circt::llhd::ConnectOp) 

Connect two signals.

Syntax:

operation ::= `llhd.con` operands attr-dict `:` type($lhs)

The con instruction connects two signals such that they essentially become one signal. All driven values on one signal will be reflected on the other.

Operands: 

OperandDescription
lhsLLHD sig type of signless integer or LLHD array type or tuple values
rhsLLHD sig type of signless integer or LLHD array type or tuple values

llhd.const (::circt::llhd::ConstOp) 

Introduce a new constant.

The llhd.const instruction introduces a new constant value as an SSA-operator. Legal types are integers and time. Note: Signals are not legal to define using llhd.const, use the llhd.sig instruction for that.

Syntax:

const-op ::= ssa-id `=`
  `llhd.const` attribute-value attr-dict `:` result-type

Example:

%0 = llhd.const 1 : i64
%1 = llhd.const #llhd.time<1ns, 2d, 3d> : !llhd.time

Attributes: 

AttributeMLIR TypeDescription
value::mlir::Attributeany attribute

Results: 

ResultDescription
outsignless integer or LLHD time type

llhd.drv (::circt::llhd::DrvOp) 

Drive a value into a signal.

Syntax:

operation ::= `llhd.drv` $signal `,` $value `after` $time ( `if` $enable^ )? attr-dict `:`
              type($signal)

The llhd.drv operation drives a new value onto a signal. A time operand also has to be passed, which specifies the frequency at which the drive will be performed. An optional enable value can be passed as last argument. In this case the drive will only be performed if the value is 1. In case no enable signal is passed the drive will always be performed. This operation does not define any new SSA operands.

Syntax:

drv-op ::= `llhd.drv` ssa-signal `,` ssa-const `after` ssa-time
  (`if` ssa-enable)? `:` !llhd.sig<const-type>

Example:

%init = llhd.const 1 : i1
%en = llhd.const 0 : i1
%time = llhd.const #llhd.time<1ns, 0d, 0e> : !llhd.time
%sig = llhd.sig %init : i1
%new = llhd.not %init : i1

llhd.drv %sig, %new after %time : !llhd.sig<i1>
llhd.drv %sig, %new after %time if %en : !llhd.sig<i1>

Operands: 

OperandDescription
signalLLHD sig type of signless integer or LLHD array type or tuple values
valuesignless integer or LLHD array type or tuple
timeLLHD time type
enable1-bit signless integer

llhd.dyn_extract_element (::circt::llhd::DynExtractElementOp) 

Dynamically extract an element from an array or signal of array.

Syntax:

operation ::= `llhd.dyn_extract_element` $target `,` $index attr-dict `:` functional-type(operands, results)

The llhd.dyn_extract_element operation allows to dynamically access an element of the $target operand. The $index operand defines the index of the element to extract. If %target is a signal, a new subsignal aliasing the element will be returned.

Example:

%index = llhd.const 1 : i2

%init = llhd.const 3 : i8
%0 = llhd.array_uniform %init : !llhd.array<3xi8>
%1 = llhd.dyn_extract_element %0, %index : (!llhd.array<3xi8>, i2) -> i8

%2 = llhd.sig %0 : !llhd.array<3xi8>
%3 = llhd.dyn_extract_element %2, %index
  : (!llhd.sig<!llhd.array<3xi8>>, i2) -> !llhd.sig<i8>

Operands: 

OperandDescription
targetLLHD array type or LLHD sig type of LLHD array type values
indexsignless integer

Results: 

ResultDescription
resultany type

llhd.dyn_extract_slice (::circt::llhd::DynExtractSliceOp) 

Dynamically extract a slice of consecutive elements

Syntax:

operation ::= `llhd.dyn_extract_slice` operands attr-dict `:` functional-type(operands, results)

The llhd.dyn_extract_slice operation allows to dynamically access a slice of the $target operand, starting at the index given by the $start operand. The resulting slice length is defined by the result type. The $target operand kind has to match the result kind. If $target is an array, only the number of elements can change, while the element type has to remain the same.

Example:

%0 = llhd.const 0x0f0 : i12
%1 = llhd.const 4 : i3

%3 = llhd.dyn_extract_slice %0, %1 : (i12, i3) -> i4    // %3: 0xf

Operands: 

OperandDescription
targetsignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values
startsignless integer

Results: 

ResultDescription
resultsignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values

llhd.entity (::circt::llhd::EntityOp) 

Create an entity.

The llhd.entity operation defines a new entity unit. An entity represents the data-flow description of how a circuit’s output values change in reaction to changing input values. An entity contains one region with a single block and an implicit TerminatorOp terminator. Both the block name and terminator are omitted in the custom syntax. No further blocks and control-flow are legal inside an entity.

Syntax:

entity-op ::= `llhd.entity` entity-symbol `(` arg-list `)` `->`
  `(` out-list `)` attr-dict entity-region

Example:

llhd.entity @Foo () -> () {
  %0 = llhd.const 0 : i1
  %toggle = llhd.sig %0 : i1 -> !llhd.sig<i1>
  %1 = llhd.prb %toggle : !llhd.sig<i1> -> i1
  %2 = llhd.not %1 : i1
  %dt = llhd.const #llhd.time<1ns, 0d, 0e> : !llhd.time
  llhd.drv %toggle, %2, %dt : !llhd.sig<i1>, i1, !llhd.time
}

Attributes: 

AttributeMLIR TypeDescription
ins::mlir::IntegerAttr64-bit signless integer attribute

llhd.eq (::circt::llhd::EqOp) 

Logical Equality

Syntax:

operation ::= `llhd.eq` operands attr-dict `:` type($lhs)

This operation compares two values and returns 1 if they are the same and 0 otherwise. It is capable of comparing all types in the LLHD dialect. It performs element-wise equality for arrays and tuples.

Examples:

%const1 = constant 1 : i32
%const2 = constant 2 : i32
%eq = llhd.eq %const1, %const2 : i32  // %eq = 0

%const3 = constant 0 : i1
%tup1 = llhd.tuple %const1, %const3 : tuple<i32, i1>
%tup2 = llhd.tuple %const2, %const3 : tuple<i32, i1>
%tupeq = llhd.eq %tup1, %tup2 : i32  // %tupeq = 0

Operands: 

OperandDescription
lhsany type
rhsany type

Results: 

ResultDescription
result1-bit signless integer

llhd.extract_element (::circt::llhd::ExtractElementOp) 

Extract an element from an array, tuple, or signal of an array or tuple.

Syntax:

operation ::= `llhd.extract_element` $target `,` $index attr-dict `:` type($target) `->` type($result)

The llhd.extract_element operation allows access to an element of the $target operand. The $index attribute defines the index of the element to extract. If %target is a signal, a new subsignal aliasing the element will be returned.

Example:

%init = llhd.const 3 : i8
%0 = llhd.array_uniform %init : !llhd.array<3xi8>
%1 = llhd.extract_element %0, 0 : !llhd.array<3xi8> -> i8

%2 = llhd.sig %0 : !llhd.array<3xi8>
%3 = llhd.extract_element %2, 0
  : !llhd.sig<!llhd.array<3xi8>> -> !llhd.sig<i8>

%4 = llhd.const 8 : i16
%5 = llhd.tuple %0, %4 : tuple<!llhd.array<3xi8>, i16>
%6 = llhd.extract_element %5, 1 : tuple<!llhd.array<3xi8>, i16> -> i16

Attributes: 

AttributeMLIR TypeDescription
index::mlir::IntegerAttrindex attribute

Operands: 

OperandDescription
targetLLHD array type or tuple or LLHD sig type of LLHD array type or tuple values

Results: 

ResultDescription
resultany type

llhd.extract_slice (::circt::llhd::ExtractSliceOp) 

Extract a slice of consecutive elements.

Syntax:

operation ::= `llhd.extract_slice` $target `,` $start attr-dict `:` type($target) `->` type($result)

The llhd.extract_slice operation allows access to a slice of the $target operand. The $start attribute defines the index of the first element. The return type is the same as $target but with the width of the specified result type. If %target is a signal, a new subsignal aliasing the slice will be returned.

Example:

%0 = llhd.const 123 : i32
%1 = llhd.extract_slice %0, 0 : i32 -> i2

%2 = llhd.sig %0 : i32
%3 = llhd.extract_slice %2, 0 : !llhd.sig<i32> -> !llhd.sig<i5>

Attributes: 

AttributeMLIR TypeDescription
start::mlir::IntegerAttrindex attribute

Operands: 

OperandDescription
targetsignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values

Results: 

ResultDescription
resultsignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values

llhd.halt (::circt::llhd::HaltOp) 

Terminates execution of a process.

Syntax:

operation ::= `llhd.halt` attr-dict

The halt instruction terminates execution of a process. All processes must halt eventually or consist of an infinite loop.

  • This is a terminator instruction
  • This instruction is only allowed in processes (llhd.proc).

Syntax:

halt-op ::= `llhd.halt`

Example:

llhd.halt

llhd.insert_element (::circt::llhd::InsertElementOp) 

Insert an element into an array or tuple.

Syntax:

operation ::= `llhd.insert_element` $target `,` $element `,` $index attr-dict `:`
              type($target) `,` type($element)

The llhd.insert_element operation allows insertion of an element represented by the $element operand into the $target operand. The $index attribute defines the index where to insert the element. The return type is the same as $target. Note that the $target is not changed, but a new value with the element inserted is returned.

Example:

%init = llhd.const 1 : i8
%target = llhd.array_uniform : !llhd.array<3xi8>
%element = llhd.const 2 : i8
%0 = llhd.insert_element %target, %element, 0 : !llhd.array<3xi8>, i8

%tuptarget = llhd.tuple %element, %target : tuple<i8, !llhd.array<3xi8>
%newelement = llhd.const 4 : i8
%1 = llhd.insert_element %tuptarget, %newelement, 0
  : tuple<i8, !llhd.array<3xi8>>, i8

Attributes: 

AttributeMLIR TypeDescription
index::mlir::IntegerAttrindex attribute

Operands: 

OperandDescription
targetLLHD array type or tuple
elementany type

Results: 

ResultDescription
resultLLHD array type or tuple

llhd.insert_slice (::circt::llhd::InsertSliceOp) 

Insert a slice of consecutive elements.

Syntax:

operation ::= `llhd.insert_slice` $target `,` $slice `,` $start attr-dict `:` type($target) `,` type($slice)

The llhd.insert_slice operation allows insertion of a slice represented by the $slice operand into the $target operand. The $start attribute defines the index of the first element. The return type is the same as $target. Note that the $target is not changed, but a new value with the slice inserted is returned.

Example:

%itarget = llhd.const 123 : i32
%islice = llhd.const 2 : i2
%0 = llhd.insert_slice %itarget, %islice, 0 : i32, i2

%init1 = llhd.const 2 : i32
%init2 = llhd.const 3 : i32
%vtarget = llhd.array_uniform %init1 : !llhd.array<3xi32>
%vslice = llhd.array_uniform %init2 : !llhd.array<2xi32>
%1 = llhd.insert_slice %vtarget, %vslice, 0
  : !llhd.array<3xi32>, !llhd.array<2xi32>

Attributes: 

AttributeMLIR TypeDescription
start::mlir::IntegerAttrindex attribute

Operands: 

OperandDescription
targetsignless integer or LLHD array type
slicesignless integer or LLHD array type

Results: 

ResultDescription
resultsignless integer or LLHD array type

llhd.inst (::circt::llhd::InstOp) 

Instantiates a process or entity.

Syntax:

operation ::= `llhd.inst` $name $callee `(` $inputs `)` `->` `(` $outputs `)` attr-dict `:`
              functional-type($inputs, $outputs)

Instantiates a process or entity and thus allows to build hierarchies. Can only be used within an entity. An instance defines a unique name within the entity it resides in.

Syntax:

inst-op ::= `llhd.inst` inst-name symbol-name `(` ssa-input-list `)` `->`
  `(` ssa-output-list `)` attr-dict `:`
  functional-type(ssa-input-list, ssa-output-list)

Example:

llhd.inst "foo" @empty() -> () : () -> ()
llhd.inst "bar" @proc_symbol() -> (%out0) : () -> !llhd.sig<i32>
llhd.inst "baz" @entity_symbol(%in0, %in1) -> (%out0, %out1) :
  (!llhd.sig<i32>, !llhd.sig<i16>) -> (!llhd.sig<i8>, !llhd.sig<i4>)

Attributes: 

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
callee::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands: 

OperandDescription
inputsLLHD sig type of signless integer or LLHD array type or tuple values
outputsLLHD sig type of signless integer or LLHD array type or tuple values

llhd.load (::circt::llhd::LoadOp) 

Load a value.

Syntax:

operation ::= `llhd.load` $pointer attr-dict `:` type($pointer)

The llhd.load operation loads a value from a memory region given by pointer.

Examples:

%int = llhd.const 0 : i32
%arr = llhd.array_uniform %int : !llhd.array<3xi32>
%iPtr = llhd.var %int : i32
%arrPtr = llhd.var %arr : !llhd.array<3xi32>

%iLd = llhd.load %iPtr : !llhd.ptr<i32>
%arrLd = llhd.load %arrPtr : !llhd.ptr<!llhd.array<3xi32>>

Operands: 

OperandDescription
pointerLLHD pointer type of signless integer or LLHD array type or tuple values

Results: 

ResultDescription
resultsignless integer or LLHD array type or tuple

llhd.neg (::circt::llhd::NegOp) 

Negate a value.

The operand and result always have the same type. The type has to be a signless integer of any width. Although, only signless integers are allowed, this instruction applies two’s complement negation of the integer, basically treating it as a signed integer.

Syntax:

neg-op ::= ssa-id `=` `llhd.neg` ssa-value attr-dict `:` type

Example:

%0 = llhd.const 42 : i32
%1 = llhd.neg %0 : i32

Operands: 

OperandDescription
valuesignless integer

Results: 

ResultDescription
«unnamed»signless integer

llhd.neq (::circt::llhd::NeqOp) 

Logical Inequality

Syntax:

operation ::= `llhd.neq` operands attr-dict `:` type($lhs)

This operation compares two values and returns 1 if they are not the same and 0 if they are the same. It is capable of comparing all types in the LLHD dialect. It performs element-wise equality for arrays and tuples.

Examples:

%const1 = constant 1 : i32
%const2 = constant 2 : i32
%neq = llhd.neq %const1, %const2 : i32  // %neq = 1

%const3 = constant 0 : i1
%tup1 = llhd.tuple %const1, %const3 : tuple<i32, i1>
%tup2 = llhd.tuple %const2, %const3 : tuple<i32, i1>
%tupneq = llhd.neq %tup1, %tup2 : i32  // %tupeq = 1

Operands: 

OperandDescription
lhsany type
rhsany type

Results: 

ResultDescription
result1-bit signless integer

llhd.not (::circt::llhd::NotOp) 

Bitwise NOT

Takes an integer of any width or a nine-valued-logic (IEEE 1164) value of any width as input. Flips each bit of a value. The result always has the exact same type.

Syntax:

not-op ::= ssa-id `=` `llhd.not` ssa-value attr-dict `:` type

Examples:

%0 = llhd.const 0 : i32
%1 = llhd.not %0 : i32

Truth Table for integers:

not01
10

Truth Table for nine-valued logic:

notUX01ZWLH-
UX10XX10X

Operands: 

OperandDescription
valuesignless integer

Results: 

ResultDescription
«unnamed»signless integer

llhd.or (::circt::llhd::OrOp) 

Bitwise OR

Takes two integers of the same width or two nine-valued-logic (IEEE 1164) values of the same width as input. Calculates the bitwise OR. The result is always of the exact same type as the two inputs.

Syntax:

or-op ::= ssa-id `=` `llhd.or` ssa-lhs `,` ssa-rhs attr-dict `:` type

Examples:

%0 = llhd.const 0 : i32
%1 = llhd.or %0, %0 : i32

Truth Table for integers:

or01
001
111

Truth Table for nine-valued logic:

orUX01ZWLH-
UUUU1UUU1U
XUXX1XXX1X
0UX01XX01X
1111111111
ZUXX1XXX1X
WUXX1XXX1X
LUX01XX01X
H111111111
-UXX1XXX1X

Operands: 

OperandDescription
lhssignless integer
rhssignless integer

Results: 

ResultDescription
«unnamed»signless integer

llhd.prb (::circt::llhd::PrbOp) 

Probe a signal.

Syntax:

operation ::= `llhd.prb` $signal attr-dict `:` type($signal)

The llhd.prb instruction probes a signal and returns the value it currently carries as a new SSA operand. The result type is always the type carried by the signal.

Syntax:

prb-op ::= ssa-id `=` `llhd.prb` ssa-sig attr-dict `:` !llhd.sig<type>

Example:

%const_i1 = llhd.const 1 : i1
%sig_i1 = llhd.sig %const_i1 : i1
%prbd = llhd.prb %sig_i1 : !llhd.sig<i1>

Operands: 

OperandDescription
signalLLHD sig type of signless integer or LLHD array type or tuple values

Results: 

ResultDescription
resultsignless integer or LLHD array type or tuple

llhd.proc (::circt::llhd::ProcOp) 

Create a process

A llhd.proc represents control-flow in a timed fashion. It allows a procedural description of how a circuit’s output signals change in reaction to changing input signals. It has a region with arbitrarily many basic blocks. The first block is the entry block and cannot be targeted by the terminators. It uses llhd.wait as a terminator to add timed control-flow. Immediate control-flow with br or cond_br is also possible. Every process must either contain an infinite loop or terminate with the llhd.halt terminator.

How does a process compare to functions and entities?

UnitParadigmTimingModels
Functioncontrol-flowimmediateComputation in zero time
Processcontrol-flowtimedBehavioral circuit description
Entitydata-flowtimedStructural circuit description

Syntax:

proc-op ::= `llhd.proc` proc-symbol `(` ssa-input-list `)` `->`
  `(` ssa-output-list `)` attr-dict `{` proc-region `}`

Examples:

llhd.proc @example(%in0 : !llhd.sig<i64>, %in1 : !llhd.sig<i1>) ->
    (%out2 : !llhd.sig<i1>) {
  br ^bb1
^bb1:
  llhd.halt
}

Attributes: 

AttributeMLIR TypeDescription
ins::mlir::IntegerAttr64-bit signless integer attribute

llhd.reg (::circt::llhd::RegOp) 

Represents a storage element

This instruction represents a storage element. It drives its output onto the ‘signal’ value. An arbitrary amount of triggers can be added to the storage element. However, at least one is required. They are quadruples consisting of the new value to be stored if the trigger applies, the mode and trigger value which specify when this trigger has to be applied as well as a delay. Optionally, each triple may also have a gate condition, in this case the trigger only applies if the gate is one. If multiple triggers apply the left-most in the list takes precedence.

There are five modes available:

ModeMeaning
“low”Storage element stores value while the trigger is low. Models active-low resets and low-transparent latches.
“high”Storage element stores value while the trigger is high. Models active-high resets and high-transparent latches.
“rise”Storage element stores value upon the rising edge of the trigger. Models rising-edge flip-flops.
“fall”Storage element stores value upon the falling edge of the trigger. Models falling-edge flip-flops.
“both”Storage element stores value upon the a rising or a falling edge of the trigger. Models dual-edge flip-flops.

This instruction may only be used in an LLHD entity.

Syntax:

reg-op ::= `llhd.reg` signal-ssa-value
  ( `,` `(` value-ssa-value `,` mode-string trigger-ssa-value `after`
  delay-ssa-value ( `if` gate-ssa-value )? `:` value-type )+
  attr-dict `:` signal-type

Examples:

A rising, falling, and dual-edge triggered flip-flop:

llhd.reg %Q, (%D, "rise" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
llhd.reg %Q, (%D, "fall" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
llhd.reg %Q, (%D, "both" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>

A rising-edge triggered flip-flop with active-low reset:

llhd.reg %Q, (%init, "low" %RSTB after %T : !llhd.sig<i8>),
  (%D, "rise" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>

A rising-edge triggered enable flip-flop with active-low reset:

llhd.reg %Q, (%init, "low" %RSTB after %T : !llhd.sig<i8>),
  (%D, "rise" %CLK after %T if %EN : !llhd.sig<i8>) : !llhd.sig<i8>

A transparent-low and transparent-high latch:

llhd.reg %Q, (%D, "low" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>
llhd.reg %Q, (%D, "high" %CLK after %T : !llhd.sig<i8>) : !llhd.sig<i8>

An SR latch:

%0 = llhd.const 0 : i1
%1 = llhd.const 1 : i1
llhd.reg %Q, (%0, "high" %R after %T : !llhd.sig<i1>),
  (%1, "high" %S after %T : !llhd.sig<i1>) : !llhd.sig<i1>

Attributes: 

AttributeMLIR TypeDescription
modes::mlir::ArrayAttrreg mode array attribute
gateMask::mlir::ArrayAttr64-bit integer array attribute

Operands: 

OperandDescription
signalLLHD sig type of signless integer or LLHD array type or tuple values
valuessignless integer or LLHD array type or tuple or LLHD sig type of signless integer or LLHD array type or tuple values
triggers1-bit signless integer
delaysLLHD time type
gates1-bit signless integer

llhd.smod (::circt::llhd::SModOp) 

Signed modulo.

This instruction computes the signed modulo of two signless integers of any width, treating the leading bit as sign. The operand and result types always have to be the same. To calculate the signed remainder of two integers, use remi_signed from the standard dialect.

Syntax:

smod-op ::= ssa-id `=` `llhd.smod` ssa-lhs `,` ssa-rhs attr-dict `:` type

Examples:

%0 = llhd.const 9 : i4
%1 = llhd.const 4 : i4
%2 = llhd.smod %0, %1 : i4

Operands: 

OperandDescription
lhssignless integer
rhssignless integer

Results: 

ResultDescription
«unnamed»signless integer

llhd.shl (::circt::llhd::ShlOp) 

Shifts a value to the left by a given amount.

Syntax:

operation ::= `llhd.shl` operands attr-dict `:` functional-type(operands, results)

The type of the base value and the hidden value must be the same, but may differ in the number of bits or elements. The result always has the same type (including width) of the base value. The instruction is transparent to signals and pointers. For example, passing a signal as argument will shift the underlying value and return a signal to the shifted value. Allowed (underlying) types are signless integers, nine-valued-logic values and arrays. The shift amount has to be a signless integer. A shift amount bigger than the number of bits or elements of the hidden value is undefined. The hidden value is uncovered by non-zero shift amounts. E.g. consider the four bit values base = 0xf, hidden = 0xc shifted by an amount of three result in 0xe.

Syntax:

shl-op ::= ssa-id `=`
  `llhd.shl` ssa-base `,` ssa-hidden `,` ssa-amount attr-dict `:`
  `(` base-type `,` hidden-type `,` amount-type `)` `->` result-type

Examples:

%0 = llhd.shl %base, %hidden, %amount : (i4, i2, i2) -> i4

Operands: 

OperandDescription
basesignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values
hiddensignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values
amountsignless integer

Results: 

ResultDescription
resultsignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values

llhd.shr (::circt::llhd::ShrOp) 

Shifts a value to the right by a given amount.

Syntax:

operation ::= `llhd.shr` operands attr-dict `:` functional-type(operands, results)

The type of the base value and the hidden value must be the same, but may differ in the number of bits or elements. The result always has the same type (including width) of the base value. The instruction is transparent to signals and pointers. For example, passing a signal as argument will shift the underlying value and return a signal to the shifted value. Allowed (underlying) types are signless integers, nine-valued-logic values and arrays. The shift amount has to be a signless integer. A shift amount bigger than the number of bits or elements of the hidden value is undefined. The hidden value is uncovered by non-zero shift amounts. E.g. consider the four bit values base = 0xf, hidden = 0xc shifted by an amount of three result in 0x9.

Syntax:

shr-op ::= ssa-id `=`
  `llhd.shr` ssa-base `,` ssa-hidden `,` ssa-amount attr-dict `:`
  `(` base-type `,` hidden-type `,` amount-type `)` `->` result-type

Examples:

%0 = llhd.shr %base, %hidden, %amount : (i4, i2, i2) -> i4

Operands: 

OperandDescription
basesignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values
hiddensignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values
amountsignless integer

Results: 

ResultDescription
resultsignless integer or LLHD array type or LLHD sig type of signless integer or LLHD array type values

llhd.sig (::circt::llhd::SigOp) 

Create a signal.

Syntax:

operation ::= `llhd.sig` $name $init attr-dict `:` type($init)

The llhd.sig instruction introduces a new signal in the IR. The input operand determines the initial value carried by the signal, while the result type will always be a signal carrying the type of the init operand. A signal defines a unique name within the entity it resides in. Signals can only be allocated within entities.

Syntax:

sig-op ::= ssa-id `=` `llhd.sig` sig-name ssa-init attr-dict `:` init-type

Example:

%init_i64 = llhd.const 123 : i64
%sig_i64 = llhd.sig "foo" %init_64 : i64

%init_i1 = llhd.const 1 : i1
%sig_i1 = llhd.sig "bar" %init_i1 : i1

The first llhd.sig instruction creates a new signal named “foo”, carrying an i64 type with initial value of 123, while the second one creates a new signal named “bar”, carrying an i1 type with initial value of 1.

Attributes: 

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute

Operands: 

OperandDescription
initsignless integer or LLHD array type or tuple

Results: 

ResultDescription
resultLLHD sig type of signless integer or LLHD array type or tuple values

llhd.store (::circt::llhd::StoreOp) 

Store a value.

Syntax:

operation ::= `llhd.store` $pointer `,` $value attr-dict `:` type($pointer)

The llhd.store operation stores the value value to the memory region given by pointer.

Examples:

%int = llhd.const 0 : i32
%arr = llhd.array_uniform %int : !llhd.array<3xi32>
%iPtr = llhd.var %int : i32
%arrPtr = llhd.var %arr : !llhd.array<3xi32>

llhd.store %iPtr, %int : !llhd.ptr<i32>
llhd.store %arrPtr, %arr : !llhd.ptr<!llhd.array<3xi32>>

Operands: 

OperandDescription
pointerLLHD pointer type of signless integer or LLHD array type or tuple values
valuesignless integer or LLHD array type or tuple

llhd.terminator (::circt::llhd::TerminatorOp) 

Dummy terminator

The "llhd.terminator" op is a dummy terminator for an EntityOp unit. It provides no further meaning other than ensuring correct termination of an entitiy’s region. This operation provides no custom syntax and should never explicitly appear in LLHD’s custom syntax.

llhd.tuple (::circt::llhd::TupleOp) 

Create a tuple from a list of values.

Syntax:

operation ::= `llhd.tuple` $values attr-dict `:` type($result)

The llhd.tuple operation creates a tuple from a list of SSA-values.

Example:

%c1 = llhd.const 1 : i32
%c2 = llhd.const 2 : i2
%sig = llhd.sig "sig_name" %c1 : i32
%array = llhd.array_uniform %c1 : !llhd.array<2xi32>
%tuple = llhd.tuple %c1, %c2, %array, %sig :
  tuple<i32, i2, !llhd.array<2xi32>, !llhd.sig<i32>>

Operands: 

OperandDescription
valuesany type

Results: 

ResultDescription
resulttuple

llhd.var (::circt::llhd::VarOp) 

Stack allocation.

Syntax:

operation ::= `llhd.var` $init attr-dict `:` type($init)

The llhd.var operation allocates a memory region on the stack with the initial value given by init, and returns a pointer to the allocated region.

Examples:

%int = llhd.const 0 : i32
%arr = llhd.array_uniform %int : !llhd.array<3xi32>

%iPtr = llhd.var %int : i32
%arrPtr = llhd.var %arr : !llhd.array<3xi32>

Operands: 

OperandDescription
initsignless integer or LLHD array type or tuple

Results: 

ResultDescription
resultLLHD pointer type of signless integer or LLHD array type or tuple values

llhd.wait (::circt::llhd::WaitOp) 

Suspends execution of a process.

Syntax:

operation ::= `llhd.wait` (`for` $time^ `,`)? (`(`$obs^ `:` type($obs)`)` `,`)?
              $dest (`(` $destOps^ `:` type($destOps) `)`)? attr-dict

The wait instruction suspends execution of a process until any of the observed signals change or a fixed time interval has passed. Execution resumes at the specified basic block with the passed arguments.

  • This is a terminator instruction.
  • This instruction is only allowed in processes (llhd.proc).

Example:

llhd.wait ^bb1
llhd.wait for %time, ^bb1(%time : !llhd.time)
llhd.wait (%0, %1 : !llhd.sig<i64>, !llhd.sig<i1>), ^bb1(%1 : !llhd.sig<i1>)
llhd.wait for %time, (%0, %1 : !llhd.sig<i64>, !llhd.sig<i1>),
  ^bb1(%1, %0 : !llhd.sig<i1>, !llhd.sig<i64>)

Operands: 

OperandDescription
obsLLHD sig type of signless integer or LLHD array type or tuple values
timeLLHD time type
destOpsany type

Successors: 

SuccessorDescription
destany successor

llhd.xor (::circt::llhd::XorOp) 

Bitwise XOR

Takes two integers of the same width or two nine-valued-logic (IEEE 1164) values of the same width as input. Calculates the bitwise XOR. The result is always of the exact same type as the two inputs.

Syntax:

xor-op ::= ssa-id `=` `llhd.xor` ssa-lhs `,` ssa-rhs attr-dict `:` type

Examples:

%0 = llhd.const 0 : i32
%1 = llhd.xor %0, %0 : i32

Truth Table for integers:

xor01
001
110

Truth Table for nine-valued logic:

xorUX01ZWLH-
UUUUUUUUUU
XUXXXXXXXX
0UX01XX01X
1UX10XX10X
ZUXXXXXXXX
WUXXXXXXXX
LUX01XX01X
HUX10XX10X
-UXXXXXXXX

Operands: 

OperandDescription
lhssignless integer
rhssignless integer

Results: 

ResultDescription
«unnamed»signless integer