# 'dfg' Dialect The `dfg` dialect groups together a set of types, operations and transformations that are useful to implement a structured abstraction on dataflow graphs. These abstractions are useful for constructing KPN/SDF-like dataflow graphs, which include definitions of nodes, edges and their connections. [TOC] ## Operations ### `dfg.channel` (dfg::ChannelOp) _Defines a channel with one input and one output port_ The `channel` operation produces a typed channel (i.e. an edge in the dataflow graph) that links two nodes (i.e. process or operator) in the dataflow graph. The input of a channel will be connected to an output port of a node, which means its type is dfg::InputType, same for output port. A channel can also be sized manually with a 32-bit integer, otherwise, it indicates an unbounded FIFO channel. The token flows in the channel can also be of memref/tensor type, which implicitly enables multiple read/write as in KPN MoC. Examples: ``` %input, %output = dfg.channel() : type $input, %output = dfg.channel(size) : shape x type ``` Interfaces: `DFG_EdgeInterface`, `MemoryEffectsOpInterface`, `OpAsmOpInterface` #### Attributes:
AttributeMLIR TypeDescription
token_type::mlir::TypeAttrany type attribute
buffer_size::mlir::IntegerAttr32-bit signless integer attribute
#### Results: | Result | Description | | :----: | ----------- | | `input_port` | Sending channel end type | | `output_port` | Receiving channel end type | ### `dfg.embed` (dfg::EmbedOp) _Embed a region as a subgraph in another._ The `embed` operation embed a region into another region. The syntax and usage of this operation is similar to `instantiate` operation. ``` dfg.region @child inputs(...) outputs(...) {...} dfg.region @parent inputs(...) outputs(...) { dfg.embed @child inputs(...) outputs(...) : (...) -> (...) } ``` Traits: `AttrSizedOperandSegments` Interfaces: `DFG_GraphInterface`, `DFG_NodeInterface` #### Attributes:
AttributeMLIR TypeDescription
actor::mlir::SymbolRefAttrsymbol reference attribute
offloaded::mlir::dfg::OffloadHardwareAttrThe hardware back to be offloaded to
#### Operands: | Operand | Description | | :-----: | ----------- | | `inputs` | variadic of Receiving channel end type | | `outputs` | variadic of Sending channel end type | ### `dfg.instantiate` (dfg::InstantiateOp) _Instantiates an DFG node._ The `instantiate` operation instantiate an operator or process in a region with a set of inputs and outputs. InstantiateOp creates a DFG node with a set of input and output values. ``` dfg.operator @operator inputs(...) outputs(...) {...} dfg.process @process inputs(...) outputs(...) {...} dfg.region @graph inputs(...) outputs(...) { dfg.instantiate @operator inputs(...) outputs(...) : (...) -> (...) dfg.instantiate @process inputs(...) outputs(...) : (...) -> (...) } ``` Traits: `AttrSizedOperandSegments` Interfaces: `DFG_NodeInterface` #### Attributes:
AttributeMLIR TypeDescription
actor::mlir::SymbolRefAttrsymbol reference attribute
offloaded::mlir::dfg::OffloadHardwareAttrThe hardware back to be offloaded to
#### Operands: | Operand | Description | | :-----: | ----------- | | `inputs` | variadic of Receiving channel end type | | `outputs` | variadic of Sending channel end type | ### `dfg.loop` (dfg::LoopOp) _Defines the repeatedly executed body of a process._ The `loop` operation defines the repeatedly executed body of a process. During each iteration, operations in the body can pull tokens from the process input ports, perform computations, and push tokens to the process output ports. The `inputs` and `outputs` lists identify the process ports that are monitored for stream termination. A port is closed when no further tokens will be transferred through it. When closure is observed on the listed input ports, the process loop terminates and closure propagates through its listed output ports. This allows downstream processes, and eventually the whole dataflow graph, to shut down. Example: ``` dfg.process @add inputs(%a: !dfg.output) outputs(%b: !dfg.input) { dfg.loop inputs(%a: !dfg.output) outputs(%b: !dfg.input) { ops ... } } ``` Traits: `AttrSizedOperandSegments`, `AutomaticAllocationScope`, `HasParent`, `NoTerminator`, `RecursiveMemoryEffects` #### Operands: | Operand | Description | | :-----: | ----------- | | `input_channels` | variadic of Receiving channel end type | | `output_channels` | variadic of Sending channel end type | ### `dfg.operator` (dfg::OperatorOp) _Defines an DFG node in SDF MoC_ The `operator` operation defines one node (actor) in the SDF dataflow model. An operator is a special case of `process`, which only write values into output ports once at the end. Example: ``` dfg.operator @node inputs(%in0: i32, %in1: i32) outputs(%out0: i32, %out1: i32) { ops ... dfg.output ... } ``` Traits: `AffineScope`, `AutomaticAllocationScope`, `HasParent`, `IsolatedFromAbove`, `SingleBlockImplicitTerminator`, `SingleBlock` Interfaces: `DFG_NodeInterface`, `OpAsmOpInterface` #### Attributes:
AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
function_type::mlir::TypeAttrtype attribute of function type
### `dfg.output` (dfg::OutputOp) _Terminator for an OperatorOp_ Syntax: ``` operation ::= `dfg.output` attr-dict ($operands^ `:` type($operands))? ``` Traits: `HasParent`, `Terminator` #### Operands: | Operand | Description | | :-----: | ----------- | | `operands` | variadic of any non-token type | ### `dfg.process` (dfg::ProcessOp) _Defines a process in the KPN MoC_ The `process` operation defines one node (actor) in the KPN dataflow model. A process is a symbol at module scope and can be connected to other processes through its input and output ports. The port interface is described by `function_type`: - function inputs represent incoming channel ends - function results represent outgoing channel ends A `process` can have one region with other IRs inside or none with a link to a library call. Example: ``` dfg.process @node inputs(%in0: !dfg.output, %in1: !dfg.output) outputs(%out0: !dfg.input, %out1: !dfg.input) { ops ... } ``` Traits: `AffineScope`, `AutomaticAllocationScope`, `HasParent`, `IsolatedFromAbove`, `NoTerminator` Interfaces: `DFG_NodeInterface`, `OpAsmOpInterface` #### Attributes:
AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
function_type::mlir::TypeAttrtype attribute of function type
multiplicity::mlir::DenseI64ArrayAttri64 dense array attribute
### `dfg.pull` (dfg::PullOp) _Pulls a token from an input port of a node._ The `pull` operation reads a token out from an input port of a node, which is connected via a channel to an output port of another node. An optional set of indices must be used if the read port has a shape, indicating a set of ports to be chosen from. Example: ``` dfg.process @pull inputs(%in0: !dfg.output, %in1: !dfg.output) { %0 = arith.constant ... : index %token0 = dfg.pull %in0 : !dfg.output %token1 = dfg.pull %in1[%0] : !dfg.output } ``` Interfaces: `OpAsmOpInterface` #### Operands: | Operand | Description | | :-----: | ----------- | | `read_port` | Receiving channel end type | | `indices` | variadic of index | #### Results: | Result | Description | | :----: | ----------- | | `token` | any non-token type | ### `dfg.pull_as_memref` (dfg::PullAsMemRefOp) _Pulls as a memref from a shaped input port of a node._ Interfaces: `OpAsmOpInterface` #### Operands: | Operand | Description | | :-----: | ----------- | | `read_port` | Receiving channel end type | #### Results: | Result | Description | | :----: | ----------- | | `token_memref` | memref of any non-token type values | ### `dfg.pull_as_tensor` (dfg::PullAsTensorOp) _Pulls as a tensor from a shaped input port of a node._ Interfaces: `OpAsmOpInterface` #### Operands: | Operand | Description | | :-----: | ----------- | | `read_port` | Receiving channel end type | #### Results: | Result | Description | | :----: | ----------- | | `token_tensor` | ranked tensor of any non-token type values | ### `dfg.push` (dfg::PushOp) _Pushes a token to an output port of a node._ The `push` operation writes a token to an output port of a node, which is connected via a channel to an input port of another node. An optional set of indices must be used if the port has a shape. Example: ``` dfg.process @push outputs(%out0: !dfg.input, %out1: !dfg.input) { %0 = arith.constant ... : index %1 = arith.constant ... : type %token0 = dfg.push %1 to %out0 : !dfg.input %token1 = dfg.push %1 to %out1[%0] : !dfg.input } ``` #### Operands: | Operand | Description | | :-----: | ----------- | | `token` | any non-token type | | `write_port` | Sending channel end type | | `indices` | variadic of index | ### `dfg.push_memref` (dfg::PushMemRefOp) _Pushes a memref to a shaped output port of a node._ #### Operands: | Operand | Description | | :-----: | ----------- | | `token_memref` | memref of any non-token type values | | `write_port` | Sending channel end type | ### `dfg.push_tensor` (dfg::PushTensorOp) _Pushes a tensor to a shaped output port of a node._ #### Operands: | Operand | Description | | :-----: | ----------- | | `token_tensor` | ranked tensor of any non-token type values | | `write_port` | Sending channel end type | ### `dfg.region` (dfg::RegionOp) _Defines a region(subgraph) in the DFG._ The `region` operation defines one node(subgraph) or the entire graph in the dataflow graph model. A region can be embedded into another region as subgraph, which content can only be an instantiation of a node(processes/operators/regions) and their connections(channels). A region's input/output ports must be connected/used. Example: ``` dfg.region @node inputs(%in0: !dfg.output, %in1: !dfg.output) outputs(%out0: !dfg.input, %out1: !dfg.input) { %0:2 = dfg.channel ... dfg.instantiate @process ... dfg.instantiate @operator ... dfg.embed @region ... } ``` Traits: `IsolatedFromAbove`, `NoTerminator` Interfaces: `DFG_GraphInterface`, `DFG_NodeInterface`, `OpAsmOpInterface` #### Attributes:
AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
function_type::mlir::TypeAttrtype attribute of function type
## Types ### InputType _Sending channel end type_ The `input` type represents the sending end of a dataflow edge in a dataflow graph. This type takes an optional shape and a scalar MLIR type as element type, such as: `!dfg.input`, `!dfg.input<2xi32>`, `!dfg.input<2x2xi32>` #### Parameters: | Parameter | C++ type | Description | | :-------: | :-------: | ----------- | | shape | `::llvm::ArrayRef` | | | elementType | `Type` | | ### OutputType _Receiving channel end type_ The `output` type represents the receiving end of a dataflow edge in a dataflow graph. Details are similar to dfg::InputType. #### Parameters: | Parameter | C++ type | Description | | :-------: | :-------: | ----------- | | shape | `::llvm::ArrayRef` | | | elementType | `Type` | | ## Enums ### OffloadHardware _The hardware back to be offloaded to_ #### Cases: | Symbol | Value | String | | :----: | :---: | ------ | | EmitHLS | `0` | emithls | | MDC | `1` | mdc | | CGRA | `2` | cgra |