CIRCT

Circuit IR Compilers and Tools

'esi' Dialect

Type constraint definition 

An ESI-compatible channel port 

An ESI port kind which models a latency-insensitive, unidirectional, point-to-point data stream. Channels are typed (like all of ESI). Said type can be any MLIR type, but must be lowered to something a backend knows how to output (i.e. something emitVerilog knows about).

Example:

hw.module.extern @Sender() -> (%x: !esi.channel<i1>)
hw.module @Reciever(%a: !esi.channel<hw.array<5xi16>>) { }

Operation definition 

esi.decode.capnp (::circt::esi::CapnpDecode) 

Translate bits in Cap’nProto messages to HW typed data

Syntax:

operation ::= `esi.decode.capnp` $clk $valid $capnpBits attr-dict `:` type($capnpBits) `->` type($decodedData)

Operands: 

OperandDescription
clk1-bit signless integer
valid1-bit signless integer
capnpBitsan HW bit array

Results: 

ResultDescription
decodedDataany type

esi.encode.capnp (::circt::esi::CapnpEncode) 

Translate HW typed data to Cap’nProto

Syntax:

operation ::= `esi.encode.capnp` $clk $valid $dataToEncode attr-dict `:` type($dataToEncode) `->` type($capnpBits)

Operands: 

OperandDescription
clk1-bit signless integer
valid1-bit signless integer
dataToEncodeany type

Results: 

ResultDescription
capnpBitsan HW bit array

esi.buffer (::circt::esi::ChannelBuffer) 

Control options for an ESI channel.

A channel buffer (buffer) is essentially a set of options on a channel. It always adds at least one cycle of latency (pipeline stage) to the channel, but this is configurable.

This operation is inserted on an ESI dataflow edge. It must exist previous to SystemVerilog emission but can be added in a lowering pass.

Example:

%esiChan = hw.instance "sender" @Sender () : () -> (!esi.channel<i1>)
// Allow automatic selection of options.
%bufferedChan = esi.buffer %esiChan { } : i1
hw.instance "recv" @Reciever (%bufferedChan) : (!esi.channel<i1>) -> ()

// Alternatively, specify the number of stages.
%fourStageBufferedChan = esi.buffer %esiChan { stages = 4 } : i1

Attributes: 

AttributeMLIR TypeDescription
options::circt::esi::ChannelBufferOptionsDictionaryAttr with field(s): ‘stages’, ‘name’ (each field having its own constraints)

Operands: 

OperandDescription
clk1-bit signless integer
rstn1-bit signless integer
input

Results: 

ResultDescription
output

esi.cosim (::circt::esi::CosimEndpoint) 

Co-simulation endpoint

Syntax:

operation ::= `esi.cosim` $clk `,` $rstn `,` $send `,` $endpointID attr-dict
              `:` type($send) `->` type($recv)

A co-simulation endpoint is a connection from the simulation to some outside process, usually a software application responsible for driving the simulation (driver).

ESI uses a serialization protocol called Cap’n Proto (capnp for short). The advantage of capnp is the decoding overhead: for value types (ints, structs, etc.) there is none! This stands in contrast to Protocol Buffers and Bond as their messages contain metadata for each field which must be interpreted.

The advantage of using a well-supported serialization protocol is language support – driver applications can be written in any language supported by the specific protocol.

Attributes: 

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

Operands: 

OperandDescription
clk1-bit signless integer
rstn1-bit signless integer
send

Results: 

ResultDescription
recv

esi.null (::circt::esi::NullSourceOp) 

An op which never produces messages.

Syntax:

operation ::= `esi.null` attr-dict `:` type($out)

Results: 

ResultDescription
out

esi.stage (::circt::esi::PipelineStage) 

An elastic buffer stage.

An individual elastic pipeline register. Generally lowered to from a ChannelBuffer (‘buffer’), though can be inserted anywhere to add an additional pipeline stage. Adding individually could be useful for late-pass latency balancing.

Operands: 

OperandDescription
clk1-bit signless integer
rstn1-bit signless integer
input

Results: 

ResultDescription
output

esi.unwrap.iface (::circt::esi::UnwrapSVInterface) 

Unwrap an SV interface from an ESI port

Syntax:

operation ::= `esi.unwrap.iface` $chanInput `into` $interfaceSource attr-dict `:` `(` type($chanInput) `,` type($interfaceSource) `)`

Unwrap an ESI channel into a SystemVerilog interface containing valid, ready, and data signals.

Operands: 

OperandDescription
chanInput
interfaceSourcesv.interface

esi.unwrap.vr (::circt::esi::UnwrapValidReady) 

Unwrap a value from an ESI port

Unwrapping a value allows operations on the contained value. Unwrap the channel along with a ready signal that you generate. Result is the data along with a valid signal.

Operands: 

OperandDescription
chanInput
ready1-bit signless integer

Results: 

ResultDescription
rawOutputany type
valid1-bit signless integer

esi.wrap.iface (::circt::esi::WrapSVInterface) 

Wrap an SV interface into an ESI port

Syntax:

operation ::= `esi.wrap.iface` $interfaceSink attr-dict `:` type($interfaceSink) `->` type($output)

Wrap a SystemVerilog interface into an ESI channel. Interface MUST look like an interface produced by ESI meaning it MUST contain valid, ready, and data signals. Any other signals will be discarded.

Operands: 

OperandDescription
interfaceSinksv.interface

Results: 

ResultDescription
output

esi.wrap.vr (::circt::esi::WrapValidReady) 

Wrap a value into an ESI port

Wrapping a value into an ESI port type allows modules to send values down an ESI port. Wrap data with valid bit, result is the ESI channel and the ready signal from the other end of the channel.

Operands: 

OperandDescription
rawInputany type
valid1-bit signless integer

Results: 

ResultDescription
chanOutput
ready1-bit signless integer

Type definition 

ChannelPort 

An ESI-compatible channel port

An ESI port kind which models a latency-insensitive, unidirectional, point-to-point data stream. Channels are typed (like all of ESI). Said type can be any MLIR type, but must be lowered to something a backend knows how to output (i.e. something emitVerilog knows about).

Example:

hw.module.extern @Sender() -> (%x: !esi.channel<i1>)
hw.module @Reciever(%a: !esi.channel<hw.array<5xi16>>) { }

Parameters: 

ParameterC++ typeDescription
innerType