'llhd' Dialect
A low-level hardware description dialect in MLIR.
Operations ¶
llhd.con
(::circt::llhd::ConnectOp) ¶
Connect two signals.
Syntax:
operation ::= `llhd.con` operands attr-dict `:` qualified(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.
Traits: HasParent<hw::HWModuleOp>
, SameTypeOperands
Operands: ¶
Operand | Description |
---|---|
lhs | InOutType |
rhs | InOutType |
llhd.constant_time
(::circt::llhd::ConstantTimeOp) ¶
Introduce a new time constant.
Syntax:
operation ::= `llhd.constant_time` $value attr-dict
The llhd.constant_time
instruction introduces a new constant time value as
an SSA-operator.
Example:
%1 = llhd.constant_time #llhd.time<1ns, 2d, 3d>
Traits: AlwaysSpeculatableImplTrait
, ConstantLike
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
value | llhd::TimeAttr | time attribute |
Results: ¶
Result | Description |
---|---|
result | time type |
llhd.delay
(::circt::llhd::DelayOp) ¶
Specifies value propagation delay
Syntax:
operation ::= `llhd.delay` $input `by` $delay attr-dict `:` type($result)
This operation propagates all value changes of the input to the output after the specified time delay. Reference values are not supported (e.g., pointers, inout, etc.) since the store-like operation used for those types should encode a delayed store.
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
delay | llhd::TimeAttr | time attribute |
Operands: ¶
Operand | Description |
---|---|
input | a type without inout |
Results: ¶
Result | Description |
---|---|
result | a type without inout |
llhd.drv
(::circt::llhd::DrvOp) ¶
Drive a value into a signal.
Syntax:
operation ::= `llhd.drv` $signal `,` $value `after` $time ( `if` $enable^ )? attr-dict `:`
qualified(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.
Example:
%true = hw.constant true
%false = hw.constant false
%time = llhd.constant_time <1ns, 0d, 0e>
%sig = llhd.sig %true : i1
llhd.drv %sig, %false after %time : !hw.inout<i1>
llhd.drv %sig, %false after %time if %true : !hw.inout<i1>
Interfaces: DestructurableAccessorOpInterface
, SafeMemorySlotAccessOpInterface
Operands: ¶
Operand | Description |
---|---|
signal | InOutType |
value | a known primitive element |
time | time type |
enable | 1-bit signless integer |
llhd.final
(::circt::llhd::FinalOp) ¶
A process that runs at the end of simulation
Syntax:
operation ::= `llhd.final` attr-dict-with-keyword $body
An llhd.final
op encapsulates a region of IR that is to be executed after
the last time step of a simulation has completed. This can be used to
implement various forms of state cleanup and tear-down. Some verifications
ops may also want to check that certain final conditions hold at the end of
a simulation run.
The llhd.wait
terminator is not allowed in llhd.final
processes since
there is no later time slot for the execution to resume. Control flow must
eventually end in an llhd.halt
terminator.
Execution order between multiple llhd.final
ops is undefined.
Example:
hw.module @Foo() {
llhd.final {
func.call @printSimulationStatistics() : () -> ()
llhd.halt
}
}
Traits: HasParent<hw::HWModuleOp>
, NoRegionArguments
, RecursiveMemoryEffects
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.
Traits: HasParent<ProcessOp, FinalOp>
, Terminator
llhd.load
(::circt::llhd::LoadOp) ¶
Load a value.
Syntax:
operation ::= `llhd.load` $pointer attr-dict `:` qualified(type($pointer))
The llhd.load
operation loads a value from a memory region given by
pointer
.
Example:
%int = hw.constant 0 : i32
%iPtr = llhd.var %int : i32
%iLd = llhd.load %iPtr : !llhd.ptr<i32>
Interfaces: InferTypeOpInterface
Operands: ¶
Operand | Description |
---|---|
pointer | pointer type |
Results: ¶
Result | Description |
---|---|
result | a known primitive element |
llhd.output
(::circt::llhd::OutputOp) ¶
Introduce a new signal and drive a value onto it.
Syntax:
operation ::= `llhd.output` ( $name^ )? $value `after` $time attr-dict `:` qualified(type($value))
The llhd.output
operation introduces a new signal and continuously
drives a the given value onto it after a given time-delay. The same
value is used to initialize the signal in the same way as the ‘init’
value in llhd.sig
. An optional name can be given to the created signal.
This shows up, e.g., in the simulation trace.
Example:
%value = hw.constant true
%time = llhd.constant_time <1ns, 0d, 0e>
%sig = llhd.output "sigName" %value after %time : i1
// is equivalent to
%value = hw.constant true
%time = llhd.constant_time <1ns, 0d, 0e>
%sig = llhd.sig "sigName" %value : i1
llhd.drv %sig, %value after %time : !hw.inout<i1>
Interfaces: InferTypeOpInterface
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
name | ::mlir::StringAttr | string attribute |
Operands: ¶
Operand | Description |
---|---|
value | a known primitive element |
time | time type |
Results: ¶
Result | Description |
---|---|
result | InOutType |
llhd.prb
(::circt::llhd::PrbOp) ¶
Probe a signal.
Syntax:
operation ::= `llhd.prb` $signal attr-dict `:` qualified(type($signal))
This operation 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.
Example:
%true = hw.constant true
%sig_i1 = llhd.sig %true : i1
%prbd = llhd.prb %sig_i1 : !hw.inout<i1>
Interfaces: DestructurableAccessorOpInterface
, InferTypeOpInterface
, SafeMemorySlotAccessOpInterface
Operands: ¶
Operand | Description |
---|---|
signal | InOutType |
Results: ¶
Result | Description |
---|---|
result | a known primitive element |
llhd.process
(::circt::llhd::ProcessOp) ¶
Create a process
Syntax:
operation ::= `llhd.process` attr-dict-with-keyword $body
A llhd.process
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?
Unit | Paradigm | Timing | Models |
---|---|---|---|
Function | control-flow | immediate | Computation in zero time |
Process | control-flow | timed | Behavioral circuit description |
Entity | data-flow | timed | Structural circuit description |
Examples:
hw.module @top() {
llhd.process {
br ^bb1
^bb1:
llhd.halt
}
}
Traits: HasParent<hw::HWModuleOp>
, NoRegionArguments
, RecursiveMemoryEffects
llhd.ptr.array_get
(::circt::llhd::PtrArrayGetOp) ¶
Extract an element from a pointer to an array.
Syntax:
operation ::= `llhd.ptr.array_get` $input `[` $index `]` attr-dict `:` qualified(type($input))
The llhd.ptr.array_get
operation allows to access the element of the
$input
operand at position $index
. A new pointer aliasing the element
will be returned.
Example:
// Returns a !llhd.ptr<i8>
%0 = llhd.ptr.array_get %arr[%index] : !llhd.ptr<!hw.array<4xi8>>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
input | LLHD pointer type of an ArrayType values |
index | a signless integer bitvector |
Results: ¶
Result | Description |
---|---|
result | LLHD pointer type of a type without inout values |
llhd.ptr.array_slice
(::circt::llhd::PtrArraySliceOp) ¶
Get a range of consecutive values from a pointer to an array
Syntax:
operation ::= `llhd.ptr.array_slice` $input `at` $lowIndex attr-dict `:` functional-type($input, $result)
The llhd.ptr.array_slice
operation allows to access a sub-range of the
$input
operand, starting at the index given by the $lowIndex
operand. The resulting slice length is defined by the result type.
Returns a pointer aliasing the elements of the slice.
Width of ’lowIndex’ 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 ’lowIndex’ is ceil(log2(M)). Lower and upper bound indexes which are larger than the size of the ‘input’ array results in undefined behavior.
Example:
%3 = llhd.ptr.array_slice %input at %lowIndex :
(!llhd.ptr<!hw.array<4xi8>>) -> !llhd.ptr<!hw.array<2xi8>>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
input | LLHD pointer type of an ArrayType values |
lowIndex | a signless integer bitvector |
Results: ¶
Result | Description |
---|---|
result | LLHD pointer type of an ArrayType values |
llhd.ptr.extract
(::circt::llhd::PtrExtractOp) ¶
Extract a range of bits from an integer pointer
Syntax:
operation ::= `llhd.ptr.extract` $input `from` $lowBit attr-dict `:` functional-type($input, $result)
The llhd.ptr.extract
operation allows to access a range of bits
of the $input
operand, starting at the index given by the $lowBit
operand. The result length is defined by the result type.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
input | LLHD pointer type of a signless integer bitvector values |
lowBit | a signless integer bitvector |
Results: ¶
Result | Description |
---|---|
result | LLHD pointer type of a signless integer bitvector values |
llhd.ptr.struct_extract
(::circt::llhd::PtrStructExtractOp) ¶
Extract a field from a pointer to a struct.
Syntax:
operation ::= `llhd.ptr.struct_extract` $input `[` $field `]` attr-dict `:` qualified(type($input))
The llhd.ptr.struct_extract
operation allows access to the field of the
$input
operand given by its name via the $field
attribute.
A new pointer aliasing the field will be returned.
Example:
// Returns a !llhd.ptr<i8>
%0 = llhd.ptr.struct_extract %struct["foo"]
: !llhd.ptr<!hw.struct<foo: i8, bar: i16>>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
field | ::mlir::StringAttr | string attribute |
Operands: ¶
Operand | Description |
---|---|
input | LLHD pointer type of a StructType values |
Results: ¶
Result | Description |
---|---|
result | LLHD pointer type of a type without inout values |
llhd.sig
(::circt::llhd::SignalOp) ¶
Create a signal.
Syntax:
operation ::= `llhd.sig` `` custom<ImplicitSSAName>($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.
Example:
%c123_i64 = hw.constant 123 : i64
%foo = llhd.sig %c123_i64 : i64
%0 = llhd.sig name "foo" %c123_i64 : i64
This example creates a new signal named “foo”, carrying an i64
type with
initial value of 123.
Interfaces: DestructurableAllocationOpInterface
, InferTypeOpInterface
, OpAsmOpInterface
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
name | ::mlir::StringAttr | string attribute |
Operands: ¶
Operand | Description |
---|---|
init | a known primitive element |
Results: ¶
Result | Description |
---|---|
result | InOutType |
llhd.sig.array_get
(::circt::llhd::SigArrayGetOp) ¶
Extract an element from a signal of an array.
Syntax:
operation ::= `llhd.sig.array_get` $input `[` $index `]` attr-dict `:` qualified(type($input))
The llhd.sig.array_get
operation allows to access the element of the
$input
operand at position $index
. A new subsignal aliasing the element
will be returned.
Example:
// Returns a !hw.inout<i8>
%0 = llhd.sig.array_get %arr[%index] : !hw.inout<array<4xi8>>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, DestructurableAccessorOpInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
, SafeMemorySlotAccessOpInterface
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
input | InOutType of an ArrayType values |
index | a signless integer bitvector |
Results: ¶
Result | Description |
---|---|
result | InOutType of a type without inout values |
llhd.sig.array_slice
(::circt::llhd::SigArraySliceOp) ¶
Get a range of consecutive values from a signal of an array
Syntax:
operation ::= `llhd.sig.array_slice` $input `at` $lowIndex attr-dict `:` functional-type($input, $result)
The llhd.sig.array_slice
operation allows to access a sub-range of the
$input
operand, starting at the index given by the $lowIndex
operand. The resulting slice length is defined by the result type.
Returns a signal aliasing the elements of the slice.
Width of ’lowIndex’ 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 ’lowIndex’ is ceil(log2(M)). Lower and upper bound indexes which are larger than the size of the ‘input’ array results in undefined behavior.
Example:
%3 = llhd.sig.array_slice %input at %lowIndex :
(!hw.inout<array<4xi8>>) -> !hw.inout<array<2xi8>>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
input | InOutType of an ArrayType values |
lowIndex | a signless integer bitvector |
Results: ¶
Result | Description |
---|---|
result | InOutType of an ArrayType values |
llhd.sig.extract
(::circt::llhd::SigExtractOp) ¶
Extract a range of bits from an integer signal
Syntax:
operation ::= `llhd.sig.extract` $input `from` $lowBit attr-dict `:` functional-type($input, $result)
The llhd.sig.extract
operation allows to access a range of bits
of the $input
operand, starting at the index given by the $lowBit
operand. The result length is defined by the result type.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
input | InOutType of a signless integer bitvector values |
lowBit | a signless integer bitvector |
Results: ¶
Result | Description |
---|---|
result | InOutType of a signless integer bitvector values |
llhd.sig.struct_extract
(::circt::llhd::SigStructExtractOp) ¶
Extract a field from a signal of a struct.
Syntax:
operation ::= `llhd.sig.struct_extract` $input `[` $field `]` attr-dict `:` qualified(type($input))
The llhd.sig.struct_extract
operation allows access to the field of the
$input
operand given by its name via the $field
attribute.
A new subsignal aliasing the field will be returned.
Example:
// Returns a !hw.inout<i8>
%0 = llhd.sig.struct_extract %struct["foo"]
: !hw.inout<struct<foo: i8, bar: i16>>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, DestructurableAccessorOpInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
, SafeMemorySlotAccessOpInterface
Effects: MemoryEffects::Effect{}
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
field | ::mlir::StringAttr | string attribute |
Operands: ¶
Operand | Description |
---|---|
input | InOutType of a StructType values |
Results: ¶
Result | Description |
---|---|
result | InOutType of a type without inout values |
llhd.store
(::circt::llhd::StoreOp) ¶
Store a value.
Syntax:
operation ::= `llhd.store` $pointer `,` $value attr-dict `:` qualified(type($pointer))
The llhd.store
operation stores the value value
to the memory region
given by pointer
.
Example:
%int = hw.constant 0 : i32
%iPtr = llhd.var %int : i32
llhd.store %iPtr, %int : !llhd.ptr<i32>
Operands: ¶
Operand | Description |
---|---|
pointer | pointer type |
value | a known primitive element |
llhd.var
(::circt::llhd::VarOp) ¶
Stack allocation.
Syntax:
operation ::= `llhd.var` $init attr-dict `:` qualified(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.
Example:
%int = hw.constant 0 : i32
%iPtr = llhd.var %int : i32
Interfaces: InferTypeOpInterface
Operands: ¶
Operand | Description |
---|---|
init | a known primitive element |
Results: ¶
Result | Description |
---|---|
result | pointer type |
llhd.wait
(::circt::llhd::WaitOp) ¶
Suspends execution of a process.
Syntax:
operation ::= `llhd.wait` (`for` $time^ `,`)? (`(`$observed^ `:` qualified(type($observed))`)` `,`)?
$dest (`(` $destOps^ `:` qualified(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.process
).
Example:
llhd.wait ^bb1
llhd.wait for %time, ^bb1(%time : !llhd.time)
llhd.wait (%0, %1 : !hw.inout<i64>, !hw.inout<i1>), ^bb1(%1 : !hw.inout<i1>)
llhd.wait for %time, (%0, %1 : !hw.inout<i64>, !hw.inout<i1>),
^bb1(%1, %0 : !hw.inout<i1>, !hw.inout<i64>)
Traits: AttrSizedOperandSegments
, HasParent<ProcessOp>
, Terminator
Interfaces: BranchOpInterface
Operands: ¶
Operand | Description |
---|---|
observed | variadic of a known primitive element |
time | time type |
destOps | variadic of any type |
Successors: ¶
Successor | Description |
---|---|
dest | any successor |
Attributes ¶
TimeAttr ¶
time attribute
Represents a value of the LLHD time type.
Example: #llhd.time<0ns, 1d, 0e>
Parameters: ¶
Parameter | C++ type | Description |
---|---|---|
type | llhd::TimeType | |
time | unsigned | |
timeUnit | ::llvm::StringRef | SI time unit |
delta | unsigned | |
epsilon | unsigned |
Types ¶
PtrType ¶
pointer type
Syntax:
!llhd.ptr<
::mlir::Type # elementType
>
Represents a pointer to a memory location holding a value of its element type. May be used to load and store data in distinct memory slots.
Parameters: ¶
Parameter | C++ type | Description |
---|---|---|
elementType | ::mlir::Type |
TimeType ¶
time type
Syntax: !llhd.time
Represents a simulation time value as a combination of a real time value in seconds (or any smaller SI time unit), a delta value representing infinitesimal time steps, and an epsilon value representing an absolute time slot within a delta step (used to model SystemVerilog scheduling regions).