CIRCT

Circuit IR Compilers and Tools

'esi' Dialect

The Elastic Silicon Interconnect dialect aims to aid in accelerator system construction.

WARNING: The ESI dialect has evolved significantly since its inception while these documents have not. As such, large parts are significantly out-of-date.

Application channels

The main component of ESI are point-to-point, typed channels that allow designers to connect modules to each other and software, then communicate by sending messages. Channels largely abstract away the details of message communication from the designer, though the designer can declaratively specify how to implement the channel.

Messages have types: ints, structs, arrays, unions, and variable-length lists. The width of a channel is not necessarily the same width as the message. ESI “windows” can be used to break up a message into a series of “frames”. IP blocks can emit / absorb “windowed” messages or full-sized messages, which can be automatically broken up to save wire area at the cost of bandwidth.

Any channel which is exposed to the host will have a platform-agnostic software API constructed for it based on the type of the channel. The software application merely has to connect to the accelerator then invoke a method to send or receive messages from the accelerator system.

ChannelBundleType

a bundle of channels

Syntax:

!esi.bundle<
  ::llvm::ArrayRef<BundledChannel>,   # channels
  ::mlir::UnitAttr   # resettable
>

A channel bundle (sometimes referred to as just “bundle”) is a set of channels of associated signals, along with per-channel names and directions. The prototypical example for a bundle is a request-response channel pair.

The direction terminology is a bit confusing. Let us designate the module which is outputting the bundle as the “sender” module and a module which has a bundle as an input as the “receiver”. The directions “from” and “to” are from the senders perspective. So, the “to” direction means that channel is transmitting messages from the sender to the receiver. Then, “from” means that the sender is getting messages from the receiver (typically responses).

When requesting a bundle from a service, the service is always considered the sender; so, “to” means the service is sending messages to the client and “from” means the service is receiving messages from the client.

Parameters:

ParameterC++ typeDescription
channels::llvm::ArrayRef<BundledChannel>
resettable::mlir::UnitAttrboolean flag

ChannelType

An ESI-compatible channel port

Syntax:

!esi.channel<
  Type,   # inner
  ::circt::esi::ChannelSignaling,   # signaling
  uint64_t   # dataDelay
>

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).

Parameters: signaling: the style of the control signals (valid/ready vs FIFO). dataDelay: the number of cycles data takes to arrive after the control indicates a transaction has occured. For instance, on a FIFO without read ahead, this would be 1. Defaults to 0.

Example:

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

Parameters:

ParameterC++ typeDescription
innerType
signaling::circt::esi::ChannelSignaling
dataDelayuint64_t

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.

ListType

a runtime-variably sized list

Syntax:

!esi.list<
  Type   # elementType
>

In software, a chunk of memory with runtime-specified length. In hardware, a stream of runtime-specified amount of data transmitted over many cycles in compile-time specified specified windows (chunks).

Parameters:

ParameterC++ typeDescription
elementTypeType

WindowType

a data window

Syntax:

!esi.window<
  StringAttr,   # name
  mlir::Type,   # into
  ::llvm::ArrayRef<WindowFrameType>   # frames
>

