CIRCT

Circuit IR Compilers and Tools

'seq' Dialect

Types and operations for seq dialect

The seq dialect is intended to model digital sequential logic.

Operations

seq.clock_div (::circt::seq::ClockDividerOp)

Produces a clock divided by a power of two

Syntax:

operation ::= `seq.clock_div` $input `by` $pow2 attr-dict

The output clock is phase-aligned to the input clock.

%div_clock = seq.clock_div %clock by 1

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:

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

Operands:

OperandDescription
inputA type for clock-carrying wires

Results:

ResultDescription
outputA type for clock-carrying wires

seq.clock_gate (::circt::seq::ClockGateOp)

Safely gates a clock with an enable signal

Syntax:

operation ::= `seq.clock_gate` $input `,` $enable (`,` $test_enable^)? (`sym` $inner_sym^)? attr-dict

The seq.clock_gate enables and disables a clock safely, without glitches, based on a boolean enable value. If the enable operand is 1, the output clock produced by the clock gate is identical to the input clock. If the enable operand is 0, the output clock is a constant zero.

The enable operand is sampled at the rising edge of the input clock; any changes on the enable before or after that edge are ignored and do not affect the output clock.

The test_enable operand is optional and if present is OR’d together with the enable operand to determine whether the output clock is gated or not.

The op can be referred to using an inner symbol. Upon translation, the symbol will target the instance to the external module it lowers to.

%gatedClock = seq.clock_gate %clock, %enable
%gatedClock = seq.clock_gate %clock, %enable, %test_enable

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, InnerSymbolOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
inner_sym::circt::hw::InnerSymAttrInner symbol definition

Operands:

OperandDescription
inputA type for clock-carrying wires
enable1-bit signless integer
test_enable1-bit signless integer

Results:

ResultDescription
outputA type for clock-carrying wires

seq.clock_inv (::circt::seq::ClockInverterOp)

Inverts the clock signal

Syntax:

operation ::= `seq.clock_inv` $input attr-dict

Note that the compiler can optimize inverters away, preventing their use as part of explicit clock buffers.

%inv_clock = seq.clock_inv %clock

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
inputA type for clock-carrying wires

Results:

ResultDescription
outputA type for clock-carrying wires

seq.clock_mux (::circt::seq::ClockMuxOp)

Safely selects a clock based on a condition

Syntax:

operation ::= `seq.clock_mux` $cond `,` $trueClock `,` $falseClock attr-dict

The seq.clock_mux op selects a clock from two options. If cond is true, the first clock operand is selected to drive downstream logic. Otherwise, the second clock is used.

%clock = seq.clock_mux %cond, %trueClock, %falseClock

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
cond1-bit signless integer
trueClockA type for clock-carrying wires
falseClockA type for clock-carrying wires

Results:

ResultDescription
resultA type for clock-carrying wires

seq.compreg (::circt::seq::CompRegOp)

Register a value, storing it for one cycle

Syntax:

operation ::= `seq.compreg` (`sym` $inner_sym^)? `` custom<ImplicitSSAName>($name) $input `,` $clk
              (`reset` $reset^ `,` $resetValue)?
              (`initial` $initialValue^)? attr-dict `:` type($data)
              custom<OptionalTypeMatch>(ref(type($data)), ref($resetValue), type($resetValue))
              custom<OptionalImmutableTypeMatch>(ref(type($data)), ref($initialValue), type($initialValue))

See the Seq dialect rationale for a longer description

Traits: AlwaysSpeculatableImplTrait, AttrSizedOperandSegments

Interfaces: Clocked, ConditionallySpeculatable, InferTypeOpInterface, InnerSymbolOpInterface, NoMemoryEffect (MemoryEffectOpInterface), OpAsmOpInterface, Resettable

Effects: MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
inner_sym::circt::hw::InnerSymAttrInner symbol definition

Operands:

OperandDescription
inputany type
clkA type for clock-carrying wires
reset1-bit signless integer
resetValueany type
initialValuean ImmutableType

Results:

ResultDescription
dataany type

seq.compreg.ce (::circt::seq::CompRegClockEnabledOp)

When enabled, register a value

Syntax:

