Files
gps/tools/local/circt/include/mlir/Dialect/Tosa/IR/TosaOps.td
T
2026-07-12 11:01:51 +03:00

3254 lines
101 KiB
TableGen

//===-- TosaOps.td - TOSA dialect operation definitions ----*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the operation set for the TOSA dialect as defined in
// the TOSA specfication (https://www.mlplatform.org/tosa/tosa_spec.html).
//
//===----------------------------------------------------------------------===//
#ifndef TOSA_OPS
#define TOSA_OPS
include "mlir/IR/OpBase.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/LoopLikeInterface.td"
include "mlir/IR/SymbolInterfaces.td"
include "mlir/Dialect/Tosa/IR/TosaInterfaces.td"
include "mlir/Dialect/Tosa/IR/TosaTypesBase.td"
include "mlir/Dialect/Tosa/IR/TosaOpBase.td"
//===----------------------------------------------------------------------===//
// Operator Class: Tensor Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: argmax
//===----------------------------------------------------------------------===//
def Tosa_ArgMaxOp : Tosa_InferShapedTypeOp<"argmax", [NoMemoryEffect]> {
let summary = "Perform argmax on the input.";
let description = [{
This returns the index with the largest value across the given axis of the
input tensor. If multiple locations have equal values, returns the first
match along the search axis.
This operation is not pure. Undefined behaviour may occur if the max index
is out of bounds for the output data type.
}];
let arguments = (ins
Tosa_TensorAtLeast1D: $input,
I32Attr: $axis,
DefaultValuedAttr<Tosa_NanPropagationModeAttr, "::mlir::tosa::NanPropagationMode::PROPAGATE">:$nan_mode
);
let results = (outs
Tosa_Tensor: $output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Accumulator types.
//===----------------------------------------------------------------------===//
def Tosa_AccType : AnyTypeOf<[I<32>, I<48>, F16, F32]>;
//===----------------------------------------------------------------------===//
// Operator: avg_pool2d
//===----------------------------------------------------------------------===//
def Tosa_AvgPool2dOp : Tosa_InferShapedTypeOp<"avg_pool2d", [NoMemoryEffect]> {
let summary = "Performs average pooling on the input.";
let description = [{
This performs an average pooling over the given input tensor. A sliding
window of size given by <kernel size> is passed over the input tensor, with
the mean value being placed in the output tensor. When calculating the
average, only the number of valid input tensor values, but not padding, are
used to calculate the divisor.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_Tensor4D:$input,
Tosa_ScalarIntOrFloatTensor:$input_zp,
Tosa_ScalarIntOrFloatTensor:$output_zp,
Tosa_IntArrayAttr2:$kernel,
Tosa_IntArrayAttr2:$stride,
Tosa_IntArrayAttr4:$pad,
TypeAttrOf<Tosa_AccType>:$acc_type
);
let results = (outs
Tosa_Tensor4D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16]>,
];
let builders = [Tosa_AvgPool2dOpQuantInfoBuilder];
let extraClassDeclaration = [{
FailureOr<int64_t> getInputZeroPoint();
FailureOr<int64_t> getOutputZeroPoint();
LogicalResult verifyInputZeroPoint(int64_t zp);
LogicalResult verifyOutputZeroPoint(int64_t zp);
}];
let hasVerifier = 1;
let hasCanonicalizer = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: avg_pool2d_adaptive
//===----------------------------------------------------------------------===//
def Tosa_AvgPool2dAdaptiveOp
: Tosa_InferShapedTypeOp<"avg_pool2d_adaptive", [NoMemoryEffect]> {
let summary = "Performs average pooling on the input with shape operands.";
let description = [{
This performs an average pooling over the given input tensor. A sliding
window of size given by <kernel size> is passed over the input tensor, with
the mean value being placed in the output tensor. When calculating the
average, only the number of valid input tensor values, but not padding, are
used to calculate the divisor. Compared to avg_pool2d, the kernel/stride/
pad values are provided as inputs.
}];
let arguments = (ins Tosa_Tensor4D:$input,
Tosa_ScalarIntOrFloatTensor:$input_zp,
Tosa_ScalarIntOrFloatTensor:$output_zp, Rank2TosaShape:$kernel,
Rank2TosaShape:$stride, Rank4TosaShape:$pad,
TypeAttrOf<Tosa_AccType>:$acc_type);
let results = (outs Tosa_Tensor4D:$output);
list<Availability> availability =
[Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2,
Tosa_EXT_BF16]>,
];
let builders = [Tosa_AvgPool2dAdaptiveOpQuantInfoBuilder];
let extraClassDeclaration = [{
FailureOr<int64_t> getInputZeroPoint();
FailureOr<int64_t> getOutputZeroPoint();
LogicalResult verifyInputZeroPoint(int64_t zp);
LogicalResult verifyOutputZeroPoint(int64_t zp);
}];
let hasVerifier = 1;
let hasCanonicalizer = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: conv2d
//===----------------------------------------------------------------------===//
def Tosa_Conv2DOp : Tosa_ConvOp<"conv2d"> {
let summary = "2D Convolution operator.";
let description = [{
Performs a 2D convolution over the given tensor input, using the weight
tensor. Implementations may choose to skip calculation of multiplies in
the padding area.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_Tensor4D:$input,
Tosa_Tensor4D:$weight,
Tosa_Tensor1D:$bias,
Tosa_ScalarIntOrFloatTensor:$input_zp,
Tosa_ScalarIntOrFloatTensor:$weight_zp,
Tosa_IntArrayAttr4:$pad,
Tosa_IntArrayAttr2:$stride,
Tosa_IntArrayAttr2:$dilation,
TypeAttrOf<Tosa_AccType>:$acc_type,
DefaultValuedOptionalAttr<BoolAttr, "false">:$local_bound
);
let results = (outs
Tosa_Tensor4D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT4, Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16]>,
];
let extraClassDeclaration = [{
FailureOr<int64_t> getInputZeroPoint();
FailureOr<int64_t> getWeightZeroPoint();
LogicalResult verifyInputZeroPoint(int64_t zp);
LogicalResult verifyWeightZeroPoint(int64_t zp);
}];
let builders = [Tosa_ConvOpQuantInfoBuilder];
let hasCanonicalizer = 1;
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// Operator: conv2d_block_scaled
//===----------------------------------------------------------------------===//
def Tosa_Conv2DBlockScaledOp : Tosa_InferShapedTypeOp<"conv2d_block_scaled", [NoMemoryEffect]> {
let summary = "Performs two dimensional convolution using block scaled tensors.";
let description = [{
Performs a 2D convolution over the given input data and scales, using
the weight data and scales. Implementations may choose to skip calculation
of multiplies in the padding area.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_MXFPDataTensor4D:$input_data,
Tosa_MXFPScaleTensor4D:$input_scale,
Tosa_MXFPDataTensor4D:$weight_data,
Tosa_MXFPScaleTensor4D:$weight_scale,
Tosa_Tensor1D:$bias,
Rank4TosaShape:$pad,
Rank2TosaShape:$stride,
Rank2TosaShape:$dilation,
Tosa_BlockSizeAttr:$block_size
);
let results = (outs
Tosa_Tensor4D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_MXFP_CONV]>,
];
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: conv3d
//===----------------------------------------------------------------------===//
def Tosa_Conv3DOp : Tosa_ConvOp<"conv3d"> {
let summary = "3D Convolution operator.";
let description = [{
Performs a 3D convolution over the given input tensor. Implementations
may choose to skip calculation of multiplies in the padding area.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_Tensor5D:$input,
Tosa_Tensor5D:$weight,
Tosa_Tensor1D:$bias,
Tosa_ScalarIntOrFloatTensor:$input_zp,
Tosa_ScalarIntOrFloatTensor:$weight_zp,
Tosa_IntArrayAttr6:$pad,
Tosa_IntArrayAttr3:$stride,
Tosa_IntArrayAttr3:$dilation,
TypeAttrOf<Tosa_AccType>:$acc_type,
DefaultValuedOptionalAttr<BoolAttr, "false">:$local_bound
);
let results = (outs
Tosa_Tensor5D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT4, Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16]>,
];
let extraClassDeclaration = [{
FailureOr<int64_t> getInputZeroPoint();
FailureOr<int64_t> getWeightZeroPoint();
LogicalResult verifyInputZeroPoint(int64_t zp);
LogicalResult verifyWeightZeroPoint(int64_t zp);
}];
let builders = [Tosa_ConvOpQuantInfoBuilder];
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// Operator: depthwise_conv2d
//===----------------------------------------------------------------------===//
def Tosa_DepthwiseConv2DOp : Tosa_ConvOp<"depthwise_conv2d"> {
let summary = "Depthwise 2D Convolution operator.";
let description = [{
Performs 2D convolutions separately over each channel of the given tensor
input, using the weight tensor. Implementations may choose to skip
calculation of multiplies in the padding area.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_Tensor4D:$input,
Tosa_Tensor4D:$weight,
Tosa_Tensor1D:$bias,
Tosa_ScalarIntOrFloatTensor:$input_zp,
Tosa_ScalarIntOrFloatTensor:$weight_zp,
Tosa_IntArrayAttr4:$pad,
Tosa_IntArrayAttr2:$stride,
Tosa_IntArrayAttr2:$dilation,
TypeAttrOf<Tosa_AccType>:$acc_type,
DefaultValuedOptionalAttr<BoolAttr, "false">:$local_bound
);
let results = (outs
Tosa_Tensor4D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT4, Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16]>,
];
let extraClassDeclaration = [{
FailureOr<int64_t> getInputZeroPoint();
FailureOr<int64_t> getWeightZeroPoint();
LogicalResult verifyInputZeroPoint(int64_t zp);
LogicalResult verifyWeightZeroPoint(int64_t zp);
}];
let builders = [Tosa_ConvOpQuantInfoBuilder];
let hasCanonicalizer = 1;
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// Operator: fft2d
//===----------------------------------------------------------------------===//
def Tosa_FFT2dOp : Tosa_InferShapedTypeOp<"fft2d", [
SameOperandsAndResultElementType,
SameOperandsAndResultShape,
ResultsAreFloatLike,
Pure]> {
let summary = "Performs FFT2D operation on the input.";
let description = [{
Performs a batched complex 2D Fast Fourier Transform over the input. The
complex input values are constructed from the corresponding values in the
input_real and input_imag tensors. The resulting values in the output are
split into the output_real and output_imag tensors. No normalization is
applied on either the forward or inverse versions of the operation.
Example:
```mlir
%output_real, %output_imag = tosa.fft2d %input_real, %input_imag : (tensor<8x9xf32>, tensor<8x9xf32>) -> (tensor<8x9xf32>, tensor<8x9xf32>)
```
}];
let arguments = (ins
Tosa_Tensor3D:$input_real,
Tosa_Tensor3D:$input_imag,
BoolAttr:$inverse,
DefaultValuedOptionalAttr<BoolAttr, "false">:$local_bound
);
let results = (outs
Tosa_Tensor3D:$output_real,
Tosa_Tensor3D:$output_imag
);
list<Availability> availability = [
Profile<[]>,
Extension<[Tosa_EXT_FFT]>,
];
let assemblyFormat = [{
$input_real `,` $input_imag attr-dict `:` `(` type($input_real) `,`
type($input_imag) `)` `->` `(` type($output_real) `,` type($output_imag) `)`
}];
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: matmul
//===----------------------------------------------------------------------===//
def Tosa_MatMulOp : Tosa_InferShapedTypeOp<"matmul", [NoMemoryEffect]> {
let summary = "Matrix multiplication operator.";
let description = [{
Performs two dimensional matrix multiplications.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_Tensor3D:$a,
Tosa_Tensor3D:$b,
Tosa_ScalarIntOrFloatTensor:$a_zp,
Tosa_ScalarIntOrFloatTensor:$b_zp
);
let results = (outs
Tosa_Tensor3D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16]>,
];
let extraClassDeclaration = [{
FailureOr<int64_t> getAZeroPoint();
FailureOr<int64_t> getBZeroPoint();
LogicalResult verifyAZeroPoint(int64_t zp);
LogicalResult verifyBZeroPoint(int64_t zp);
}];
let builders = [Tosa_MatMulOpQuantInfoBuilder];
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: matmul_t_block_scaled
//===----------------------------------------------------------------------===//
def Tosa_MatmulTBlockScaledOp : Tosa_InferShapedTypeOp<"matmul_t_block_scaled", [NoMemoryEffect]> {
let summary = "Performs two dimensional matrix multiplications using block scaled tensors.";
let description = [{
Performs two dimensional matrix multiplications using block scaled tensors. The block
dimension is always the the last dimension of the tensor, so the result is effectively
a matrix multiply of A by the transposed B matrix. If the N dimension of input B is of
size 1, the B matrix will be broadcast.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_MXFPDataTensor3D:$a_data,
Tosa_MXFPScaleTensor3D:$a_scale,
Tosa_MXFPDataTensor3D:$b_data,
Tosa_MXFPScaleTensor3D:$b_scale,
Tosa_BlockSizeAttr:$block_size
);
let results = (outs
Tosa_Tensor3D:$output_data
);
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_MXFP]>
];
}
//===----------------------------------------------------------------------===//
// Operator: max_pool2d
//===----------------------------------------------------------------------===//
def Tosa_MaxPool2dOp : Tosa_InferShapedTypeOp<"max_pool2d", [Pure]> {
let summary = "Performs max pooling on the input.";
let description = [{
This performs a max pooling over the given input tensor. A sliding window of
size given by <kernel size> is passed over the input tensor, with the
maximum value being placed in the
output tensor.
}];
let arguments = (ins
Tosa_Tensor4D:$input,
Tosa_IntArrayAttr2:$kernel,
Tosa_IntArrayAttr2:$stride,
Tosa_IntArrayAttr4:$pad,
DefaultValuedAttr<Tosa_NanPropagationModeAttr, "::mlir::tosa::NanPropagationMode::PROPAGATE">:$nan_mode
);
let results = (outs
Tosa_Tensor4D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16]>,
];
let hasCanonicalizer = 1;
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: max_pool2d_adaptive
//===----------------------------------------------------------------------===//
def Tosa_MaxPool2dAdaptiveOp
: Tosa_InferShapedTypeOp<"max_pool2d_adaptive", [Pure]> {
let summary = "Performs max pooling on the input.";
let description = [{
This performs a max pooling over the given input tensor. A sliding window of
size given by <kernel size> is passed over the input tensor, with the
maximum value being placed in the output tensor.
Compared to MAX_POOL2D, MAX_POOL2D_ADAPTIVE has the kernel, stride,
pad arguments as inputs rather than attributes.
}];
let arguments =
(ins Tosa_Tensor4D:$input, Rank2TosaShape:$kernel, Rank2TosaShape:$stride,
Rank4TosaShape:$pad,
DefaultValuedAttr<
Tosa_NanPropagationModeAttr,
"::mlir::tosa::NanPropagationMode::PROPAGATE">:$nan_mode);
let results = (outs Tosa_Tensor4D:$output);
list<Availability> availability =
[Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2,
Tosa_EXT_BF16]>,
];
let hasVerifier = 1;
let hasCanonicalizer = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: rfft2d
//===----------------------------------------------------------------------===//
def Tosa_RFFT2dOp : Tosa_InferShapedTypeOp<"rfft2d", [
SameOperandsAndResultElementType,
ResultsAreFloatLike,
Pure]> {
let summary = "Performs RFFT2D operation on the input.";
let description = [{
Performs a batched 2D real-valued Fast Fourier Transform over the input where
the input tensor consists of real values producing complex valued output. The
complex output values will be split into the output_real and output_imag
tensor arguments. RFFT2D takes advantage of Hermitian symmetry to only
calculate the first half of the final output axis. Implementations may choose
to skip calculation of the imaginary values at (0,0), (0,W/2), (H/2,0), and
(H/2, W/2). If the calculation is skipped, the result at that location must be
zero.
Example:
```mlir
%ouput_real, %output_imag = tosa.rfft2d %input_real : (tensor<8x16xf32>) -> (tensor<8x9xf32>, tensor<8x9xf32>)
```
}];
let arguments = (ins
Tosa_Tensor3D:$input_real,
DefaultValuedOptionalAttr<BoolAttr, "false">:$local_bound
);
let results = (outs
Tosa_Tensor3D:$output_real,
Tosa_Tensor3D:$output_imag
);
list<Availability> availability = [
Profile<[]>,
Extension<[Tosa_EXT_FFT]>,
];
let assemblyFormat = [{
$input_real attr-dict `:` `(` type($input_real) `)` `->` `(` type($output_real) `,` type($output_imag) `)`
}];
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: transpose_conv2d
//===----------------------------------------------------------------------===//
def Tosa_TransposeConv2DOp : Tosa_ConvOp<"transpose_conv2d"> {
let summary = "Transpose 2D Convolution operator.";
let description = [{
Performs a 2D transposed convolution over the given tensor input, using the
weights tensor. Implementations may choose to skip calculation of multiplies
by zero at fractional input positions.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_Tensor4D:$input,
Tosa_Tensor4D:$weight,
Tosa_Tensor1D:$bias,
Tosa_ScalarIntOrFloatTensor:$input_zp,
Tosa_ScalarIntOrFloatTensor:$weight_zp,
Tosa_IntArrayAttr4:$out_pad,
Tosa_IntArrayAttr2:$stride,
TypeAttrOf<Tosa_AccType>:$acc_type,
DefaultValuedOptionalAttr<BoolAttr, "false">:$local_bound
);
let results = (outs
Tosa_Tensor4D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT4, Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16]>,
];
let extraClassDeclaration = [{
FailureOr<int64_t> getInputZeroPoint();
FailureOr<int64_t> getWeightZeroPoint();
LogicalResult verifyInputZeroPoint(int64_t zp);
LogicalResult verifyWeightZeroPoint(int64_t zp);
}];
let builders = [Tosa_TransConvOpQuantInfoBuilder];
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// Operator Class: Activation Functions.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: clamp
//===----------------------------------------------------------------------===//
def Tosa_ClampOp : Tosa_ElementwiseUnaryOp<"clamp", [Pure]> {
let summary = "Computes clamp(features, min, max).";
let description = [{
Clamp to an arbitrary minimum and maximum value.
Maximum and minimum values are specified as values in the range of the
input type.
No zero point subtraction is done to the values, thus to clamp to the zero
point value, the zero point itself should be supplied as the minimum value.
}];
let arguments = (ins
Tosa_Tensor:$input,
Tosa_IntOrFloatAttr:$min_val,
Tosa_IntOrFloatAttr:$max_val,
DefaultValuedAttr<Tosa_NanPropagationModeAttr, "::mlir::tosa::NanPropagationMode::PROPAGATE">:$nan_mode
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT16, Tosa_EXT_BF16]>,
];
let hasCanonicalizer = 1;
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: erf
//===----------------------------------------------------------------------===//
def Tosa_ErfOp : Tosa_ElementwiseUnaryOp<"erf", [Pure]> {
let summary = "Computes gauss error function of input.";
let description = [{
Gauss error function: $ erf(x) = \frac{2}{\sqrt{\pi}} \int_{0}^{x} e^{-t^2} dt $
For quantized integer data types, the TABLE operator should be used instead
with the following definition. The ERF table has 513 entries each of
16-bit precision and covering the input range -4.0 to +4.0 in steps of 1/64.
}];
let arguments = (ins
Tosa_Tensor:$input
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: sigmoid
//===----------------------------------------------------------------------===//
def Tosa_SigmoidOp : Tosa_ElementwiseUnaryOp<"sigmoid", [Pure]> {
let summary = "Computes elementwise sigmoid of input.";
let description = [{
Applies the sigmoid logistic function to each element of the input tensor:
$ sigmoid(x) = \frac{1}{1 + e^{-x}} $.
For quantized integer data types, the TABLE operator should be used instead.
Each implementation may choose an appropriate TABLE given the scale and zero
point of the input data. Eight or sixteen bit precision tables may be used
based on the input tensor to the sigmoid function.
}];
let arguments = (ins
Tosa_Tensor:$input
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: tanh
//===----------------------------------------------------------------------===//
def Tosa_TanhOp : Tosa_ElementwiseUnaryOp<"tanh", [Pure]> {
let summary = "Computes elementwise hyperbolic tangent of input.";
let description = [{
Parameterized hyperbolic tangent: $ tanh(x) = \frac{1 - e^{-2x}}{1 + e^{-2x}} $.
For quantized integer data types, the TABLE operator should be used instead.
Each implementation may choose an appropriate TABLE given the scale and zero
point of the input data. Eight or sixteen bit precision tables may be used
based on the input tensor to the tanh function.
}];
let arguments = (ins
Tosa_Tensor:$input
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Elementwise Binary Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: add
//===----------------------------------------------------------------------===//
def Tosa_AddOp : Tosa_ElementwiseOp<"add", [
Commutative,
SameOperandsAndResultElementType]> {
let summary = "Elementwise addition operator.";
let description = [{
Elementwise addition of input1 and input2. Axis of size 1 will be broadcast,
as necessary. Rank of input tensors must match.
This operation is not pure. Undefined behaviour may occur if the calculated
result overflows.
Example:
```mlir
// Elementwise addition.
%out = tosa.add %input1, %input2 : tensor<12x6xf32>, tensor<12x6xf32> -> tensor<12x6xf32>
// Elementwise addition with broadcasting.
%out = tosa.add %input1, %input2 : tensor<12x6xsi32>, tensor<1x1xsi32> -> tensor<12x6xsi32>
```
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: arithmetic_right_shift
//===----------------------------------------------------------------------===//
def Tosa_ArithmeticRightShiftOp : Tosa_ElementwiseOp<"arithmetic_right_shift",
[SameOperandsAndResultElementType]> {
let summary = "Elementwise Arithmetic Right Shift.";
let description = [{
Elementwise arithmetic right shift of input1 by the amount specified in
input2. Axis of size 1 will be broadcast, as necessary. Rank of input tensors
must match.
This operation is not pure. Undefined behaviour may occur if the specified
shift is out of range.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2,
BoolAttr:$round
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT]>,
Extension<[Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: bitwise_and
//===----------------------------------------------------------------------===//
def Tosa_BitwiseAndOp : Tosa_ElementwiseOp<"bitwise_and", [
Commutative,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Bitwise AND operator.";
let description = [{
Elementwise bitwise AND of input1 and input2. Axis of size 1
will be broadcast as necessary. Rank of input tensors must match.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT]>,
Extension<[Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: bitwise_or
//===----------------------------------------------------------------------===//
def Tosa_BitwiseOrOp : Tosa_ElementwiseOp<"bitwise_or", [
Commutative,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Bitwise OR operator.";
let description = [{
Elementwise bitwise OR of input1 and input2. Axis of size 1 will be
broadcast as necessary. Rank of input tensors must match.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT]>,
Extension<[Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: bitwise_xor
//===----------------------------------------------------------------------===//
def Tosa_BitwiseXorOp : Tosa_ElementwiseOp<"bitwise_xor", [
Commutative,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Bitwise XOR operator.";
let description = [{
Elementwise bitwise XOR of input1 and input2. Axis of size 1 will be
broadcast as necessary. Rank of input tensors must match.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT]>,
Extension<[Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: intdiv
//===----------------------------------------------------------------------===//
def Tosa_IntDivOp : Tosa_ElementwiseOp<"intdiv", [SameOperandsAndResultElementType]> {
let summary = "Integer divide operator.";
let description = [{
Elementwise integer divide of input1 by input2. Axis of size 1 will be
broadcast as necessary. Rank of input tensors must match. The result of the
divide is truncated towards zero. Expected use is for operations on
non-scaled integers. Floating point divide should use RECIPROCAL and MUL.
Quantized integer divide should use TABLE (for 1/x) and MUL.
This operation is not pure. Undefined behaviour may occur on division by zero.
}];
let arguments = (ins
Tosa_Int32Or64Tensor:$input1,
Tosa_Int32Or64Tensor:$input2
);
let results = (outs
Tosa_Int32Or64Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: logical_and
//===----------------------------------------------------------------------===//
def Tosa_LogicalAndOp : Tosa_ElementwiseOp<"logical_and", [
Commutative,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Returns the truth value of input1 AND input2 element-wise.";
let description = [{
Elementwise logical AND of input1 and input2. Axis of size 1 will be
broadcast, as necessary. Rank of input tensors must match.
}];
let arguments = (ins
Tosa_I1Tensor:$input1,
Tosa_I1Tensor:$input2
);
let results = (outs
Tosa_I1Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: logical_left_shift
//===----------------------------------------------------------------------===//
def Tosa_LogicalLeftShiftOp : Tosa_ElementwiseOp<"logical_left_shift",
[SameOperandsAndResultElementType]> {
let summary = "Elementwise Logical Left Shift.";
let description = [{
Elementwise logical left-shift of input1 by the amount specified in input2.
Axis of size 1 will be broadcast, as necessary.
Rank of input tensors must match.
This operation is not pure. Undefined behaviour may occur if the specified
shift is out of range.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: logical_right_shift
//===----------------------------------------------------------------------===//
def Tosa_LogicalRightShiftOp : Tosa_ElementwiseOp<"logical_right_shift",
[SameOperandsAndResultElementType]> {
let summary = "Elementwise Logical Right Shift.";
let description = [{
Elementwise logical right shift of input1 by the amount specified in input2.
Axis of size 1 will be broadcast, as necessary. Rank of input tensors must
match.
This operation is not pure. Undefined behaviour may occur if the specified
shift is out of range.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: logical_or
//===----------------------------------------------------------------------===//
def Tosa_LogicalOrOp : Tosa_ElementwiseOp<"logical_or", [
Commutative,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Returns the truth value of x OR y element-wise.";
let description = [{
Elementwise logical OR of input1 and input2. Axis of size 1 will be
broadcast as necessary. Rank of input tensors must match.
}];
let arguments = (ins
Tosa_I1Tensor:$input1,
Tosa_I1Tensor:$input2
);
let results = (outs
Tosa_I1Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: logical_xor
//===----------------------------------------------------------------------===//
def Tosa_LogicalXorOp : Tosa_ElementwiseOp<"logical_xor", [
Commutative,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Returns the truth value of input1 XOR input2 element-wise.";
let description = [{
Elementwise logical XOR of input1 and input2. Axis of size 1 will be
broadcast as necessary. Rank of input tensors must match.
}];
let arguments = (ins
Tosa_I1Tensor:$input1,
Tosa_I1Tensor:$input2
);
let results = (outs
Tosa_I1Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: maximum
//===----------------------------------------------------------------------===//
def Tosa_MaximumOp : Tosa_ElementwiseOp<"maximum", [
Commutative,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Elementwise Maximum.";
let description = [{
Elementwise max of input1 and input2. Axis of size 1 will be broadcast, as
necessary. Rank of input tensors must match.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2,
DefaultValuedAttr<Tosa_NanPropagationModeAttr, "::mlir::tosa::NanPropagationMode::PROPAGATE">:$nan_mode
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: minimum
//===----------------------------------------------------------------------===//
def Tosa_MinimumOp : Tosa_ElementwiseOp<"minimum", [
Commutative,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Elementwise Minimum.";
let description = [{
Elementwise minimum of input1 and input2. Axis of size 1
will be broadcast, as necessary. Rank of input tensors must match.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2,
DefaultValuedAttr<Tosa_NanPropagationModeAttr, "::mlir::tosa::NanPropagationMode::PROPAGATE">:$nan_mode
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: mul
//===----------------------------------------------------------------------===//
def Tosa_MulOp : Tosa_Op<"mul", [
DeclareOpInterfaceMethods<InferShapedTypeOpInterface,
["inferReturnTypeComponents"]>,
NoMemoryEffect]> {
let summary = "Multiplication operator.";
let description = [{
Elementwise multiplication (Hadamard product) of input1 and input2.
Axis of size 1 will be broadcast, as necessary. Rank of input tensors must
match.
This operation is not pure. Undefined behaviour may occur if the specifed
shift is out of range or the result overflows.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2,
// Apply right shift on i32_t input data only
Tosa_ScalarInt8Tensor:$shift
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: pow
//===----------------------------------------------------------------------===//
def Tosa_PowOp : Tosa_ElementwiseOp<"pow", [SameOperandsAndResultElementType]> {
let summary = "Computes the power of one value to another.";
let description = [{
Elementwise input1 value raised to the power of input2.
Axis of size 1 will be broadcast, as necessary. Rank of input tensors must
match.
This operation is not pure. Undefined behaviour may occur if specified
exponent is negative.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: sub
//===----------------------------------------------------------------------===//
def Tosa_SubOp : Tosa_ElementwiseOp<"sub", [SameOperandsAndResultElementType]> {
let summary = "Elementwise subtraction operator.";
let description = [{
Elementwise subtraction of input1 and input2. Axis of size 1 will be
broadcast as necessary. Rank of input tensors must match.
This operation is not pure. Undefined behaviour may occur if the calculated
result underflows.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: table
//===----------------------------------------------------------------------===//
def Tosa_TableOp : Tosa_InferShapedTypeOp<"table", [NoMemoryEffect]> {
let summary = "Table lookup operator.";
let description = [{
Table lookup operation. For int8_t TABLE operation, perform a 256 entry
table lookup returning an int8_t value. For int16_t tables, the int16_t
input is treated as a fixed-point 9.7 value. The most significant 9 bits
are used to index into the table. The fractional 7 bits are used to
interpolate based on table[index] and table[index+1]. For int16_t inputs,
the TABLE operator returns a 16.7 interpolated value in an int32_t. This
value can then be input to the RESCALE operator to scale to the required
output data type. Note that int16_t table has 513 values to handle
table[index+1] when index=511.
An int16_t to int16_t table lookup can be constructed in TOSA as follows:
* Use the TABLE operator to produce a fixed point 16.7 interpolated result
* Use RESCALE (in_t=int32_t, out_t=int16_t, scale=1<<14, shift=21) to
scale the output to int16_t range (or alternate scale as required)
This operation is not pure. Undefined behaviour may occur if the calculated
slope is out of range.
}];
let arguments = (ins
Tosa_Tensor: $input1,
Tosa_Tensor1D: $table
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT]>,
Extension<[Tosa_EXT_INT16]>,
];
let assemblyFormat = [{
$input1 `,` $table attr-dict `:` `(` type($input1) `,` type($table) `)` `->` type($output)
}];
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Elementwise Unary Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: abs
//===----------------------------------------------------------------------===//
def Tosa_AbsOp : Tosa_ElementwiseUnaryOp<"abs", [NoMemoryEffect]> {
let summary = "Elementwise abs operator.";
let description = [{
Elementwise absolute value operation.
This operation is not pure. Undefined behaviour may occur if the
calculated result underflows.
Example:
```mlir
%output = tosa.abs(%input1) : (tensor<21x3xf32>) -> tensor<21x3xf32>
```
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: bitwise_not
//===----------------------------------------------------------------------===//
def Tosa_BitwiseNotOp : Tosa_ElementwiseUnaryOp<"bitwise_not", [Pure]> {
let summary = "Bitwise NOT operator.";
let description = [{
Elementwise bitwise NOT of input tensor.
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT]>,
Extension<[Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: ceil
//===----------------------------------------------------------------------===//
def Tosa_CeilOp : Tosa_ElementwiseUnaryOp<"ceil", [Pure]> {
let summary = "Elementwise ceil operator.";
let description = [{
Elementwise ceiling operation.
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: clz
//===----------------------------------------------------------------------===//
def Tosa_ClzOp : Tosa_ElementwiseUnaryOp<"clz", [Pure]> {
let summary = "Elementwise count leading zero operator.";
let description = [{
Elementwise count leading zeros operation.
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT]>,
Extension<[Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: cos
//===----------------------------------------------------------------------===//
def Tosa_CosOp : Tosa_ElementwiseUnaryOp<"cos", [Pure]> {
let summary = "Elementwise cos operator.";
let description = [{
Elementwise cosine operation for values given in radians.
}];
let arguments = (ins
Tosa_FloatTensor:$input1
);
let results = (outs
Tosa_FloatTensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: exp
//===----------------------------------------------------------------------===//
def Tosa_ExpOp : Tosa_ElementwiseUnaryOp<"exp", [Pure]> {
let summary = "Elementwise exp operator.";
let description = [{
Elementwise e to the x operation
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: floor
//===----------------------------------------------------------------------===//
def Tosa_FloorOp : Tosa_ElementwiseUnaryOp<"floor", [Pure]> {
let summary = "Elementwise floor operator.";
let description = [{
Elementwise floor operation.
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: log
//===----------------------------------------------------------------------===//
def Tosa_LogOp : Tosa_ElementwiseUnaryOp<"log", [Pure]> {
let summary = "Elementwise log operator.";
let description = [{
Elementwise natural logarithm operation
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: logical_not
//===----------------------------------------------------------------------===//
def Tosa_LogicalNotOp : Tosa_ElementwiseUnaryOp<"logical_not", [Pure]> {
let summary = "Returns the truth value of NOT input1 element-wise.";
let description = [{
Elementwise logical NOT of input.
}];
let arguments = (ins
Tosa_I1Tensor:$input1
);
let results = (outs
Tosa_I1Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: negate
//===----------------------------------------------------------------------===//
def Tosa_NegateOp : Tosa_InferShapedTypeOp<"negate", [
TosaElementwiseOperator,
NoMemoryEffect]> {
let summary = "Elementwise negate operator.";
let description = [{
Elementwise negation operation.
This operation is not pure. Undefined behaviour may occur if the calculated
result underflows or overflows.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_ScalarIntOrFloatTensor:$input1_zp,
Tosa_ScalarIntOrFloatTensor:$output_zp
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let builders = [Tosa_NegateOpQuantInfoBuilder];
let extraClassDeclaration = [{
FailureOr<int64_t> getInput1ZeroPoint();
FailureOr<int64_t> getOutputZeroPoint();
LogicalResult verifyInput1ZeroPoint(int64_t zp);
LogicalResult verifyOutputZeroPoint(int64_t zp);
}];
let hasFolder = 1;
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: reciprocal
//===----------------------------------------------------------------------===//
def Tosa_ReciprocalOp : Tosa_ElementwiseUnaryOp<"reciprocal", [Pure]> {
let summary = "Elementwise reciprocal operator.";
let description = [{
Elementwise reciprocal operation. For integer operation, a TABLE should be
used with the appropriate ranges.
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let extraClassDeclaration = [{
/// Return the reciprocal result on the operand.
static inline APFloat calcOneElement(const APFloat &operand) {
APFloat recip = APFloat(operand.getSemantics(), 1);
recip.divide(operand, APFloat::rmNearestTiesToEven);
return recip;
}
}];
let hasFolder = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: rsqrt
//===----------------------------------------------------------------------===//
def Tosa_RsqrtOp : Tosa_ElementwiseUnaryOp<"rsqrt", [Pure]> {
let summary = "Elementwise 1/sqrt operator.";
let description = [{
Elementwise reciprocal square root operation. For integer operation, a TABLE
should be used with the appropriate ranges.
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: sin
//===----------------------------------------------------------------------===//
def Tosa_SinOp : Tosa_ElementwiseUnaryOp<"sin", [Pure]> {
let summary = "Elementwise sin operator.";
let description = [{
Elementwise sine operation for values given in radians.
}];
let arguments = (ins
Tosa_FloatTensor:$input1
);
let results = (outs
Tosa_FloatTensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Elementwise Unary Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: select
//===----------------------------------------------------------------------===//
def Tosa_SelectOp : Tosa_ElementwiseOp<"select", [Pure]> {
let summary = "Elementwise select operator.";
let description = [{
Elementwise select of the output based on a condition.
}];
let arguments = (ins
Tosa_I1Tensor:$input1, // pred
Tosa_Tensor:$input2, // on true
Tosa_Tensor:$input3 // on false
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasCanonicalizeMethod = 1;
let hasFolder = 1;
let hasVerifier = 1;
let assemblyFormat = [{
operands attr-dict `:` `(` type($input1) `,` type($input2) `,` type($input3)
`)` `->` type($output)
}];
let extraClassDeclaration = [{
// Custom getters for readability
::mlir::TypedValue<::mlir::TensorType> getPred() { return getInput1(); }
::mlir::TypedValue<::mlir::TensorType> getOnTrue() { return getInput2(); }
::mlir::TypedValue<::mlir::TensorType> getOnFalse() { return getInput3(); }
}];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Comparison Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: equal
//===----------------------------------------------------------------------===//
def Tosa_EqualOp : Tosa_ElementwiseOp<"equal", [
InferTensorType,
Commutative,
SameOperandsElementType,
Pure]> {
let summary = "Returns the truth value of (input1 == input2) element-wise.";
let description = [{
Elementwise comparison operation.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_I1Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let extraClassDeclaration = [{
/// Returns when two result types are compatible for this op; method used by
/// InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
}];
let hasFolder = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: greater
//===----------------------------------------------------------------------===//
def Tosa_GreaterOp : Tosa_ElementwiseOp<"greater", [SameOperandsElementType,
Pure]> {
let summary = "Returns the truth value of (input1 > input2) element-wise.";
let description = [{
Elementwise greater than comparison operation.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_I1Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: greater_equal
//===----------------------------------------------------------------------===//
def Tosa_GreaterEqualOp : Tosa_ElementwiseOp<"greater_equal",
[SameOperandsElementType, Pure]> {
let summary = "Returns the truth value of (input1 >= input2) element-wise.";
let description = [{
Elementwise comparison operation.
}];
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Tensor:$input2
);
let results = (outs
Tosa_I1Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Reduction Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: reduce_all
//===----------------------------------------------------------------------===//
def Tosa_ReduceAllOp : Tosa_InferTensorTypeOp<"reduce_all", [Pure]> {
let summary = "Reduce All operator.";
let description = [{
Reduce a tensor along the given axis with a logical AND operation.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input,
I32Attr:$axis
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
/// Return the AND result between two integer operands
static inline APInt calcOneElement(APInt leftOperand, APInt rightOperand) {
return leftOperand & rightOperand;
}
}];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: reduce_any
//===----------------------------------------------------------------------===//
def Tosa_ReduceAnyOp : Tosa_InferTensorTypeOp<"reduce_any", [Pure]> {
let summary = "Reduce Any operator.";
let description = [{
Reduce a tensor along the given axis with a logical OR operation.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input,
I32Attr:$axis
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
/// Return the OR result between two integer operands
static inline APInt calcOneElement(APInt leftOperand, APInt rightOperand) {
return leftOperand | rightOperand;
}
}];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: reduce_max
//===----------------------------------------------------------------------===//
def Tosa_ReduceMaxOp : Tosa_InferTensorTypeOp<"reduce_max", [Pure]> {
let summary = "Reduce Max operator.";
let description = [{
Reduce a tensor along the given axis with a maximum operation.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input,
I32Attr:$axis,
DefaultValuedAttr<Tosa_NanPropagationModeAttr, "::mlir::tosa::NanPropagationMode::PROPAGATE">:$nan_mode
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
/// Return the max of the two integer operands
static inline APInt calcOneElement(APInt leftOperand, APInt rightOperand) {
return (leftOperand.sge(rightOperand)) ? leftOperand : rightOperand;
}
}];
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: reduce_min
//===----------------------------------------------------------------------===//
def Tosa_ReduceMinOp : Tosa_InferTensorTypeOp<"reduce_min", [Pure]> {
let summary = "Reduce Min operator.";
let description = [{
Reduce a tensor along the given axis with a minimum operation.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input,
I32Attr:$axis,
DefaultValuedAttr<Tosa_NanPropagationModeAttr, "::mlir::tosa::NanPropagationMode::PROPAGATE">:$nan_mode
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
/// Return the min of the two integer operands
static inline APInt calcOneElement(APInt leftOperand, APInt rightOperand) {
return (leftOperand.sle(rightOperand)) ? leftOperand : rightOperand;
}
}];
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: reduce_product
//===----------------------------------------------------------------------===//
def Tosa_ReduceProductOp : Tosa_InferTensorTypeOp<"reduce_product", [NoMemoryEffect]> {
let summary = "Reduce Product operator.";
let description = [{
Reduce a tensor along the given axis by computing the product of the axis.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input,
I32Attr:$axis
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
/// Return the prod of the two integer operands
static inline APInt calcOneElement(APInt leftOperand, APInt rightOperand) {
return leftOperand * rightOperand;
}
}];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: reduce_sum
//===----------------------------------------------------------------------===//
def Tosa_ReduceSumOp : Tosa_InferTensorTypeOp<"reduce_sum", [NoMemoryEffect]> {
let summary = "Reduce Sum operator.";
let description = [{
Reduce a tensor along the given axis by computing the sum of the axis.
This operation is not pure. Undefined behaviour may occur if the accumulated
result overflows.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input,
I32Attr:$axis
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
/// Return the sum of the two integer operands
static inline APInt calcOneElement(APInt leftOperand, APInt rightOperand) {
return leftOperand + rightOperand;
}
}];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Data Layout.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: concat
//===----------------------------------------------------------------------===//
def Tosa_ConcatOp : Tosa_InferTensorTypeOp<"concat", [Pure]> {
let summary = "Concatenates tensors along one dimension.";
let description = [{
Concatenate a list of tensors along a given axis.
No data conversion happens during a concat operation.
}];
let arguments = (ins
Variadic<Tosa_TensorAtLeast1D>:$input1,
I32Attr:$axis
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT16, Tosa_EXT_INT64]>,
];
let hasCanonicalizer = 1;
let hasVerifier = 1;
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
}];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: pad
//===----------------------------------------------------------------------===//
def Tosa_PadOp : Tosa_InferShapedTypeOp<"pad", [Pure]> {
let summary = "Pads a tensor with value specified.";
let description = [{
Pads a tensor along the borders of each dimension with a supplied value.
Returns a new tensor with the padding included. The pad_const value includes
the zero point if the tensor uses a zero point.
Example:
```mlir
%pad_const = "tosa.const"() {values = dense<3.14> : tensor<1xf32>} : () -> tensor<1xf32>
%padding = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>
tosa.pad %arg0, %padding, %pad_const: (tensor<1x2xf32>, !tosa.shape<4>, tensor<1xf32>) -> (tensor<4x9xf32>)
```
Example 2:
```mlir
%pad_const = "tosa.const"() {values = dense<3.14> : tensor<1xf32>} : () -> tensor<1xf32>
%padding = tosa.const_shape {values = dense<[-1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>
tosa.pad %arg0, %padding, %pad_const : (tensor<1x2xf32>, !tosa.shape<4>, tensor<1xf32>) -> (tensor<?x9xf32>)
```
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input1,
Tosa_Shape:$padding,
Tosa_ScalarTensor:$pad_const
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let builders = [Tosa_PadOpQuantInfoBuilder];
let hasFolder = 1;
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: reshape
//===----------------------------------------------------------------------===//
def Tosa_ReshapeOp : Tosa_InferTensorTypeOp<"reshape", [Pure]> {
let summary = "Reshape operator.";
let description = [{
Returns a tensor with the same type/values as the input, with a new shape
specified by the shape argument. Reshape may operate on tensors of any rank.
No data conversion happens during a reshape operation.
}];
let hasFolder = 1;
let hasVerifier = 1;
let arguments = (ins
Tosa_Tensor:$input1,
Tosa_Shape:$shape
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
}];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: reshape_block_scaled
//===----------------------------------------------------------------------===//
def Tosa_ReshapeBlockScaledOp
: Tosa_InferTensorTypeOp<"reshape_block_scaled", [Pure]> {
let summary = "Reshape with support for block scaled tensors.";
let description = [{
Returns a tensor-list with the same type/values as the input, with a new
shape specified by the shape argument. Reshape may operate on block-scaled
tensors (values tensor followed by scale tensor) of rank 1 or higher; or a
single non-block-scaled tensor of any rank. No data conversion happens during
a reshape operation. Reshape must retain the relationship between values
and their scale in a block for block-scaled content.
}];
let hasVerifier = 1;
let arguments = (ins Variadic<Tosa_Tensor>:$input,
Tosa_Shape:$new_value_shape, Tosa_BlockSizeAttr:$block_size);
let results = (outs Variadic<Tosa_Tensor>:$output);
list<Availability> availability = [Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
// NOTE: Validation of extensions is
// disabled for this op
Extension<[]>,
];
let extraClassDeclaration = [{
/// Returns true when two result types are compatible for this op;
/// Method used by InferTypeOpInterface.
static bool isCompatibleReturnTypes(TypeRange l, TypeRange r);
}];
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: reverse
//===----------------------------------------------------------------------===//
def Tosa_ReverseOp: Tosa_Op<"reverse", [
DeclareOpInterfaceMethods<InferShapedTypeOpInterface,
["inferReturnTypeComponents"]>,
SameOperandsAndResultRank,
SameOperandsAndResultShape,
SameOperandsAndResultElementType,
Pure]> {
let summary = "Reverse operator.";
let description = [{
Returns a tensor with the same type/values as the input, with the data
reversed along the given axis. No data conversion happens during a reverse
operation.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input1,
I32Attr:$axis
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: slice
//===----------------------------------------------------------------------===//
def Tosa_SliceOp : Tosa_InferShapedTypeOp<"slice", [Pure]> {
let summary = "Slice operator.";
let description = [{
Extracts a slice of input1, beginning at the start coordinates,
and extending for size elements in each direction.
No data conversion happens during a slice operation.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input1,
Tosa_Shape:$start,
Tosa_Shape:$size
);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasCanonicalizer = 1;
let hasFolder = 1;
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: tile
//===----------------------------------------------------------------------===//
def Tosa_TileOp : Tosa_InferShapedTypeOp<"tile", [Pure]> {
let summary = "Tile operator.";
let description = [{
Replicates input1 multiples times along each dimension.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input1,
Tosa_Shape:$multiples);
let results = (outs
Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let extraClassDeclaration = [{
LogicalResult getConstantMultiples(llvm::SmallVector<int64_t> &multiples);
}];
let hasFolder = 1;
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: transpose
//===----------------------------------------------------------------------===//
def Tosa_TransposeOp : Tosa_InferShapedTypeOp<"transpose",
[DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface ,
["reifyResultShapes"]>,
AllElementTypesMatch<["input1", "output"]>,
Pure]> {
let summary = "Transpose operator.";
let description = [{
Permutes the dimensions of the input tensor input1 based on the perms
argument. Each value in the perms list must be a valid dimension of the
input tensor and may not be repeated.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input1,
DenseI32ArrayAttr:$perms
);
let results = (
outs Tosa_TensorAtLeast1D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasCanonicalizer = 1;
let hasFolder = 1;
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Scatter/Gather Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: gather
//===----------------------------------------------------------------------===//
def Tosa_GatherOp : Tosa_InferShapedTypeOp<"gather", [NoMemoryEffect]> {
let summary = "Gather operation.";
let description = [{
Generate a tensor for which each element in the output is a subtensor of the
values tensor based on the indices. N is the number of batches, W the number
of indices in each batch, K the range of each index and C the number data
channels for each index.
This operation is not pure. Undefined behaviour may occur if the specified
indices are out of range.
}];
let arguments = (ins
Tosa_Tensor3D:$values,
Tosa_IndexTensor2D:$indices
);
let results = (outs
Tosa_Tensor3D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: row_gather
//===----------------------------------------------------------------------===//
def Tosa_RowGatherOp : Tosa_InferShapedTypeOp<"row_gather", [NoMemoryEffect]> {
let summary = "Row gather operation.";
let description = [{
Generate a tensor based on the input indices and row_count. The number of
consecutive rows gathered for each index is specified in row_count. N is
the number of batches, W is the number of indices in each batch, K is
the range of each index, and C is the number of data channels for each
index. The values tensor has shape [N, K, C] and the output tensor has shape
[N, W * row_count, C].
This operation is not pure. Undefined behaviour may occur if the specified
indices are out of range.
}];
let arguments = (ins Tosa_Tensor3D:$values, Tosa_IndexTensor2D:$indices,
Tosa_ScalarInt32Tensor:$row_count);
let results = (outs Tosa_Tensor3D:$output);
list<Availability> availability = [Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3,
Tosa_EXT_FP8E5M2, Tosa_EXT_BF16,
Tosa_EXT_INT64]>,
];
let hasCanonicalizer = 1;
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: row_gather_block_scaled
//===----------------------------------------------------------------------===//
def Tosa_RowGatherBlockScaledOp
: Tosa_InferShapedTypeOp<"row_gather_block_scaled", [NoMemoryEffect]> {
let summary =
"Row gather operation for block-scaled and non-block-scaled data.";
let description = [{
Generate a tensor-list which contains a data tensor and an optional scale
tensor based on the input indices and row_count. The number of consecutive
rows gathered for each index is specified in row_count.
The variadic `values` operands and results model the flattened
`tensor_list_t` form from the TOSA spec:
- non-block-scaled: 1 input value tensor and 1 result tensor
- block-scaled: data + scale input tensors and data + scale result tensors
This operation follows the TOSA 1.1 draft specification and may evolve as
the specification is updated.
This operation is not pure. Undefined behaviour may occur if the specified
indices are out of range.
}];
let arguments = (ins Variadic<Tosa_Tensor3D>:$values,
Tosa_IndexTensor2D:$indices, Tosa_ScalarInt32Tensor:$row_count,
Tosa_BlockSizeAttr:$block_size);
let results = (outs Variadic<Tosa_Tensor3D>:$output);
list<Availability> availability = [Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3,
Tosa_EXT_FP8E5M2, Tosa_EXT_BF16,
Tosa_EXT_MXFP, Tosa_EXT_INT64]>,
];
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator: scatter
//===----------------------------------------------------------------------===//
def Tosa_ScatterOp : Tosa_InferShapedTypeOp<"scatter", [NoMemoryEffect]> {
let summary = "Scatter operation.";
let description = [{
The values_out tensor is set to the values_in tensor with data modified as
follows: data from the input tensor is inserted at the positions specified
by the indices tensor. N is the number of batches, W the number of indices
in each batch, K the range of each index and C the number data channels for
each index. It is not permitted to repeat the same output index within a
single SCATTER operation and so each output index occurs at most once. It
follows that K >= W. In use cases that require multiple updates to the same
output position, these must be decomposed into multiple SCATTER operations.
This operation is not pure. Undefined behaviour may occur if the specified
indices are out of range or duplicate indices are provided.
}];
let arguments = (ins
Tosa_Tensor3D:$values_in,
Tosa_IndexTensor2D:$indices,
Tosa_Tensor3D:$input
);
let results = (outs
Tosa_Tensor3D:$values_out
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let hasVerifier = 1;
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Image Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: resize
//===----------------------------------------------------------------------===//
def Tosa_ResizeOp : Tosa_InferShapedTypeOp<"resize", [Pure]> {
let summary = "Resize operation, supports various resize/upsample modes.";
let description = [{
Resizes a tensor. Resize is only allowed in the H and W dimensions.
The height dimension is scaled by factor (scale_y_n/scale_y_d). The width
dimension is scaled by factor (scale_x_n/scale_x_d).
The NEAREST_NEIGHBOR mode returns the value of the input tensor closest to
the calculated sample position for both floating-point and integer data
formats.
Floating-point BILINEAR mode returns a bilinearly interpolated output value
based on the four closest input sample positions.
For integer BILINEAR interpolation mode, the output value must be scaled by
1/(scale_y_n * scale_x_n) in a following operation to complete the
interpolation (for example with a RESCALE operator).
The output dimensions can be derived from the input dimensions by inverting
the scale as described in the pseudocode. The [border_y, border_x] values
adjust the output size to allow fractional sampling beyond integer input
position (IH - 1,IW - 1).
The limit MAX_SCALE is applied to each scale ratio after reduction of the
ratio. Individual scale numerator and denominator values are allowed to be
larger than MAX_SCALE.
}];
let arguments = (ins
Tosa_Tensor4D:$input,
Rank4TosaShape:$scale,
Rank2TosaShape:$offset,
Rank2TosaShape:$border,
Tosa_ResizeModeAttr:$mode
);
let results = (outs
Tosa_Tensor4D:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT16, Tosa_EXT_BF16]>,
];
let hasFolder = 1;
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator Class: Type Conversion.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: cast
//===----------------------------------------------------------------------===//
def Tosa_CastOp: Tosa_Op<"cast", [Pure, SameOperandsAndResultShape,
DeclareOpInterfaceMethods<InferShapedTypeOpInterface,
["inferReturnTypeComponents"]>]> {
let summary = "Cast operation.";
let description = [{
Casts a tensor from one data type to another.
* This table is showing the supported conversions from the TOSA Specification.
* The MLIR dialect here can be used to represent other conversions.
| Mode | Input | Output |
|--------------------------|---------|---------|
| fp16 to fp32 | float16 | float32 |
| fp16 to int 16 | float16 | int16 |
| fp16 to int 32 | float16 | int32 |
| fp16 to int 8 | float16 | int8 |
| fp32 to fp16 | float32 | float16 |
| fp32 to int 16 | float32 | int16 |
| fp32 to int 32 | float32 | int32 |
| fp32 to int 8 | float32 | int8 |
| int 16 to fp16 | int16 | float16 |
| int 16 to fp32 | int16 | float32 |
| int 32 to fp16 | int32 | float16 |
| int 32 to fp32 | int32 | float32 |
| int 8 to fp16 | int8 | float16 |
| int 8 to fp32 | int8 | float32 |
| bool to int 16 | Boolean | int16 |
| bool to int 32 | Boolean | int32 |
| bool to int 8 | Boolean | int8 |
| int 16 to bool | int16 | Boolean |
| int 16 to int 32 | int16 | int32 |
| int 16 to int 8 | int16 | int8 |
| int 32 to bool | int32 | Boolean |
| int 32 to int 16 | int32 | int16 |
| int 32 to int 8 | int32 | int8 |
| int 8 to bool | int8 | Boolean |
| int 8 to int 16 | int8 | int16 |
| int 8 to int 32 | int8 | int32 |
| bf16 to fp32 | bf16 | float32 |
| bf16 to int 16 | bf16 | int16 |
| bf16 to int 32 | bf16 | int32 |
| bf16 to int 8 | bf16 | int8 |
| fp32 to bf16 | float32 | bf16 |
| int 16 to bf16 | int16 | bf16 |
| int 32 to bf16 | int32 | bf16 |
| int 8 to bf16 | int8 | bf16 |
| bf16 to fp8e4m3 | bf16 | fp8e4m3 |
| fp8e4m3 to bf16 | fp8e4m3 | bf16 |
| bf16 to fp8e5m2 | bf16 | fp8e5m2 |
| fp8e5m2 to bf16 | fp8e5m2 | bf16 |
| fp16 to fp8e4m3 | float16 | fp8e4m3 |
| fp32 to fp8e4m3 | float32 | fp8e4m3 |
| fp8e4m3 to fp16 | fp8e4m3 | float16 |
| fp8e4m3 to fp32 | fp8e4m3 | float32 |
| fp16 to fp8e5m2 | float16 | fp8e5m2 |
| fp32 to fp8e5m2 | float32 | fp8e5m2 |
| fp8e5m2 to fp16 | fp8e5m2 | float16 |
| fp8e5m2 to fp32 | fp8e5m2 | float32 |
}];
let arguments = (ins
Tosa_Tensor:$input
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
let hasFolder = 1;
let hasCanonicalizer = 1;
}
//===----------------------------------------------------------------------===//
// Operator: cast_from_block_scaled
//===----------------------------------------------------------------------===//
def Tosa_CastFromBlockScaledOp: Tosa_InferShapedTypeOp<"cast_from_block_scaled", [Pure]> {
let summary = "Apply scales from a scale tensor to the values in a value tensor";
let description = [{
Apply the scales from a scale tensor to the values in a value tensor, casting
the result to the output type. The block dimension must be the last dimension
of the tensor.
}];
let arguments = (ins
Tosa_MXFPDataTensorAtLeast1D:$input_data,
Tosa_MXFPScaleTensorAtLeast1D:$input_scale,
Tosa_BlockSizeAttr:$block_size
);
let results = (outs
Tosa_TensorAtLeast1D: $output_data
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_MXFP]>,
];
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: cast_to_block_scaled
//===----------------------------------------------------------------------===//
def Tosa_CastToBlockScaledOp : Tosa_InferShapedTypeOp<"cast_to_block_scaled", [Pure]> {
let summary = "Calculate scale tensor values per block, output to separate scale and data tensors.";
let description = [{
Calculate a scale value per block of input values and use that to calculate
scaled data values from an input tensor. The output tensors are cast to the
specified scale and value types. The block dimension will be the last dimension
of the tensor.
}];
let arguments = (ins
Tosa_TensorAtLeast1D:$input_data,
Tosa_BlockSizeAttr:$block_size
);
let results = (outs
Tosa_MXFPDataTensorAtLeast1D:$output_data,
Tosa_MXFPScaleTensorAtLeast1D:$output_scale
);
list<Availability> availability = [
Profile<[Tosa_PRO_FP]>,
Extension<[Tosa_EXT_BF16, Tosa_EXT_MXFP]>
];
let hasCanonicalizer = 1;
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator: rescale
//===----------------------------------------------------------------------===//
def Tosa_RescaleOp : Tosa_InferShapedTypeOp<"rescale", [NoMemoryEffect]> {
let summary = "Tosa rescale operator.";
let description = [{
RESCALE is defined using an integer multiply, add, and shift.
Rescale supports two precisions of multiplier: 16-bit and 32-bit. The 32-bit multiplier
version supports two rounding modes to enable simpler lowering of existing frameworks
that use two stage rounding. All arithmetic is designed so that it does not overflow a
64-bit accumulator and that the result fits in 32 bits. In particular, a 48-bit value
cannot be scaled with the 32-bit multiplier because the accumulator would need to have
80 bits.
The shift and value range are limited to allow a variety of implementations. The limit
of 62 on shift allows the shift to be decomposed as two right shifts of 31.
This operation is not pure. Undefined behaviour may occur if the calculated
result underflows or overflows.
Supported rescalings:
* This table is showing the supported conversions from the TOSA Specification.
* The MLIR dialect here can be used to represent other conversions.
| Mode | Input | Output | Unsigned input | Unsigned output |
|------------------------|-------|--------|----------------|-----------------|
| signed 16 to 16 | int16 | int16 | false | false |
| signed 16 to 32 | int16 | int32 | false | false |
| signed 16 to 8 | int16 | int8 | false | false |
| signed 32 to 16 | int32 | int16 | false | false |
| signed 32 to 32 | int32 | int32 | false | false |
| signed 32 to 8 | int32 | int8 | false | false |
| signed 8 to 16 | int8 | int16 | false | false |
| signed 8 to 32 | int8 | int32 | false | false |
| signed 8 to 8 | int8 | int8 | false | false |
| signed 48 to 16 | int48 | int16 | false | false |
| signed 48 to 32 | int48 | int32 | false | false |
| signed 48 to 8 | int48 | int8 | false | false |
| unsigned 8 to signed 8 | uint8 | int8 | true | false |
| signed 8 to unsigned 8 | int8 | uint8 | false | true |
}];
let arguments = (ins
Tosa_Tensor:$input,
Tosa_1DInt16Or32Tensor:$multiplier,
Tosa_1DInt8Tensor:$shift,
Tosa_ScalarIntOrFloatTensor:$input_zp,
Tosa_ScalarIntOrFloatTensor:$output_zp,
BoolAttr:$scale32,
Tosa_RoundingModeAttr:$rounding_mode,
BoolAttr:$per_channel,
BoolAttr: $input_unsigned,
BoolAttr: $output_unsigned
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT]>,
Extension<[Tosa_EXT_INT16]>,
];
let extraClassDeclaration = [{
FailureOr<int64_t> getInputZeroPoint();
FailureOr<int64_t> getOutputZeroPoint();
LogicalResult verifyInputZeroPoint(int64_t zp);
LogicalResult verifyOutputZeroPoint(int64_t zp);
}];
let hasVerifier = 1;
let hasCustomAssemblyFormat = 1;
}
//===----------------------------------------------------------------------===//
// Operator Class: Data Nodes.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: const
//===----------------------------------------------------------------------===//
def Tosa_ConstOp : Tosa_Op<"const", [ConstantLike, Pure,
AllShapesMatch<["values", "output"]>,
FirstAttrDerivedResultType]> {
let summary = "Constant operator.";
let description = [{
A node containing constant data for use as the input to an operation. May
hold data in any of the supported data formats.
Example:
```mlir
// Generic form
%out = "tosa.const"() {values = dense<0> : tensor<2x3xi32>} : () -> tensor<2x3xi32>
```
}];
let arguments = (ins
ElementsAttr:$values
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT4, Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_MXFP, Tosa_EXT_INT64]>,
];
let hasFolder = 1;
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// Operator: identity
//===----------------------------------------------------------------------===//
def Tosa_IdentityOp: Tosa_Op<"identity", [Pure,
DeclareOpInterfaceMethods<InferShapedTypeOpInterface,
["inferReturnTypeComponents"]>]> {
let summary = "Identity operator.";
let description = [{
Returns a tensor with the same shape, type, and contents as the input.
}];
let arguments = (ins
Tosa_Tensor:$input1
);
let results = (outs
Tosa_Tensor:$output
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_INT4, Tosa_EXT_INT16, Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Custom Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: custom
//===----------------------------------------------------------------------===//
def Tosa_CustomOp : Tosa_Op<"custom"> {
let summary = "Custom operator wrapper for Tosa";
let description = [{
Hardware implementing TOSA may choose to add additional custom operators
that are not expressed in the existing TOSA operations. These operators are
not expected to be portable across TOSA implementations. The input and
output signatures must be expressed in the corresponding TOSA node.
`operator_name` is a string that tells the backend which custom operator is
being called.
`domain_name` is a string identifier which can help avoid name collisions on
the identifier field.
`implementation_attrs` is a string which is a backend and identifier specific
set of attributes to the custom operator.
`input_list` is the set of tensor inputs to the custom operator.
`output_list` is the list of tensors returned by the operator. The number of operators
is backend specific.
Example:
```mlir
%out = tosa.custom %in {domain_name = "tosa_mlir_test", operator_name =
"custom_test", implementation_attrs = ""}: (tensor<10xi32>) ->
(tensor<10xi32>)
```
}];
let arguments = (ins
StrAttr:$operator_name,
StrAttr:$domain_name,
StrAttr:$implementation_attrs,
Variadic<Tosa_Tensor>:$input_list
);
let results = (outs
Variadic<Tosa_Tensor>:$output_list
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[]>,
];
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
}
//===----------------------------------------------------------------------===//
// Operator Class: Control Flow Operators.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operator: cond_if
//===----------------------------------------------------------------------===//
def Tosa_IfOp : Tosa_Op<"cond_if",
[InferShapedTypeOpAdaptor,
SingleBlockImplicitTerminator<"YieldOp">,
RecursiveMemoryEffects]> {
let summary = "Conditional if operator.";
let description = [{
Evaluates a Boolean condition and then takes one of two distinct execution
paths. This implements the semantic If-then-else structure.
}];
let arguments = (ins
Tosa_I1Tensor:$condition,
Variadic<Tosa_Tensor>:$input_list
);
let results = (outs
Variadic<Tosa_Tensor>:$output_list
);
list<Availability> availability = [
Profile<[]>,
Extension<[Tosa_EXT_CONTROLFLOW]>,
];
let regions = (region
SizedRegion<1>:$then_graph,
SizedRegion<1>:$else_graph
);
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// Operator: while_loop
//===----------------------------------------------------------------------===//
def Tosa_WhileOp : Tosa_Op<"while_loop", [
DeclareOpInterfaceMethods<LoopLikeOpInterface>,
InferShapedTypeOpAdaptor,
SingleBlockImplicitTerminator<"YieldOp">,
RecursiveMemoryEffects]> {
let summary = "output = input; While (Cond(output)) {output = Body(output)}";
let description = [{
Generates and evaluates a Boolean condition and either executes a loop body
or exits the loop. This action is performed repeatedly after
updating and re-evaluating the Boolean condition every iteration. This
implements the semantic foreach or while iterative loop structure.
}];
let arguments = (ins
Variadic<Tosa_Tensor>:$input_list
);
let results = (outs
Variadic<Tosa_Tensor>:$output_list
);
list<Availability> availability = [
Profile<[]>,
Extension<[Tosa_EXT_CONTROLFLOW]>,
];
let regions = (region
SizedRegion<1>:$cond_graph,
SizedRegion<1>:$body_graph
);
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// Operator: variable
//===----------------------------------------------------------------------===//
def Tosa_VariableOp : Tosa_Op<"variable", [Symbol]> {
let summary = "Defines a variable";
let description = [{
Defines a new TOSA variable. This is a persistent mutable value across multiple
TOSA graph invocations. Modifications are expressed using read/write semantics.
}];
let arguments = (ins
// Note: "sym_name" is used as opposed to "name" in the specification,
// since a Symbol must be named "sym_name" for it to be recognised by
// the containing SymbolTable.
SymbolNameAttr:$sym_name,
IndexElementsAttr:$var_shape,
TypeAttr:$type,
OptionalAttr<AnyAttr>:$initial_value
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_VARIABLE]>,
];
let hasCustomAssemblyFormat = 1;
let assemblyFormat = [{
$sym_name
attr-dict
custom<VariableOpTypeOrInitialValue>($var_shape, $type, $initial_value)
}];
let builders = [Tosa_VariableOpBuilder];
let extraClassDeclaration = [{
::llvm::StringRef getName() {
return getSymName();
}
}];
}
//===----------------------------------------------------------------------===//
// Operator: variable_write
//===----------------------------------------------------------------------===//
def Tosa_VariableWriteOp : Tosa_Op<"variable_write", []> {
let summary = "write_buffer operator";
let description = [{
Assigns a value to the pseudo-buffer resource holding a persistent mutable tensor.
}];
let arguments = (ins
SymbolNameAttr:$name,
Tosa_Tensor:$input1
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_VARIABLE]>,
];
let assemblyFormat = [{
$name attr-dict `,` $input1 `:` type($input1)
}];
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// Operator: variable_read
//===----------------------------------------------------------------------===//
def Tosa_VariableReadOp : Tosa_Op<"variable_read", []> {
let summary = "read_buffer operator";
let description = [{
Reads the value from a pseudo-buffer resource holding a persistent mutable tensor.
}];
let arguments = (ins
SymbolNameAttr:$name
);
let results = (outs
Tosa_Tensor:$output1
);
list<Availability> availability = [
Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
Extension<[Tosa_EXT_VARIABLE]>,
];
let assemblyFormat = [{
$name attr-dict `:` type($output1)
}];
let hasVerifier = 1;
}
include "mlir/Dialect/Tosa/IR/TosaUtilOps.td"
include "mlir/Dialect/Tosa/IR/TosaShapeOps.td"
#endif // TOSA_OPS