A ‘data window’ allows designers to break up large messages into multiple frames (aka phits) spread across multiple cycles. Windows are specified in terms of a mapping of struct fields to frames. The width of a window is the maximum frame size + the union tag (log2(#frames)).

A data window does NOT imply an ESI channel.

Current restrictions:

  • A field may only appear once.
  • Fields may only be re-ordered (wrt the original message) within a frame.
  • Array fields whose array length is not evenly divisible by ’numItems’ will have an implicit frame inserted directly after containing the leftover array items.
  • Array fields with an array length MUST be in their own frame.

Parameters:

ParameterC++ typeDescription
nameStringAttr
intomlir::Type
frames::llvm::ArrayRef<WindowFrameType>

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

WindowFieldType

a field-in-frame specifier

Syntax:

!esi.window.field<
  StringAttr,   # fieldName
  uint64_t   # numItems
>

Specify that a field should appear within the enclosing frame.

Parameters:

ParameterC++ typeDescription
fieldNameStringAttr
numItemsuint64_t# of items in arrays or lists

WindowFrameType

Declare a data window frame

Syntax:

!esi.window.frame<
  StringAttr,   # name
  ::llvm::ArrayRef<WindowFieldType>   # members
>

A named list of fields which should appear in a given frame.

Parameters:

ParameterC++ typeDescription
nameStringAttr
members::llvm::ArrayRef<WindowFieldType>

ListType

a runtime-variably sized list

Syntax:

!esi.list<
  Type   # elementType
>

In software, a chunk of memory with runtime-specified length. In hardware, a stream of runtime-specified amount of data transmitted over many cycles in compile-time specified specified windows (chunks).

Parameters:

ParameterC++ typeDescription
elementTypeType

esi.buffer (::circt::esi::ChannelBufferOp)

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.

A stages attribute may be provided to specify a specific number of cycles (pipeline stages) to use on this channel. Must be greater than 0.

A name attribute may be provided to assigned a name to a buffered connection.

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

Traits: AlwaysSpeculatableImplTrait

Interfaces: ChannelOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
stages::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 1
name::mlir::StringAttrstring attribute

Operands:

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

Results:

ResultDescription
outputan ESI channel

esi.cosim.from_host (::circt::esi::CosimFromHostEndpointOp)

Co-simulation endpoint receiving data from the host

Syntax:

operation ::= `esi.cosim.from_host` $clk `,` $rst `,` $id attr-dict `:` qualified(type($fromHost))

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

It is uni-directional, in this case receiving data from the host for the simulation.

NOTE: $id MUST be unique across all endpoints at simulation runtime.

Attributes:

AttributeMLIR TypeDescription
id::mlir::StringAttrstring attribute

Operands:

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

Results:

ResultDescription
fromHostan ESI channel

esi.cosim.to_host (::circt::esi::CosimToHostEndpointOp)

Co-simulation endpoint sending data to the host.

Syntax:

operation ::= `esi.cosim.to_host` $clk `,` $rst `,` $toHost`,` $id attr-dict `:` qualified(type($toHost))

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

It is uni-directional, in this case sending data from the simulation to the host.

NOTE: $id MUST be unique across all endpoints at simulation runtime.

Attributes:

AttributeMLIR TypeDescription
id::mlir::StringAttrstring attribute

Operands:

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

esi.fifo (::circt::esi::FIFOOp)

A FIFO with ESI channel connections

Syntax:

operation ::= `esi.fifo` `in` $input `clk` $clk `rst` $rst `depth` $depth attr-dict
              `:` type($input) `->` type($output)

A FIFO is a first-in-first-out buffer. This operation is a simple FIFO which can be used to connect two ESI channels. The ESI channels MUST have FIFO signaling semantics.

Attributes:

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

Operands:

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

Results:

ResultDescription
outputan ESI channel

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

An op which never produces messages.

Syntax:

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

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Results:

ResultDescription
outan ESI channel

esi.bundle.pack (::circt::esi::PackBundleOp)

Pack channels into a bundle

Syntax:

operation ::= `esi.bundle.pack` $toChannels attr-dict `:` custom<UnPackBundleType>(
              type($toChannels), type($fromChannels), type($bundle))

Interfaces: OpAsmOpInterface

Operands:

OperandDescription
toChannelsvariadic of an ESI channel

Results:

ResultDescription
bundlea bundle of channels
fromChannelsvariadic of an ESI channel

esi.stage (::circt::esi::PipelineStageOp)

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.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ChannelOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

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

Results:

ResultDescription
outputan ESI channel

esi.bundle.unpack (::circt::esi::UnpackBundleOp)

Unpack channels from a bundle

Syntax:

operation ::= `esi.bundle.unpack` $fromChannels `from` $bundle attr-dict `:` custom<UnPackBundleType>(
              type($toChannels), type($fromChannels), type($bundle))

Interfaces: OpAsmOpInterface

Operands:

OperandDescription
bundlea bundle of channels
fromChannelsvariadic of an ESI channel

Results:

ResultDescription
toChannelsvariadic of an ESI channel

esi.unwrap.fifo (::circt::esi::UnwrapFIFOOp)

Unwrap a value from an ESI port into a FIFO interface

Syntax:

operation ::= `esi.unwrap.fifo` $chanInput `,` $rden attr-dict `:` qualified(type($chanInput))

Interfaces: ChannelOpInterface, InferTypeOpInterface

Operands:

OperandDescription
chanInputan ESI channel
rden1-bit signless integer

Results:

ResultDescription
dataany type
empty1-bit signless integer

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

Unwrap an SV interface from an ESI port

Syntax:

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

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

Interfaces: ChannelOpInterface

Operands:

OperandDescription
chanInputan ESI channel
interfaceSourcesv.interface

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

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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
chanInputan ESI channel
ready1-bit signless integer

Results:

ResultDescription
rawOutputany type
valid1-bit signless integer

esi.window.unwrap (::circt::esi::UnwrapWindow)

Unwrap a data window into a union

Syntax:

operation ::= `esi.window.unwrap` $window attr-dict `:` qualified(type($window))

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
windowa data window

Results:

ResultDescription
framea UnionType

esi.wrap.fifo (::circt::esi::WrapFIFOOp)

Wrap a value into an ESI port with FIFO signaling

Syntax:

operation ::= `esi.wrap.fifo` $data `,` $empty attr-dict `:`
              custom<WrapFIFOType>(type($data), type($chanOutput))

Interfaces: ChannelOpInterface

Operands:

OperandDescription
dataany type
empty1-bit signless integer

Results:

ResultDescription
chanOutputan ESI channel
rden1-bit signless integer

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

Wrap an SV interface into an ESI port

Syntax:

operation ::= `esi.wrap.iface` $interfaceSink attr-dict `:` qualified(type($interfaceSink)) `->` qualified(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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
interfaceSinksv.interface

Results:

ResultDescription
outputan ESI channel

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

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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
rawInputany type
valid1-bit signless integer

Results:

ResultDescription
chanOutputan ESI channel
ready1-bit signless integer

esi.window.wrap (::circt::esi::WrapWindow)

Wrap a union into a data window

Syntax:

operation ::= `esi.window.wrap` $frame attr-dict `:` custom<InferWindowRet>(type($frame), type($window))

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
framea UnionType

Results:

ResultDescription
windowa data window

Services

ESI “services” provide device-wide connectivity and arbitration for shared resources, which can be requested from any IP block (service “client”). Standard services will include DRAM, clock/reset, statistical counter reporting, and debug.

esi.manifest.hier_node (::circt::esi::AppIDHierNodeOp)

A node in the AppID hierarchy

Syntax:

operation ::= `esi.manifest.hier_node` qualified($appID) `mod` $moduleRef attr-dict-with-keyword $children

Traits: HasParent<circt::esi::AppIDHierRootOp, circt::esi::AppIDHierNodeOp>, NoTerminator, SingleBlock

Attributes:

AttributeMLIR TypeDescription
appID::circt::esi::AppIDAttrAn application relevant instance identifier
moduleRef::mlir::FlatSymbolRefAttrflat symbol reference attribute

esi.manifest.hier_root (::circt::esi::AppIDHierRootOp)

The root of an appid instance hierarchy

Syntax:

operation ::= `esi.manifest.hier_root` $topModuleRef attr-dict-with-keyword $children

Traits: HasParent<mlir::ModuleOp>, NoTerminator, SingleBlock

Attributes:

AttributeMLIR TypeDescription
topModuleRef::mlir::FlatSymbolRefAttrflat symbol reference attribute

esi.buffer (::circt::esi::ChannelBufferOp)

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.

A stages attribute may be provided to specify a specific number of cycles (pipeline stages) to use on this channel. Must be greater than 0.

A name attribute may be provided to assigned a name to a buffered connection.

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

Traits: AlwaysSpeculatableImplTrait

Interfaces: ChannelOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
stages::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 1
name::mlir::StringAttrstring attribute

Operands:

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

Results:

ResultDescription
outputan ESI channel

esi.manifest.compressed (::circt::esi::CompressedManifestOp)

A zlib-compressed JSON manifest

Syntax:

operation ::= `esi.manifest.compressed` $compressedManifest attr-dict

Attributes:

AttributeMLIR TypeDescription
compressedManifest::circt::esi::BlobAttrA binary blob

esi.cosim.from_host (::circt::esi::CosimFromHostEndpointOp)

Co-simulation endpoint receiving data from the host

Syntax:

operation ::= `esi.cosim.from_host` $clk `,` $rst `,` $id attr-dict `:` qualified(type($fromHost))

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

It is uni-directional, in this case receiving data from the host for the simulation.

NOTE: $id MUST be unique across all endpoints at simulation runtime.

Attributes:

AttributeMLIR TypeDescription
id::mlir::StringAttrstring attribute

Operands:

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

Results:

ResultDescription
fromHostan ESI channel

esi.cosim.to_host (::circt::esi::CosimToHostEndpointOp)

Co-simulation endpoint sending data to the host.

Syntax:

operation ::= `esi.cosim.to_host` $clk `,` $rst `,` $toHost`,` $id attr-dict `:` qualified(type($toHost))

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

It is uni-directional, in this case sending data from the simulation to the host.

NOTE: $id MUST be unique across all endpoints at simulation runtime.

Attributes:

AttributeMLIR TypeDescription
id::mlir::StringAttrstring attribute

Operands:

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

esi.service.decl (::circt::esi::CustomServiceDeclOp)

An ESI service interface declaration

Syntax:

operation ::= `esi.service.decl` $sym_name $ports attr-dict

A declaration of an ESI service interface. Defines a contract between a service provider and its clients.

Example:

esi.service.decl @HostComms {
  esi.service.port send : !esi.bundle<[!esi.any from "send"]>
  esi.service.port recieve : !esi.channel<[i8 to "recv"]>
}

Traits: HasParent<::mlir::ModuleOp>, NoTerminator, SingleBlock

Interfaces: ServiceDeclOpInterface, Symbol

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute

esi.fifo (::circt::esi::FIFOOp)

A FIFO with ESI channel connections

Syntax:

operation ::= `esi.fifo` `in` $input `clk` $clk `rst` $rst `depth` $depth attr-dict
              `:` type($input) `->` type($output)

A FIFO is a first-in-first-out buffer. This operation is a simple FIFO which can be used to connect two ESI channels. The ESI channels MUST have FIFO signaling semantics.

Attributes:

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

Operands:

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

Results:

ResultDescription
outputan ESI channel

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

An op which never produces messages.

Syntax:

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

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Results:

ResultDescription
outan ESI channel

esi.bundle.pack (::circt::esi::PackBundleOp)

Pack channels into a bundle

Syntax:

operation ::= `esi.bundle.pack` $toChannels attr-dict `:` custom<UnPackBundleType>(
              type($toChannels), type($fromChannels), type($bundle))

Interfaces: OpAsmOpInterface

Operands:

OperandDescription
toChannelsvariadic of an ESI channel

Results:

ResultDescription
bundlea bundle of channels
fromChannelsvariadic of an ESI channel

esi.stage (::circt::esi::PipelineStageOp)

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.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ChannelOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

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

Results:

ResultDescription
outputan ESI channel

esi.service.req (::circt::esi::RequestConnectionOp)

Request a connection to receive data

Syntax:

operation ::= `esi.service.req` $servicePort `(` qualified($appID) `)`
              attr-dict `:` qualified(type($toClient))

Interfaces: HasAppID, SymbolUserOpInterface

Attributes:

AttributeMLIR TypeDescription
servicePort::circt::hw::InnerRefAttrRefer to a name inside a module
appID::circt::esi::AppIDAttrAn application relevant instance identifier

Results:

ResultDescription
toClienta bundle of channels

esi.service.port (::circt::esi::ServiceDeclPortOp)

An ESI service bundle being received by the client

Syntax:

operation ::= `esi.service.port` $inner_sym  attr-dict `:` $toClientType

Traits: HasParent<::circt::esi::CustomServiceDeclOp>

Attributes:

AttributeMLIR TypeDescription
inner_sym::mlir::StringAttrstring attribute
toClientType::mlir::TypeAttrtype attribute of a bundle of channels

esi.manifest.impl_conn (::circt::esi::ServiceImplClientRecordOp)

Details of a service implementation client connection

Syntax:

operation ::= `esi.manifest.impl_conn` $relAppIDPath `req` $servicePort `(` $typeID `)`
              (`channels` $channelAssignments^)? (`with` $implDetails^)? attr-dict

A record containing all the necessary details of how to connect to a client which the parent service record is servicing. Emitted on a per-client bundle basis. There shall be at most on of these records in the entire manifest for a particular client.

Traits: HasParent<ServiceImplRecordOp>

Interfaces: IsManifestData

Attributes:

AttributeMLIR TypeDescription
relAppIDPath::mlir::ArrayAttrArray of AppIDs
servicePort::circt::hw::InnerRefAttrRefer to a name inside a module
typeID::mlir::TypeAttrtype attribute of a bundle of channels
channelAssignments::mlir::DictionaryAttrdictionary of named attribute values
implDetails::mlir::DictionaryAttrdictionary of named attribute values

esi.manifest.service_impl (::circt::esi::ServiceImplRecordOp)

Record of a service implementation

Syntax:

operation ::= `esi.manifest.service_impl` qualified($appID) (`svc` $service^)? (`std` $stdService^)?
              `by` $serviceImplName `with` $implDetails
              attr-dict-with-keyword custom<ServiceImplRecordReqDetails>($reqDetails)

A record of a service implementation. Optionally emitted by the service implementation. Contains information necessary to connect to the service and service clients.

Traits: NoTerminator

Interfaces: HasAppID, IsManifestData

Attributes:

AttributeMLIR TypeDescription
appID::circt::esi::AppIDAttrAn application relevant instance identifier
service::mlir::FlatSymbolRefAttrflat symbol reference attribute
stdService::mlir::StringAttrstring attribute
serviceImplName::mlir::StringAttrstring attribute
implDetails::mlir::DictionaryAttrdictionary of named attribute values

esi.service.impl_req.req (::circt::esi::ServiceImplementConnReqOp)

The canonical form of a connection request

Syntax:

operation ::= `esi.service.impl_req.req` $servicePort `(` $relativeAppIDPath `)`
              attr-dict `:` qualified(type($toClient))

Interfaces: SymbolUserOpInterface

Attributes:

AttributeMLIR TypeDescription
servicePort::circt::hw::InnerRefAttrRefer to a name inside a module
relativeAppIDPath::mlir::ArrayAttrArray of AppIDs

Results:

ResultDescription
toClienta bundle of channels

esi.service.impl_req (::circt::esi::ServiceImplementReqOp)

Request for a service to be implemented

Syntax:

operation ::= `esi.service.impl_req` qualified($appID) (`svc` $service_symbol^)? `impl` `as` $impl_type
              (`std` $stdService^)? (`opts` $impl_opts^)? `(` $inputs `)`
              attr-dict `:` functional-type($inputs, results)
              $portReqs

The connect services pass replaces service.instances with this op. The portReqs region is the set of connection requests which need to be implemented for this service instance. Channels to/from the requests have been added to the operands/results of this op and consumers/producers have been redirected.

Some other pass or frontend is expected to replace this op with an actual implementation.

Traits: NoTerminator

Interfaces: HasAppID

Attributes:

AttributeMLIR TypeDescription
appID::circt::esi::AppIDAttrAn application relevant instance identifier
service_symbol::mlir::FlatSymbolRefAttrflat symbol reference attribute
impl_type::mlir::StringAttrstring attribute
stdService::mlir::StringAttrstring attribute
impl_opts::mlir::DictionaryAttrdictionary of named attribute values

Operands:

OperandDescription
inputsvariadic of any type

Results:

ResultDescription
outputsvariadic of any type

esi.service.instance (::circt::esi::ServiceInstanceOp)

Instantiate a server module

Syntax:

operation ::= `esi.service.instance` qualified($appID) (`svc` $service_symbol^)? `impl` `as` $impl_type
              (`opts` $impl_opts^)? `(` $inputs `)`
              attr-dict `:` functional-type($inputs, results)

Instantiate a service adhering to a service declaration interface.

A pass collects all of the connection requests to the service this op implements from the containing modules’ descendants (in the instance hierarchy). It bubbles them all up to the module containing this op, creating the necessary ESI channel ports, groups them appropriately, then replaces this op with a service.impl_req.

If ‘service_symbol’ isn’t specified, this instance will be used to implement all of the service requests which get surfaced to here. This option is generally used at the top level to specify host connectivity.

Since implementing the server will usually need “normal” I/O, inputs and results act like normal hw.instance ports.

$identifier is used by frontends to specify or remember the type of implementation to use for this service.

Interfaces: HasAppID

Attributes:

AttributeMLIR TypeDescription
appID::circt::esi::AppIDAttrAn application relevant instance identifier
service_symbol::mlir::FlatSymbolRefAttrflat symbol reference attribute
impl_type::mlir::StringAttrstring attribute
impl_opts::mlir::DictionaryAttrdictionary of named attribute values

Operands:

OperandDescription
inputsvariadic of any type

Results:

ResultDescription
«unnamed»variadic of any type

esi.manifest.req (::circt::esi::ServiceRequestRecordOp)

Record of a service request

Syntax:

operation ::= `esi.manifest.req` qualified($requestor) `,` $servicePort (`std` $stdService^)?
              `,` $typeID attr-dict

A record of a service request, including the requestor, the service requested, and the parameters of the request. Emitted before connecting the service to preserve metadata about the original request.

Interfaces: HasAppID, IsManifestData

Attributes:

AttributeMLIR TypeDescription
requestor::circt::esi::AppIDAttrAn application relevant instance identifier
servicePort::circt::hw::InnerRefAttrRefer to a name inside a module
stdService::mlir::StringAttrstring attribute
typeID::mlir::TypeAttrtype attribute of a bundle of channels

esi.manifest.constants (::circt::esi::SymbolConstantsOp)

Constant values associated with a symbol

Syntax:

operation ::= `esi.manifest.constants` $symbolRef $constants attr-dict

Interfaces: IsManifestData

Attributes:

AttributeMLIR TypeDescription
symbolRef::mlir::FlatSymbolRefAttrflat symbol reference attribute
constants::mlir::DictionaryAttrdictionary of named attribute values

esi.manifest.sym (::circt::esi::SymbolMetadataOp)

Metadata about a symbol

Syntax:

operation ::= `esi.manifest.sym` $symbolRef
              (`name` $name^)?
              (`repo` $repo^)?
              (`commit` $commitHash^)?
              (`version` $version^)?
              (`summary` $summary^)?
              attr-dict

Metadata about a symbol, including its name, repository, commit hash, version, and summary. All are optional, but strongly encouraged. Any additional metadata which users wish to attach should go as discardable attributes.

Interfaces: IsManifestData

Attributes:

AttributeMLIR TypeDescription
symbolRef::mlir::FlatSymbolRefAttrflat symbol reference attribute
name::mlir::StringAttrstring attribute
repo::mlir::StringAttrstring attribute
commitHash::mlir::StringAttrstring attribute
version::mlir::StringAttrstring attribute
summary::mlir::StringAttrstring attribute

esi.bundle.unpack (::circt::esi::UnpackBundleOp)

Unpack channels from a bundle

Syntax:

operation ::= `esi.bundle.unpack` $fromChannels `from` $bundle attr-dict `:` custom<UnPackBundleType>(
              type($toChannels), type($fromChannels), type($bundle))

Interfaces: OpAsmOpInterface

Operands:

OperandDescription
bundlea bundle of channels
fromChannelsvariadic of an ESI channel

Results:

ResultDescription
toChannelsvariadic of an ESI channel

esi.unwrap.fifo (::circt::esi::UnwrapFIFOOp)

Unwrap a value from an ESI port into a FIFO interface

Syntax:

operation ::= `esi.unwrap.fifo` $chanInput `,` $rden attr-dict `:` qualified(type($chanInput))

Interfaces: ChannelOpInterface, InferTypeOpInterface

Operands:

OperandDescription
chanInputan ESI channel
rden1-bit signless integer

Results:

ResultDescription
dataany type
empty1-bit signless integer

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

Unwrap an SV interface from an ESI port

Syntax:

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

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

Interfaces: ChannelOpInterface

Operands:

OperandDescription
chanInputan ESI channel
interfaceSourcesv.interface

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

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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
chanInputan ESI channel
ready1-bit signless integer

Results:

ResultDescription
rawOutputany type
valid1-bit signless integer

esi.window.unwrap (::circt::esi::UnwrapWindow)

Unwrap a data window into a union

Syntax:

operation ::= `esi.window.unwrap` $window attr-dict `:` qualified(type($window))

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
windowa data window

Results:

ResultDescription
framea UnionType

esi.wrap.fifo (::circt::esi::WrapFIFOOp)

Wrap a value into an ESI port with FIFO signaling

Syntax:

operation ::= `esi.wrap.fifo` $data `,` $empty attr-dict `:`
              custom<WrapFIFOType>(type($data), type($chanOutput))

Interfaces: ChannelOpInterface

Operands:

OperandDescription
dataany type
empty1-bit signless integer

Results:

ResultDescription
chanOutputan ESI channel
rden1-bit signless integer

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

Wrap an SV interface into an ESI port

Syntax:

operation ::= `esi.wrap.iface` $interfaceSink attr-dict `:` qualified(type($interfaceSink)) `->` qualified(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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
interfaceSinksv.interface

Results:

ResultDescription
outputan ESI channel

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

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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
rawInputany type
valid1-bit signless integer

Results:

ResultDescription
chanOutputan ESI channel
ready1-bit signless integer

esi.window.wrap (::circt::esi::WrapWindow)

Wrap a union into a data window

Syntax:

operation ::= `esi.window.wrap` $frame attr-dict `:` custom<InferWindowRet>(type($frame), type($window))

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
framea UnionType

Results:

ResultDescription
windowa data window

esi.manifest.hier_node (::circt::esi::AppIDHierNodeOp)

A node in the AppID hierarchy

Syntax:

operation ::= `esi.manifest.hier_node` qualified($appID) `mod` $moduleRef attr-dict-with-keyword $children

Traits: HasParent<circt::esi::AppIDHierRootOp, circt::esi::AppIDHierNodeOp>, NoTerminator, SingleBlock

Attributes:

AttributeMLIR TypeDescription
appID::circt::esi::AppIDAttrAn application relevant instance identifier
moduleRef::mlir::FlatSymbolRefAttrflat symbol reference attribute

esi.manifest.hier_root (::circt::esi::AppIDHierRootOp)

The root of an appid instance hierarchy

Syntax:

operation ::= `esi.manifest.hier_root` $topModuleRef attr-dict-with-keyword $children

Traits: HasParent<mlir::ModuleOp>, NoTerminator, SingleBlock

Attributes:

AttributeMLIR TypeDescription
topModuleRef::mlir::FlatSymbolRefAttrflat symbol reference attribute

esi.service.std.call (::circt::esi::CallServiceDeclOp)

Service against which hardware can call into software

Syntax:

operation ::= `esi.service.std.call` $sym_name attr-dict

Traits: HasParent<::mlir::ModuleOp>, NoTerminator, SingleBlock

Interfaces: ServiceDeclOpInterface, Symbol

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute

esi.buffer (::circt::esi::ChannelBufferOp)

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.

A stages attribute may be provided to specify a specific number of cycles (pipeline stages) to use on this channel. Must be greater than 0.

A name attribute may be provided to assigned a name to a buffered connection.

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

Traits: AlwaysSpeculatableImplTrait

Interfaces: ChannelOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Attributes:

AttributeMLIR TypeDescription
stages::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 1
name::mlir::StringAttrstring attribute

Operands:

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

Results:

ResultDescription
outputan ESI channel

esi.manifest.compressed (::circt::esi::CompressedManifestOp)

A zlib-compressed JSON manifest

Syntax:

operation ::= `esi.manifest.compressed` $compressedManifest attr-dict

Attributes:

AttributeMLIR TypeDescription
compressedManifest::circt::esi::BlobAttrA binary blob

esi.cosim.from_host (::circt::esi::CosimFromHostEndpointOp)

Co-simulation endpoint receiving data from the host

Syntax:

operation ::= `esi.cosim.from_host` $clk `,` $rst `,` $id attr-dict `:` qualified(type($fromHost))

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

It is uni-directional, in this case receiving data from the host for the simulation.

NOTE: $id MUST be unique across all endpoints at simulation runtime.

Attributes:

AttributeMLIR TypeDescription
id::mlir::StringAttrstring attribute

Operands:

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

Results:

ResultDescription
fromHostan ESI channel

esi.cosim.to_host (::circt::esi::CosimToHostEndpointOp)

Co-simulation endpoint sending data to the host.

Syntax:

operation ::= `esi.cosim.to_host` $clk `,` $rst `,` $toHost`,` $id attr-dict `:` qualified(type($toHost))

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

It is uni-directional, in this case sending data from the simulation to the host.

NOTE: $id MUST be unique across all endpoints at simulation runtime.

Attributes:

AttributeMLIR TypeDescription
id::mlir::StringAttrstring attribute

Operands:

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

esi.service.decl (::circt::esi::CustomServiceDeclOp)

An ESI service interface declaration

Syntax:

operation ::= `esi.service.decl` $sym_name $ports attr-dict

A declaration of an ESI service interface. Defines a contract between a service provider and its clients.

Example:

esi.service.decl @HostComms {
  esi.service.port send : !esi.bundle<[!esi.any from "send"]>
  esi.service.port recieve : !esi.channel<[i8 to "recv"]>
}

Traits: HasParent<::mlir::ModuleOp>, NoTerminator, SingleBlock

Interfaces: ServiceDeclOpInterface, Symbol

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute

esi.fifo (::circt::esi::FIFOOp)

A FIFO with ESI channel connections

Syntax:

operation ::= `esi.fifo` `in` $input `clk` $clk `rst` $rst `depth` $depth attr-dict
              `:` type($input) `->` type($output)

A FIFO is a first-in-first-out buffer. This operation is a simple FIFO which can be used to connect two ESI channels. The ESI channels MUST have FIFO signaling semantics.

Attributes:

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

Operands:

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

Results:

ResultDescription
outputan ESI channel

esi.service.std.func (::circt::esi::FuncServiceDeclOp)

Function service

Syntax:

operation ::= `esi.service.std.func` $sym_name attr-dict

Declares a service which provides a function call interface to a client.

Ports: to_client call(args: any) -> result: any Client exposes a function call interface to the user and does not allow out-of-order returns.

TODO: ports for out-of-order returns

Traits: HasParent<::mlir::ModuleOp>, NoTerminator, SingleBlock

Interfaces: ServiceDeclOpInterface, Symbol

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute

esi.service.std.hostmem (::circt::esi::HostMemServiceDeclOp)

Host memory service

Syntax:

operation ::= `esi.service.std.hostmem` $sym_name attr-dict

Declares a service to read/write host memory. Used for DMA services. Must be implemented by a BSP.

Traits: HasParent<::mlir::ModuleOp>

Interfaces: ServiceDeclOpInterface, Symbol

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute

esi.service.std.mmio (::circt::esi::MMIOServiceDeclOp)

MMIO service

Syntax:

operation ::= `esi.service.std.mmio` $sym_name attr-dict

Declares a service to be backed by a MMIO interface, which is platform dependent. Must be implemented by a BSP.

Traits: HasParent<::mlir::ModuleOp>

Interfaces: ServiceDeclOpInterface, Symbol

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute

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

An op which never produces messages.

Syntax:

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

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Results:

ResultDescription
outan ESI channel

esi.bundle.pack (::circt::esi::PackBundleOp)

Pack channels into a bundle

Syntax:

operation ::= `esi.bundle.pack` $toChannels attr-dict `:` custom<UnPackBundleType>(
              type($toChannels), type($fromChannels), type($bundle))

Interfaces: OpAsmOpInterface

Operands:

OperandDescription
toChannelsvariadic of an ESI channel

Results:

ResultDescription
bundlea bundle of channels
fromChannelsvariadic of an ESI channel

esi.stage (::circt::esi::PipelineStageOp)

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.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ChannelOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

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

Results:

ResultDescription
outputan ESI channel

esi.mem.ram (::circt::esi::RandomAccessMemoryDeclOp)

Random access memory service

Syntax:

operation ::= `esi.mem.ram` $sym_name $innerType `x` $depth attr-dict

Declares a service which is backed by a memory of some sort. Allows random access of the inner elements.

Ports: read(address: clog2(depth)) -> data: innerType write({address: clog2(depth), data: innerType}) -> done: i0

Users can ensure R/W ordering by waiting for the write “done” message before issuing a potentially dependant read. Ordering of R/W messages in flight is undefined.

Traits: HasParent<::mlir::ModuleOp>, NoTerminator, SingleBlock

Interfaces: ServiceDeclOpInterface, Symbol

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
innerType::mlir::TypeAttrany type attribute
depth::mlir::IntegerAttr64-bit signless integer attribute

esi.service.req (::circt::esi::RequestConnectionOp)

Request a connection to receive data

Syntax:

operation ::= `esi.service.req` $servicePort `(` qualified($appID) `)`
              attr-dict `:` qualified(type($toClient))

Interfaces: HasAppID, SymbolUserOpInterface

Attributes:

AttributeMLIR TypeDescription
servicePort::circt::hw::InnerRefAttrRefer to a name inside a module
appID::circt::esi::AppIDAttrAn application relevant instance identifier

Results:

ResultDescription
toClienta bundle of channels

esi.service.port (::circt::esi::ServiceDeclPortOp)

An ESI service bundle being received by the client

Syntax:

operation ::= `esi.service.port` $inner_sym  attr-dict `:` $toClientType

Traits: HasParent<::circt::esi::CustomServiceDeclOp>

Attributes:

AttributeMLIR TypeDescription
inner_sym::mlir::StringAttrstring attribute
toClientType::mlir::TypeAttrtype attribute of a bundle of channels

esi.manifest.impl_conn (::circt::esi::ServiceImplClientRecordOp)

Details of a service implementation client connection

Syntax:

operation ::= `esi.manifest.impl_conn` $relAppIDPath `req` $servicePort `(` $typeID `)`
              (`channels` $channelAssignments^)? (`with` $implDetails^)? attr-dict

A record containing all the necessary details of how to connect to a client which the parent service record is servicing. Emitted on a per-client bundle basis. There shall be at most on of these records in the entire manifest for a particular client.

Traits: HasParent<ServiceImplRecordOp>

Interfaces: IsManifestData

Attributes:

AttributeMLIR TypeDescription
relAppIDPath::mlir::ArrayAttrArray of AppIDs
servicePort::circt::hw::InnerRefAttrRefer to a name inside a module
typeID::mlir::TypeAttrtype attribute of a bundle of channels
channelAssignments::mlir::DictionaryAttrdictionary of named attribute values
implDetails::mlir::DictionaryAttrdictionary of named attribute values

esi.manifest.service_impl (::circt::esi::ServiceImplRecordOp)

Record of a service implementation

Syntax:

operation ::= `esi.manifest.service_impl` qualified($appID) (`svc` $service^)? (`std` $stdService^)?
              `by` $serviceImplName `with` $implDetails
              attr-dict-with-keyword custom<ServiceImplRecordReqDetails>($reqDetails)

A record of a service implementation. Optionally emitted by the service implementation. Contains information necessary to connect to the service and service clients.

Traits: NoTerminator

Interfaces: HasAppID, IsManifestData

Attributes:

AttributeMLIR TypeDescription
appID::circt::esi::AppIDAttrAn application relevant instance identifier
service::mlir::FlatSymbolRefAttrflat symbol reference attribute
stdService::mlir::StringAttrstring attribute
serviceImplName::mlir::StringAttrstring attribute
implDetails::mlir::DictionaryAttrdictionary of named attribute values

esi.service.impl_req.req (::circt::esi::ServiceImplementConnReqOp)

The canonical form of a connection request

Syntax:

operation ::= `esi.service.impl_req.req` $servicePort `(` $relativeAppIDPath `)`
              attr-dict `:` qualified(type($toClient))

Interfaces: SymbolUserOpInterface

Attributes:

AttributeMLIR TypeDescription
servicePort::circt::hw::InnerRefAttrRefer to a name inside a module
relativeAppIDPath::mlir::ArrayAttrArray of AppIDs

Results:

ResultDescription
toClienta bundle of channels

esi.service.impl_req (::circt::esi::ServiceImplementReqOp)

Request for a service to be implemented

Syntax:

operation ::= `esi.service.impl_req` qualified($appID) (`svc` $service_symbol^)? `impl` `as` $impl_type
              (`std` $stdService^)? (`opts` $impl_opts^)? `(` $inputs `)`
              attr-dict `:` functional-type($inputs, results)
              $portReqs

The connect services pass replaces service.instances with this op. The portReqs region is the set of connection requests which need to be implemented for this service instance. Channels to/from the requests have been added to the operands/results of this op and consumers/producers have been redirected.

Some other pass or frontend is expected to replace this op with an actual implementation.

Traits: NoTerminator

Interfaces: HasAppID

Attributes:

AttributeMLIR TypeDescription
appID::circt::esi::AppIDAttrAn application relevant instance identifier
service_symbol::mlir::FlatSymbolRefAttrflat symbol reference attribute
impl_type::mlir::StringAttrstring attribute
stdService::mlir::StringAttrstring attribute
impl_opts::mlir::DictionaryAttrdictionary of named attribute values

Operands:

OperandDescription
inputsvariadic of any type

Results:

ResultDescription
outputsvariadic of any type

esi.service.instance (::circt::esi::ServiceInstanceOp)

Instantiate a server module

Syntax:

operation ::= `esi.service.instance` qualified($appID) (`svc` $service_symbol^)? `impl` `as` $impl_type
              (`opts` $impl_opts^)? `(` $inputs `)`
              attr-dict `:` functional-type($inputs, results)

Instantiate a service adhering to a service declaration interface.

A pass collects all of the connection requests to the service this op implements from the containing modules’ descendants (in the instance hierarchy). It bubbles them all up to the module containing this op, creating the necessary ESI channel ports, groups them appropriately, then replaces this op with a service.impl_req.

If ‘service_symbol’ isn’t specified, this instance will be used to implement all of the service requests which get surfaced to here. This option is generally used at the top level to specify host connectivity.

Since implementing the server will usually need “normal” I/O, inputs and results act like normal hw.instance ports.

$identifier is used by frontends to specify or remember the type of implementation to use for this service.

Interfaces: HasAppID

Attributes:

AttributeMLIR TypeDescription
appID::circt::esi::AppIDAttrAn application relevant instance identifier
service_symbol::mlir::FlatSymbolRefAttrflat symbol reference attribute
impl_type::mlir::StringAttrstring attribute
impl_opts::mlir::DictionaryAttrdictionary of named attribute values

Operands:

OperandDescription
inputsvariadic of any type

Results:

ResultDescription
«unnamed»variadic of any type

esi.manifest.req (::circt::esi::ServiceRequestRecordOp)

Record of a service request

Syntax:

operation ::= `esi.manifest.req` qualified($requestor) `,` $servicePort (`std` $stdService^)?
              `,` $typeID attr-dict

A record of a service request, including the requestor, the service requested, and the parameters of the request. Emitted before connecting the service to preserve metadata about the original request.

Interfaces: HasAppID, IsManifestData

Attributes:

AttributeMLIR TypeDescription
requestor::circt::esi::AppIDAttrAn application relevant instance identifier
servicePort::circt::hw::InnerRefAttrRefer to a name inside a module
stdService::mlir::StringAttrstring attribute
typeID::mlir::TypeAttrtype attribute of a bundle of channels

esi.manifest.constants (::circt::esi::SymbolConstantsOp)

Constant values associated with a symbol

Syntax:

operation ::= `esi.manifest.constants` $symbolRef $constants attr-dict

Interfaces: IsManifestData

Attributes:

AttributeMLIR TypeDescription
symbolRef::mlir::FlatSymbolRefAttrflat symbol reference attribute
constants::mlir::DictionaryAttrdictionary of named attribute values

esi.manifest.sym (::circt::esi::SymbolMetadataOp)

Metadata about a symbol

Syntax:

operation ::= `esi.manifest.sym` $symbolRef
              (`name` $name^)?
              (`repo` $repo^)?
              (`commit` $commitHash^)?
              (`version` $version^)?
              (`summary` $summary^)?
              attr-dict

Metadata about a symbol, including its name, repository, commit hash, version, and summary. All are optional, but strongly encouraged. Any additional metadata which users wish to attach should go as discardable attributes.

Interfaces: IsManifestData

Attributes:

AttributeMLIR TypeDescription
symbolRef::mlir::FlatSymbolRefAttrflat symbol reference attribute
name::mlir::StringAttrstring attribute
repo::mlir::StringAttrstring attribute
commitHash::mlir::StringAttrstring attribute
version::mlir::StringAttrstring attribute
summary::mlir::StringAttrstring attribute

esi.bundle.unpack (::circt::esi::UnpackBundleOp)

Unpack channels from a bundle

Syntax:

operation ::= `esi.bundle.unpack` $fromChannels `from` $bundle attr-dict `:` custom<UnPackBundleType>(
              type($toChannels), type($fromChannels), type($bundle))

Interfaces: OpAsmOpInterface

Operands:

OperandDescription
bundlea bundle of channels
fromChannelsvariadic of an ESI channel

Results:

ResultDescription
toChannelsvariadic of an ESI channel

esi.unwrap.fifo (::circt::esi::UnwrapFIFOOp)

Unwrap a value from an ESI port into a FIFO interface

Syntax:

operation ::= `esi.unwrap.fifo` $chanInput `,` $rden attr-dict `:` qualified(type($chanInput))

Interfaces: ChannelOpInterface, InferTypeOpInterface

Operands:

OperandDescription
chanInputan ESI channel
rden1-bit signless integer

Results:

ResultDescription
dataany type
empty1-bit signless integer

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

Unwrap an SV interface from an ESI port

Syntax:

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

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

Interfaces: ChannelOpInterface

Operands:

OperandDescription
chanInputan ESI channel
interfaceSourcesv.interface

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

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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
chanInputan ESI channel
ready1-bit signless integer

Results:

ResultDescription
rawOutputany type
valid1-bit signless integer

esi.window.unwrap (::circt::esi::UnwrapWindow)

Unwrap a data window into a union

Syntax:

operation ::= `esi.window.unwrap` $window attr-dict `:` qualified(type($window))

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
windowa data window

Results:

ResultDescription
framea UnionType

esi.wrap.fifo (::circt::esi::WrapFIFOOp)

Wrap a value into an ESI port with FIFO signaling

Syntax:

operation ::= `esi.wrap.fifo` $data `,` $empty attr-dict `:`
              custom<WrapFIFOType>(type($data), type($chanOutput))

Interfaces: ChannelOpInterface

Operands:

OperandDescription
dataany type
empty1-bit signless integer

Results:

ResultDescription
chanOutputan ESI channel
rden1-bit signless integer

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

Wrap an SV interface into an ESI port

Syntax:

operation ::= `esi.wrap.iface` $interfaceSink attr-dict `:` qualified(type($interfaceSink)) `->` qualified(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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
interfaceSinksv.interface

Results:

ResultDescription
outputan ESI channel

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

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.

Interfaces: ChannelOpInterface

Operands:

OperandDescription
rawInputany type
valid1-bit signless integer

Results:

ResultDescription
chanOutputan ESI channel
ready1-bit signless integer

esi.window.wrap (::circt::esi::WrapWindow)

Wrap a union into a data window

Syntax:

operation ::= `esi.window.wrap` $frame attr-dict `:` custom<InferWindowRet>(type($frame), type($window))

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

Operands:

OperandDescription
framea UnionType

Results:

ResultDescription
windowa data window

Structural

ESI has a special module which doesn’t expose ports. All external interactions are expected to be done through services.

esi.pure_module.input (::circt::esi::ESIPureModuleInputOp)

Inputs become input ports when the module is lowered

Syntax:

operation ::= `esi.pure_module.input` $name attr-dict `:` type($value)

To create input ports when lowering a pure module op into an HWModuleOp, use this op. This op is typically created by a service implementation generator.

If two ‘input’ ops exist in the same block, the names match, and the type matches they’ll become one port during lowering. Two or more may not exist with the same name and different types. Useful for ‘clk’ and ‘rst’.

Traits: HasParent<ESIPureModuleOp>

Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute

Results:

ResultDescription
valueany type

esi.pure_module (::circt::esi::ESIPureModuleOp)

ESI pure module

Syntax:

operation ::= `esi.pure_module` $sym_name attr-dict-with-keyword $body

A module containing only ESI channels and modules with only ESI ports. All non-local connectivity is done through ESI services. If this module is the top level in the design, then the design’s actual top level ports are defined by a BSP.

Useful on its own for simulation and BSPs which don’t define a top-level.

Traits: HasParent<mlir::ModuleOp>, NoRegionArguments, NoTerminator, SingleBlock

Interfaces: HWModuleLike, InstanceGraphModuleOpInterface, PortList, RegionKindInterface, Symbol

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute

esi.pure_module.output (::circt::esi::ESIPureModuleOutputOp)

Outputs become output ports when the module is lowered

Syntax:

operation ::= `esi.pure_module.output` $name `,` $value attr-dict `:` type($value)

To create output ports when lowering a pure module op into an HWModuleOp, use this op. This op is typically created by a service implementation generator.

Two ‘output’ ops with the same name cannot exist in the same block.

Traits: HasParent<ESIPureModuleOp>

Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute

Operands:

OperandDescription
valueany type

esi.pure_module.param (::circt::esi::ESIPureModuleParamOp)

Params become module parameters when the module is lowered

Syntax:

operation ::= `esi.pure_module.param` $name `:` $type attr-dict

Allows attaching parameters to modules which become HW module parameters when lowering. Currently, they are ignored. Some low-level BSPs instantiate modules with parameters. This allows the modules produced to accept parameters so those BSPs can instantiate them.

Traits: HasParent<ESIPureModuleOp>

Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
type::mlir::TypeAttrany type attribute

Interfaces

Misc CIRCT interfaces.

ChannelOpInterface (ChannelOpInterface)

“An interface for operations which carries channel semantics.”

Methods:

channelType

circt::esi::ChannelType channelType();

“Returns the channel type of this operation.”

NOTE: This method must be implemented by the user.

innerType

mlir::Type innerType();

“Returns the inner type of this channel. This will be the type of the data value of the channel, if the channel carries data semantics. Else, return NoneType.”

NOTE: This method must be implemented by the user.

HasAppID (HasAppIDOpInterface)

Op can be identified by an AppID.

Methods:

getAppID

::circt::esi::AppIDAttr getAppID();

Returns the AppID of this operation.

NOTE: This method must be implemented by the user.

IsManifestData (IsManifestData)

Op’s attributes should be represented in the manifest.

Methods:

getManifestClass

static StringRef getManifestClass();

Get the class name for this op.

NOTE: This method must be implemented by the user.

getSymbolRefAttr

FlatSymbolRefAttr getSymbolRefAttr();

Get the symbol to which this manifest data is referring, if any.

NOTE: This method must be implemented by the user.

getDetails

void getDetails(SmallVectorImpl<NamedAttribute>&results);

Populate results with the manifest data.

NOTE: This method must be implemented by the user.

getDetailsAsDict

DictionaryAttr getDetailsAsDict();

Get the manifest data from this op as an attribute.

NOTE: This method must be implemented by the user.

ServiceDeclOpInterface (ServiceDeclOpInterface)

Any op which represents a service declaration should implement this interface.

Methods:

getPortList

void getPortList(llvm::SmallVectorImpl<ServicePortInfo>&ports);

Returns the list of interface ports for this service interface.

NOTE: This method must be implemented by the user.

getTypeName

std::optional<StringRef> getTypeName();

Return a well-known name for this service type.

NOTE: This method must be implemented by the user.

getPortInfo

FailureOr<ServicePortInfo> getPortInfo(StringAttr portName);

Get info on a particular port.

NOTE: This method must be implemented by the user.

'esi' Dialect Docs