operation ::= `seq.compreg.ce` (`sym` $inner_sym^)? `` custom<ImplicitSSAName>($name) $input `,` $clk `,` $clockEnable
              (`reset` $reset^ `,` $resetValue)?
              (`initial` $initialValue^)? attr-dict `:` type($data)
              custom<OptionalTypeMatch>(ref(type($data)), ref($resetValue), type($resetValue))
              custom<OptionalImmutableTypeMatch>(ref(type($data)), ref($initialValue), type($initialValue))

See the Seq dialect rationale for a longer description

Traits: AlwaysSpeculatableImplTrait, AttrSizedOperandSegments

Interfaces: Clocked, ConditionallySpeculatable, InferTypeOpInterface, InnerSymbolOpInterface, NoMemoryEffect (MemoryEffectOpInterface), OpAsmOpInterface, Resettable

Effects: MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
inner_sym::circt::hw::InnerSymAttrInner symbol definition

Operands:

OperandDescription
inputany type
clkA type for clock-carrying wires
clockEnable1-bit signless integer
reset1-bit signless integer
resetValueany type
initialValuean ImmutableType

Results:

ResultDescription
dataany type

seq.const_clock (::circt::seq::ConstClockOp)

Produce constant clock value

Syntax:

operation ::= `seq.const_clock` $value attr-dict

The constant operation produces a constant clock value.

  %clock = seq.const_clock low

Traits: AlwaysSpeculatableImplTrait, ConstantLike

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
value::circt::seq::ClockConstAttrclock constant

Results:

ResultDescription
resultA type for clock-carrying wires

seq.fifo (::circt::seq::FIFOOp)

A high-level FIFO operation

Syntax:

operation ::= `seq.fifo` `depth` $depth
              (`rd_latency` $rdLatency^)?
              custom<FIFOAFThreshold>($almostFullThreshold, type($almostFull))
              custom<FIFOAEThreshold>($almostEmptyThreshold, type($almostEmpty))
              `in` $input `rdEn` $rdEn `wrEn` $wrEn `clk` $clk `rst` $rst attr-dict `:` type($input)

This operation represents a high-level abstraction of a FIFO. Access to the FIFO is structural, and thus may be composed with other core RTL dialect operations. The fifo operation is configurable with the following parameters:

  1. Depth (cycles)
  2. Read latency (cycles) is the number of cycles it takes for a read to return data after the read enable signal is asserted.
  3. Almost full/empty thresholds (optional). If not provided, these will be asserted when the FIFO is full/empty.

Like seq.hlmem there are no guarantees that all possible fifo configuration are able to be lowered. Available lowering passes will pattern match on the requested fifo configuration and attempt to provide a legal lowering.

Traits: AttrSizedResultSegments

Interfaces: OpAsmOpInterface

Attributes:

AttributeMLIR TypeDescription
depth::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 1
rdLatency::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 0
almostFullThreshold::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 0
almostEmptyThreshold::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 0

Operands:

OperandDescription
inputany type
rdEn1-bit signless integer
wrEn1-bit signless integer
clkA type for clock-carrying wires
rst1-bit signless integer

Results:

ResultDescription
outputany type
full1-bit signless integer
empty1-bit signless integer
almostFull1-bit signless integer
almostEmpty1-bit signless integer

seq.firmem (::circt::seq::FirMemOp)

A FIRRTL-flavored memory

Syntax:

operation ::= `seq.firmem` (`sym` $inner_sym^)? `` custom<ImplicitSSAName>($name)
              $readLatency `,` $writeLatency `,` $ruw `,` $wuw
              attr-dict `:` type($memory)

The seq.firmem op represents memories lowered from the FIRRTL dialect. It is used to capture some of the peculiarities of what FIRRTL expects from memories, while still representing them at the HW dialect level.

A seq.firmem declares the memory and captures the memory-level parameters such as width and depth or how read/write collisions are resolved. The read, write, and read-write ports are expressed as separate operations that take the declared memory as an operand.

Interfaces: InnerSymbolOpInterface, MemoryEffectOpInterface (MemoryEffectOpInterface), OpAsmOpInterface

Effects: MemoryEffects::Effect{MemoryEffects::Allocate on ::mlir::SideEffects::DefaultResource}

Attributes:

AttributeMLIR TypeDescription
readLatency::mlir::IntegerAttr32-bit signless integer attribute
writeLatency::mlir::IntegerAttr32-bit signless integer attribute
ruwcirct::seq::RUWAttrRead-Under-Write Behavior
wuwcirct::seq::WUWAttrWrite-Under-Write Behavior
name::mlir::StringAttrstring attribute
inner_sym::circt::hw::InnerSymAttrInner symbol definition
init::circt::seq::FirMemInitAttrMemory initialization information
prefix::mlir::StringAttrstring attribute
output_file::mlir::Attributeany attribute

