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

586 lines
24 KiB
TableGen

//===-- TosaOpBase.td - TOSA dialect op builders -----------*- 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 common definitions for the TOSA dialect.
//
//===----------------------------------------------------------------------===//
#ifndef TOSA_OP_BASE
#define TOSA_OP_BASE
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/EnumAttr.td"
include "mlir/IR/OpBase.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/LoopLikeInterface.td"
include "mlir/Dialect/Tosa/IR/TosaInterfaces.td"
//===----------------------------------------------------------------------===//
// The TOSA Dialect.
//===----------------------------------------------------------------------===//
def Tosa_Dialect : Dialect {
let name = "tosa";
let description = [{
The Tensor Operator Set Architecture (TOSA) dialect.
This dialect implements the TOSA standard described at
https://www.mlplatform.org/tosa/tosa_spec.html .
Tensor Operator Set Architecture (TOSA) provides a set of whole-tensor
operations commonly employed by Deep Neural Networks. The intent is to
enable a variety of implementations running on a diverse range of
processors, with the results at the TOSA level consistent across those
implementations. Applications or frameworks which target TOSA can therefore
be deployed on a wide range of different processors, such as CPUs or GPUs,
with defined accuracy and compatibility constraints. Most operators from the
common ML frameworks should be expressible in TOSA. It is expected that
there will be tools to lower from the ML frameworks into TOSA.
}];
let dependentDialects = ["tensor::TensorDialect", "quant::QuantDialect"];
let cppNamespace = "mlir::tosa";
let hasConstantMaterializer = 1;
let useDefaultAttributePrinterParser = 1;
let useDefaultTypePrinterParser = 1;
}
//===----------------------------------------------------------------------===//
// TOSA Attributes.
//===----------------------------------------------------------------------===//
class Tosa_Attr<string attrName, string attrMnemonic, list<Trait> traits = []>
: AttrDef<Tosa_Dialect, attrName, traits> {
let mnemonic = attrMnemonic;
}
//===----------------------------------------------------------------------===//
// TOSA Operator Quantization Attributes.
//===----------------------------------------------------------------------===//
// Quantization attributes used across TOSA operators. Quantization attributes
// feed numerical precision parameters to the functional implementation of TOSA
// operators.
// The functional behavior is defined in the TOSA specification maintained at
// https://www.mlplatform.org/tosa/tosa_spec.html. TOSA leverages MLIR's built in
// quantization support: https://mlir.llvm.org/docs/Quantization/, and supports
// uniform quantization. Depending on datatype, asymmetric and symmetric
// quantization are supported. The types themselves are described in
// TosaTypesBase.td .
// This quantization attribute expresses numerical behavior of operators where
// the operator has a numerical relationship between a single input and output.
// For example: tosa.negate.
def Tosa_UnaryOpQuantizationAttr
: Tosa_Attr<"UnaryOpQuantization", "unary_quant"> {
let summary = "Attribute for UnaryOp quantization information.";
let parameters = (ins "int64_t":$input_zp, "int64_t":$output_zp);
let assemblyFormat = "`<` struct(params) `>`";
}
// There is no explicit BinaryOpQuantizationAttr for 2-input/1-output ops. In
// this case, a tosa.rescale is used to express the inputs to the same scale.
// TODO: Upload WIP legalization document describing this construction by
// example.
// This quantization attribute holds input and weight zero point. Both the
// ConvOp and MatMulOp QuantizationAttrs follow a common design semantic where
// their ownquantization attribute only expresses the numerical behavior at
// the inputs.
// The scaling of their accumulator output is done using an explicit
// tosa.rescale operator that scales the accumulator result to output scale.
def Tosa_ConvOpQuantizationAttr
: Tosa_Attr<"ConvOpQuantization", "conv_quant"> {
let summary = "Attribute for Conv type op quantization information.";
let parameters = (ins "int64_t":$input_zp, "int64_t":$weight_zp);
let assemblyFormat = "`<` struct(params) `>`";
}
def Tosa_MatMulOpQuantizationAttr
: Tosa_Attr< "MatMulOpQuantization", "matmul_quant"> {
let summary = "Attribute for MatMulOp quantization information.";
let parameters = (ins "int64_t":$a_zp, "int64_t":$b_zp);
let assemblyFormat = "`<` struct(params) `>`";
}
// This attribute holds input zero point correction applied to the padding
// zeros to ensure numerical accuracy in the subsequent TOSA operations.
// Its functional application is described in the tosa.pad() operator
// description in the specification.
def Tosa_PadOpQuantizationAttr : Tosa_Attr<"PadOpQuantization", "pad_quant"> {
let summary = "Attribute for PadOp quantization information.";
let parameters = (ins "int64_t":$input_zp);
let assemblyFormat = "`<` struct(params) `>`";
}
//===----------------------------------------------------------------------===//
// TOSA Operator Quantization Builders.
//===----------------------------------------------------------------------===//
// This builder is called on all convolution operators except for TransposeConv,
// which has specialized output shape semantics. The builder also defines the
// bitwidth of the output given the bit width of the input & weight content.
def Tosa_ConvOpQuantInfoBuilder : OpBuilder<
(ins "::mlir::Type":$outputType, "::mlir::Value":$input,
"::mlir::Value":$weight, "::mlir::Value":$bias,
"::mlir::DenseI64ArrayAttr":$pad, "::mlir::DenseI64ArrayAttr":$stride,
"::mlir::DenseI64ArrayAttr":$dilation,
"::mlir::TypeAttr":$acc_type),
[{
buildConvOpWithQuantInfo($_builder, $_state, outputType,
input, weight, bias,
pad, stride, dilation, acc_type);
}]>;
// Handles tosa.transpose_conv2d which has an outpad and output shape attribute.
def Tosa_TransConvOpQuantInfoBuilder : OpBuilder<
(ins "::mlir::Type":$outputType, "::mlir::Value":$input,
"::mlir::Value":$weight, "mlir::Value":$bias,
"::mlir::DenseI64ArrayAttr":$outpad,
"::mlir::DenseI64ArrayAttr":$stride,
"::mlir::TypeAttr":$acc_type),
[{
buildTransConvOpWithQuantInfo($_builder, $_state, outputType,
input, weight, bias,
outpad, stride, acc_type);
}]>;
// The tosa.matmul op is also intended to be generated where a fully_connected
// op must be constructed where the weight is not a constant. In this case,
// the fully_connected op must be expressed using matmul.
// TODO: Add link to the leglization document explaining this.
def Tosa_MatMulOpQuantInfoBuilder : OpBuilder<
(ins "Type":$outputType, "Value":$a, "Value":$b),
[{
buildMatMulOpWithQuantInfo($_builder, $_state, outputType,
a, b);
}]>;
// Both the tosa.avg_pool2d and unary ops use the same
// UnaryOpQuantizationAttr but the avg_pool operator has its own builder as it
// has additional parameters not part of the unary ops.
def Tosa_AvgPool2dOpQuantInfoBuilder : OpBuilder<
(ins "::mlir::Type":$outputType, "::mlir::Value":$input,
"::mlir::DenseI64ArrayAttr":$kernel, "::mlir::DenseI64ArrayAttr":$stride,
"::mlir::DenseI64ArrayAttr":$pad, "::mlir::TypeAttr":$acc_type),
[{
buildAvgPool2dOpWithQuantInfo($_builder, $_state, outputType,
input, kernel, stride, pad, acc_type);
}]>;
def Tosa_AvgPool2dAdaptiveOpQuantInfoBuilder
: OpBuilder<(ins "::mlir::Type":$outputType, "::mlir::Value":$input,
"::mlir::DenseI64ArrayAttr":$kernel,
"::mlir::DenseI64ArrayAttr":$stride,
"::mlir::DenseI64ArrayAttr":$pad,
"::mlir::TypeAttr":$acc_type),
[{
buildAvgPool2dAdaptiveOpWithQuantInfo($_builder, $_state, outputType,
input, kernel, stride, pad, acc_type);
}]>;
// This builder is called on single-parameter negate operators that have a scale
// relationship between their input and output, expressed by the
// UnaryOpQuantizationAttr.
def Tosa_NegateOpQuantInfoBuilder : OpBuilder<
(ins "Type":$outputType, "Value":$input),
[{
buildNegateOpWithQuantInfo($_builder, $_state, outputType, input);
}]>;
// These builders are called on the TOSA pad operator that needs to create its
// own OptionalAttr quantization_attr parameter to scale the padding values
// correctly.
def Tosa_PadOpQuantInfoBuilder : OpBuilder<
(ins "Type":$outputType, "Value":$input, "Value":$paddings),
[{
buildPadOpWithQuantInfo($_builder, $_state, outputType,
input, paddings);
}]>;
// This builder is called on the TOSA variable operator with a variable type
// and optional initial value. The builder will extract var_shape and element type
// attributes from variable type.
def Tosa_VariableOpBuilder : OpBuilder<
(ins "StringRef":$sym_name, "Type":$variable_type, "Attribute":$initial_value),
[{
buildVariableOp($_builder, $_state, sym_name, variable_type, initial_value);
}]>;
// Wrapper over base I32EnumAttr to set common fields.
class Tosa_I32Enum<string name, string description, list<I32EnumAttrCase> cases>
: I32EnumAttr<name, description, cases> {
let genSpecializedAttr = 0;
let cppNamespace = "::mlir::tosa";
}
class Tosa_I32EnumAttr<string name, string description, string mnemonic,
list<I32EnumAttrCase> cases>
: EnumAttr<Tosa_Dialect, Tosa_I32Enum<name, description, cases>, mnemonic> {
let assemblyFormat = "`<` $value `>`";
}
//===----------------------------------------------------------------------===//
// TOSA Profiles and extensions
//
// Profile:
// INT : Integer Inference. Integer operations, primarily 8 and 32-bit values.
// FP : Floating-Point Inference. Primarily FP16 and FP32 operations.
//
// Extension:
// INT64 : 64-bit integer operations.
// INT16 : 16-bit integer operations.
// INT4 : 4-bit integer weights.
// BF16 : BFloat16 operations.
// FP8E4M3 : 8-bit floating-point operations E4M3.
// FP8E5M2 : 8-bit floating-point operations E5M2.
// FFT : Fast Fourier Transform operations.
// VARIABLE : Stateful variable operations.
// CONTROLFLOW : Control Flow operations.
// DOUBLEROUND : Adds double rounding support to the RESCALE operator.
// INEXACTROUND : Adds inexact rounding support to the RESCALE operator.
// DYNAMIC : Removes all Compile Time Constant state for CTC inputs.
// MXFP : Microscaling formats.
// MXFP_CONV : Microscaling format convolution.
// SHAPE : Shape calcuation operators.
//===----------------------------------------------------------------------===//
def Tosa_NONE : I32EnumAttrCase<"none", 0>;
def Tosa_PRO_INT : I32EnumAttrCase<"pro_int", 1>;
def Tosa_PRO_FP : I32EnumAttrCase<"pro_fp", 2>;
def Tosa_ProfileAttr
: Tosa_I32EnumAttr<"Profile", "supported TOSA profiles", "prof",
[Tosa_PRO_INT, Tosa_PRO_FP, Tosa_NONE]> {
let extraClassDeclaration = [{
static llvm::SmallVector<Profile, 2> getAllValues() {
return {Profile::pro_int, Profile::pro_fp};
}
}];
}
def Tosa_ProfileArrayAttr
: TypedArrayAttrBase<Tosa_ProfileAttr, "TOSA profile array attribute">;
def Tosa_EXT_NONE : I32EnumAttrCase<"none", 0>;
def Tosa_EXT_INT16 : I32EnumAttrCase<"int16", 1>;
def Tosa_EXT_INT4 : I32EnumAttrCase<"int4", 2>;
def Tosa_EXT_BF16 : I32EnumAttrCase<"bf16", 3>;
def Tosa_EXT_FP8E4M3 : I32EnumAttrCase<"fp8e4m3", 4>;
def Tosa_EXT_FP8E5M2 : I32EnumAttrCase<"fp8e5m2", 5>;
def Tosa_EXT_FFT : I32EnumAttrCase<"fft", 6>;
def Tosa_EXT_VARIABLE : I32EnumAttrCase<"variable", 7>;
def Tosa_EXT_CONTROLFLOW : I32EnumAttrCase<"controlflow", 8>;
def Tosa_EXT_DOUBLEROUND : I32EnumAttrCase<"doubleround", 9>;
def Tosa_EXT_INEXACTROUND : I32EnumAttrCase<"inexactround", 10>;
def Tosa_EXT_DYNAMIC : I32EnumAttrCase<"dynamic", 11>;
def Tosa_EXT_MXFP : I32EnumAttrCase<"mxfp", 12>;
def Tosa_EXT_INT64 : I32EnumAttrCase<"int64", 13>;
def Tosa_EXT_MXFP_CONV : I32EnumAttrCase<"mxfp_conv", 14>;
def Tosa_EXT_SHAPE : I32EnumAttrCase<"shape", 15>;
def Tosa_ExtensionAttr
: Tosa_I32EnumAttr<"Extension", "supported TOSA extensions", "ext", [
Tosa_EXT_NONE, Tosa_EXT_INT16, Tosa_EXT_INT4, Tosa_EXT_BF16,
Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_FFT, Tosa_EXT_VARIABLE,
Tosa_EXT_CONTROLFLOW, Tosa_EXT_DOUBLEROUND, Tosa_EXT_INEXACTROUND,
Tosa_EXT_DYNAMIC, Tosa_EXT_MXFP, Tosa_EXT_INT64, Tosa_EXT_MXFP_CONV,
Tosa_EXT_SHAPE,
]> {
let extraClassDeclaration = [{
static llvm::SmallVector<Extension, 14> getAllValues() {
return {
Extension::int16, Extension::int4, Extension::bf16,
Extension::fp8e4m3, Extension::fp8e5m2, Extension::fft,
Extension::variable, Extension::controlflow, Extension::doubleround,
Extension::inexactround, Extension::dynamic, Extension::mxfp,
Extension::int64, Extension::mxfp_conv, Extension::shape
};
}
}];
}
def Tosa_ExtensionArrayAttr
: TypedArrayAttrBase<Tosa_ExtensionAttr, "TOSA extension array attribute">;
// The base class for defining op availability dimensions.
class Availability {
// The following are fields for controlling the generated C++ OpInterface.
// The namespace for the generated C++ OpInterface subclass.
string cppNamespace = "::mlir::tosa";
// The name for the generated C++ OpInterface subclass.
string interfaceName = ?;
// The description for the generated C++ OpInterface subclass.
string interfaceDescription = "";
// The query function's return type in the generated C++ OpInterface subclass.
string queryFnRetType = ?;
// The query function's name in the generated C++ OpInterface subclass.
string queryFnName = ?;
// The logic for merging two availability requirements.
code mergeAction = ?;
// The initializer for the final availability requirement.
string initializer = ?;
// An availability instance's type.
string instanceType = ?;
// The following are fields for a concrete availability instance.
// The code for preparing a concrete instance. This should be C++ statements
// and will be generated before the `mergeAction` logic.
code instancePreparation = "";
// The availability requirement carried by a concrete instance.
string instance = ?;
}
class Profile<list<I32EnumAttrCase> profiles> : Availability {
let interfaceName = "QueryProfileInterface";
let interfaceDescription = [{
Querying interface for the supported set of Tosa profile.
This interface provides a `getProfiles()` method to query
the supported set of Tosa profile. The returned value is a
list of `mlir::Tosa::Profile` enum number.
}];
let queryFnRetType = "::llvm::SmallVector<::llvm::ArrayRef<"
"::mlir::tosa::Profile>, 1>";
let queryFnName = "getProfiles";
let mergeAction = !if(
!empty(profiles), "", "$overall.emplace_back($instance)");
let initializer = "{}";
let instanceType = "::llvm::ArrayRef<::mlir::tosa::Profile>";
// Pack all profiles as a static array and get its reference.
let instancePreparation = !if(!empty(profiles), "",
"static const ::mlir::tosa::Profile profs[] = {" #
!interleave(!foreach(prof, profiles,
"::mlir::tosa::Profile::" # prof.symbol), ", ") #
"}; " #
"ArrayRef<::mlir::tosa::Profile> " #
"ref(profs, std::size(profs));");
let instance = "ref";
}
class Extension<list<I32EnumAttrCase> extensions> : Availability {
let interfaceName = "QueryExtensionInterface";
let interfaceDescription = [{
Querying interface for the supported set of TOSA extension.
This interface provides a `getExtensions()` method to query
the supported set of Tosa extension. The returned value is a
list of `mlir::Tosa::Extension` enum number.
}];
let queryFnRetType = "::llvm::SmallVector<::llvm::ArrayRef<"
"::mlir::tosa::Extension>, 1>";
let queryFnName = "getExtensions";
let mergeAction = !if(
!empty(extensions), "", "$overall.emplace_back($instance)");
let initializer = "{}";
let instanceType = "::llvm::ArrayRef<::mlir::tosa::Extension>";
// Pack all extensions as a static array and get its reference.
let instancePreparation = !if(!empty(extensions), "",
"static const ::mlir::tosa::Extension exts[] = {" #
!interleave(!foreach(ext, extensions,
"::mlir::tosa::Extension::" # ext.symbol), ", ") #
"}; " #
"ArrayRef<::mlir::tosa::Extension> " #
"ref(exts, std::size(exts));");
let instance = "ref";
}
//===----------------------------------------------------------------------===//
// TOSA Levels
//===----------------------------------------------------------------------===//
def Tosa_LVL_NONE : I32EnumAttrCase<"none", 0>;
def Tosa_LVL_8K : I32EnumAttrCase<"eightK", 1, "8k">;
def Tosa_LevelAttr
: Tosa_I32EnumAttr<"Level", "supported TOSA levels", "level", [Tosa_LVL_NONE, Tosa_LVL_8K]>;
//===----------------------------------------------------------------------===//
// TOSA Specification versions
//===----------------------------------------------------------------------===//
def Tosa_V_1_0 : I32EnumAttrCase<"V_1_0", 0, "1.0">;
def Tosa_V_1_1_DRAFT : I32EnumAttrCase<"V_1_1_DRAFT", 1, "1.1.draft">;
def Tosa_SpecificationVersion : Tosa_I32EnumAttr<
"SpecificationVersion", "TOSA specification version", "specification_version",
[Tosa_V_1_0, Tosa_V_1_1_DRAFT]>;
//===----------------------------------------------------------------------===//
// TOSA target environment.
//===----------------------------------------------------------------------===//
def Tosa_TargetEnv : Tosa_Attr<"TargetEnv", "target_env"> {
let summary = "Target environment information.";
let parameters = ( ins
"SpecificationVersion": $specification_version,
"Level": $level,
ArrayRefParameter<"Profile">: $profiles,
ArrayRefParameter<"Extension">: $extensions
);
let assemblyFormat = "`<` `specification_version` `=` $specification_version `,` "
"`level` `=` $level `,` `profiles` `=` `[` $profiles `]` `,` "
"`extensions` `=` `[` $extensions `]` `>`";
}
//===----------------------------------------------------------------------===//
// Enum attributes.
//===----------------------------------------------------------------------===//
// Defined in `section 3. Enumerations` of the TOSA specification.
def Tosa_RESIZE_NEAREST_NEIGHBOR : I32EnumAttrCase<"NEAREST_NEIGHBOR", 1>;
def Tosa_RESIZE_BILINEAR : I32EnumAttrCase<"BILINEAR", 2>;
def Tosa_ResizeModeAttr
: Tosa_I32EnumAttr<"ResizeMode", "Supported resize/upsampling strategies", "resize_mode",
[Tosa_RESIZE_NEAREST_NEIGHBOR, Tosa_RESIZE_BILINEAR]>;
def Tosa_NANPROPAGATION_PROPAGATE : I32EnumAttrCase<"PROPAGATE", 1>;
def Tosa_NANPROPAGATION_IGNORE : I32EnumAttrCase<"IGNORE", 2>;
def Tosa_NanPropagationModeAttr
: Tosa_I32EnumAttr<"NanPropagationMode", "Supported NaN propagation strategies", "nan_mode",
[Tosa_NANPROPAGATION_PROPAGATE, Tosa_NANPROPAGATION_IGNORE]>;
def Tosa_ROUNDING_SINGLE_ROUND : I32EnumAttrCase<"SINGLE_ROUND", 1>;
def Tosa_ROUNDING_INEXACT_ROUND : I32EnumAttrCase<"INEXACT_ROUND", 2>;
def Tosa_ROUNDING_DOUBLE_ROUND : I32EnumAttrCase<"DOUBLE_ROUND", 3>;
def Tosa_RoundingModeAttr
: Tosa_I32EnumAttr<"RoundingMode", "Supported rounding modes", "rounding_mode",
[Tosa_ROUNDING_SINGLE_ROUND, Tosa_ROUNDING_INEXACT_ROUND, Tosa_ROUNDING_DOUBLE_ROUND]>;
def Tosa_BLOCK_SIZE_1 : I32EnumAttrCase<"BLOCK_SIZE_1", 1>;
def Tosa_BLOCK_SIZE_32 : I32EnumAttrCase<"BLOCK_SIZE_32", 32>;
def Tosa_BlockSizeAttr
: Tosa_I32EnumAttr<"BlockSize", "Block size for the block_scaled formats",
"block_size", [Tosa_BLOCK_SIZE_1, Tosa_BLOCK_SIZE_32]> {
let extraClassDeclaration = [{
static uint32_t getBlockSizeValue(BlockSize blockSize) {
return static_cast<uint32_t>(blockSize);
}
}];
}
//===----------------------------------------------------------------------===//
// TOSA Interfaces.
//===----------------------------------------------------------------------===//
def QueryProfileInterface : OpInterface<"QueryProfileInterface"> {
let cppNamespace = "::mlir::tosa";
let methods = [InterfaceMethod<
"get supported profiles",
"::llvm::SmallVector<::llvm::ArrayRef<::mlir::tosa::Profile>, 1>",
"getProfiles">];
}
def QueryExtensionInterface : OpInterface<"QueryExtensionInterface"> {
let cppNamespace = "::mlir::tosa";
let methods = [InterfaceMethod<
"get supported extensions",
"::llvm::SmallVector<::llvm::ArrayRef<::mlir::tosa::Extension>, 1>",
"getExtensions">];
}
//===----------------------------------------------------------------------===//
// TOSA Operator Trait.
//===----------------------------------------------------------------------===//
// Permits broadcasting. Elementwise trait is too strict.
def TosaElementwiseOperator : NativeOpTrait<"TosaElementwiseOperator"> {
let cppNamespace = "mlir::OpTrait::tosa";
}
//===----------------------------------------------------------------------===//
// TOSA Operator Trait.
//===----------------------------------------------------------------------===//
// Op operands with TOSA shape types must be compile time resolvable
def TosaResolvableShapeOperands : NativeOpTrait<"TosaResolvableShapeOperands"> {
let cppNamespace = "mlir::OpTrait::tosa";
}
//===----------------------------------------------------------------------===//
// TOSA Operator Class.
//===----------------------------------------------------------------------===//
class Tosa_Op<string mnemonic, list<Trait> traits = []> :
Op<Tosa_Dialect, mnemonic, !listconcat(traits, [TosaOpInterface,
DeclareOpInterfaceMethods<QueryProfileInterface>,
DeclareOpInterfaceMethods<QueryExtensionInterface>,
TosaResolvableShapeOperands])> {
// Default availability specification.
list<Availability> availability = [
Profile<[]>,
Extension<[]>];
// When not set, manual implementation of these methods is required.
bit autogenAvailability = 1;
}
class Tosa_ElementwiseOp<string mnemonic, list<Trait> traits = []> :
Tosa_Op<mnemonic, !listconcat(traits, [
DeclareOpInterfaceMethods<InferShapedTypeOpInterface,
["inferReturnTypeComponents"]>,
ResultsBroadcastableShape,
TosaElementwiseOperator,
SameOperandsAndResultRank,
NoMemoryEffect])> {}
class Tosa_ElementwiseUnaryOp<string mnemonic, list<Trait> traits = []> :
Tosa_ElementwiseOp<mnemonic, !listconcat(traits, [
SameOperandsAndResultShape,
SameOperandsAndResultElementType])> {}
class Tosa_InferTensorTypeOp<string mnemonic, list<Trait> traits = []>
: Tosa_Op<mnemonic, !listconcat(traits, [InferTensorTypeAdaptor])> {}
class Tosa_InferShapedTypeOp<string mnemonic, list<Trait> traits = []>
: Tosa_Op<mnemonic, !listconcat(traits, [InferShapedTypeOpAdaptor])> {}
// The "SameVariadicOperandSize" trait allows us to pass optional arguments
// for multiple zero points in convolution ops.
class Tosa_ConvOp<string mnemonic, list<Trait> traits = []>
: Tosa_InferShapedTypeOp<mnemonic, !listconcat(traits,
[SameVariadicOperandSize, NoMemoryEffect])> {
let assemblyFormat =
"operands attr-dict `:` functional-type(operands, results)";
}
#endif // TOSA_OP_BASE