Results:

ResultDescription
memoryA FIRRTL-flavored memory

seq.firmem.read_port (::circt::seq::FirMemReadOp)

A memory read port

Syntax:

operation ::= `seq.firmem.read_port` $memory `[` $address `]` `,` `clock` $clk
              (`enable` $enable^)?
              attr-dict `:` type($memory)

The seq.firmem.read_port op represents a read port on a seq.firmem memory. It takes the memory as an operand, together with the address to be read, the clock on which the read is synchronized, and an optional enable. Omitting the enable operand has the same effect as passing a constant true to it.

Interfaces: Clocked, InferTypeOpInterface, MemoryEffectOpInterface (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{MemoryEffects::Read on ::mlir::SideEffects::DefaultResource}

Operands:

OperandDescription
memoryA FIRRTL-flavored memory
addresssignless integer
clkA type for clock-carrying wires
enable1-bit signless integer

Results:

ResultDescription
datasignless integer

seq.firmem.read_write_port (::circt::seq::FirMemReadWriteOp)

A memory read-write port

Syntax:

operation ::= `seq.firmem.read_write_port` $memory `[` $address `]` `=` $writeData `if` $mode `,` `clock` $clk
              (`enable` $enable^)? (`mask` $mask^)?
              attr-dict `:` type($memory) (`,` type($mask)^)?

The seq.firmem.read_write_port op represents a read-write port on a seq.firmem memory. It takes the memory as an operand, together with the address and data to be written, a mode operand indicating whether the port should perform a read (mode=0) or a write (mode=1), the clock on which the read and write is synchronized, an optional enable, and and optional write mask. Omitting the enable operand has the same effect as passing a constant true to it. Omitting the write mask operand has the same effect as passing an all-ones value to it. A write mask operand can only be present if the seq.firmem specifies a mask width; otherwise it must be omitted.

Traits: AttrSizedOperandSegments

Interfaces: Clocked, InferTypeOpInterface, MemoryEffectOpInterface (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{MemoryEffects::Read on ::mlir::SideEffects::DefaultResource, MemoryEffects::Write on ::mlir::SideEffects::DefaultResource}

Operands:

OperandDescription
memoryA FIRRTL-flavored memory
addresssignless integer
clkA type for clock-carrying wires
enable1-bit signless integer
writeDatasignless integer
mode1-bit signless integer
masksignless integer

Results:

ResultDescription
readDatasignless integer

seq.firmem.write_port (::circt::seq::FirMemWriteOp)

A memory write port

Syntax:

operation ::= `seq.firmem.write_port` $memory `[` $address `]` `=` $data `,` `clock` $clk
              (`enable` $enable^)? (`mask` $mask^)?
              attr-dict `:` type($memory) (`,` type($mask)^)?

The seq.firmem.write_port op represents a write port on a seq.firmem memory. It takes the memory as an operand, together with the address and data to be written, the clock on which the write is synchronized, an optional enable, and and optional write mask. Omitting the enable operand has the same effect as passing a constant true to it. Omitting the write mask operand has the same effect as passing an all-ones value to it. A write mask operand can only be present if the seq.firmem specifies a mask width; otherwise it must be omitted.

Traits: AttrSizedOperandSegments

Interfaces: Clocked, MemoryEffectOpInterface (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{MemoryEffects::Write on ::mlir::SideEffects::DefaultResource}

Operands:

OperandDescription
memoryA FIRRTL-flavored memory
addresssignless integer
clkA type for clock-carrying wires
enable1-bit signless integer
datasignless integer
masksignless integer

seq.firreg (::circt::seq::FirRegOp)

Register with preset and sync or async reset

firreg represents registers originating from FIRRTL after the lowering of the IR to HW. The register is used as an intermediary in the process of lowering to SystemVerilog to facilitate optimisation at the HW level, compactly representing a register with a single operation instead of composing it from register definitions, always blocks and if statements.

The data output of the register accesses the value it stores. On the rising edge of the clk input, the register takes a new value provided by the next signal. Optionally, the register can also be provided with a synchronous or an asynchronous reset signal and resetValue, as shown in the example below.

%name = seq.firreg %next clock %clk [ sym @sym ]
    [ reset (sync|async) %reset, %value ]
    [ preset value ] : type

Implicitly, all registers are pre-set to a randomized value.

A register implementing a counter starting at 0 from reset can be defined as follows:

%zero = hw.constant 0 : i32
%reg = seq.firreg %next clock %clk reset sync %reset, %zero : i32
%one = hw.constant 1 : i32
%next = comb.add %reg, %one : i32

Traits: AlwaysSpeculatableImplTrait, SameVariadicOperandSize

Interfaces: Clocked, ConditionallySpeculatable, InferTypeOpInterface, InnerSymbolOpInterface, MemoryEffectOpInterface (MemoryEffectOpInterface), NoMemoryEffect (MemoryEffectOpInterface), OpAsmOpInterface, Resettable

Effects: MemoryEffects::Effect{MemoryEffects::Write on ::mlir::SideEffects::DefaultResource, MemoryEffects::Read on ::mlir::SideEffects::DefaultResource, MemoryEffects::Allocate on ::mlir::SideEffects::DefaultResource}, MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
inner_sym::circt::hw::InnerSymAttrInner symbol definition
preset::mlir::IntegerAttrarbitrary integer attribute
isAsync::mlir::UnitAttrunit attribute

Operands:

OperandDescription
nextany type
clkA type for clock-carrying wires
reset1-bit signless integer
resetValueany type

Results:

ResultDescription
dataany type

seq.from_clock (::circt::seq::FromClockOp)

Cast from a clock type to a wire type

Syntax:

operation ::= `seq.from_clock` $input attr-dict

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
inputA type for clock-carrying wires

Results:

ResultDescription
output1-bit signless integer

seq.from_immutable (::circt::seq::FromImmutableOp)

Cast from an immutable type to a wire type

Syntax:

operation ::= `seq.from_immutable` $input attr-dict `:` functional-type(operands, results)

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
inputan ImmutableType

Results:

ResultDescription
outputany type

seq.hlmem (::circt::seq::HLMemOp)

Instantiate a high-level memory.

Syntax:

operation ::= `seq.hlmem` $name $clk `,` $rst attr-dict `:` type($handle)

See the Seq dialect rationale for a longer description

Interfaces: Clocked, OpAsmOpInterface

Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute

Operands:

OperandDescription
clkA type for clock-carrying wires
rst1-bit signless integer

Results:

ResultDescription
handleMulti-dimensional memory type

seq.initial (::circt::seq::InitialOp)

Operation that produces values for initialization

Syntax:

operation ::= `seq.initial` `(` $inputs `)` $body attr-dict `:` functional-type($inputs, results)

seq.initial op creates values wrapped types with !seq.immutable. See the Seq dialect rationale for a longer description.

Traits: IsolatedFromAbove, RecursiveMemoryEffects, RecursivelySpeculatableImplTrait, SingleBlockImplicitTerminator<YieldOp>, SingleBlock

Interfaces: ConditionallySpeculatable

Operands:

OperandDescription
inputsvariadic of an ImmutableType

Results:

ResultDescription
«unnamed»variadic of an ImmutableType

seq.read (::circt::seq::ReadPortOp)

Structural read access to a seq.hlmem, with an optional read enable signal.

Traits: AttrSizedOperandSegments

Interfaces: OpAsmOpInterface

Attributes:

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

Operands:

OperandDescription
memoryMulti-dimensional memory type
addressesvariadic of a signless integer bitvector
rdEn1-bit signless integer

Results:

ResultDescription
readDataany type

seq.shiftreg (::circt::seq::ShiftRegOp)

Shift register

Syntax:

operation ::= `seq.shiftreg` `[` $numElements `]`
              (`sym` $inner_sym^)? `` custom<ImplicitSSAName>($name) $input `,` $clk `,` $clockEnable
              (`reset` $reset^ `,` $resetValue)?
              (`powerOn` $powerOnValue^)? attr-dict `:` type($data)
              custom<OptionalTypeMatch>(ref(type($data)), ref($resetValue), type($resetValue))
              custom<OptionalTypeMatch>(ref(type($data)), ref($powerOnValue), type($powerOnValue))

The seq.shiftreg op represents a shift register. It takes the input value and shifts it every cycle when clockEnable is asserted. The reset and resetValue operands are optional and if present, every entry in the shift register will be initialized to resetValue upon assertion of the reset signal. Exact reset behavior (sync/async) is implementation defined.

Traits: AlwaysSpeculatableImplTrait, AttrSizedOperandSegments

Interfaces: Clocked, ConditionallySpeculatable, InferTypeOpInterface, InnerSymbolOpInterface, NoMemoryEffect (MemoryEffectOpInterface), OpAsmOpInterface, Resettable

Effects: MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
numElements::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 1
name::mlir::StringAttrstring attribute
inner_sym::circt::hw::InnerSymAttrInner symbol definition

Operands:

OperandDescription
inputany type
clkA type for clock-carrying wires
clockEnable1-bit signless integer
reset1-bit signless integer
resetValueany type
powerOnValueany type

Results:

ResultDescription
dataany type

seq.to_clock (::circt::seq::ToClockOp)

Cast from a wire type to a clock type

Syntax:

operation ::= `seq.to_clock` $input attr-dict

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
input1-bit signless integer

Results:

ResultDescription
outputA type for clock-carrying wires

seq.write (::circt::seq::WritePortOp)

Structural write access to a seq.hlmem

Attributes:

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

Operands:

OperandDescription
memoryMulti-dimensional memory type
addressesvariadic of a signless integer bitvector
inDataany type
wrEn1-bit signless integer

seq.yield (::circt::seq::YieldOp)

Yield values

Syntax:

operation ::= `seq.yield` attr-dict ($operands^ `:` type($operands))?

Traits: AlwaysSpeculatableImplTrait, HasParent<InitialOp>, Terminator

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
operandsvariadic of any type

Attributes

ClockConstAttr

clock constant

Syntax:

#seq.clock_constant<
  circt::seq::ClockConst   # value
>

Enum cases:

  • low (Low)
  • high (High)

Parameters:

ParameterC++ typeDescription
valuecirct::seq::ClockConstan enum of type ClockConst

FirMemInitAttr

Memory initialization information

Syntax:

#seq.firmem.init<
  mlir::StringAttr,   # filename
  bool,   # isBinary
  bool   # isInline
>

This attribute captures what the initial contents of a memory should be. At the moment this is modeled primarily with simulation in mind, where the memory contents are pre-loaded from a file at simulation startup.

The filename specifies a file on disk that contains the initial contents for this memory. If isBinary is set, the file is interpreted as a binary file, otherwise it is treated as hexadecimal. This is modeled after the $readmemh and $readmemb SystemVerilog functions. If isInline is set, the initialization is emitted directly in the memory model; otherwise it is split out into a separate module that can be bound in.

Parameters:

ParameterC++ typeDescription
filenamemlir::StringAttr
isBinarybool
isInlinebool

Type constraints

an ImmutableType

Types

ClockType

A type for clock-carrying wires

Syntax: !seq.clock

The !seq.clock type represents signals which can be used to drive the clock input of sequential operations.

FirMemType

A FIRRTL-flavored memory

Syntax:

!seq.firmem<
  uint64_t,   # depth
  uint32_t,   # width
  std::optional<uint32_t>   # maskWidth
>

The !seq.firmem type represents a FIRRTL-flavored memory declared by a seq.firmem operation. It captures the parameters of the memory that are relevant to the read, write, and read-write ports, such as width and depth.

Parameters:

ParameterC++ typeDescription
depthuint64_t
widthuint32_t
maskWidthstd::optional<uint32_t>

HLMemType

Multi-dimensional memory type

Syntax:

hlmem-type ::== `hlmem` `<` dim-list element-type `>`

The HLMemType represents the type of an addressable memory structure. The type is inherently multidimensional. Dimensions must be known integer values.

Note: unidimensional memories are represented as <1x{element type}> - <{element type}> is illegal.

Parameters:

ParameterC++ typeDescription
shape::llvm::ArrayRef<int64_t>
elementTypeType

ImmutableType

Value type that is immutable after initialization

Syntax:

!seq.immutable<
  ::mlir::Type   # innerType
>

Parameters:

ParameterC++ typeDescription
innerType::mlir::Type

Enums

ClockConst

clock constant

Cases:

SymbolValueString
Low0low
High1high

RUW

Read-Under-Write Behavior

Cases:

SymbolValueString
Undefined0undefined
Old1old
New2new

WUW

Write-Under-Write Behavior

Cases:

SymbolValueString
Undefined0undefined
PortOrder1port_order

'seq' Dialect Docs